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 virtual SkImageInfo imageInfo() const SK_OVERRIDE { 39 return fEmptyBitmap.info(); 40 } 41 42 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } 43 44 protected: 45 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE { 46 return false; 47 } 48 virtual void clear(SkColor color) SK_OVERRIDE { 49 NothingToDo(); 50 } 51 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE { 52 SkBitmap bm; 53 54 if (GetBitmapFromPaint(paint, &bm)) { 55 SkRect clipRect = SkRect::Make(draw.fRC->getBounds()); 56 fPRCont->add(bm.pixelRef(), clipRect); 57 } 58 } 59 virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, 60 const SkPoint points[], const SkPaint& paint) SK_OVERRIDE { 61 SkBitmap bm; 62 if (!GetBitmapFromPaint(paint, &bm)) { 63 return; 64 } 65 66 if (0 == count) { 67 return; 68 } 69 70 SkPoint min = points[0]; 71 SkPoint max = points[0]; 72 for (size_t i = 1; i < count; ++i) { 73 const SkPoint& point = points[i]; 74 75 min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y())); 76 max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y())); 77 } 78 79 SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1); 80 81 this->drawRect(draw, bounds, paint); 82 } 83 virtual void drawRect(const SkDraw& draw, const SkRect& rect, 84 const SkPaint& paint) SK_OVERRIDE { 85 SkBitmap bm; 86 if (GetBitmapFromPaint(paint, &bm)) { 87 SkRect mappedRect; 88 draw.fMatrix->mapRect(&mappedRect, rect); 89 SkRect clipRect = SkRect::Make(draw.fRC->getBounds()); 90 mappedRect.intersect(clipRect); 91 fPRCont->add(bm.pixelRef(), mappedRect); 92 } 93 } 94 virtual void drawOval(const SkDraw& draw, const SkRect& rect, 95 const SkPaint& paint) SK_OVERRIDE { 96 this->drawRect(draw, rect, paint); 97 } 98 virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect, 99 const SkPaint& paint) SK_OVERRIDE { 100 this->drawRect(draw, rrect.rect(), paint); 101 } 102 virtual void drawPath(const SkDraw& draw, const SkPath& path, 103 const SkPaint& paint, const SkMatrix* prePathMatrix, 104 bool pathIsMutable) SK_OVERRIDE { 105 SkBitmap bm; 106 if (!GetBitmapFromPaint(paint, &bm)) { 107 return; 108 } 109 110 SkRect pathBounds = path.getBounds(); 111 if (NULL != prePathMatrix) { 112 prePathMatrix->mapRect(&pathBounds); 113 } 114 115 this->drawRect(draw, pathBounds, paint); 116 } 117 virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, 118 const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE { 119 SkMatrix totMatrix; 120 totMatrix.setConcat(*draw.fMatrix, matrix); 121 122 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 123 SkIntToScalar(bitmap.height())); 124 SkRect mappedRect; 125 totMatrix.mapRect(&mappedRect, bitmapRect); 126 fPRCont->add(bitmap.pixelRef(), mappedRect); 127 128 SkBitmap paintBitmap; 129 if (GetBitmapFromPaint(paint, &paintBitmap)) { 130 fPRCont->add(paintBitmap.pixelRef(), mappedRect); 131 } 132 } 133 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 134 int x, int y, const SkPaint& paint) SK_OVERRIDE { 135 // Sprites aren't affected by current matrix, so we can't reuse drawRect. 136 SkMatrix matrix; 137 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 138 139 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 140 SkIntToScalar(bitmap.height())); 141 SkRect mappedRect; 142 matrix.mapRect(&mappedRect, bitmapRect); 143 fPRCont->add(bitmap.pixelRef(), mappedRect); 144 145 SkBitmap paintBitmap; 146 if (GetBitmapFromPaint(paint, &paintBitmap)) { 147 fPRCont->add(paintBitmap.pixelRef(), mappedRect); 148 } 149 } 150 virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 151 const SkRect* srcOrNull, const SkRect& dst, 152 const SkPaint& paint, 153 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE { 154 SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()), 155 SkIntToScalar(bitmap.height())); 156 SkMatrix matrix; 157 matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit); 158 this->drawBitmap(draw, bitmap, matrix, paint); 159 } 160 virtual void drawText(const SkDraw& draw, const void* text, size_t len, 161 SkScalar x, SkScalar y, 162 const SkPaint& paint) SK_OVERRIDE { 163 SkBitmap bitmap; 164 if (!GetBitmapFromPaint(paint, &bitmap)) { 165 return; 166 } 167 168 // Math is borrowed from SkBBoxRecord 169 SkRect bounds; 170 paint.measureText(text, len, &bounds); 171 SkPaint::FontMetrics metrics; 172 paint.getFontMetrics(&metrics); 173 174 if (paint.isVerticalText()) { 175 SkScalar h = bounds.fBottom - bounds.fTop; 176 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 177 bounds.fTop -= h / 2; 178 bounds.fBottom -= h / 2; 179 } 180 bounds.fBottom += metrics.fBottom; 181 bounds.fTop += metrics.fTop; 182 } else { 183 SkScalar w = bounds.fRight - bounds.fLeft; 184 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 185 bounds.fLeft -= w / 2; 186 bounds.fRight -= w / 2; 187 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 188 bounds.fLeft -= w; 189 bounds.fRight -= w; 190 } 191 bounds.fTop = metrics.fTop; 192 bounds.fBottom = metrics.fBottom; 193 } 194 195 SkScalar pad = (metrics.fBottom - metrics.fTop) / 2; 196 bounds.fLeft -= pad; 197 bounds.fRight += pad; 198 bounds.offset(x, y); 199 200 this->drawRect(draw, bounds, paint); 201 } 202 virtual void drawPosText(const SkDraw& draw, const void* text, size_t len, 203 const SkScalar pos[], SkScalar constY, 204 int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE { 205 SkBitmap bitmap; 206 if (!GetBitmapFromPaint(paint, &bitmap)) { 207 return; 208 } 209 210 if (0 == len) { 211 return; 212 } 213 214 // Similar to SkDraw asserts. 215 SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2); 216 217 SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1]; 218 219 SkPoint min, max; 220 min.set(pos[0], y); 221 max.set(pos[0], y); 222 223 for (size_t i = 1; i < len; ++i) { 224 SkScalar x = pos[i * scalarsPerPos]; 225 SkScalar y = constY; 226 if (2 == scalarsPerPos) { 227 y += pos[i * scalarsPerPos + 1]; 228 } 229 230 min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y())); 231 max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y())); 232 } 233 234 SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y()); 235 236 // Math is borrowed from SkBBoxRecord 237 SkPaint::FontMetrics metrics; 238 paint.getFontMetrics(&metrics); 239 240 bounds.fTop += metrics.fTop; 241 bounds.fBottom += metrics.fBottom; 242 243 SkScalar pad = (metrics.fTop - metrics.fBottom) / 2; 244 bounds.fLeft -= pad; 245 bounds.fRight += pad; 246 247 this->drawRect(draw, bounds, paint); 248 } 249 virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len, 250 const SkPath& path, const SkMatrix* matrix, 251 const SkPaint& paint) SK_OVERRIDE { 252 SkBitmap bitmap; 253 if (!GetBitmapFromPaint(paint, &bitmap)) { 254 return; 255 } 256 257 // Math is borrowed from SkBBoxRecord 258 SkRect bounds = path.getBounds(); 259 SkPaint::FontMetrics metrics; 260 paint.getFontMetrics(&metrics); 261 262 SkScalar pad = metrics.fTop; 263 // TODO: inset?! 264 bounds.fLeft += pad; 265 bounds.fRight -= pad; 266 bounds.fTop += pad; 267 bounds.fBottom -= pad; 268 269 this->drawRect(draw, bounds, paint); 270 } 271 virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount, 272 const SkPoint verts[], const SkPoint texs[], 273 const SkColor colors[], SkXfermode* xmode, 274 const uint16_t indices[], int indexCount, 275 const SkPaint& paint) SK_OVERRIDE { 276 this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint); 277 } 278 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 279 const SkPaint&) SK_OVERRIDE { 280 NothingToDo(); 281 } 282 // TODO: allow this call to return failure, or move to SkBitmapDevice only. 283 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE { 284 return fEmptyBitmap; 285 } 286 virtual void lockPixels() SK_OVERRIDE { NothingToDo(); } 287 virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); } 288 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } 289 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } 290 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&, 291 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { 292 return false; 293 } 294 295 private: 296 SkPictureUtils::SkPixelRefContainer* fPRCont; 297 SkISize fSize; 298 299 SkBitmap fEmptyBitmap; // legacy -- need to remove 300 301 static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) { 302 SkShader* shader = paint.getShader(); 303 if (NULL != shader) { 304 if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) { 305 return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL); 306 } 307 } 308 return false; 309 } 310 311 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE { 312 NotSupported(); 313 } 314 315 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE { 316 // we expect to only get called via savelayer, in which case it is fine. 317 SkASSERT(kSaveLayer_Usage == usage); 318 return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice, 319 (info.width(), info.height(), fPRCont)); 320 } 321 322 virtual void flush() SK_OVERRIDE {} 323 324 static void NotSupported() { 325 SkDEBUGFAIL("this method should never be called"); 326 } 327 328 static void NothingToDo() {} 329 330 typedef SkBaseDevice INHERITED; 331 }; 332 333 #endif // SkGatherPixelRefsAndRects_DEFINED 334