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