LibWeb: SVG: implement SmoothQuadraticBezierCurve

For this we need to track the control point of the previous command and
calculate a new control point based on it.
This commit is contained in:
Simon Danner 2020-09-07 22:58:47 +02:00 committed by Andreas Kling
parent 772fcba814
commit 9648bf4ada
Notes: sideshowbarker 2024-07-19 02:50:19 +09:00
2 changed files with 41 additions and 2 deletions

View File

@ -448,6 +448,8 @@ void SVGPathElement::paint(Gfx::Painter& painter, const SVGPaintingContext& cont
print_instruction(instruction);
#endif
bool clear_last_control_point = true;
switch (instruction.type) {
case PathInstructionType::Move: {
Gfx::FloatPoint point = { data[0], data[1] };
@ -580,27 +582,62 @@ void SVGPathElement::paint(Gfx::Painter& painter, const SVGPaintingContext& cont
break;
}
case PathInstructionType::QuadraticBezierCurve: {
clear_last_control_point = false;
Gfx::FloatPoint through = { data[0], data[1] };
Gfx::FloatPoint point = { data[2], data[3] };
if (absolute) {
path.quadratic_bezier_curve_to(through, point);
m_previous_control_point = through;
} else {
ASSERT(!path.segments().is_empty());
auto last_point = path.segments().last().point();
path.quadratic_bezier_curve_to(through + last_point, point + last_point);
auto control_point = through + last_point;
path.quadratic_bezier_curve_to(control_point, point + last_point);
m_previous_control_point = control_point;
}
break;
}
case PathInstructionType::SmoothQuadraticBezierCurve: {
clear_last_control_point = false;
ASSERT(!path.segments().is_empty());
auto last_point = path.segments().last().point();
if (m_previous_control_point.is_null()) {
m_previous_control_point = last_point;
}
auto dx_end_control = last_point.dx_relative_to(m_previous_control_point);
auto dy_end_control = last_point.dy_relative_to(m_previous_control_point);
auto control_point = Gfx::FloatPoint {last_point.x() + dx_end_control, last_point.y() + dy_end_control};
Gfx::FloatPoint end_point = {data[0], data[1]};
if (absolute) {
path.quadratic_bezier_curve_to(control_point, end_point);
}
else {
path.quadratic_bezier_curve_to(control_point, end_point + last_point);
}
m_previous_control_point = control_point;
break;
}
case PathInstructionType::Curve:
case PathInstructionType::SmoothCurve:
case PathInstructionType::SmoothQuadraticBezierCurve:
// Instead of crashing the browser every time we come across an SVG
// with these path instructions, let's just skip them
continue;
case PathInstructionType::Invalid:
ASSERT_NOT_REACHED();
}
if (clear_last_control_point) {
m_previous_control_point = Gfx::FloatPoint {};
}
}
// We need to fill the path before applying the stroke, however the filled

View File

@ -112,6 +112,8 @@ public:
private:
Vector<PathInstruction> m_instructions;
Gfx::FloatPoint m_previous_control_point = {};
};
}