Index: sky/engine/core/rendering/InlineTextBox.cpp |
diff --git a/sky/engine/core/rendering/InlineTextBox.cpp b/sky/engine/core/rendering/InlineTextBox.cpp |
index 3132df88be7b7b532de198962c128f8e9521b601..feb203950d1c68cb494bc86bf40aeb6f37b78684 100644 |
--- a/sky/engine/core/rendering/InlineTextBox.cpp |
+++ b/sky/engine/core/rendering/InlineTextBox.cpp |
@@ -796,10 +796,25 @@ static void adjustStepToDecorationLength(float& step, float& controlPointDistanc |
controlPointDistance += adjustment; |
} |
+struct CurveAlongX { |
+ static inline float y(FloatPoint p) { return p.y(); } |
+ static inline float x(FloatPoint p) { return p.x(); } |
+ static inline FloatPoint p(float x, float y) { return FloatPoint(x, y); } |
+ static inline void setX(FloatPoint& p, double x) { p.setX(x); } |
abarth-chromium
2015/06/19 23:00:46
const FloatPoint& for y, x, and setX.
(Also, I wo
|
+}; |
+ |
+struct CurveAlongY { |
+ static inline float y(FloatPoint p) { return p.x(); } |
+ static inline float x(FloatPoint p) { return p.y(); } |
+ static inline FloatPoint p(float x, float y) { return FloatPoint(y, x); } |
+ static inline void setX(FloatPoint& p, double x) { p.setY(x); } |
abarth-chromium
2015/06/19 23:00:45
ditto
|
+}; |
+ |
/* |
- * Draw one cubic Bezier curve and repeat the same pattern long the the decoration's axis. |
- * The start point (p1), controlPoint1, controlPoint2 and end point (p2) of the Bezier curve |
- * form a diamond shape: |
+ * Draw one cubic Bezier curve and repeat the same pattern along the |
+ * the decoration's axis. The start point (p1), controlPoint1, |
+ * controlPoint2 and end point (p2) of the Bezier curve form a diamond |
+ * shape, as follows (the four points marked +): |
* |
* step |
* |-----------| |
@@ -822,84 +837,62 @@ static void adjustStepToDecorationLength(float& step, float& controlPointDistanc |
* |
* |-----------| |
* step |
+ * |
+ * strokeWavyTextDecorationInternal() takes two points, p1 and p2. |
+ * These must be axis-aligned. If they are horizontally-aligned, |
+ * specialize it with CurveAlongX; if they are vertically aligned, |
+ * specialize it with CurveAlongY. The function is written as if it |
+ * was doing everything along the X axis; CurveAlongY just flips the |
+ * coordinates around. |
*/ |
-static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint p1, FloatPoint p2, float strokeThickness) |
+template <class T> static void strokeWavyTextDecorationInternal(GraphicsContext* context, FloatPoint p1, FloatPoint p2, float strokeThickness) |
abarth-chromium
2015/06/19 23:00:45
s/T/Curve/ for readability.
|
{ |
+ ASSERT(T::y(p1) == T::y(p2)); // verify that this is indeed axis-aligned |
+ |
context->adjustLineToPixelBoundaries(p1, p2, strokeThickness, context->strokeStyle()); |
Path path; |
path.moveTo(p1); |
- // Distance between decoration's axis and Bezier curve's control points. |
- // The height of the curve is based on this distance. Use a minimum of 6 pixels distance since |
- // the actual curve passes approximately at half of that distance, that is 3 pixels. |
- // The minimum height of the curve is also approximately 3 pixels. Increases the curve's height |
- // as strockThickness increases to make the curve looks better. |
- float controlPointDistance = 3 * std::max<float>(2, strokeThickness); |
- |
- // Increment used to form the diamond shape between start point (p1), control |
- // points and end point (p2) along the axis of the decoration. Makes the |
- // curve wider as strockThickness increases to make the curve looks better. |
- float step = 2 * std::max<float>(2, strokeThickness); |
- |
- bool isVerticalLine = (p1.x() == p2.x()); |
- |
- if (isVerticalLine) { |
- ASSERT(p1.x() == p2.x()); |
- |
- float xAxis = p1.x(); |
- float y1; |
- float y2; |
- |
- if (p1.y() < p2.y()) { |
- y1 = p1.y(); |
- y2 = p2.y(); |
- } else { |
- y1 = p2.y(); |
- y2 = p1.y(); |
- } |
+ float controlPointDistance = 2 * strokeThickness; |
+ float step = controlPointDistance; |
- adjustStepToDecorationLength(step, controlPointDistance, y2 - y1); |
- FloatPoint controlPoint1(xAxis + controlPointDistance, 0); |
- FloatPoint controlPoint2(xAxis - controlPointDistance, 0); |
+ float yAxis = T::y(p1); |
+ float x1; |
+ float x2; |
- for (float y = y1; y + 2 * step <= y2;) { |
- controlPoint1.setY(y + step); |
- controlPoint2.setY(y + step); |
- y += 2 * step; |
- path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(xAxis, y)); |
- } |
+ if (T::x(p1) < T::x(p2)) { |
+ x1 = T::x(p1); |
+ x2 = T::x(p2); |
abarth-chromium
2015/06/19 23:00:45
Should we give these more semantic names, like |ma
|
} else { |
- ASSERT(p1.y() == p2.y()); |
- |
- float yAxis = p1.y(); |
- float x1; |
- float x2; |
- |
- if (p1.x() < p2.x()) { |
- x1 = p1.x(); |
- x2 = p2.x(); |
- } else { |
- x1 = p2.x(); |
- x2 = p1.x(); |
- } |
+ x1 = T::x(p2); |
+ x2 = T::x(p1); |
+ } |
- adjustStepToDecorationLength(step, controlPointDistance, x2 - x1); |
- FloatPoint controlPoint1(0, yAxis + controlPointDistance); |
- FloatPoint controlPoint2(0, yAxis - controlPointDistance); |
+ adjustStepToDecorationLength(step, controlPointDistance, x2 - x1); |
- for (float x = x1; x + 2 * step <= x2;) { |
- controlPoint1.setX(x + step); |
- controlPoint2.setX(x + step); |
- x += 2 * step; |
- path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yAxis)); |
- } |
+ FloatPoint controlPoint1 = T::p(0, yAxis + controlPointDistance); |
+ FloatPoint controlPoint2 = T::p(0, yAxis - controlPointDistance); |
+ |
+ for (float x = x1; x + 2 * step <= x2;) { |
+ T::setX(controlPoint1, x + step); |
+ T::setX(controlPoint2, x + step); |
+ x += 2 * step; |
+ path.addBezierCurveTo(controlPoint1, controlPoint2, T::p(x, yAxis)); |
} |
context->setShouldAntialias(true); |
context->strokePath(path); |
} |
+static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint p1, FloatPoint p2, float strokeThickness) |
+{ |
+ if (p1.y() == p2.y()) // horizontal line |
+ strokeWavyTextDecorationInternal<CurveAlongX>(context, p1, p2, strokeThickness); |
+ else // vertical line |
+ strokeWavyTextDecorationInternal<CurveAlongY>(context, p1, p2, strokeThickness); |
+} |
+ |
static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle) |
{ |
return decorationStyle == TextDecorationStyleDotted || decorationStyle == TextDecorationStyleDashed; |
@@ -962,7 +955,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& |
// Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px. |
// Update Underline thickness, in case we have Faulty Font Metrics calculating underline thickness by old method. |
- float textDecorationThickness = styleToUse->fontMetrics().underlineThickness(); |
+ float textDecorationThickness = styleToUse->fontMetrics().underlineThickness(); // TODO(ianh): Make this author-controllable |
int fontHeightInt = (int)(styleToUse->fontMetrics().floatHeight() + 0.5); |
if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHeightInt >> 1))) |
textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f); |