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';