add optional pref-config table to codecs



git-svn-id: http://skia.googlecode.com/svn/trunk@519 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 4711f89..768d671 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -37,7 +37,8 @@
 
 SkImageDecoder::SkImageDecoder()
     : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1),
-      fDitherImage(true) {
+      fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
+      fUsePrefTable(false) {
 }
 
 SkImageDecoder::~SkImageDecoder() {
@@ -91,6 +92,46 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
+    if (NULL == pref) {
+        fUsePrefTable = false;
+    } else {
+        fUsePrefTable = true;
+        memcpy(fPrefTable, pref, sizeof(fPrefTable));
+    }
+}
+
+SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
+                                               bool srcHasAlpha) const {
+    SkBitmap::Config config;
+
+    if (fUsePrefTable) {
+        int index = 0;
+        switch (srcDepth) {
+            case kIndex_SrcDepth:
+                index = 0;
+                break;
+            case k16Bit_SrcDepth:
+                index = 2;
+                break;
+            case k32Bit_SrcDepth:
+                index = 4;
+                break;
+        }
+        if (srcHasAlpha) {
+            index += 1;
+        }
+        config = fPrefTable[index];
+    } else {
+        config = fDefaultPref;
+    }
+
+    if (SkBitmap::kNo_Config == config) {
+        config = SkImageDecoder::GetDeviceConfig();
+    }
+    return config;
+}
+
 bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
                             SkBitmap::Config pref, Mode mode) {
     // pass a temporary bitmap, so that if we return false, we are assured of
@@ -99,8 +140,10 @@
 
     // we reset this to false before calling onDecode
     fShouldCancelDecode = false;
+    // assign this, for use by getPrefConfig(), in case fUsePrefTable is false
+    fDefaultPref = pref;
 
-    if (!this->onDecode(stream, &tmp, pref, mode)) {
+    if (!this->onDecode(stream, &tmp, mode)) {
         return false;
     }
     bm->swap(tmp);
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index a4dcbf6..30bfbdb 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -31,8 +31,7 @@
     }
 
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
 };
 
 static SkImageDecoder* Factory(SkStream* stream) {
@@ -81,8 +80,7 @@
     bool fJustBounds;
 };
 
-bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
-                                 SkBitmap::Config prefConfig, Mode mode) {
+bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
 
     size_t length = stream->getLength();
     SkAutoMalloc storage(length);
@@ -110,12 +108,12 @@
     
     int width = callback.width();
     int height = callback.height();
-    SkBitmap::Config config = SkBitmap::kARGB_8888_Config;
-    
+    SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
+
     // only accept prefConfig if it makes sense for us
-    if (SkBitmap::kARGB_4444_Config == prefConfig ||
-            SkBitmap::kRGB_565_Config == config) {
-        config = prefConfig;
+    if (SkBitmap::kARGB_4444_Config != config &&
+            SkBitmap::kRGB_565_Config != config) {
+        config = SkBitmap::kARGB_8888_Config;
     }
 
     SkScaledBitmapSampler sampler(width, height, getSampleSize());
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 258a8a0..d2470cc 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -31,8 +31,7 @@
     }
     
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
 };
 
 static const uint8_t gStartingIterlaceYValue[] = {
@@ -154,8 +153,7 @@
     return false;
 }
 
-bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm,
-                                 SkBitmap::Config prefConfig, Mode mode) {   
+bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
     GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
     if (NULL == gif) {
         return error_return(gif, *bm, "DGifOpen");
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index 9f21e13..ef5b7ac 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -29,8 +29,7 @@
     }
 
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -79,8 +78,7 @@
     return 0;
 }
 
-bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
-                                 SkBitmap::Config pref, Mode mode)
+bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
 {
     size_t length = stream->read(NULL, 0);
     SkAutoMalloc autoMal(length);
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 476cfa1..a64efbc 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -55,8 +55,7 @@
     }
 
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
 //////////////////////////////////////////////////////////////////////////
@@ -157,8 +156,7 @@
     return false;   // must always return false
 }
 
-bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
-                                  SkBitmap::Config prefConfig, Mode mode) {
+bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
 #ifdef TIME_DECODE
     AutoTimeMillis atm("JPEG Decode");
 #endif
@@ -215,11 +213,7 @@
     /* default format is RGB */
     cinfo.out_color_space = JCS_RGB;
 
-    SkBitmap::Config config = prefConfig;
-    // if no user preference, see what the device recommends
-    if (config == SkBitmap::kNo_Config)
-        config = SkImageDecoder::GetDeviceConfig();
-
+    SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
     // only these make sense for jpegs
     if (config != SkBitmap::kARGB_8888_Config &&
         config != SkBitmap::kARGB_4444_Config &&
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 6df56b4..3548fc8 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -37,8 +37,7 @@
     }
     
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
 #ifndef png_jmpbuf
@@ -110,9 +109,9 @@
     return reallyHasAlpha;
 }
 
-static bool canUpscalePaletteToConfig(SkBitmap::Config prefConfig,
+static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig,
                                       bool srcHasAlpha) {
-    switch (prefConfig) {
+    switch (dstConfig) {
         case SkBitmap::kARGB_8888_Config:
         case SkBitmap::kARGB_4444_Config:
             return true;
@@ -137,7 +136,7 @@
 }
 
 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
-                                 SkBitmap::Config prefConfig, Mode mode) {
+                                 Mode mode) {
 //    SkAutoTrace    apr("SkPNGImageDecoder::onDecode");
 
     /* Create and initialize the png_struct with the desired error handler
@@ -233,11 +232,11 @@
     }
     
     if (color_type == PNG_COLOR_TYPE_PALETTE) {
-        config = SkBitmap::kIndex8_Config;
-        // now see if we can upscale to their requested config
         bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
-        if (canUpscalePaletteToConfig(prefConfig, paletteHasAlpha)) {
-            config = prefConfig;
+        config = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
+        // now see if we can upscale to their requested config
+        if (!canUpscalePaletteToConfig(config, paletteHasAlpha)) {
+            config = SkBitmap::kIndex8_Config;
         }
     } else {
         png_color_16p   transpColor = NULL;
@@ -278,14 +277,16 @@
                 PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
                 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
             hasAlpha = true;
-            config = SkBitmap::kARGB_8888_Config;
-        } else {    // we get to choose the config
-            config = prefConfig;
-            if (config == SkBitmap::kNo_Config) {
-                config = SkImageDecoder::GetDeviceConfig();
+        }
+        config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha);
+        // now match the request against our capabilities
+        if (hasAlpha) {
+            if (config != SkBitmap::kARGB_4444_Config) {
+                config = SkBitmap::kARGB_8888_Config;
             }
+        } else {
             if (config != SkBitmap::kRGB_565_Config &&
-                    config != SkBitmap::kARGB_4444_Config) {
+                config != SkBitmap::kARGB_4444_Config) {
                 config = SkBitmap::kARGB_8888_Config;
             }
         }
@@ -311,9 +312,6 @@
     const int sampleSize = this->getSampleSize();
     SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
 
-    // we must always return the same config, independent of mode, so if we were
-    // going to respect prefConfig, it must have happened by now
-
     decodedBitmap->setConfig(config, sampler.scaledWidth(),
                              sampler.scaledHeight(), 0);
     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index ac242ea..6d63ca9 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -29,8 +29,7 @@
     }
     
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
 static bool read_byte(SkStream* stream, uint8_t* data)
@@ -107,7 +106,7 @@
 #define SkAlign8(x)     (((x) + 7) & ~7)
 
 bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
-                                  SkBitmap::Config prefConfig, Mode mode)
+                                  Mode mode)
 {
     wbmp_head   head;
     
diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp
index fc4f358..e207592 100644
--- a/src/images/SkJpegUtility.cpp
+++ b/src/images/SkJpegUtility.cpp
@@ -43,7 +43,7 @@
 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 > src->bytes_in_buffer) {
+    if (num_bytes > (long)src->bytes_in_buffer) {
         long bytesToSkip = num_bytes - src->bytes_in_buffer;
         while (bytesToSkip > 0) {
             long bytes = (long)src->fStream->skip(bytesToSkip);
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index ea865c8..e7a5528 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -42,14 +42,12 @@
 
 class SkImageDecoder_CG : public SkImageDecoder {
 protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode);
+    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
 };
 
 #define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
 
-bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm,
-                                 SkBitmap::Config pref, Mode mode) {
+bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
     CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
 
     if (NULL == imageSrc) {