1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkStrokeRec.h" 9 #include "SkPaintDefaults.h" 10 11 // must be < 0, since ==0 means hairline, and >0 means normal stroke 12 #define kStrokeRec_FillStyleWidth (-SK_Scalar1) 13 14 SkStrokeRec::SkStrokeRec(InitStyle s) { 15 fResScale = 1; 16 fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; 17 fMiterLimit = SkPaintDefaults_MiterLimit; 18 fCap = SkPaint::kDefault_Cap; 19 fJoin = SkPaint::kDefault_Join; 20 fStrokeAndFill = false; 21 } 22 23 SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) { 24 memcpy(this, &src, sizeof(src)); 25 } 26 27 SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) { 28 this->init(paint, paint.getStyle(), resScale); 29 } 30 31 SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) { 32 this->init(paint, styleOverride, resScale); 33 } 34 35 void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) { 36 fResScale = resScale; 37 38 switch (style) { 39 case SkPaint::kFill_Style: 40 fWidth = kStrokeRec_FillStyleWidth; 41 fStrokeAndFill = false; 42 break; 43 case SkPaint::kStroke_Style: 44 fWidth = paint.getStrokeWidth(); 45 fStrokeAndFill = false; 46 break; 47 case SkPaint::kStrokeAndFill_Style: 48 if (0 == paint.getStrokeWidth()) { 49 // hairline+fill == fill 50 fWidth = kStrokeRec_FillStyleWidth; 51 fStrokeAndFill = false; 52 } else { 53 fWidth = paint.getStrokeWidth(); 54 fStrokeAndFill = true; 55 } 56 break; 57 default: 58 SkDEBUGFAIL("unknown paint style"); 59 // fall back on just fill 60 fWidth = kStrokeRec_FillStyleWidth; 61 fStrokeAndFill = false; 62 break; 63 } 64 65 // copy these from the paint, regardless of our "style" 66 fMiterLimit = paint.getStrokeMiter(); 67 fCap = paint.getStrokeCap(); 68 fJoin = paint.getStrokeJoin(); 69 } 70 71 SkStrokeRec::Style SkStrokeRec::getStyle() const { 72 if (fWidth < 0) { 73 return kFill_Style; 74 } else if (0 == fWidth) { 75 return kHairline_Style; 76 } else { 77 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 78 } 79 } 80 81 void SkStrokeRec::setFillStyle() { 82 fWidth = kStrokeRec_FillStyleWidth; 83 fStrokeAndFill = false; 84 } 85 86 void SkStrokeRec::setHairlineStyle() { 87 fWidth = 0; 88 fStrokeAndFill = false; 89 } 90 91 void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { 92 if (strokeAndFill && (0 == width)) { 93 // hairline+fill == fill 94 this->setFillStyle(); 95 } else { 96 fWidth = width; 97 fStrokeAndFill = strokeAndFill; 98 } 99 } 100 101 #include "SkStroke.h" 102 103 #if !defined SK_LEGACY_STROKE_CURVES && defined SK_DEBUG 104 // enables tweaking these values at runtime from SampleApp 105 bool gDebugStrokerErrorSet = false; 106 SkScalar gDebugStrokerError; 107 #endif 108 109 bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 110 if (fWidth <= 0) { // hairline or fill 111 return false; 112 } 113 114 SkStroke stroker; 115 stroker.setCap(fCap); 116 stroker.setJoin(fJoin); 117 stroker.setMiterLimit(fMiterLimit); 118 stroker.setWidth(fWidth); 119 stroker.setDoFill(fStrokeAndFill); 120 #if !defined SK_LEGACY_STROKE_CURVES && defined SK_DEBUG 121 stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale); 122 #else 123 stroker.setResScale(fResScale); 124 #endif 125 stroker.strokePath(src, dst); 126 return true; 127 } 128 129 void SkStrokeRec::applyToPaint(SkPaint* paint) const { 130 if (fWidth < 0) { // fill 131 paint->setStyle(SkPaint::kFill_Style); 132 return; 133 } 134 135 paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); 136 paint->setStrokeWidth(fWidth); 137 paint->setStrokeMiter(fMiterLimit); 138 paint->setStrokeCap(fCap); 139 paint->setStrokeJoin(fJoin); 140 } 141