mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:47: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();
|
return m_path.value();
|
||||||
|
|
||||||
Gfx::Path path;
|
Gfx::Path path;
|
||||||
|
PathInstructionType last_instruction = PathInstructionType::Invalid;
|
||||||
|
|
||||||
for (auto& instruction : m_instructions) {
|
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).
|
// 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: {
|
case PathInstructionType::SmoothQuadraticBezierCurve: {
|
||||||
clear_last_control_point = false;
|
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;
|
m_previous_control_point = last_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,6 +571,8 @@ Gfx::Path& SVGPathElement::get_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
case PathInstructionType::Curve: {
|
case PathInstructionType::Curve: {
|
||||||
|
clear_last_control_point = false;
|
||||||
|
|
||||||
Gfx::FloatPoint c1 = { data[0], data[1] };
|
Gfx::FloatPoint c1 = { data[0], data[1] };
|
||||||
Gfx::FloatPoint c2 = { data[2], data[3] };
|
Gfx::FloatPoint c2 = { data[2], data[3] };
|
||||||
Gfx::FloatPoint p2 = { data[4], data[5] };
|
Gfx::FloatPoint p2 = { data[4], data[5] };
|
||||||
|
@ -578,13 +582,34 @@ Gfx::Path& SVGPathElement::get_path()
|
||||||
c2 += last_point;
|
c2 += last_point;
|
||||||
}
|
}
|
||||||
path.cubic_bezier_curve_to(c1, c2, p2);
|
path.cubic_bezier_curve_to(c1, c2, p2);
|
||||||
|
|
||||||
|
m_previous_control_point = c2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PathInstructionType::SmoothCurve:
|
case PathInstructionType::SmoothCurve: {
|
||||||
// Instead of crashing the browser every time we come across an SVG
|
clear_last_control_point = false;
|
||||||
// with these path instructions, let's just skip them
|
|
||||||
continue;
|
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:
|
case PathInstructionType::Invalid:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -592,6 +617,7 @@ Gfx::Path& SVGPathElement::get_path()
|
||||||
if (clear_last_control_point) {
|
if (clear_last_control_point) {
|
||||||
m_previous_control_point = Gfx::FloatPoint {};
|
m_previous_control_point = Gfx::FloatPoint {};
|
||||||
}
|
}
|
||||||
|
last_instruction = instruction.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_path = path;
|
m_path = path;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue