Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 
      9 #include "Sk2DPathEffect.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkWriteBuffer.h"
     12 #include "SkPath.h"
     13 #include "SkRegion.h"
     14 #include "SkStrokeRec.h"
     15 
     16 Sk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) {
     17     // Calling invert will set the type mask on both matrices, making them thread safe.
     18     fMatrixIsInvertible = fMatrix.invert(&fInverse);
     19 }
     20 
     21 bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src,
     22                                 SkStrokeRec*, const SkRect*) const {
     23     if (!fMatrixIsInvertible) {
     24         return false;
     25     }
     26 
     27     SkPath  tmp;
     28     SkIRect ir;
     29 
     30     src.transform(fInverse, &tmp);
     31     tmp.getBounds().round(&ir);
     32     if (!ir.isEmpty()) {
     33         this->begin(ir, dst);
     34 
     35         SkRegion rgn;
     36         rgn.setPath(tmp, SkRegion(ir));
     37         SkRegion::Iterator iter(rgn);
     38         for (; !iter.done(); iter.next()) {
     39             const SkIRect& rect = iter.rect();
     40             for (int y = rect.fTop; y < rect.fBottom; ++y) {
     41                 this->nextSpan(rect.fLeft, y, rect.width(), dst);
     42             }
     43         }
     44 
     45         this->end(dst);
     46     }
     47     return true;
     48 }
     49 
     50 void Sk2DPathEffect::nextSpan(int x, int y, int count, SkPath* path) const {
     51     if (!fMatrixIsInvertible) {
     52         return;
     53     }
     54 
     55     const SkMatrix& mat = this->getMatrix();
     56     SkPoint src, dst;
     57 
     58     src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf);
     59     do {
     60         mat.mapPoints(&dst, &src, 1);
     61         this->next(dst, x++, y, path);
     62         src.fX += SK_Scalar1;
     63     } while (--count > 0);
     64 }
     65 
     66 void Sk2DPathEffect::begin(const SkIRect& uvBounds, SkPath* dst) const {}
     67 void Sk2DPathEffect::next(const SkPoint& loc, int u, int v, SkPath* dst) const {}
     68 void Sk2DPathEffect::end(SkPath* dst) const {}
     69 
     70 ///////////////////////////////////////////////////////////////////////////////
     71 
     72 void Sk2DPathEffect::flatten(SkWriteBuffer& buffer) const {
     73     this->INHERITED::flatten(buffer);
     74     buffer.writeMatrix(fMatrix);
     75 }
     76 
     77 #ifndef SK_IGNORE_TO_STRING
     78 void Sk2DPathEffect::toString(SkString* str) const {
     79     str->appendf("(matrix: %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f)",
     80             fMatrix[SkMatrix::kMScaleX], fMatrix[SkMatrix::kMSkewX],  fMatrix[SkMatrix::kMTransX],
     81             fMatrix[SkMatrix::kMSkewY],  fMatrix[SkMatrix::kMScaleY], fMatrix[SkMatrix::kMTransY],
     82             fMatrix[SkMatrix::kMPersp0], fMatrix[SkMatrix::kMPersp1], fMatrix[SkMatrix::kMPersp2]);
     83 }
     84 #endif
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 
     88 bool SkLine2DPathEffect::filterPath(SkPath* dst, const SkPath& src,
     89                             SkStrokeRec* rec, const SkRect* cullRect) const {
     90     if (this->INHERITED::filterPath(dst, src, rec, cullRect)) {
     91         rec->setStrokeStyle(fWidth);
     92         return true;
     93     }
     94     return false;
     95 }
     96 
     97 void SkLine2DPathEffect::nextSpan(int u, int v, int ucount, SkPath* dst) const {
     98     if (ucount > 1) {
     99         SkPoint    src[2], dstP[2];
    100 
    101         src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
    102         src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
    103         this->getMatrix().mapPoints(dstP, src, 2);
    104 
    105         dst->moveTo(dstP[0]);
    106         dst->lineTo(dstP[1]);
    107     }
    108 }
    109 
    110 sk_sp<SkFlattenable> SkLine2DPathEffect::CreateProc(SkReadBuffer& buffer) {
    111     SkMatrix matrix;
    112     buffer.readMatrix(&matrix);
    113     SkScalar width = buffer.readScalar();
    114     return SkLine2DPathEffect::Make(width, matrix);
    115 }
    116 
    117 void SkLine2DPathEffect::flatten(SkWriteBuffer &buffer) const {
    118     buffer.writeMatrix(this->getMatrix());
    119     buffer.writeScalar(fWidth);
    120 }
    121 
    122 
    123 #ifndef SK_IGNORE_TO_STRING
    124 void SkLine2DPathEffect::toString(SkString* str) const {
    125     str->appendf("SkLine2DPathEffect: (");
    126     this->INHERITED::toString(str);
    127     str->appendf("width: %f", fWidth);
    128     str->appendf(")");
    129 }
    130 #endif
    131 
    132 ///////////////////////////////////////////////////////////////////////////////
    133 
    134 SkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p)
    135     : INHERITED(m), fPath(p) {
    136 }
    137 
    138 sk_sp<SkFlattenable> SkPath2DPathEffect::CreateProc(SkReadBuffer& buffer) {
    139     SkMatrix matrix;
    140     buffer.readMatrix(&matrix);
    141     SkPath path;
    142     buffer.readPath(&path);
    143     return SkPath2DPathEffect::Make(matrix, path);
    144 }
    145 
    146 void SkPath2DPathEffect::flatten(SkWriteBuffer& buffer) const {
    147     buffer.writeMatrix(this->getMatrix());
    148     buffer.writePath(fPath);
    149 }
    150 
    151 void SkPath2DPathEffect::next(const SkPoint& loc, int u, int v,
    152                               SkPath* dst) const {
    153     dst->addPath(fPath, loc.fX, loc.fY);
    154 }
    155 
    156 #ifndef SK_IGNORE_TO_STRING
    157 void SkPath2DPathEffect::toString(SkString* str) const {
    158     str->appendf("SkPath2DPathEffect: (");
    159     this->INHERITED::toString(str);
    160     // TODO: print out path information
    161     str->appendf(")");
    162 }
    163 #endif
    164