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