1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 9cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 10cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 11cb93a386Sopenharmony_ci#include "include/effects/Sk2DPathEffect.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPathEffectBase.h" 13cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 14cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciclass Sk2DPathEffect : public SkPathEffectBase { 17cb93a386Sopenharmony_cipublic: 18cb93a386Sopenharmony_ci Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) { 19cb93a386Sopenharmony_ci // Calling invert will set the type mask on both matrices, making them thread safe. 20cb93a386Sopenharmony_ci fMatrixIsInvertible = fMatrix.invert(&fInverse); 21cb93a386Sopenharmony_ci } 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciprotected: 24cb93a386Sopenharmony_ci /** New virtual, to be overridden by subclasses. 25cb93a386Sopenharmony_ci This is called once from filterPath, and provides the 26cb93a386Sopenharmony_ci uv parameter bounds for the path. Subsequent calls to 27cb93a386Sopenharmony_ci next() will receive u and v values within these bounds, 28cb93a386Sopenharmony_ci and then a call to end() will signal the end of processing. 29cb93a386Sopenharmony_ci */ 30cb93a386Sopenharmony_ci virtual void begin(const SkIRect& uvBounds, SkPath* dst) const {} 31cb93a386Sopenharmony_ci virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const {} 32cb93a386Sopenharmony_ci virtual void end(SkPath* dst) const {} 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci /** Low-level virtual called per span of locations in the u-direction. 35cb93a386Sopenharmony_ci The default implementation calls next() repeatedly with each 36cb93a386Sopenharmony_ci location. 37cb93a386Sopenharmony_ci */ 38cb93a386Sopenharmony_ci virtual void nextSpan(int x, int y, int ucount, SkPath* path) const { 39cb93a386Sopenharmony_ci if (!fMatrixIsInvertible) { 40cb93a386Sopenharmony_ci return; 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci #if defined(SK_BUILD_FOR_FUZZER) 43cb93a386Sopenharmony_ci if (ucount > 100) { 44cb93a386Sopenharmony_ci return; 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci #endif 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci const SkMatrix& mat = this->getMatrix(); 49cb93a386Sopenharmony_ci SkPoint src, dst; 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf); 52cb93a386Sopenharmony_ci do { 53cb93a386Sopenharmony_ci mat.mapPoints(&dst, &src, 1); 54cb93a386Sopenharmony_ci this->next(dst, x++, y, path); 55cb93a386Sopenharmony_ci src.fX += SK_Scalar1; 56cb93a386Sopenharmony_ci } while (--ucount > 0); 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci const SkMatrix& getMatrix() const { return fMatrix; } 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci void flatten(SkWriteBuffer& buffer) const override { 62cb93a386Sopenharmony_ci this->INHERITED::flatten(buffer); 63cb93a386Sopenharmony_ci buffer.writeMatrix(fMatrix); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ci bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 67cb93a386Sopenharmony_ci const SkRect* cullRect, const SkMatrix&) const override { 68cb93a386Sopenharmony_ci if (!fMatrixIsInvertible) { 69cb93a386Sopenharmony_ci return false; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci SkPath tmp; 73cb93a386Sopenharmony_ci SkIRect ir; 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci src.transform(fInverse, &tmp); 76cb93a386Sopenharmony_ci tmp.getBounds().round(&ir); 77cb93a386Sopenharmony_ci if (!ir.isEmpty()) { 78cb93a386Sopenharmony_ci this->begin(ir, dst); 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci SkRegion rgn; 81cb93a386Sopenharmony_ci rgn.setPath(tmp, SkRegion(ir)); 82cb93a386Sopenharmony_ci SkRegion::Iterator iter(rgn); 83cb93a386Sopenharmony_ci for (; !iter.done(); iter.next()) { 84cb93a386Sopenharmony_ci const SkIRect& rect = iter.rect(); 85cb93a386Sopenharmony_ci for (int y = rect.fTop; y < rect.fBottom; ++y) { 86cb93a386Sopenharmony_ci this->nextSpan(rect.fLeft, y, rect.width(), dst); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci this->end(dst); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci return true; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ciprivate: 96cb93a386Sopenharmony_ci SkMatrix fMatrix, fInverse; 97cb93a386Sopenharmony_ci bool fMatrixIsInvertible; 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci // For simplicity, assume fast bounds cannot be computed 100cb93a386Sopenharmony_ci bool computeFastBounds(SkRect*) const override { return false; } 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci friend class Sk2DPathEffectBlitter; 103cb93a386Sopenharmony_ci using INHERITED = SkPathEffect; 104cb93a386Sopenharmony_ci}; 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ciclass SkLine2DPathEffectImpl : public Sk2DPathEffect { 109cb93a386Sopenharmony_cipublic: 110cb93a386Sopenharmony_ci SkLine2DPathEffectImpl(SkScalar width, const SkMatrix& matrix) 111cb93a386Sopenharmony_ci : Sk2DPathEffect(matrix) 112cb93a386Sopenharmony_ci , fWidth(width) 113cb93a386Sopenharmony_ci { 114cb93a386Sopenharmony_ci SkASSERT(width >= 0); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 118cb93a386Sopenharmony_ci const SkRect* cullRect, const SkMatrix& ctm) const override { 119cb93a386Sopenharmony_ci if (this->INHERITED::onFilterPath(dst, src, rec, cullRect, ctm)) { 120cb93a386Sopenharmony_ci rec->setStrokeStyle(fWidth); 121cb93a386Sopenharmony_ci return true; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci return false; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci void nextSpan(int u, int v, int ucount, SkPath* dst) const override { 127cb93a386Sopenharmony_ci if (ucount > 1) { 128cb93a386Sopenharmony_ci SkPoint src[2], dstP[2]; 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); 131cb93a386Sopenharmony_ci src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); 132cb93a386Sopenharmony_ci this->getMatrix().mapPoints(dstP, src, 2); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci dst->moveTo(dstP[0]); 135cb93a386Sopenharmony_ci dst->lineTo(dstP[1]); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { 140cb93a386Sopenharmony_ci SkMatrix matrix; 141cb93a386Sopenharmony_ci buffer.readMatrix(&matrix); 142cb93a386Sopenharmony_ci SkScalar width = buffer.readScalar(); 143cb93a386Sopenharmony_ci return SkLine2DPathEffect::Make(width, matrix); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci void flatten(SkWriteBuffer &buffer) const override { 147cb93a386Sopenharmony_ci buffer.writeMatrix(this->getMatrix()); 148cb93a386Sopenharmony_ci buffer.writeScalar(fWidth); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci Factory getFactory() const override { return CreateProc; } 152cb93a386Sopenharmony_ci const char* getTypeName() const override { return "SkLine2DPathEffectImpl"; } 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ciprivate: 155cb93a386Sopenharmony_ci SkScalar fWidth; 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci using INHERITED = Sk2DPathEffect; 158cb93a386Sopenharmony_ci}; 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////// 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ciclass SK_API SkPath2DPathEffectImpl : public Sk2DPathEffect { 163cb93a386Sopenharmony_cipublic: 164cb93a386Sopenharmony_ci SkPath2DPathEffectImpl(const SkMatrix& m, const SkPath& p) : INHERITED(m), fPath(p) {} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci void next(const SkPoint& loc, int u, int v, SkPath* dst) const override { 167cb93a386Sopenharmony_ci dst->addPath(fPath, loc.fX, loc.fY); 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { 171cb93a386Sopenharmony_ci SkMatrix matrix; 172cb93a386Sopenharmony_ci buffer.readMatrix(&matrix); 173cb93a386Sopenharmony_ci SkPath path; 174cb93a386Sopenharmony_ci buffer.readPath(&path); 175cb93a386Sopenharmony_ci return SkPath2DPathEffect::Make(matrix, path); 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci void flatten(SkWriteBuffer& buffer) const override { 179cb93a386Sopenharmony_ci buffer.writeMatrix(this->getMatrix()); 180cb93a386Sopenharmony_ci buffer.writePath(fPath); 181cb93a386Sopenharmony_ci } 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci Factory getFactory() const override { return CreateProc; } 184cb93a386Sopenharmony_ci const char* getTypeName() const override { return "SkPath2DPathEffectImpl"; } 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ciprivate: 187cb93a386Sopenharmony_ci SkPath fPath; 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci using INHERITED = Sk2DPathEffect; 190cb93a386Sopenharmony_ci}; 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkLine2DPathEffect::Make(SkScalar width, const SkMatrix& matrix) { 195cb93a386Sopenharmony_ci if (!(width >= 0)) { 196cb93a386Sopenharmony_ci return nullptr; 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkLine2DPathEffectImpl(width, matrix)); 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkPath2DPathEffect::Make(const SkMatrix& matrix, const SkPath& path) { 202cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkPath2DPathEffectImpl(matrix, path)); 203cb93a386Sopenharmony_ci} 204cb93a386Sopenharmony_ci 205cb93a386Sopenharmony_civoid SkLine2DPathEffect::RegisterFlattenables() { 206cb93a386Sopenharmony_ci SK_REGISTER_FLATTENABLE(SkLine2DPathEffectImpl); 207cb93a386Sopenharmony_ci} 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_civoid SkPath2DPathEffect::RegisterFlattenables() { 210cb93a386Sopenharmony_ci SK_REGISTER_FLATTENABLE(SkPath2DPathEffectImpl); 211cb93a386Sopenharmony_ci} 212