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 "../core/SkRasterClip.h" 18#include "SkXfermode.h" 19#include <new> 20 21struct SkLayerRasterizer_Rec { 22 SkPaint fPaint; 23 SkVector fOffset; 24}; 25 26SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec)) 27{ 28} 29 30SkLayerRasterizer::~SkLayerRasterizer() { 31 SkDeque::F2BIter iter(fLayers); 32 SkLayerRasterizer_Rec* rec; 33 34 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) 35 rec->fPaint.~SkPaint(); 36} 37 38void SkLayerRasterizer::addLayer(const SkPaint& paint, SkScalar dx, 39 SkScalar dy) { 40 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back(); 41 42 new (&rec->fPaint) SkPaint(paint); 43 rec->fOffset.set(dx, dy); 44} 45 46static bool compute_bounds(const SkDeque& layers, const SkPath& path, 47 const SkMatrix& matrix, 48 const SkIRect* clipBounds, SkIRect* bounds) { 49 SkDeque::F2BIter iter(layers); 50 SkLayerRasterizer_Rec* rec; 51 52 bounds->set(SK_MaxS32, SK_MaxS32, SK_MinS32, SK_MinS32); 53 54 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 55 const SkPaint& paint = rec->fPaint; 56 SkPath fillPath, devPath; 57 const SkPath* p = &path; 58 59 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 60 paint.getFillPath(path, &fillPath); 61 p = &fillPath; 62 } 63 if (p->isEmpty()) { 64 continue; 65 } 66 67 // apply the matrix and offset 68 { 69 SkMatrix m = matrix; 70 m.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 71 p->transform(m, &devPath); 72 } 73 74 SkMask mask; 75 if (!SkDraw::DrawToMask(devPath, clipBounds, paint.getMaskFilter(), 76 &matrix, &mask, 77 SkMask::kJustComputeBounds_CreateMode)) { 78 return false; 79 } 80 81 bounds->join(mask.fBounds); 82 } 83 return true; 84} 85 86bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, 87 const SkIRect* clipBounds, 88 SkMask* mask, SkMask::CreateMode mode) { 89 if (fLayers.empty()) { 90 return false; 91 } 92 93 if (SkMask::kJustRenderImage_CreateMode != mode) { 94 if (!compute_bounds(fLayers, path, matrix, clipBounds, &mask->fBounds)) 95 return false; 96 } 97 98 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 99 mask->fFormat = SkMask::kA8_Format; 100 mask->fRowBytes = mask->fBounds.width(); 101 size_t size = mask->computeImageSize(); 102 if (0 == size) { 103 return false; // too big to allocate, abort 104 } 105 mask->fImage = SkMask::AllocImage(size); 106 memset(mask->fImage, 0, size); 107 } 108 109 if (SkMask::kJustComputeBounds_CreateMode != mode) { 110 SkBitmap device; 111 SkRasterClip rectClip; 112 SkDraw draw; 113 SkMatrix translatedMatrix; // this translates us to our local pixels 114 SkMatrix drawMatrix; // this translates the path by each layer's offset 115 116 rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height())); 117 118 translatedMatrix = matrix; 119 translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), 120 -SkIntToScalar(mask->fBounds.fTop)); 121 122 device.setConfig(SkBitmap::kA8_Config, mask->fBounds.width(), mask->fBounds.height(), mask->fRowBytes); 123 device.setPixels(mask->fImage); 124 125 draw.fBitmap = &device; 126 draw.fMatrix = &drawMatrix; 127 draw.fRC = &rectClip; 128 draw.fClip = &rectClip.bwRgn(); 129 // we set the matrixproc in the loop, as the matrix changes each time (potentially) 130 draw.fBounder = NULL; 131 132 SkDeque::F2BIter iter(fLayers); 133 SkLayerRasterizer_Rec* rec; 134 135 while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { 136 drawMatrix = translatedMatrix; 137 drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY); 138 draw.drawPath(path, rec->fPaint); 139 } 140 } 141 return true; 142} 143 144/////////// Routines for flattening ///////////////// 145 146static void paint_read(SkPaint* paint, SkFlattenableReadBuffer& buffer) { 147 paint->setAntiAlias(buffer.readBool()); 148 paint->setStyle((SkPaint::Style)buffer.readU8()); 149 paint->setAlpha(buffer.readU8()); 150 151 if (paint->getStyle() != SkPaint::kFill_Style) { 152 paint->setStrokeWidth(buffer.readScalar()); 153 paint->setStrokeMiter(buffer.readScalar()); 154 paint->setStrokeCap((SkPaint::Cap)buffer.readU8()); 155 paint->setStrokeJoin((SkPaint::Join)buffer.readU8()); 156 } 157 158 SkSafeUnref(paint->setMaskFilter((SkMaskFilter*)buffer.readFlattenable())); 159 SkSafeUnref(paint->setPathEffect((SkPathEffect*)buffer.readFlattenable())); 160 SkSafeUnref(paint->setRasterizer((SkRasterizer*)buffer.readFlattenable())); 161 SkSafeUnref(paint->setXfermode((SkXfermode*)buffer.readFlattenable())); 162} 163 164static void paint_write(const SkPaint& paint, SkFlattenableWriteBuffer& buffer) { 165 buffer.writeBool(paint.isAntiAlias()); 166 buffer.write8(paint.getStyle()); 167 buffer.write8(paint.getAlpha()); 168 169 if (paint.getStyle() != SkPaint::kFill_Style) { 170 buffer.writeScalar(paint.getStrokeWidth()); 171 buffer.writeScalar(paint.getStrokeMiter()); 172 buffer.write8(paint.getStrokeCap()); 173 buffer.write8(paint.getStrokeJoin()); 174 } 175 176 buffer.writeFlattenable(paint.getMaskFilter()); 177 buffer.writeFlattenable(paint.getPathEffect()); 178 buffer.writeFlattenable(paint.getRasterizer()); 179 buffer.writeFlattenable(paint.getXfermode()); 180} 181 182SkLayerRasterizer::SkLayerRasterizer(SkFlattenableReadBuffer& buffer) 183 : SkRasterizer(buffer), fLayers(sizeof(SkLayerRasterizer_Rec)) { 184 int count = buffer.readS32(); 185 186 for (int i = 0; i < count; i++) { 187 SkLayerRasterizer_Rec* rec = (SkLayerRasterizer_Rec*)fLayers.push_back(); 188 189#if 0 190 new (&rec->fPaint) SkPaint(buffer); 191#else 192 new (&rec->fPaint) SkPaint; 193 paint_read(&rec->fPaint, buffer); 194#endif 195 rec->fOffset.fX = buffer.readScalar(); 196 rec->fOffset.fY = buffer.readScalar(); 197 } 198} 199 200void SkLayerRasterizer::flatten(SkFlattenableWriteBuffer& buffer) { 201 this->INHERITED::flatten(buffer); 202 203 buffer.write32(fLayers.count()); 204 205 SkDeque::F2BIter iter(fLayers); 206 const SkLayerRasterizer_Rec* rec; 207 208 while ((rec = (const SkLayerRasterizer_Rec*)iter.next()) != NULL) { 209#if 0 210 rec->fPaint.flatten(buffer); 211#else 212 paint_write(rec->fPaint, buffer); 213#endif 214 buffer.writeScalar(rec->fOffset.fX); 215 buffer.writeScalar(rec->fOffset.fY); 216 } 217} 218 219SkFlattenable* SkLayerRasterizer::CreateProc(SkFlattenableReadBuffer& buffer) { 220 return SkNEW_ARGS(SkLayerRasterizer, (buffer)); 221} 222 223SkFlattenable::Factory SkLayerRasterizer::getFactory() { 224 return CreateProc; 225} 226 227SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerRasterizer) 228 229