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