mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
svg: code refactoring
--cyclomatic complexity, no logical changes.
This commit is contained in:
parent
6357da3b97
commit
8492a63052
1 changed files with 114 additions and 138 deletions
|
@ -22,10 +22,8 @@
|
||||||
|
|
||||||
#include "tvgMath.h" /* to include math.h before cstring */
|
#include "tvgMath.h" /* to include math.h before cstring */
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
|
||||||
#include "tvgShape.h"
|
#include "tvgShape.h"
|
||||||
#include "tvgCompressor.h"
|
#include "tvgCompressor.h"
|
||||||
#include "tvgPaint.h"
|
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
#include "tvgStr.h"
|
#include "tvgStr.h"
|
||||||
#include "tvgSvgLoaderCommon.h"
|
#include "tvgSvgLoaderCommon.h"
|
||||||
|
@ -89,7 +87,6 @@ static void _transformMultiply(const Matrix* mBBox, Matrix* gradTransf)
|
||||||
static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient* g, const Box& vBox, int opacity)
|
static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient* g, const Box& vBox, int opacity)
|
||||||
{
|
{
|
||||||
Fill::ColorStop* stops;
|
Fill::ColorStop* stops;
|
||||||
int stopCount = 0;
|
|
||||||
auto fillGrad = LinearGradient::gen();
|
auto fillGrad = LinearGradient::gen();
|
||||||
auto isTransform = (g->transform ? true : false);
|
auto isTransform = (g->transform ? true : false);
|
||||||
auto& finalTransform = fillGrad->transform();
|
auto& finalTransform = fillGrad->transform();
|
||||||
|
@ -110,27 +107,25 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
|
||||||
fillGrad->spread(g->spread);
|
fillGrad->spread(g->spread);
|
||||||
|
|
||||||
//Update the stops
|
//Update the stops
|
||||||
stopCount = g->stops.count;
|
if (g->stops.count == 0) return fillGrad;
|
||||||
if (stopCount > 0) {
|
|
||||||
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
stops = (Fill::ColorStop*)malloc(g->stops.count * sizeof(Fill::ColorStop));
|
||||||
if (!stops) return fillGrad;
|
auto prevOffset = 0.0f;
|
||||||
auto prevOffset = 0.0f;
|
for (uint32_t i = 0; i < g->stops.count; ++i) {
|
||||||
for (uint32_t i = 0; i < g->stops.count; ++i) {
|
auto colorStop = &g->stops[i];
|
||||||
auto colorStop = &g->stops[i];
|
//Use premultiplied color
|
||||||
//Use premultiplied color
|
stops[i].r = colorStop->r;
|
||||||
stops[i].r = colorStop->r;
|
stops[i].g = colorStop->g;
|
||||||
stops[i].g = colorStop->g;
|
stops[i].b = colorStop->b;
|
||||||
stops[i].b = colorStop->b;
|
stops[i].a = static_cast<uint8_t>((colorStop->a * opacity) / 255);
|
||||||
stops[i].a = static_cast<uint8_t>((colorStop->a * opacity) / 255);
|
stops[i].offset = colorStop->offset;
|
||||||
stops[i].offset = colorStop->offset;
|
//check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
|
||||||
//check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
|
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
|
||||||
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
|
else if (colorStop->offset > 1) stops[i].offset = 1;
|
||||||
else if (colorStop->offset > 1) stops[i].offset = 1;
|
prevOffset = stops[i].offset;
|
||||||
prevOffset = stops[i].offset;
|
|
||||||
}
|
|
||||||
fillGrad->colorStops(stops, stopCount);
|
|
||||||
free(stops);
|
|
||||||
}
|
}
|
||||||
|
fillGrad->colorStops(stops, g->stops.count);
|
||||||
|
free(stops);
|
||||||
return fillGrad;
|
return fillGrad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +133,6 @@ static unique_ptr<LinearGradient> _applyLinearGradientProperty(SvgStyleGradient*
|
||||||
static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* g, const Box& vBox, int opacity)
|
static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient* g, const Box& vBox, int opacity)
|
||||||
{
|
{
|
||||||
Fill::ColorStop *stops;
|
Fill::ColorStop *stops;
|
||||||
int stopCount = 0;
|
|
||||||
auto fillGrad = RadialGradient::gen();
|
auto fillGrad = RadialGradient::gen();
|
||||||
auto isTransform = (g->transform ? true : false);
|
auto isTransform = (g->transform ? true : false);
|
||||||
auto& finalTransform = fillGrad->transform();
|
auto& finalTransform = fillGrad->transform();
|
||||||
|
@ -163,27 +157,25 @@ static unique_ptr<RadialGradient> _applyRadialGradientProperty(SvgStyleGradient*
|
||||||
fillGrad->spread(g->spread);
|
fillGrad->spread(g->spread);
|
||||||
|
|
||||||
//Update the stops
|
//Update the stops
|
||||||
stopCount = g->stops.count;
|
if (g->stops.count == 0) return fillGrad;
|
||||||
if (stopCount > 0) {
|
|
||||||
stops = (Fill::ColorStop*)calloc(stopCount, sizeof(Fill::ColorStop));
|
stops = (Fill::ColorStop*)malloc(g->stops.count * sizeof(Fill::ColorStop));
|
||||||
if (!stops) return fillGrad;
|
auto prevOffset = 0.0f;
|
||||||
auto prevOffset = 0.0f;
|
for (uint32_t i = 0; i < g->stops.count; ++i) {
|
||||||
for (uint32_t i = 0; i < g->stops.count; ++i) {
|
auto colorStop = &g->stops[i];
|
||||||
auto colorStop = &g->stops[i];
|
//Use premultiplied color
|
||||||
//Use premultiplied color
|
stops[i].r = colorStop->r;
|
||||||
stops[i].r = colorStop->r;
|
stops[i].g = colorStop->g;
|
||||||
stops[i].g = colorStop->g;
|
stops[i].b = colorStop->b;
|
||||||
stops[i].b = colorStop->b;
|
stops[i].a = static_cast<uint8_t>((colorStop->a * opacity) / 255);
|
||||||
stops[i].a = static_cast<uint8_t>((colorStop->a * opacity) / 255);
|
stops[i].offset = colorStop->offset;
|
||||||
stops[i].offset = colorStop->offset;
|
//check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
|
||||||
//check the offset corner cases - refer to: https://svgwg.org/svg2-draft/pservers.html#StopNotes
|
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
|
||||||
if (colorStop->offset < prevOffset) stops[i].offset = prevOffset;
|
else if (colorStop->offset > 1) stops[i].offset = 1;
|
||||||
else if (colorStop->offset > 1) stops[i].offset = 1;
|
prevOffset = stops[i].offset;
|
||||||
prevOffset = stops[i].offset;
|
|
||||||
}
|
|
||||||
fillGrad->colorStops(stops, stopCount);
|
|
||||||
free(stops);
|
|
||||||
}
|
}
|
||||||
|
fillGrad->colorStops(stops, g->stops.count);
|
||||||
|
free(stops);
|
||||||
return fillGrad;
|
return fillGrad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +189,7 @@ static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape*
|
||||||
Matrix finalTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
Matrix finalTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
if (node->transform) finalTransform = *node->transform;
|
if (node->transform) finalTransform = *node->transform;
|
||||||
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
||||||
Matrix m = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
|
finalTransform *= {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
|
||||||
finalTransform *= m;
|
|
||||||
}
|
}
|
||||||
if (child->transform) finalTransform = *child->transform * finalTransform;
|
if (child->transform) finalTransform = *child->transform * finalTransform;
|
||||||
|
|
||||||
|
@ -208,9 +199,7 @@ static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape*
|
||||||
|
|
||||||
static bool _appendClipChild(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, bool clip)
|
static bool _appendClipChild(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, bool clip)
|
||||||
{
|
{
|
||||||
if (node->type == SvgNodeType::Use) {
|
if (node->type == SvgNodeType::Use) return _appendClipUseNode(loaderData, node, shape, vBox, svgPath);
|
||||||
return _appendClipUseNode(loaderData, node, shape, vBox, svgPath);
|
|
||||||
}
|
|
||||||
return _appendClipShape(loaderData, node, shape, vBox, svgPath, nullptr);
|
return _appendClipShape(loaderData, node, shape, vBox, svgPath, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +217,7 @@ static Matrix _compositionTransform(Paint* paint, const SvgNode* node, const Svg
|
||||||
if (!compNode->node.clip.userSpace) {
|
if (!compNode->node.clip.userSpace) {
|
||||||
float x, y, w, h;
|
float x, y, w, h;
|
||||||
P(paint)->bounds(&x, &y, &w, &h, false, false);
|
P(paint)->bounds(&x, &y, &w, &h, false, false);
|
||||||
Matrix mBBox = {w, 0, x, 0, h, y, 0, 0, 1};
|
m *= {w, 0, x, 0, h, y, 0, 0, 1};
|
||||||
m *= mBBox;
|
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +236,6 @@ static void _applyComposition(SvgLoaderData& loaderData, Paint* paint, const Svg
|
||||||
node->style->clipPath.applying = true;
|
node->style->clipPath.applying = true;
|
||||||
|
|
||||||
auto comp = Shape::gen();
|
auto comp = Shape::gen();
|
||||||
|
|
||||||
auto child = compNode->child.data;
|
auto child = compNode->child.data;
|
||||||
auto valid = false; //Composite only when valid shapes exist
|
auto valid = false; //Composite only when valid shapes exist
|
||||||
|
|
||||||
|
@ -280,15 +267,11 @@ static void _applyComposition(SvgLoaderData& loaderData, Paint* paint, const Svg
|
||||||
if (!compNode->node.mask.userSpace) {
|
if (!compNode->node.mask.userSpace) {
|
||||||
Matrix finalTransform = _compositionTransform(paint, node, compNode, SvgNodeType::Mask);
|
Matrix finalTransform = _compositionTransform(paint, node, compNode, SvgNodeType::Mask);
|
||||||
comp->transform(finalTransform);
|
comp->transform(finalTransform);
|
||||||
} else {
|
} else if (node->transform) {
|
||||||
if (node->transform) comp->transform(*node->transform);
|
comp->transform(*node->transform);
|
||||||
}
|
|
||||||
|
|
||||||
if (compNode->node.mask.type == SvgMaskType::Luminance) {
|
|
||||||
paint->mask(std::move(comp), MaskMethod::Luma);
|
|
||||||
} else {
|
|
||||||
paint->mask(std::move(comp), MaskMethod::Alpha);
|
|
||||||
}
|
}
|
||||||
|
if (compNode->node.mask.type == SvgMaskType::Luminance) paint->mask(std::move(comp), MaskMethod::Luma);
|
||||||
|
else paint->mask(std::move(comp), MaskMethod::Alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
node->style->mask.applying = false;
|
node->style->mask.applying = false;
|
||||||
|
@ -330,13 +313,9 @@ static void _applyProperty(SvgLoaderData& loaderData, SvgNode* node, Shape* vg,
|
||||||
vg->fill(style->fill.paint.color.r, style->fill.paint.color.g, style->fill.paint.color.b, style->fill.opacity);
|
vg->fill(style->fill.paint.color.r, style->fill.paint.color.g, style->fill.paint.color.b, style->fill.opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply the fill rule
|
|
||||||
vg->fill((tvg::FillRule)style->fill.fillRule);
|
vg->fill((tvg::FillRule)style->fill.fillRule);
|
||||||
//Rendering order
|
|
||||||
vg->order(!style->paintOrder);
|
vg->order(!style->paintOrder);
|
||||||
|
vg->opacity(style->opacity);
|
||||||
//Apply node opacity
|
|
||||||
if (style->opacity < 255) vg->opacity(style->opacity);
|
|
||||||
|
|
||||||
if (node->type == SvgNodeType::G || node->type == SvgNodeType::Use) return;
|
if (node->type == SvgNodeType::G || node->type == SvgNodeType::Use) return;
|
||||||
|
|
||||||
|
@ -445,21 +424,16 @@ static unique_ptr<Shape> _shapeBuildHelper(SvgLoaderData& loaderData, SvgNode* n
|
||||||
|
|
||||||
static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform)
|
static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath, const Matrix* transform)
|
||||||
{
|
{
|
||||||
|
if (!_recognizeShape(node, shape)) return false;
|
||||||
|
|
||||||
//The 'transform' matrix has higher priority than the node->transform, since it already contains it
|
//The 'transform' matrix has higher priority than the node->transform, since it already contains it
|
||||||
auto m = transform ? transform : (node->transform ? node->transform : nullptr);
|
auto m = transform ? transform : (node->transform ? node->transform : nullptr);
|
||||||
|
|
||||||
uint32_t currentPtsCnt = 0;
|
uint32_t currentPtsCnt = 0;
|
||||||
if (m) {
|
if (m) {
|
||||||
const Point *tmp = nullptr;
|
currentPtsCnt = shape->pathCoords(nullptr);
|
||||||
currentPtsCnt = shape->pathCoords(&tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_recognizeShape(node, shape)) return false;
|
|
||||||
|
|
||||||
if (m) {
|
|
||||||
const Point *pts = nullptr;
|
const Point *pts = nullptr;
|
||||||
auto ptsCnt = shape->pathCoords(&pts);
|
auto ptsCnt = shape->pathCoords(&pts);
|
||||||
|
|
||||||
auto p = const_cast<Point*>(pts) + currentPtsCnt;
|
auto p = const_cast<Point*>(pts) + currentPtsCnt;
|
||||||
while (currentPtsCnt++ < ptsCnt) {
|
while (currentPtsCnt++ < ptsCnt) {
|
||||||
*p *= *m;
|
*p *= *m;
|
||||||
|
@ -478,10 +452,12 @@ enum class imageMimeTypeEncoding
|
||||||
utf8 = 0x2
|
utf8 = 0x2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
constexpr imageMimeTypeEncoding operator|(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
||||||
return static_cast<imageMimeTypeEncoding>(static_cast<int>(a) | static_cast<int>(b));
|
return static_cast<imageMimeTypeEncoding>(static_cast<int>(a) | static_cast<int>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
constexpr bool operator&(imageMimeTypeEncoding a, imageMimeTypeEncoding b) {
|
||||||
return (static_cast<int>(a) & static_cast<int>(b));
|
return (static_cast<int>(a) & static_cast<int>(b));
|
||||||
}
|
}
|
||||||
|
@ -508,38 +484,37 @@ static bool _isValidImageMimeTypeAndEncoding(const char** href, const char** mim
|
||||||
//mediatype := [ type "/" subtype ] *( ";" parameter )
|
//mediatype := [ type "/" subtype ] *( ";" parameter )
|
||||||
//parameter := attribute "=" value
|
//parameter := attribute "=" value
|
||||||
for (unsigned int i = 0; i < sizeof(imageMimeTypes) / sizeof(imageMimeTypes[0]); i++) {
|
for (unsigned int i = 0; i < sizeof(imageMimeTypes) / sizeof(imageMimeTypes[0]); i++) {
|
||||||
if (!strncmp(*href, imageMimeTypes[i].name, imageMimeTypes[i].sz - 1)) {
|
if (strncmp(*href, imageMimeTypes[i].name, imageMimeTypes[i].sz - 1)) continue;
|
||||||
*href += imageMimeTypes[i].sz - 1;
|
*href += imageMimeTypes[i].sz - 1;
|
||||||
*mimetype = imageMimeTypes[i].name;
|
*mimetype = imageMimeTypes[i].name;
|
||||||
|
|
||||||
while (**href && **href != ',') {
|
while (**href && **href != ',') {
|
||||||
while (**href && **href != ';') ++(*href);
|
while (**href && **href != ';') ++(*href);
|
||||||
if (!**href) return false;
|
if (!**href) return false;
|
||||||
++(*href);
|
++(*href);
|
||||||
|
|
||||||
if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::base64) {
|
if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::base64) {
|
||||||
if (!strncmp(*href, "base64,", sizeof("base64,") - 1)) {
|
if (!strncmp(*href, "base64,", sizeof("base64,") - 1)) {
|
||||||
*href += sizeof("base64,") - 1;
|
*href += sizeof("base64,") - 1;
|
||||||
*encoding = imageMimeTypeEncoding::base64;
|
*encoding = imageMimeTypeEncoding::base64;
|
||||||
return true; //valid base64
|
return true; //valid base64
|
||||||
}
|
|
||||||
}
|
|
||||||
if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8) {
|
|
||||||
if (!strncmp(*href, "utf8,", sizeof("utf8,") - 1)) {
|
|
||||||
*href += sizeof("utf8,") - 1;
|
|
||||||
*encoding = imageMimeTypeEncoding::utf8;
|
|
||||||
return true; //valid utf8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//no encoding defined
|
if (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8) {
|
||||||
if (**href == ',' && (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8)) {
|
if (!strncmp(*href, "utf8,", sizeof("utf8,") - 1)) {
|
||||||
++(*href);
|
*href += sizeof("utf8,") - 1;
|
||||||
*encoding = imageMimeTypeEncoding::utf8;
|
*encoding = imageMimeTypeEncoding::utf8;
|
||||||
return true; //allow no encoding defined if utf8 expected
|
return true; //valid utf8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
//no encoding defined
|
||||||
|
if (**href == ',' && (imageMimeTypes[i].encoding & imageMimeTypeEncoding::utf8)) {
|
||||||
|
++(*href);
|
||||||
|
*encoding = imageMimeTypeEncoding::utf8;
|
||||||
|
return true; //allow no encoding defined if utf8 expected
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -600,11 +575,13 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
||||||
TaskScheduler::async(true);
|
TaskScheduler::async(true);
|
||||||
|
|
||||||
float w, h;
|
float w, h;
|
||||||
Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
Matrix m;
|
||||||
if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) {
|
if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) {
|
||||||
auto sx = node->node.image.w / w;
|
auto sx = node->node.image.w / w;
|
||||||
auto sy = node->node.image.h / h;
|
auto sy = node->node.image.h / h;
|
||||||
m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
|
m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
|
||||||
|
} else {
|
||||||
|
m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
}
|
}
|
||||||
if (node->transform) m = *node->transform * m;
|
if (node->transform) m = *node->transform * m;
|
||||||
picture->transform(m);
|
picture->transform(m);
|
||||||
|
@ -622,8 +599,7 @@ static Matrix _calculateAspectRatioMatrix(AspectRatioAlign align, AspectRatioMee
|
||||||
auto tvx = box.x * sx;
|
auto tvx = box.x * sx;
|
||||||
auto tvy = box.y * sy;
|
auto tvy = box.y * sy;
|
||||||
|
|
||||||
if (align == AspectRatioAlign::None)
|
if (align == AspectRatioAlign::None) return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
|
||||||
return {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
|
|
||||||
|
|
||||||
//Scale
|
//Scale
|
||||||
if (meetOrSlice == AspectRatioMeetOrSlice::Meet) {
|
if (meetOrSlice == AspectRatioMeetOrSlice::Meet) {
|
||||||
|
@ -703,7 +679,6 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
||||||
|
|
||||||
if (node->node.use.symbol) {
|
if (node->node.use.symbol) {
|
||||||
auto symbol = node->node.use.symbol->node.symbol;
|
auto symbol = node->node.use.symbol->node.symbol;
|
||||||
|
|
||||||
auto width = (symbol.hasWidth ? symbol.w : vBox.w);
|
auto width = (symbol.hasWidth ? symbol.w : vBox.w);
|
||||||
if (node->node.use.isWidthSet) width = node->node.use.w;
|
if (node->node.use.isWidthSet) width = node->node.use.w;
|
||||||
auto height = (symbol.hasHeight ? symbol.h : vBox.h);;
|
auto height = (symbol.hasHeight ? symbol.h : vBox.h);;
|
||||||
|
@ -785,8 +760,10 @@ static unique_ptr<Text> _textBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
||||||
if (!textNode->text) return nullptr;
|
if (!textNode->text) return nullptr;
|
||||||
auto text = Text::gen();
|
auto text = Text::gen();
|
||||||
|
|
||||||
Matrix textTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
Matrix textTransform;
|
||||||
if (node->transform) textTransform = *node->transform;
|
if (node->transform) textTransform = *node->transform;
|
||||||
|
else textTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
|
|
||||||
translateR(&textTransform, node->node.text.x, node->node.text.y - textNode->fontSize);
|
translateR(&textTransform, node->node.text.x, node->node.text.y - textNode->fontSize);
|
||||||
text->transform(textTransform);
|
text->transform(textTransform);
|
||||||
|
|
||||||
|
@ -812,43 +789,42 @@ static unique_ptr<Scene> _sceneBuildHelper(SvgLoaderData& loaderData, const SvgN
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isGroupType(node->type) || mask) {
|
if (!_isGroupType(node->type) && !mask) return nullptr;
|
||||||
auto scene = Scene::gen();
|
|
||||||
// For a Symbol node, the viewBox transformation has to be applied first - see _useBuildHelper()
|
|
||||||
if (!mask && node->transform && node->type != SvgNodeType::Symbol) scene->transform(*node->transform);
|
|
||||||
|
|
||||||
if (node->style->display && node->style->opacity != 0) {
|
auto scene = Scene::gen();
|
||||||
auto child = node->child.data;
|
// For a Symbol node, the viewBox transformation has to be applied first - see _useBuildHelper()
|
||||||
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
|
if (!mask && node->transform && node->type != SvgNodeType::Symbol) scene->transform(*node->transform);
|
||||||
if (_isGroupType((*child)->type)) {
|
|
||||||
if ((*child)->type == SvgNodeType::Use)
|
if (!node->style->display || node->style->opacity == 0) return scene;
|
||||||
scene->push(_useBuildHelper(loaderData, *child, vBox, svgPath, depth + 1));
|
|
||||||
else if (!((*child)->type == SvgNodeType::Symbol && node->type != SvgNodeType::Use))
|
auto child = node->child.data;
|
||||||
scene->push(_sceneBuildHelper(loaderData, *child, vBox, svgPath, false, depth + 1));
|
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
|
||||||
if ((*child)->id) scene->id = djb2Encode((*child)->id);
|
if (_isGroupType((*child)->type)) {
|
||||||
} else if ((*child)->type == SvgNodeType::Image) {
|
if ((*child)->type == SvgNodeType::Use)
|
||||||
if (auto image = _imageBuildHelper(loaderData, *child, vBox, svgPath)) {
|
scene->push(_useBuildHelper(loaderData, *child, vBox, svgPath, depth + 1));
|
||||||
if ((*child)->id) image->id = djb2Encode((*child)->id);
|
else if (!((*child)->type == SvgNodeType::Symbol && node->type != SvgNodeType::Use))
|
||||||
scene->push(std::move(image));
|
scene->push(_sceneBuildHelper(loaderData, *child, vBox, svgPath, false, depth + 1));
|
||||||
}
|
if ((*child)->id) scene->id = djb2Encode((*child)->id);
|
||||||
} else if ((*child)->type == SvgNodeType::Text) {
|
} else if ((*child)->type == SvgNodeType::Image) {
|
||||||
if (auto text = _textBuildHelper(loaderData, *child, vBox, svgPath)) {
|
if (auto image = _imageBuildHelper(loaderData, *child, vBox, svgPath)) {
|
||||||
if ((*child)->id) text->id = djb2Encode((*child)->id);
|
if ((*child)->id) image->id = djb2Encode((*child)->id);
|
||||||
scene->push(std::move(text));
|
scene->push(std::move(image));
|
||||||
}
|
}
|
||||||
} else if ((*child)->type != SvgNodeType::Mask) {
|
} else if ((*child)->type == SvgNodeType::Text) {
|
||||||
if (auto shape = _shapeBuildHelper(loaderData, *child, vBox, svgPath)) {
|
if (auto text = _textBuildHelper(loaderData, *child, vBox, svgPath)) {
|
||||||
if ((*child)->id) shape->id = djb2Encode((*child)->id);
|
if ((*child)->id) text->id = djb2Encode((*child)->id);
|
||||||
scene->push(std::move(shape));
|
scene->push(std::move(text));
|
||||||
}
|
}
|
||||||
}
|
} else if ((*child)->type != SvgNodeType::Mask) {
|
||||||
|
if (auto shape = _shapeBuildHelper(loaderData, *child, vBox, svgPath)) {
|
||||||
|
if ((*child)->id) shape->id = djb2Encode((*child)->id);
|
||||||
|
scene->push(std::move(shape));
|
||||||
}
|
}
|
||||||
_applyComposition(loaderData, scene.get(), node, vBox, svgPath);
|
|
||||||
scene->opacity(node->style->opacity);
|
|
||||||
}
|
}
|
||||||
return scene;
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
_applyComposition(loaderData, scene.get(), node, vBox, svgPath);
|
||||||
|
scene->opacity(node->style->opacity);
|
||||||
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue