SkBitmapDevice.cpp revision b07a94f1cba3976596ae1a7f23d8c2043ba353f3
153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com/* 253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * Copyright 2013 Google Inc. 353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * 453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com * found in the LICENSE file. 653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com */ 753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkBitmapDevice.h" 953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkConfig8888.h" 10b2db898573e3cdcc8234eebf51961bfc4977ebbcreed#include "SkDeviceProperties.h" 1153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkDraw.h" 1253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkRasterClip.h" 1353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com#include "SkShader.h" 1476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com#include "SkSurface.h" 1553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 164469938e92d779dff05e745559e67907bbf21e78reed@google.com#define CHECK_FOR_ANNOTATION(paint) \ 174469938e92d779dff05e745559e67907bbf21e78reed@google.com do { if (paint.getAnnotation()) { return; } } while (0) 1853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 1915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgstatic bool valid_for_bitmap_device(const SkImageInfo& info, 2015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkAlphaType* newAlphaType) { 2115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (info.width() < 0 || info.height() < 0) { 2215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return false; 2315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 2415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 2515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org // TODO: can we stop supporting kUnknown in SkBitmkapDevice? 2615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (kUnknown_SkColorType == info.colorType()) { 2715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (newAlphaType) { 2815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org *newAlphaType = kIgnore_SkAlphaType; 2915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 3015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return true; 3115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 32969588f0c9030d5a4942085a4b5a5ea7e8d2bc25skia.committer@gmail.com 3315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org switch (info.alphaType()) { 3415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kPremul_SkAlphaType: 3515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kOpaque_SkAlphaType: 3615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 3715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org default: 3815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return false; 3915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 4015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 4115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkAlphaType canonicalAlphaType = info.alphaType(); 4215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 4315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org switch (info.colorType()) { 4415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kAlpha_8_SkColorType: 4515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 4615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org case kRGB_565_SkColorType: 4715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org canonicalAlphaType = kOpaque_SkAlphaType; 4815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 4928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 5015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org break; 5115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org default: 5215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return false; 5315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 5415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 5515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (newAlphaType) { 5615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org *newAlphaType = canonicalAlphaType; 5715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 5815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return true; 5915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org} 6015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 6115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) { 6215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL)); 6353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 6453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 6553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comSkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties) 6653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com : SkBaseDevice(deviceProperties) 6715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org , fBitmap(bitmap) 6815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org{ 6915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL)); 7053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 7153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 7215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.orgSkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo, 7315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org const SkDeviceProperties* props) { 74e5ea500d4714a7d84de2bf913e81be3b65d2de68reed SkAlphaType newAT = origInfo.alphaType(); 75e5ea500d4714a7d84de2bf913e81be3b65d2de68reed if (!valid_for_bitmap_device(origInfo, &newAT)) { 7615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return NULL; 7715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 7815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 79e5ea500d4714a7d84de2bf913e81be3b65d2de68reed const SkImageInfo info = origInfo.makeAlphaType(newAT); 8015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkBitmap bitmap; 8115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org 8215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (kUnknown_SkColorType == info.colorType()) { 83a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org if (!bitmap.setInfo(info)) { 8415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return NULL; 8515a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 8615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } else { 87848250415eddc54075f7eb8795e8db79e749c6abreed if (!bitmap.tryAllocPixels(info)) { 8815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return NULL; 8915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 9015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org if (!bitmap.info().isOpaque()) { 9115a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org bitmap.eraseColor(SK_ColorTRANSPARENT); 9215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 9315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 9453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 95b2db898573e3cdcc8234eebf51961bfc4977ebbcreed if (props) { 96b2db898573e3cdcc8234eebf51961bfc4977ebbcreed return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props)); 9715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } else { 9815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org return SkNEW_ARGS(SkBitmapDevice, (bitmap)); 9915a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org } 10053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 10153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 102c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkBitmapDevice::imageInfo() const { 103c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return fBitmap.info(); 104c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 105c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 10653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { 10753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkASSERT(bm.width() == fBitmap.width()); 10853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkASSERT(bm.height() == fBitmap.height()); 10953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config) 11053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap.lockPixels(); 11153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 11253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 1136987dcaf257dd7c2c8e0014cf7452fde82bcba5bfmalitaSkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { 114b2db898573e3cdcc8234eebf51961bfc4977ebbcreed SkDeviceProperties leaky(cinfo.fPixelGeometry); 115b2db898573e3cdcc8234eebf51961bfc4977ebbcreed return SkBitmapDevice::Create(cinfo.fInfo, &leaky); 11653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 11753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 11853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::lockPixels() { 11953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (fBitmap.lockPixelsAreWritable()) { 12053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap.lockPixels(); 12153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 12253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 12353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 12453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::unlockPixels() { 12553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (fBitmap.lockPixelsAreWritable()) { 12653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap.unlockPixels(); 12753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 12853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 12953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 13053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::clear(SkColor color) { 13153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com fBitmap.eraseColor(color); 13253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 13353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 13453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comconst SkBitmap& SkBitmapDevice::onAccessBitmap() { 13553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return fBitmap; 13653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 13753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 1389c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.comvoid* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) { 1399c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com if (fBitmap.getPixels()) { 1409c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com *info = fBitmap.info(); 1419c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com *rowBytes = fBitmap.rowBytes(); 1429c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com return fBitmap.getPixels(); 1439c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com } 1449c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com return NULL; 1459c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com} 1469c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com 147231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org#include "SkConfig8888.h" 1480e9770515cab45decb56a5926d1741b71854fb4cpiotaixr#include "SkPixelRef.h" 1497111d463cee893a479280c7af41757e709e33ef5reed@google.com 1504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels, 1514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org size_t srcRowBytes, int x, int y) { 1520d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com // since we don't stop creating un-pixeled devices yet, check for no pixels here 1530d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com if (NULL == fBitmap.getPixels()) { 1540d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com return false; 1550d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com } 1560d30c51c6cf45b3a08a3000b6d348c16bdec7f05reed@google.com 157e5ea500d4714a7d84de2bf913e81be3b65d2de68reed const SkImageInfo dstInfo = fBitmap.info().makeWH(srcInfo.width(), srcInfo.height()); 1584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 1594cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org void* dstPixels = fBitmap.getAddr(x, y); 1604cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org size_t dstRowBytes = fBitmap.rowBytes(); 1614cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org 162b184f7f52b2a94e95aee326a3ca37110d2e43336reed if (SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) { 1634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org fBitmap.notifyPixelsChanged(); 1644cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return true; 1654cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org } 1664cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org return false; 1674cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org} 16853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 169a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.orgbool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 170a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org int x, int y) { 171b184f7f52b2a94e95aee326a3ca37110d2e43336reed return fBitmap.readPixels(dstInfo, dstPixels, dstRowBytes, x, y); 172a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org} 173a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org 17453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 17553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 17653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { 17753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawPaint(paint); 17853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 17953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 18053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, 18153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPoint pts[], const SkPaint& paint) { 1824469938e92d779dff05e745559e67907bbf21e78reed@google.com CHECK_FOR_ANNOTATION(paint); 18353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawPoints(mode, count, pts, paint); 18453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 18553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 18653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { 1874469938e92d779dff05e745559e67907bbf21e78reed@google.com CHECK_FOR_ANNOTATION(paint); 18853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawRect(r, paint); 18953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 19053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 19153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { 1924469938e92d779dff05e745559e67907bbf21e78reed@google.com CHECK_FOR_ANNOTATION(paint); 19353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 19453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkPath path; 19553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com path.addOval(oval); 19653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 19753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // required to override drawOval. 19853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com this->drawPath(draw, path, paint, NULL, true); 19953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 20053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 20153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) { 2024469938e92d779dff05e745559e67907bbf21e78reed@google.com CHECK_FOR_ANNOTATION(paint); 20353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 20450a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#ifdef SK_IGNORE_BLURRED_RRECT_OPT 20550a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com SkPath path; 20650a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com 20750a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com path.addRRect(rrect); 20850a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 20950a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com // required to override drawRRect. 21050a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com this->drawPath(draw, path, paint, NULL, true); 21150a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#else 212a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com draw.drawRRect(rrect, paint); 21350a7600d05d427c64f77d39c8c18d2bf6cabd25brobertphillips@google.com#endif 21453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 21553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 21653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path, 21753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint, const SkMatrix* prePathMatrix, 21853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bool pathIsMutable) { 2194469938e92d779dff05e745559e67907bbf21e78reed@google.com CHECK_FOR_ANNOTATION(paint); 22053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawPath(path, paint, prePathMatrix, pathIsMutable); 22153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 22253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 22353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, 22453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkMatrix& matrix, const SkPaint& paint) { 22553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawBitmap(bitmap, matrix, paint); 22653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 22753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 22853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 22953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkRect* src, const SkRect& dst, 23053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint, 23153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkCanvas::DrawBitmapRectFlags flags) { 23253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkMatrix matrix; 23353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkRect bitmapBounds, tmpSrc, tmpDst; 23453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkBitmap tmpBitmap; 23553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 23653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bitmapBounds.isetWH(bitmap.width(), bitmap.height()); 23753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 23853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Compute matrix from the two rectangles 23953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (src) { 24053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com tmpSrc = *src; 24153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } else { 24253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com tmpSrc = bitmapBounds; 24353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 24453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 24553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 24653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkRect* dstPtr = &dst; 24753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkBitmap* bitmapPtr = &bitmap; 24853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 24953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if 25053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // needed (if the src was clipped). No check needed if src==null. 25153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (src) { 25253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (!bitmapBounds.contains(*src)) { 25353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (!tmpSrc.intersect(bitmapBounds)) { 25453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return; // nothing to draw 25553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 25653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // recompute dst, based on the smaller tmpSrc 25753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.mapRect(&tmpDst, tmpSrc); 25853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dstPtr = &tmpDst; 25953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 26053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 26153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // since we may need to clamp to the borders of the src rect within 26253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // the bitmap, we extract a subset. 263b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkIRect srcIR = tmpSrc.roundOut(); 2640e9770515cab45decb56a5926d1741b71854fb4cpiotaixr if(bitmap.pixelRef()->getTexture()) { 2650e9770515cab45decb56a5926d1741b71854fb4cpiotaixr // Accelerated source canvas, don't use extractSubset but readPixels to get the subset. 2660e9770515cab45decb56a5926d1741b71854fb4cpiotaixr // This way, the pixels are copied in CPU memory instead of GPU memory. 2670e9770515cab45decb56a5926d1741b71854fb4cpiotaixr bitmap.pixelRef()->readPixels(&tmpBitmap, &srcIR); 2680e9770515cab45decb56a5926d1741b71854fb4cpiotaixr } else { 2690e9770515cab45decb56a5926d1741b71854fb4cpiotaixr if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { 2700e9770515cab45decb56a5926d1741b71854fb4cpiotaixr return; 2710e9770515cab45decb56a5926d1741b71854fb4cpiotaixr } 27253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 27353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com bitmapPtr = &tmpBitmap; 27453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 27553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Since we did an extract, we need to adjust the matrix accordingly 27653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkScalar dx = 0, dy = 0; 27753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (srcIR.fLeft > 0) { 27853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dx = SkIntToScalar(srcIR.fLeft); 27953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 28053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (srcIR.fTop > 0) { 28153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com dy = SkIntToScalar(srcIR.fTop); 28253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 28353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (dx || dy) { 28453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com matrix.preTranslate(dx, dy); 28553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 28653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 28753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkRect extractedBitmapBounds; 28853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height()); 28953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (extractedBitmapBounds == tmpSrc) { 29053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // no fractional part in src, we can just call drawBitmap 29153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com goto USE_DRAWBITMAP; 29253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 29353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } else { 29453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com USE_DRAWBITMAP: 29553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // We can go faster by just calling drawBitmap, which will concat the 29653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // matrix with the CTM, and try to call drawSprite if it can. If not, 29753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // it will make a shader and call drawRect, as we do below. 29853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com this->drawBitmap(draw, *bitmapPtr, matrix, paint); 29953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return; 30053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 30153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 30253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // construct a shader, so we can call drawRect with the dst 30353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr, 30453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkShader::kClamp_TileMode, 3059c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkShader::kClamp_TileMode, 3069c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org &matrix); 30753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com if (NULL == s) { 30853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return; 30953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 31053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 31153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkPaint paintWithShader(paint); 31253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paintWithShader.setStyle(SkPaint::kFill_Style); 31353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paintWithShader.setShader(s)->unref(); 31453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 31553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // Call ourself, in case the subclass wanted to share this setup code 31653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com // but handle the drawRect code themselves. 31753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com this->drawRect(draw, *dstPtr, paintWithShader); 31853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 31953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 32053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, 32153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com int x, int y, const SkPaint& paint) { 32253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawSprite(bitmap, x, y, paint); 32353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 32453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 32553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len, 32653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com SkScalar x, SkScalar y, const SkPaint& paint) { 32753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawText((const char*)text, len, x, y, paint); 32853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 32953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 33053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, 33105c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkScalar xpos[], int scalarsPerPos, 33205c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkPoint& offset, const SkPaint& paint) { 33305c4a4322e7d4f3417b7df33825bab8603d52051fmalita draw.drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint); 33453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 33553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 33653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text, 33753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com size_t len, const SkPath& path, 33853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkMatrix* matrix, 33953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint) { 34053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawTextOnPath((const char*)text, len, path, matrix, paint); 34153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 34253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 34353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, 34453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com int vertexCount, 34553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPoint verts[], const SkPoint textures[], 34653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkColor colors[], SkXfermode* xmode, 34753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const uint16_t indices[], int indexCount, 34853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkPaint& paint) { 34953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode, 35053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com indices, indexCount, paint); 35153238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 35253238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 35353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.comvoid SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, 35453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com int x, int y, const SkPaint& paint) { 35553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com const SkBitmap& src = device->accessBitmap(false); 35653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com draw.drawSprite(src, x, y, paint); 35753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 35853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 3594a8126e7f81384526629b1e21bf89b632ea13cd9reedSkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 3604a8126e7f81384526629b1e21bf89b632ea13cd9reed return SkSurface::NewRaster(info, &props); 36176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com} 36276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com 363c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgconst void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) { 364466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org const SkImageInfo bmInfo = fBitmap.info(); 365466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org if (fBitmap.getPixels() && (kUnknown_SkColorType != bmInfo.colorType())) { 366466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org if (info) { 367466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org *info = bmInfo; 368466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org } 369c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org if (rowBytes) { 370c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org *rowBytes = fBitmap.rowBytes(); 371c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 372c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return fBitmap.getPixels(); 373c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org } 374c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org return NULL; 375c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org} 376c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org 377be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblancoSkImageFilter::Cache* SkBitmapDevice::getImageFilterCache() { 378be129b26f13d575fd6b396c6ae759838ecc9bd1asenorblanco SkImageFilter::Cache* cache = SkImageFilter::Cache::Get(); 37955b6d8be997a447ef9ce0f029697677a940bfc24senorblanco cache->ref(); 38055b6d8be997a447ef9ce0f029697677a940bfc24senorblanco return cache; 38155b6d8be997a447ef9ce0f029697677a940bfc24senorblanco} 38255b6d8be997a447ef9ce0f029697677a940bfc24senorblanco 38353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com/////////////////////////////////////////////////////////////////////////////// 38453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com 385b2db898573e3cdcc8234eebf51961bfc4977ebbcreedbool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const { 386cba73780bbd12fd254229517aec04fcbf0b64b52commit-bot@chromium.org if (kN32_SkColorType != fBitmap.colorType() || 38753238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.getRasterizer() || 38853238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.getPathEffect() || 38953238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.isFakeBoldText() || 39053238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com paint.getStyle() != SkPaint::kFill_Style || 391b2db898573e3cdcc8234eebf51961bfc4977ebbcreed !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) 392b2db898573e3cdcc8234eebf51961bfc4977ebbcreed { 39353238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return true; 39453238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com } 39553238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com return false; 39653238bc96051d1774b7f72d3ebfd35a7dd4c04dfrobertphillips@google.com} 397