Home | History | Annotate | Download | only in effects
      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 
     21 struct SkLayerRasterizer_Rec {
     22     SkPaint     fPaint;
     23     SkVector    fOffset;
     24 };
     25 
     26 SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
     27 {
     28 }
     29 
     30 SkLayerRasterizer::~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 
     38 void 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 
     46 static 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 
     86 bool 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 
    146 static 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 
    164 static 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 
    182 SkLayerRasterizer::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 
    200 void 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 
    219 SkFlattenable* SkLayerRasterizer::CreateProc(SkFlattenableReadBuffer& buffer) {
    220     return SkNEW_ARGS(SkLayerRasterizer, (buffer));
    221 }
    222 
    223 SkFlattenable::Factory SkLayerRasterizer::getFactory() {
    224     return CreateProc;
    225 }
    226 
    227 SK_DEFINE_FLATTENABLE_REGISTRAR(SkLayerRasterizer)
    228 
    229