SkLayerRasterizer.cpp revision a0c2bc24381fea063008f9c8823756eb020603b3
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 "SkFlattenableBuffers.h" 13#include "SkMask.h" 14#include "SkMaskFilter.h" 15#include "SkPaint.h" 16#include "SkPath.h" 17#include "SkPathEffect.h" 18#include "../core/SkRasterClip.h" 19#include "SkXfermode.h" 20#include <new> 21 22struct SkLayerRasterizer_Rec { 23 SkPaint fPaint; 24 SkVector fOffset; 25}; 26 27SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec)) 28{ 29} 30 31SkLayerRasterizer::~SkLayerRasterizer() { 32 SkDeque::F2BIter iter(fLayers); 33 SkLayerRasterizer_Rec* rec; 34 35 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) 36 rec->fPaint.~SkPaint(); 37} 38 39void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx, 40 SkScalar dy) { 41 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back(); 42 43 SkNEW_PLACEMENT_ARGS(&rec->fPaint, SkPaint, (paint)); 44 rec->fOffset.set(dx, dy); 45} 46 47static bool compute_bounds(const SkDeque& layers, const SkPath& path, 48 const SkMatrix& matrix, 49 const SkIRect* clipBounds, SkIRect* bounds) { 50 SkDeque::F2BIter iter(layers); 51 SkLayerRasterizer_Rec* rec; 52 53 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32); 54 55 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 56 const SkPaint& paint = rec->fPaint; 57 SkPath fillPath, devPath; 58 const SkPath* p = &path; 59 60 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 61 paint.getFillPath(path, &fillPath); 62 p = &fillPath; 63 } 64 if (p->isEmpty()) { 65 continue; 66 } 67 68 // apply the matrix and offset 69 { 70 SkMatrix m = matrix; 71 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 72 p->transform(m, &devPath); 73 } 74 75 SkMask mask; 76 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(), 77 &matrix, &mask, 78 SkMask::kJustComputeBounds_CreateMode, 79 SkPaint::kFill_Style)) { 80 return false; 81 } 82 83 bounds->join(mask.fBounds); 84 } 85 return true; 86} 87 88bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, 89 const SkIRect* clipBounds, 90 SkMask* mask, SkMask::CreateMode mode) { 91 if (fLayers.empty()) { 92 return false; 93 } 94 95 if (SkMask::kJustRenderImage_CreateMode != mode) { 96 if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds)) 97 return false; 98 } 99 100 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 101 mask->fFormat = SkMask::kA8_Format; 102 mask->fRowBytes = mask->fBounds.width(); 103 size_t size = mask->computeImageSize(); 104 if (0 == size) { 105 return false; // too big to allocate, abort 106 } 107 mask->fImage = SkMask::AllocImage(size); 108 memset(mask->fImage, 0, size); 109 } 110 111 if (SkMask::kJustComputeBounds_CreateMode != mode) { 112 SkBitmap device; 113 SkRasterClip rectClip; 114 SkDraw draw; 115 SkMatrix translatedMatrix; // this translates us to our local pixels 116 SkMatrix drawMatrix; // this translates the path by each layer's offset 117 118 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height())); 119 120 translatedMatrix = matrix; 121 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), 122 -SkIntToScalar(mask->fBounds.fTop)); 123 124 device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes); 125 device.setPixels(mask->fImage); 126 127 draw.fBitmap = &device; 128 draw.fMatrix = &drawMatrix; 129 draw.fRC = &rectClip; 130 draw.fClip = &rectClip.bwRgn(); 131 // we set the matrixproc in the loop, as the matrix changes each time (potentially) 132 draw.fBounder = NULL; 133 134 SkDeque::F2BIter iter(fLayers); 135 SkLayerRasterizer_Rec* rec; 136 137 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 138 drawMatrix = translatedMatrix; 139 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 140 draw.drawPath(path, rec->fPaint); 141 } 142 } 143 return true; 144} 145 146SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer) 147 : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) { 148 int count = buffer.readInt(); 149 150 for (int i = 0; i < count; i++) { 151 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back(); 152 153 SkNEW_PLACEMENT(&rec->fPaint, SkPaint); 154 buffer.readPaint(&rec->fPaint); 155 buffer.readPoint(&rec->fOffset); 156 } 157} 158 159void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const { 160 this->INHERITED::flatten(buffer); 161 162 buffer.writeInt(fLayers.count()); 163 164 SkDeque::F2BIter iter(fLayers); 165 const SkLayerRasterizer_Rec* rec; 166 167 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) { 168 buffer.writePaint(rec->fPaint); 169 buffer.writePoint(rec->fOffset); 170 } 171} 172