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/SkPaint.h" 9cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 10cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 11cb93a386Sopenharmony_ci#include "include/core/SkStrokeRec.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 13cb93a386Sopenharmony_ci#include "src/core/SkStroke.h" 14cb93a386Sopenharmony_ci#include "tests/Test.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cistatic bool equal(const SkRect& a, const SkRect& b) { 17cb93a386Sopenharmony_ci return SkScalarNearlyEqual(a.left(), b.left()) && 18cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.top(), b.top()) && 19cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.right(), b.right()) && 20cb93a386Sopenharmony_ci SkScalarNearlyEqual(a.bottom(), b.bottom()); 21cb93a386Sopenharmony_ci} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_cistatic void test_strokecubic(skiatest::Reporter* reporter) { 24cb93a386Sopenharmony_ci uint32_t hexCubicVals[] = { 25cb93a386Sopenharmony_ci 0x424c1086, 0x44bcf0cb, // fX=51.0161362 fY=1511.52478 26cb93a386Sopenharmony_ci 0x424c107c, 0x44bcf0cb, // fX=51.0160980 fY=1511.52478 27cb93a386Sopenharmony_ci 0x424c10c2, 0x44bcf0cb, // fX=51.0163651 fY=1511.52478 28cb93a386Sopenharmony_ci 0x424c1119, 0x44bcf0ca, // fX=51.0166969 fY=1511.52466 29cb93a386Sopenharmony_ci }; 30cb93a386Sopenharmony_ci SkPoint cubicVals[] = { 31cb93a386Sopenharmony_ci {51.0161362f, 1511.52478f }, 32cb93a386Sopenharmony_ci {51.0160980f, 1511.52478f }, 33cb93a386Sopenharmony_ci {51.0163651f, 1511.52478f }, 34cb93a386Sopenharmony_ci {51.0166969f, 1511.52466f }, 35cb93a386Sopenharmony_ci }; 36cb93a386Sopenharmony_ci SkPaint paint; 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 39cb93a386Sopenharmony_ci paint.setStrokeWidth(0.394537568f); 40cb93a386Sopenharmony_ci SkPath path, fillPath; 41cb93a386Sopenharmony_ci path.moveTo(cubicVals[0]); 42cb93a386Sopenharmony_ci path.cubicTo(cubicVals[1], cubicVals[2], cubicVals[3]); 43cb93a386Sopenharmony_ci paint.getFillPath(path, &fillPath); 44cb93a386Sopenharmony_ci path.reset(); 45cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(hexCubicVals[0]), SkBits2Float(hexCubicVals[1])); 46cb93a386Sopenharmony_ci path.cubicTo(SkBits2Float(hexCubicVals[2]), SkBits2Float(hexCubicVals[3]), 47cb93a386Sopenharmony_ci SkBits2Float(hexCubicVals[4]), SkBits2Float(hexCubicVals[5]), 48cb93a386Sopenharmony_ci SkBits2Float(hexCubicVals[6]), SkBits2Float(hexCubicVals[7])); 49cb93a386Sopenharmony_ci paint.getFillPath(path, &fillPath); 50cb93a386Sopenharmony_ci} 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_cistatic void test_strokerect(skiatest::Reporter* reporter) { 53cb93a386Sopenharmony_ci const SkScalar width = SkIntToScalar(10); 54cb93a386Sopenharmony_ci SkPaint paint; 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 57cb93a386Sopenharmony_ci paint.setStrokeWidth(width); 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci SkRect r = { 0, 0, SkIntToScalar(200), SkIntToScalar(100) }; 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci SkRect outer(r); 62cb93a386Sopenharmony_ci outer.outset(width/2, width/2); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci static const SkPaint::Join joins[] = { 65cb93a386Sopenharmony_ci SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join 66cb93a386Sopenharmony_ci }; 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(joins); ++i) { 69cb93a386Sopenharmony_ci paint.setStrokeJoin(joins[i]); 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci SkPath path, fillPath; 72cb93a386Sopenharmony_ci path.addRect(r); 73cb93a386Sopenharmony_ci paint.getFillPath(path, &fillPath); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, equal(outer, fillPath.getBounds())); 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_ci bool isMiter = SkPaint::kMiter_Join == joins[i]; 78cb93a386Sopenharmony_ci SkRect nested[2]; 79cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(fillPath, nested) == isMiter); 80cb93a386Sopenharmony_ci if (isMiter) { 81cb93a386Sopenharmony_ci SkRect inner(r); 82cb93a386Sopenharmony_ci inner.inset(width/2, width/2); 83cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, equal(nested[0], outer)); 84cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, equal(nested[1], inner)); 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_cistatic void test_strokerec_equality(skiatest::Reporter* reporter) { 90cb93a386Sopenharmony_ci { 91cb93a386Sopenharmony_ci SkStrokeRec s1(SkStrokeRec::kFill_InitStyle); 92cb93a386Sopenharmony_ci SkStrokeRec s2(SkStrokeRec::kFill_InitStyle); 93cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci // Test that style mismatch is detected. 96cb93a386Sopenharmony_ci s2.setHairlineStyle(); 97cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2)); 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci s1.setHairlineStyle(); 100cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci // ResScale is not part of equality. 103cb93a386Sopenharmony_ci s1.setResScale(2.1f); 104cb93a386Sopenharmony_ci s2.setResScale(1.2f); 105cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 106cb93a386Sopenharmony_ci s1.setFillStyle(); 107cb93a386Sopenharmony_ci s2.setFillStyle(); 108cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 109cb93a386Sopenharmony_ci s1.setStrokeStyle(1.0f, false); 110cb93a386Sopenharmony_ci s2.setStrokeStyle(1.0f, false); 111cb93a386Sopenharmony_ci s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f); 112cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f); 113cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci // Stroke parameters on fill or hairline style are not part of equality. 117cb93a386Sopenharmony_ci { 118cb93a386Sopenharmony_ci SkStrokeRec s1(SkStrokeRec::kFill_InitStyle); 119cb93a386Sopenharmony_ci SkStrokeRec s2(SkStrokeRec::kFill_InitStyle); 120cb93a386Sopenharmony_ci for (int i = 0; i < 2; ++i) { 121cb93a386Sopenharmony_ci s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f); 122cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.1f); 123cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 124cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBevel_Join, 2.9f); 125cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 126cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 2.9f); 127cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 128cb93a386Sopenharmony_ci s1.setHairlineStyle(); 129cb93a386Sopenharmony_ci s2.setHairlineStyle(); 130cb93a386Sopenharmony_ci } 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci // Stroke parameters on stroke style are part of equality. 134cb93a386Sopenharmony_ci { 135cb93a386Sopenharmony_ci SkStrokeRec s1(SkStrokeRec::kFill_InitStyle); 136cb93a386Sopenharmony_ci SkStrokeRec s2(SkStrokeRec::kFill_InitStyle); 137cb93a386Sopenharmony_ci s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f); 138cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f); 139cb93a386Sopenharmony_ci s1.setStrokeStyle(1.0f, false); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci s2.setStrokeStyle(1.0f, true); 142cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2)); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci s2.setStrokeStyle(2.1f, false); 145cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2)); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci s2.setStrokeStyle(1.0f, false); 148cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.1f); 151cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); // Miter limit not relevant to butt caps. 152cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBevel_Join, 2.9f); 153cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2)); 154cb93a386Sopenharmony_ci s2.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 2.9f); 155cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2)); 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci // Sets fill. 158cb93a386Sopenharmony_ci s1.setStrokeStyle(0.0f, true); 159cb93a386Sopenharmony_ci s2.setStrokeStyle(0.0f, true); 160cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2)); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci} 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci// From skbug.com/6491. The large stroke width can cause numerical instabilities. 165cb93a386Sopenharmony_cistatic void test_big_stroke(skiatest::Reporter* reporter) { 166cb93a386Sopenharmony_ci SkPaint paint; 167cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStrokeAndFill_Style); 168cb93a386Sopenharmony_ci paint.setStrokeWidth(1.49679073e+10f); 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci SkPath path; 171cb93a386Sopenharmony_ci path.moveTo(SkBits2Float(0x46380000), SkBits2Float(0xc6380000)); // 11776, -11776 172cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x46a00000), SkBits2Float(0xc6a00000)); // 20480, -20480 173cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x468c0000), SkBits2Float(0xc68c0000)); // 17920, -17920 174cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x46100000), SkBits2Float(0xc6100000)); // 9216, -9216 175cb93a386Sopenharmony_ci path.lineTo(SkBits2Float(0x46380000), SkBits2Float(0xc6380000)); // 11776, -11776 176cb93a386Sopenharmony_ci path.close(); 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci SkPath strokeAndFillPath; 179cb93a386Sopenharmony_ci paint.getFillPath(path, &strokeAndFillPath); 180cb93a386Sopenharmony_ci} 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ciDEF_TEST(Stroke, reporter) { 183cb93a386Sopenharmony_ci test_strokecubic(reporter); 184cb93a386Sopenharmony_ci test_strokerect(reporter); 185cb93a386Sopenharmony_ci test_strokerec_equality(reporter); 186cb93a386Sopenharmony_ci test_big_stroke(reporter); 187cb93a386Sopenharmony_ci} 188