SVG和SVG接口类设计
SVG类
SVG类用于在低层次表示一个树形的SVG结构。提供以下接口:
- 标签
- 属性
- 子节点管理
- 设置与获取原生HTML
- 克隆与拷贝
- 比较
- 差异
具体类
定义SVG的抽象类,其中含有所有SVG元素使用到的公共内容,涵盖了上述所有接口。然后定义SVG的具体类,例如<rect>,<circle>等,它们在标签、设置属性、克隆拷贝、比较、差异这几个接口上具有多态性。
接口定义
标签
一个虚函数get_tag
。SVGElement中的实现是返回?
。各个具体类中返回对应的标签,如rect
、circle
等。
virtual const std::string get_tag() const;
设置属性
一系列Getter和Setter封装。属性的类型均为字符串。
-
通用属性
SVGElement中提供了所有的通用属性。包括
-
元素属性
子节点管理
子节点是一个shared_ptr的vector;同时为了方便双向树形操作,内部还保存了一个weak_ptr指向父亲。
提供一些基本的子节点管理接口:
void add_inner_element(const std::shared_ptr<SVGElement> &element, int index = -1);
void remove_inner_element(const std::shared_ptr<SVGElement> &element, bool remove_all = false);
std::shared_ptr<SVGElement> get_inner_element(int index) const;
const std::vector<std::shared_ptr<SVGElement>> get_inner_elements() const;
void set_inner_elements(const std::vector<std::shared_ptr<SVGElement>> &inner_elements);
这些接口涵盖增删改查。
设置与获取原生HTML
DOM节点中实际上是支持任意内容,例如outerHTML可以解析文本和HTML。核心中不考虑这种设计,但支持其显示。
void set_raw_HTML(const std::string &text);
const std::string get_raw_HTML() const;
若被设置了原生HTML,则所有内容都被隐藏,只使用该原生HTML;反之,将使用由设置的内容推导出的HTML。
输出HTML使用如下方法:
const std::string outer_SVG() const;
克隆与拷贝
克隆:返回一个新的shared_ptr,指向新对象,新对象的所有内容和自己一致。
拷贝:重载等号运算符,从另一个对象进行赋值。要求两个对象的类型相同。
virtual std::shared_ptr<SVGElement> clone() const;
virtual SVGElement &operator=(const SVGElement &element);
比较
比较两个SVG对象是否相同。指的是推导出的HTML是否完全相同。
bool operator==(const SVGElement &element) const;
bool operator!=(const SVGElement &element) const;
差异
即DOM Diff算法。并且能推导出如何从一个SVG通过DOM操作变换到另一个SVG。
virtual const std::string operator-(const SVGElement &element) const;
接口实现
大部分细节不作描述。之后将详细讲解技术核心:Hash和Diff部分。
SVG接口类
SVG接口类用于在高层次对SVG类作可用性封装。首先是通过属性类对SVG类中的字符串形式的属性提供自动类型转换,然后是简化子节点管理过程,最后是提供提交机制便于每次操作后的渲染。
具体类
定义SVGI的抽象类,继承自SVG的抽象类并提供可用性封装。然后定义SVGI的具体类,多继承SVGI和SVG的具体类,例如<rect>,<circle>等。它们保留了SVG中的多态性,并SVGI的提交操作上具有多态性。
涉及到菱形继承,因此采用虚继承。
接口定义
自动类型转换的属性
自动类型转换来自之前讲解过的SVG属性类设计:
在此前实现的基础上,SVGI中对这些内容进行使用。例如stop-color
属性,可被如下定义:
AttrEnumerate<AttrConstCurrentcolor, AttrColor, AttrColor, AttrConstInherit> StopColor;
属性中的getter和setter被绑定到SVG的对应成员函数;commit和callback为类中以动态化的形式管理。具体如何管理详见之后的提交。
子节点操作简化
将子节点操作简化为如下形式:
void add(const std::shared_ptr<SVGIElement> &element, int index = -1);
void remove(const std::shared_ptr<SVGIElement> &element, bool remove_all = false);
void remove(int index);
std::shared_ptr<SVGIElement> child(int index) const;
const std::vector<std::shared_ptr<SVGIElement>> children() const;
void children(const std::vector<std::shared_ptr<SVGIElement>> &inner_elements);
这些定义既是简化,也是解决菱形继承下的二义性。
提交
一个和Diff算法相近的过程。使用了动态化的管理形式,对提交过程做出优化。
接口实现
大部分细节不作描述。之后将详细讲解技术核心:提交。