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 "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 
     22 struct SkLayerRasterizer_Rec {
     23     SkPaint     fPaint;
     24     SkVector    fOffset;
     25 };
     26 
     27 SkLayerRasterizer::SkLayerRasterizer() : fLayers(sizeof(SkLayerRasterizer_Rec))
     28 {
     29 }
     30 
     31 SkLayerRasterizer::~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 
     39 void 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 
     47 static 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 
     88 bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix,
     89                                     const SkIRect* clipBounds,
     90                                     SkMask* mask, SkMask::CreateMode mode) const {
     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 SkLayerRasterizer::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 
    159 void 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