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 (strokeIsDashed(m_thickness, m_style)) { |
74 float width = | 74 float width = |
75 m_style == DashedStroke ? dashRatio * m_thickness : m_thickness; | 75 m_style == DashedStroke ? dashRatio * m_thickness : m_thickness; |
76 | 76 |
77 // Truncate the width, since we don't want fuzzy dots or dashes. | 77 // Truncate the width, since we don't want fuzzy dots or dashes. |
78 int dashLength = static_cast<int>(width); | 78 int dashLength = static_cast<int>(width); |
79 // Subtract off the endcaps, since they're rendered separately. | 79 // Subtract off the endcaps, since they're rendered separately. |
80 int distance = length - 2 * static_cast<int>(m_thickness); | 80 int distance = length - 2 * static_cast<int>(m_thickness); |
81 int phase = 1; | 81 int phase = 1; |
82 if (dashLength > 1) { | 82 if (dashLength > 1) { |
83 // Determine how many dashes or dots we should have. | 83 // Determine how many dashes or dots we should have. |
84 int numDashes = distance / dashLength; | 84 int numDashes = distance / dashLength; |
85 int remainder = distance % dashLength; | 85 int remainder = distance % dashLength; |
86 // Adjust the phase to center the dashes within the line. | 86 // Adjust the phase to center the dashes within the line. |
87 if (numDashes % 2) { | 87 if (numDashes % 2) { |
88 // Odd: shift right a full dash, minus half the remainder. | 88 // Odd: shift right a full dash, minus half the remainder. |
89 phase = dashLength - remainder / 2; | 89 phase = dashLength - remainder / 2; |
90 } else { | 90 } else { |
91 // Even: shift right half a dash, minus half the remainder. | 91 // Even: shift right half a dash, minus half the remainder. |
92 phase = (dashLength - remainder) / 2; | 92 phase = (dashLength - remainder) / 2; |
93 } | 93 } |
94 } | 94 } |
95 SkScalar dashLengthSk = SkIntToScalar(dashLength); | 95 SkScalar dashLengthSk = SkIntToScalar(dashLength); |
96 SkScalar intervals[2] = {dashLengthSk, dashLengthSk}; | 96 SkScalar intervals[2] = {dashLengthSk, dashLengthSk}; |
97 flags->setPathEffect( | 97 flags->setPathEffect( |
98 SkDashPathEffect::Make(intervals, 2, SkIntToScalar(phase))); | 98 SkDashPathEffect::Make(intervals, 2, SkIntToScalar(phase))); |
| 99 } else if (m_style == DottedStroke) { |
| 100 flags->setStrokeCap((PaintFlags::Cap)RoundCap); |
| 101 // Adjust the width to get equal dot spacing as much as possible. |
| 102 float perDotLength = m_thickness * 2; |
| 103 static float epsilon = 1.0e-2f; |
| 104 if (length < perDotLength + m_thickness) { |
| 105 // Exactly 2 dots with whatever space we can get |
| 106 SkScalar intervals[2] = {0, length - m_thickness - epsilon}; |
| 107 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 108 return; |
| 109 } |
| 110 |
| 111 // Determine what number of dots gives the minimum deviation from |
| 112 // idealGap between dots. Set the gap to that width. |
| 113 float minNumDots = floorf((length + m_thickness) / perDotLength); |
| 114 float maxNumDots = minNumDots + 1; |
| 115 float minGap = (length - minNumDots * m_thickness) / (minNumDots - 1); |
| 116 float maxGap = (length - maxNumDots * m_thickness) / (maxNumDots - 1); |
| 117 if (fabs(minGap - m_thickness) < fabs(maxGap - m_thickness)) { |
| 118 SkScalar intervals[2] = {0, minGap + m_thickness - epsilon}; |
| 119 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 120 } else { |
| 121 SkScalar intervals[2] = {0, maxGap + m_thickness - epsilon}; |
| 122 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 123 } |
99 } else { | 124 } else { |
100 // TODO(schenney): WavyStroke: https://crbug.com/229574 | 125 // TODO(schenney): WavyStroke https://crbug.com/229574 |
101 flags->setPathEffect(0); | 126 flags->setPathEffect(0); |
102 } | 127 } |
103 } | 128 } |
104 | 129 |
| 130 bool StrokeData::strokeIsDashed(float width, StrokeStyle style) { |
| 131 return style == DashedStroke || (style == DottedStroke && width <= 3); |
| 132 } |
| 133 |
105 } // namespace blink | 134 } // namespace blink |
OLD | NEW |