Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkImagePriv.h"
      9 #include "SkCanvas.h"
     10 #include "SkPicture.h"
     11 
     12 SkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info& info,
     13                                            bool* isOpaque) {
     14     switch (info.fColorType) {
     15         case SkImage::kAlpha_8_ColorType:
     16             switch (info.fAlphaType) {
     17                 case SkImage::kIgnore_AlphaType:
     18                     // makes no sense
     19                     return SkBitmap::kNo_Config;
     20 
     21                 case SkImage::kOpaque_AlphaType:
     22                     *isOpaque = true;
     23                     return SkBitmap::kA8_Config;
     24 
     25                 case SkImage::kPremul_AlphaType:
     26                 case SkImage::kUnpremul_AlphaType:
     27                     *isOpaque = false;
     28                     return SkBitmap::kA8_Config;
     29             }
     30             break;
     31 
     32         case SkImage::kRGB_565_ColorType:
     33             // we ignore fAlpahType, though some would not make sense
     34             *isOpaque = true;
     35             return SkBitmap::kRGB_565_Config;
     36 
     37         case SkImage::kRGBA_8888_ColorType:
     38         case SkImage::kBGRA_8888_ColorType:
     39             // not supported yet
     40             return SkBitmap::kNo_Config;
     41 
     42         case SkImage::kPMColor_ColorType:
     43             switch (info.fAlphaType) {
     44                 case SkImage::kIgnore_AlphaType:
     45                 case SkImage::kUnpremul_AlphaType:
     46                     // not supported yet
     47                     return SkBitmap::kNo_Config;
     48                 case SkImage::kOpaque_AlphaType:
     49                     *isOpaque = true;
     50                     return SkBitmap::kARGB_8888_Config;
     51                 case SkImage::kPremul_AlphaType:
     52                     *isOpaque = false;
     53                     return SkBitmap::kARGB_8888_Config;
     54             }
     55             break;
     56     }
     57     SkASSERT(!"how did we get here");
     58     return SkBitmap::kNo_Config;
     59 }
     60 
     61 int SkImageBytesPerPixel(SkImage::ColorType ct) {
     62     static const uint8_t gColorTypeBytesPerPixel[] = {
     63         1,  // kAlpha_8_ColorType
     64         2,  // kRGB_565_ColorType
     65         4,  // kRGBA_8888_ColorType
     66         4,  // kBGRA_8888_ColorType
     67         4,  // kPMColor_ColorType
     68     };
     69 
     70     SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel));
     71     return gColorTypeBytesPerPixel[ct];
     72 }
     73 
     74 bool SkBitmapToImageInfo(const SkBitmap& bm, SkImage::Info* info) {
     75     switch (bm.config()) {
     76         case SkBitmap::kA8_Config:
     77             info->fColorType = SkImage::kAlpha_8_ColorType;
     78             break;
     79 
     80         case SkBitmap::kRGB_565_Config:
     81             info->fColorType = SkImage::kRGB_565_ColorType;
     82             break;
     83 
     84         case SkBitmap::kARGB_8888_Config:
     85             info->fColorType = SkImage::kPMColor_ColorType;
     86             break;
     87 
     88         default:
     89             return false;
     90     }
     91 
     92     info->fWidth = bm.width();
     93     info->fHeight = bm.height();
     94     info->fAlphaType = bm.isOpaque() ? SkImage::kOpaque_AlphaType :
     95                                        SkImage::kPremul_AlphaType;
     96     return true;
     97 }
     98 
     99 SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
    100     SkImage::Info info;
    101     if (!SkBitmapToImageInfo(bm, &info)) {
    102         return NULL;
    103     }
    104 
    105     SkImage* image = NULL;
    106     if (canSharePixelRef || bm.isImmutable()) {
    107         image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes());
    108     } else {
    109         bm.lockPixels();
    110         if (bm.getPixels()) {
    111             image = SkImage::NewRasterCopy(info, bm.getPixels(), bm.rowBytes());
    112         }
    113         bm.unlockPixels();
    114     }
    115     return image;
    116 }
    117 
    118 static bool needs_layer(const SkPaint& paint) {
    119     return  0xFF != paint.getAlpha() ||
    120     paint.getColorFilter() ||
    121     paint.getImageFilter() ||
    122     SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode);
    123 }
    124 
    125 void SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
    126                             SkScalar x, SkScalar y, const SkPaint* paint) {
    127     int saveCount = canvas->getSaveCount();
    128 
    129     if (paint && needs_layer(*paint)) {
    130         SkRect bounds;
    131         bounds.set(x, y,
    132                    x + SkIntToScalar(picture->width()),
    133                    y + SkIntToScalar(picture->height()));
    134         canvas->saveLayer(&bounds, paint);
    135         canvas->translate(x, y);
    136     } else if (x || y) {
    137         canvas->save();
    138         canvas->translate(x, y);
    139     }
    140 
    141     canvas->drawPicture(*picture);
    142     canvas->restoreToCount(saveCount);
    143 }
    144 
    145 void SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
    146                             const SkRect* src,  const SkRect& dst, const SkPaint* paint) {
    147     int saveCount = canvas->getSaveCount();
    148 
    149     SkMatrix matrix;
    150     SkRect   tmpSrc;
    151 
    152     if (NULL != src) {
    153         tmpSrc = *src;
    154     } else {
    155         tmpSrc.set(0, 0,
    156                    SkIntToScalar(picture->width()),
    157                    SkIntToScalar(picture->height()));
    158     }
    159 
    160     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
    161     if (paint && needs_layer(*paint)) {
    162         canvas->saveLayer(&dst, paint);
    163     } else {
    164         canvas->save();
    165     }
    166     canvas->concat(matrix);
    167     if (!paint || !needs_layer(*paint)) {
    168         canvas->clipRect(tmpSrc);
    169     }
    170 
    171     canvas->drawPicture(*picture);
    172     canvas->restoreToCount(saveCount);
    173 }
    174