| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2014 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #ifndef SkGatherPixelRefsAndRects_DEFINED | |
| 9 #define SkGatherPixelRefsAndRects_DEFINED | |
| 10 | |
| 11 #include "SkBitmap.h" | |
| 12 #include "SkDevice.h" | |
| 13 #include "SkDraw.h" | |
| 14 #include "SkPictureUtils.h" | |
| 15 #include "SkRasterClip.h" | |
| 16 #include "SkRefCnt.h" | |
| 17 #include "SkRRect.h" | |
| 18 #include "SkTypes.h" | |
| 19 | |
| 20 // This GatherPixelRefs device passes all discovered pixel refs and their | |
| 21 // device bounds to the user provided SkPixelRefContainer-derived object | |
| 22 class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice { | |
| 23 public: | |
| 24 SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice) | |
| 25 | |
| 26 SkGatherPixelRefsAndRectsDevice(int width, int height, | |
| 27 SkPictureUtils::SkPixelRefContainer* prCont)
{ | |
| 28 fSize.set(width, height); | |
| 29 fPRCont = prCont; | |
| 30 SkSafeRef(fPRCont); | |
| 31 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); | |
| 32 } | |
| 33 | |
| 34 virtual ~SkGatherPixelRefsAndRectsDevice() { | |
| 35 SkSafeUnref(fPRCont); | |
| 36 } | |
| 37 | |
| 38 SkImageInfo imageInfo() const SK_OVERRIDE { | |
| 39 return fEmptyBitmap.info(); | |
| 40 } | |
| 41 | |
| 42 protected: | |
| 43 void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE { | |
| 44 SkBitmap bm; | |
| 45 | |
| 46 if (GetBitmapFromPaint(paint, &bm)) { | |
| 47 SkRect clipRect = SkRect::Make(draw.fRC->getBounds()); | |
| 48 fPRCont->add(bm.pixelRef(), clipRect); | |
| 49 } | |
| 50 } | |
| 51 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t
count, | |
| 52 const SkPoint points[], const SkPaint& paint) SK_OVE
RRIDE { | |
| 53 SkBitmap bm; | |
| 54 if (!GetBitmapFromPaint(paint, &bm)) { | |
| 55 return; | |
| 56 } | |
| 57 | |
| 58 if (0 == count) { | |
| 59 return; | |
| 60 } | |
| 61 | |
| 62 SkPoint min = points[0]; | |
| 63 SkPoint max = points[0]; | |
| 64 for (size_t i = 1; i < count; ++i) { | |
| 65 const SkPoint& point = points[i]; | |
| 66 | |
| 67 min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.
y())); | |
| 68 max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.
y())); | |
| 69 } | |
| 70 | |
| 71 SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1)
; | |
| 72 | |
| 73 this->drawRect(draw, bounds, paint); | |
| 74 } | |
| 75 virtual void drawRect(const SkDraw& draw, const SkRect& rect, | |
| 76 const SkPaint& paint) SK_OVERRIDE { | |
| 77 SkBitmap bm; | |
| 78 if (GetBitmapFromPaint(paint, &bm)) { | |
| 79 SkRect mappedRect; | |
| 80 draw.fMatrix->mapRect(&mappedRect, rect); | |
| 81 SkRect clipRect = SkRect::Make(draw.fRC->getBounds()); | |
| 82 if (mappedRect.intersect(clipRect)) { | |
| 83 fPRCont->add(bm.pixelRef(), mappedRect); | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 virtual void drawOval(const SkDraw& draw, const SkRect& rect, | |
| 88 const SkPaint& paint) SK_OVERRIDE { | |
| 89 this->drawRect(draw, rect, paint); | |
| 90 } | |
| 91 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect, | |
| 92 const SkPaint& paint) SK_OVERRIDE { | |
| 93 this->drawRect(draw, rrect.rect(), paint); | |
| 94 } | |
| 95 virtual void drawPath(const SkDraw& draw, const SkPath& path, | |
| 96 const SkPaint& paint, const SkMatrix* prePathMatrix, | |
| 97 bool pathIsMutable) SK_OVERRIDE { | |
| 98 SkBitmap bm; | |
| 99 if (!GetBitmapFromPaint(paint, &bm)) { | |
| 100 return; | |
| 101 } | |
| 102 | |
| 103 SkRect pathBounds = path.getBounds(); | |
| 104 if (prePathMatrix) { | |
| 105 prePathMatrix->mapRect(&pathBounds); | |
| 106 } | |
| 107 | |
| 108 this->drawRect(draw, pathBounds, paint); | |
| 109 } | |
| 110 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, | |
| 111 const SkMatrix& matrix, const SkPaint& paint) SK_OVE
RRIDE { | |
| 112 SkMatrix totMatrix; | |
| 113 totMatrix.setConcat(*draw.fMatrix, matrix); | |
| 114 | |
| 115 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), | |
| 116 SkIntToScalar(bitmap.height())); | |
| 117 SkRect mappedRect; | |
| 118 totMatrix.mapRect(&mappedRect, bitmapRect); | |
| 119 fPRCont->add(bitmap.pixelRef(), mappedRect); | |
| 120 | |
| 121 SkBitmap paintBitmap; | |
| 122 if (GetBitmapFromPaint(paint, &paintBitmap)) { | |
| 123 fPRCont->add(paintBitmap.pixelRef(), mappedRect); | |
| 124 } | |
| 125 } | |
| 126 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, | |
| 127 int x, int y, const SkPaint& paint) SK_OVERRIDE { | |
| 128 // Sprites aren't affected by current matrix, so we can't reuse drawRect
. | |
| 129 SkMatrix matrix; | |
| 130 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | |
| 131 | |
| 132 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), | |
| 133 SkIntToScalar(bitmap.height())); | |
| 134 SkRect mappedRect; | |
| 135 matrix.mapRect(&mappedRect, bitmapRect); | |
| 136 fPRCont->add(bitmap.pixelRef(), mappedRect); | |
| 137 | |
| 138 SkBitmap paintBitmap; | |
| 139 if (GetBitmapFromPaint(paint, &paintBitmap)) { | |
| 140 fPRCont->add(paintBitmap.pixelRef(), mappedRect); | |
| 141 } | |
| 142 } | |
| 143 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, | |
| 144 const SkRect* srcOrNull, const SkRect& dst, | |
| 145 const SkPaint& paint, | |
| 146 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE
{ | |
| 147 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), | |
| 148 SkIntToScalar(bitmap.height())); | |
| 149 SkMatrix matrix; | |
| 150 matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit); | |
| 151 this->drawBitmap(draw, bitmap, matrix, paint); | |
| 152 } | |
| 153 virtual void drawText(const SkDraw& draw, const void* text, size_t len, | |
| 154 SkScalar x, SkScalar y, | |
| 155 const SkPaint& paint) SK_OVERRIDE { | |
| 156 SkBitmap bitmap; | |
| 157 if (!GetBitmapFromPaint(paint, &bitmap)) { | |
| 158 return; | |
| 159 } | |
| 160 | |
| 161 // Math is borrowed from SkBBoxRecord | |
| 162 SkRect bounds; | |
| 163 paint.measureText(text, len, &bounds); | |
| 164 SkPaint::FontMetrics metrics; | |
| 165 paint.getFontMetrics(&metrics); | |
| 166 | |
| 167 if (paint.isVerticalText()) { | |
| 168 SkScalar h = bounds.fBottom - bounds.fTop; | |
| 169 if (paint.getTextAlign() == SkPaint::kCenter_Align) { | |
| 170 bounds.fTop -= h / 2; | |
| 171 bounds.fBottom -= h / 2; | |
| 172 } | |
| 173 bounds.fBottom += metrics.fBottom; | |
| 174 bounds.fTop += metrics.fTop; | |
| 175 } else { | |
| 176 SkScalar w = bounds.fRight - bounds.fLeft; | |
| 177 if (paint.getTextAlign() == SkPaint::kCenter_Align) { | |
| 178 bounds.fLeft -= w / 2; | |
| 179 bounds.fRight -= w / 2; | |
| 180 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { | |
| 181 bounds.fLeft -= w; | |
| 182 bounds.fRight -= w; | |
| 183 } | |
| 184 bounds.fTop = metrics.fTop; | |
| 185 bounds.fBottom = metrics.fBottom; | |
| 186 } | |
| 187 | |
| 188 SkScalar pad = (metrics.fBottom - metrics.fTop) / 2; | |
| 189 bounds.fLeft -= pad; | |
| 190 bounds.fRight += pad; | |
| 191 bounds.offset(x, y); | |
| 192 | |
| 193 this->drawRect(draw, bounds, paint); | |
| 194 } | |
| 195 virtual void drawPosText(const SkDraw& draw, const void* text, size_t len, | |
| 196 const SkScalar pos[], int scalarsPerPos, | |
| 197 const SkPoint& offset, const SkPaint& paint) SK_OVE
RRIDE { | |
| 198 SkBitmap bitmap; | |
| 199 if (!GetBitmapFromPaint(paint, &bitmap)) { | |
| 200 return; | |
| 201 } | |
| 202 | |
| 203 if (0 == len) { | |
| 204 return; | |
| 205 } | |
| 206 | |
| 207 // Similar to SkDraw asserts. | |
| 208 SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2); | |
| 209 | |
| 210 SkPoint min = SkPoint::Make(offset.x() + pos[0], | |
| 211 offset.y() + (2 == scalarsPerPos ? pos[1] :
0)); | |
| 212 SkPoint max = min; | |
| 213 | |
| 214 for (size_t i = 1; i < len; ++i) { | |
| 215 SkScalar x = offset.x() + pos[i * scalarsPerPos]; | |
| 216 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * 2 + 1] : 0); | |
| 217 | |
| 218 min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y())); | |
| 219 max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y())); | |
| 220 } | |
| 221 | |
| 222 SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y()); | |
| 223 | |
| 224 // Math is borrowed from SkBBoxRecord | |
| 225 SkPaint::FontMetrics metrics; | |
| 226 paint.getFontMetrics(&metrics); | |
| 227 | |
| 228 bounds.fTop += metrics.fTop; | |
| 229 bounds.fBottom += metrics.fBottom; | |
| 230 | |
| 231 SkScalar pad = (metrics.fTop - metrics.fBottom) / 2; | |
| 232 bounds.fLeft -= pad; | |
| 233 bounds.fRight += pad; | |
| 234 | |
| 235 this->drawRect(draw, bounds, paint); | |
| 236 } | |
| 237 virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len
, | |
| 238 const SkPath& path, const SkMatrix* matrix, | |
| 239 const SkPaint& paint) SK_OVERRIDE { | |
| 240 SkBitmap bitmap; | |
| 241 if (!GetBitmapFromPaint(paint, &bitmap)) { | |
| 242 return; | |
| 243 } | |
| 244 | |
| 245 // Math is borrowed from SkBBoxRecord | |
| 246 SkRect bounds = path.getBounds(); | |
| 247 SkPaint::FontMetrics metrics; | |
| 248 paint.getFontMetrics(&metrics); | |
| 249 | |
| 250 SkScalar pad = metrics.fTop; | |
| 251 // TODO: inset?! | |
| 252 bounds.fLeft += pad; | |
| 253 bounds.fRight -= pad; | |
| 254 bounds.fTop += pad; | |
| 255 bounds.fBottom -= pad; | |
| 256 | |
| 257 this->drawRect(draw, bounds, paint); | |
| 258 } | |
| 259 virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vert
exCount, | |
| 260 const SkPoint verts[], const SkPoint texs[], | |
| 261 const SkColor colors[], SkXfermode* xmode, | |
| 262 const uint16_t indices[], int indexCount, | |
| 263 const SkPaint& paint) SK_OVERRIDE { | |
| 264 this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts,
paint); | |
| 265 } | |
| 266 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, | |
| 267 const SkPaint&) SK_OVERRIDE { | |
| 268 NothingToDo(); | |
| 269 } | |
| 270 // TODO: allow this call to return failure, or move to SkBitmapDevice only. | |
| 271 const SkBitmap& onAccessBitmap() SK_OVERRIDE { | |
| 272 return fEmptyBitmap; | |
| 273 } | |
| 274 void lockPixels() SK_OVERRIDE { NothingToDo(); } | |
| 275 void unlockPixels() SK_OVERRIDE { NothingToDo(); } | |
| 276 bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } | |
| 277 bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false;
} | |
| 278 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImag
eFilter::Context&, | |
| 279 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { | |
| 280 return false; | |
| 281 } | |
| 282 | |
| 283 private: | |
| 284 SkPictureUtils::SkPixelRefContainer* fPRCont; | |
| 285 SkISize fSize; | |
| 286 | |
| 287 SkBitmap fEmptyBitmap; // legacy -- need to remo
ve | |
| 288 | |
| 289 static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) { | |
| 290 SkShader* shader = paint.getShader(); | |
| 291 if (shader) { | |
| 292 if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) { | |
| 293 return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, N
ULL, NULL); | |
| 294 } | |
| 295 } | |
| 296 return false; | |
| 297 } | |
| 298 | |
| 299 void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE { | |
| 300 NotSupported(); | |
| 301 } | |
| 302 | |
| 303 SkBaseDevice* onCreateCompatibleDevice(const CreateInfo& info) SK_OVERRIDE { | |
| 304 // we expect to only get called via savelayer, in which case it is fine. | |
| 305 SkASSERT(kSaveLayer_Usage == info.fUsage); | |
| 306 return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, | |
| 307 (info.fInfo.width(), info.fInfo.height(), fPRCont)); | |
| 308 } | |
| 309 | |
| 310 static void NotSupported() { | |
| 311 SkDEBUGFAIL("this method should never be called"); | |
| 312 } | |
| 313 | |
| 314 static void NothingToDo() {} | |
| 315 | |
| 316 typedef SkBaseDevice INHERITED; | |
| 317 }; | |
| 318 | |
| 319 #endif // SkGatherPixelRefsAndRects_DEFINED | |
| OLD | NEW |