Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | |
michael@0 | 2 | /* |
michael@0 | 3 | * Copyright 2012 Google Inc. |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | #include "SkBBoxRecord.h" |
michael@0 | 10 | |
michael@0 | 11 | void SkBBoxRecord::drawOval(const SkRect& rect, const SkPaint& paint) { |
michael@0 | 12 | if (this->transformBounds(rect, &paint)) { |
michael@0 | 13 | INHERITED::drawOval(rect, paint); |
michael@0 | 14 | } |
michael@0 | 15 | } |
michael@0 | 16 | |
michael@0 | 17 | void SkBBoxRecord::drawRRect(const SkRRect& rrect, const SkPaint& paint) { |
michael@0 | 18 | if (this->transformBounds(rrect.rect(), &paint)) { |
michael@0 | 19 | INHERITED::drawRRect(rrect, paint); |
michael@0 | 20 | } |
michael@0 | 21 | } |
michael@0 | 22 | |
michael@0 | 23 | void SkBBoxRecord::drawRect(const SkRect& rect, const SkPaint& paint) { |
michael@0 | 24 | if (this->transformBounds(rect, &paint)) { |
michael@0 | 25 | INHERITED::drawRect(rect, paint); |
michael@0 | 26 | } |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | void SkBBoxRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, |
michael@0 | 30 | const SkPaint& paint) { |
michael@0 | 31 | if (this->transformBounds(outer.rect(), &paint)) { |
michael@0 | 32 | this->INHERITED::onDrawDRRect(outer, inner, paint); |
michael@0 | 33 | } |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | void SkBBoxRecord::drawPath(const SkPath& path, const SkPaint& paint) { |
michael@0 | 37 | if (path.isInverseFillType()) { |
michael@0 | 38 | // If path is inverse filled, use the current clip bounds as the |
michael@0 | 39 | // path's device-space bounding box. |
michael@0 | 40 | SkIRect clipBounds; |
michael@0 | 41 | if (this->getClipDeviceBounds(&clipBounds)) { |
michael@0 | 42 | this->handleBBox(SkRect::Make(clipBounds)); |
michael@0 | 43 | INHERITED::drawPath(path, paint); |
michael@0 | 44 | } |
michael@0 | 45 | } else if (this->transformBounds(path.getBounds(), &paint)) { |
michael@0 | 46 | INHERITED::drawPath(path, paint); |
michael@0 | 47 | } |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | void SkBBoxRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts[], |
michael@0 | 51 | const SkPaint& paint) { |
michael@0 | 52 | SkRect bbox; |
michael@0 | 53 | bbox.set(pts, SkToInt(count)); |
michael@0 | 54 | // Small min width value, just to ensure hairline point bounding boxes aren't empty. |
michael@0 | 55 | // Even though we know hairline primitives are drawn one pixel wide, we do not use a |
michael@0 | 56 | // minimum of 1 because the playback scale factor is unknown at record time. Later |
michael@0 | 57 | // outsets will take care of adding additional padding for antialiasing and rounding out |
michael@0 | 58 | // to integer device coordinates, guaranteeing that the rasterized pixels will be included |
michael@0 | 59 | // in the computed bounds. |
michael@0 | 60 | // Note: The device coordinate outset in SkBBoxHierarchyRecord::handleBBox is currently |
michael@0 | 61 | // done in the recording coordinate space, which is wrong. |
michael@0 | 62 | // http://code.google.com/p/skia/issues/detail?id=1021 |
michael@0 | 63 | static const SkScalar kMinWidth = 0.01f; |
michael@0 | 64 | SkScalar halfStrokeWidth = SkMaxScalar(paint.getStrokeWidth(), kMinWidth) / 2; |
michael@0 | 65 | bbox.outset(halfStrokeWidth, halfStrokeWidth); |
michael@0 | 66 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 67 | INHERITED::drawPoints(mode, count, pts, paint); |
michael@0 | 68 | } |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | void SkBBoxRecord::drawPaint(const SkPaint& paint) { |
michael@0 | 72 | SkRect bbox; |
michael@0 | 73 | if (this->getClipBounds(&bbox)) { |
michael@0 | 74 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 75 | INHERITED::drawPaint(paint); |
michael@0 | 76 | } |
michael@0 | 77 | } |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | void SkBBoxRecord::clear(SkColor color) { |
michael@0 | 81 | SkISize size = this->getDeviceSize(); |
michael@0 | 82 | SkRect bbox = {0, 0, SkIntToScalar(size.width()), SkIntToScalar(size.height())}; |
michael@0 | 83 | this->handleBBox(bbox); |
michael@0 | 84 | INHERITED::clear(color); |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | void SkBBoxRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, |
michael@0 | 88 | const SkPaint& paint) { |
michael@0 | 89 | SkRect bbox; |
michael@0 | 90 | paint.measureText(text, byteLength, &bbox); |
michael@0 | 91 | SkPaint::FontMetrics metrics; |
michael@0 | 92 | paint.getFontMetrics(&metrics); |
michael@0 | 93 | |
michael@0 | 94 | // Vertical and aligned text need to be offset |
michael@0 | 95 | if (paint.isVerticalText()) { |
michael@0 | 96 | SkScalar h = bbox.fBottom - bbox.fTop; |
michael@0 | 97 | if (paint.getTextAlign() == SkPaint::kCenter_Align) { |
michael@0 | 98 | bbox.fTop -= h / 2; |
michael@0 | 99 | bbox.fBottom -= h / 2; |
michael@0 | 100 | } |
michael@0 | 101 | // Pad top and bottom with max extents from FontMetrics |
michael@0 | 102 | bbox.fBottom += metrics.fBottom; |
michael@0 | 103 | bbox.fTop += metrics.fTop; |
michael@0 | 104 | } else { |
michael@0 | 105 | SkScalar w = bbox.fRight - bbox.fLeft; |
michael@0 | 106 | if (paint.getTextAlign() == SkPaint::kCenter_Align) { |
michael@0 | 107 | bbox.fLeft -= w / 2; |
michael@0 | 108 | bbox.fRight -= w / 2; |
michael@0 | 109 | } else if (paint.getTextAlign() == SkPaint::kRight_Align) { |
michael@0 | 110 | bbox.fLeft -= w; |
michael@0 | 111 | bbox.fRight -= w; |
michael@0 | 112 | } |
michael@0 | 113 | // Set vertical bounds to max extents from font metrics |
michael@0 | 114 | bbox.fTop = metrics.fTop; |
michael@0 | 115 | bbox.fBottom = metrics.fBottom; |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | // Pad horizontal bounds on each side by half of max vertical extents (this is sort of |
michael@0 | 119 | // arbitrary, but seems to produce reasonable results, if there were a way of getting max |
michael@0 | 120 | // glyph X-extents to pad by, that may be better here, but FontMetrics fXMin and fXMax seem |
michael@0 | 121 | // incorrect on most platforms (too small in Linux, never even set in Windows). |
michael@0 | 122 | SkScalar pad = (metrics.fBottom - metrics.fTop) / 2; |
michael@0 | 123 | bbox.fLeft -= pad; |
michael@0 | 124 | bbox.fRight += pad; |
michael@0 | 125 | |
michael@0 | 126 | bbox.fLeft += x; |
michael@0 | 127 | bbox.fRight += x; |
michael@0 | 128 | bbox.fTop += y; |
michael@0 | 129 | bbox.fBottom += y; |
michael@0 | 130 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 131 | INHERITED::drawText(text, byteLength, x, y, paint); |
michael@0 | 132 | } |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | void SkBBoxRecord::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, |
michael@0 | 136 | const SkPaint* paint) { |
michael@0 | 137 | SkRect bbox = {left, top, left + bitmap.width(), top + bitmap.height()}; |
michael@0 | 138 | if (this->transformBounds(bbox, paint)) { |
michael@0 | 139 | INHERITED::drawBitmap(bitmap, left, top, paint); |
michael@0 | 140 | } |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | void SkBBoxRecord::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, |
michael@0 | 144 | const SkRect& dst, const SkPaint* paint, |
michael@0 | 145 | DrawBitmapRectFlags flags) { |
michael@0 | 146 | if (this->transformBounds(dst, paint)) { |
michael@0 | 147 | INHERITED::drawBitmapRectToRect(bitmap, src, dst, paint, flags); |
michael@0 | 148 | } |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | void SkBBoxRecord::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& mat, |
michael@0 | 152 | const SkPaint* paint) { |
michael@0 | 153 | SkMatrix m = mat; |
michael@0 | 154 | SkRect bbox = {0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())}; |
michael@0 | 155 | m.mapRect(&bbox); |
michael@0 | 156 | if (this->transformBounds(bbox, paint)) { |
michael@0 | 157 | INHERITED::drawBitmapMatrix(bitmap, mat, paint); |
michael@0 | 158 | } |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | void SkBBoxRecord::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, |
michael@0 | 162 | const SkRect& dst, const SkPaint* paint) { |
michael@0 | 163 | if (this->transformBounds(dst, paint)) { |
michael@0 | 164 | INHERITED::drawBitmapNine(bitmap, center, dst, paint); |
michael@0 | 165 | } |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | void SkBBoxRecord::drawPosText(const void* text, size_t byteLength, |
michael@0 | 169 | const SkPoint pos[], const SkPaint& paint) { |
michael@0 | 170 | SkRect bbox; |
michael@0 | 171 | bbox.set(pos, paint.countText(text, byteLength)); |
michael@0 | 172 | SkPaint::FontMetrics metrics; |
michael@0 | 173 | paint.getFontMetrics(&metrics); |
michael@0 | 174 | bbox.fTop += metrics.fTop; |
michael@0 | 175 | bbox.fBottom += metrics.fBottom; |
michael@0 | 176 | |
michael@0 | 177 | // pad on left and right by half of max vertical glyph extents |
michael@0 | 178 | SkScalar pad = (metrics.fTop - metrics.fBottom) / 2; |
michael@0 | 179 | bbox.fLeft += pad; |
michael@0 | 180 | bbox.fRight -= pad; |
michael@0 | 181 | |
michael@0 | 182 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 183 | INHERITED::drawPosText(text, byteLength, pos, paint); |
michael@0 | 184 | } |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | void SkBBoxRecord::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], |
michael@0 | 188 | SkScalar constY, const SkPaint& paint) { |
michael@0 | 189 | size_t numChars = paint.countText(text, byteLength); |
michael@0 | 190 | if (numChars == 0) { |
michael@0 | 191 | return; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | const SkFlatData* flatPaintData = this->getFlatPaintData(paint); |
michael@0 | 195 | WriteTopBot(paint, *flatPaintData); |
michael@0 | 196 | |
michael@0 | 197 | SkScalar top = flatPaintData->topBot()[0]; |
michael@0 | 198 | SkScalar bottom = flatPaintData->topBot()[1]; |
michael@0 | 199 | SkScalar pad = top - bottom; |
michael@0 | 200 | |
michael@0 | 201 | SkRect bbox; |
michael@0 | 202 | bbox.fLeft = SK_ScalarMax; |
michael@0 | 203 | bbox.fRight = SK_ScalarMin; |
michael@0 | 204 | |
michael@0 | 205 | for (size_t i = 0; i < numChars; ++i) { |
michael@0 | 206 | if (xpos[i] < bbox.fLeft) { |
michael@0 | 207 | bbox.fLeft = xpos[i]; |
michael@0 | 208 | } |
michael@0 | 209 | if (xpos[i] > bbox.fRight) { |
michael@0 | 210 | bbox.fRight = xpos[i]; |
michael@0 | 211 | } |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | // pad horizontally by max glyph height |
michael@0 | 215 | bbox.fLeft += pad; |
michael@0 | 216 | bbox.fRight -= pad; |
michael@0 | 217 | |
michael@0 | 218 | bbox.fTop = top + constY; |
michael@0 | 219 | bbox.fBottom = bottom + constY; |
michael@0 | 220 | |
michael@0 | 221 | if (!this->transformBounds(bbox, &paint)) { |
michael@0 | 222 | return; |
michael@0 | 223 | } |
michael@0 | 224 | // This is the equivalent of calling: |
michael@0 | 225 | // INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint); |
michael@0 | 226 | // but we filled our flat paint beforehand so that we could get font metrics. |
michael@0 | 227 | drawPosTextHImpl(text, byteLength, xpos, constY, paint, flatPaintData); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | void SkBBoxRecord::drawSprite(const SkBitmap& bitmap, int left, int top, |
michael@0 | 231 | const SkPaint* paint) { |
michael@0 | 232 | SkRect bbox; |
michael@0 | 233 | bbox.set(SkIRect::MakeXYWH(left, top, bitmap.width(), bitmap.height())); |
michael@0 | 234 | this->handleBBox(bbox); // directly call handleBBox, matrix is ignored |
michael@0 | 235 | INHERITED::drawSprite(bitmap, left, top, paint); |
michael@0 | 236 | } |
michael@0 | 237 | |
michael@0 | 238 | void SkBBoxRecord::drawTextOnPath(const void* text, size_t byteLength, |
michael@0 | 239 | const SkPath& path, const SkMatrix* matrix, |
michael@0 | 240 | const SkPaint& paint) { |
michael@0 | 241 | SkRect bbox = path.getBounds(); |
michael@0 | 242 | SkPaint::FontMetrics metrics; |
michael@0 | 243 | paint.getFontMetrics(&metrics); |
michael@0 | 244 | |
michael@0 | 245 | // pad out all sides by the max glyph height above baseline |
michael@0 | 246 | SkScalar pad = metrics.fTop; |
michael@0 | 247 | bbox.fLeft += pad; |
michael@0 | 248 | bbox.fRight -= pad; |
michael@0 | 249 | bbox.fTop += pad; |
michael@0 | 250 | bbox.fBottom -= pad; |
michael@0 | 251 | |
michael@0 | 252 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 253 | INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint); |
michael@0 | 254 | } |
michael@0 | 255 | } |
michael@0 | 256 | |
michael@0 | 257 | void SkBBoxRecord::drawVertices(VertexMode mode, int vertexCount, |
michael@0 | 258 | const SkPoint vertices[], const SkPoint texs[], |
michael@0 | 259 | const SkColor colors[], SkXfermode* xfer, |
michael@0 | 260 | const uint16_t indices[], int indexCount, |
michael@0 | 261 | const SkPaint& paint) { |
michael@0 | 262 | SkRect bbox; |
michael@0 | 263 | bbox.set(vertices, vertexCount); |
michael@0 | 264 | if (this->transformBounds(bbox, &paint)) { |
michael@0 | 265 | INHERITED::drawVertices(mode, vertexCount, vertices, texs, |
michael@0 | 266 | colors, xfer, indices, indexCount, paint); |
michael@0 | 267 | } |
michael@0 | 268 | } |
michael@0 | 269 | |
michael@0 | 270 | void SkBBoxRecord::drawPicture(SkPicture& picture) { |
michael@0 | 271 | if (picture.width() > 0 && picture.height() > 0 && |
michael@0 | 272 | this->transformBounds(SkRect::MakeWH(picture.width(), picture.height()), NULL)) { |
michael@0 | 273 | INHERITED::drawPicture(picture); |
michael@0 | 274 | } |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | bool SkBBoxRecord::transformBounds(const SkRect& bounds, const SkPaint* paint) { |
michael@0 | 278 | SkRect outBounds = bounds; |
michael@0 | 279 | outBounds.sort(); |
michael@0 | 280 | |
michael@0 | 281 | if (paint) { |
michael@0 | 282 | // account for stroking, path effects, shadows, etc |
michael@0 | 283 | if (paint->canComputeFastBounds()) { |
michael@0 | 284 | SkRect temp; |
michael@0 | 285 | outBounds = paint->computeFastBounds(outBounds, &temp); |
michael@0 | 286 | } else { |
michael@0 | 287 | // set bounds to current clip |
michael@0 | 288 | if (!this->getClipBounds(&outBounds)) { |
michael@0 | 289 | // current clip is empty |
michael@0 | 290 | return false; |
michael@0 | 291 | } |
michael@0 | 292 | } |
michael@0 | 293 | } |
michael@0 | 294 | |
michael@0 | 295 | if (!outBounds.isEmpty() && !this->quickReject(outBounds)) { |
michael@0 | 296 | this->getTotalMatrix().mapRect(&outBounds); |
michael@0 | 297 | this->handleBBox(outBounds); |
michael@0 | 298 | return true; |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | return false; |
michael@0 | 302 | } |