1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkLayerRasterizer.h" 11#include "SkDraw.h" 12#include "SkReadBuffer.h" 13#include "SkWriteBuffer.h" 14#include "SkMask.h" 15#include "SkMaskFilter.h" 16#include "SkPaint.h" 17#include "SkPath.h" 18#include "SkPathEffect.h" 19#include "../core/SkRasterClip.h" 20#include "SkXfermode.h" 21#include <new> 22 23struct SkLayerRasterizer_Rec { 24 SkPaint fPaint; 25 SkVector fOffset; 26}; 27 28SkLayerRasterizer::SkLayerRasterizer() 29 : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec)))) 30{ 31} 32 33SkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers) 34{ 35} 36 37// Helper function to call destructors on SkPaints held by layers and delete layers. 38static void clean_up_layers(SkDeque* layers) { 39 SkDeque::F2BIter iter(*layers); 40 SkLayerRasterizer_Rec* rec; 41 42 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) 43 rec->fPaint.~SkPaint(); 44 45 SkDELETE(layers); 46} 47 48SkLayerRasterizer::~SkLayerRasterizer() { 49 SkASSERT(fLayers); 50 clean_up_layers(const_cast<SkDeque*>(fLayers)); 51} 52 53#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API 54void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx, 55 SkScalar dy) { 56 SkASSERT(fLayers); 57 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back(); 58 59 SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint)); 60 rec->fOffset.set(dx, dy); 61} 62#endif 63 64static bool compute_bounds(const SkDeque& layers, const SkPath& path, 65 const SkMatrix& matrix, 66 const SkIRect* clipBounds, SkIRect* bounds) { 67 SkDeque::F2BIter iter(layers); 68 SkLayerRasterizer_Rec* rec; 69 70 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32); 71 72 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 73 const SkPaint& paint = rec->fPaint; 74 SkPath fillPath, devPath; 75 const SkPath* p = &path; 76 77 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 78 paint.getFillPath(path, &fillPath); 79 p = &fillPath; 80 } 81 if (p->isEmpty()) { 82 continue; 83 } 84 85 // apply the matrix and offset 86 { 87 SkMatrix m = matrix; 88 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 89 p->transform(m, &devPath); 90 } 91 92 SkMask mask; 93 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(), 94 &matrix, &mask, 95 SkMask::kJustComputeBounds_CreateMode, 96 SkPaint::kFill_Style)) { 97 return false; 98 } 99 100 bounds->join(mask.fBounds); 101 } 102 return true; 103} 104 105bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, 106 const SkIRect* clipBounds, 107 SkMask* mask, SkMask::CreateMode mode) const { 108 SkASSERT(fLayers); 109 if (fLayers->empty()) { 110 return false; 111 } 112 113 if (SkMask::kJustRenderImage_CreateMode != mode) { 114 if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds)) 115 return false; 116 } 117 118 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 119 mask->fFormat = SkMask::kA8_Format; 120 mask->fRowBytes = mask->fBounds.width(); 121 size_t size = mask->computeImageSize(); 122 if (0 == size) { 123 return false; // too big to allocate, abort 124 } 125 mask->fImage = SkMask::AllocImage(size); 126 memset(mask->fImage, 0, size); 127 } 128 129 if (SkMask::kJustComputeBounds_CreateMode != mode) { 130 SkBitmap device; 131 SkRasterClip rectClip; 132 SkDraw draw; 133 SkMatrix translatedMatrix; // this translates us to our local pixels 134 SkMatrix drawMatrix; // this translates the path by each layer's offset 135 136 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height())); 137 138 translatedMatrix = matrix; 139 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), 140 -SkIntToScalar(mask->fBounds.fTop)); 141 142 device.installMaskPixels(*mask); 143 144 draw.fBitmap = &device; 145 draw.fMatrix = &drawMatrix; 146 draw.fRC = &rectClip; 147 draw.fClip = &rectClip.bwRgn(); 148 // we set the matrixproc in the loop, as the matrix changes each time (potentially) 149 150 SkDeque::F2BIter iter(*fLayers); 151 SkLayerRasterizer_Rec* rec; 152 153 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 154 drawMatrix = translatedMatrix; 155 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 156 draw.drawPath(path, rec->fPaint); 157 } 158 } 159 return true; 160} 161 162SkLayerRasterizer::SkLayerRasterizer(SkReadBuffer& buffer) 163 : SkRasterizer(buffer), fLayers(ReadLayers(buffer)) {} 164 165SkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) { 166 int count = buffer.readInt(); 167 168 SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec))); 169 for (int i = 0; i < count; i++) { 170 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back(); 171 172 SkNEW_PLACEMENT(&rec->fPaint, SkPaint); 173 buffer.readPaint(&rec->fPaint); 174 buffer.readPoint(&rec->fOffset); 175 } 176 return layers; 177} 178 179void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const { 180 this->INHERITED::flatten(buffer); 181 182 SkASSERT(fLayers); 183 buffer.writeInt(fLayers->count()); 184 185 SkDeque::F2BIter iter(*fLayers); 186 const SkLayerRasterizer_Rec* rec; 187 188 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) { 189 buffer.writePaint(rec->fPaint); 190 buffer.writePoint(rec->fOffset); 191 } 192} 193 194SkLayerRasterizer::Builder::Builder() 195 : fLayers(SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec)))) 196{ 197} 198 199SkLayerRasterizer::Builder::~Builder() 200{ 201 if (fLayers != NULL) { 202 clean_up_layers(fLayers); 203 } 204} 205 206void SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx, 207 SkScalar dy) { 208 SkASSERT(fLayers); 209 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back(); 210 211 SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint)); 212 rec->fOffset.set(dx, dy); 213} 214 215SkLayerRasterizer* SkLayerRasterizer::Builder::detachRasterizer() { 216 SkLayerRasterizer* rasterizer; 217 if (0 == fLayers->count()) { 218 rasterizer = NULL; 219 SkDELETE(fLayers); 220 } else { 221 rasterizer = SkNEW_ARGS(SkLayerRasterizer, (fLayers)); 222 } 223 fLayers = NULL; 224 return rasterizer; 225} 226 227SkLayerRasterizer* SkLayerRasterizer::Builder::snapshotRasterizer() const { 228 if (0 == fLayers->count()) { 229 return NULL; 230 } 231 SkDeque* layers = SkNEW_ARGS(SkDeque, (sizeof(SkLayerRasterizer_Rec), fLayers->count())); 232 SkDeque::F2BIter iter(*fLayers); 233 const SkLayerRasterizer_Rec* recOrig; 234 SkDEBUGCODE(int count = 0;) 235 while ((recOrig = static_cast<SkLayerRasterizer_Rec*>(iter.next())) != NULL) { 236 SkDEBUGCODE(count++); 237 SkLayerRasterizer_Rec* recCopy = static_cast<SkLayerRasterizer_Rec*>(layers->push_back()); 238 SkNEW_PLACEMENT_ARGS(&recCopy->fPaint, SkPaint, (recOrig->fPaint)); 239 recCopy->fOffset = recOrig->fOffset; 240 } 241 SkASSERT(fLayers->count() == count); 242 SkASSERT(layers->count() == count); 243 SkLayerRasterizer* rasterizer = SkNEW_ARGS(SkLayerRasterizer, (layers)); 244 return rasterizer; 245} 246