Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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 */
8 #include "SkBitmapDevice.h"
9 #include "SkConfig8888.h"
10 #include "SkDraw.h"
11 #include "SkRasterClip.h"
12 #include "SkShader.h"
13 #include "SkSurface.h"
15 #define CHECK_FOR_ANNOTATION(paint) \
16 do { if (paint.getAnnotation()) { return; } } while (0)
18 static bool valid_for_bitmap_device(const SkImageInfo& info,
19 SkAlphaType* newAlphaType) {
20 if (info.width() < 0 || info.height() < 0) {
21 return false;
22 }
24 // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
25 if (kUnknown_SkColorType == info.colorType()) {
26 if (newAlphaType) {
27 *newAlphaType = kIgnore_SkAlphaType;
28 }
29 return true;
30 }
32 switch (info.alphaType()) {
33 case kPremul_SkAlphaType:
34 case kOpaque_SkAlphaType:
35 break;
36 default:
37 return false;
38 }
40 SkAlphaType canonicalAlphaType = info.alphaType();
42 switch (info.colorType()) {
43 case kAlpha_8_SkColorType:
44 break;
45 case kRGB_565_SkColorType:
46 canonicalAlphaType = kOpaque_SkAlphaType;
47 break;
48 case kPMColor_SkColorType:
49 break;
50 default:
51 return false;
52 }
54 if (newAlphaType) {
55 *newAlphaType = canonicalAlphaType;
56 }
57 return true;
58 }
60 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
61 SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
62 }
64 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
65 : SkBaseDevice(deviceProperties)
66 , fBitmap(bitmap)
67 {
68 SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
69 }
71 #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
72 void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) {
73 fBitmap.setConfig(config, width, height, 0, isOpaque ?
74 kOpaque_SkAlphaType : kPremul_SkAlphaType);
76 if (SkBitmap::kNo_Config != config) {
77 if (!fBitmap.allocPixels()) {
78 // indicate failure by zeroing our bitmap
79 fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
80 kOpaque_SkAlphaType : kPremul_SkAlphaType);
81 } else if (!isOpaque) {
82 fBitmap.eraseColor(SK_ColorTRANSPARENT);
83 }
84 }
85 }
87 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
88 this->init(config, width, height, isOpaque);
89 }
91 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
92 const SkDeviceProperties& deviceProperties)
93 : SkBaseDevice(deviceProperties)
94 {
95 this->init(config, width, height, isOpaque);
96 }
97 #endif
98 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
99 const SkDeviceProperties* props) {
100 SkImageInfo info = origInfo;
101 if (!valid_for_bitmap_device(info, &info.fAlphaType)) {
102 return NULL;
103 }
105 SkBitmap bitmap;
107 if (kUnknown_SkColorType == info.colorType()) {
108 if (!bitmap.setConfig(info)) {
109 return NULL;
110 }
111 } else {
112 if (!bitmap.allocPixels(info)) {
113 return NULL;
114 }
115 if (!bitmap.info().isOpaque()) {
116 bitmap.eraseColor(SK_ColorTRANSPARENT);
117 }
118 }
120 if (props) {
121 return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
122 } else {
123 return SkNEW_ARGS(SkBitmapDevice, (bitmap));
124 }
125 }
127 SkImageInfo SkBitmapDevice::imageInfo() const {
128 return fBitmap.info();
129 }
131 void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
132 SkASSERT(bm.width() == fBitmap.width());
133 SkASSERT(bm.height() == fBitmap.height());
134 fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
135 fBitmap.lockPixels();
136 }
138 SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
139 return SkBitmapDevice::Create(info, &this->getDeviceProperties());
140 }
142 void SkBitmapDevice::lockPixels() {
143 if (fBitmap.lockPixelsAreWritable()) {
144 fBitmap.lockPixels();
145 }
146 }
148 void SkBitmapDevice::unlockPixels() {
149 if (fBitmap.lockPixelsAreWritable()) {
150 fBitmap.unlockPixels();
151 }
152 }
154 void SkBitmapDevice::clear(SkColor color) {
155 fBitmap.eraseColor(color);
156 }
158 const SkBitmap& SkBitmapDevice::onAccessBitmap() {
159 return fBitmap;
160 }
162 bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) {
163 return false;
164 }
166 bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
167 const SkImageFilter::Context& ctx, SkBitmap* result,
168 SkIPoint* offset) {
169 return false;
170 }
172 bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) {
173 return true;
174 }
176 bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
177 int x, int y,
178 SkCanvas::Config8888 config8888) {
179 SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
180 SkASSERT(!bitmap.isNull());
181 SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y,
182 bitmap.width(),
183 bitmap.height())));
185 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
186 const SkBitmap& src = this->accessBitmap(false);
188 SkBitmap subset;
189 if (!src.extractSubset(&subset, srcRect)) {
190 return false;
191 }
192 if (kPMColor_SkColorType != subset.colorType()) {
193 // It'd be preferable to do this directly to bitmap.
194 subset.copyTo(&subset, kPMColor_SkColorType);
195 }
196 SkAutoLockPixels alp(bitmap);
197 uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
198 SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
199 return true;
200 }
202 #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
203 void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
204 int x, int y,
205 SkCanvas::Config8888 config8888) {
206 if (bitmap.isNull() || bitmap.getTexture()) {
207 return;
208 }
209 const SkBitmap* sprite = &bitmap;
210 // check whether we have to handle a config8888 that doesn't match SkPMColor
211 if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
212 SkCanvas::kNative_Premul_Config8888 != config8888 &&
213 kPMColorAlias != config8888) {
215 // We're going to have to convert from a config8888 to the native config
216 // First we clip to the device bounds.
217 SkBitmap dstBmp = this->accessBitmap(true);
218 SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
219 bitmap.width(), bitmap.height());
220 SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
221 if (!spriteRect.intersect(devRect)) {
222 return;
223 }
225 // write directly to the device if it has pixels and is SkPMColor
226 bool drawSprite;
227 if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
228 // we can write directly to the dst when doing the conversion
229 dstBmp.extractSubset(&dstBmp, spriteRect);
230 drawSprite = false;
231 } else {
232 // we convert to a temporary bitmap and draw that as a sprite
233 if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(),
234 spriteRect.height()))) {
235 return;
236 }
237 drawSprite = true;
238 }
240 // copy pixels to dstBmp and convert from config8888 to native config.
241 SkAutoLockPixels alp(bitmap);
242 uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
243 spriteRect.fTop - y);
244 SkCopyConfig8888ToBitmap(dstBmp,
245 srcPixels,
246 bitmap.rowBytes(),
247 config8888);
249 if (drawSprite) {
250 // we've clipped the sprite when we made a copy
251 x = spriteRect.fLeft;
252 y = spriteRect.fTop;
253 sprite = &dstBmp;
254 } else {
255 return;
256 }
257 }
259 SkPaint paint;
260 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
261 SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
262 SkDraw draw;
263 draw.fRC = &clip;
264 draw.fClip = &clip.bwRgn();
265 draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
266 draw.fMatrix = &SkMatrix::I();
267 this->drawSprite(draw, *sprite, x, y, paint);
268 }
269 #endif
271 void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
272 if (fBitmap.getPixels()) {
273 *info = fBitmap.info();
274 *rowBytes = fBitmap.rowBytes();
275 return fBitmap.getPixels();
276 }
277 return NULL;
278 }
280 static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow,
281 int rowCount) {
282 SkASSERT(bytesPerRow <= srcRB);
283 SkASSERT(bytesPerRow <= dstRB);
284 for (int i = 0; i < rowCount; ++i) {
285 memcpy(dst, src, bytesPerRow);
286 dst = (char*)dst + dstRB;
287 src = (const char*)src + srcRB;
288 }
289 }
291 static bool info2config8888(const SkImageInfo& info, SkCanvas::Config8888* config) {
292 bool pre;
293 switch (info.alphaType()) {
294 case kPremul_SkAlphaType:
295 case kOpaque_SkAlphaType:
296 pre = true;
297 break;
298 case kUnpremul_SkAlphaType:
299 pre = false;
300 break;
301 default:
302 return false;
303 }
304 switch (info.colorType()) {
305 case kRGBA_8888_SkColorType:
306 *config = pre ? SkCanvas::kRGBA_Premul_Config8888 : SkCanvas::kRGBA_Unpremul_Config8888;
307 return true;
308 case kBGRA_8888_SkColorType:
309 *config = pre ? SkCanvas::kBGRA_Premul_Config8888 : SkCanvas::kBGRA_Unpremul_Config8888;
310 return true;
311 default:
312 return false;
313 }
314 }
316 // TODO: make this guy real, and not rely on legacy config8888 utility
317 #include "SkConfig8888.h"
318 static bool write_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
319 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
320 if (srcInfo.dimensions() != dstInfo.dimensions()) {
321 return false;
322 }
323 if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) {
324 SkCanvas::Config8888 srcConfig, dstConfig;
325 if (!info2config8888(srcInfo, &srcConfig) || !info2config8888(dstInfo, &dstConfig)) {
326 return false;
327 }
328 SkConvertConfig8888Pixels((uint32_t*)dstPixels, dstRowBytes, dstConfig,
329 (const uint32_t*)srcPixels, srcRowBytes, srcConfig,
330 srcInfo.width(), srcInfo.height());
331 return true;
332 }
333 if (srcInfo.colorType() == dstInfo.colorType()) {
334 switch (srcInfo.colorType()) {
335 case kRGB_565_SkColorType:
336 case kAlpha_8_SkColorType:
337 break;
338 case kARGB_4444_SkColorType:
339 if (srcInfo.alphaType() != dstInfo.alphaType()) {
340 return false;
341 }
342 break;
343 default:
344 return false;
345 }
346 rect_memcpy(dstPixels, dstRowBytes, srcPixels, srcRowBytes,
347 srcInfo.width() * srcInfo.bytesPerPixel(), srcInfo.height());
348 }
349 // TODO: add support for more conversions as needed
350 return false;
351 }
353 bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
354 size_t srcRowBytes, int x, int y) {
355 // since we don't stop creating un-pixeled devices yet, check for no pixels here
356 if (NULL == fBitmap.getPixels()) {
357 return false;
358 }
360 SkImageInfo dstInfo = fBitmap.info();
361 dstInfo.fWidth = srcInfo.width();
362 dstInfo.fHeight = srcInfo.height();
364 void* dstPixels = fBitmap.getAddr(x, y);
365 size_t dstRowBytes = fBitmap.rowBytes();
367 if (write_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
368 fBitmap.notifyPixelsChanged();
369 return true;
370 }
371 return false;
372 }
374 ///////////////////////////////////////////////////////////////////////////////
376 void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
377 draw.drawPaint(paint);
378 }
380 void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
381 const SkPoint pts[], const SkPaint& paint) {
382 CHECK_FOR_ANNOTATION(paint);
383 draw.drawPoints(mode, count, pts, paint);
384 }
386 void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
387 CHECK_FOR_ANNOTATION(paint);
388 draw.drawRect(r, paint);
389 }
391 void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
392 CHECK_FOR_ANNOTATION(paint);
394 SkPath path;
395 path.addOval(oval);
396 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
397 // required to override drawOval.
398 this->drawPath(draw, path, paint, NULL, true);
399 }
401 void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
402 CHECK_FOR_ANNOTATION(paint);
404 #ifdef SK_IGNORE_BLURRED_RRECT_OPT
405 SkPath path;
407 path.addRRect(rrect);
408 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
409 // required to override drawRRect.
410 this->drawPath(draw, path, paint, NULL, true);
411 #else
412 draw.drawRRect(rrect, paint);
413 #endif
414 }
416 void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
417 const SkPaint& paint, const SkMatrix* prePathMatrix,
418 bool pathIsMutable) {
419 CHECK_FOR_ANNOTATION(paint);
420 draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
421 }
423 void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
424 const SkMatrix& matrix, const SkPaint& paint) {
425 draw.drawBitmap(bitmap, matrix, paint);
426 }
428 void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
429 const SkRect* src, const SkRect& dst,
430 const SkPaint& paint,
431 SkCanvas::DrawBitmapRectFlags flags) {
432 SkMatrix matrix;
433 SkRect bitmapBounds, tmpSrc, tmpDst;
434 SkBitmap tmpBitmap;
436 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
438 // Compute matrix from the two rectangles
439 if (src) {
440 tmpSrc = *src;
441 } else {
442 tmpSrc = bitmapBounds;
443 }
444 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
446 const SkRect* dstPtr = &dst;
447 const SkBitmap* bitmapPtr = &bitmap;
449 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
450 // needed (if the src was clipped). No check needed if src==null.
451 if (src) {
452 if (!bitmapBounds.contains(*src)) {
453 if (!tmpSrc.intersect(bitmapBounds)) {
454 return; // nothing to draw
455 }
456 // recompute dst, based on the smaller tmpSrc
457 matrix.mapRect(&tmpDst, tmpSrc);
458 dstPtr = &tmpDst;
459 }
461 // since we may need to clamp to the borders of the src rect within
462 // the bitmap, we extract a subset.
463 SkIRect srcIR;
464 tmpSrc.roundOut(&srcIR);
465 if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
466 return;
467 }
468 bitmapPtr = &tmpBitmap;
470 // Since we did an extract, we need to adjust the matrix accordingly
471 SkScalar dx = 0, dy = 0;
472 if (srcIR.fLeft > 0) {
473 dx = SkIntToScalar(srcIR.fLeft);
474 }
475 if (srcIR.fTop > 0) {
476 dy = SkIntToScalar(srcIR.fTop);
477 }
478 if (dx || dy) {
479 matrix.preTranslate(dx, dy);
480 }
482 SkRect extractedBitmapBounds;
483 extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
484 if (extractedBitmapBounds == tmpSrc) {
485 // no fractional part in src, we can just call drawBitmap
486 goto USE_DRAWBITMAP;
487 }
488 } else {
489 USE_DRAWBITMAP:
490 // We can go faster by just calling drawBitmap, which will concat the
491 // matrix with the CTM, and try to call drawSprite if it can. If not,
492 // it will make a shader and call drawRect, as we do below.
493 this->drawBitmap(draw, *bitmapPtr, matrix, paint);
494 return;
495 }
497 // construct a shader, so we can call drawRect with the dst
498 SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
499 SkShader::kClamp_TileMode,
500 SkShader::kClamp_TileMode);
501 if (NULL == s) {
502 return;
503 }
504 s->setLocalMatrix(matrix);
506 SkPaint paintWithShader(paint);
507 paintWithShader.setStyle(SkPaint::kFill_Style);
508 paintWithShader.setShader(s)->unref();
510 // Call ourself, in case the subclass wanted to share this setup code
511 // but handle the drawRect code themselves.
512 this->drawRect(draw, *dstPtr, paintWithShader);
513 }
515 void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
516 int x, int y, const SkPaint& paint) {
517 draw.drawSprite(bitmap, x, y, paint);
518 }
520 void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
521 SkScalar x, SkScalar y, const SkPaint& paint) {
522 draw.drawText((const char*)text, len, x, y, paint);
523 }
525 void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
526 const SkScalar xpos[], SkScalar y,
527 int scalarsPerPos, const SkPaint& paint) {
528 draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
529 }
531 void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
532 size_t len, const SkPath& path,
533 const SkMatrix* matrix,
534 const SkPaint& paint) {
535 draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
536 }
538 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
539 int vertexCount,
540 const SkPoint verts[], const SkPoint textures[],
541 const SkColor colors[], SkXfermode* xmode,
542 const uint16_t indices[], int indexCount,
543 const SkPaint& paint) {
544 draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
545 indices, indexCount, paint);
546 }
548 void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
549 int x, int y, const SkPaint& paint) {
550 const SkBitmap& src = device->accessBitmap(false);
551 draw.drawSprite(src, x, y, paint);
552 }
554 SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) {
555 return SkSurface::NewRaster(info);
556 }
558 const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) {
559 if (fBitmap.getPixels() && fBitmap.asImageInfo(info)) {
560 if (rowBytes) {
561 *rowBytes = fBitmap.rowBytes();
562 }
563 return fBitmap.getPixels();
564 }
565 return NULL;
566 }
568 ///////////////////////////////////////////////////////////////////////////////
570 bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
571 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
572 // we're cool with the paint as is
573 return false;
574 }
576 if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
577 paint.getRasterizer() ||
578 paint.getPathEffect() ||
579 paint.isFakeBoldText() ||
580 paint.getStyle() != SkPaint::kFill_Style ||
581 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
582 // turn off lcd
583 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
584 flags->fHinting = paint.getHinting();
585 return true;
586 }
587 // we're cool with the paint as is
588 return false;
589 }