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