1 /* 2 * Copyright 2012 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 #include "SkBitmapDevice.h" 9 #include "SkCanvas.h" 10 #include "SkData.h" 11 #include "SkNoSaveLayerCanvas.h" 12 #include "SkPictureUtils.h" 13 #include "SkPixelRef.h" 14 #include "SkRRect.h" 15 #include "SkShader.h" 16 17 class PixelRefSet { 18 public: 19 PixelRefSet(SkTDArray<SkPixelRef*>* array) : fArray(array) {} 20 21 // This does a linear search on existing pixelrefs, so if this list gets big 22 // we should use a more complex sorted/hashy thing. 23 // 24 void add(SkPixelRef* pr) { 25 uint32_t genID = pr->getGenerationID(); 26 if (fGenID.find(genID) < 0) { 27 *fArray->append() = pr; 28 *fGenID.append() = genID; 29 // SkDebugf("--- adding [%d] %x %d\n", fArray->count() - 1, pr, genID); 30 } else { 31 // SkDebugf("--- already have %x %d\n", pr, genID); 32 } 33 } 34 35 private: 36 SkTDArray<SkPixelRef*>* fArray; 37 SkTDArray<uint32_t> fGenID; 38 }; 39 40 static void not_supported() { 41 SkDEBUGFAIL("this method should never be called"); 42 } 43 44 static void nothing_to_do() {} 45 46 /** 47 * This device will route all bitmaps (primitives and in shaders) to its PRSet. 48 * It should never actually draw anything, so there need not be any pixels 49 * behind its device. 50 */ 51 class GatherPixelRefDevice : public SkBaseDevice { 52 public: 53 SK_DECLARE_INST_COUNT(GatherPixelRefDevice) 54 55 GatherPixelRefDevice(int width, int height, PixelRefSet* prset) { 56 fSize.set(width, height); 57 fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); 58 fPRSet = prset; 59 } 60 61 virtual SkImageInfo imageInfo() const SK_OVERRIDE { 62 return SkImageInfo::MakeUnknown(fSize.width(), fSize.height()); 63 } 64 virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; } 65 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE { 66 return false; 67 } 68 // TODO: allow this call to return failure, or move to SkBitmapDevice only. 69 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE { 70 return fEmptyBitmap; 71 } 72 virtual void lockPixels() SK_OVERRIDE { nothing_to_do(); } 73 virtual void unlockPixels() SK_OVERRIDE { nothing_to_do(); } 74 virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } 75 virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } 76 virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&, 77 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE { 78 return false; 79 } 80 81 virtual void clear(SkColor color) SK_OVERRIDE { 82 nothing_to_do(); 83 } 84 85 virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE { 86 this->addBitmapFromPaint(paint); 87 } 88 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, 89 const SkPoint[], const SkPaint& paint) SK_OVERRIDE { 90 this->addBitmapFromPaint(paint); 91 } 92 virtual void drawRect(const SkDraw&, const SkRect&, 93 const SkPaint& paint) SK_OVERRIDE { 94 this->addBitmapFromPaint(paint); 95 } 96 virtual void drawRRect(const SkDraw&, const SkRRect&, 97 const SkPaint& paint) SK_OVERRIDE { 98 this->addBitmapFromPaint(paint); 99 } 100 virtual void drawOval(const SkDraw&, const SkRect&, 101 const SkPaint& paint) SK_OVERRIDE { 102 this->addBitmapFromPaint(paint); 103 } 104 virtual void drawPath(const SkDraw&, const SkPath& path, 105 const SkPaint& paint, const SkMatrix* prePathMatrix, 106 bool pathIsMutable) SK_OVERRIDE { 107 this->addBitmapFromPaint(paint); 108 } 109 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 110 const SkMatrix&, const SkPaint& paint) SK_OVERRIDE { 111 this->addBitmap(bitmap); 112 if (kAlpha_8_SkColorType == bitmap.colorType()) { 113 this->addBitmapFromPaint(paint); 114 } 115 } 116 virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap, 117 const SkRect* srcOrNull, const SkRect& dst, 118 const SkPaint& paint, 119 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE { 120 this->addBitmap(bitmap); 121 if (kAlpha_8_SkColorType == bitmap.colorType()) { 122 this->addBitmapFromPaint(paint); 123 } 124 } 125 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 126 int x, int y, const SkPaint& paint) SK_OVERRIDE { 127 this->addBitmap(bitmap); 128 } 129 virtual void drawText(const SkDraw&, const void* text, size_t len, 130 SkScalar x, SkScalar y, 131 const SkPaint& paint) SK_OVERRIDE { 132 this->addBitmapFromPaint(paint); 133 } 134 virtual void drawPosText(const SkDraw&, const void* text, size_t len, 135 const SkScalar pos[], SkScalar constY, 136 int, const SkPaint& paint) SK_OVERRIDE { 137 this->addBitmapFromPaint(paint); 138 } 139 virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, 140 const SkPath& path, const SkMatrix* matrix, 141 const SkPaint& paint) SK_OVERRIDE { 142 this->addBitmapFromPaint(paint); 143 } 144 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount, 145 const SkPoint verts[], const SkPoint texs[], 146 const SkColor colors[], SkXfermode* xmode, 147 const uint16_t indices[], int indexCount, 148 const SkPaint& paint) SK_OVERRIDE { 149 this->addBitmapFromPaint(paint); 150 } 151 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 152 const SkPaint&) SK_OVERRIDE { 153 nothing_to_do(); 154 } 155 156 protected: 157 virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE { 158 not_supported(); 159 } 160 virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE { 161 // we expect to only get called via savelayer, in which case it is fine. 162 SkASSERT(kSaveLayer_Usage == usage); 163 return SkNEW_ARGS(GatherPixelRefDevice, (info.width(), info.height(), fPRSet)); 164 } 165 virtual void flush() SK_OVERRIDE {} 166 167 private: 168 PixelRefSet* fPRSet; 169 SkBitmap fEmptyBitmap; // legacy -- need to remove the need for this guy 170 SkISize fSize; 171 172 void addBitmap(const SkBitmap& bm) { 173 fPRSet->add(bm.pixelRef()); 174 } 175 176 void addBitmapFromPaint(const SkPaint& paint) { 177 SkShader* shader = paint.getShader(); 178 if (shader) { 179 SkBitmap bm; 180 // Check whether the shader is a gradient in order to short-circuit 181 // call to asABitmap to prevent generation of bitmaps from 182 // gradient shaders, which implement asABitmap. 183 if (SkShader::kNone_GradientType == shader->asAGradient(NULL) && 184 shader->asABitmap(&bm, NULL, NULL)) { 185 fPRSet->add(bm.pixelRef()); 186 } 187 } 188 } 189 190 typedef SkBaseDevice INHERITED; 191 }; 192 193 SkData* SkPictureUtils::GatherPixelRefs(const SkPicture* pict, const SkRect& area) { 194 if (NULL == pict) { 195 return NULL; 196 } 197 198 // this test also handles if either area or pict's width/height are empty 199 if (!SkRect::Intersects(area, pict->cullRect())) { 200 return NULL; 201 } 202 203 SkTDArray<SkPixelRef*> array; 204 PixelRefSet prset(&array); 205 206 GatherPixelRefDevice device(SkScalarCeilToInt(pict->cullRect().width()), 207 SkScalarCeilToInt(pict->cullRect().height()), 208 &prset); 209 SkNoSaveLayerCanvas canvas(&device); 210 211 canvas.clipRect(area, SkRegion::kIntersect_Op, false); 212 canvas.drawPicture(pict); 213 214 SkData* data = NULL; 215 int count = array.count(); 216 if (count > 0) { 217 data = SkData::NewFromMalloc(array.detach(), count * sizeof(SkPixelRef*)); 218 } 219 return data; 220 } 221