diff --git a/bridge/CMakeLists.txt b/bridge/CMakeLists.txt
index 81b63ae196..3079f78644 100644
--- a/bridge/CMakeLists.txt
+++ b/bridge/CMakeLists.txt
@@ -366,6 +366,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
core/svg/svg_circle_element.cc
core/svg/svg_ellipse_element.cc
core/svg/svg_style_element.cc
+ core/svg/svg_line_element.cc
# Legacy implements, should remove them in the future.
core/dom/legacy/element_attributes.cc
@@ -515,6 +516,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
out/qjs_svg_circle_element.cc
out/qjs_svg_ellipse_element.cc
out/qjs_svg_style_element.cc
+ out/qjs_svg_line_element.cc
)
diff --git a/bridge/bindings/qjs/binding_initializer.cc b/bridge/bindings/qjs/binding_initializer.cc
index 54d2ce71bf..f37e50dce0 100644
--- a/bridge/bindings/qjs/binding_initializer.cc
+++ b/bridge/bindings/qjs/binding_initializer.cc
@@ -77,6 +77,7 @@
#include "qjs_svg_g_element.h"
#include "qjs_svg_geometry_element.h"
#include "qjs_svg_graphics_element.h"
+#include "qjs_svg_line_element.h"
#include "qjs_svg_path_element.h"
#include "qjs_svg_rect_element.h"
#include "qjs_svg_style_element.h"
@@ -187,6 +188,7 @@ void InstallBindings(ExecutingContext* context) {
QJSSVGCircleElement::Install(context);
QJSSVGEllipseElement::Install(context);
QJSSVGStyleElement::Install(context);
+ QJSSVGLineElement::Install(context);
// Legacy bindings, not standard.
QJSElementAttributes::Install(context);
diff --git a/bridge/bindings/qjs/wrapper_type_info.h b/bridge/bindings/qjs/wrapper_type_info.h
index 671fa69964..085bbef1ae 100644
--- a/bridge/bindings/qjs/wrapper_type_info.h
+++ b/bridge/bindings/qjs/wrapper_type_info.h
@@ -104,6 +104,7 @@ enum {
JS_CLASS_SVG_CIRCLE_ELEMENT,
JS_CLASS_SVG_ELLIPSE_ELEMENT,
JS_CLASS_SVG_STYLE_ELEMENT,
+ JS_CLASS_SVG_LINE_ELEMENT,
// SVG unit
JS_CLASS_SVG_LENGTH,
diff --git a/bridge/core/svg/svg_line_element.cc b/bridge/core/svg/svg_line_element.cc
new file mode 100644
index 0000000000..e4a3bcef12
--- /dev/null
+++ b/bridge/core/svg/svg_line_element.cc
@@ -0,0 +1,11 @@
+/**
+ * Copyright (C) 2022-present The WebF authors. All rights reserved.
+ */
+
+#include "svg_line_element.h"
+#include "svg_geometry_element.h"
+#include "svg_names.h"
+
+namespace webf {
+SVGLineElement::SVGLineElement(Document& document) : SVGGeometryElement(svg_names::kline, document) {}
+} // namespace webf
diff --git a/bridge/core/svg/svg_line_element.d.ts b/bridge/core/svg/svg_line_element.d.ts
new file mode 100644
index 0000000000..42d90c715a
--- /dev/null
+++ b/bridge/core/svg/svg_line_element.d.ts
@@ -0,0 +1,10 @@
+/**
+ * Copyright (C) 2022-present The WebF authors. All rights reserved.
+ */
+
+import {SVGGeometryElement} from "./svg_geometry_element";
+
+export interface SVGLineElement extends SVGGeometryElement {
+ new(): void;
+ // TODO: add property in the future
+}
diff --git a/bridge/core/svg/svg_line_element.h b/bridge/core/svg/svg_line_element.h
new file mode 100644
index 0000000000..c2867eb0e8
--- /dev/null
+++ b/bridge/core/svg/svg_line_element.h
@@ -0,0 +1,22 @@
+/**
+ * Copyright (C) 2022-present The WebF authors. All rights reserved.
+ */
+#ifndef BRIDGE_CORE_SVG_SVG_LINE_ELEMENT_H_
+#define BRIDGE_CORE_SVG_SVG_LINE_ELEMENT_H_
+
+#include "core/svg/svg_geometry_element.h"
+
+namespace webf {
+
+class SVGLineElement : public SVGGeometryElement {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ using ImplType = SVGLineElement*;
+ explicit SVGLineElement(Document&);
+
+ private:
+};
+} // namespace webf
+
+#endif // BRIDGE_CORE_SVG_SVG_LINE_ELEMENT_H_
diff --git a/bridge/core/svg/svg_tag_names.json5 b/bridge/core/svg/svg_tag_names.json5
index 294bec606f..01b6832d4a 100644
--- a/bridge/core/svg/svg_tag_names.json5
+++ b/bridge/core/svg/svg_tag_names.json5
@@ -33,6 +33,7 @@
"g",
"circle",
"ellipse",
- "style"
+ "style",
+ "line"
]
}
diff --git a/integration_tests/snapshots/svg/shapes/line-01.svg.png b/integration_tests/snapshots/svg/shapes/line-01.svg.png
new file mode 100644
index 0000000000..f098f3b22e
Binary files /dev/null and b/integration_tests/snapshots/svg/shapes/line-01.svg.png differ
diff --git a/integration_tests/specs/svg/shapes/line-01.svg b/integration_tests/specs/svg/shapes/line-01.svg
new file mode 100644
index 0000000000..646a9fb0e9
--- /dev/null
+++ b/integration_tests/specs/svg/shapes/line-01.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/webf/lib/src/css/keywords.dart b/webf/lib/src/css/keywords.dart
index 8058046fe8..d6c96bc88c 100644
--- a/webf/lib/src/css/keywords.dart
+++ b/webf/lib/src/css/keywords.dart
@@ -323,6 +323,10 @@ const String D = 'd';
const String FILL_RULE = 'fillRule';
const String STROKE_LINECAP = 'strokeLinecap';
const String STROKE_LINEJOIN = 'strokeLinejoin';
+const String X1 = 'x1';
+const String Y1 = 'y1';
+const String X2 = 'x2';
+const String Y2 = 'y2';
// Pseudo
const String CONTENT = 'content';
diff --git a/webf/lib/src/css/render_style.dart b/webf/lib/src/css/render_style.dart
index 144f83ed78..4177b51263 100644
--- a/webf/lib/src/css/render_style.dart
+++ b/webf/lib/src/css/render_style.dart
@@ -202,6 +202,10 @@ abstract class RenderStyle {
CSSFillRule get fillRule;
CSSStrokeLinecap get strokeLinecap;
CSSStrokeLinejoin get strokeLinejoin;
+ CSSLengthValue get x1;
+ CSSLengthValue get y1;
+ CSSLengthValue get x2;
+ CSSLengthValue get y2;
void addFontRelativeProperty(String propertyName);
void addRootFontRelativeProperty(String propertyName);
@@ -486,6 +490,10 @@ class CSSRenderStyle extends RenderStyle
case CX:
case CY:
case R:
+ case X1:
+ case X2:
+ case Y1:
+ case Y2:
case STROKE_WIDTH:
value = CSSLength.resolveLength(propertyValue, renderStyle, propertyName);
break;
diff --git a/webf/lib/src/css/svg.dart b/webf/lib/src/css/svg.dart
index d60f368ec4..8a35d87e48 100644
--- a/webf/lib/src/css/svg.dart
+++ b/webf/lib/src/css/svg.dart
@@ -178,6 +178,38 @@ mixin CSSSvgMixin on RenderStyle {
_markRepaint();
}
+ CSSLengthValue? _x1;
+ @override get x1 => _x1 ?? CSSLengthValue.zero;
+ set x1(CSSLengthValue value){
+ if(_x1 == value) return;
+ _x1 = value;
+ _markShapeUpdate();
+ }
+
+ CSSLengthValue? _y1;
+ @override get y1 => _y1 ?? CSSLengthValue.zero;
+ set y1(CSSLengthValue value){
+ if(_y1 == value) return;
+ _y1 = value;
+ _markShapeUpdate();
+ }
+
+ CSSLengthValue? _x2;
+ @override get x2 => _x2 ?? CSSLengthValue.zero;
+ set x2(CSSLengthValue value){
+ if(_x2 == value) return;
+ _x2 = value;
+ _markShapeUpdate();
+ }
+
+ CSSLengthValue? _y2;
+ @override get y2 => _y2 ?? CSSLengthValue.zero;
+ set y2(CSSLengthValue value){
+ if(_y2 == value) return;
+ _y2 = value;
+ _markShapeUpdate();
+ }
+
static resolveFillRule(String value) {
return _CSSFillRuleMap[value] ?? CSSFillRule.nonzero;
}
diff --git a/webf/lib/src/dom/element.dart b/webf/lib/src/dom/element.dart
index 912c951e8b..01517cee6f 100644
--- a/webf/lib/src/dom/element.dart
+++ b/webf/lib/src/dom/element.dart
@@ -1725,6 +1725,18 @@ abstract class Element extends ContainerNode with ElementBase, ElementEventMixin
case R:
renderStyle.r = value;
break;
+ case X1:
+ renderStyle.x1 = value;
+ break;
+ case X2:
+ renderStyle.x2 = value;
+ break;
+ case Y1:
+ renderStyle.y1 = value;
+ break;
+ case Y2:
+ renderStyle.y2 = value;
+ break;
case D:
renderStyle.d = value;
break;
diff --git a/webf/lib/src/svg/line.dart b/webf/lib/src/svg/line.dart
new file mode 100644
index 0000000000..c3ce41fec1
--- /dev/null
+++ b/webf/lib/src/svg/line.dart
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022-present The WebF authors. All rights reserved.
+ */
+
+import 'package:webf/src/svg/rendering/line.dart';
+import 'package:webf/svg.dart';
+
+class SVGLineElement extends SVGGeometryElement {
+
+ late final RenderSVGLine _renderer;
+
+ @override
+ get renderBoxModel => _renderer;
+
+ @override
+ get presentationAttributeConfigs => super.presentationAttributeConfigs
+ ..addAll([
+ SVGPresentationAttributeConfig('x1'),
+ SVGPresentationAttributeConfig('y1'),
+ SVGPresentationAttributeConfig('x2'),
+ SVGPresentationAttributeConfig('y2'),
+ ]);
+
+ SVGLineElement(super.context) {
+ _renderer = RenderSVGLine(renderStyle: renderStyle, element: this);
+ }
+}
diff --git a/webf/lib/src/svg/registry.dart b/webf/lib/src/svg/registry.dart
index 173ceeef0e..f08dd64099 100644
--- a/webf/lib/src/svg/registry.dart
+++ b/webf/lib/src/svg/registry.dart
@@ -14,4 +14,5 @@ final Map svgElementsRegistry = {
'CIRCLE': (context) => SVGCircleElement(context),
'ELLIPSE': (context) => SVGEllipseElement(context),
'STYLE': (context) => SVGStyleElement(context),
+ 'LINE': (context) => SVGLineElement(context),
};
diff --git a/webf/lib/src/svg/rendering/line.dart b/webf/lib/src/svg/rendering/line.dart
new file mode 100644
index 0000000000..2e63e8ac09
--- /dev/null
+++ b/webf/lib/src/svg/rendering/line.dart
@@ -0,0 +1,19 @@
+
+import 'dart:ui';
+
+import 'package:webf/src/svg/rendering/shape.dart';
+
+// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line
+class RenderSVGLine extends RenderSVGShape{
+ RenderSVGLine({required super.renderStyle,super.element});
+
+ @override
+ Path asPath() {
+ final x1 = renderStyle.x1.computedValue;
+ final y1 = renderStyle.y1.computedValue;
+ final x2 = renderStyle.x2.computedValue;
+ final y2 = renderStyle.y2.computedValue;
+ return Path()..moveTo(x1, y1)..lineTo(x2, y2);
+ }
+
+}
diff --git a/webf/lib/svg.dart b/webf/lib/svg.dart
index ca9577c7d9..d0cae57d0a 100644
--- a/webf/lib/svg.dart
+++ b/webf/lib/svg.dart
@@ -17,3 +17,4 @@ export 'src/svg/unknown.dart';
export 'src/svg/circle.dart';
export 'src/svg/ellipse.dart';
export 'src/svg/style.dart';
+export 'src/svg/line.dart';