|  | /* | 
|  | * Copyright 2010 The Android Open Source Project | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  |  | 
|  | #include "SkJpegUtility.h" | 
|  |  | 
|  | ///////////////////////////////////////////////////////////////////// | 
|  | static void sk_init_source(j_decompress_ptr cinfo) { | 
|  | skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src; | 
|  | src->next_input_byte = (const JOCTET*)src->fBuffer; | 
|  | src->bytes_in_buffer = 0; | 
|  | #ifdef SK_BUILD_FOR_ANDROID | 
|  | src->current_offset = 0; | 
|  | #endif | 
|  | if (!src->fStream->rewind()) { | 
|  | SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); | 
|  | cinfo->err->error_exit((j_common_ptr)cinfo); | 
|  | } | 
|  | } | 
|  |  | 
|  | #ifdef SK_BUILD_FOR_ANDROID | 
|  | static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) { | 
|  | skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; | 
|  | size_t bo = (size_t) byte_offset; | 
|  |  | 
|  | if (bo > src->current_offset) { | 
|  | (void)src->fStream->skip(bo - src->current_offset); | 
|  | } else { | 
|  | if (!src->fStream->rewind()) { | 
|  | SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); | 
|  | cinfo->err->error_exit((j_common_ptr)cinfo); | 
|  | return false; | 
|  | } | 
|  | (void)src->fStream->skip(bo); | 
|  | } | 
|  |  | 
|  | src->current_offset = bo; | 
|  | src->next_input_byte = (const JOCTET*)src->fBuffer; | 
|  | src->bytes_in_buffer = 0; | 
|  | return true; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) { | 
|  | skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; | 
|  | if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) { | 
|  | return FALSE; | 
|  | } | 
|  | size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); | 
|  | // note that JPEG is happy with less than the full read, | 
|  | // as long as the result is non-zero | 
|  | if (bytes == 0) { | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | #ifdef SK_BUILD_FOR_ANDROID | 
|  | src->current_offset += bytes; | 
|  | #endif | 
|  | src->next_input_byte = (const JOCTET*)src->fBuffer; | 
|  | src->bytes_in_buffer = bytes; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { | 
|  | skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src; | 
|  |  | 
|  | if (num_bytes > (long)src->bytes_in_buffer) { | 
|  | size_t bytesToSkip = num_bytes - src->bytes_in_buffer; | 
|  | while (bytesToSkip > 0) { | 
|  | size_t bytes = src->fStream->skip(bytesToSkip); | 
|  | if (bytes <= 0 || bytes > bytesToSkip) { | 
|  | //              SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes); | 
|  | cinfo->err->error_exit((j_common_ptr)cinfo); | 
|  | return; | 
|  | } | 
|  | #ifdef SK_BUILD_FOR_ANDROID | 
|  | src->current_offset += bytes; | 
|  | #endif | 
|  | bytesToSkip -= bytes; | 
|  | } | 
|  | src->next_input_byte = (const JOCTET*)src->fBuffer; | 
|  | src->bytes_in_buffer = 0; | 
|  | } else { | 
|  | src->next_input_byte += num_bytes; | 
|  | src->bytes_in_buffer -= num_bytes; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void sk_term_source(j_decompress_ptr /*cinfo*/) {} | 
|  |  | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) | 
|  | : fStream(SkRef(stream)) | 
|  | , fDecoder(decoder) { | 
|  |  | 
|  | init_source = sk_init_source; | 
|  | fill_input_buffer = sk_fill_input_buffer; | 
|  | skip_input_data = sk_skip_input_data; | 
|  | resync_to_restart = jpeg_resync_to_restart; | 
|  | term_source = sk_term_source; | 
|  | #ifdef SK_BUILD_FOR_ANDROID | 
|  | seek_input_data = sk_seek_input_data; | 
|  | #endif | 
|  | //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize); | 
|  | } | 
|  |  | 
|  | skjpeg_source_mgr::~skjpeg_source_mgr() { | 
|  | SkSafeUnref(fStream); | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | static void sk_init_destination(j_compress_ptr cinfo) { | 
|  | skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; | 
|  |  | 
|  | dest->next_output_byte = dest->fBuffer; | 
|  | dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; | 
|  | } | 
|  |  | 
|  | static boolean sk_empty_output_buffer(j_compress_ptr cinfo) { | 
|  | skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; | 
|  |  | 
|  | //  if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer)) | 
|  | if (!dest->fStream->write(dest->fBuffer, | 
|  | skjpeg_destination_mgr::kBufferSize)) { | 
|  | ERREXIT(cinfo, JERR_FILE_WRITE); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | dest->next_output_byte = dest->fBuffer; | 
|  | dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | static void sk_term_destination (j_compress_ptr cinfo) { | 
|  | skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; | 
|  |  | 
|  | size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer; | 
|  | if (size > 0) { | 
|  | if (!dest->fStream->write(dest->fBuffer, size)) { | 
|  | ERREXIT(cinfo, JERR_FILE_WRITE); | 
|  | return; | 
|  | } | 
|  | } | 
|  | dest->fStream->flush(); | 
|  | } | 
|  |  | 
|  | skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream) | 
|  | : fStream(stream) { | 
|  | this->init_destination = sk_init_destination; | 
|  | this->empty_output_buffer = sk_empty_output_buffer; | 
|  | this->term_destination = sk_term_destination; | 
|  | } | 
|  |  | 
|  | void skjpeg_error_exit(j_common_ptr cinfo) { | 
|  | skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err; | 
|  |  | 
|  | (*error->output_message) (cinfo); | 
|  |  | 
|  | /* Let the memory manager delete any temp files before we die */ | 
|  | jpeg_destroy(cinfo); | 
|  |  | 
|  | longjmp(error->fJmpBuf, -1); | 
|  | } |