1557152d10b1fcac78e82e8db946e1c998879be60reed@google.com/*
2557152d10b1fcac78e82e8db946e1c998879be60reed@google.com * Copyright 2012 Google Inc.
3557152d10b1fcac78e82e8db946e1c998879be60reed@google.com *
4557152d10b1fcac78e82e8db946e1c998879be60reed@google.com * Use of this source code is governed by a BSD-style license that can be
5557152d10b1fcac78e82e8db946e1c998879be60reed@google.com * found in the LICENSE file.
6557152d10b1fcac78e82e8db946e1c998879be60reed@google.com */
7557152d10b1fcac78e82e8db946e1c998879be60reed@google.com
8248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com#include "SkImagePriv.h"
9843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org#include "SkCanvas.h"
10843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org#include "SkPicture.h"
11248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
12248ec25fa948c09fec34883bf673e56c2048bd3freed@google.comSkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info& info,
13248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                                           bool* isOpaque) {
14248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    switch (info.fColorType) {
15248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkImage::kAlpha_8_ColorType:
16248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            switch (info.fAlphaType) {
17248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kIgnore_AlphaType:
18248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    // makes no sense
19248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kNo_Config;
20248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
21248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kOpaque_AlphaType:
22248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    *isOpaque = true;
23248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kA8_Config;
24248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
25248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kPremul_AlphaType:
26248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kUnpremul_AlphaType:
27248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    *isOpaque = false;
28248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kA8_Config;
29248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            }
30248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            break;
31248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
32248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkImage::kRGB_565_ColorType:
33248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            // we ignore fAlpahType, though some would not make sense
34248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            *isOpaque = true;
35248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            return SkBitmap::kRGB_565_Config;
36248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
37248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkImage::kRGBA_8888_ColorType:
38248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkImage::kBGRA_8888_ColorType:
39248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            // not supported yet
40248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            return SkBitmap::kNo_Config;
41248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
42248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkImage::kPMColor_ColorType:
43248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            switch (info.fAlphaType) {
44248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kIgnore_AlphaType:
45248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kUnpremul_AlphaType:
46248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    // not supported yet
47248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kNo_Config;
48248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kOpaque_AlphaType:
49248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    *isOpaque = true;
50248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kARGB_8888_Config;
51248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                case SkImage::kPremul_AlphaType:
52248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    *isOpaque = false;
53248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                    return SkBitmap::kARGB_8888_Config;
54248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            }
55248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            break;
56248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    }
57248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    SkASSERT(!"how did we get here");
58248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    return SkBitmap::kNo_Config;
59248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com}
60248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
61248ec25fa948c09fec34883bf673e56c2048bd3freed@google.comint SkImageBytesPerPixel(SkImage::ColorType ct) {
62248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    static const uint8_t gColorTypeBytesPerPixel[] = {
63248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        1,  // kAlpha_8_ColorType
64248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        2,  // kRGB_565_ColorType
65248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        4,  // kRGBA_8888_ColorType
66248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        4,  // kBGRA_8888_ColorType
67248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        4,  // kPMColor_ColorType
68248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    };
69248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
70248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel));
71248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    return gColorTypeBytesPerPixel[ct];
72248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com}
73248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
74248ec25fa948c09fec34883bf673e56c2048bd3freed@google.combool SkBitmapToImageInfo(const SkBitmap& bm, SkImage::Info* info) {
75248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    switch (bm.config()) {
76248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkBitmap::kA8_Config:
77248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            info->fColorType = SkImage::kAlpha_8_ColorType;
78248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            break;
79248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
80248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkBitmap::kRGB_565_Config:
81248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            info->fColorType = SkImage::kRGB_565_ColorType;
82248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            break;
83935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
84248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        case SkBitmap::kARGB_8888_Config:
85248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            info->fColorType = SkImage::kPMColor_ColorType;
86248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            break;
87935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
88248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        default:
89248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com            return false;
90248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    }
91935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
92248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    info->fWidth = bm.width();
93248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    info->fHeight = bm.height();
94248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    info->fAlphaType = bm.isOpaque() ? SkImage::kOpaque_AlphaType :
95248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com                                       SkImage::kPremul_AlphaType;
96248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    return true;
97248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com}
98248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
992ffcbf828d03b8e32ffc93b1b0ee8a98faeaa51ereed@google.comSkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
100248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    SkImage::Info info;
101248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    if (!SkBitmapToImageInfo(bm, &info)) {
102248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        return NULL;
103248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    }
104248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
105248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    SkImage* image = NULL;
1062ffcbf828d03b8e32ffc93b1b0ee8a98faeaa51ereed@google.com    if (canSharePixelRef || bm.isImmutable()) {
107248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes());
108248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    } else {
109248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        bm.lockPixels();
110843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org        if (bm.getPixels()) {
111b42b493aef62c04c5cbdacdffe984bec5c76648cmike@reedtribe.org            image = SkImage::NewRasterCopy(info, bm.getPixels(), bm.rowBytes());
112248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        }
113248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com        bm.unlockPixels();
114248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    }
115248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com    return image;
116248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com}
117248ec25fa948c09fec34883bf673e56c2048bd3freed@google.com
118843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.orgstatic bool needs_layer(const SkPaint& paint) {
119843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    return  0xFF != paint.getAlpha() ||
120843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    paint.getColorFilter() ||
121843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    paint.getImageFilter() ||
122843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode);
123843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org}
124843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org
125843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.orgvoid SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
126843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org                            SkScalar x, SkScalar y, const SkPaint* paint) {
127843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    int saveCount = canvas->getSaveCount();
128935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
129843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    if (paint && needs_layer(*paint)) {
130843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org        SkRect bounds;
131843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org        bounds.set(x, y,
132843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org                   x + SkIntToScalar(picture->width()),
133843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org                   y + SkIntToScalar(picture->height()));
134843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org        canvas->saveLayer(&bounds, paint);
13521f61024c088345bbdf306c9dcfdcef7096752bereed@google.com        canvas->translate(x, y);
136843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    } else if (x || y) {
137843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org        canvas->save();
13821f61024c088345bbdf306c9dcfdcef7096752bereed@google.com        canvas->translate(x, y);
139843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    }
140935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
141843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    canvas->drawPicture(*picture);
142843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org    canvas->restoreToCount(saveCount);
143843d95b34a971e0cbaf3deb695fd5989e0c1dfdemike@reedtribe.org}
144b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org
145b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.orgvoid SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
146fb9ab0f1780a8cf15fc886fad439e95818d264d6skia.committer@gmail.com                            const SkRect* src,  const SkRect& dst, const SkPaint* paint) {
147fb9ab0f1780a8cf15fc886fad439e95818d264d6skia.committer@gmail.com    int saveCount = canvas->getSaveCount();
148b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org
149b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    SkMatrix matrix;
150b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    SkRect   tmpSrc;
151b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org
152b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    if (NULL != src) {
153b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org        tmpSrc = *src;
154b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    } else {
155b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org        tmpSrc.set(0, 0,
156b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org                   SkIntToScalar(picture->width()),
157b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org                   SkIntToScalar(picture->height()));
158b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    }
159b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org
160b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
161b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    if (paint && needs_layer(*paint)) {
162b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org        canvas->saveLayer(&dst, paint);
163b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    } else {
164b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org        canvas->save();
165b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    }
166b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    canvas->concat(matrix);
167b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    if (!paint || !needs_layer(*paint)) {
168b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org        canvas->clipRect(tmpSrc);
169b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    }
170fb9ab0f1780a8cf15fc886fad439e95818d264d6skia.committer@gmail.com
171b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    canvas->drawPicture(*picture);
172b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org    canvas->restoreToCount(saveCount);
173b71e1b41724c00f4b4b52b371e4254674fb4a027commit-bot@chromium.org}
174