michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "Sk2DPathEffect.h" michael@0: #include "SkReadBuffer.h" michael@0: #include "SkWriteBuffer.h" michael@0: #include "SkPath.h" michael@0: #include "SkRegion.h" michael@0: michael@0: Sk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) { michael@0: fMatrixIsInvertible = mat.invert(&fInverse); michael@0: } michael@0: michael@0: bool Sk2DPathEffect::filterPath(SkPath* dst, const SkPath& src, michael@0: SkStrokeRec*, const SkRect*) const { michael@0: if (!fMatrixIsInvertible) { michael@0: return false; michael@0: } michael@0: michael@0: SkPath tmp; michael@0: SkIRect ir; michael@0: michael@0: src.transform(fInverse, &tmp); michael@0: tmp.getBounds().round(&ir); michael@0: if (!ir.isEmpty()) { michael@0: this->begin(ir, dst); michael@0: michael@0: SkRegion rgn; michael@0: rgn.setPath(tmp, SkRegion(ir)); michael@0: SkRegion::Iterator iter(rgn); michael@0: for (; !iter.done(); iter.next()) { michael@0: const SkIRect& rect = iter.rect(); michael@0: for (int y = rect.fTop; y < rect.fBottom; ++y) { michael@0: this->nextSpan(rect.fLeft, y, rect.width(), dst); michael@0: } michael@0: } michael@0: michael@0: this->end(dst); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void Sk2DPathEffect::nextSpan(int x, int y, int count, SkPath* path) const { michael@0: if (!fMatrixIsInvertible) { michael@0: return; michael@0: } michael@0: michael@0: const SkMatrix& mat = this->getMatrix(); michael@0: SkPoint src, dst; michael@0: michael@0: src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf); michael@0: do { michael@0: mat.mapPoints(&dst, &src, 1); michael@0: this->next(dst, x++, y, path); michael@0: src.fX += SK_Scalar1; michael@0: } while (--count > 0); michael@0: } michael@0: michael@0: void Sk2DPathEffect::begin(const SkIRect& uvBounds, SkPath* dst) const {} michael@0: void Sk2DPathEffect::next(const SkPoint& loc, int u, int v, SkPath* dst) const {} michael@0: void Sk2DPathEffect::end(SkPath* dst) const {} michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: void Sk2DPathEffect::flatten(SkWriteBuffer& buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: buffer.writeMatrix(fMatrix); michael@0: } michael@0: michael@0: Sk2DPathEffect::Sk2DPathEffect(SkReadBuffer& buffer) { michael@0: buffer.readMatrix(&fMatrix); michael@0: fMatrixIsInvertible = fMatrix.invert(&fInverse); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: bool SkLine2DPathEffect::filterPath(SkPath* dst, const SkPath& src, michael@0: SkStrokeRec* rec, const SkRect* cullRect) const { michael@0: if (this->INHERITED::filterPath(dst, src, rec, cullRect)) { michael@0: rec->setStrokeStyle(fWidth); michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: void SkLine2DPathEffect::nextSpan(int u, int v, int ucount, SkPath* dst) const { michael@0: if (ucount > 1) { michael@0: SkPoint src[2], dstP[2]; michael@0: michael@0: src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); michael@0: src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); michael@0: this->getMatrix().mapPoints(dstP, src, 2); michael@0: michael@0: dst->moveTo(dstP[0]); michael@0: dst->lineTo(dstP[1]); michael@0: } michael@0: } michael@0: michael@0: SkLine2DPathEffect::SkLine2DPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) { michael@0: fWidth = buffer.readScalar(); michael@0: } michael@0: michael@0: void SkLine2DPathEffect::flatten(SkWriteBuffer &buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: buffer.writeScalar(fWidth); michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p) michael@0: : INHERITED(m), fPath(p) { michael@0: } michael@0: michael@0: SkPath2DPathEffect::SkPath2DPathEffect(SkReadBuffer& buffer) michael@0: : INHERITED(buffer) { michael@0: buffer.readPath(&fPath); michael@0: } michael@0: michael@0: void SkPath2DPathEffect::flatten(SkWriteBuffer& buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: buffer.writePath(fPath); michael@0: } michael@0: michael@0: void SkPath2DPathEffect::next(const SkPoint& loc, int u, int v, michael@0: SkPath* dst) const { michael@0: dst->addPath(fPath, loc.fX, loc.fY); michael@0: }