158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com/*
258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * Copyright 2012 Google Inc.
358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com *
458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * Use of this source code is governed by a BSD-style license that can be
558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * found in the LICENSE file.
658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com */
758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkImage_Base.h"
958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkImagePriv.h"
1058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkBitmap.h"
1158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkCanvas.h"
1258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkData.h"
131bed687f6b8fc67336f0f5d6fb5a5b38dd0fdff9halcanary@google.com#include "SkMallocPixelRef.h"
1458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
1558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comclass SkImage_Raster : public SkImage_Base {
1658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.compublic:
17b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    static bool ValidArgs(const Info& info, size_t rowBytes) {
1858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        const int maxDimension = SK_MaxS32 >> 2;
1958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        const size_t kMaxPixelByteSize = SK_MaxS32;
2058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
2158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        if (info.fWidth < 0 || info.fHeight < 0) {
2258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
2358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
2458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        if (info.fWidth > maxDimension || info.fHeight > maxDimension) {
2558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
2658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
272bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com        if ((unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType) {
2858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
2958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
30d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com        if ((unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType) {
3158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
3258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
3358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
34a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        if (kUnknown_SkColorType == info.colorType()) {
3558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
3658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
37fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        // TODO: check colorspace
39fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        if (rowBytes < SkImageMinRowBytes(info)) {
4158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
4258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        int64_t size = (int64_t)info.fHeight * rowBytes;
45d9e0181405c9853ffd20502555200205a5ab09b1bsalomon@google.com        if (size > (int64_t)kMaxPixelByteSize) {
4658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com            return false;
4758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        }
4858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return true;
4958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
5058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
5158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    static SkImage* NewEmpty();
5258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
532bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com    SkImage_Raster(const SkImageInfo&, SkData*, size_t rb);
5458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    virtual ~SkImage_Raster();
5558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
5658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
57dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE;
584f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE;
594f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE;
604b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com    virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
6158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
6258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // exposed for SkSurface_Raster via SkNewImageFromPixelRef
63e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes);
6458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
6597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
6697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
6758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comprivate:
6858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    SkImage_Raster() : INHERITED(0, 0) {}
6958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
7058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    SkBitmap    fBitmap;
7158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
7258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    typedef SkImage_Base INHERITED;
7358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com};
7458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
7558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com///////////////////////////////////////////////////////////////////////////////
7658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
7758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comSkImage* SkImage_Raster::NewEmpty() {
7858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // Returns lazily created singleton
7958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    static SkImage* gEmpty;
8058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    if (NULL == gEmpty) {
8158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        gEmpty = SkNEW(SkImage_Raster);
8258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
8358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    gEmpty->ref();
8458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    return gEmpty;
8558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
8658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
874f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comstatic void release_data(void* addr, void* context) {
884f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    SkData* data = static_cast<SkData*>(context);
894f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    data->unref();
904f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
914f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
92b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.orgSkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes)
934f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    : INHERITED(info.fWidth, info.fHeight)
944f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com{
954f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    data->ref();
964f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    void* addr = const_cast<void*>(data->data());
9700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    SkColorTable* ctable = NULL;
984f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
9900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
10058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    fBitmap.setImmutable();
1014f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    fBitmap.lockPixels();
10258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
10358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
104e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.orgSkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes)
105e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    : INHERITED(info.fWidth, info.fHeight)
106f1901788d8753332c5748a30e8d14e290c155bd1commit-bot@chromium.org{
107a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org    fBitmap.setInfo(info, rowBytes);
108e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    fBitmap.setPixelRef(pr);
1094f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    fBitmap.lockPixels();
11058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
11158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
11258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comSkImage_Raster::~SkImage_Raster() {}
11358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
11458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comvoid SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) {
11558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    canvas->drawBitmap(fBitmap, x, y, paint);
11658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
11758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
1184f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comvoid SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src,
1194f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com                                      const SkRect& dst, const SkPaint* paint) {
120dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org    canvas->drawBitmapRectToRect(fBitmap, src, dst, paint);
121dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org}
122dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org
1234f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.combool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const {
1244f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    if (dst->pixelRef()) {
1254f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        return this->INHERITED::onReadPixels(dst, subset);
1264f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    } else {
1274f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        SkBitmap src;
1284f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        if (!fBitmap.extractSubset(&src, subset)) {
1294f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com            return false;
1304f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com        }
1318a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org        return src.copyTo(dst, src.colorType());
1324f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
1334f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
1344f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1354f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comconst void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr,
1364f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com                                         size_t* rowBytesPtr) const {
137466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    const SkImageInfo info = fBitmap.info();
138466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org    if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) {
1392776e01d2c8ae6a23718cd4f4d9a4bf368a8e46breed@google.com        return NULL;
1404f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    }
1414f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    *infoPtr = info;
1424f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    *rowBytesPtr = fBitmap.rowBytes();
1434f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com    return fBitmap.getPixels();
1444f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com}
1454f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com
1464b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.combool SkImage_Raster::getROPixels(SkBitmap* dst) const {
1474b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com    *dst = fBitmap;
1484b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com    return true;
1494b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com}
1504b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com
15158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com///////////////////////////////////////////////////////////////////////////////
15258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
1532bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) {
154b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
15558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return NULL;
15658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
15758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    if (0 == info.fWidth && 0 == info.fHeight) {
15858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return SkImage_Raster::NewEmpty();
15958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
16058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // check this after empty-check
16158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    if (NULL == pixels) {
16258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return NULL;
16358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // Here we actually make a copy of the caller's pixel data
16658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes));
167b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
16858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
16958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
17058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
171999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.comSkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) {
172b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    if (!SkImage_Raster::ValidArgs(info, rowBytes)) {
17358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return NULL;
17458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
17558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    if (0 == info.fWidth && 0 == info.fHeight) {
17658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return SkImage_Raster::NewEmpty();
17758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
17858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // check this after empty-check
179999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.com    if (NULL == data) {
18058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return NULL;
18158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
18358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    // did they give us enough data?
18458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    size_t size = info.fHeight * rowBytes;
185999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.com    if (data->size() < size) {
18658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com        return NULL;
18758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com    }
188fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
189b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org    return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes));
19058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
19158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
192e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.orgSkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr,
193e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org                                size_t rowBytes) {
194e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org    return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes));
19558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}
19658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com
19797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comSkPixelRef* SkBitmapImageGetPixelRef(SkImage* image) {
19897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    return ((SkImage_Raster*)image)->getPixelRef();
19997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
200