gfx/skia/trunk/src/pdf/SkPDFImage.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2010 The Android Open Source Project
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #include "SkPDFImage.h"
    10 #include "SkBitmap.h"
    11 #include "SkColor.h"
    12 #include "SkColorPriv.h"
    13 #include "SkData.h"
    14 #include "SkFlate.h"
    15 #include "SkPDFCatalog.h"
    16 #include "SkRect.h"
    17 #include "SkStream.h"
    18 #include "SkString.h"
    19 #include "SkUnPreMultiply.h"
    21 static const int kNoColorTransform = 0;
    23 static bool skip_compression(SkPDFCatalog* catalog) {
    24     return SkToBool(catalog->getDocumentFlags() &
    25                     SkPDFDocument::kFavorSpeedOverSize_Flags);
    26 }
    28 static size_t get_uncompressed_size(const SkBitmap& bitmap,
    29                                     const SkIRect& srcRect) {
    30     switch (bitmap.config()) {
    31         case SkBitmap::kIndex8_Config:
    32             return srcRect.width() * srcRect.height();
    33         case SkBitmap::kARGB_4444_Config:
    34             return ((srcRect.width() * 3 + 1) / 2) * srcRect.height();
    35         case SkBitmap::kRGB_565_Config:
    36             return srcRect.width() * 3 * srcRect.height();
    37         case SkBitmap::kARGB_8888_Config:
    38             return srcRect.width() * 3 * srcRect.height();
    39         case SkBitmap::kA8_Config:
    40             return 1;
    41         default:
    42             SkASSERT(false);
    43             return 0;
    44     }
    45 }
    47 static SkStream* extract_index8_image(const SkBitmap& bitmap,
    48                                       const SkIRect& srcRect) {
    49     const int rowBytes = srcRect.width();
    50     SkStream* stream = SkNEW_ARGS(SkMemoryStream,
    51                                   (get_uncompressed_size(bitmap, srcRect)));
    52     uint8_t* dst = (uint8_t*)stream->getMemoryBase();
    54     for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
    55         memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes);
    56         dst += rowBytes;
    57     }
    58     return stream;
    59 }
    61 static SkStream* extract_argb4444_data(const SkBitmap& bitmap,
    62                                        const SkIRect& srcRect,
    63                                        bool extractAlpha,
    64                                        bool* isOpaque,
    65                                        bool* isTransparent) {
    66     SkStream* stream;
    67     uint8_t* dst = NULL;
    68     if (extractAlpha) {
    69         const int alphaRowBytes = (srcRect.width() + 1) / 2;
    70         stream = SkNEW_ARGS(SkMemoryStream,
    71                             (alphaRowBytes * srcRect.height()));
    72     } else {
    73         stream = SkNEW_ARGS(SkMemoryStream,
    74                             (get_uncompressed_size(bitmap, srcRect)));
    75     }
    76     dst = (uint8_t*)stream->getMemoryBase();
    78     for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
    79         uint16_t* src = bitmap.getAddr16(0, y);
    80         int x;
    81         for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) {
    82             if (extractAlpha) {
    83                 dst[0] = (SkGetPackedA4444(src[x]) << 4) |
    84                     SkGetPackedA4444(src[x + 1]);
    85                 *isOpaque &= dst[0] == SK_AlphaOPAQUE;
    86                 *isTransparent &= dst[0] == SK_AlphaTRANSPARENT;
    87                 dst++;
    88             } else {
    89                 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
    90                     SkGetPackedG4444(src[x]);
    91                 dst[1] = (SkGetPackedB4444(src[x]) << 4) |
    92                     SkGetPackedR4444(src[x + 1]);
    93                 dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) |
    94                     SkGetPackedB4444(src[x + 1]);
    95                 dst += 3;
    96             }
    97         }
    98         if (srcRect.width() & 1) {
    99             if (extractAlpha) {
   100                 dst[0] = (SkGetPackedA4444(src[x]) << 4);
   101                 *isOpaque &= dst[0] == (SK_AlphaOPAQUE & 0xF0);
   102                 *isTransparent &= dst[0] == (SK_AlphaTRANSPARENT & 0xF0);
   103                 dst++;
   105             } else {
   106                 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
   107                     SkGetPackedG4444(src[x]);
   108                 dst[1] = (SkGetPackedB4444(src[x]) << 4);
   109                 dst += 2;
   110             }
   111         }
   112     }
   113     return stream;
   114 }
   116 static SkStream* extract_rgb565_image(const SkBitmap& bitmap,
   117                                       const SkIRect& srcRect) {
   118     SkStream* stream = SkNEW_ARGS(SkMemoryStream,
   119                                   (get_uncompressed_size(bitmap,
   120                                                      srcRect)));
   121     uint8_t* dst = (uint8_t*)stream->getMemoryBase();
   122     for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
   123         uint16_t* src = bitmap.getAddr16(0, y);
   124         for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
   125             dst[0] = SkGetPackedR16(src[x]);
   126             dst[1] = SkGetPackedG16(src[x]);
   127             dst[2] = SkGetPackedB16(src[x]);
   128             dst += 3;
   129         }
   130     }
   131     return stream;
   132 }
   134 static SkStream* extract_argb8888_data(const SkBitmap& bitmap,
   135                                        const SkIRect& srcRect,
   136                                        bool extractAlpha,
   137                                        bool* isOpaque,
   138                                        bool* isTransparent) {
   139     SkStream* stream;
   140     if (extractAlpha) {
   141         stream = SkNEW_ARGS(SkMemoryStream,
   142                             (srcRect.width() * srcRect.height()));
   143     } else {
   144         stream = SkNEW_ARGS(SkMemoryStream,
   145                             (get_uncompressed_size(bitmap, srcRect)));
   146     }
   147     uint8_t* dst = (uint8_t*)stream->getMemoryBase();
   149     for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
   150         uint32_t* src = bitmap.getAddr32(0, y);
   151         for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
   152             if (extractAlpha) {
   153                 dst[0] = SkGetPackedA32(src[x]);
   154                 *isOpaque &= dst[0] == SK_AlphaOPAQUE;
   155                 *isTransparent &= dst[0] == SK_AlphaTRANSPARENT;
   156                 dst++;
   157             } else {
   158                 dst[0] = SkGetPackedR32(src[x]);
   159                 dst[1] = SkGetPackedG32(src[x]);
   160                 dst[2] = SkGetPackedB32(src[x]);
   161                 dst += 3;
   162             }
   163         }
   164     }
   165     return stream;
   166 }
   168 static SkStream* extract_a8_alpha(const SkBitmap& bitmap,
   169                                   const SkIRect& srcRect,
   170                                   bool* isOpaque,
   171                                   bool* isTransparent) {
   172     const int alphaRowBytes = srcRect.width();
   173     SkStream* stream = SkNEW_ARGS(SkMemoryStream,
   174                                   (alphaRowBytes * srcRect.height()));
   175     uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase();
   177     for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
   178         uint8_t* src = bitmap.getAddr8(0, y);
   179         for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
   180             alphaDst[0] = src[x];
   181             *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE;
   182             *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT;
   183             alphaDst++;
   184         }
   185     }
   186     return stream;
   187 }
   189 static SkStream* create_black_image() {
   190     SkStream* stream = SkNEW_ARGS(SkMemoryStream, (1));
   191     ((uint8_t*)stream->getMemoryBase())[0] = 0;
   192     return stream;
   193 }
   195 /**
   196  * Extract either the color or image data from a SkBitmap into a SkStream.
   197  * @param bitmap        Bitmap to extract data from.
   198  * @param srcRect       Region in the bitmap to extract.
   199  * @param extractAlpha  Set to true to extract the alpha data or false to
   200  *                      extract the color data.
   201  * @param isTransparent Pointer to a bool to output whether the alpha is
   202  *                      completely transparent. May be NULL. Only valid when
   203  *                      extractAlpha == true.
   204  * @return              Unencoded image data, or NULL if either data was not
   205  *                      available or alpha data was requested but the image was
   206  *                      entirely transparent or opaque.
   207  */
   208 static SkStream* extract_image_data(const SkBitmap& bitmap,
   209                                     const SkIRect& srcRect,
   210                                     bool extractAlpha, bool* isTransparent) {
   211     SkBitmap::Config config = bitmap.config();
   212     if (extractAlpha && (config == SkBitmap::kIndex8_Config ||
   213             config == SkBitmap::kRGB_565_Config)) {
   214         if (isTransparent != NULL) {
   215             *isTransparent = false;
   216         }
   217         return NULL;
   218     }
   219     bool isOpaque = true;
   220     bool transparent = extractAlpha;
   221     SkStream* stream = NULL;
   223     bitmap.lockPixels();
   224     switch (config) {
   225         case SkBitmap::kIndex8_Config:
   226             if (!extractAlpha) {
   227                 stream = extract_index8_image(bitmap, srcRect);
   228             }
   229             break;
   230         case SkBitmap::kARGB_4444_Config:
   231             stream = extract_argb4444_data(bitmap, srcRect, extractAlpha,
   232                                            &isOpaque, &transparent);
   233             break;
   234         case SkBitmap::kRGB_565_Config:
   235             if (!extractAlpha) {
   236                 stream = extract_rgb565_image(bitmap, srcRect);
   237             }
   238             break;
   239         case SkBitmap::kARGB_8888_Config:
   240             stream = extract_argb8888_data(bitmap, srcRect, extractAlpha,
   241                                            &isOpaque, &transparent);
   242             break;
   243         case SkBitmap::kA8_Config:
   244             if (!extractAlpha) {
   245                 stream = create_black_image();
   246             } else {
   247                 stream = extract_a8_alpha(bitmap, srcRect,
   248                                           &isOpaque, &transparent);
   249             }
   250             break;
   251         default:
   252             SkASSERT(false);
   253     }
   254     bitmap.unlockPixels();
   256     if (isTransparent != NULL) {
   257         *isTransparent = transparent;
   258     }
   259     if (extractAlpha && (transparent || isOpaque)) {
   260         SkSafeUnref(stream);
   261         return NULL;
   262     }
   263     return stream;
   264 }
   266 static SkPDFArray* make_indexed_color_space(SkColorTable* table) {
   267     SkPDFArray* result = new SkPDFArray();
   268     result->reserve(4);
   269     result->appendName("Indexed");
   270     result->appendName("DeviceRGB");
   271     result->appendInt(table->count() - 1);
   273     // Potentially, this could be represented in fewer bytes with a stream.
   274     // Max size as a string is 1.5k.
   275     SkString index;
   276     for (int i = 0; i < table->count(); i++) {
   277         char buf[3];
   278         SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]);
   279         buf[0] = SkGetPackedR32(color);
   280         buf[1] = SkGetPackedG32(color);
   281         buf[2] = SkGetPackedB32(color);
   282         index.append(buf, 3);
   283     }
   284     result->append(new SkPDFString(index))->unref();
   285     return result;
   286 }
   288 /**
   289  * Removes the alpha component of an ARGB color (including unpremultiply) while
   290  * keeping the output in the same format as the input.
   291  */
   292 static uint32_t remove_alpha_argb8888(uint32_t pmColor) {
   293     SkColor color = SkUnPreMultiply::PMColorToColor(pmColor);
   294     return SkPackARGB32NoCheck(SK_AlphaOPAQUE,
   295                                SkColorGetR(color),
   296                                SkColorGetG(color),
   297                                SkColorGetB(color));
   298 }
   300 static uint16_t remove_alpha_argb4444(uint16_t pmColor) {
   301     return SkPixel32ToPixel4444(
   302             remove_alpha_argb8888(SkPixel4444ToPixel32(pmColor)));
   303 }
   305 static uint32_t get_argb8888_neighbor_avg_color(const SkBitmap& bitmap,
   306                                                 int xOrig, int yOrig) {
   307     uint8_t count = 0;
   308     uint16_t r = 0;
   309     uint16_t g = 0;
   310     uint16_t b = 0;
   312     for (int y = yOrig - 1; y <= yOrig + 1; y++) {
   313         if (y < 0 || y >= bitmap.height()) {
   314             continue;
   315         }
   316         uint32_t* src = bitmap.getAddr32(0, y);
   317         for (int x = xOrig - 1; x <= xOrig + 1; x++) {
   318             if (x < 0 || x >= bitmap.width()) {
   319                 continue;
   320             }
   321             if (SkGetPackedA32(src[x]) != SK_AlphaTRANSPARENT) {
   322                 uint32_t color = remove_alpha_argb8888(src[x]);
   323                 r += SkGetPackedR32(color);
   324                 g += SkGetPackedG32(color);
   325                 b += SkGetPackedB32(color);
   326                 count++;
   327             }
   328         }
   329     }
   331     if (count == 0) {
   332         return SkPackARGB32NoCheck(SK_AlphaOPAQUE, 0, 0, 0);
   333     } else {
   334         return SkPackARGB32NoCheck(SK_AlphaOPAQUE,
   335                                    r / count, g / count, b / count);
   336     }
   337 }
   339 static uint16_t get_argb4444_neighbor_avg_color(const SkBitmap& bitmap,
   340                                                 int xOrig, int yOrig) {
   341     uint8_t count = 0;
   342     uint8_t r = 0;
   343     uint8_t g = 0;
   344     uint8_t b = 0;
   346     for (int y = yOrig - 1; y <= yOrig + 1; y++) {
   347         if (y < 0 || y >= bitmap.height()) {
   348             continue;
   349         }
   350         uint16_t* src = bitmap.getAddr16(0, y);
   351         for (int x = xOrig - 1; x <= xOrig + 1; x++) {
   352             if (x < 0 || x >= bitmap.width()) {
   353                 continue;
   354             }
   355             if ((SkGetPackedA4444(src[x]) & 0x0F) != SK_AlphaTRANSPARENT) {
   356                 uint16_t color = remove_alpha_argb4444(src[x]);
   357                 r += SkGetPackedR4444(color);
   358                 g += SkGetPackedG4444(color);
   359                 b += SkGetPackedB4444(color);
   360                 count++;
   361             }
   362         }
   363     }
   365     if (count == 0) {
   366         return SkPackARGB4444(SK_AlphaOPAQUE & 0x0F, 0, 0, 0);
   367     } else {
   368         return SkPackARGB4444(SK_AlphaOPAQUE & 0x0F,
   369                                    r / count, g / count, b / count);
   370     }
   371 }
   373 static SkBitmap unpremultiply_bitmap(const SkBitmap& bitmap,
   374                                      const SkIRect& srcRect) {
   375     SkBitmap outBitmap;
   376     outBitmap.setConfig(bitmap.config(), srcRect.width(), srcRect.height());
   377     outBitmap.allocPixels();
   378     int dstRow = 0;
   380     outBitmap.lockPixels();
   381     bitmap.lockPixels();
   382     switch (bitmap.config()) {
   383         case SkBitmap::kARGB_4444_Config: {
   384             for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
   385                 uint16_t* dst = outBitmap.getAddr16(0, dstRow);
   386                 uint16_t* src = bitmap.getAddr16(0, y);
   387                 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
   388                     uint8_t a = SkGetPackedA4444(src[x]);
   389                     // It is necessary to average the color component of
   390                     // transparent pixels with their surrounding neighbors
   391                     // since the PDF renderer may separately re-sample the
   392                     // alpha and color channels when the image is not
   393                     // displayed at its native resolution. Since an alpha of
   394                     // zero gives no information about the color component,
   395                     // the pathological case is a white image with sharp
   396                     // transparency bounds - the color channel goes to black,
   397                     // and the should-be-transparent pixels are rendered
   398                     // as grey because of the separate soft mask and color
   399                     // resizing.
   400                     if (a == (SK_AlphaTRANSPARENT & 0x0F)) {
   401                         *dst = get_argb4444_neighbor_avg_color(bitmap, x, y);
   402                     } else {
   403                         *dst = remove_alpha_argb4444(src[x]);
   404                     }
   405                     dst++;
   406                 }
   407                 dstRow++;
   408             }
   409             break;
   410         }
   411         case SkBitmap::kARGB_8888_Config: {
   412             for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
   413                 uint32_t* dst = outBitmap.getAddr32(0, dstRow);
   414                 uint32_t* src = bitmap.getAddr32(0, y);
   415                 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
   416                     uint8_t a = SkGetPackedA32(src[x]);
   417                     if (a == SK_AlphaTRANSPARENT) {
   418                         *dst = get_argb8888_neighbor_avg_color(bitmap, x, y);
   419                     } else {
   420                         *dst = remove_alpha_argb8888(src[x]);
   421                     }
   422                     dst++;
   423                 }
   424                 dstRow++;
   425             }
   426             break;
   427         }
   428         default:
   429             SkASSERT(false);
   430     }
   431     bitmap.unlockPixels();
   432     outBitmap.unlockPixels();
   434     outBitmap.setImmutable();
   436     return outBitmap;
   437 }
   439 // static
   440 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
   441                                     const SkIRect& srcRect,
   442                                     SkPicture::EncodeBitmap encoder) {
   443     if (bitmap.config() == SkBitmap::kNo_Config) {
   444         return NULL;
   445     }
   447     bool isTransparent = false;
   448     SkAutoTUnref<SkStream> alphaData;
   449     if (!bitmap.isOpaque()) {
   450         // Note that isOpaque is not guaranteed to return false for bitmaps
   451         // with alpha support but a completely opaque alpha channel,
   452         // so alphaData may still be NULL if we have a completely opaque
   453         // (or transparent) bitmap.
   454         alphaData.reset(
   455                 extract_image_data(bitmap, srcRect, true, &isTransparent));
   456     }
   457     if (isTransparent) {
   458         return NULL;
   459     }
   461     SkPDFImage* image;
   462     SkBitmap::Config config = bitmap.config();
   463     if (alphaData.get() != NULL && (config == SkBitmap::kARGB_8888_Config ||
   464             config == SkBitmap::kARGB_4444_Config)) {
   465         SkBitmap unpremulBitmap = unpremultiply_bitmap(bitmap, srcRect);
   466         image = SkNEW_ARGS(SkPDFImage, (NULL, unpremulBitmap, false,
   467                            SkIRect::MakeWH(srcRect.width(), srcRect.height()),
   468                            encoder));
   469     } else {
   470         image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap, false, srcRect, encoder));
   471     }
   472     if (alphaData.get() != NULL) {
   473         SkAutoTUnref<SkPDFImage> mask(
   474                 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap,
   475                                         true, srcRect, NULL)));
   476         image->addSMask(mask);
   477     }
   479     return image;
   480 }
   482 SkPDFImage::~SkPDFImage() {
   483     fResources.unrefAll();
   484 }
   486 SkPDFImage* SkPDFImage::addSMask(SkPDFImage* mask) {
   487     fResources.push(mask);
   488     mask->ref();
   489     insert("SMask", new SkPDFObjRef(mask))->unref();
   490     return mask;
   491 }
   493 void SkPDFImage::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
   494                               SkTSet<SkPDFObject*>* newResourceObjects) {
   495     GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
   496 }
   498 SkPDFImage::SkPDFImage(SkStream* stream,
   499                        const SkBitmap& bitmap,
   500                        bool isAlpha,
   501                        const SkIRect& srcRect,
   502                        SkPicture::EncodeBitmap encoder)
   503     : fIsAlpha(isAlpha),
   504       fSrcRect(srcRect),
   505       fEncoder(encoder) {
   507     if (bitmap.isImmutable()) {
   508         fBitmap = bitmap;
   509     } else {
   510         bitmap.deepCopyTo(&fBitmap);
   511         fBitmap.setImmutable();
   512     }
   514     if (stream != NULL) {
   515         setData(stream);
   516         fStreamValid = true;
   517     } else {
   518         fStreamValid = false;
   519     }
   521     SkBitmap::Config config = fBitmap.config();
   523     insertName("Type", "XObject");
   524     insertName("Subtype", "Image");
   526     bool alphaOnly = (config == SkBitmap::kA8_Config);
   528     if (!isAlpha && alphaOnly) {
   529         // For alpha only images, we stretch a single pixel of black for
   530         // the color/shape part.
   531         SkAutoTUnref<SkPDFInt> one(new SkPDFInt(1));
   532         insert("Width", one.get());
   533         insert("Height", one.get());
   534     } else {
   535         insertInt("Width", fSrcRect.width());
   536         insertInt("Height", fSrcRect.height());
   537     }
   539     if (isAlpha || alphaOnly) {
   540         insertName("ColorSpace", "DeviceGray");
   541     } else if (config == SkBitmap::kIndex8_Config) {
   542         SkAutoLockPixels alp(fBitmap);
   543         insert("ColorSpace",
   544                make_indexed_color_space(fBitmap.getColorTable()))->unref();
   545     } else {
   546         insertName("ColorSpace", "DeviceRGB");
   547     }
   549     int bitsPerComp = 8;
   550     if (config == SkBitmap::kARGB_4444_Config) {
   551         bitsPerComp = 4;
   552     }
   553     insertInt("BitsPerComponent", bitsPerComp);
   555     if (config == SkBitmap::kRGB_565_Config) {
   556         SkASSERT(!isAlpha);
   557         SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0));
   558         SkAutoTUnref<SkPDFScalar> scale5Val(
   559                 new SkPDFScalar(8.2258f));  // 255/2^5-1
   560         SkAutoTUnref<SkPDFScalar> scale6Val(
   561                 new SkPDFScalar(4.0476f));  // 255/2^6-1
   562         SkAutoTUnref<SkPDFArray> decodeValue(new SkPDFArray());
   563         decodeValue->reserve(6);
   564         decodeValue->append(zeroVal.get());
   565         decodeValue->append(scale5Val.get());
   566         decodeValue->append(zeroVal.get());
   567         decodeValue->append(scale6Val.get());
   568         decodeValue->append(zeroVal.get());
   569         decodeValue->append(scale5Val.get());
   570         insert("Decode", decodeValue.get());
   571     }
   572 }
   574 SkPDFImage::SkPDFImage(SkPDFImage& pdfImage)
   575     : SkPDFStream(pdfImage),
   576       fBitmap(pdfImage.fBitmap),
   577       fIsAlpha(pdfImage.fIsAlpha),
   578       fSrcRect(pdfImage.fSrcRect),
   579       fEncoder(pdfImage.fEncoder),
   580       fStreamValid(pdfImage.fStreamValid) {
   581     // Nothing to do here - the image params are already copied in SkPDFStream's
   582     // constructor, and the bitmap will be regenerated and encoded in
   583     // populate.
   584 }
   586 bool SkPDFImage::populate(SkPDFCatalog* catalog) {
   587     if (getState() == kUnused_State) {
   588         // Initializing image data for the first time.
   589         SkDynamicMemoryWStream dctCompressedWStream;
   590         if (!skip_compression(catalog) && fEncoder &&
   591                 get_uncompressed_size(fBitmap, fSrcRect) > 1) {
   592             SkBitmap subset;
   593             // Extract subset
   594             if (!fBitmap.extractSubset(&subset, fSrcRect)) {
   595                 // TODO(edisonn) It fails only for kA1_Config, if that is a
   596                 // major concern we will fix it later, so far it is NYI.
   597                 return false;
   598             }
   599             size_t pixelRefOffset = 0;
   600             SkAutoTUnref<SkData> data(fEncoder(&pixelRefOffset, subset));
   601             if (data.get() && data->size() < get_uncompressed_size(fBitmap,
   602                                                                    fSrcRect)) {
   603                 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream,
   604                                                          (data)));
   605                 setData(stream.get());
   607                 insertName("Filter", "DCTDecode");
   608                 insertInt("ColorTransform", kNoColorTransform);
   609                 insertInt("Length", getData()->getLength());
   610                 setState(kCompressed_State);
   611                 return true;
   612             }
   613         }
   614         // Fallback method
   615         if (!fStreamValid) {
   616             SkAutoTUnref<SkStream> stream(
   617                     extract_image_data(fBitmap, fSrcRect, fIsAlpha, NULL));
   618             setData(stream);
   619             fStreamValid = true;
   620         }
   621         return INHERITED::populate(catalog);
   622     } else if (getState() == kNoCompression_State &&
   623             !skip_compression(catalog) &&
   624             (SkFlate::HaveFlate() || fEncoder)) {
   625         // Compression has not been requested when the stream was first created,
   626         // but the new catalog wants it compressed.
   627         if (!getSubstitute()) {
   628             SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this));
   629             setSubstitute(substitute);
   630             catalog->setSubstitute(this, substitute);
   631         }
   632         return false;
   633     }
   634     return true;
   635 }

mercurial