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