SkImage.cpp revision 8572fc01ac4f6bdcf173b05417776abc55f729c1
155d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak/*
255d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak * Copyright 2012 Google Inc.
355d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak *
455d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak * Use of this source code is governed by a BSD-style license that can be
555d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak * found in the LICENSE file.
655d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak */
755d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak
855d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak#include "SkBitmap.h"
955d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak#include "SkCanvas.h"
1055d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak#include "SkImagePriv.h"
1155d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak#include "SkImage_Base.h"
1255d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak
1355d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modakstatic SkImage_Base* as_IB(SkImage* image) {
1455d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak    return static_cast<SkImage_Base*>(image);
1555d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak}
1655d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak
1755d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modakstatic const SkImage_Base* as_IB(const SkImage* image) {
1855d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak    return static_cast<const SkImage_Base*>(image);
1955d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak}
2055d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak
2155d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modakuint32_t SkImage::NextUniqueID() {
2255d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak    static int32_t gUniqueID;
2355d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak
2455d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak    // never return 0;
2555d04e4a11434fcdb0435b7fd0f8b1daf38bf3c4subrata_modak    uint32_t id;
26    do {
27        id = sk_atomic_inc(&gUniqueID) + 1;
28    } while (0 == id);
29    return id;
30}
31
32void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
33    as_IB(this)->onDraw(canvas, x, y, paint);
34}
35
36void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
37                   const SkPaint* paint) const {
38    as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
39}
40
41const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
42    SkImageInfo infoStorage;
43    size_t rowBytesStorage;
44    if (NULL == info) {
45        info = &infoStorage;
46    }
47    if (NULL == rowBytes) {
48        rowBytes = &rowBytesStorage;
49    }
50    return as_IB(this)->onPeekPixels(info, rowBytes);
51}
52
53bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
54    if (NULL == bitmap) {
55        return false;
56    }
57
58    SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
59
60    // trim against the bitmap, if its already been allocated
61    if (bitmap->pixelRef()) {
62        bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
63        bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
64        if (bounds.isEmpty()) {
65            return false;
66        }
67    }
68
69    if (subset && !bounds.intersect(*subset)) {
70        // perhaps we could return true + empty-bitmap?
71        return false;
72    }
73    return as_IB(this)->onReadPixels(bitmap, bounds);
74}
75
76GrTexture* SkImage::getTexture() {
77    return as_IB(this)->onGetTexture();
78}
79
80SkShader* SkImage::newShader(SkShader::TileMode tileX,
81                             SkShader::TileMode tileY,
82                             const SkMatrix* localMatrix) const {
83    return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
84}
85
86SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
87    SkBitmap bm;
88    if (as_IB(this)->getROPixels(&bm)) {
89        return SkImageEncoder::EncodeData(bm, type, quality);
90    }
91    return NULL;
92}
93
94///////////////////////////////////////////////////////////////////////////////
95
96static bool raster_canvas_supports(const SkImageInfo& info) {
97    switch (info.fColorType) {
98        case kN32_SkColorType:
99            return kUnpremul_SkAlphaType != info.fAlphaType;
100        case kRGB_565_SkColorType:
101            return true;
102        case kAlpha_8_SkColorType:
103            return true;
104        default:
105            break;
106    }
107    return false;
108}
109
110bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
111    if (bitmap->pixelRef()) {
112        const SkImageInfo info = bitmap->info();
113        if (kUnknown_SkColorType == info.colorType()) {
114            return false;
115        }
116        if (!raster_canvas_supports(info)) {
117            return false;
118        }
119    } else {
120        const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
121        SkBitmap tmp;
122        if (!tmp.allocPixels(info)) {
123            return false;
124        }
125        *bitmap = tmp;
126    }
127
128    SkRect srcR, dstR;
129    srcR.set(subset);
130    dstR = srcR;
131    dstR.offset(-dstR.left(), -dstR.top());
132
133    SkCanvas canvas(*bitmap);
134
135    SkPaint paint;
136    paint.setXfermodeMode(SkXfermode::kClear_Mode);
137    canvas.drawRect(dstR, paint);
138
139    const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
140    return true;
141}
142