SkDevice.cpp revision f67e4cf4c18cd228738a11372859ee0280bce1d7
1#include "SkDevice.h"
2#include "SkDraw.h"
3#include "SkRect.h"
4
5SkDeviceFactory::~SkDeviceFactory() {}
6
7SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) {
8    fOrigin.setZero();
9}
10
11SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
12        : fCanvas(canvas), fBitmap(bitmap) {
13    fOrigin.setZero();
14    // auto-allocate if we're for offscreen drawing
15    if (isForLayer) {
16        if (NULL == fBitmap.getPixels() && NULL == fBitmap.pixelRef()) {
17            fBitmap.allocPixels();
18            if (!fBitmap.isOpaque()) {
19                fBitmap.eraseColor(0);
20            }
21        }
22    }
23}
24
25void SkDevice::lockPixels() {
26    fBitmap.lockPixels();
27}
28
29void SkDevice::unlockPixels() {
30    fBitmap.unlockPixels();
31}
32
33const SkBitmap& SkDevice::accessBitmap(bool changePixels) {
34    this->onAccessBitmap(&fBitmap);
35    if (changePixels) {
36        fBitmap.notifyPixelsChanged();
37    }
38    return fBitmap;
39}
40
41void SkDevice::getBounds(SkIRect* bounds) const {
42    if (bounds) {
43        bounds->set(0, 0, fBitmap.width(), fBitmap.height());
44    }
45}
46
47bool SkDevice::intersects(const SkIRect& r, SkIRect* sect) const {
48    SkIRect bounds;
49
50    this->getBounds(&bounds);
51    return sect ? sect->intersect(r, bounds) : SkIRect::Intersects(r, bounds);
52}
53
54void SkDevice::eraseColor(SkColor eraseColor) {
55    fBitmap.eraseColor(eraseColor);
56}
57
58void SkDevice::onAccessBitmap(SkBitmap* bitmap) {}
59
60void SkDevice::setMatrixClip(const SkMatrix&, const SkRegion&,
61                             const SkClipStack&) {}
62
63///////////////////////////////////////////////////////////////////////////////
64
65bool SkDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
66    const SkBitmap& src = this->accessBitmap(false);
67
68    SkIRect bounds;
69    bounds.set(0, 0, src.width(), src.height());
70    if (!bounds.intersect(srcRect)) {
71        return false;
72    }
73
74    SkBitmap subset;
75    if (!src.extractSubset(&subset, bounds)) {
76        return false;
77    }
78
79    SkBitmap tmp;
80    if (!subset.copyTo(&tmp, SkBitmap::kARGB_8888_Config)) {
81        return false;
82    }
83
84    tmp.swap(*bitmap);
85    return true;
86}
87
88void SkDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
89    SkPaint paint;
90    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
91
92    SkCanvas canvas(this);
93    canvas.drawSprite(bitmap, x, y, &paint);
94}
95
96///////////////////////////////////////////////////////////////////////////////
97
98void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
99    draw.drawPaint(paint);
100}
101
102void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
103                              const SkPoint pts[], const SkPaint& paint) {
104    draw.drawPoints(mode, count, pts, paint);
105}
106
107void SkDevice::drawRect(const SkDraw& draw, const SkRect& r,
108                            const SkPaint& paint) {
109    draw.drawRect(r, paint);
110}
111
112void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
113                        const SkPaint& paint, const SkMatrix* prePathMatrix,
114                        bool pathIsMutable) {
115    draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
116}
117
118void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
119                          const SkIRect* srcRect,
120                          const SkMatrix& matrix, const SkPaint& paint) {
121    SkBitmap        tmp;    // storage if we need a subset of bitmap
122    const SkBitmap* bitmapPtr = &bitmap;
123
124    if (srcRect) {
125        if (!bitmap.extractSubset(&tmp, *srcRect)) {
126            return;     // extraction failed
127        }
128        bitmapPtr = &tmp;
129    }
130    draw.drawBitmap(*bitmapPtr, matrix, paint);
131}
132
133void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
134                              int x, int y, const SkPaint& paint) {
135    draw.drawSprite(bitmap, x, y, paint);
136}
137
138void SkDevice::drawText(const SkDraw& draw, const void* text, size_t len,
139                            SkScalar x, SkScalar y, const SkPaint& paint) {
140    draw.drawText((const char*)text, len, x, y, paint);
141}
142
143void SkDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
144                               const SkScalar xpos[], SkScalar y,
145                               int scalarsPerPos, const SkPaint& paint) {
146    draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
147}
148
149void SkDevice::drawTextOnPath(const SkDraw& draw, const void* text,
150                                  size_t len, const SkPath& path,
151                                  const SkMatrix* matrix,
152                                  const SkPaint& paint) {
153    draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
154}
155
156#ifdef ANDROID
157void SkDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
158                                     const SkPoint pos[], const SkPaint& paint,
159                                     const SkPath& path, const SkMatrix* matrix) {
160    draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
161}
162#endif
163
164void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
165                                int vertexCount,
166                                const SkPoint verts[], const SkPoint textures[],
167                                const SkColor colors[], SkXfermode* xmode,
168                                const uint16_t indices[], int indexCount,
169                                const SkPaint& paint) {
170    draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
171                      indices, indexCount, paint);
172}
173
174void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
175                              int x, int y, const SkPaint& paint) {
176    draw.drawSprite(device->accessBitmap(false), x, y, paint);
177}
178
179///////////////////////////////////////////////////////////////////////////////
180
181bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
182    if (!paint.isLCDRenderText()) {
183        // we're cool with the paint as is
184        return false;
185    }
186
187    if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
188        paint.getShader() ||
189        paint.getXfermode() || // unless its srcover
190        paint.getMaskFilter() ||
191        paint.getRasterizer() ||
192        paint.getColorFilter() ||
193        paint.getPathEffect() ||
194        paint.isFakeBoldText() ||
195        paint.getStyle() != SkPaint::kFill_Style) {
196        // turn off lcd
197        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
198        flags->fHinting = paint.getHinting();
199        return true;
200    }
201    // we're cool with the paint as is
202    return false;
203}
204
205///////////////////////////////////////////////////////////////////////////////
206
207SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
208                                           SkBitmap::Config config, int width,
209                                           int height, bool isOpaque,
210                                           bool isForLayer) {
211    SkBitmap bitmap;
212    bitmap.setConfig(config, width, height);
213    bitmap.setIsOpaque(isOpaque);
214
215    return SkNEW_ARGS(SkDevice, (canvas, bitmap, isForLayer));
216}
217