SkPathEffect.cpp revision 687c57c7d5a17549f63e0b15208db18b220e2a91
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 "SkFlattenableBuffers.h" 13#include "SkPaintDefaults.h" 14 15// must be < 0, since ==0 means hairline, and >0 means normal stroke 16#define kStrokeRec_FillStyleWidth (-SK_Scalar1) 17 18SkStrokeRec::SkStrokeRec(InitStyle s) { 19 fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; 20 fMiterLimit = SkPaintDefaults_MiterLimit; 21 fCap = SkPaint::kDefault_Cap; 22 fJoin = SkPaint::kDefault_Join; 23 fStrokeAndFill = false; 24} 25 26SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) { 27 memcpy(this, &src, sizeof(src)); 28} 29 30SkStrokeRec::SkStrokeRec(const SkPaint& paint) { 31 switch (paint.getStyle()) { 32 case SkPaint::kFill_Style: 33 fWidth = kStrokeRec_FillStyleWidth; 34 fStrokeAndFill = false; 35 break; 36 case SkPaint::kStroke_Style: 37 fWidth = paint.getStrokeWidth(); 38 fStrokeAndFill = false; 39 break; 40 case SkPaint::kStrokeAndFill_Style: 41 if (0 == paint.getStrokeWidth()) { 42 // hairline+fill == fill 43 fWidth = kStrokeRec_FillStyleWidth; 44 fStrokeAndFill = false; 45 } else { 46 fWidth = paint.getStrokeWidth(); 47 fStrokeAndFill = true; 48 } 49 break; 50 default: 51 SkASSERT(!"unknown paint style"); 52 // fall back on just fill 53 fWidth = kStrokeRec_FillStyleWidth; 54 fStrokeAndFill = false; 55 break; 56 } 57 58 // copy these from the paint, regardless of our "style" 59 fMiterLimit = paint.getStrokeMiter(); 60 fCap = paint.getStrokeCap(); 61 fJoin = paint.getStrokeJoin(); 62} 63 64SkStrokeRec::Style SkStrokeRec::getStyle() const { 65 if (fWidth < 0) { 66 return kFill_Style; 67 } else if (0 == fWidth) { 68 return kHairline_Style; 69 } else { 70 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 71 } 72} 73 74void SkStrokeRec::setFillStyle() { 75 fWidth = kStrokeRec_FillStyleWidth; 76 fStrokeAndFill = false; 77} 78 79void SkStrokeRec::setHairlineStyle() { 80 fWidth = 0; 81 fStrokeAndFill = false; 82} 83 84void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { 85 if (strokeAndFill && (0 == width)) { 86 // hairline+fill == fill 87 this->setFillStyle(); 88 } else { 89 fWidth = width; 90 fStrokeAndFill = strokeAndFill; 91 } 92} 93 94#include "SkStroke.h" 95 96bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 97 if (fWidth <= 0) { // hairline or fill 98 return false; 99 } 100 101 SkStroke stroker; 102 stroker.setCap(fCap); 103 stroker.setJoin(fJoin); 104 stroker.setMiterLimit(fMiterLimit); 105 stroker.setWidth(fWidth); 106 stroker.setDoFill(fStrokeAndFill); 107 stroker.strokePath(src, dst); 108 return true; 109} 110 111/////////////////////////////////////////////////////////////////////////////// 112 113SK_DEFINE_INST_COUNT(SkPathEffect) 114 115void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) { 116 *dst = src; 117} 118 119bool SkPathEffect::asPoints(PointData* results, const SkPath& src, 120 const SkStrokeRec&, const SkMatrix&) const { 121 return false; 122} 123 124/////////////////////////////////////////////////////////////////////////////// 125 126SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1) 127 : fPE0(pe0), fPE1(pe1) { 128 SkASSERT(pe0); 129 SkASSERT(pe1); 130 fPE0->ref(); 131 fPE1->ref(); 132} 133 134SkPairPathEffect::~SkPairPathEffect() { 135 SkSafeUnref(fPE0); 136 SkSafeUnref(fPE1); 137} 138 139/* 140 Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data] 141*/ 142void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 143 this->INHERITED::flatten(buffer); 144 buffer.writeFlattenable(fPE0); 145 buffer.writeFlattenable(fPE1); 146} 147 148SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) { 149 fPE0 = buffer.readFlattenableT<SkPathEffect>(); 150 fPE1 = buffer.readFlattenableT<SkPathEffect>(); 151 // either of these may fail, so we have to check for nulls later on 152} 153 154/////////////////////////////////////////////////////////////////////////////// 155 156bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, 157 SkStrokeRec* rec) { 158 // we may have failed to unflatten these, so we have to check 159 if (!fPE0 || !fPE1) { 160 return false; 161 } 162 163 SkPath tmp; 164 const SkPath* ptr = &src; 165 166 if (fPE1->filterPath(&tmp, src, rec)) { 167 ptr = &tmp; 168 } 169 return fPE0->filterPath(dst, *ptr, rec); 170} 171 172/////////////////////////////////////////////////////////////////////////////// 173 174bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src, 175 SkStrokeRec* rec) { 176 // use bit-or so that we always call both, even if the first one succeeds 177 return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec); 178} 179