1e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 2e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com/* 3e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com * Copyright 2012 Google Inc. 4e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com * 5e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com * Use of this source code is governed by a BSD-style license that can be 6e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com * found in the LICENSE file. 7e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com */ 8e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 9e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com#include "SkBBoxRecord.h" 10b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h" 11e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 12b7425173f96e93b090787e2386ba5f022b6c2869fmalita#include "SkTextBlob.h" 13b7425173f96e93b090787e2386ba5f022b6c2869fmalita 14837f5321a409228a27fc710eb71c87866b820cfbsenorblancoSkBBoxRecord::~SkBBoxRecord() { 15837f5321a409228a27fc710eb71c87866b820cfbsenorblanco fSaveStack.deleteAll(); 16837f5321a409228a27fc710eb71c87866b820cfbsenorblanco} 17837f5321a409228a27fc710eb71c87866b820cfbsenorblanco 185f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.orgvoid SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) { 195f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org if (this->transformBounds(rect, &paint)) { 205f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org INHERITED::drawOval(rect, paint); 215f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org } 225f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org} 235f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org 245f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.orgvoid SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 255f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org if (this->transformBounds(rrect.rect(), &paint)) { 265f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org INHERITED::drawRRect(rrect, paint); 275f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org } 285f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org} 295f8c8f448673c65c5434cf1e419319eccf34117bjunov@chromium.org 307ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) { 31e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(rect, &paint)) { 327ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.com INHERITED::drawRect(rect, paint); 33e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 34e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 35e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 36ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 37ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org const SkPaint& paint) { 38ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org if (this->transformBounds(outer.rect(), &paint)) { 39ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org this->INHERITED::onDrawDRRect(outer, inner, paint); 40ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org } 41ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org} 42ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org 437ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.comvoid SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) { 440c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org if (path.isInverseFillType()) { 450c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org // If path is inverse filled, use the current clip bounds as the 460c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org // path's device-space bounding box. 470c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org SkIRect clipBounds; 480c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org if (this->getClipDeviceBounds(&clipBounds)) { 494469938e92d779dff05e745559e67907bbf21e78reed@google.com this->handleBBox(SkRect::Make(clipBounds)); 507ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.com INHERITED::drawPath(path, paint); 510c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org } 520c8ec2f658a206cbedd0d955167654fae85ad5fbjunov@chromium.org } else if (this->transformBounds(path.getBounds(), &paint)) { 537ce564cccb246ec56427085872b2e1458fe74bd1bsalomon@google.com INHERITED::drawPath(path, paint); 54e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 55e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 56e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 57e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 58e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPaint& paint) { 59e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox; 606fcd28ba1de83b72f4c8343ccec27d26c127de32reed@google.com bbox.set(pts, SkToInt(count)); 61b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // Small min width value, just to ensure hairline point bounding boxes aren't empty. 62b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // Even though we know hairline primitives are drawn one pixel wide, we do not use a 63b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // minimum of 1 because the playback scale factor is unknown at record time. Later 64b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // outsets will take care of adding additional padding for antialiasing and rounding out 65b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // to integer device coordinates, guaranteeing that the rasterized pixels will be included 66b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // in the computed bounds. 67b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently 68b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // done in the recording coordinate space, which is wrong. 69b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org // http://code.google.com/p/skia/issues/detail?id=1021 704b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org static const SkScalar kMinWidth = 0.01f; 71b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2; 72b3470c8c421ee8f367673a67c3408507cee04434junov@chromium.org bbox.outset(halfStrokeWidth, halfStrokeWidth); 73e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 74e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawPoints(mode, count, pts, paint); 75e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 7604ba448579b976369075c675d847ef0f779d40f4skia.committer@gmail.com} 77e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 78e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawPaint(const SkPaint& paint) { 79e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox; 80e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->getClipBounds(&bbox)) { 81e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 82e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawPaint(paint); 83e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 84e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 85e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 86e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 87e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::clear(SkColor color) { 88e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkISize size = this->getDeviceSize(); 89ec0aa764ebe36aecdfb77286d665fccc85ab204ageorge@mozilla.com SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())}; 90e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com this->handleBBox(bbox); 91e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::clear(color); 92e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 93e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 94e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkBBoxRecord::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 95e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com const SkPaint& paint) { 96e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox; 97e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com paint.measureText(text, byteLength, &bbox); 98e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkPaint::FontMetrics metrics; 99e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com paint.getFontMetrics(&metrics); 100e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 101e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // Vertical and aligned text need to be offset 102e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (paint.isVerticalText()) { 103e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkScalar h = bbox.fBottom - bbox.fTop; 104e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 105e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop -= h / 2; 106e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom -= h / 2; 107e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 108e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // Pad top and bottom with max extents from FontMetrics 109e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom += metrics.fBottom; 110e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop += metrics.fTop; 111e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } else { 112e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkScalar w = bbox.fRight - bbox.fLeft; 113e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 114e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft -= w / 2; 115e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight -= w / 2; 116e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 117e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft -= w; 118e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight -= w; 119e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 120e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // Set vertical bounds to max extents from font metrics 121e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop = metrics.fTop; 122e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom = metrics.fBottom; 123e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 124e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 12504ba448579b976369075c675d847ef0f779d40f4skia.committer@gmail.com // Pad horizontal bounds on each side by half of max vertical extents (this is sort of 126e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // arbitrary, but seems to produce reasonable results, if there were a way of getting max 127e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem 128e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // incorrect on most platforms (too small in Linux, never even set in Windows). 129e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkScalar pad = (metrics.fBottom - metrics.fTop) / 2; 130e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft -= pad; 131e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight += pad; 132e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 133e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft += x; 134e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight += x; 135e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop += y; 136e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom += y; 137e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 138e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com INHERITED::onDrawText(text, byteLength, x, y, paint); 139e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 140e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 141e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 142e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 143e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPaint* paint) { 144e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()}; 145e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, paint)) { 146e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawBitmap(bitmap, left, top, paint); 147e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 148e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 149e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 1507112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, 151eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org const SkRect& dst, const SkPaint* paint, 152eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org DrawBitmapRectFlags flags) { 153e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(dst, paint)) { 154eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags); 155e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 156e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 157e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 158e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat, 159e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPaint* paint) { 160e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkMatrix m = mat; 161ec0aa764ebe36aecdfb77286d665fccc85ab204ageorge@mozilla.com SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())}; 162e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com m.mapRect(&bbox); 163e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, paint)) { 164e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawBitmapMatrix(bitmap, mat, paint); 165e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 166e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 167e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 168e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 169e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkRect& dst, const SkPaint* paint) { 170e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(dst, paint)) { 171e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawBitmapNine(bitmap, center, dst, paint); 172e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 173e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 174e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 175300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// Hack to work-around https://code.google.com/p/chromium/issues/detail?id=373785 176300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// This logic assums that 'pad' is enough to add to the left and right to account for 177300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// big glyphs. For the font in question (a logo font) the glyphs is much wider than just 178300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// the pointsize (approx 3x wider). 179300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// As a temp work-around, we scale-up pad. 180300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// A more correct fix might be to add fontmetrics.fMaxX, but we don't have that value in hand 181300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// at the moment, and (possibly) the value in the font may not be accurate (but who knows). 182300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org// 183300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.orgstatic SkScalar hack_373785_amend_pad(SkScalar pad) { 184300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org return pad * 4; 185300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org} 186300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org 187e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkBBoxRecord::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 188e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com const SkPaint& paint) { 189e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox; 190e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.set(pos, paint.countText(text, byteLength)); 191e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkPaint::FontMetrics metrics; 192e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com paint.getFontMetrics(&metrics); 193e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop += metrics.fTop; 194e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom += metrics.fBottom; 195e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 196e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // pad on left and right by half of max vertical glyph extents 197e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkScalar pad = (metrics.fTop - metrics.fBottom) / 2; 198300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org pad = hack_373785_amend_pad(pad); 199e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft += pad; 200e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight -= pad; 201e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 202e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 203e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com INHERITED::onDrawPosText(text, byteLength, pos, paint); 204e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 205e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 206e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 207e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkBBoxRecord::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 208e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com SkScalar constY, const SkPaint& paint) { 209e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com size_t numChars = paint.countText(text, byteLength); 210cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org if (numChars == 0) { 211cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org return; 212cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org } 213cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 214cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org const SkFlatData* flatPaintData = this->getFlatPaintData(paint); 215cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org WriteTopBot(paint, *flatPaintData); 216cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 217cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org SkScalar top = flatPaintData->topBot()[0]; 218cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org SkScalar bottom = flatPaintData->topBot()[1]; 219cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org SkScalar pad = top - bottom; 220cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 221cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org SkRect bbox; 222cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fLeft = SK_ScalarMax; 223cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fRight = SK_ScalarMin; 224cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 225cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org for (size_t i = 0; i < numChars; ++i) { 226cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org if (xpos[i] < bbox.fLeft) { 227cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fLeft = xpos[i]; 228e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 229cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org if (xpos[i] > bbox.fRight) { 230cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fRight = xpos[i]; 231e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 232e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 233cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 234cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org // pad horizontally by max glyph height 235300790e228751661e1245c774b967b6cc50ffa1bcommit-bot@chromium.org pad = hack_373785_amend_pad(pad); 236cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fLeft += pad; 237cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fRight -= pad; 238cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 239cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fTop = top + constY; 240cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org bbox.fBottom = bottom + constY; 241cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org 242cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org if (!this->transformBounds(bbox, &paint)) { 243cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org return; 244cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org } 245cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org // This is the equivalent of calling: 246cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org // INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint); 247cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org // but we filled our flat paint beforehand so that we could get font metrics. 248cf7be95b19f283e3c5410f977474f433a1e10dadcommit-bot@chromium.org drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData); 249e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 250e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 251e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top, 252e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPaint* paint) { 25378c0c30987075821547979de55200c32bcaa3e49junov@chromium.org SkRect bbox; 25478c0c30987075821547979de55200c32bcaa3e49junov@chromium.org bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height())); 255e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com this->handleBBox(bbox); // directly call handleBBox, matrix is ignored 25678c0c30987075821547979de55200c32bcaa3e49junov@chromium.org INHERITED::drawSprite(bitmap, left, top, paint); 257e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 258e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 259e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkBBoxRecord::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 260e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com const SkMatrix* matrix, const SkPaint& paint) { 261e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox = path.getBounds(); 262e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkPaint::FontMetrics metrics; 263e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com paint.getFontMetrics(&metrics); 264e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 265e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // pad out all sides by the max glyph height above baseline 266e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkScalar pad = metrics.fTop; 267e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fLeft += pad; 268e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fRight -= pad; 269e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fTop += pad; 270e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.fBottom -= pad; 271e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 272e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 273e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint); 274e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 275e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 276e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 277b7425173f96e93b090787e2386ba5f022b6c2869fmalitavoid SkBBoxRecord::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 278b7425173f96e93b090787e2386ba5f022b6c2869fmalita const SkPaint& paint) { 279b7425173f96e93b090787e2386ba5f022b6c2869fmalita SkRect bbox = blob->bounds(); 280b7425173f96e93b090787e2386ba5f022b6c2869fmalita bbox.offset(x, y); 281b7425173f96e93b090787e2386ba5f022b6c2869fmalita // FIXME: implement implicit blob bounds! 282b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (bbox.isEmpty()) { 283b7425173f96e93b090787e2386ba5f022b6c2869fmalita this->getClipBounds(&bbox); 284b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 285b7425173f96e93b090787e2386ba5f022b6c2869fmalita 286b7425173f96e93b090787e2386ba5f022b6c2869fmalita if (this->transformBounds(bbox, &paint)) { 287b7425173f96e93b090787e2386ba5f022b6c2869fmalita INHERITED::onDrawTextBlob(blob, x, y, paint); 288b7425173f96e93b090787e2386ba5f022b6c2869fmalita } 289b7425173f96e93b090787e2386ba5f022b6c2869fmalita} 290b7425173f96e93b090787e2386ba5f022b6c2869fmalita 291e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.comvoid SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount, 292e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPoint vertices[], const SkPoint texs[], 293e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkColor colors[], SkXfermode* xfer, 294e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const uint16_t indices[], int indexCount, 295e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com const SkPaint& paint) { 296e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect bbox; 297e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com bbox.set(vertices, vertexCount); 298e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (this->transformBounds(bbox, &paint)) { 299e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com INHERITED::drawVertices(mode, vertexCount, vertices, texs, 300e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com colors, xfer, indices, indexCount, paint); 301e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 302e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 303e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 304b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkBBoxRecord::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 305b3c9d1c33caf325aada244204215eb790c228c12dandov const SkPoint texCoords[4], SkXfermode* xmode, 306b3c9d1c33caf325aada244204215eb790c228c12dandov const SkPaint& paint) { 307963137b75c0a1fe91f35e9826742f36309f5e65ddandov SkRect bbox; 308b3c9d1c33caf325aada244204215eb790c228c12dandov bbox.set(cubics, SkPatchUtils::kNumCtrlPts); 309963137b75c0a1fe91f35e9826742f36309f5e65ddandov if (this->transformBounds(bbox, &paint)) { 310b3c9d1c33caf325aada244204215eb790c228c12dandov INHERITED::onDrawPatch(cubics, colors, texCoords, xmode, paint); 311963137b75c0a1fe91f35e9826742f36309f5e65ddandov } 312963137b75c0a1fe91f35e9826742f36309f5e65ddandov} 313963137b75c0a1fe91f35e9826742f36309f5e65ddandov 314d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkBBoxRecord::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 315d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed const SkPaint* paint) { 316a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips SkRect bounds = picture->cullRect(); 317d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed // todo: wonder if we should allow passing an optional matrix to transformBounds so we don't 318d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed // end up transforming the rect twice. 319d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed if (matrix) { 320d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed matrix->mapRect(&bounds); 321d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed } 322d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed if (this->transformBounds(bounds, paint)) { 323d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed this->INHERITED::onDrawPicture(picture, matrix, paint); 324e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 325e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 326e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 327837f5321a409228a27fc710eb71c87866b820cfbsenorblancovoid SkBBoxRecord::willSave() { 328837f5321a409228a27fc710eb71c87866b820cfbsenorblanco fSaveStack.push(NULL); 329837f5321a409228a27fc710eb71c87866b820cfbsenorblanco this->INHERITED::willSave(); 330837f5321a409228a27fc710eb71c87866b820cfbsenorblanco} 331837f5321a409228a27fc710eb71c87866b820cfbsenorblanco 332837f5321a409228a27fc710eb71c87866b820cfbsenorblancoSkCanvas::SaveLayerStrategy SkBBoxRecord::willSaveLayer(const SkRect* bounds, 333837f5321a409228a27fc710eb71c87866b820cfbsenorblanco const SkPaint* paint, 334837f5321a409228a27fc710eb71c87866b820cfbsenorblanco SaveFlags flags) { 335837f5321a409228a27fc710eb71c87866b820cfbsenorblanco // Image filters can affect the effective bounds of primitives drawn inside saveLayer(). 336837f5321a409228a27fc710eb71c87866b820cfbsenorblanco // Copy the paint so we can compute the modified bounds in transformBounds(). 337837f5321a409228a27fc710eb71c87866b820cfbsenorblanco fSaveStack.push(paint && paint->getImageFilter() ? new SkPaint(*paint) : NULL); 338837f5321a409228a27fc710eb71c87866b820cfbsenorblanco return this->INHERITED::willSaveLayer(bounds, paint, flags); 339837f5321a409228a27fc710eb71c87866b820cfbsenorblanco} 340837f5321a409228a27fc710eb71c87866b820cfbsenorblanco 341837f5321a409228a27fc710eb71c87866b820cfbsenorblancovoid SkBBoxRecord::willRestore() { 342837f5321a409228a27fc710eb71c87866b820cfbsenorblanco delete fSaveStack.top(); 343837f5321a409228a27fc710eb71c87866b820cfbsenorblanco fSaveStack.pop(); 344837f5321a409228a27fc710eb71c87866b820cfbsenorblanco this->INHERITED::willRestore(); 345837f5321a409228a27fc710eb71c87866b820cfbsenorblanco} 346837f5321a409228a27fc710eb71c87866b820cfbsenorblanco 347e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.combool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) { 348e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect outBounds = bounds; 3496006b5641e575181f2d6f1212b8db491b2c2671cjunov@chromium.org outBounds.sort(); 350e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 351e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (paint) { 352e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // account for stroking, path effects, shadows, etc 353e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (paint->canComputeFastBounds()) { 354e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com SkRect temp; 3556006b5641e575181f2d6f1212b8db491b2c2671cjunov@chromium.org outBounds = paint->computeFastBounds(outBounds, &temp); 356e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } else { 357e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // set bounds to current clip 358e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com if (!this->getClipBounds(&outBounds)) { 359e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com // current clip is empty 360e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com return false; 361e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 362e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 363e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 364e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 365837f5321a409228a27fc710eb71c87866b820cfbsenorblanco for (int i = fSaveStack.count() - 1; i >= 0; --i) { 366837f5321a409228a27fc710eb71c87866b820cfbsenorblanco const SkPaint* paint = fSaveStack.getAt(i); 367837f5321a409228a27fc710eb71c87866b820cfbsenorblanco if (paint && paint->canComputeFastBounds()) { 368837f5321a409228a27fc710eb71c87866b820cfbsenorblanco SkRect temp; 369837f5321a409228a27fc710eb71c87866b820cfbsenorblanco outBounds = paint->computeFastBounds(outBounds, &temp); 370837f5321a409228a27fc710eb71c87866b820cfbsenorblanco } 371837f5321a409228a27fc710eb71c87866b820cfbsenorblanco } 372837f5321a409228a27fc710eb71c87866b820cfbsenorblanco 37359a6a2b98302adc4732fc26873043bad1a94e9f1bungeman@google.com if (!outBounds.isEmpty() && !this->quickReject(outBounds)) { 374e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com this->getTotalMatrix().mapRect(&outBounds); 375e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com this->handleBBox(outBounds); 376e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com return true; 377e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com } 378e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com 379e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com return false; 380e0201a4448f5e770cc081ca3425bed528af27f8drileya@google.com} 381