SkPathEffect.cpp revision fd4be26c4202ae91f0f7cf2c03e44b5169d885eb
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#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 fWidth = paint.getStrokeWidth(); 42 fStrokeAndFill = true; 43 break; 44 default: 45 SkASSERT(!"unknown paint style"); 46 // fall back on just fill 47 fWidth = kStrokeRec_FillStyleWidth; 48 fStrokeAndFill = false; 49 break; 50 } 51 52 // copy these from the paint, regardless of our "style" 53 fMiterLimit = paint.getStrokeMiter(); 54 fCap = paint.getStrokeCap(); 55 fJoin = paint.getStrokeJoin(); 56} 57 58SkStrokeRec::Style SkStrokeRec::getStyle() const { 59 if (fWidth < 0) { 60 return kFill_Style; 61 } else if (0 == fWidth) { 62 return kHairline_Style; 63 } else { 64 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 65 } 66} 67 68void SkStrokeRec::setFillStyle() { 69 fWidth = kStrokeRec_FillStyleWidth; 70} 71 72#include "SkStroke.h" 73 74bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 75 if (fWidth <= 0) { // hairline or fill 76 return false; 77 } 78 79 SkStroke stroker; 80 stroker.setCap(fCap); 81 stroker.setJoin(fJoin); 82 stroker.setMiterLimit(fMiterLimit); 83 stroker.setWidth(fWidth); 84 stroker.setDoFill(fStrokeAndFill); 85 stroker.strokePath(src, dst); 86 return true; 87} 88 89/////////////////////////////////////////////////////////////////////////////// 90 91void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) { 92 *dst = src; 93} 94 95/////////////////////////////////////////////////////////////////////////////// 96 97SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1) 98 : fPE0(pe0), fPE1(pe1) { 99 SkASSERT(pe0); 100 SkASSERT(pe1); 101 fPE0->ref(); 102 fPE1->ref(); 103} 104 105SkPairPathEffect::~SkPairPathEffect() { 106 SkSafeUnref(fPE0); 107 SkSafeUnref(fPE1); 108} 109 110/* 111 Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data] 112*/ 113void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const { 114 this->INHERITED::flatten(buffer); 115 buffer.writeFlattenable(fPE0); 116 buffer.writeFlattenable(fPE1); 117} 118 119SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) { 120 fPE0 = (SkPathEffect*)buffer.readFlattenable(); 121 fPE1 = (SkPathEffect*)buffer.readFlattenable(); 122 // either of these may fail, so we have to check for nulls later on 123} 124 125/////////////////////////////////////////////////////////////////////////////// 126 127bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, 128 SkStrokeRec* rec) { 129 // we may have failed to unflatten these, so we have to check 130 if (!fPE0 || !fPE1) { 131 return false; 132 } 133 134 SkPath tmp; 135 const SkPath* ptr = &src; 136 137 if (fPE1->filterPath(&tmp, src, rec)) { 138 ptr = &tmp; 139 } 140 return fPE0->filterPath(dst, *ptr, rec); 141} 142 143/////////////////////////////////////////////////////////////////////////////// 144 145bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src, 146 SkStrokeRec* rec) { 147 // use bit-or so that we always call both, even if the first one succeeds 148 return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec); 149} 150 151/////////////////////////////////////////////////////////////////////////////// 152 153SK_DEFINE_FLATTENABLE_REGISTRAR(SkComposePathEffect) 154SK_DEFINE_FLATTENABLE_REGISTRAR(SkSumPathEffect) 155 156