SkImagePriv.cpp revision d28ba8010c6058bf073f7e815d5b2d7fdf698601
16997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com/*
26997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * Copyright 2012 Google Inc.
36997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com *
46997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * Use of this source code is governed by a BSD-style license that can be
56997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com * found in the LICENSE file.
66997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com */
76997ebbe5cf06c938cc893e1d0217dc4048edf82reed@google.com
8889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com#include "SkImagePriv.h"
970e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org#include "SkCanvas.h"
1070e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org#include "SkPicture.h"
11889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
12889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.comSkBitmap::Config SkImageInfoToBitmapConfig(const SkImage::Info& info,
13889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                                           bool* isOpaque) {
14889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    switch (info.fColorType) {
15889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkImage::kAlpha_8_ColorType:
16889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            switch (info.fAlphaType) {
17d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kIgnore_SkAlphaType:
18889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    // makes no sense
19889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kNo_Config;
20889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
21d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kOpaque_SkAlphaType:
22889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    *isOpaque = true;
23889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kA8_Config;
24889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
25d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kPremul_SkAlphaType:
26d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kUnpremul_SkAlphaType:
27889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    *isOpaque = false;
28889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kA8_Config;
29889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            }
30889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            break;
31889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
32889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkImage::kRGB_565_ColorType:
33889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            // we ignore fAlpahType, though some would not make sense
34889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            *isOpaque = true;
35889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            return SkBitmap::kRGB_565_Config;
36889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
37889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkImage::kPMColor_ColorType:
38889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            switch (info.fAlphaType) {
39d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kIgnore_SkAlphaType:
40d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kUnpremul_SkAlphaType:
41889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    // not supported yet
42889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kNo_Config;
43d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kOpaque_SkAlphaType:
44889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    *isOpaque = true;
45889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kARGB_8888_Config;
46d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                case kPremul_SkAlphaType:
47889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    *isOpaque = false;
48889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com                    return SkBitmap::kARGB_8888_Config;
49889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            }
50889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            break;
51d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com
52d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com        default:
53d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com            // break for unsupported colortypes
54d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com            break;
55889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    }
56889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return SkBitmap::kNo_Config;
57889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
58889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
59889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.comint SkImageBytesPerPixel(SkImage::ColorType ct) {
60889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    static const uint8_t gColorTypeBytesPerPixel[] = {
61889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        1,  // kAlpha_8_ColorType
62889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        2,  // kRGB_565_ColorType
63889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        4,  // kRGBA_8888_ColorType
64889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        4,  // kBGRA_8888_ColorType
65889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        4,  // kPMColor_ColorType
66889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    };
67889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
68889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    SkASSERT((size_t)ct < SK_ARRAY_COUNT(gColorTypeBytesPerPixel));
69889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return gColorTypeBytesPerPixel[ct];
70889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
71889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
72889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.combool SkBitmapToImageInfo(const SkBitmap& bm, SkImage::Info* info) {
73889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    switch (bm.config()) {
74889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkBitmap::kA8_Config:
75889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            info->fColorType = SkImage::kAlpha_8_ColorType;
76889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            break;
77889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
78889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkBitmap::kRGB_565_Config:
79889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            info->fColorType = SkImage::kRGB_565_ColorType;
80889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            break;
81fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
82889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        case SkBitmap::kARGB_8888_Config:
83889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            info->fColorType = SkImage::kPMColor_ColorType;
84889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            break;
85fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
86889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        default:
87889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com            return false;
88889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    }
89fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
90889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    info->fWidth = bm.width();
91889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    info->fHeight = bm.height();
92d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com    info->fAlphaType = bm.isOpaque() ? kOpaque_SkAlphaType :
93d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com                                       kPremul_SkAlphaType;
94889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return true;
95889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
96889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
9797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comSkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
98889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    SkImage::Info info;
99889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    if (!SkBitmapToImageInfo(bm, &info)) {
100889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        return NULL;
101889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    }
102889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
103889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    SkImage* image = NULL;
10497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (canSharePixelRef || bm.isImmutable()) {
105889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        image = SkNewImageFromPixelRef(info, bm.pixelRef(), bm.rowBytes());
106889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    } else {
107889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        bm.lockPixels();
10870e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org        if (bm.getPixels()) {
109b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org            image = SkImage::NewRasterCopy(info, bm.getPixels(), bm.rowBytes());
110889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        }
111889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com        bm.unlockPixels();
112889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    }
113889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com    return image;
114889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com}
115889b09edfeb5f461ca283dfd08ee6b23560a7859reed@google.com
11670e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.orgstatic bool needs_layer(const SkPaint& paint) {
11770e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    return  0xFF != paint.getAlpha() ||
11870e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    paint.getColorFilter() ||
11970e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    paint.getImageFilter() ||
12070e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode);
12170e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org}
12270e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org
12370e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.orgvoid SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
12470e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org                            SkScalar x, SkScalar y, const SkPaint* paint) {
12570e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    int saveCount = canvas->getSaveCount();
126fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12770e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    if (paint && needs_layer(*paint)) {
12870e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org        SkRect bounds;
12970e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org        bounds.set(x, y,
13070e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org                   x + SkIntToScalar(picture->width()),
13170e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org                   y + SkIntToScalar(picture->height()));
13270e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org        canvas->saveLayer(&bounds, paint);
1339ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com        canvas->translate(x, y);
13470e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    } else if (x || y) {
13570e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org        canvas->save();
1369ea5a3bc7361cb88d37280b5922fba9430fed328reed@google.com        canvas->translate(x, y);
13770e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    }
138fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13970e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    canvas->drawPicture(*picture);
14070e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org    canvas->restoreToCount(saveCount);
14170e359055240d0de93da4ba71bf5833164fb394cmike@reedtribe.org}
142dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
143dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.orgvoid SkImagePrivDrawPicture(SkCanvas* canvas, SkPicture* picture,
1447f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com                            const SkRect* src,  const SkRect& dst, const SkPaint* paint) {
1457f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com    int saveCount = canvas->getSaveCount();
146dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
147dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    SkMatrix matrix;
148dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    SkRect   tmpSrc;
149dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
150dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    if (NULL != src) {
151dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org        tmpSrc = *src;
152dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    } else {
153dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org        tmpSrc.set(0, 0,
154dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org                   SkIntToScalar(picture->width()),
155dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org                   SkIntToScalar(picture->height()));
156dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    }
157dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
158dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
159dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    if (paint && needs_layer(*paint)) {
160dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org        canvas->saveLayer(&dst, paint);
161dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    } else {
162dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org        canvas->save();
163dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    }
164dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    canvas->concat(matrix);
165dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    if (!paint || !needs_layer(*paint)) {
166dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org        canvas->clipRect(tmpSrc);
167dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    }
1687f1af501f206da48a7ff791af53432c9c1c89d08skia.committer@gmail.com
169dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    canvas->drawPicture(*picture);
170dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    canvas->restoreToCount(saveCount);
171dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org}
172