mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 04:37:34 +00:00
LibWeb: Implement SVG S
(SmoothCurve) commands
These were being parsed, but skipped when rendering. With this fix, the SVG on discord's invite screen looks pretty nice! :^)
This commit is contained in:
parent
dc7e73a0b7
commit
bf178e0196
1 changed files with 31 additions and 5 deletions
|
@ -462,6 +462,7 @@ Gfx::Path& SVGPathElement::get_path()
|
|||
return m_path.value();
|
||||
|
||||
Gfx::Path path;
|
||||
PathInstructionType last_instruction = PathInstructionType::Invalid;
|
||||
|
||||
for (auto& instruction : m_instructions) {
|
||||
// If the first path element uses relative coordinates, we treat them as absolute by making them relative to (0, 0).
|
||||
|
@ -548,7 +549,8 @@ Gfx::Path& SVGPathElement::get_path()
|
|||
case PathInstructionType::SmoothQuadraticBezierCurve: {
|
||||
clear_last_control_point = false;
|
||||
|
||||
if (m_previous_control_point.is_null()) {
|
||||
if (m_previous_control_point.is_null()
|
||||
|| ((last_instruction != PathInstructionType::QuadraticBezierCurve) && (last_instruction != PathInstructionType::SmoothQuadraticBezierCurve))) {
|
||||
m_previous_control_point = last_point;
|
||||
}
|
||||
|
||||
|
@ -569,6 +571,8 @@ Gfx::Path& SVGPathElement::get_path()
|
|||
}
|
||||
|
||||
case PathInstructionType::Curve: {
|
||||
clear_last_control_point = false;
|
||||
|
||||
Gfx::FloatPoint c1 = { data[0], data[1] };
|
||||
Gfx::FloatPoint c2 = { data[2], data[3] };
|
||||
Gfx::FloatPoint p2 = { data[4], data[5] };
|
||||
|
@ -578,13 +582,34 @@ Gfx::Path& SVGPathElement::get_path()
|
|||
c2 += last_point;
|
||||
}
|
||||
path.cubic_bezier_curve_to(c1, c2, p2);
|
||||
|
||||
m_previous_control_point = c2;
|
||||
break;
|
||||
}
|
||||
|
||||
case PathInstructionType::SmoothCurve:
|
||||
// Instead of crashing the browser every time we come across an SVG
|
||||
// with these path instructions, let's just skip them
|
||||
continue;
|
||||
case PathInstructionType::SmoothCurve: {
|
||||
clear_last_control_point = false;
|
||||
|
||||
if (m_previous_control_point.is_null()
|
||||
|| ((last_instruction != PathInstructionType::Curve) && (last_instruction != PathInstructionType::SmoothCurve))) {
|
||||
m_previous_control_point = last_point;
|
||||
}
|
||||
|
||||
auto reflected_previous_control_x = last_point.dx_relative_to(m_previous_control_point);
|
||||
auto reflected_previous_control_y = last_point.dy_relative_to(m_previous_control_point);
|
||||
Gfx::FloatPoint c1 = Gfx::FloatPoint { reflected_previous_control_x, reflected_previous_control_y };
|
||||
Gfx::FloatPoint c2 = { data[0], data[1] };
|
||||
Gfx::FloatPoint p2 = { data[2], data[3] };
|
||||
if (!absolute) {
|
||||
p2 += last_point;
|
||||
c1 += last_point;
|
||||
c2 += last_point;
|
||||
}
|
||||
path.cubic_bezier_curve_to(c1, c2, p2);
|
||||
|
||||
m_previous_control_point = c2;
|
||||
break;
|
||||
}
|
||||
case PathInstructionType::Invalid:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
@ -592,6 +617,7 @@ Gfx::Path& SVGPathElement::get_path()
|
|||
if (clear_last_control_point) {
|
||||
m_previous_control_point = Gfx::FloatPoint {};
|
||||
}
|
||||
last_instruction = instruction.type;
|
||||
}
|
||||
|
||||
m_path = path;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue