1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 9cb93a386Sopenharmony_ci#include "src/core/SkPaintDefaults.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci// must be < 0, since ==0 means hairline, and >0 means normal stroke 12cb93a386Sopenharmony_ci#define kStrokeRec_FillStyleWidth (-SK_Scalar1) 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ciSkStrokeRec::SkStrokeRec(InitStyle s) { 15cb93a386Sopenharmony_ci fResScale = 1; 16cb93a386Sopenharmony_ci fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; 17cb93a386Sopenharmony_ci fMiterLimit = SkPaintDefaults_MiterLimit; 18cb93a386Sopenharmony_ci fCap = SkPaint::kDefault_Cap; 19cb93a386Sopenharmony_ci fJoin = SkPaint::kDefault_Join; 20cb93a386Sopenharmony_ci fStrokeAndFill = false; 21cb93a386Sopenharmony_ci} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciSkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) { 24cb93a386Sopenharmony_ci this->init(paint, paint.getStyle(), resScale); 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciSkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) { 28cb93a386Sopenharmony_ci this->init(paint, styleOverride, resScale); 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_civoid SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) { 32cb93a386Sopenharmony_ci fResScale = resScale; 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci switch (style) { 35cb93a386Sopenharmony_ci case SkPaint::kFill_Style: 36cb93a386Sopenharmony_ci fWidth = kStrokeRec_FillStyleWidth; 37cb93a386Sopenharmony_ci fStrokeAndFill = false; 38cb93a386Sopenharmony_ci break; 39cb93a386Sopenharmony_ci case SkPaint::kStroke_Style: 40cb93a386Sopenharmony_ci fWidth = paint.getStrokeWidth(); 41cb93a386Sopenharmony_ci fStrokeAndFill = false; 42cb93a386Sopenharmony_ci break; 43cb93a386Sopenharmony_ci case SkPaint::kStrokeAndFill_Style: 44cb93a386Sopenharmony_ci if (0 == paint.getStrokeWidth()) { 45cb93a386Sopenharmony_ci // hairline+fill == fill 46cb93a386Sopenharmony_ci fWidth = kStrokeRec_FillStyleWidth; 47cb93a386Sopenharmony_ci fStrokeAndFill = false; 48cb93a386Sopenharmony_ci } else { 49cb93a386Sopenharmony_ci fWidth = paint.getStrokeWidth(); 50cb93a386Sopenharmony_ci fStrokeAndFill = true; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci break; 53cb93a386Sopenharmony_ci default: 54cb93a386Sopenharmony_ci SkDEBUGFAIL("unknown paint style"); 55cb93a386Sopenharmony_ci // fall back on just fill 56cb93a386Sopenharmony_ci fWidth = kStrokeRec_FillStyleWidth; 57cb93a386Sopenharmony_ci fStrokeAndFill = false; 58cb93a386Sopenharmony_ci break; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci // copy these from the paint, regardless of our "style" 62cb93a386Sopenharmony_ci fMiterLimit = paint.getStrokeMiter(); 63cb93a386Sopenharmony_ci fCap = paint.getStrokeCap(); 64cb93a386Sopenharmony_ci fJoin = paint.getStrokeJoin(); 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ciSkStrokeRec::Style SkStrokeRec::getStyle() const { 68cb93a386Sopenharmony_ci if (fWidth < 0) { 69cb93a386Sopenharmony_ci return kFill_Style; 70cb93a386Sopenharmony_ci } else if (0 == fWidth) { 71cb93a386Sopenharmony_ci return kHairline_Style; 72cb93a386Sopenharmony_ci } else { 73cb93a386Sopenharmony_ci return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci} 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_civoid SkStrokeRec::setFillStyle() { 78cb93a386Sopenharmony_ci fWidth = kStrokeRec_FillStyleWidth; 79cb93a386Sopenharmony_ci fStrokeAndFill = false; 80cb93a386Sopenharmony_ci} 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_civoid SkStrokeRec::setHairlineStyle() { 83cb93a386Sopenharmony_ci fWidth = 0; 84cb93a386Sopenharmony_ci fStrokeAndFill = false; 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_civoid SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { 88cb93a386Sopenharmony_ci if (strokeAndFill && (0 == width)) { 89cb93a386Sopenharmony_ci // hairline+fill == fill 90cb93a386Sopenharmony_ci this->setFillStyle(); 91cb93a386Sopenharmony_ci } else { 92cb93a386Sopenharmony_ci fWidth = width; 93cb93a386Sopenharmony_ci fStrokeAndFill = strokeAndFill; 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci} 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci#include "src/core/SkStroke.h" 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci#ifdef SK_DEBUG 100cb93a386Sopenharmony_ci // enables tweaking these values at runtime from Viewer 101cb93a386Sopenharmony_ci bool gDebugStrokerErrorSet = false; 102cb93a386Sopenharmony_ci SkScalar gDebugStrokerError; 103cb93a386Sopenharmony_ci#endif 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_cibool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 106cb93a386Sopenharmony_ci if (fWidth <= 0) { // hairline or fill 107cb93a386Sopenharmony_ci return false; 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci SkStroke stroker; 111cb93a386Sopenharmony_ci stroker.setCap((SkPaint::Cap)fCap); 112cb93a386Sopenharmony_ci stroker.setJoin((SkPaint::Join)fJoin); 113cb93a386Sopenharmony_ci stroker.setMiterLimit(fMiterLimit); 114cb93a386Sopenharmony_ci stroker.setWidth(fWidth); 115cb93a386Sopenharmony_ci stroker.setDoFill(fStrokeAndFill); 116cb93a386Sopenharmony_ci#ifdef SK_DEBUG 117cb93a386Sopenharmony_ci stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale); 118cb93a386Sopenharmony_ci#else 119cb93a386Sopenharmony_ci stroker.setResScale(fResScale); 120cb93a386Sopenharmony_ci#endif 121cb93a386Sopenharmony_ci stroker.strokePath(src, dst); 122cb93a386Sopenharmony_ci return true; 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_civoid SkStrokeRec::applyToPaint(SkPaint* paint) const { 126cb93a386Sopenharmony_ci if (fWidth < 0) { // fill 127cb93a386Sopenharmony_ci paint->setStyle(SkPaint::kFill_Style); 128cb93a386Sopenharmony_ci return; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); 132cb93a386Sopenharmony_ci paint->setStrokeWidth(fWidth); 133cb93a386Sopenharmony_ci paint->setStrokeMiter(fMiterLimit); 134cb93a386Sopenharmony_ci paint->setStrokeCap((SkPaint::Cap)fCap); 135cb93a386Sopenharmony_ci paint->setStrokeJoin((SkPaint::Join)fJoin); 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ciSkScalar SkStrokeRec::getInflationRadius() const { 139cb93a386Sopenharmony_ci return GetInflationRadius((SkPaint::Join)fJoin, fMiterLimit, (SkPaint::Cap)fCap, fWidth); 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ciSkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) { 143cb93a386Sopenharmony_ci SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth(); 144cb93a386Sopenharmony_ci return GetInflationRadius(paint.getStrokeJoin(), paint.getStrokeMiter(), paint.getStrokeCap(), 145cb93a386Sopenharmony_ci width); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ciSkScalar SkStrokeRec::GetInflationRadius(SkPaint::Join join, SkScalar miterLimit, SkPaint::Cap cap, 150cb93a386Sopenharmony_ci SkScalar strokeWidth) { 151cb93a386Sopenharmony_ci if (strokeWidth < 0) { // fill 152cb93a386Sopenharmony_ci return 0; 153cb93a386Sopenharmony_ci } else if (0 == strokeWidth) { 154cb93a386Sopenharmony_ci // FIXME: We need a "matrixScale" parameter here in order to properly handle hairlines. 155cb93a386Sopenharmony_ci // Their with is determined in device space, unlike other strokes. 156cb93a386Sopenharmony_ci // http://skbug.com/8157 157cb93a386Sopenharmony_ci return SK_Scalar1; 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci // since we're stroked, outset the rect by the radius (and join type, caps) 161cb93a386Sopenharmony_ci SkScalar multiplier = SK_Scalar1; 162cb93a386Sopenharmony_ci if (SkPaint::kMiter_Join == join) { 163cb93a386Sopenharmony_ci multiplier = std::max(multiplier, miterLimit); 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci if (SkPaint::kSquare_Cap == cap) { 166cb93a386Sopenharmony_ci multiplier = std::max(multiplier, SK_ScalarSqrt2); 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci return strokeWidth/2 * multiplier; 169cb93a386Sopenharmony_ci} 170cb93a386Sopenharmony_ci 171