SkLayerRasterizer.cpp revision 96fcdcc219d2a0d3579719b84b28bede76efba64
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() : fLayers(new SkDeque(sizeof(SkLayerRasterizer_Rec))) {} 29 30SkLayerRasterizer::SkLayerRasterizer(SkDeque* layers) : fLayers(layers) 31{ 32} 33 34// Helper function to call destructors on SkPaints held by layers and delete layers. 35static void clean_up_layers(SkDeque* layers) { 36 SkDeque::F2BIter iter(*layers); 37 SkLayerRasterizer_Rec* rec; 38 39 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr) 40 rec->fPaint.~SkPaint(); 41 42 delete layers; 43} 44 45SkLayerRasterizer::~SkLayerRasterizer() { 46 SkASSERT(fLayers); 47 clean_up_layers(const_cast<SkDeque*>(fLayers)); 48} 49 50static bool compute_bounds(const SkDeque& layers, const SkPath& path, 51 const SkMatrix& matrix, 52 const SkIRect* clipBounds, SkIRect* bounds) { 53 SkDeque::F2BIter iter(layers); 54 SkLayerRasterizer_Rec* rec; 55 56 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32); 57 58 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr) { 59 const SkPaint& paint = rec->fPaint; 60 SkPath fillPath, devPath; 61 const SkPath* p = &path; 62 63 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 64 paint.getFillPath(path, &fillPath); 65 p = &fillPath; 66 } 67 if (p->isEmpty()) { 68 continue; 69 } 70 71 // apply the matrix and offset 72 { 73 SkMatrix m = matrix; 74 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 75 p->transform(m, &devPath); 76 } 77 78 SkMask mask; 79 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(), 80 &matrix, &mask, 81 SkMask::kJustComputeBounds_CreateMode, 82 SkPaint::kFill_Style)) { 83 return false; 84 } 85 86 bounds->join(mask.fBounds); 87 } 88 return true; 89} 90 91bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, 92 const SkIRect* clipBounds, 93 SkMask* mask, SkMask::CreateMode mode) const { 94 SkASSERT(fLayers); 95 if (fLayers->empty()) { 96 return false; 97 } 98 99 if (SkMask::kJustRenderImage_CreateMode != mode) { 100 if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds)) 101 return false; 102 } 103 104 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 105 mask->fFormat = SkMask::kA8_Format; 106 mask->fRowBytes = mask->fBounds.width(); 107 size_t size = mask->computeImageSize(); 108 if (0 == size) { 109 return false; // too big to allocate, abort 110 } 111 mask->fImage = SkMask::AllocImage(size); 112 memset(mask->fImage, 0, size); 113 } 114 115 if (SkMask::kJustComputeBounds_CreateMode != mode) { 116 SkDraw draw; 117 if (!draw.fDst.reset(*mask)) { 118 return false; 119 } 120 121 SkRasterClip rectClip; 122 SkMatrix translatedMatrix; // this translates us to our local pixels 123 SkMatrix drawMatrix; // this translates the path by each layer's offset 124 125 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height())); 126 127 translatedMatrix = matrix; 128 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), 129 -SkIntToScalar(mask->fBounds.fTop)); 130 131 draw.fMatrix = &drawMatrix; 132 draw.fRC = &rectClip; 133 draw.fClip = &rectClip.bwRgn(); 134 // we set the matrixproc in the loop, as the matrix changes each time (potentially) 135 136 SkDeque::F2BIter iter(*fLayers); 137 SkLayerRasterizer_Rec* rec; 138 139 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != nullptr) { 140 drawMatrix = translatedMatrix; 141 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 142 draw.drawPath(path, rec->fPaint); 143 } 144 } 145 return true; 146} 147 148SkFlattenable* SkLayerRasterizer::CreateProc(SkReadBuffer& buffer) { 149 return new SkLayerRasterizer(ReadLayers(buffer)); 150} 151 152SkDeque* SkLayerRasterizer::ReadLayers(SkReadBuffer& buffer) { 153 int count = buffer.readInt(); 154 155 SkDeque* layers = new SkDeque(sizeof(SkLayerRasterizer_Rec)); 156 for (int i = 0; i < count; i++) { 157 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)layers->push_back(); 158 159 new (&rec->fPaint) SkPaint; 160 buffer.readPaint(&rec->fPaint); 161 buffer.readPoint(&rec->fOffset); 162 } 163 return layers; 164} 165 166void SkLayerRasterizer::flatten(SkWriteBuffer& buffer) const { 167 this->INHERITED::flatten(buffer); 168 169 SkASSERT(fLayers); 170 buffer.writeInt(fLayers->count()); 171 172 SkDeque::F2BIter iter(*fLayers); 173 const SkLayerRasterizer_Rec* rec; 174 175 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != nullptr) { 176 buffer.writePaint(rec->fPaint); 177 buffer.writePoint(rec->fOffset); 178 } 179} 180 181SkLayerRasterizer::Builder::Builder() : fLayers(new SkDeque(sizeof(SkLayerRasterizer_Rec))) {} 182 183SkLayerRasterizer::Builder::~Builder() 184{ 185 if (fLayers != nullptr) { 186 clean_up_layers(fLayers); 187 } 188} 189 190void SkLayerRasterizer::Builder::addLayer(const SkPaint& paint, SkScalar dx, 191 SkScalar dy) { 192 SkASSERT(fLayers); 193 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers->push_back(); 194 195 new (&rec->fPaint) SkPaint(paint); 196 rec->fOffset.set(dx, dy); 197} 198 199SkLayerRasterizer* SkLayerRasterizer::Builder::detachRasterizer() { 200 SkLayerRasterizer* rasterizer; 201 if (0 == fLayers->count()) { 202 rasterizer = nullptr; 203 delete fLayers; 204 } else { 205 rasterizer = new SkLayerRasterizer(fLayers); 206 } 207 fLayers = nullptr; 208 return rasterizer; 209} 210 211SkLayerRasterizer* SkLayerRasterizer::Builder::snapshotRasterizer() const { 212 if (0 == fLayers->count()) { 213 return nullptr; 214 } 215 SkDeque* layers = new SkDeque(sizeof(SkLayerRasterizer_Rec), fLayers->count()); 216 SkDeque::F2BIter iter(*fLayers); 217 const SkLayerRasterizer_Rec* recOrig; 218 SkDEBUGCODE(int count = 0;) 219 while ((recOrig = static_cast<SkLayerRasterizer_Rec*>(iter.next())) != nullptr) { 220 SkDEBUGCODE(count++); 221 SkLayerRasterizer_Rec* recCopy = static_cast<SkLayerRasterizer_Rec*>(layers->push_back()); 222 new (&recCopy->fPaint) SkPaint(recOrig->fPaint); 223 recCopy->fOffset = recOrig->fOffset; 224 } 225 SkASSERT(fLayers->count() == count); 226 SkASSERT(layers->count() == count); 227 SkLayerRasterizer* rasterizer = new SkLayerRasterizer(layers); 228 return rasterizer; 229} 230