refactor helper functions out of libjpeg wrapper



git-svn-id: http://skia.googlecode.com/svn/trunk@476 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/images/SkJpegUtility.h b/include/images/SkJpegUtility.h
new file mode 100644
index 0000000..cc9d246
--- /dev/null
+++ b/include/images/SkJpegUtility.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkJpegUtility_DEFINED
+#define SkJpegUtility_DEFINED
+
+#include "SkImageDecoder.h"
+#include "SkStream.h"
+
+extern "C" {
+    #include "jpeglib.h"
+    #include "jerror.h"
+}
+
+#include <setjmp.h>
+
+/* Our error-handling struct.
+ *
+*/
+struct skjpeg_error_mgr : jpeg_error_mgr {
+    jmp_buf fJmpBuf;
+};
+
+
+void skjpeg_error_exit(j_common_ptr cinfo);
+
+///////////////////////////////////////////////////////////////////////////
+/* Our source struct for directing jpeg to our stream object.
+*/
+struct skjpeg_source_mgr : jpeg_source_mgr {
+    skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder);
+
+    SkStream*   fStream;
+    const void* fMemoryBase;
+    size_t      fMemoryBaseSize;
+    SkImageDecoder* fDecoder;
+    enum {
+        kBufferSize = 1024
+    };
+    char    fBuffer[kBufferSize];
+};
+
+/////////////////////////////////////////////////////////////////////////////
+/* Our destination struct for directing decompressed pixels to our stream
+ * object.
+ */
+struct skjpeg_destination_mgr : jpeg_destination_mgr {
+    skjpeg_destination_mgr(SkWStream* stream);
+
+    SkWStream*  fStream;
+
+    enum {
+        kBufferSize = 1024
+    };
+    uint8_t fBuffer[kBufferSize];
+};
+
+#endif
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 2bb922a..fa2188e 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -16,6 +16,7 @@
 
 #include "SkImageDecoder.h"
 #include "SkImageEncoder.h"
+#include "SkJpegUtility.h"
 #include "SkColorPriv.h"
 #include "SkDither.h"
 #include "SkScaledBitmapSampler.h"
@@ -78,21 +79,6 @@
     SkMSec      fNow;
 };
 
-/* our source struct for directing jpeg to our stream object
-*/
-struct sk_source_mgr : jpeg_source_mgr {
-    sk_source_mgr(SkStream* stream, SkImageDecoder* decoder);
-
-    SkStream*   fStream;
-    const void* fMemoryBase;
-    size_t      fMemoryBaseSize;
-    SkImageDecoder* fDecoder;
-    enum {
-        kBufferSize = 1024
-    };
-    char    fBuffer[kBufferSize];
-};
-
 /* Automatically clean up after throwing an exception */
 class JPEGAutoClean {
 public:
@@ -109,95 +95,6 @@
     jpeg_decompress_struct* cinfo_ptr;
 };
 
