SkPathEffect.cpp revision e4f10a70807166484e5a6303a5cd0034e5e87aba
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 "SkPathEffect.h" 11#include "SkPath.h" 12#include "SkBuffer.h" 13 14void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) { 15 *dst = src; 16} 17 18/////////////////////////////////////////////////////////////////////////////// 19 20SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1) 21 : fPE0(pe0), fPE1(pe1) { 22 SkASSERT(pe0); 23 SkASSERT(pe1); 24 fPE0->ref(); 25 fPE1->ref(); 26} 27 28SkPairPathEffect::~SkPairPathEffect() { 29 SkSafeUnref(fPE0); 30 SkSafeUnref(fPE1); 31} 32 33/* 34 Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data] 35*/ 36void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 37 this->INHERITED::flatten(buffer); 38 buffer.writeFlattenable(fPE0); 39 buffer.writeFlattenable(fPE1); 40} 41 42SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) { 43 fPE0 = (SkPathEffect*)buffer.readFlattenable(); 44 fPE1 = (SkPathEffect*)buffer.readFlattenable(); 45 // either of these may fail, so we have to check for nulls later on 46} 47 48/////////////////////////////////////////////////////////////////////////////// 49 50bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, 51 SkScalar* width) { 52 // we may have failed to unflatten these, so we have to check 53 if (!fPE0 || !fPE1) { 54 return false; 55 } 56 57 SkPath tmp; 58 const SkPath* ptr = &src; 59 60 if (fPE1->filterPath(&tmp, src, width)) { 61 ptr = &tmp; 62 } 63 return fPE0->filterPath(dst, *ptr, width); 64} 65 66/////////////////////////////////////////////////////////////////////////////// 67 68bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src, 69 SkScalar* width) { 70 // use bit-or so that we always call both, even if the first one succeeds 71 return fPE0->filterPath(dst, src, width) | fPE1->filterPath(dst, src, width); 72} 73 74/////////////////////////////////////////////////////////////////////////////// 75 76#include "SkStroke.h" 77 78/** \class SkStrokePathEffect 79 80 SkStrokePathEffect simulates stroking inside a patheffect, allowing the 81 caller to have explicit control of when to stroke a path. Typically this is 82 used if the caller wants to stroke before another patheffect is applied 83 (using SkComposePathEffect or SkSumPathEffect). 84 */ 85class SkStrokePathEffect : public SkPathEffect { 86public: 87 SkStrokePathEffect(const SkPaint&); 88 SkStrokePathEffect(SkScalar width, SkPaint::Style, SkPaint::Join, 89 SkPaint::Cap, SkScalar miterLimit = -1); 90 91 // overrides 92 virtual bool filterPath(SkPath* dst, const SkPath& src, SkScalar* width); 93 94 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkStrokePathEffect) 95 96protected: 97 SkStrokePathEffect(SkFlattenableReadBuffer&); 98 virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; 99 100private: 101 SkScalar fWidth, fMiter; 102 uint8_t fStyle, fJoin, fCap; 103 104 typedef SkPathEffect INHERITED; 105 106 // illegal 107 SkStrokePathEffect(const SkStrokePathEffect&); 108 SkStrokePathEffect& operator=(const SkStrokePathEffect&); 109}; 110 111SkStrokePathEffect::SkStrokePathEffect(const SkPaint& paint) 112 : fWidth(paint.getStrokeWidth()), fMiter(paint.getStrokeMiter()), 113 fStyle(SkToU8(paint.getStyle())), fJoin(SkToU8(paint.getStrokeJoin())), 114 fCap(SkToU8(paint.getStrokeCap())) { 115} 116 117SkStrokePathEffect::SkStrokePathEffect(SkScalar width, SkPaint::Style style, 118 SkPaint::Join join, SkPaint::Cap cap, SkScalar miter) 119 : fWidth(width), fMiter(miter), fStyle(SkToU8(style)), 120 fJoin(SkToU8(join)), fCap(SkToU8(cap)) { 121 if (miter < 0) { // signal they want the default 122 fMiter = SkIntToScalar(4); 123 } 124} 125 126bool SkStrokePathEffect::filterPath(SkPath* dst, const SkPath& src, 127 SkScalar* width) { 128 if (fWidth < 0 || fStyle == SkPaint::kFill_Style) { 129 return false; 130 } 131 132 if (fStyle == SkPaint::kStroke_Style && fWidth == 0) { // hairline 133 *width = 0; 134 return true; 135 } 136 137 SkStroke stroke; 138 139 stroke.setWidth(fWidth); 140 stroke.setMiterLimit(fMiter); 141 stroke.setJoin((SkPaint::Join)fJoin); 142 stroke.setCap((SkPaint::Cap)fCap); 143 stroke.setDoFill(fStyle == SkPaint::kStrokeAndFill_Style); 144 145 stroke.strokePath(src, dst); 146 return true; 147} 148 149void SkStrokePathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 150 this->INHERITED::flatten(buffer); 151 buffer.writeScalar(fWidth); 152 buffer.writeScalar(fMiter); 153 buffer.write8(fStyle); 154 buffer.write8(fJoin); 155 buffer.write8(fCap); 156} 157 158SkStrokePathEffect::SkStrokePathEffect(SkFlattenableReadBuffer& buffer) { 159 fWidth = buffer.readScalar(); 160 fMiter = buffer.readScalar(); 161 fStyle = buffer.readU8(); 162 fJoin = buffer.readU8(); 163 fCap = buffer.readU8(); 164} 165 166/////////////////////////////////////////////////////////////////////////////// 167 168SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposePathEffect) 169//SK_DEFINE_FLATTENABLE_REGISTRAR(SkStrokePathEffect) 170SK_DEFINE_FLATTENABLE_REGISTRAR(SkSumPathEffect) 171 172