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