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