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