15f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com/* 25f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com * Copyright 2012 Google Inc. 35f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com * 45f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com * Use of this source code is governed by a BSD-style license that can be 55f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com * found in the LICENSE file. 65f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com */ 75f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 85f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h" 95f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkPaintDefaults.h" 105f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 115f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com// must be < 0, since ==0 means hairline, and >0 means normal stroke 125f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#define kStrokeRec_FillStyleWidth (-SK_Scalar1) 135f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 145f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comSkStrokeRec::SkStrokeRec(InitStyle s) { 1505d9044de4f1c6e791df66a425638752daac4c6breed fResScale = 1; 165f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0; 175f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fMiterLimit = SkPaintDefaults_MiterLimit; 185f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fCap = SkPaint::kDefault_Cap; 195f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fJoin = SkPaint::kDefault_Join; 205f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 215f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 225f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 2305d9044de4f1c6e791df66a425638752daac4c6breedSkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) { 2405d9044de4f1c6e791df66a425638752daac4c6breed this->init(paint, paint.getStyle(), resScale); 25e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel} 26e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel 2705d9044de4f1c6e791df66a425638752daac4c6breedSkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) { 2805d9044de4f1c6e791df66a425638752daac4c6breed this->init(paint, styleOverride, resScale); 29e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel} 30e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel 3105d9044de4f1c6e791df66a425638752daac4c6breedvoid SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) { 3205d9044de4f1c6e791df66a425638752daac4c6breed fResScale = resScale; 3305d9044de4f1c6e791df66a425638752daac4c6breed 34e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel switch (style) { 355f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com case SkPaint::kFill_Style: 365f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = kStrokeRec_FillStyleWidth; 375f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 385f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com break; 395f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com case SkPaint::kStroke_Style: 405f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = paint.getStrokeWidth(); 415f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 425f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com break; 435f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com case SkPaint::kStrokeAndFill_Style: 445f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (0 == paint.getStrokeWidth()) { 455f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com // hairline+fill == fill 465f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = kStrokeRec_FillStyleWidth; 475f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 485f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } else { 495f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = paint.getStrokeWidth(); 505f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = true; 515f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } 525f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com break; 535f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com default: 54330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com SkDEBUGFAIL("unknown paint style"); 555f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com // fall back on just fill 565f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = kStrokeRec_FillStyleWidth; 575f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 585f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com break; 595f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } 605f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 615f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com // copy these from the paint, regardless of our "style" 625f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fMiterLimit = paint.getStrokeMiter(); 635f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fCap = paint.getStrokeCap(); 645f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fJoin = paint.getStrokeJoin(); 655f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 665f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 675f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comSkStrokeRec::Style SkStrokeRec::getStyle() const { 685f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (fWidth < 0) { 695f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com return kFill_Style; 705f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } else if (0 == fWidth) { 715f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com return kHairline_Style; 725f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } else { 735f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style; 745f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } 755f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 765f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 775f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comvoid SkStrokeRec::setFillStyle() { 785f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = kStrokeRec_FillStyleWidth; 795f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 805f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 815f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 825f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comvoid SkStrokeRec::setHairlineStyle() { 835f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = 0; 845f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = false; 855f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 865f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 875f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comvoid SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) { 885f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (strokeAndFill && (0 == width)) { 895f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com // hairline+fill == fill 905f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com this->setFillStyle(); 915f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } else { 925f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fWidth = width; 935f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com fStrokeAndFill = strokeAndFill; 945f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } 955f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 965f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 975f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStroke.h" 985f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 999d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary#ifdef SK_DEBUG 10004e4d08556750ff6be4576a4cd4925964c63376fcaryclark // enables tweaking these values at runtime from SampleApp 10104e4d08556750ff6be4576a4cd4925964c63376fcaryclark bool gDebugStrokerErrorSet = false; 10204e4d08556750ff6be4576a4cd4925964c63376fcaryclark SkScalar gDebugStrokerError; 10304e4d08556750ff6be4576a4cd4925964c63376fcaryclark#endif 10404e4d08556750ff6be4576a4cd4925964c63376fcaryclark 1055f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.combool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const { 1065f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com if (fWidth <= 0) { // hairline or fill 1075f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com return false; 1085f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com } 1095f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com 1105f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStroke stroker; 111897c9937636c2287bb217c76da9a56afb43050acjvanverth stroker.setCap((SkPaint::Cap)fCap); 112897c9937636c2287bb217c76da9a56afb43050acjvanverth stroker.setJoin((SkPaint::Join)fJoin); 1135f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroker.setMiterLimit(fMiterLimit); 1145f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroker.setWidth(fWidth); 1155f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroker.setDoFill(fStrokeAndFill); 116a76b7a3b04bc0e937921a1eb38d713c619e60e4ecaryclark#ifdef SK_DEBUG 11704e4d08556750ff6be4576a4cd4925964c63376fcaryclark stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale); 11804e4d08556750ff6be4576a4cd4925964c63376fcaryclark#else 11905d9044de4f1c6e791df66a425638752daac4c6breed stroker.setResScale(fResScale); 120feff7d2d7719f52c7ea52db156003e609002bf04caryclark#endif 1215f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com stroker.strokePath(src, dst); 1225f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com return true; 1235f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com} 12420b373cf3116905fc5ca1928c9b504851335ca43cdalton 12520b373cf3116905fc5ca1928c9b504851335ca43cdaltonvoid SkStrokeRec::applyToPaint(SkPaint* paint) const { 12620b373cf3116905fc5ca1928c9b504851335ca43cdalton if (fWidth < 0) { // fill 12720b373cf3116905fc5ca1928c9b504851335ca43cdalton paint->setStyle(SkPaint::kFill_Style); 12820b373cf3116905fc5ca1928c9b504851335ca43cdalton return; 12920b373cf3116905fc5ca1928c9b504851335ca43cdalton } 13020b373cf3116905fc5ca1928c9b504851335ca43cdalton 13120b373cf3116905fc5ca1928c9b504851335ca43cdalton paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style); 13220b373cf3116905fc5ca1928c9b504851335ca43cdalton paint->setStrokeWidth(fWidth); 13320b373cf3116905fc5ca1928c9b504851335ca43cdalton paint->setStrokeMiter(fMiterLimit); 134897c9937636c2287bb217c76da9a56afb43050acjvanverth paint->setStrokeCap((SkPaint::Cap)fCap); 135897c9937636c2287bb217c76da9a56afb43050acjvanverth paint->setStrokeJoin((SkPaint::Join)fJoin); 13620b373cf3116905fc5ca1928c9b504851335ca43cdalton} 1375668648e875abe0a064caabef432ade4745deb89bsalomon 1385668648e875abe0a064caabef432ade4745deb89bsalomonstatic inline SkScalar get_inflation_bounds(SkPaint::Join join, 1395668648e875abe0a064caabef432ade4745deb89bsalomon SkScalar strokeWidth, 1405668648e875abe0a064caabef432ade4745deb89bsalomon SkScalar miterLimit) { 1415668648e875abe0a064caabef432ade4745deb89bsalomon if (strokeWidth < 0) { // fill 1425668648e875abe0a064caabef432ade4745deb89bsalomon return 0; 1435668648e875abe0a064caabef432ade4745deb89bsalomon } else if (0 == strokeWidth) { 1445668648e875abe0a064caabef432ade4745deb89bsalomon return SK_Scalar1; 1455668648e875abe0a064caabef432ade4745deb89bsalomon } 1465668648e875abe0a064caabef432ade4745deb89bsalomon // since we're stroked, outset the rect by the radius (and join type) 1475668648e875abe0a064caabef432ade4745deb89bsalomon SkScalar radius = SkScalarHalf(strokeWidth); 1485668648e875abe0a064caabef432ade4745deb89bsalomon if (SkPaint::kMiter_Join == join) { 1495668648e875abe0a064caabef432ade4745deb89bsalomon if (miterLimit > SK_Scalar1) { 150a99b6ceff92183b424634f2e7276b9ea1d59e69dMike Reed radius *= miterLimit; 1515668648e875abe0a064caabef432ade4745deb89bsalomon } 1525668648e875abe0a064caabef432ade4745deb89bsalomon } 1535668648e875abe0a064caabef432ade4745deb89bsalomon return radius; 1545668648e875abe0a064caabef432ade4745deb89bsalomon} 1555668648e875abe0a064caabef432ade4745deb89bsalomon 1565668648e875abe0a064caabef432ade4745deb89bsalomonSkScalar SkStrokeRec::getInflationRadius() const { 1575668648e875abe0a064caabef432ade4745deb89bsalomon return get_inflation_bounds((SkPaint::Join)fJoin, fWidth, fMiterLimit); 1585668648e875abe0a064caabef432ade4745deb89bsalomon} 1595668648e875abe0a064caabef432ade4745deb89bsalomon 1605668648e875abe0a064caabef432ade4745deb89bsalomonSkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) { 1615668648e875abe0a064caabef432ade4745deb89bsalomon SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth(); 1625668648e875abe0a064caabef432ade4745deb89bsalomon return get_inflation_bounds(paint.getStrokeJoin(), width, paint.getStrokeMiter()); 1635668648e875abe0a064caabef432ade4745deb89bsalomon 1645668648e875abe0a064caabef432ade4745deb89bsalomon} 165