Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: src/core/SkBitmapDevice.cpp

Issue 23553006: Move SkBitmapDevice functions to their own file (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Add SkBitmapDevice.cpp to CL Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkDevice.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkBitmapDevice.h"
9 #include "SkConfig8888.h"
10 #include "SkDraw.h"
11 #include "SkRasterClip.h"
12 #include "SkShader.h"
13
14 SK_DEFINE_INST_COUNT(SkBitmapDevice)
15
16 #define CHECK_FOR_NODRAW_ANNOTATION(paint) \
17 do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
18
19 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
20 : fBitmap(bitmap) {
21 SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
22 }
23
24 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
25 : SkBaseDevice(deviceProperties)
26 , fBitmap(bitmap) {
27 }
28
29 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, b ool isOpaque) {
30 fBitmap.setConfig(config, width, height);
31 fBitmap.allocPixels();
32 fBitmap.setIsOpaque(isOpaque);
33 if (!isOpaque) {
34 fBitmap.eraseColor(SK_ColorTRANSPARENT);
35 }
36 }
37
38 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, b ool isOpaque,
39 const SkDeviceProperties& deviceProperties)
40 : SkBaseDevice(deviceProperties) {
41
42 fBitmap.setConfig(config, width, height);
43 fBitmap.allocPixels();
44 fBitmap.setIsOpaque(isOpaque);
45 if (!isOpaque) {
46 fBitmap.eraseColor(SK_ColorTRANSPARENT);
47 }
48 }
49
50 SkBitmapDevice::~SkBitmapDevice() {
51 }
52
53 void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
54 SkASSERT(bm.width() == fBitmap.width());
55 SkASSERT(bm.height() == fBitmap.height());
56 fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
57 fBitmap.lockPixels();
58 }
59
60 SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
61 int width, int height,
62 bool isOpaque,
63 Usage usage) {
64 return SkNEW_ARGS(SkBitmapDevice,(config, width, height, isOpaque,
65 this->getDeviceProperties()));
66 }
67
68 void SkBitmapDevice::lockPixels() {
69 if (fBitmap.lockPixelsAreWritable()) {
70 fBitmap.lockPixels();
71 }
72 }
73
74 void SkBitmapDevice::unlockPixels() {
75 if (fBitmap.lockPixelsAreWritable()) {
76 fBitmap.unlockPixels();
77 }
78 }
79
80 void SkBitmapDevice::getGlobalBounds(SkIRect* bounds) const {
81 if (NULL != bounds) {
82 const SkIPoint& origin = this->getOrigin();
83 bounds->setXYWH(origin.x(), origin.y(),
84 fBitmap.width(), fBitmap.height());
85 }
86 }
87
88 void SkBitmapDevice::clear(SkColor color) {
89 fBitmap.eraseColor(color);
90 }
91
92 const SkBitmap& SkBitmapDevice::onAccessBitmap() {
93 return fBitmap;
94 }
95
96 bool SkBitmapDevice::canHandleImageFilter(SkImageFilter*) {
97 return false;
98 }
99
100 bool SkBitmapDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
101 const SkMatrix& ctm, SkBitmap* result,
102 SkIPoint* offset) {
103 return false;
104 }
105
106 bool SkBitmapDevice::allowImageFilter(SkImageFilter*) {
107 return true;
108 }
109
110 bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
111 int x, int y,
112 SkCanvas::Config8888 config8888) {
113 SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
114 SkASSERT(!bitmap.isNull());
115 SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::Ma keXYWH(x, y,
116 bitmap .width(),
117 bitmap .height())));
118
119 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
120 const SkBitmap& src = this->accessBitmap(false);
121
122 SkBitmap subset;
123 if (!src.extractSubset(&subset, srcRect)) {
124 return false;
125 }
126 if (SkBitmap::kARGB_8888_Config != subset.config()) {
127 // It'd be preferable to do this directly to bitmap.
128 subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
129 }
130 SkAutoLockPixels alp(bitmap);
131 uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
132 SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
133 return true;
134 }
135
136 void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
137 int x, int y,
138 SkCanvas::Config8888 config8888) {
139 if (bitmap.isNull() || bitmap.getTexture()) {
140 return;
141 }
142 const SkBitmap* sprite = &bitmap;
143 // check whether we have to handle a config8888 that doesn't match SkPMColor
144 if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
145 SkCanvas::kNative_Premul_Config8888 != config8888 &&
146 kPMColorAlias != config8888) {
147
148 // We're going to have to convert from a config8888 to the native config
149 // First we clip to the device bounds.
150 SkBitmap dstBmp = this->accessBitmap(true);
151 SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
152 bitmap.width(), bitmap.height());
153 SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
154 if (!spriteRect.intersect(devRect)) {
155 return;
156 }
157
158 // write directly to the device if it has pixels and is SkPMColor
159 bool drawSprite;
160 if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
161 // we can write directly to the dst when doing the conversion
162 dstBmp.extractSubset(&dstBmp, spriteRect);
163 drawSprite = false;
164 } else {
165 // we convert to a temporary bitmap and draw that as a sprite
166 dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
167 spriteRect.width(),
168 spriteRect.height());
169 if (!dstBmp.allocPixels()) {
170 return;
171 }
172 drawSprite = true;
173 }
174
175 // copy pixels to dstBmp and convert from config8888 to native config.
176 SkAutoLockPixels alp(bitmap);
177 uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
178 spriteRect.fTop - y);
179 SkCopyConfig8888ToBitmap(dstBmp,
180 srcPixels,
181 bitmap.rowBytes(),
182 config8888);
183
184 if (drawSprite) {
185 // we've clipped the sprite when we made a copy
186 x = spriteRect.fLeft;
187 y = spriteRect.fTop;
188 sprite = &dstBmp;
189 } else {
190 return;
191 }
192 }
193
194 SkPaint paint;
195 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
196 SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
197 SkDraw draw;
198 draw.fRC = &clip;
199 draw.fClip = &clip.bwRgn();
200 draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
201 draw.fMatrix = &SkMatrix::I();
202 this->drawSprite(draw, *sprite, x, y, paint);
203 }
204
205 ///////////////////////////////////////////////////////////////////////////////
206
207 void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
208 draw.drawPaint(paint);
209 }
210
211 void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, si ze_t count,
212 const SkPoint pts[], const SkPaint& paint) {
213 CHECK_FOR_NODRAW_ANNOTATION(paint);
214 draw.drawPoints(mode, count, pts, paint);
215 }
216
217 void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint & paint) {
218 CHECK_FOR_NODRAW_ANNOTATION(paint);
219 draw.drawRect(r, paint);
220 }
221
222 void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPa int& paint) {
223 CHECK_FOR_NODRAW_ANNOTATION(paint);
224
225 SkPath path;
226 path.addOval(oval);
227 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
228 // required to override drawOval.
229 this->drawPath(draw, path, paint, NULL, true);
230 }
231
232 void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const S kPaint& paint) {
233 CHECK_FOR_NODRAW_ANNOTATION(paint);
234
235 SkPath path;
236 path.addRRect(rrect);
237 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
238 // required to override drawRRect.
239 this->drawPath(draw, path, paint, NULL, true);
240 }
241
242 void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
243 const SkPaint& paint, const SkMatrix* prePathMatri x,
244 bool pathIsMutable) {
245 CHECK_FOR_NODRAW_ANNOTATION(paint);
246 draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
247 }
248
249 void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
250 const SkMatrix& matrix, const SkPaint& paint) {
251 draw.drawBitmap(bitmap, matrix, paint);
252 }
253
254 void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
255 const SkRect* src, const SkRect& dst,
256 const SkPaint& paint,
257 SkCanvas::DrawBitmapRectFlags flags) {
258 SkMatrix matrix;
259 SkRect bitmapBounds, tmpSrc, tmpDst;
260 SkBitmap tmpBitmap;
261
262 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
263
264 // Compute matrix from the two rectangles
265 if (src) {
266 tmpSrc = *src;
267 } else {
268 tmpSrc = bitmapBounds;
269 }
270 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
271
272 const SkRect* dstPtr = &dst;
273 const SkBitmap* bitmapPtr = &bitmap;
274
275 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
276 // needed (if the src was clipped). No check needed if src==null.
277 if (src) {
278 if (!bitmapBounds.contains(*src)) {
279 if (!tmpSrc.intersect(bitmapBounds)) {
280 return; // nothing to draw
281 }
282 // recompute dst, based on the smaller tmpSrc
283 matrix.mapRect(&tmpDst, tmpSrc);
284 dstPtr = &tmpDst;
285 }
286
287 // since we may need to clamp to the borders of the src rect within
288 // the bitmap, we extract a subset.
289 SkIRect srcIR;
290 tmpSrc.roundOut(&srcIR);
291 if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
292 return;
293 }
294 bitmapPtr = &tmpBitmap;
295
296 // Since we did an extract, we need to adjust the matrix accordingly
297 SkScalar dx = 0, dy = 0;
298 if (srcIR.fLeft > 0) {
299 dx = SkIntToScalar(srcIR.fLeft);
300 }
301 if (srcIR.fTop > 0) {
302 dy = SkIntToScalar(srcIR.fTop);
303 }
304 if (dx || dy) {
305 matrix.preTranslate(dx, dy);
306 }
307
308 SkRect extractedBitmapBounds;
309 extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
310 if (extractedBitmapBounds == tmpSrc) {
311 // no fractional part in src, we can just call drawBitmap
312 goto USE_DRAWBITMAP;
313 }
314 } else {
315 USE_DRAWBITMAP:
316 // We can go faster by just calling drawBitmap, which will concat the
317 // matrix with the CTM, and try to call drawSprite if it can. If not,
318 // it will make a shader and call drawRect, as we do below.
319 this->drawBitmap(draw, *bitmapPtr, matrix, paint);
320 return;
321 }
322
323 // construct a shader, so we can call drawRect with the dst
324 SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
325 SkShader::kClamp_TileMode,
326 SkShader::kClamp_TileMode);
327 if (NULL == s) {
328 return;
329 }
330 s->setLocalMatrix(matrix);
331
332 SkPaint paintWithShader(paint);
333 paintWithShader.setStyle(SkPaint::kFill_Style);
334 paintWithShader.setShader(s)->unref();
335
336 // Call ourself, in case the subclass wanted to share this setup code
337 // but handle the drawRect code themselves.
338 this->drawRect(draw, *dstPtr, paintWithShader);
339 }
340
341 void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
342 int x, int y, const SkPaint& paint) {
343 draw.drawSprite(bitmap, x, y, paint);
344 }
345
346 void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
347 SkScalar x, SkScalar y, const SkPaint& paint) {
348 draw.drawText((const char*)text, len, x, y, paint);
349 }
350
351 void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n,
352 const SkScalar xpos[], SkScalar y,
353 int scalarsPerPos, const SkPaint& paint) {
354 draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
355 }
356
357 void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
358 size_t len, const SkPath& path,
359 const SkMatrix* matrix,
360 const SkPaint& paint) {
361 draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
362 }
363
364 #ifdef SK_BUILD_FOR_ANDROID
365 void SkBitmapDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, siz e_t len,
366 const SkPoint pos[], const SkPaint& paint ,
367 const SkPath& path, const SkMatrix* matri x) {
368 draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
369 }
370 #endif
371
372 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode ,
373 int vertexCount,
374 const SkPoint verts[], const SkPoint textures[ ],
375 const SkColor colors[], SkXfermode* xmode,
376 const uint16_t indices[], int indexCount,
377 const SkPaint& paint) {
378 draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
379 indices, indexCount, paint);
380 }
381
382 void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
383 int x, int y, const SkPaint& paint) {
384 const SkBitmap& src = device->accessBitmap(false);
385 draw.drawSprite(src, x, y, paint);
386 }
387
388 ///////////////////////////////////////////////////////////////////////////////
389
390 bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
391 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
392 // we're cool with the paint as is
393 return false;
394 }
395
396 if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
397 paint.getRasterizer() ||
398 paint.getPathEffect() ||
399 paint.isFakeBoldText() ||
400 paint.getStyle() != SkPaint::kFill_Style ||
401 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
402 // turn off lcd
403 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
404 flags->fHinting = paint.getHinting();
405 return true;
406 }
407 // we're cool with the paint as is
408 return false;
409 }
410
OLDNEW
« no previous file with comments | « gyp/core.gypi ('k') | src/core/SkDevice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698