-static void sk_init_source(j_decompress_ptr cinfo) {
-    sk_source_mgr*  src = (sk_source_mgr*)cinfo->src;
-    src->next_input_byte = (const JOCTET*)src->fBuffer;
-    src->bytes_in_buffer = 0;
-}
-
-static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
-    sk_source_mgr* src = (sk_source_mgr*)cinfo->src;
-    if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
-        return FALSE;
-    }
-    size_t bytes = src->fStream->read(src->fBuffer, sk_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;
-    }
-
-    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) {
-    SkASSERT(num_bytes > 0);
-
-    sk_source_mgr*  src = (sk_source_mgr*)cinfo->src;
-
-    long bytesToSkip = num_bytes - src->bytes_in_buffer;
-
-    // check if the skip amount exceeds the current buffer
-    if (bytesToSkip > 0) {
-        size_t bytes = src->fStream->skip(bytesToSkip);
-        if (bytes != (size_t)bytesToSkip) {
-//            SkDebugf("xxxxxxxxxxxxxx failure to skip request %d actual %d\n", bytesToSkip, bytes);
-            cinfo->err->error_exit((j_common_ptr)cinfo);
-        }
-        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 boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
-    sk_source_mgr*  src = (sk_source_mgr*)cinfo->src;
-
-    // what is the desired param for???
-
-    if (!src->fStream->rewind()) {
-        SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
-        cinfo->err->error_exit((j_common_ptr)cinfo);
-        return FALSE;
-    }
-    src->next_input_byte = (const JOCTET*)src->fBuffer;
-    src->bytes_in_buffer = 0;
-    return TRUE;
-}
-
-static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void skmem_init_source(j_decompress_ptr cinfo) {
-    sk_source_mgr*  src = (sk_source_mgr*)cinfo->src;
-    src->next_input_byte = (const JOCTET*)src->fMemoryBase;
-    src->bytes_in_buffer = src->fMemoryBaseSize;
-}
-
-static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
-    SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n");
-    return FALSE;
-}
-
-static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
-    sk_source_mgr*  src = (sk_source_mgr*)cinfo->src;
-//    SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes);
-    src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes);
-    src->bytes_in_buffer -= num_bytes;
-}
-
-static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) {
-    SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n");
-    return TRUE;
-}
-
-static void skmem_term_source(j_decompress_ptr /*cinfo*/) {}
-
 #ifdef ANDROID
 /* Check if the memory cap property is set.
    If so, use the memory size for jpeg decode.
@@ -214,49 +111,6 @@
 }
 #endif
 
-///////////////////////////////////////////////////////////////////////////////
-
-sk_source_mgr::sk_source_mgr(SkStream* stream, SkImageDecoder* decoder) : fStream(stream) {
-    fDecoder = decoder;
-    const void* baseAddr = stream->getMemoryBase();
-    if (baseAddr && false) {
-        fMemoryBase = baseAddr;
-        fMemoryBaseSize = stream->getLength();
-        
-        init_source = skmem_init_source;
-        fill_input_buffer = skmem_fill_input_buffer;
-        skip_input_data = skmem_skip_input_data;
-        resync_to_restart = skmem_resync_to_restart;
-        term_source = skmem_term_source;
-    } else {
-        fMemoryBase = NULL;
-        fMemoryBaseSize = 0;
-
-        init_source = sk_init_source;
-        fill_input_buffer = sk_fill_input_buffer;
-        skip_input_data = sk_skip_input_data;
-        resync_to_restart = sk_resync_to_restart;
-        term_source = sk_term_source;
-    }
-//    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
-}
-
-#include <setjmp.h>
-
-struct sk_error_mgr : jpeg_error_mgr {
-    jmp_buf fJmpBuf;
-};
-
-static void sk_error_exit(j_common_ptr cinfo) {
-    sk_error_mgr* error = (sk_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);
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -294,11 +148,11 @@
     JPEGAutoClean autoClean;
 
     jpeg_decompress_struct  cinfo;
-    sk_error_mgr            sk_err;
-    sk_source_mgr           sk_stream(stream, this);
+    skjpeg_error_mgr        sk_err;
+    skjpeg_source_mgr       sk_stream(stream, this);
 
     cinfo.err = jpeg_std_error(&sk_err);
-    sk_err.error_exit = sk_error_exit;
+    sk_err.error_exit = skjpeg_error_exit;
 
     // All objects need to be instantiated before this setjmp call so that
     // they will be cleaned up properly if an error occurs.
@@ -681,58 +535,6 @@
     }
 }
 
-struct sk_destination_mgr : jpeg_destination_mgr {
-    sk_destination_mgr(SkWStream* stream);
-
-    SkWStream*  fStream;
-
-    enum {
-        kBufferSize = 1024
-    };
-    uint8_t fBuffer[kBufferSize];
-};
-
-static void sk_init_destination(j_compress_ptr cinfo) {
-    sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest;
-
-    dest->next_output_byte = dest->fBuffer;
-    dest->free_in_buffer = sk_destination_mgr::kBufferSize;
-}
-
-static boolean sk_empty_output_buffer(j_compress_ptr cinfo) {
-    sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest;
-
-//  if (!dest->fStream->write(dest->fBuffer, sk_destination_mgr::kBufferSize - dest->free_in_buffer))
-    if (!dest->fStream->write(dest->fBuffer, sk_destination_mgr::kBufferSize)) {
-        ERREXIT(cinfo, JERR_FILE_WRITE);
-        return false;
-    }
-
-    dest->next_output_byte = dest->fBuffer;
-    dest->free_in_buffer = sk_destination_mgr::kBufferSize;
-    return TRUE;
-}
-
-static void sk_term_destination (j_compress_ptr cinfo) {
-    sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest;
-
-    size_t size = sk_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();
-}
-
-sk_destination_mgr::sk_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;
-}
-
 class SkJPEGImageEncoder : public SkImageEncoder {
 protected:
     virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
@@ -751,15 +553,15 @@
         }
 
         jpeg_compress_struct    cinfo;
-        sk_error_mgr            sk_err;
-        sk_destination_mgr      sk_wstream(stream);
+        skjpeg_error_mgr        sk_err;
+        skjpeg_destination_mgr  sk_wstream(stream);
 
         // allocate these before set call setjmp
         SkAutoMalloc    oneRow;
         SkAutoLockColors ctLocker;
 
         cinfo.err = jpeg_std_error(&sk_err);
-        sk_err.error_exit = sk_error_exit;
+        sk_err.error_exit = skjpeg_error_exit;
         if (setjmp(sk_err.fJmpBuf)) {
             return false;
         }
@@ -830,4 +632,3 @@
 
 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
-
diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp
new file mode 100644
index 0000000..9c6eb04
--- /dev/null
+++ b/src/images/SkJpegUtility.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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;
+}
+
+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;
+    }
+
+    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) {
+    SkASSERT(num_bytes > 0);
+
+    skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
+
+    long bytesToSkip = num_bytes - src->bytes_in_buffer;
+
+    // check if the skip amount exceeds the current buffer
+    if (bytesToSkip > 0) {
+        size_t bytes = src->fStream->skip(bytesToSkip);
+        if (bytes != (size_t)bytesToSkip) {
+//            SkDebugf("xxxxxxxxxxxxxx failure to skip request %d actual %d\n", bytesToSkip, bytes);
+            cinfo->err->error_exit((j_common_ptr)cinfo);
+        }
+        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 boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
+    skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
+
+    // what is the desired param for???
+
+    if (!src->fStream->rewind()) {
+        SkDebugf("xxxxxxxxxxxxxx failure to rewind\n");
+        cinfo->err->error_exit((j_common_ptr)cinfo);
+        return FALSE;
+    }
+    src->next_input_byte = (const JOCTET*)src->fBuffer;
+    src->bytes_in_buffer = 0;
+    return TRUE;
+}
+
+static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
+
+
+static void skmem_init_source(j_decompress_ptr cinfo) {
+    skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
+    src->next_input_byte = (const JOCTET*)src->fMemoryBase;
+    src->bytes_in_buffer = src->fMemoryBaseSize;
+}
+
+static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
+    SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n");
+    return FALSE;
+}
+
+static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
+    skjpeg_source_mgr*  src = (skjpeg_source_mgr*)cinfo->src;
+//    SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes);
+    src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes);
+    src->bytes_in_buffer -= num_bytes;
+}
+
+static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) {
+    SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n");
+    return TRUE;
+}
+
+static void skmem_term_source(j_decompress_ptr /*cinfo*/) {}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) : fStream(stream) {
+    fDecoder = decoder;
+    const void* baseAddr = stream->getMemoryBase();
+    if (baseAddr && false) {
+        fMemoryBase = baseAddr;
+        fMemoryBaseSize = stream->getLength();
+
+        init_source = skmem_init_source;
+        fill_input_buffer = skmem_fill_input_buffer;
+        skip_input_data = skmem_skip_input_data;
+        resync_to_restart = skmem_resync_to_restart;
+        term_source = skmem_term_source;
+    } else {
+        fMemoryBase = NULL;
+        fMemoryBaseSize = 0;
+
+        init_source = sk_init_source;
+        fill_input_buffer = sk_fill_input_buffer;
+        skip_input_data = sk_skip_input_data;
+        resync_to_restart = sk_resync_to_restart;
+        term_source = sk_term_source;
+    }
+//    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+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);
+}