1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 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/SkStrokeRec.h" 9cb93a386Sopenharmony_ci#include "include/effects/SkOpPathEffect.h" 10cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 11cb93a386Sopenharmony_ci#include "src/core/SkRectPriv.h" 12cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 13cb93a386Sopenharmony_ci#include "src/effects/SkOpPE.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkMergePathEffect::Make(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two, 16cb93a386Sopenharmony_ci SkPathOp op) { 17cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkOpPE(std::move(one), std::move(two), op)); 18cb93a386Sopenharmony_ci} 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciSkOpPE::SkOpPE(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two, SkPathOp op) 21cb93a386Sopenharmony_ci : fOne(std::move(one)), fTwo(std::move(two)), fOp(op) {} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cibool SkOpPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 24cb93a386Sopenharmony_ci const SkRect* cull, const SkMatrix& ctm) const { 25cb93a386Sopenharmony_ci SkPath one, two; 26cb93a386Sopenharmony_ci if (fOne) { 27cb93a386Sopenharmony_ci if (!fOne->filterPath(&one, src, rec, cull, ctm)) { 28cb93a386Sopenharmony_ci return false; 29cb93a386Sopenharmony_ci } 30cb93a386Sopenharmony_ci } else { 31cb93a386Sopenharmony_ci one = src; 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci if (fTwo) { 34cb93a386Sopenharmony_ci if (!fTwo->filterPath(&two, src, rec, cull, ctm)) { 35cb93a386Sopenharmony_ci return false; 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci } else { 38cb93a386Sopenharmony_ci two = src; 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci return Op(one, two, fOp, dst); 41cb93a386Sopenharmony_ci} 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cibool SkOpPE::computeFastBounds(SkRect* bounds) const { 44cb93a386Sopenharmony_ci if (!bounds) { 45cb93a386Sopenharmony_ci return (!SkToBool(fOne) || as_PEB(fOne)->computeFastBounds(nullptr)) && 46cb93a386Sopenharmony_ci (!SkToBool(fTwo) || as_PEB(fTwo)->computeFastBounds(nullptr)); 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci // bounds will hold the result of the fOne while b2 holds the result of fTwo's fast bounds 50cb93a386Sopenharmony_ci SkRect b2 = *bounds; 51cb93a386Sopenharmony_ci if (fOne && !as_PEB(fOne)->computeFastBounds(bounds)) { 52cb93a386Sopenharmony_ci return false; 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci if (fTwo && !as_PEB(fTwo)->computeFastBounds(&b2)) { 55cb93a386Sopenharmony_ci return false; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci switch (fOp) { 59cb93a386Sopenharmony_ci case SkPathOp::kIntersect_SkPathOp: 60cb93a386Sopenharmony_ci if (!bounds->intersect(b2)) { 61cb93a386Sopenharmony_ci bounds->setEmpty(); 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci break; 64cb93a386Sopenharmony_ci case SkPathOp::kDifference_SkPathOp: 65cb93a386Sopenharmony_ci // (one - two) conservatively leaves one's bounds unmodified 66cb93a386Sopenharmony_ci break; 67cb93a386Sopenharmony_ci case SkPathOp::kReverseDifference_SkPathOp: 68cb93a386Sopenharmony_ci // (two - one) conservatively leaves two's bounds unmodified 69cb93a386Sopenharmony_ci *bounds = b2; 70cb93a386Sopenharmony_ci break; 71cb93a386Sopenharmony_ci case SkPathOp::kXOR_SkPathOp: 72cb93a386Sopenharmony_ci // fall through to union since XOR computes a subset of regular OR 73cb93a386Sopenharmony_ci case SkPathOp::kUnion_SkPathOp: 74cb93a386Sopenharmony_ci bounds->join(b2); 75cb93a386Sopenharmony_ci break; 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci return true; 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_civoid SkOpPE::flatten(SkWriteBuffer& buffer) const { 82cb93a386Sopenharmony_ci buffer.writeFlattenable(fOne.get()); 83cb93a386Sopenharmony_ci buffer.writeFlattenable(fTwo.get()); 84cb93a386Sopenharmony_ci buffer.write32(fOp); 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkOpPE::CreateProc(SkReadBuffer& buffer) { 88cb93a386Sopenharmony_ci auto one = buffer.readPathEffect(); 89cb93a386Sopenharmony_ci auto two = buffer.readPathEffect(); 90cb93a386Sopenharmony_ci SkPathOp op = buffer.read32LE(kReverseDifference_SkPathOp); 91cb93a386Sopenharmony_ci return buffer.isValid() ? SkMergePathEffect::Make(std::move(one), std::move(two), op) : nullptr; 92cb93a386Sopenharmony_ci} 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkMatrixPathEffect::MakeTranslate(SkScalar dx, SkScalar dy) { 97cb93a386Sopenharmony_ci if (!SkScalarsAreFinite(dx, dy)) { 98cb93a386Sopenharmony_ci return nullptr; 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkMatrixPE(SkMatrix::Translate(dx, dy))); 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkMatrixPathEffect::Make(const SkMatrix& matrix) { 104cb93a386Sopenharmony_ci if (!matrix.isFinite()) { 105cb93a386Sopenharmony_ci return nullptr; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkMatrixPE(matrix)); 108cb93a386Sopenharmony_ci} 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ciSkMatrixPE::SkMatrixPE(const SkMatrix& matrix) : fMatrix(matrix) { 111cb93a386Sopenharmony_ci SkASSERT(matrix.isFinite()); 112cb93a386Sopenharmony_ci} 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_cibool SkMatrixPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*, 115cb93a386Sopenharmony_ci const SkMatrix&) const { 116cb93a386Sopenharmony_ci src.transform(fMatrix, dst); 117cb93a386Sopenharmony_ci return true; 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_civoid SkMatrixPE::flatten(SkWriteBuffer& buffer) const { 121cb93a386Sopenharmony_ci buffer.writeMatrix(fMatrix); 122cb93a386Sopenharmony_ci} 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkMatrixPE::CreateProc(SkReadBuffer& buffer) { 125cb93a386Sopenharmony_ci SkMatrix mx; 126cb93a386Sopenharmony_ci buffer.readMatrix(&mx); 127cb93a386Sopenharmony_ci return buffer.isValid() ? SkMatrixPathEffect::Make(mx) : nullptr; 128cb93a386Sopenharmony_ci} 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkStrokePathEffect::Make(SkScalar width, SkPaint::Join join, SkPaint::Cap cap, 133cb93a386Sopenharmony_ci SkScalar miter) { 134cb93a386Sopenharmony_ci if (!SkScalarsAreFinite(width, miter) || width < 0 || miter < 0) { 135cb93a386Sopenharmony_ci return nullptr; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci return sk_sp<SkPathEffect>(new SkStrokePE(width, join, cap, miter)); 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ciSkStrokePE::SkStrokePE(SkScalar width, SkPaint::Join join, SkPaint::Cap cap, SkScalar miter) 141cb93a386Sopenharmony_ci : fWidth(width), fMiter(miter), fJoin(join), fCap(cap) {} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_cibool SkStrokePE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*, 144cb93a386Sopenharmony_ci const SkMatrix&) const { 145cb93a386Sopenharmony_ci SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); 146cb93a386Sopenharmony_ci rec.setStrokeStyle(fWidth); 147cb93a386Sopenharmony_ci rec.setStrokeParams(fCap, fJoin, fMiter); 148cb93a386Sopenharmony_ci return rec.applyToPath(dst, src); 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_cibool SkStrokePE::computeFastBounds(SkRect* bounds) const { 152cb93a386Sopenharmony_ci if (bounds) { 153cb93a386Sopenharmony_ci SkStrokeRec rec(SkStrokeRec::kFill_InitStyle); 154cb93a386Sopenharmony_ci rec.setStrokeStyle(fWidth); 155cb93a386Sopenharmony_ci rec.setStrokeParams(fCap, fJoin, fMiter); 156cb93a386Sopenharmony_ci bounds->outset(rec.getInflationRadius(), rec.getInflationRadius()); 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci return true; 159cb93a386Sopenharmony_ci} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_civoid SkStrokePE::flatten(SkWriteBuffer& buffer) const { 162cb93a386Sopenharmony_ci buffer.writeScalar(fWidth); 163cb93a386Sopenharmony_ci buffer.writeScalar(fMiter); 164cb93a386Sopenharmony_ci buffer.write32(fJoin); 165cb93a386Sopenharmony_ci buffer.write32(fCap); 166cb93a386Sopenharmony_ci} 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkStrokePE::CreateProc(SkReadBuffer& buffer) { 169cb93a386Sopenharmony_ci SkScalar width = buffer.readScalar(); 170cb93a386Sopenharmony_ci SkScalar miter = buffer.readScalar(); 171cb93a386Sopenharmony_ci SkPaint::Join join = buffer.read32LE(SkPaint::kLast_Join); 172cb93a386Sopenharmony_ci SkPaint::Cap cap = buffer.read32LE(SkPaint::kLast_Cap); 173cb93a386Sopenharmony_ci return buffer.isValid() ? SkStrokePathEffect::Make(width, join, cap, miter) : nullptr; 174cb93a386Sopenharmony_ci} 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci#include "include/effects/SkStrokeAndFillPathEffect.h" 179cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_cisk_sp<SkPathEffect> SkStrokeAndFillPathEffect::Make() { 182cb93a386Sopenharmony_ci static SkPathEffect* strokeAndFill = new SkStrokeAndFillPE; 183cb93a386Sopenharmony_ci return sk_ref_sp(strokeAndFill); 184cb93a386Sopenharmony_ci} 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_civoid SkStrokeAndFillPE::flatten(SkWriteBuffer&) const {} 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_cistatic bool known_to_be_opposite_directions(const SkPath& a, const SkPath& b) { 189cb93a386Sopenharmony_ci auto a_dir = SkPathPriv::ComputeFirstDirection(a), 190cb93a386Sopenharmony_ci b_dir = SkPathPriv::ComputeFirstDirection(b); 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci return (a_dir == SkPathFirstDirection::kCCW && 193cb93a386Sopenharmony_ci b_dir == SkPathFirstDirection::kCW) 194cb93a386Sopenharmony_ci || 195cb93a386Sopenharmony_ci (a_dir == SkPathFirstDirection::kCW && 196cb93a386Sopenharmony_ci b_dir == SkPathFirstDirection::kCCW); 197cb93a386Sopenharmony_ci} 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_cibool SkStrokeAndFillPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 200cb93a386Sopenharmony_ci const SkRect*, const SkMatrix&) const { 201cb93a386Sopenharmony_ci // This one is weird, since we exist to allow this paint-style to go away. If we see it, 202cb93a386Sopenharmony_ci // just let the normal machine run its course. 203cb93a386Sopenharmony_ci if (rec->getStyle() == SkStrokeRec::kStrokeAndFill_Style) { 204cb93a386Sopenharmony_ci *dst = src; 205cb93a386Sopenharmony_ci return true; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci if (rec->getStyle() == SkStrokeRec::kStroke_Style) { 209cb93a386Sopenharmony_ci if (!rec->applyToPath(dst, src)) { 210cb93a386Sopenharmony_ci return false; 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci if (known_to_be_opposite_directions(src, *dst)) { 214cb93a386Sopenharmony_ci dst->reverseAddPath(src); 215cb93a386Sopenharmony_ci } else { 216cb93a386Sopenharmony_ci dst->addPath(src); 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci } else { 219cb93a386Sopenharmony_ci *dst = src; 220cb93a386Sopenharmony_ci } 221cb93a386Sopenharmony_ci rec->setFillStyle(); 222cb93a386Sopenharmony_ci return true; 223cb93a386Sopenharmony_ci} 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_cisk_sp<SkFlattenable> SkStrokeAndFillPE::CreateProc(SkReadBuffer& buffer) { 226cb93a386Sopenharmony_ci return SkStrokeAndFillPathEffect::Make(); 227cb93a386Sopenharmony_ci} 228