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