SVG: Support geometry properties of use tag

This patch adds a support for geometry properties (x, y) of <use> tag
This commit is contained in:
Michal Maciola 2021-10-25 15:02:28 +02:00 committed by JunsuChoi
parent 4db3087c45
commit 00dfd55f18
3 changed files with 48 additions and 1 deletions

View file

@ -1818,12 +1818,36 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes) {
}
static constexpr struct
{
const char* tag;
SvgParserLengthType type;
int sz;
size_t offset;
} useTags[] = {
{"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)},
{"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)},
{"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)},
{"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)}
};
static bool _attrParseUseNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode *defs, *nodeFrom, *node = loader->svgParse->node;
string* id;
SvgUseNode* use = &(node->node.use);
int sz = strlen(key);
unsigned char* array = (unsigned char*)use;
for (unsigned int i = 0; i < sizeof(useTags) / sizeof(useTags[0]); i++) {
if (useTags[i].sz - 1 == sz && !strncmp(useTags[i].tag, key, sz)) {
*((float*)(array + useTags[i].offset)) = _toFloat(loader->svgParse, value, useTags[i].type);
return true;
}
}
if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
id = _idFromHref(value);
defs = _getDefsNode(node);

View file

@ -157,6 +157,11 @@ struct SvgDefsNode
Array<SvgStyleGradient*> gradients;
};
struct SvgUseNode
{
float x, y, w, h;
};
struct SvgEllipseNode
{
@ -334,6 +339,7 @@ struct SvgNode
SvgGNode g;
SvgDocNode doc;
SvgDefsNode defs;
SvgUseNode use;
SvgCircleNode circle;
SvgEllipseNode ellipse;
SvgPolygonNode polygon;

View file

@ -57,6 +57,7 @@
#include <float.h>
static bool _appendShape(SvgNode* node, Shape* shape, float vx, float vy, float vw, float vh);
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, float vx, float vy, float vw, float vh, const string& svgPath);
/************************************************************************/
/* Internal Class Implementation */
@ -550,6 +551,19 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, float vx, float vy,
}
static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, float vx, float vy, float vw, float vh, const string& svgPath)
{
auto scene = _sceneBuildHelper(node, vx, vy, vw, vh, svgPath);
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
scene->translate(node->node.use.x, node->node.use.y);
}
if (node->node.use.w > 0.0f && node->node.use.h > 0.0f) {
//TODO: handle width/height properties
}
return scene;
}
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, float vx, float vy, float vw, float vh, const string& svgPath)
{
if (_isGroupType(node->type)) {
@ -560,7 +574,10 @@ static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, float vx, float
auto child = node->child.data;
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
if (_isGroupType((*child)->type)) {
scene->push(_sceneBuildHelper(*child, vx, vy, vw, vh, svgPath));
if ((*child)->type == SvgNodeType::Use)
scene->push(_useBuildHelper(*child, vx, vy, vw, vh, svgPath));
else
scene->push(_sceneBuildHelper(*child, vx, vy, vw, vh, svgPath));
} else if ((*child)->type == SvgNodeType::Image) {
auto image = _imageBuildHelper(*child, vx, vy, vw, vh, svgPath);
if (image) scene->push(move(image));