Chromium Code Reviews| 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 16 matching lines...) Expand all Loading... | |
| 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 #include "platform/graphics/StrokeData.h" | 29 #include "platform/graphics/StrokeData.h" |
| 30 #include "platform/graphics/paint/PaintFlags.h" | 30 #include "platform/graphics/paint/PaintFlags.h" |
| 31 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 31 #include "third_party/skia/include/effects/SkDashPathEffect.h" |
| 32 #include "wtf/PtrUtil.h" | 32 #include "wtf/PtrUtil.h" |
| 33 #include <memory> | 33 #include <memory> |
| 34 | 34 |
| 35 namespace blink { | 35 namespace blink { |
| 36 | 36 |
| 37 static const int dashRatio = 3; // Ratio of the length of a dash to its width. | |
| 38 | |
| 39 void StrokeData::setLineDash(const DashArray& dashes, float dashOffset) { | 37 void StrokeData::setLineDash(const DashArray& dashes, float dashOffset) { |
| 40 // FIXME: This is lifted directly off SkiaSupport, lines 49-74 | 38 // FIXME: This is lifted directly off SkiaSupport, lines 49-74 |
| 41 // so it is not guaranteed to work correctly. | 39 // so it is not guaranteed to work correctly. |
| 42 size_t dashLength = dashes.size(); | 40 size_t dashLength = dashes.size(); |
| 43 if (!dashLength) { | 41 if (!dashLength) { |
| 44 // If no dash is set, revert to solid stroke | 42 // If no dash is set, revert to solid stroke |
| 45 // FIXME: do we need to set NoStroke in some cases? | 43 // FIXME: do we need to set NoStroke in some cases? |
| 46 m_style = SolidStroke; | 44 m_style = SolidStroke; |
| 47 m_dash.reset(); | 45 m_dash.reset(); |
| 48 return; | 46 return; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 61 flags->setStyle(PaintFlags::kStroke_Style); | 59 flags->setStyle(PaintFlags::kStroke_Style); |
| 62 flags->setStrokeWidth(SkFloatToScalar(m_thickness)); | 60 flags->setStrokeWidth(SkFloatToScalar(m_thickness)); |
| 63 flags->setStrokeCap(m_lineCap); | 61 flags->setStrokeCap(m_lineCap); |
| 64 flags->setStrokeJoin(m_lineJoin); | 62 flags->setStrokeJoin(m_lineJoin); |
| 65 flags->setStrokeMiter(SkFloatToScalar(m_miterLimit)); | 63 flags->setStrokeMiter(SkFloatToScalar(m_miterLimit)); |
| 66 | 64 |
| 67 setupPaintDashPathEffect(flags, length); | 65 setupPaintDashPathEffect(flags, length); |
| 68 } | 66 } |
| 69 | 67 |
| 70 void StrokeData::setupPaintDashPathEffect(PaintFlags* flags, int length) const { | 68 void StrokeData::setupPaintDashPathEffect(PaintFlags* flags, int length) const { |
| 69 static float epsilon = 1.0e-2f; | |
|
f(malita)
2017/03/08 16:51:56
nit: can we leave this close to its only user, and
Stephen Chennney
2017/03/08 17:33:26
Yes, I should revert that back to where it was bef
| |
| 71 if (m_dash) { | 70 if (m_dash) { |
| 72 flags->setPathEffect(m_dash); | 71 flags->setPathEffect(m_dash); |
| 73 } else if (strokeIsDashed(m_thickness, m_style)) { | 72 } else if (strokeIsDashed(m_thickness, m_style)) { |
| 74 float width = | 73 float dashLength = m_thickness; |
| 75 m_style == DashedStroke ? dashRatio * m_thickness : m_thickness; | 74 float gapLength = dashLength; |
| 76 | 75 if (m_style == DashedStroke) { |
| 77 // Truncate the width, since we don't want fuzzy dots or dashes. | 76 dashLength *= StrokeData::dashLengthRatio(m_thickness); |
| 78 int dashLength = static_cast<int>(width); | 77 gapLength *= StrokeData::dashGapRatio(m_thickness); |
| 79 // Subtract off the endcaps, since they're rendered separately. | 78 } |
| 80 int distance = length - 2 * static_cast<int>(m_thickness); | 79 float perDashLength = dashLength + gapLength; |
| 81 int phase = 1; | 80 // Account for modification to effective length in |
| 82 if (dashLength > 1) { | 81 // GraphicsContext::adjustLineToPixelBoundaries |
| 83 // Determine how many dashes or dots we should have. | 82 length -= 2 * m_thickness; |
| 84 int numDashes = distance / dashLength; | 83 if (length <= dashLength) { |
| 85 int remainder = distance % dashLength; | 84 // No space for dashes |
| 86 // Adjust the phase to center the dashes within the line. | 85 flags->setPathEffect(0); |
| 87 if (numDashes % 2) { | 86 } else if (length <= 2 * dashLength + gapLength) { |
| 88 // Odd: shift right a full dash, minus half the remainder. | 87 // Exactly 2 dashes proportionally sized |
| 89 phase = dashLength - remainder / 2; | 88 float multiplier = length / (2 * dashLength + gapLength); |
| 90 } else { | 89 SkScalar intervals[2] = {dashLength * multiplier, gapLength * multiplier}; |
| 91 // Even: shift right half a dash, minus half the remainder. | 90 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 92 phase = (dashLength - remainder) / 2; | 91 } else { |
| 92 float gap = gapLength; | |
| 93 if (m_style == DashedStroke) { | |
| 94 // Determine what number of dashes gives the minimum deviation from | |
| 95 // idealGap between dashes. Set the gap to that width. | |
| 96 float minNumDashes = floorf((length + gapLength) / perDashLength); | |
| 97 float maxNumDashes = minNumDashes + 1; | |
| 98 float minGap = | |
| 99 (length - minNumDashes * dashLength) / (minNumDashes - 1); | |
| 100 float maxGap = | |
| 101 (length - maxNumDashes * dashLength) / (maxNumDashes - 1); | |
| 102 gap = fabs(minGap - gapLength) < fabs(maxGap - gapLength) ? minGap | |
| 103 : maxGap; | |
| 93 } | 104 } |
| 105 SkScalar intervals[2] = {dashLength, gap}; | |
| 106 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); | |
| 94 } | 107 } |
| 95 SkScalar dashLengthSk = SkIntToScalar(dashLength); | |
| 96 SkScalar intervals[2] = {dashLengthSk, dashLengthSk}; | |
| 97 flags->setPathEffect( | |
| 98 SkDashPathEffect::Make(intervals, 2, SkIntToScalar(phase))); | |
| 99 } else if (m_style == DottedStroke) { | 108 } else if (m_style == DottedStroke) { |
| 100 flags->setStrokeCap((PaintFlags::Cap)RoundCap); | 109 flags->setStrokeCap((PaintFlags::Cap)RoundCap); |
| 101 // Adjust the width to get equal dot spacing as much as possible. | 110 // Adjust the width to get equal dot spacing as much as possible. |
| 102 float perDotLength = m_thickness * 2; | 111 float perDotLength = m_thickness * 2; |
| 103 static float epsilon = 1.0e-2f; | |
| 104 if (length < perDotLength + m_thickness) { | 112 if (length < perDotLength + m_thickness) { |
| 105 // Exactly 2 dots with whatever space we can get | 113 // Exactly 2 dots with whatever space we can get |
| 106 SkScalar intervals[2] = {0, length - m_thickness - epsilon}; | 114 SkScalar intervals[2] = {0, length - m_thickness - epsilon}; |
| 107 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); | 115 flags->setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); |
| 108 return; | 116 return; |
| 109 } | 117 } |
| 110 | 118 |
| 111 // Determine what number of dots gives the minimum deviation from | 119 // Determine what number of dots gives the minimum deviation from |
| 112 // idealGap between dots. Set the gap to that width. | 120 // idealGap between dots. Set the gap to that width. |
| 113 float minNumDots = floorf((length + m_thickness) / perDotLength); | 121 float minNumDots = floorf((length + m_thickness) / perDotLength); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 125 // TODO(schenney): WavyStroke https://crbug.com/229574 | 133 // TODO(schenney): WavyStroke https://crbug.com/229574 |
| 126 flags->setPathEffect(0); | 134 flags->setPathEffect(0); |
| 127 } | 135 } |
| 128 } | 136 } |
| 129 | 137 |
| 130 bool StrokeData::strokeIsDashed(float width, StrokeStyle style) { | 138 bool StrokeData::strokeIsDashed(float width, StrokeStyle style) { |
| 131 return style == DashedStroke || (style == DottedStroke && width <= 3); | 139 return style == DashedStroke || (style == DottedStroke && width <= 3); |
| 132 } | 140 } |
| 133 | 141 |
| 134 } // namespace blink | 142 } // namespace blink |
| OLD | NEW |