1c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com/*
2c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Copyright 2012 Google Inc.
3c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com *
4c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Use of this source code is governed by a BSD-style license that can be
5c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * found in the LICENSE file.
6c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com */
7c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
8c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkSurface_Base.h"
9c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkImagePriv.h"
10c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkCanvas.h"
1197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkDevice.h"
12c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkMallocPixelRef.h"
13c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
14c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comstatic const size_t kIgnoreRowBytesValue = (size_t)~0;
15c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
16c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comclass SkSurface_Raster : public SkSurface_Base {
17c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.compublic:
182bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com    static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
19c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
202bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com    SkSurface_Raster(const SkImageInfo&, void*, size_t rb);
211360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    SkSurface_Raster(SkPixelRef*);
22c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
23c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
242bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com    virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
255ee449af7448c202cfc6e9a359d8f996392885b2junov@chromium.org    virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
26c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
27c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com                        const SkPaint*) SK_OVERRIDE;
28c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org    virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
29c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
30c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comprivate:
31c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    SkBitmap    fBitmap;
32c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    bool        fWeOwnThePixels;
33c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
34c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    typedef SkSurface_Base INHERITED;
35c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com};
36c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
37c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com///////////////////////////////////////////////////////////////////////////////
38c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
392bd8b8100529c96c81c30f749f672f4caf775b04reed@google.combool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
40c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    static const size_t kMaxTotalSize = SK_MaxS32;
41c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
42c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    int shift = 0;
431360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    switch (info.fColorType) {
441360c52b10dad45d7a6850370eab40c6253d7988reed@google.com        case kAlpha_8_SkColorType:
45c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            shift = 0;
46c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            break;
471360c52b10dad45d7a6850370eab40c6253d7988reed@google.com        case kRGB_565_SkColorType:
48c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            shift = 1;
49c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            break;
5028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
51c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            shift = 2;
52c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            break;
53c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        default:
54c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com            return false;
55c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
56c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
57c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    if (kIgnoreRowBytesValue == rowBytes) {
58c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return true;
59c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
60c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
61c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    uint64_t minRB = (uint64_t)info.fWidth << shift;
62c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    if (minRB > rowBytes) {
63c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return false;
64c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
65c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
66c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    size_t alignedRowBytes = rowBytes >> shift << shift;
67c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    if (alignedRowBytes != rowBytes) {
68c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return false;
69c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
70c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
711360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    uint64_t size = sk_64_mul(info.fHeight, rowBytes);
72c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    if (size > kMaxTotalSize) {
73c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return false;
74c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
75fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
76c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    return true;
77c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
78c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
792bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
801360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    : INHERITED(info)
811360c52b10dad45d7a6850370eab40c6253d7988reed@google.com{
82a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    fBitmap.installPixels(info, pixels, rb);
8397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    fWeOwnThePixels = false;    // We are "Direct"
84c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
85c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
861360c52b10dad45d7a6850370eab40c6253d7988reed@google.comSkSurface_Raster::SkSurface_Raster(SkPixelRef* pr)
87e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    : INHERITED(pr->info().fWidth, pr->info().fHeight)
881360c52b10dad45d7a6850370eab40c6253d7988reed@google.com{
89e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    const SkImageInfo& info = pr->info();
90e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org
91a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    fBitmap.setInfo(info, info.minRowBytes());
92e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    fBitmap.setPixelRef(pr);
93c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    fWeOwnThePixels = true;
94c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
95e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    if (!info.isOpaque()) {
96dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com        fBitmap.eraseColor(SK_ColorTRANSPARENT);
97c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
98c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
99c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
100c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comSkCanvas* SkSurface_Raster::onNewCanvas() {
101c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    return SkNEW_ARGS(SkCanvas, (fBitmap));
102c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
103c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
1042bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
105b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    return SkSurface::NewRaster(info);
106c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
107c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
108c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comvoid SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
109c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com                              const SkPaint* paint) {
110c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    canvas->drawBitmap(fBitmap, x, y, paint);
111c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
112c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
1135ee449af7448c202cfc6e9a359d8f996392885b2junov@chromium.orgSkImage* SkSurface_Raster::onNewImageSnapshot() {
11497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
11597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
11697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
117c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
11897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    // are we sharing pixelrefs with the image?
119c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org    SkASSERT(NULL != this->getCachedImage());
120acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org    if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
12197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        SkASSERT(fWeOwnThePixels);
122c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        if (kDiscard_ContentChangeMode == mode) {
123672588b684d484dce6ae251e9e163e4a46924322reed@google.com            fBitmap.setPixelRef(NULL);
124c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org            fBitmap.allocPixels();
125c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        } else {
126c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org            SkBitmap prev(fBitmap);
1276285f4f7662853336b788d6ee3e177c396f7fb01commit-bot@chromium.org            prev.deepCopyTo(&fBitmap);
128c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org        }
12997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // Now fBitmap is a deep copy of itself (and therefore different from
13097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // what is being used by the image. Next we update the canvas to use
13197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com        // this as its backend, so we can't modify the image's pixels anymore.
132acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org        SkASSERT(NULL != this->getCachedCanvas());
133acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org        this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
13497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
13597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
13697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
137c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com///////////////////////////////////////////////////////////////////////////////
138c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
1392bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
140b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    if (!SkSurface_Raster::Valid(info, rowBytes)) {
141c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return NULL;
142c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
143c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    if (NULL == pixels) {
144c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return NULL;
145c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
147b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
148c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
149c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com
1502bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
151b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    if (!SkSurface_Raster::Valid(info)) {
152c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return NULL;
153c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
154fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
155bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
156bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com    if (NULL == pr.get()) {
157c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com        return NULL;
158c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com    }
1591360c52b10dad45d7a6850370eab40c6253d7988reed@google.com    return SkNEW_ARGS(SkSurface_Raster, (pr));
160c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}
161