diff options
Diffstat (limited to 'gfx/skia/skia/src/core/SkStrokeRec.cpp')
-rw-r--r-- | gfx/skia/skia/src/core/SkStrokeRec.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/core/SkStrokeRec.cpp b/gfx/skia/skia/src/core/SkStrokeRec.cpp new file mode 100644 index 0000000000..d63079269f --- /dev/null +++ b/gfx/skia/skia/src/core/SkStrokeRec.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "include/core/SkStrokeRec.h" + +#include "src/core/SkPaintDefaults.h" +#include "src/core/SkStroke.h" + +#include <algorithm> + +// must be < 0, since ==0 means hairline, and >0 means normal stroke +#define kStrokeRec_FillStyleWidth (-SK_Scalar1) + +SkStrokeRec::SkStrokeRec(InitStyle s) { + fResScale = 1; + fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; + fMiterLimit = SkPaintDefaults_MiterLimit; + fCap = SkPaint::kDefault_Cap; + fJoin = SkPaint::kDefault_Join; + fStrokeAndFill = false; +} + +SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) { + this->init(paint, paint.getStyle(), resScale); +} + +SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) { + this->init(paint, styleOverride, resScale); +} + +void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) { + fResScale = resScale; + + switch (style) { + case SkPaint::kFill_Style: + fWidth = kStrokeRec_FillStyleWidth; + fStrokeAndFill = false; + break; + case SkPaint::kStroke_Style: + fWidth = paint.getStrokeWidth(); + fStrokeAndFill = false; + break; + case SkPaint::kStrokeAndFill_Style: + if (0 == paint.getStrokeWidth()) { + // hairline+fill == fill + fWidth = kStrokeRec_FillStyleWidth; + fStrokeAndFill = false; + } else { + fWidth = paint.getStrokeWidth(); + fStrokeAndFill = true; + } + break; + default: + SkDEBUGFAIL("unknown paint style"); + // fall back on just fill + fWidth = kStrokeRec_FillStyleWidth; + fStrokeAndFill = false; + break; + } + + // copy these from the paint, regardless of our "style" + fMiterLimit = paint.getStrokeMiter(); + fCap = paint.getStrokeCap(); + fJoin = paint.getStrokeJoin(); +} + +SkStrokeRec::Style SkStrokeRec::getStyle() const { + if (fWidth < 0) { + return kFill_Style; + } else if (0 == fWidth) { + return kHairline_Style; + } else { + return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; + } +} + +void SkStrokeRec::setFillStyle() { + fWidth = kStrokeRec_FillStyleWidth; + fStrokeAndFill = false; +} + +void SkStrokeRec::setHairlineStyle() { + fWidth = 0; + fStrokeAndFill = false; +} + +void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { + if (strokeAndFill && (0 == width)) { + // hairline+fill == fill + this->setFillStyle(); + } else { + fWidth = width; + fStrokeAndFill = strokeAndFill; + } +} + +#ifdef SK_DEBUG + // enables tweaking these values at runtime from Viewer + bool gDebugStrokerErrorSet = false; + SkScalar gDebugStrokerError; +#endif + +bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { + if (fWidth <= 0) { // hairline or fill + return false; + } + + SkStroke stroker; + stroker.setCap((SkPaint::Cap)fCap); + stroker.setJoin((SkPaint::Join)fJoin); + stroker.setMiterLimit(fMiterLimit); + stroker.setWidth(fWidth); + stroker.setDoFill(fStrokeAndFill); +#ifdef SK_DEBUG + stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale); +#else + stroker.setResScale(fResScale); +#endif + stroker.strokePath(src, dst); + return true; +} + +void SkStrokeRec::applyToPaint(SkPaint* paint) const { + if (fWidth < 0) { // fill + paint->setStyle(SkPaint::kFill_Style); + return; + } + + paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); + paint->setStrokeWidth(fWidth); + paint->setStrokeMiter(fMiterLimit); + paint->setStrokeCap((SkPaint::Cap)fCap); + paint->setStrokeJoin((SkPaint::Join)fJoin); +} + +SkScalar SkStrokeRec::getInflationRadius() const { + return GetInflationRadius((SkPaint::Join)fJoin, fMiterLimit, (SkPaint::Cap)fCap, fWidth); +} + +SkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) { + SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth(); + return GetInflationRadius(paint.getStrokeJoin(), paint.getStrokeMiter(), paint.getStrokeCap(), + width); + +} + +SkScalar SkStrokeRec::GetInflationRadius(SkPaint::Join join, SkScalar miterLimit, SkPaint::Cap cap, + SkScalar strokeWidth) { + if (strokeWidth < 0) { // fill + return 0; + } else if (0 == strokeWidth) { + // FIXME: We need a "matrixScale" parameter here in order to properly handle hairlines. + // Their with is determined in device space, unlike other strokes. + // http://skbug.com/8157 + return SK_Scalar1; + } + + // since we're stroked, outset the rect by the radius (and join type, caps) + SkScalar multiplier = SK_Scalar1; + if (SkPaint::kMiter_Join == join) { + multiplier = std::max(multiplier, miterLimit); + } + if (SkPaint::kSquare_Cap == cap) { + multiplier = std::max(multiplier, SK_ScalarSqrt2); + } + return strokeWidth/2 * multiplier; +} + |