OLD | NEW |
1 // Copyright (C) 2013 Google Inc. All rights reserved. | 1 // Copyright (C) 2013 Google Inc. All rights reserved. |
2 // | 2 // |
3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
5 // met: | 5 // met: |
6 // | 6 // |
7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
10 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 flags->setStrokeCap(m_lineCap); | 63 flags->setStrokeCap(m_lineCap); |
64 flags->setStrokeJoin(m_lineJoin); | 64 flags->setStrokeJoin(m_lineJoin); |
65 flags->setStrokeMiter(SkFloatToScalar(m_miterLimit)); | 65 flags->setStrokeMiter(SkFloatToScalar(m_miterLimit)); |
66 | 66 |
67 setupPaintDashPathEffect(flags, length); | 67 setupPaintDashPathEffect(flags, length); |
68 } | 68 } |
69 | 69 |
70 void StrokeData::setupPaintDashPathEffect(PaintFlags* flags, int length) const { | 70 void StrokeData::setupPaintDashPathEffect(PaintFlags* flags, int length) const { |
71 if (m_dash) { | 71 if (m_dash) { |
72 flags->setPathEffect(m_dash); | 72 flags->setPathEffect(m_dash); |
73 } else if (m_style == DashedStroke || m_style == DottedStroke) { | 73 } else if (m_style == DashedStroke || |
| 74 (m_style == DottedStroke && m_thickness <= 3)) { |
74 float width = | 75 float width = |
75 m_style == DashedStroke ? dashRatio * m_thickness : m_thickness; | 76 m_style == DashedStroke ? dashRatio * m_thickness : m_thickness; |
76 | 77 |
77 // Truncate the width, since we don't want fuzzy dots or dashes. | 78 // Truncate the width, since we don't want fuzzy dots or dashes. |
78 int dashLength = static_cast<int>(width); | 79 int dashLength = static_cast<int>(width); |
79 // Subtract off the endcaps, since they're rendered separately. | 80 // Subtract off the endcaps, since they're rendered separately. |
80 int distance = length - 2 * static_cast<int>(m_thickness); | 81 int distance = length - 2 * static_cast<int>(m_thickness); |
81 int phase = 1; | 82 int phase = 1; |
82 if (dashLength > 1) { | 83 if (dashLength > 1) { |
83 // Determine how many dashes or dots we should have. | 84 // Determine how many dashes or dots we should have. |
84 int numDashes = distance / dashLength; | 85 int numDashes = distance / dashLength; |
85 int remainder = distance % dashLength; | 86 int remainder = distance % dashLength; |
86 // Adjust the phase to center the dashes within the line. | 87 // Adjust the phase to center the dashes within the line. |
87 if (numDashes % 2) { | 88 if (numDashes % 2) { |
88 // Odd: shift right a full dash, minus half the remainder. | 89 // Odd: shift right a full dash, minus half the remainder. |
89 phase = dashLength - remainder / 2; | 90 phase = dashLength - remainder / 2; |
90 } else { | 91 } else { |
91 // Even: shift right half a dash, minus half the remainder. | 92 // Even: shift right half a dash, minus half the remainder. |
92 phase = (dashLength - remainder) / 2; | 93 phase = (dashLength - remainder) / 2; |
93 } | 94 } |
94 } | 95 } |
95 SkScalar dashLengthSk = SkIntToScalar(dashLength); | 96 SkScalar dashLengthSk = SkIntToScalar(dashLength); |
96 SkScalar intervals[2] = {dashLengthSk, dashLengthSk}; | 97 SkScalar intervals[2] = {dashLengthSk, dashLengthSk}; |
97 flags->setPathEffect( | 98 flags->setPathEffect( |
98 SkDashPathEffect::Make(intervals, 2, SkIntToScalar(phase))); | 99 SkDashPathEffect::Make(intervals, 2, SkIntToScalar(phase))); |
| 100 } else if (m_style == DottedStroke) { |
| 101 flags->setStrokeCap((PaintFlags::Cap)RoundCap); |
| 102 // Adjust the width to get equal dot spacing as much as possible. |
| 103 float perDotLength = m_thickness * 2; |
| 104 static float epsilon = 1.0e-2f; |
| 105 if (length < perDotLength + m_thickness) { |
| 106 // Exactly 2 dots with whatever space we can get |
| 107 SkScalar intervals[2] = {0, length - m_thickness - epsilon}; |
| 108 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 109 return; |
| 110 } |
| 111 |
| 112 // Determine what number of dots gives the minimum deviation from |
| 113 // idealGap between dots. Set the gap to that width. |
| 114 float minNumDots = floorf((length + m_thickness) / perDotLength); |
| 115 float maxNumDots = minNumDots + 1; |
| 116 float minGap = (length - minNumDots * m_thickness) / (minNumDots - 1); |
| 117 float maxGap = (length - maxNumDots * m_thickness) / (maxNumDots - 1); |
| 118 if (fabs(minGap - m_thickness) < fabs(maxGap - m_thickness)) { |
| 119 SkScalar intervals[2] = {0, minGap + m_thickness - epsilon}; |
| 120 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 121 } else { |
| 122 SkScalar intervals[2] = {0, maxGap + m_thickness - epsilon}; |
| 123 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 124 } |
99 } else { | 125 } else { |
100 // TODO(schenney): WavyStroke: https://crbug.com/229574 | 126 // TODO(schenney): WavyStroke https://crbug.com/229574 |
101 flags->setPathEffect(0); | 127 flags->setPathEffect(0); |
102 } | 128 } |
103 } | 129 } |
104 | 130 |
105 } // namespace blink | 131 } // namespace blink |
OLD | NEW |