gfx/skia/trunk/src/images/SkScaledBitmapSampler.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 2007 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  */
     9 #include "SkScaledBitmapSampler.h"
    10 #include "SkBitmap.h"
    11 #include "SkColorPriv.h"
    12 #include "SkDither.h"
    13 #include "SkTypes.h"
    15 // 8888
    17 static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
    18                               const uint8_t* SK_RESTRICT src,
    19                               int width, int deltaSrc, int, const SkPMColor[]) {
    20     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
    21     for (int x = 0; x < width; x++) {
    22         dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
    23         src += deltaSrc;
    24     }
    25     return false;
    26 }
    28 static SkScaledBitmapSampler::RowProc get_gray_to_8888_proc(const SkImageDecoder& decoder) {
    29     // Dither, unpremul, and skipZeroes have no effect
    30     return Sample_Gray_D8888;
    31 }
    33 static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
    34                               const uint8_t* SK_RESTRICT src,
    35                               int width, int deltaSrc, int, const SkPMColor[]) {
    36     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
    37     for (int x = 0; x < width; x++) {
    38         dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
    39         src += deltaSrc;
    40     }
    41     return false;
    42 }
    44 static SkScaledBitmapSampler::RowProc get_RGBx_to_8888_proc(const SkImageDecoder& decoder) {
    45     // Dither, unpremul, and skipZeroes have no effect
    46     return Sample_RGBx_D8888;
    47 }
    49 static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
    50                               const uint8_t* SK_RESTRICT src,
    51                               int width, int deltaSrc, int, const SkPMColor[]) {
    52     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
    53     unsigned alphaMask = 0xFF;
    54     for (int x = 0; x < width; x++) {
    55         unsigned alpha = src[3];
    56         dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
    57         src += deltaSrc;
    58         alphaMask &= alpha;
    59     }
    60     return alphaMask != 0xFF;
    61 }
    63 static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow,
    64                                        const uint8_t* SK_RESTRICT src,
    65                                        int width, int deltaSrc, int,
    66                                        const SkPMColor[]) {
    67     uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
    68     unsigned alphaMask = 0xFF;
    69     for (int x = 0; x < width; x++) {
    70         unsigned alpha = src[3];
    71         dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
    72         src += deltaSrc;
    73         alphaMask &= alpha;
    74     }
    75     return alphaMask != 0xFF;
    76 }
    78 static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow,
    79                                     const uint8_t* SK_RESTRICT src,
    80                                     int width, int deltaSrc, int,
    81                                     const SkPMColor[]) {
    82     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
    83     unsigned alphaMask = 0xFF;
    84     for (int x = 0; x < width; x++) {
    85         unsigned alpha = src[3];
    86         if (0 != alpha) {
    87             dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
    88         }
    89         src += deltaSrc;
    90         alphaMask &= alpha;
    91     }
    92     return alphaMask != 0xFF;
    93 }
    95 static SkScaledBitmapSampler::RowProc get_RGBA_to_8888_proc(const SkImageDecoder& decoder) {
    96     // Dither has no effect.
    97     if (decoder.getRequireUnpremultipliedColors()) {
    98         // We could check each component for a zero, at the expense of extra checks.
    99         // For now, just return unpremul.
   100         return Sample_RGBA_D8888_Unpremul;
   101     }
   102     // Supply the versions that premultiply the colors
   103     if (decoder.getSkipWritingZeroes()) {
   104         return Sample_RGBA_D8888_SkipZ;
   105     }
   106     return Sample_RGBA_D8888;
   107 }
   109 // 565
   111 static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
   112                              const uint8_t* SK_RESTRICT src,
   113                              int width, int deltaSrc, int, const SkPMColor[]) {
   114     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   115     for (int x = 0; x < width; x++) {
   116         dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
   117         src += deltaSrc;
   118     }
   119     return false;
   120 }
   122 static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
   123                                const uint8_t* SK_RESTRICT src,
   124                            int width, int deltaSrc, int y, const SkPMColor[]) {
   125     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   126     DITHER_565_SCAN(y);
   127     for (int x = 0; x < width; x++) {
   128         dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
   129         src += deltaSrc;
   130     }
   131     return false;
   132 }
   134 static SkScaledBitmapSampler::RowProc get_gray_to_565_proc(const SkImageDecoder& decoder) {
   135     // Unpremul and skip zeroes make no difference
   136     if (decoder.getDitherImage()) {
   137         return Sample_Gray_D565_D;
   138     }
   139     return Sample_Gray_D565;
   140 }
   142 static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
   143                              const uint8_t* SK_RESTRICT src,
   144                              int width, int deltaSrc, int, const SkPMColor[]) {
   145     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   146     for (int x = 0; x < width; x++) {
   147         dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
   148         src += deltaSrc;
   149     }
   150     return false;
   151 }
   153 static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
   154                                const uint8_t* SK_RESTRICT src,
   155                                int width, int deltaSrc, int y,
   156                                const SkPMColor[]) {
   157     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   158     DITHER_565_SCAN(y);
   159     for (int x = 0; x < width; x++) {
   160         dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
   161         src += deltaSrc;
   162     }
   163     return false;
   164 }
   166 static SkScaledBitmapSampler::RowProc get_RGBx_to_565_proc(const SkImageDecoder& decoder) {
   167     // Unpremul and skip zeroes make no difference
   168     if (decoder.getDitherImage()) {
   169         return Sample_RGBx_D565_D;
   170     }
   171     return Sample_RGBx_D565;
   172 }
   175 static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
   176                              const uint8_t* SK_RESTRICT src,
   177                              int width, int deltaSrc, int, const SkPMColor[]) {
   178     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   179     uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
   180     for (int x = 0; x < width; x++) {
   181         dst[x] = castedSrc[0];
   182         castedSrc += deltaSrc >> 1;
   183     }
   184     return false;
   185 }
   187 static SkScaledBitmapSampler::RowProc get_565_to_565_proc(const SkImageDecoder& decoder) {
   188     // Unpremul, dither, and skip zeroes have no effect
   189     return Sample_D565_D565;
   190 }
   192 // 4444
   194 static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
   195                               const uint8_t* SK_RESTRICT src,
   196                               int width, int deltaSrc, int, const SkPMColor[]) {
   197     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   198     for (int x = 0; x < width; x++) {
   199         unsigned gray = src[0] >> 4;
   200         dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
   201         src += deltaSrc;
   202     }
   203     return false;
   204 }
   206 static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
   207                                 const uint8_t* SK_RESTRICT src,
   208                             int width, int deltaSrc, int y, const SkPMColor[]) {
   209     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   210     DITHER_4444_SCAN(y);
   211     for (int x = 0; x < width; x++) {
   212         dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
   213                                       DITHER_VALUE(x));
   214         src += deltaSrc;
   215     }
   216     return false;
   217 }
   219 static SkScaledBitmapSampler::RowProc get_gray_to_4444_proc(const SkImageDecoder& decoder) {
   220     // Skip zeroes and unpremul make no difference
   221     if (decoder.getDitherImage()) {
   222         return Sample_Gray_D4444_D;
   223     }
   224     return Sample_Gray_D4444;
   225 }
   227 static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
   228                               const uint8_t* SK_RESTRICT src,
   229                               int width, int deltaSrc, int, const SkPMColor[]) {
   230     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   231     for (int x = 0; x < width; x++) {
   232         dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
   233         src += deltaSrc;
   234     }
   235     return false;
   236 }
   238 static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
   239                                 const uint8_t* SK_RESTRICT src,
   240                             int width, int deltaSrc, int y, const SkPMColor[]) {
   241     SkPMColor16* dst = (SkPMColor16*)dstRow;
   242     DITHER_4444_SCAN(y);
   244     for (int x = 0; x < width; x++) {
   245         dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
   246                                       DITHER_VALUE(x));
   247         src += deltaSrc;
   248     }
   249     return false;
   250 }
   252 static SkScaledBitmapSampler::RowProc get_RGBx_to_4444_proc(const SkImageDecoder& decoder) {
   253     // Skip zeroes and unpremul make no difference
   254     if (decoder.getDitherImage()) {
   255         return Sample_RGBx_D4444_D;
   256     }
   257     return Sample_RGBx_D4444;
   258 }
   260 static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
   261                               const uint8_t* SK_RESTRICT src,
   262                               int width, int deltaSrc, int, const SkPMColor[]) {
   263     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   264     unsigned alphaMask = 0xFF;
   266     for (int x = 0; x < width; x++) {
   267         unsigned alpha = src[3];
   268         SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
   269         dst[x] = SkPixel32ToPixel4444(c);
   270         src += deltaSrc;
   271         alphaMask &= alpha;
   272     }
   273     return alphaMask != 0xFF;
   274 }
   276 static bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow,
   277                                     const uint8_t* SK_RESTRICT src,
   278                                     int width, int deltaSrc, int,
   279                                     const SkPMColor[]) {
   280     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   281     unsigned alphaMask = 0xFF;
   283     for (int x = 0; x < width; x++) {
   284         unsigned alpha = src[3];
   285         if (alpha != 0) {
   286             SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
   287             dst[x] = SkPixel32ToPixel4444(c);
   288         }
   289         src += deltaSrc;
   290         alphaMask &= alpha;
   291     }
   292     return alphaMask != 0xFF;
   293 }
   296 static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
   297                                 const uint8_t* SK_RESTRICT src,
   298                                 int width, int deltaSrc, int y,
   299                                 const SkPMColor[]) {
   300     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   301     unsigned alphaMask = 0xFF;
   302     DITHER_4444_SCAN(y);
   304     for (int x = 0; x < width; x++) {
   305         unsigned alpha = src[3];
   306         SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
   307         dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
   308         src += deltaSrc;
   309         alphaMask &= alpha;
   310     }
   311     return alphaMask != 0xFF;
   312 }
   314 static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
   315                                       const uint8_t* SK_RESTRICT src,
   316                                       int width, int deltaSrc, int y,
   317                                       const SkPMColor[]) {
   318     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   319     unsigned alphaMask = 0xFF;
   320     DITHER_4444_SCAN(y);
   322     for (int x = 0; x < width; x++) {
   323         unsigned alpha = src[3];
   324         if (alpha != 0) {
   325             SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
   326             dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
   327         }
   328         src += deltaSrc;
   329         alphaMask &= alpha;
   330     }
   331     return alphaMask != 0xFF;
   332 }
   334 static SkScaledBitmapSampler::RowProc get_RGBA_to_4444_proc(const SkImageDecoder& decoder) {
   335     if (decoder.getRequireUnpremultipliedColors()) {
   336         // Unpremultiplied is not supported for 4444
   337         return NULL;
   338     }
   339     const bool dither = decoder.getDitherImage();
   340     if (decoder.getSkipWritingZeroes()) {
   341         if (dither) {
   342             return Sample_RGBA_D4444_D_SkipZ;
   343         }
   344         return Sample_RGBA_D4444_SkipZ;
   345     }
   346     if (dither) {
   347         return Sample_RGBA_D4444_D;
   348     }
   349     return Sample_RGBA_D4444;
   350 }
   352 // Index
   354 #define A32_MASK_IN_PLACE   (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
   356 static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
   357                                const uint8_t* SK_RESTRICT src,
   358                        int width, int deltaSrc, int, const SkPMColor ctable[]) {
   360     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
   361     SkPMColor cc = A32_MASK_IN_PLACE;
   362     for (int x = 0; x < width; x++) {
   363         SkPMColor c = ctable[*src];
   364         cc &= c;
   365         dst[x] = c;
   366         src += deltaSrc;
   367     }
   368     return cc != A32_MASK_IN_PLACE;
   369 }
   371 static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow,
   372                                      const uint8_t* SK_RESTRICT src,
   373                                      int width, int deltaSrc, int,
   374                                      const SkPMColor ctable[]) {
   376     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
   377     SkPMColor cc = A32_MASK_IN_PLACE;
   378     for (int x = 0; x < width; x++) {
   379         SkPMColor c = ctable[*src];
   380         cc &= c;
   381         if (c != 0) {
   382             dst[x] = c;
   383         }
   384         src += deltaSrc;
   385     }
   386     return cc != A32_MASK_IN_PLACE;
   387 }
   389 static SkScaledBitmapSampler::RowProc get_index_to_8888_proc(const SkImageDecoder& decoder) {
   390     if (decoder.getRequireUnpremultipliedColors()) {
   391         // Unpremultiplied is not supported for an index source.
   392         return NULL;
   393     }
   394     // Dither makes no difference
   395     if (decoder.getSkipWritingZeroes()) {
   396         return Sample_Index_D8888_SkipZ;
   397     }
   398     return Sample_Index_D8888;
   399 }
   401 static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
   402                                const uint8_t* SK_RESTRICT src,
   403                        int width, int deltaSrc, int, const SkPMColor ctable[]) {
   405     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   406     for (int x = 0; x < width; x++) {
   407         dst[x] = SkPixel32ToPixel16(ctable[*src]);
   408         src += deltaSrc;
   409     }
   410     return false;
   411 }
   413 static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
   414                                 const uint8_t* SK_RESTRICT src, int width,
   415                                 int deltaSrc, int y, const SkPMColor ctable[]) {
   417     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
   418     DITHER_565_SCAN(y);
   420     for (int x = 0; x < width; x++) {
   421         SkPMColor c = ctable[*src];
   422         dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
   423                                   SkGetPackedB32(c), DITHER_VALUE(x));
   424         src += deltaSrc;
   425     }
   426     return false;
   427 }
   429 static SkScaledBitmapSampler::RowProc get_index_to_565_proc(const SkImageDecoder& decoder) {
   430     // Unpremultiplied and skip zeroes make no difference
   431     if (decoder.getDitherImage()) {
   432         return Sample_Index_D565_D;
   433     }
   434     return Sample_Index_D565;
   435 }
   437 static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
   438                                const uint8_t* SK_RESTRICT src, int width,
   439                                int deltaSrc, int y, const SkPMColor ctable[]) {
   441     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   442     SkPMColor cc = A32_MASK_IN_PLACE;
   443     for (int x = 0; x < width; x++) {
   444         SkPMColor c = ctable[*src];
   445         cc &= c;
   446         dst[x] = SkPixel32ToPixel4444(c);
   447         src += deltaSrc;
   448     }
   449     return cc != A32_MASK_IN_PLACE;
   450 }
   452 static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
   453                                  const uint8_t* SK_RESTRICT src, int width,
   454                                 int deltaSrc, int y, const SkPMColor ctable[]) {
   456     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   457     SkPMColor cc = A32_MASK_IN_PLACE;
   458     DITHER_4444_SCAN(y);
   460     for (int x = 0; x < width; x++) {
   461         SkPMColor c = ctable[*src];
   462         cc &= c;
   463         dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
   464         src += deltaSrc;
   465     }
   466     return cc != A32_MASK_IN_PLACE;
   467 }
   469 static bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow,
   470                                      const uint8_t* SK_RESTRICT src, int width,
   471                                      int deltaSrc, int y, const SkPMColor ctable[]) {
   473     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   474     SkPMColor cc = A32_MASK_IN_PLACE;
   475     for (int x = 0; x < width; x++) {
   476         SkPMColor c = ctable[*src];
   477         cc &= c;
   478         if (c != 0) {
   479             dst[x] = SkPixel32ToPixel4444(c);
   480         }
   481         src += deltaSrc;
   482     }
   483     return cc != A32_MASK_IN_PLACE;
   484 }
   486 static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
   487                                        const uint8_t* SK_RESTRICT src, int width,
   488                                        int deltaSrc, int y, const SkPMColor ctable[]) {
   490     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
   491     SkPMColor cc = A32_MASK_IN_PLACE;
   492     DITHER_4444_SCAN(y);
   494     for (int x = 0; x < width; x++) {
   495         SkPMColor c = ctable[*src];
   496         cc &= c;
   497         if (c != 0) {
   498             dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
   499         }
   500         src += deltaSrc;
   501     }
   502     return cc != A32_MASK_IN_PLACE;
   503 }
   505 static SkScaledBitmapSampler::RowProc get_index_to_4444_proc(const SkImageDecoder& decoder) {
   506     // Unpremul not allowed
   507     if (decoder.getRequireUnpremultipliedColors()) {
   508         return NULL;
   509     }
   510     const bool dither = decoder.getDitherImage();
   511     if (decoder.getSkipWritingZeroes()) {
   512         if (dither) {
   513             return Sample_Index_D4444_D_SkipZ;
   514         }
   515         return Sample_Index_D4444_SkipZ;
   516     }
   517     if (dither) {
   518         return Sample_Index_D4444_D;
   519     }
   520     return Sample_Index_D4444;
   521 }
   523 static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
   524                             const uint8_t* SK_RESTRICT src,
   525                             int width, int deltaSrc, int, const SkPMColor[]) {
   526     if (1 == deltaSrc) {
   527         memcpy(dstRow, src, width);
   528     } else {
   529         uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
   530         for (int x = 0; x < width; x++) {
   531             dst[x] = src[0];
   532             src += deltaSrc;
   533         }
   534     }
   535     return false;
   536 }
   538 static SkScaledBitmapSampler::RowProc get_index_to_index_proc(const SkImageDecoder& decoder) {
   539     // Unpremul not allowed
   540     if (decoder.getRequireUnpremultipliedColors()) {
   541         return NULL;
   542     }
   543     // Ignore dither and skip zeroes
   544     return Sample_Index_DI;
   545 }
   547 // A8
   548 static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
   549                             const uint8_t* SK_RESTRICT src,
   550                             int width, int deltaSrc, int,
   551                             const SkPMColor[]) {
   552     // Sampling Gray to A8 uses the same function as Index to Index8,
   553     // except we assume that there is alpha for speed, since an A8
   554     // bitmap with no alpha is not interesting.
   555     (void) Sample_Index_DI(dstRow, src, width, deltaSrc, /* y unused */ 0,
   556                            /* ctable unused */ NULL);
   557     return true;
   558 }
   560 static SkScaledBitmapSampler::RowProc get_gray_to_A8_proc(const SkImageDecoder& decoder) {
   561     if (decoder.getRequireUnpremultipliedColors()) {
   562         return NULL;
   563     }
   564     // Ignore skip and dither.
   565     return Sample_Gray_DA8;
   566 }
   568 typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkImageDecoder& decoder);
   569 ///////////////////////////////////////////////////////////////////////////////
   571 #include "SkScaledBitmapSampler.h"
   573 SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
   574                                              int sampleSize) {
   575     fCTable = NULL;
   576     fDstRow = NULL;
   577     fRowProc = NULL;
   579     if (width <= 0 || height <= 0) {
   580         sk_throw();
   581     }
   583     SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode);
   585     if (sampleSize <= 1) {
   586         fScaledWidth = width;
   587         fScaledHeight = height;
   588         fX0 = fY0 = 0;
   589         fDX = fDY = 1;
   590         return;
   591     }
   593     int dx = SkMin32(sampleSize, width);
   594     int dy = SkMin32(sampleSize, height);
   596     fScaledWidth = width / dx;
   597     fScaledHeight = height / dy;
   599     SkASSERT(fScaledWidth > 0);
   600     SkASSERT(fScaledHeight > 0);
   602     fX0 = dx >> 1;
   603     fY0 = dy >> 1;
   605     SkASSERT(fX0 >= 0 && fX0 < width);
   606     SkASSERT(fY0 >= 0 && fY0 < height);
   608     fDX = dx;
   609     fDY = dy;
   611     SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
   612     SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
   613 }
   615 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
   616                                   const SkImageDecoder& decoder,
   617                                   const SkPMColor ctable[]) {
   618     static const RowProcChooser gProcChoosers[] = {
   619         get_gray_to_8888_proc,
   620         get_RGBx_to_8888_proc,
   621         get_RGBA_to_8888_proc,
   622         get_index_to_8888_proc,
   623         NULL, // 565 to 8888
   625         get_gray_to_565_proc,
   626         get_RGBx_to_565_proc,
   627         get_RGBx_to_565_proc, // The source alpha will be ignored.
   628         get_index_to_565_proc,
   629         get_565_to_565_proc,
   631         get_gray_to_4444_proc,
   632         get_RGBx_to_4444_proc,
   633         get_RGBA_to_4444_proc,
   634         get_index_to_4444_proc,
   635         NULL, // 565 to 4444
   637         NULL, // gray to index
   638         NULL, // rgbx to index
   639         NULL, // rgba to index
   640         get_index_to_index_proc,
   641         NULL, // 565 to index
   643         get_gray_to_A8_proc,
   644         NULL, // rgbx to a8
   645         NULL, // rgba to a8
   646         NULL, // index to a8
   647         NULL, // 565 to a8
   648     };
   650     // The jump between dst configs in the table
   651     static const int gProcDstConfigSpan = 5;
   652     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan,
   653                       gProcs_has_the_wrong_number_of_entries);
   655     fCTable = ctable;
   657     int index = 0;
   658     switch (sc) {
   659         case SkScaledBitmapSampler::kGray:
   660             fSrcPixelSize = 1;
   661             index += 0;
   662             break;
   663         case SkScaledBitmapSampler::kRGB:
   664             fSrcPixelSize = 3;
   665             index += 1;
   666             break;
   667         case SkScaledBitmapSampler::kRGBX:
   668             fSrcPixelSize = 4;
   669             index += 1;
   670             break;
   671         case SkScaledBitmapSampler::kRGBA:
   672             fSrcPixelSize = 4;
   673             index += 2;
   674             break;
   675         case SkScaledBitmapSampler::kIndex:
   676             fSrcPixelSize = 1;
   677             index += 3;
   678             break;
   679         case SkScaledBitmapSampler::kRGB_565:
   680             fSrcPixelSize = 2;
   681             index += 4;
   682             break;
   683         default:
   684             return false;
   685     }
   687     switch (dst->config()) {
   688         case SkBitmap::kARGB_8888_Config:
   689             index += 0 * gProcDstConfigSpan;
   690             break;
   691         case SkBitmap::kRGB_565_Config:
   692             index += 1 * gProcDstConfigSpan;
   693             break;
   694         case SkBitmap::kARGB_4444_Config:
   695             index += 2 * gProcDstConfigSpan;
   696             break;
   697         case SkBitmap::kIndex8_Config:
   698             index += 3 * gProcDstConfigSpan;
   699             break;
   700         case SkBitmap::kA8_Config:
   701             index += 4 * gProcDstConfigSpan;
   702             break;
   703         default:
   704             return false;
   705     }
   707     RowProcChooser chooser = gProcChoosers[index];
   708     if (NULL == chooser) {
   709         fRowProc = NULL;
   710     } else {
   711         fRowProc = chooser(decoder);
   712     }
   713     fDstRow = (char*)dst->getPixels();
   714     fDstRowBytes = dst->rowBytes();
   715     fCurrY = 0;
   716     return fRowProc != NULL;
   717 }
   719 bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
   720     SkASSERT(kInterlaced_SampleMode != fSampleMode);
   721     SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
   722     SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
   724     bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
   725                              fDX * fSrcPixelSize, fCurrY, fCTable);
   726     fDstRow += fDstRowBytes;
   727     fCurrY += 1;
   728     return hadAlpha;
   729 }
   731 bool SkScaledBitmapSampler::sampleInterlaced(const uint8_t* SK_RESTRICT src, int srcY) {
   732     SkASSERT(kConsecutive_SampleMode != fSampleMode);
   733     SkDEBUGCODE(fSampleMode = kInterlaced_SampleMode);
   734     // Any line that should be a part of the destination can be created by the formula:
   735     // fY0 + (some multiplier) * fDY
   736     // so if srcY - fY0 is not an integer multiple of fDY that srcY will be skipped.
   737     const int srcYMinusY0 = srcY - fY0;
   738     if (srcYMinusY0 % fDY != 0) {
   739         // This line is not part of the output, so return false for alpha, since we have
   740         // not added an alpha to the output.
   741         return false;
   742     }
   743     // Unlike in next(), where the data is used sequentially, this function skips around,
   744     // so fDstRow and fCurrY are never updated. fDstRow must always be the starting point
   745     // of the destination bitmap's pixels, which is used to calculate the destination row
   746     // each time this function is called.
   747     const int dstY = srcYMinusY0 / fDY;
   748     SkASSERT(dstY < fScaledHeight);
   749     char* dstRow = fDstRow + dstY * fDstRowBytes;
   750     return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
   751                     fDX * fSrcPixelSize, dstY, fCTable);
   752 }
   754 #ifdef SK_DEBUG
   755 // The following code is for a test to ensure that changing the method to get the right row proc
   756 // did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp
   758 // friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc.
   759 class RowProcTester {
   760 public:
   761     static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) {
   762         return sampler.fRowProc;
   763     }
   764 };
   767 // Table showing the expected RowProc for each combination of inputs.
   768 // Table formated as follows:
   769 // Each group of 5 consecutive rows represents sampling from a single
   770 // SkScaledBitmapSampler::SrcConfig.
   771 // Within each set, each row represents a different destination SkBitmap::Config
   772 // Each column represents a different combination of dither and unpremul.
   773 // D = dither   ~D = no dither
   774 // U = unpremul ~U = no unpremul
   775 //  ~D~U                D~U                     ~DU                         DU
   776 SkScaledBitmapSampler::RowProc gTestProcs[] = {
   777     // Gray
   778     Sample_Gray_DA8,    Sample_Gray_DA8,        NULL,                       NULL,                       // to A8
   779     NULL,               NULL,                   NULL,                       NULL,                       // to Index8
   780     Sample_Gray_D565,   Sample_Gray_D565_D,     Sample_Gray_D565,           Sample_Gray_D565_D,         // to 565
   781     Sample_Gray_D4444,  Sample_Gray_D4444_D,    Sample_Gray_D4444,          Sample_Gray_D4444_D,        // to 4444
   782     Sample_Gray_D8888,  Sample_Gray_D8888,      Sample_Gray_D8888,          Sample_Gray_D8888,          // to 8888
   783     // Index
   784     NULL,               NULL,                   NULL,                       NULL,                       // to A8
   785     Sample_Index_DI,    Sample_Index_DI,        NULL,                       NULL,                       // to Index8
   786     Sample_Index_D565,  Sample_Index_D565_D,    Sample_Index_D565,          Sample_Index_D565_D,        // to 565
   787     Sample_Index_D4444, Sample_Index_D4444_D,   NULL,                       NULL,                       // to 4444
   788     Sample_Index_D8888, Sample_Index_D8888,     NULL,                       NULL,                       // to 8888
   789     // RGB
   790     NULL,               NULL,                   NULL,                       NULL,                       // to A8
   791     NULL,               NULL,                   NULL,                       NULL,                       // to Index8
   792     Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
   793     Sample_RGBx_D4444,  Sample_RGBx_D4444_D,    Sample_RGBx_D4444,          Sample_RGBx_D4444_D,        // to 4444
   794     Sample_RGBx_D8888,  Sample_RGBx_D8888,      Sample_RGBx_D8888,          Sample_RGBx_D8888,          // to 8888
   795     // RGBx is the same as RGB
   796     NULL,               NULL,                   NULL,                       NULL,                       // to A8
   797     NULL,               NULL,                   NULL,                       NULL,                       // to Index8
   798     Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
   799     Sample_RGBx_D4444,  Sample_RGBx_D4444_D,    Sample_RGBx_D4444,          Sample_RGBx_D4444_D,        // to 4444
   800     Sample_RGBx_D8888,  Sample_RGBx_D8888,      Sample_RGBx_D8888,          Sample_RGBx_D8888,          // to 8888
   801     // RGBA
   802     NULL,               NULL,                   NULL,                       NULL,                       // to A8
   803     NULL,               NULL,                   NULL,                       NULL,                       // to Index8
   804     Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
   805     Sample_RGBA_D4444,  Sample_RGBA_D4444_D,    NULL,                       NULL,                       // to 4444
   806     Sample_RGBA_D8888,  Sample_RGBA_D8888,      Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888
   807     // RGB_565
   808     NULL,               NULL,                   NULL,                       NULL,                       // to A8
   809     NULL,               NULL,                   NULL,                       NULL,                       // to Index8
   810     Sample_D565_D565,   Sample_D565_D565,       Sample_D565_D565,           Sample_D565_D565,           // to 565
   811     NULL,               NULL,                   NULL,                       NULL,                       // to 4444
   812     NULL,               NULL,                   NULL,                       NULL,                       // to 8888
   813 };
   815 // Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields.
   816 class DummyDecoder : public SkImageDecoder {
   817 public:
   818     DummyDecoder() {}
   819 protected:
   820     virtual bool onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) SK_OVERRIDE {
   821         return false;
   822     }
   823 };
   825 void test_row_proc_choice();
   826 void test_row_proc_choice() {
   827     SkBitmap dummyBitmap;
   828     DummyDecoder dummyDecoder;
   829     size_t procCounter = 0;
   830     for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
   831         for (int c = SkBitmap::kA8_Config; c <= SkBitmap::kARGB_8888_Config; ++c) {
   832             for (int unpremul = 0; unpremul <= 1; ++unpremul) {
   833                 for (int dither = 0; dither <= 1; ++dither) {
   834                     // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
   835                     // be considered valid.
   836                     SkScaledBitmapSampler sampler(10, 10, 1);
   837                     dummyBitmap.setConfig((SkBitmap::Config) c, 10, 10);
   838                     dummyDecoder.setDitherImage(SkToBool(dither));
   839                     dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
   840                     sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
   841                                   dummyDecoder);
   842                     SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter];
   843                     SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler);
   844                     SkASSERT(expected == actual);
   845                     procCounter++;
   846                 }
   847             }
   848         }
   849     }
   850     SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter);
   851 }
   852 #endif // SK_DEBUG

mercurial