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 SkPaint& paint, SkScalar resScale) { 24 this->init(paint, paint.getStyle(), resScale); 25 } 26 27 SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) { 28 this->init(paint, styleOverride, resScale); 29 } 30 31 void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) { 32 fResScale = resScale; 33 34 switch (style) { 35 case SkPaint::kFill_Style: 36 fWidth = kStrokeRec_FillStyleWidth; 37 fStrokeAndFill = false; 38 break; 39 case SkPaint::kStroke_Style: 40 fWidth = paint.getStrokeWidth(); 41 fStrokeAndFill = false; 42 break; 43 case SkPaint::kStrokeAndFill_Style: 44 if (0 == paint.getStrokeWidth()) { 45 // hairline+fill == fill 46 fWidth = kStrokeRec_FillStyleWidth; 47 fStrokeAndFill = false; 48 } else { 49 fWidth = paint.getStrokeWidth(); 50 fStrokeAndFill = true; 51 } 52 break; 53 default: 54 SkDEBUGFAIL("unknown paint style"); 55 // fall back on just fill 56 fWidth = kStrokeRec_FillStyleWidth; 57 fStrokeAndFill = false; 58 break; 59 } 60 61 // copy these from the paint, regardless of our "style" 62 fMiterLimit = paint.getStrokeMiter(); 63 fCap = paint.getStrokeCap(); 64 fJoin = paint.getStrokeJoin(); 65 } 66 67 SkStrokeRec::Style SkStrokeRec::getStyle() const { 68 if (fWidth < 0) { 69 return kFill_Style; 70 } else if (0 == fWidth) { 71 return kHairline_Style; 72 } else { 73 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 74 } 75 } 76 77 void SkStrokeRec::setFillStyle() { 78 fWidth = kStrokeRec_FillStyleWidth; 79 fStrokeAndFill = false; 80 } 81 82 void SkStrokeRec::setHairlineStyle() { 83 fWidth = 0; 84 fStrokeAndFill = false; 85 } 86 87 void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { 88 if (strokeAndFill && (0 == width)) { 89 // hairline+fill == fill 90 this->setFillStyle(); 91 } else { 92 fWidth = width; 93 fStrokeAndFill = strokeAndFill; 94 } 95 } 96 97 #include "SkStroke.h" 98 99 #ifdef SK_DEBUG 100 // enables tweaking these values at runtime from SampleApp 101 bool gDebugStrokerErrorSet = false; 102 SkScalar gDebugStrokerError; 103 #endif 104 105 bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 106 if (fWidth <= 0) { // hairline or fill 107 return false; 108 } 109 110 SkStroke stroker; 111 stroker.setCap((SkPaint::Cap)fCap); 112 stroker.setJoin((SkPaint::Join)fJoin); 113 stroker.setMiterLimit(fMiterLimit); 114 stroker.setWidth(fWidth); 115 stroker.setDoFill(fStrokeAndFill); 116 #ifdef SK_DEBUG 117 stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale); 118 #else 119 stroker.setResScale(fResScale); 120 #endif 121 stroker.strokePath(src, dst); 122 return true; 123 } 124 125 void SkStrokeRec::applyToPaint(SkPaint* paint) const { 126 if (fWidth < 0) { // fill 127 paint->setStyle(SkPaint::kFill_Style); 128 return; 129 } 130 131 paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); 132 paint->setStrokeWidth(fWidth); 133 paint->setStrokeMiter(fMiterLimit); 134 paint->setStrokeCap((SkPaint::Cap)fCap); 135 paint->setStrokeJoin((SkPaint::Join)fJoin); 136 } 137