SkLayerRasterizer.cpp revision 75a0972dd7d0dbc614b9fb81b4450a349c005325
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 "SkBuffer.h" 12#include "SkDraw.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 new (&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 146/////////// Routines for flattening ///////////////// 147 148static void paint_read(SkPaint* paint, SkFlattenableReadBuffer& buffer) { 149 paint->setAntiAlias(buffer.readBool()); 150 paint->setStyle((SkPaint::Style)buffer.readU8()); 151 paint->setAlpha(buffer.readU8()); 152 153 if (paint->getStyle() != SkPaint::kFill_Style) { 154 paint->setStrokeWidth(buffer.readScalar()); 155 paint->setStrokeMiter(buffer.readScalar()); 156 paint->setStrokeCap((SkPaint::Cap)buffer.readU8()); 157 paint->setStrokeJoin((SkPaint::Join)buffer.readU8()); 158 } 159 160 SkSafeUnref(paint->setMaskFilter((SkMaskFilter*)buffer.readFlattenable())); 161 SkSafeUnref(paint->setPathEffect((SkPathEffect*)buffer.readFlattenable())); 162 SkSafeUnref(paint->setRasterizer((SkRasterizer*)buffer.readFlattenable())); 163 SkSafeUnref(paint->setXfermode((SkXfermode*)buffer.readFlattenable())); 164} 165 166static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer) { 167 buffer.writeBool(paint.isAntiAlias()); 168 buffer.write8(paint.getStyle()); 169 buffer.write8(paint.getAlpha()); 170 171 if (paint.getStyle() != SkPaint::kFill_Style) { 172 buffer.writeScalar(paint.getStrokeWidth()); 173 buffer.writeScalar(paint.getStrokeMiter()); 174 buffer.write8(paint.getStrokeCap()); 175 buffer.write8(paint.getStrokeJoin()); 176 } 177 178 buffer.writeFlattenable(paint.getMaskFilter()); 179 buffer.writeFlattenable(paint.getPathEffect()); 180 buffer.writeFlattenable(paint.getRasterizer()); 181 buffer.writeFlattenable(paint.getXfermode()); 182} 183 184SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer) 185 : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) { 186 int count = buffer.readS32(); 187 188 for (int i = 0; i < count; i++) { 189 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back(); 190 191#if 0 192 new (&rec->fPaint) SkPaint(buffer); 193#else 194 new (&rec->fPaint) SkPaint; 195 paint_read(&rec->fPaint, buffer); 196#endif 197 rec->fOffset.fX = buffer.readScalar(); 198 rec->fOffset.fY = buffer.readScalar(); 199 } 200} 201 202void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) const { 203 this->INHERITED::flatten(buffer); 204 205 buffer.write32(fLayers.count()); 206 207 SkDeque::F2BIter iter(fLayers); 208 const SkLayerRasterizer_Rec* rec; 209 210 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) { 211#if 0 212 rec->fPaint.flatten(buffer); 213#else 214 paint_write(rec->fPaint, buffer); 215#endif 216 buffer.writeScalar(rec->fOffset.fX); 217 buffer.writeScalar(rec->fOffset.fY); 218 } 219} 220 221SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerRasterizer) 222 223