ThorVG: Sync with upstream 0.8.0

This commit is contained in:
K. S. Ernest (iFire) Lee 2022-03-08 04:56:23 -08:00
parent 86b0faf2ec
commit f7a809603c
92 changed files with 870 additions and 227 deletions

View File

@ -399,7 +399,7 @@ License: Expat
Files: ./thirdparty/thorvg/ Files: ./thirdparty/thorvg/
Comment: ThorVG Comment: ThorVG
Copyright: 2020-2021, Samsung Electronics Co., Ltd. Copyright: 2020-2022, Samsung Electronics Co., Ltd.
License: Expat License: Expat
Files: ./thirdparty/tinyexr/ Files: ./thirdparty/tinyexr/

View File

@ -34,6 +34,7 @@ thirdparty_sources = [
"src/loaders/svg/tvgSvgSceneBuilder.cpp", "src/loaders/svg/tvgSvgSceneBuilder.cpp",
"src/loaders/svg/tvgSvgPath.cpp", "src/loaders/svg/tvgSvgPath.cpp",
"src/loaders/svg/tvgSvgLoader.cpp", "src/loaders/svg/tvgSvgLoader.cpp",
"src/loaders/svg/tvgSvgCssStyle.cpp",
"src/loaders/tvg/tvgTvgBinInterpreter.cpp", "src/loaders/tvg/tvgTvgBinInterpreter.cpp",
"src/loaders/tvg/tvgTvgLoader.cpp", "src/loaders/tvg/tvgTvgLoader.cpp",
"src/loaders/jpg/tvgJpgLoader.cpp", "src/loaders/jpg/tvgJpgLoader.cpp",

View File

@ -627,7 +627,7 @@ instead of `miniz.h` as an external dependency.
## thorvg ## thorvg
- Upstream: https://github.com/Samsung/thorvg - Upstream: https://github.com/Samsung/thorvg
- Version: 0.7.1 (d53eb2a880002cb770ace1c1ace9c5dfcfc28252, 2022) - Version: 0.8.0 (41093c17b3cac440bdcc53f8b69abeb5734696b5, 2022)
- License: MIT - License: MIT
Files extracted from upstream source: Files extracted from upstream source:

View File

@ -1,4 +1,4 @@
Hermet Park <chuneon.park@samsung.com> Hermet Park <hermetpark@gmail.com>
Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com> Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com>
Junsu Choi <jsuya.choi@samsung.com> Junsu Choi <jsuya.choi@samsung.com>
Pranay Samanta <pranay.ks@samsung.com> Pranay Samanta <pranay.ks@samsung.com>

View File

@ -1,4 +1,4 @@
Copyright (c) 2020 - 2021 notice for the ThorVG Project (see AUTHORS) Copyright (c) 2020 - 2022 notice for the ThorVG Project (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -13,5 +13,5 @@
#define THORVG_JPG_LOADER_SUPPORT 1 #define THORVG_JPG_LOADER_SUPPORT 1
#define THORVG_VERSION_STRING "0.7.1" #define THORVG_VERSION_STRING "0.8.0"
#endif #endif

View File

@ -145,8 +145,9 @@ enum class TVG_EXPORT CompositeMethod
{ {
None = 0, ///< No composition is applied. None = 0, ///< No composition is applied.
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered. ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which intersects with the target is visible. AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
InvAlphaMask ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which is not covered by the target is visible. InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
LumaMask ///< @BETA_API The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible.
}; };
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -235,6 +235,7 @@ struct SwImage
struct SwBlender struct SwBlender
{ {
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
uint32_t (*lumaValue)(uint32_t c);
}; };
struct SwCompositor; struct SwCompositor;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -47,6 +47,18 @@ static inline uint32_t _ialpha(uint32_t c)
} }
static inline uint32_t _abgrLumaValue(uint32_t c)
{
return ((((c&0xff)*54) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B
}
static inline uint32_t _argbLumaValue(uint32_t c)
{
return ((((c&0xff)*19) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R
}
static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{ {
return (a << 24 | b << 16 | g << 8 | r); return (a << 24 | b << 16 | g << 8 | r);
@ -139,7 +151,7 @@ static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t
auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h; ++y) { for (uint32_t y = 0; y < h; ++y) {
auto dst = &buffer[y * surface->stride]; auto dst = &buffer[y * surface->stride];
@ -173,6 +185,8 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color
return _rasterMaskedRect(surface, region, color, _alpha); return _rasterMaskedRect(surface, region, color, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterMaskedRect(surface, region, color, _ialpha); return _rasterMaskedRect(surface, region, color, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterMaskedRect(surface, region, color, surface->blender.lumaValue);
} }
} else { } else {
if (opacity == 255) { if (opacity == 255) {
@ -246,6 +260,8 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8
return _rasterMaskedRle(surface, rle, color, _alpha); return _rasterMaskedRle(surface, rle, color, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterMaskedRle(surface, rle, color, _ialpha); return _rasterMaskedRle(surface, rle, color, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterMaskedRle(surface, rle, color, surface->blender.lumaValue);
} }
} else { } else {
if (opacity == 255) { if (opacity == 255) {
@ -275,6 +291,8 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _alpha); return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha); return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.lumaValue);
} }
} else { } else {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr); return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
@ -494,12 +512,16 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _alpha); return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha); return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
} }
} else { } else {
if (surface->compositor->method == CompositeMethod::AlphaMask) { if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha); return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha); return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
} }
} }
} else { } else {
@ -616,12 +638,16 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
return _rasterDirectMaskedRleRGBAImage(surface, image, _alpha); return _rasterDirectMaskedRleRGBAImage(surface, image, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha); return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.lumaValue);
} }
} else { } else {
if (surface->compositor->method == CompositeMethod::AlphaMask) { if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _alpha); return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha); return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.lumaValue);
} }
} }
} else { } else {
@ -643,6 +669,8 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _alpha); return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _ialpha); return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, surface->blender.lumaValue);
} }
} else { } else {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, nullptr); return _rasterTexmapPolygon(surface, image, transform, &region, opacity, nullptr);
@ -832,12 +860,16 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _alpha); return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha); return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
} }
} else { } else {
if (surface->compositor->method == CompositeMethod::AlphaMask) { if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha); return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha); return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
} }
} }
} else { } else {
@ -861,7 +893,7 @@ static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* imag
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x); auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) { for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer; auto dst = buffer;
@ -888,7 +920,7 @@ static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x); auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) { for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer; auto dst = buffer;
@ -952,12 +984,16 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
return _rasterDirectMaskedRGBAImage(surface, image, region, _alpha); return _rasterDirectMaskedRGBAImage(surface, image, region, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha); return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.lumaValue);
} }
} else { } else {
if (surface->compositor->method == CompositeMethod::AlphaMask) { if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _alpha); return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha); return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.lumaValue);
} }
} }
} else { } else {
@ -1062,6 +1098,8 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
return _rasterLinearGradientMaskedRect(surface, region, fill, _alpha); return _rasterLinearGradientMaskedRect(surface, region, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha); return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
} }
} else { } else {
if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill); if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
@ -1166,6 +1204,8 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
return _rasterLinearGradientMaskedRle(surface, rle, fill, _alpha); return _rasterLinearGradientMaskedRle(surface, rle, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha); return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
} }
} else { } else {
if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill); if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
@ -1253,6 +1293,8 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
return _rasterRadialGradientMaskedRect(surface, region, fill, _alpha); return _rasterRadialGradientMaskedRect(surface, region, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha); return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
} }
} else { } else {
if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill); if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
@ -1356,6 +1398,8 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
return _rasterRadialGradientMaskedRle(surface, rle, fill, _alpha); return _rasterRadialGradientMaskedRle(surface, rle, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha); return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha);
} else if (surface->compositor->method == CompositeMethod::LumaMask) {
return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
} }
} else { } else {
if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill); if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
@ -1385,8 +1429,10 @@ bool rasterCompositor(SwSurface* surface)
{ {
if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) { if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) {
surface->blender.join = _abgrJoin; surface->blender.join = _abgrJoin;
surface->blender.lumaValue = _abgrLumaValue;
} else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) { } else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
surface->blender.join = _argbJoin; surface->blender.join = _argbJoin;
surface->blender.lumaValue = _argbLumaValue;
} else { } else {
//What Color Space ??? //What Color Space ???
return false; return false;
@ -1500,4 +1546,4 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co
//TODO: case: _rasterGrayscaleImage() //TODO: case: _rasterGrayscaleImage()
//TODO: case: _rasterAlphaImage() //TODO: case: _rasterAlphaImage()
return _rasterRGBAImage(surface, image, transform, bbox, opacity); return _rasterRGBAImage(surface, image, transform, bbox, opacity);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -26,8 +26,8 @@
static inline uint8x8_t ALPHA_BLEND(uint8x8_t c, uint8x8_t a) static inline uint8x8_t ALPHA_BLEND(uint8x8_t c, uint8x8_t a)
{ {
uint16x8_t t = vmull_u8(c, a); uint16x8_t t = vmull_u8(c, a);
return vshrn_n_u16(t, 8); return vshrn_n_u16(t, 8);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -19,11 +19,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
#include <math.h> #include "tvgMath.h"
#include "tvgSwCommon.h" #include "tvgSwCommon.h"
#include "tvgTaskScheduler.h" #include "tvgTaskScheduler.h"
#include "tvgSwRenderer.h" #include "tvgSwRenderer.h"
#include "tvgMath.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -79,8 +79,8 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
viewport.x = static_cast<int32_t>(v1.x); viewport.x = static_cast<int32_t>(v1.x);
viewport.y = static_cast<int32_t>(v1.y); viewport.y = static_cast<int32_t>(v1.y);
viewport.w = static_cast<int32_t>(v2.x - v1.x + 0.5f); viewport.w = static_cast<int32_t>(ceil(v2.x - viewport.x));
viewport.h = static_cast<int32_t>(v2.y - v1.y + 0.5f); viewport.h = static_cast<int32_t>(ceil(v2.y - viewport.y));
if (viewport.w < 0) viewport.w = 0; if (viewport.w < 0) viewport.w = 0;
if (viewport.h < 0) viewport.h = 0; if (viewport.h < 0) viewport.h = 0;
@ -404,4 +404,4 @@ uint8_t Paint::opacity() const noexcept
uint32_t Paint::identifier() const noexcept uint32_t Paint::identifier() const noexcept
{ {
return pImpl->id; return pImpl->id;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -93,7 +93,10 @@ bool PngLoader::read()
png_image_free(image); png_image_free(image);
return false; return false;
} }
if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) return false; if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) {
free(buffer);
return false;
}
content = reinterpret_cast<uint32_t*>(buffer); content = reinterpret_cast<uint32_t*>(buffer);
_premultiply(reinterpret_cast<uint32_t*>(buffer), image->width, image->height); _premultiply(reinterpret_cast<uint32_t*>(buffer), image->width, image->height);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -382,8 +382,8 @@ struct Row
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS; const int tmp0 = static_cast<unsigned int>(ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS; const int tmp1 = static_cast<unsigned int>(ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
@ -461,8 +461,8 @@ struct Col
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS; const int tmp0 = static_cast<unsigned int>(ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS; const int tmp1 = static_cast<unsigned int>(ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2; const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
@ -2557,7 +2557,7 @@ void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int
s = JPGD_HUFF_EXTEND(r, s); s = JPGD_HUFF_EXTEND(r, s);
} }
pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]); pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low); p[0] = static_cast<jpgd_block_t>(static_cast<unsigned int>(s) << pD->m_successive_low);
} }
@ -2588,7 +2588,7 @@ void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int
if ((k += r) > 63) pD->stop_decoding(JPGD_DECODE_ERROR); if ((k += r) > 63) pD->stop_decoding(JPGD_DECODE_ERROR);
r = pD->get_bits_no_markers(s); r = pD->get_bits_no_markers(s);
s = JPGD_HUFF_EXTEND(r, s); s = JPGD_HUFF_EXTEND(r, s);
p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low); p[g_ZAG[k]] = static_cast<jpgd_block_t>(static_cast<unsigned int>(s) << pD->m_successive_low);
} else { } else {
if (r == 15) { if (r == 15) {
if ((k += 15) > 63) pD->stop_decoding(JPGD_DECODE_ERROR); if ((k += 15) > 63) pD->stop_decoding(JPGD_DECODE_ERROR);
@ -2607,7 +2607,7 @@ void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, in
{ {
int s, k, r; int s, k, r;
int p1 = 1 << pD->m_successive_low; int p1 = 1 << pD->m_successive_low;
int m1 = (-1) << pD->m_successive_low; int m1 = static_cast<unsigned int>(-1) << pD->m_successive_low;
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y); jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
JPGD_ASSERT(pD->m_spectral_end <= 63); JPGD_ASSERT(pD->m_spectral_end <= 63);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "tvgSvgCssStyle.h"
/************************************************************************/
/* Internal Class Implementation */
/************************************************************************/
static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
{
if (from == nullptr) return;
//Copy the properties of 'from' only if they were explicitly set (not the default ones).
if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
to->color = from->color;
to->curColorSet = true;
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
}
//Fill
if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
to->fill.paint.color = from->fill.paint.color;
to->fill.paint.none = from->fill.paint.none;
to->fill.paint.curColor = from->fill.paint.curColor;
if (from->fill.paint.url) to->fill.paint.url = strdup(from->fill.paint.url);
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
}
if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
to->fill.opacity = from->fill.opacity;
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
}
if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
to->fill.fillRule = from->fill.fillRule;
to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
}
//Stroke
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
to->stroke.paint.color = from->stroke.paint.color;
to->stroke.paint.none = from->stroke.paint.none;
to->stroke.paint.curColor = from->stroke.paint.curColor;
if (from->stroke.paint.url) to->stroke.paint.url = strdup(from->stroke.paint.url);
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
to->stroke.opacity = from->stroke.opacity;
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
to->stroke.width = from->stroke.width;
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
if (from->stroke.dash.array.count > 0) {
to->stroke.dash.array.clear();
to->stroke.dash.array.reserve(from->stroke.dash.array.count);
for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
}
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
}
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
to->stroke.cap = from->stroke.cap;
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
}
if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
to->stroke.join = from->stroke.join;
to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
}
//Opacity
//TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
to->opacity = from->opacity;
to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
}
}
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
{
//Copy matrix attribute
if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
to->transform = (Matrix*)malloc(sizeof(Matrix));
if (to->transform) {
*to->transform = *from->transform;
to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
}
}
//Copy style attribute
_copyStyle(to->style, from->style);
if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
}
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type)
{
if (!style) return nullptr;
auto child = style->child.data;
for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
if ((*child)->type == type) {
if ((!title && !(*child)->id) || (title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
}
}
return nullptr;
}
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
{
if (!style) return nullptr;
auto child = style->child.data;
for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
if ((*child)->type == SvgNodeType::CssStyle) {
if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
}
}
return nullptr;
}
void cssUpdateStyle(SvgNode* doc, SvgNode* style)
{
if (doc->child.count > 0) {
auto child = doc->child.data;
for (uint32_t i = 0; i < doc->child.count; ++i, ++child) {
if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
cssCopyStyleAttr(*child, cssNode);
}
if (auto cssNode = cssFindStyleNode(style, nullptr)) {
cssCopyStyleAttr(*child, cssNode);
}
cssUpdateStyle(*child, style);
}
}
}
void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style)
{
for (uint32_t i = 0; i < postponeds.count; ++i) {
auto nodeIdPair = postponeds.data[i];
//css styling: tag.name has higher priority than .name
if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id, nodeIdPair.node->type)) {
cssCopyStyleAttr(nodeIdPair.node, cssNode);
}
if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id)) {
cssCopyStyleAttr(nodeIdPair.node, cssNode);
}
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _TVG_SVG_CSS_STYLE_H_
#define _TVG_SVG_CSS_STYLE_H_
#include "tvgSvgLoaderCommon.h"
void cssCopyStyleAttr(SvgNode* to, const SvgNode* from);
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type);
SvgNode* cssFindStyleNode(const SvgNode* style, const char* title);
void cssUpdateStyle(SvgNode* doc, SvgNode* style);
void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style);
#endif //_TVG_SVG_CSS_STYLE_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -60,6 +60,8 @@
#include "tvgSvgLoader.h" #include "tvgSvgLoader.h"
#include "tvgSvgSceneBuilder.h" #include "tvgSvgSceneBuilder.h"
#include "tvgSvgUtil.h" #include "tvgSvgUtil.h"
#include "tvgSvgCssStyle.h"
#include "tvgMath.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* Internal Class Implementation */
@ -75,11 +77,10 @@
#define PX_PER_MM 3.779528f //1 in = 25.4 mm -> PX_PER_IN/25.4 #define PX_PER_MM 3.779528f //1 in = 25.4 mm -> PX_PER_IN/25.4
#define PX_PER_CM 37.79528f //1 in = 2.54 cm -> PX_PER_IN/2.54 #define PX_PER_CM 37.79528f //1 in = 2.54 cm -> PX_PER_IN/2.54
typedef bool (*parseAttributes)(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength); typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func);
typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength); typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength);
static char* _skipSpace(const char* str, const char* end) static char* _skipSpace(const char* str, const char* end)
{ {
while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) { while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) {
@ -200,6 +201,14 @@ static int _toOpacity(const char* str)
} }
static SvgMaskType _toMaskType(const char* str)
{
if (!strcmp(str, "Alpha")) return SvgMaskType::Alpha;
return SvgMaskType::Luminance;
}
#define _PARSE_TAG(Type, Name, Name1, Tags_Array, Default) \ #define _PARSE_TAG(Type, Name, Name1, Tags_Array, Default) \
static Type _to##Name1(const char* str) \ static Type _to##Name1(const char* str) \
{ \ { \
@ -726,6 +735,12 @@ error:
} }
static void _postpone(Array<SvgNodeIdPair>& nodes, SvgNode *node, char* id)
{
nodes.push({node, id});
}
/* /*
// TODO - remove? // TODO - remove?
static constexpr struct static constexpr struct
@ -786,14 +801,12 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "preserveAspectRatio")) { } else if (!strcmp(key, "preserveAspectRatio")) {
if (!strcmp(value, "none")) doc->preserveAspect = false; if (!strcmp(value, "none")) doc->preserveAspect = false;
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
}
#ifdef THORVG_LOG_ENABLED #ifdef THORVG_LOG_ENABLED
else if ((!strcmp(key, "x") || !strcmp(key, "y")) && fabsf(svgUtilStrtof(value, nullptr)) > FLT_EPSILON) { } else if ((!strcmp(key, "x") || !strcmp(key, "y")) && fabsf(svgUtilStrtof(value, nullptr)) > FLT_EPSILON) {
TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value); TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value);
}
#endif #endif
else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
return true; return true;
@ -922,6 +935,12 @@ static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, con
} }
static void _handleMaskTypeAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
node->node.mask.type = _toMaskType(value);
}
static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{ {
//TODO : The display attribute can have various values as well as "none". //TODO : The display attribute can have various values as well as "none".
@ -933,6 +952,29 @@ static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node,
} }
static void _handleCssClassAttr(SvgLoaderData* loader, SvgNode* node, const char* value)
{
auto cssClass = &node->style->cssClass;
if (*cssClass && value) free(*cssClass);
*cssClass = _copyId(value);
bool cssClassFound = false;
//css styling: tag.name has higher priority than .name
if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass, node->type)) {
cssClassFound = true;
cssCopyStyleAttr(node, cssNode);
}
if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass)) {
cssClassFound = true;
cssCopyStyleAttr(node, cssNode);
}
if (!cssClassFound) _postpone(loader->nodesToStyle, node, *cssClass);
}
typedef void (*styleMethod)(SvgLoaderData* loader, SvgNode* node, const char* value); typedef void (*styleMethod)(SvgLoaderData* loader, SvgNode* node, const char* value);
#define STYLE_DEF(Name, Name1, Flag) { #Name, sizeof(#Name), _handle##Name1##Attr, Flag } #define STYLE_DEF(Name, Name1, Flag) { #Name, sizeof(#Name), _handle##Name1##Attr, Flag }
@ -959,6 +1001,7 @@ static constexpr struct
STYLE_DEF(transform, Transform, SvgStyleFlags::Transform), STYLE_DEF(transform, Transform, SvgStyleFlags::Transform),
STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath), STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath),
STYLE_DEF(mask, Mask, SvgStyleFlags::Mask), STYLE_DEF(mask, Mask, SvgStyleFlags::Mask),
STYLE_DEF(mask-type, MaskType, SvgStyleFlags::MaskType),
STYLE_DEF(display, Display, SvgStyleFlags::Display) STYLE_DEF(display, Display, SvgStyleFlags::Display)
}; };
@ -1006,12 +1049,14 @@ static bool _attrParseGNode(void* data, const char* key, const char* value)
SvgNode* node = loader->svgParse->node; SvgNode* node = loader->svgParse->node;
if (!strcmp(key, "style")) { if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) { } else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value); node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1030,17 +1075,19 @@ static bool _attrParseClipPathNode(void* data, const char* key, const char* valu
{ {
SvgLoaderData* loader = (SvgLoaderData*)data; SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node; SvgNode* node = loader->svgParse->node;
SvgCompositeNode* comp = &(node->node.comp); SvgClipNode* clip = &(node->node.clip);
if (!strcmp(key, "style")) { if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) { } else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value); node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "clipPathUnits")) { } else if (!strcmp(key, "clipPathUnits")) {
if (!strcmp(value, "objectBoundingBox")) comp->userSpace = false; if (!strcmp(value, "objectBoundingBox")) clip->userSpace = false;
} else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
@ -1052,17 +1099,21 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value)
{ {
SvgLoaderData* loader = (SvgLoaderData*)data; SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node; SvgNode* node = loader->svgParse->node;
SvgCompositeNode* comp = &(node->node.comp); SvgMaskNode* mask = &(node->node.mask);
if (!strcmp(key, "style")) { if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) { } else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value); node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "maskContentUnits")) { } else if (!strcmp(key, "maskContentUnits")) {
if (!strcmp(value, "objectBoundingBox")) comp->userSpace = false; if (!strcmp(value, "objectBoundingBox")) mask->userSpace = false;
} else if (!strcmp(key, "mask-type")) {
mask->type = _toMaskType(value);
} else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
@ -1070,6 +1121,46 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value)
} }
static bool _attrParseCssStyleNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node;
if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
return true;
}
static bool _attrParseSymbolNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node;
SvgSymbolNode* symbol = &(node->node.symbol);
if (!strcmp(key, "viewBox")) {
if (!_parseNumber(&value, &symbol->vx) || !_parseNumber(&value, &symbol->vy)) return false;
if (!_parseNumber(&value, &symbol->vw) || !_parseNumber(&value, &symbol->vh)) return false;
} else if (!strcmp(key, "width")) {
symbol->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal);
} else if (!strcmp(key, "height")) {
symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
} else if (!strcmp(key, "preserveAspectRatio")) {
if (!strcmp(value, "none")) symbol->preserveAspect = false;
} else if (!strcmp(key, "overflow")) {
if (!strcmp(value, "visible")) symbol->overflowVisible = true;
} else {
return _attrParseGNode(data, key, value);
}
return true;
}
static SvgNode* _createNode(SvgNode* parent, SvgNodeType type) static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
{ {
SvgNode* node = (SvgNode*)calloc(1, sizeof(SvgNode)); SvgNode* node = (SvgNode*)calloc(1, sizeof(SvgNode));
@ -1121,7 +1212,7 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
} }
static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength, TVG_UNUSED parseAttributes func)
{ {
if (loader->def && loader->doc->node.doc.defs) return loader->def; if (loader->def && loader->doc->node.doc.defs) return loader->def;
SvgNode* node = _createNode(nullptr, SvgNodeType::Defs); SvgNode* node = _createNode(nullptr, SvgNodeType::Defs);
@ -1132,17 +1223,17 @@ static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED Svg
} }
static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::G); loader->svgParse->node = _createNode(parent, SvgNodeType::G);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseGNode, loader); func(buf, bufLength, _attrParseGNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Doc); loader->svgParse->node = _createNode(parent, SvgNodeType::Doc);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
@ -1152,7 +1243,7 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
loader->svgParse->global.h = 0; loader->svgParse->global.h = 0;
doc->preserveAspect = true; doc->preserveAspect = true;
simpleXmlParseAttributes(buf, bufLength, _attrParseSvgNode, loader); func(buf, bufLength, _attrParseSvgNode, loader);
if (loader->svgParse->global.w == 0) { if (loader->svgParse->global.w == 0) {
if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1; if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1;
@ -1167,32 +1258,60 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
} }
static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, TVG_UNUSED const char* buf, TVG_UNUSED unsigned bufLength) static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, TVG_UNUSED const char* buf, TVG_UNUSED unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Mask); loader->svgParse->node = _createNode(parent, SvgNodeType::Mask);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->node.comp.userSpace = true; loader->svgParse->node->node.mask.userSpace = true;
loader->svgParse->node->node.mask.type = SvgMaskType::Luminance;
simpleXmlParseAttributes(buf, bufLength, _attrParseMaskNode, loader); func(buf, bufLength, _attrParseMaskNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
static SvgNode* _createClipPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createClipPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::ClipPath); loader->svgParse->node = _createNode(parent, SvgNodeType::ClipPath);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->display = false; loader->svgParse->node->display = false;
loader->svgParse->node->node.comp.userSpace = true; loader->svgParse->node->node.clip.userSpace = true;
simpleXmlParseAttributes(buf, bufLength, _attrParseClipPathNode, loader); func(buf, bufLength, _attrParseClipPathNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
static SvgNode* _createCssStyleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::CssStyle);
if (!loader->svgParse->node) return nullptr;
func(buf, bufLength, _attrParseCssStyleNode, loader);
return loader->svgParse->node;
}
static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Symbol);
if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->display = false;
loader->svgParse->node->node.symbol.preserveAspect = true;
loader->svgParse->node->node.symbol.overflowVisible = false;
func(buf, bufLength, _attrParseSymbolNode, loader);
return loader->svgParse->node;
}
static bool _attrParsePathNode(void* data, const char* key, const char* value) static bool _attrParsePathNode(void* data, const char* key, const char* value)
{ {
SvgLoaderData* loader = (SvgLoaderData*)data; SvgLoaderData* loader = (SvgLoaderData*)data;
@ -1203,7 +1322,7 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
//Temporary: need to copy //Temporary: need to copy
path->path = _copyId(value); path->path = _copyId(value);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1211,6 +1330,8 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
@ -1218,13 +1339,13 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Path); loader->svgParse->node = _createNode(parent, SvgNodeType::Path);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParsePathNode, loader); func(buf, bufLength, _attrParsePathNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1263,7 +1384,7 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
} }
if (!strcmp(key, "style")) { if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1271,6 +1392,8 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
@ -1278,13 +1401,13 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Circle); loader->svgParse->node = _createNode(parent, SvgNodeType::Circle);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseCircleNode, loader); func(buf, bufLength, _attrParseCircleNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1325,8 +1448,10 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value
if (!strcmp(key, "id")) { if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1338,13 +1463,13 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value
} }
static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Ellipse); loader->svgParse->node = _createNode(parent, SvgNodeType::Ellipse);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseEllipseNode, loader); func(buf, bufLength, _attrParseEllipseNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1400,7 +1525,7 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
if (!strcmp(key, "points")) { if (!strcmp(key, "points")) {
return _attrParsePolygonPoints(value, &polygon->points, &polygon->pointsCount); return _attrParsePolygonPoints(value, &polygon->points, &polygon->pointsCount);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1408,6 +1533,8 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else { } else {
return _parseStyleAttr(loader, key, value, false); return _parseStyleAttr(loader, key, value, false);
} }
@ -1415,24 +1542,24 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
} }
static SvgNode* _createPolygonNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createPolygonNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Polygon); loader->svgParse->node = _createNode(parent, SvgNodeType::Polygon);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader); func(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Polyline); loader->svgParse->node = _createNode(parent, SvgNodeType::Polyline);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader); func(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1482,8 +1609,10 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value)
if (!strcmp(key, "id")) { if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
ret = simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); ret = simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1496,7 +1625,7 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Rect); loader->svgParse->node = _createNode(parent, SvgNodeType::Rect);
@ -1504,7 +1633,7 @@ static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const ch
loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false; loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false;
simpleXmlParseAttributes(buf, bufLength, _attrParseRectNode, loader); func(buf, bufLength, _attrParseRectNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1545,8 +1674,10 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value)
if (!strcmp(key, "id")) { if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
@ -1558,13 +1689,13 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createLineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createLineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Line); loader->svgParse->node = _createNode(parent, SvgNodeType::Line);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseLineNode, loader); func(buf, bufLength, _attrParseLineNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1616,12 +1747,16 @@ static bool _attrParseImageNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) { } else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id); if (node->id && value) free(node->id);
node->id = _copyId(value); node->id = _copyId(value);
} else if (!strcmp(key, "class")) {
_handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader); return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) { } else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value); _handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) { } else if (!strcmp(key, "mask")) {
_handleMaskAttr(loader, node, value); _handleMaskAttr(loader, node, value);
} else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value);
} else { } else {
return _parseStyleAttr(loader, key, value); return _parseStyleAttr(loader, key, value);
} }
@ -1629,13 +1764,13 @@ static bool _attrParseImageNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Image); loader->svgParse->node = _createNode(parent, SvgNodeType::Image);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseImageNode, loader); func(buf, bufLength, _attrParseImageNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
@ -1941,12 +2076,6 @@ static void _cloneNode(SvgNode* from, SvgNode* parent, int depth)
} }
static void _postponeCloneNode(SvgLoaderData* loader, SvgNode *node, char* id)
{
loader->cloneNodes.push({node, id});
}
static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc) static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
{ {
for (uint32_t i = 0; i < cloneNodes->count; ++i) { for (uint32_t i = 0; i < cloneNodes->count; ++i) {
@ -1955,6 +2084,9 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
auto nodeFrom = _findChildById(defs, nodeIdPair.id); auto nodeFrom = _findChildById(defs, nodeIdPair.id);
if (!nodeFrom) nodeFrom = _findChildById(doc, nodeIdPair.id); if (!nodeFrom) nodeFrom = _findChildById(doc, nodeIdPair.id);
_cloneNode(nodeFrom, nodeIdPair.node, 0); _cloneNode(nodeFrom, nodeIdPair.node, 0);
if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
nodeIdPair.node->node.use.symbol = nodeFrom;
}
free(nodeIdPair.id); free(nodeIdPair.id);
} }
} }
@ -1967,10 +2099,10 @@ static constexpr struct
int sz; int sz;
size_t offset; size_t offset;
} useTags[] = { } useTags[] = {
{"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)}, {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgUseNode, x)},
{"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)}, {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgUseNode, y)},
{"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)}, {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgUseNode, w)},
{"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)} {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgUseNode, h)}
}; };
@ -1986,6 +2118,10 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
for (unsigned int i = 0; i < sizeof(useTags) / sizeof(useTags[0]); i++) { for (unsigned int i = 0; i < sizeof(useTags) / sizeof(useTags[0]); i++) {
if (useTags[i].sz - 1 == sz && !strncmp(useTags[i].tag, key, sz)) { if (useTags[i].sz - 1 == sz && !strncmp(useTags[i].tag, key, sz)) {
*((float*)(array + useTags[i].offset)) = _toFloat(loader->svgParse, value, useTags[i].type); *((float*)(array + useTags[i].offset)) = _toFloat(loader->svgParse, value, useTags[i].type);
if (useTags[i].offset == offsetof(SvgUseNode, w)) use->isWidthSet = true;
else if (useTags[i].offset == offsetof(SvgUseNode, h)) use->isHeightSet = true;
return true; return true;
} }
} }
@ -1996,12 +2132,13 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
nodeFrom = _findChildById(defs, id); nodeFrom = _findChildById(defs, id);
if (nodeFrom) { if (nodeFrom) {
_cloneNode(nodeFrom, node, 0); _cloneNode(nodeFrom, node, 0);
if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
free(id); free(id);
} else { } else {
//some svg export software include <defs> element at the end of the file //some svg export software include <defs> element at the end of the file
//if so the 'from' element won't be found now and we have to repeat finding //if so the 'from' element won't be found now and we have to repeat finding
//after the whole file is parsed //after the whole file is parsed
_postponeCloneNode(loader, node, id); _postpone(loader->cloneNodes, node, id);
} }
} else { } else {
return _attrParseGNode(data, key, value); return _attrParseGNode(data, key, value);
@ -2010,16 +2147,20 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
} }
static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength) static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{ {
loader->svgParse->node = _createNode(parent, SvgNodeType::Use); loader->svgParse->node = _createNode(parent, SvgNodeType::Use);
if (!loader->svgParse->node) return nullptr; if (!loader->svgParse->node) return nullptr;
simpleXmlParseAttributes(buf, bufLength, _attrParseUseNode, loader); loader->svgParse->node->node.use.isWidthSet = false;
loader->svgParse->node->node.use.isHeightSet = false;
func(buf, bufLength, _attrParseUseNode, loader);
return loader->svgParse->node; return loader->svgParse->node;
} }
//TODO: Implement 'text' primitive //TODO: Implement 'text' primitive
static constexpr struct static constexpr struct
{ {
@ -2049,7 +2190,9 @@ static constexpr struct
{"g", sizeof("g"), _createGNode}, {"g", sizeof("g"), _createGNode},
{"svg", sizeof("svg"), _createSvgNode}, {"svg", sizeof("svg"), _createSvgNode},
{"mask", sizeof("mask"), _createMaskNode}, {"mask", sizeof("mask"), _createMaskNode},
{"clipPath", sizeof("clipPath"), _createClipPathNode} {"clipPath", sizeof("clipPath"), _createClipPathNode},
{"style", sizeof("style"), _createCssStyleNode},
{"symbol", sizeof("symbol"), _createSymbolNode}
}; };
@ -2204,8 +2347,8 @@ static bool _attrParseRadialGradientNode(void* data, const char* key, const char
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { } else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref); if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value); grad->ref = _idFromHref(value);
} else if (!strcmp(key, "gradientUnits") && !strcmp(value, "userSpaceOnUse")) { } else if (!strcmp(key, "gradientUnits")) {
grad->userSpace = true; if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
} else if (!strcmp(key, "gradientTransform")) { } else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value); grad->transform = _parseTransformationMatrix(value);
} else { } else {
@ -2291,7 +2434,7 @@ static bool _attrParseStops(void* data, const char* key, const char* value)
_toColor(value, &stop->r, &stop->g, &stop->b, nullptr); _toColor(value, &stop->r, &stop->g, &stop->b, nullptr);
} }
} else if (!strcmp(key, "style")) { } else if (!strcmp(key, "style")) {
simpleXmlParseW3CAttribute(value, _attrParseStopsStyle, data); simpleXmlParseW3CAttribute(value, strlen(value), _attrParseStopsStyle, data);
} else { } else {
return false; return false;
} }
@ -2394,8 +2537,8 @@ static bool _attrParseLinearGradientNode(void* data, const char* key, const char
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) { } else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref); if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value); grad->ref = _idFromHref(value);
} else if (!strcmp(key, "gradientUnits") && !strcmp(value, "userSpaceOnUse")) { } else if (!strcmp(key, "gradientUnits")) {
grad->userSpace = true; if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
} else if (!strcmp(key, "gradientTransform")) { } else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value); grad->transform = _parseTransformationMatrix(value);
} else { } else {
@ -2479,11 +2622,13 @@ static constexpr struct
{"svg", sizeof("svg")}, {"svg", sizeof("svg")},
{"defs", sizeof("defs")}, {"defs", sizeof("defs")},
{"mask", sizeof("mask")}, {"mask", sizeof("mask")},
{"clipPath", sizeof("clipPath")} {"clipPath", sizeof("clipPath")},
{"style", sizeof("style")},
{"symbol", sizeof("symbol")}
}; };
static void _svgLoaderParerXmlClose(SvgLoaderData* loader, const char* content) static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content)
{ {
content = _skipSpace(content, nullptr); content = _skipSpace(content, nullptr);
@ -2531,13 +2676,20 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
if (empty) return; if (empty) return;
if (!loader->doc) { if (!loader->doc) {
if (strcmp(tagName, "svg")) return; //Not a valid svg document if (strcmp(tagName, "svg")) return; //Not a valid svg document
node = method(loader, nullptr, attrs, attrsLength); node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->doc = node; loader->doc = node;
} else { } else {
if (!strcmp(tagName, "svg")) return; //Already loaded <svg>(SvgNodeType::Doc) tag if (!strcmp(tagName, "svg")) return; //Already loaded <svg>(SvgNodeType::Doc) tag
if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1]; if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1];
else parent = loader->doc; else parent = loader->doc;
node = method(loader, parent, attrs, attrsLength); if (!strcmp(tagName, "style")) {
node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->cssStyle = node;
loader->doc->node.doc.style = node;
loader->style = true;
} else {
node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
}
} }
if (!node) return; if (!node) return;
@ -2547,7 +2699,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
} else if ((method = _findGraphicsFactory(tagName))) { } else if ((method = _findGraphicsFactory(tagName))) {
if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1]; if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1];
else parent = loader->doc; else parent = loader->doc;
node = method(loader, parent, attrs, attrsLength); node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
} else if ((gradientMethod = _findGradientFactory(tagName))) { } else if ((gradientMethod = _findGradientFactory(tagName))) {
SvgStyleGradient* gradient; SvgStyleGradient* gradient;
gradient = gradientMethod(loader, attrs, attrsLength); gradient = gradientMethod(loader, attrs, attrsLength);
@ -2578,6 +2730,42 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
} }
static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* content, unsigned int length)
{
char* tag;
char* name;
const char* attrs = nullptr;
unsigned int attrsLength = 0;
FactoryMethod method;
GradientFactoryMethod gradientMethod;
SvgNode *node = nullptr;
while (auto next = simpleXmlParseCSSAttribute(content, length, &tag, &name, &attrs, &attrsLength)) {
if ((method = _findGroupFactory(tag))) {
if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
} else if ((method = _findGraphicsFactory(tag))) {
if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
} else if ((gradientMethod = _findGradientFactory(tag))) {
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
} else if (!strcmp(tag, "stop")) {
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
} else if (!strcmp(tag, "all")) {
if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
} else if (!isIgnoreUnsupportedLogElements(tag)) {
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
}
length -= next - content;
content = next;
free(tag);
free(name);
}
loader->style = false;
}
static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content, unsigned int length) static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content, unsigned int length)
{ {
SvgLoaderData* loader = (SvgLoaderData*)data; SvgLoaderData* loader = (SvgLoaderData*)data;
@ -2592,11 +2780,14 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content
break; break;
} }
case SimpleXMLType::Close: { case SimpleXMLType::Close: {
_svgLoaderParerXmlClose(loader, content); _svgLoaderParserXmlClose(loader, content);
break; break;
} }
case SimpleXMLType::Data: case SimpleXMLType::Data:
case SimpleXMLType::CData: case SimpleXMLType::CData: {
if (loader->style) _svgLoaderParserXmlCssStyle(loader, content, length);
break;
}
case SimpleXMLType::DoctypeChild: { case SimpleXMLType::DoctypeChild: {
break; break;
} }
@ -2619,7 +2810,7 @@ static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node)
#ifdef THORVG_LOG_ENABLED #ifdef THORVG_LOG_ENABLED
auto type = simpleXmlNodeTypeToString(node->type); auto type = simpleXmlNodeTypeToString(node->type);
if (!node->display && node->type != SvgNodeType::ClipPath) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type); if (!node->display && node->type != SvgNodeType::ClipPath && node->type != SvgNodeType::Symbol) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type);
if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type); if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type);
if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type); if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type);
@ -2749,6 +2940,7 @@ static void _freeNodeStyle(SvgStyleProperty* style)
//style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode. //style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode.
free(style->clipPath.url); free(style->clipPath.url);
free(style->mask.url); free(style->mask.url);
free(style->cssClass);
if (style->fill.paint.gradient) { if (style->fill.paint.gradient) {
style->fill.paint.gradient->clear(); style->fill.paint.gradient->clear();
@ -2793,6 +2985,7 @@ static void _freeNode(SvgNode* node)
} }
case SvgNodeType::Doc: { case SvgNodeType::Doc: {
_freeNode(node->node.doc.defs); _freeNode(node->node.doc.defs);
_freeNode(node->node.doc.style);
break; break;
} }
case SvgNodeType::Defs: { case SvgNodeType::Defs: {
@ -2846,7 +3039,7 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch
if ((method = _findGroupFactory(tagName))) { if ((method = _findGroupFactory(tagName))) {
if (!loader->doc) { if (!loader->doc) {
if (strcmp(tagName, "svg")) return true; //Not a valid svg document if (strcmp(tagName, "svg")) return true; //Not a valid svg document
node = method(loader, nullptr, attrs, attrsLength); node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->doc = node; loader->doc = node;
loader->stack.push(node); loader->stack.push(node);
return false; return false;
@ -2906,16 +3099,20 @@ void SvgLoader::run(unsigned tid)
if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return; if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return;
if (loaderData.doc) { if (loaderData.doc) {
_updateStyle(loaderData.doc, nullptr);
auto defs = loaderData.doc->node.doc.defs; auto defs = loaderData.doc->node.doc.defs;
if (loaderData.nodesToStyle.count > 0) cssApplyStyleToPostponeds(loaderData.nodesToStyle, loaderData.cssStyle);
if (loaderData.cssStyle) cssUpdateStyle(loaderData.doc, loaderData.cssStyle);
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes, loaderData.doc);
_updateComposite(loaderData.doc, loaderData.doc); _updateComposite(loaderData.doc, loaderData.doc);
if (defs) _updateComposite(loaderData.doc, defs); if (defs) _updateComposite(loaderData.doc, defs);
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes, loaderData.doc);
if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients); if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients);
if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients); if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients);
_updateStyle(loaderData.doc, nullptr);
} }
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath); root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -51,6 +51,8 @@ enum class SvgNodeType
Video, Video,
ClipPath, ClipPath,
Mask, Mask,
CssStyle,
Symbol,
Unknown Unknown
}; };
@ -111,7 +113,8 @@ enum class SvgStyleFlags
Transform = 0x800, Transform = 0x800,
ClipPath = 0x1000, ClipPath = 0x1000,
Mask = 0x2000, Mask = 0x2000,
Display = 0x4000 MaskType = 0x4000,
Display = 0x8000
}; };
enum class SvgStopStyleFlags enum class SvgStopStyleFlags
@ -127,6 +130,12 @@ enum class SvgFillRule
OddEven = 1 OddEven = 1
}; };
enum class SvgMaskType
{
Luminance = 0,
Alpha
};
//Length type to recalculate %, pt, pc, mm, cm etc //Length type to recalculate %, pt, pc, mm, cm etc
enum class SvgParserLengthType enum class SvgParserLengthType
{ {
@ -145,6 +154,7 @@ struct SvgDocNode
float vw; float vw;
float vh; float vh;
SvgNode* defs; SvgNode* defs;
SvgNode* style;
bool preserveAspect; bool preserveAspect;
}; };
@ -157,12 +167,22 @@ struct SvgDefsNode
Array<SvgStyleGradient*> gradients; Array<SvgStyleGradient*> gradients;
}; };
struct SvgSymbolNode
{
float w, h;
float vx, vy, vw, vh;
bool preserveAspect;
bool overflowVisible;
};
struct SvgUseNode struct SvgUseNode
{ {
float x, y, w, h; float x, y, w, h;
bool isWidthSet;
bool isHeightSet;
SvgNode* symbol;
}; };
struct SvgEllipseNode struct SvgEllipseNode
{ {
float cx; float cx;
@ -215,11 +235,21 @@ struct SvgPolygonNode
float* points; float* points;
}; };
struct SvgCompositeNode struct SvgClipNode
{ {
bool userSpace; bool userSpace;
}; };
struct SvgMaskNode
{
SvgMaskType type;
bool userSpace;
};
struct SvgCssStyleNode
{
};
struct SvgLinearGradient struct SvgLinearGradient
{ {
float x1; float x1;
@ -328,6 +358,7 @@ struct SvgStyleProperty
int opacity; int opacity;
SvgColor color; SvgColor color;
bool curColorSet; bool curColorSet;
char* cssClass;
SvgStyleFlags flags; SvgStyleFlags flags;
}; };
@ -352,7 +383,10 @@ struct SvgNode
SvgPathNode path; SvgPathNode path;
SvgLineNode line; SvgLineNode line;
SvgImageNode image; SvgImageNode image;
SvgCompositeNode comp; SvgMaskNode mask;
SvgClipNode clip;
SvgCssStyleNode cssStyle;
SvgSymbolNode symbol;
} node; } node;
bool display; bool display;
~SvgNode(); ~SvgNode();
@ -384,15 +418,18 @@ struct SvgNodeIdPair
struct SvgLoaderData struct SvgLoaderData
{ {
Array<SvgNode *> stack = {nullptr, 0, 0}; Array<SvgNode*> stack = {nullptr, 0, 0};
SvgNode* doc = nullptr; SvgNode* doc = nullptr;
SvgNode* def = nullptr; SvgNode* def = nullptr;
SvgNode* cssStyle = nullptr;
Array<SvgStyleGradient*> gradients; Array<SvgStyleGradient*> gradients;
SvgStyleGradient* latestGradient = nullptr; //For stops SvgStyleGradient* latestGradient = nullptr; //For stops
SvgParser* svgParse = nullptr; SvgParser* svgParse = nullptr;
Array<SvgNodeIdPair> cloneNodes; Array<SvgNodeIdPair> cloneNodes;
Array<SvgNodeIdPair> nodesToStyle;
int level = 0; int level = 0;
bool result = false; bool result = false;
bool style = false;
}; };
/* /*

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -68,12 +68,12 @@ struct Box
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath); static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask); static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite = nullptr);
static inline bool _isGroupType(SvgNodeType type) static inline bool _isGroupType(SvgNodeType type)
{ {
if (type == SvgNodeType::Doc || type == SvgNodeType::G || type == SvgNodeType::Use || type == SvgNodeType::ClipPath) return true; if (type == SvgNodeType::Doc || type == SvgNodeType::G || type == SvgNodeType::Use || type == SvgNodeType::ClipPath || type == SvgNodeType::Symbol) return true;
return false; return false;
} }
@ -276,15 +276,21 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
Composition can be applied recursively if its children nodes have composition target to this one. */ Composition can be applied recursively if its children nodes have composition target to this one. */
if (node->style->mask.applying) { if (node->style->mask.applying) {
TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?"); TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?");
} else { } else {
auto compNode = node->style->mask.node; auto compNode = node->style->mask.node;
if (compNode && compNode->child.count > 0) { if (compNode && compNode->child.count > 0) {
node->style->mask.applying = true; node->style->mask.applying = true;
auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true); bool isMaskWhite = true;
auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true, &isMaskWhite);
if (comp) { if (comp) {
if (node->transform) comp->transform(*node->transform); if (node->transform) comp->transform(*node->transform);
paint->composite(move(comp), CompositeMethod::AlphaMask);
if (compNode->node.mask.type == SvgMaskType::Luminance && !isMaskWhite) {
paint->composite(move(comp), CompositeMethod::LumaMask);
} else {
paint->composite(move(comp), CompositeMethod::AlphaMask);
}
} }
node->style->mask.applying = false; node->style->mask.applying = false;
@ -534,57 +540,137 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con
string imagePath = href; string imagePath = href;
if (strncmp(href, "/", 1)) { if (strncmp(href, "/", 1)) {
auto last = svgPath.find_last_of("/"); auto last = svgPath.find_last_of("/");
imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1 )) + imagePath; imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath;
} }
if (picture->load(imagePath) != Result::Success) return nullptr; if (picture->load(imagePath) != Result::Success) return nullptr;
} }
float w, h; float w, h;
Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
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;
Matrix 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};
picture->transform(m);
} }
if (node->transform) m = mathMultiply(node->transform, &m);
picture->transform(m);
_applyComposition(picture.get(), node, vBox, svgPath); _applyComposition(picture.get(), node, vBox, svgPath);
return picture; return picture;
} }
static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath) static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool* isMaskWhite)
{ {
auto scene = _sceneBuildHelper(node, vBox, svgPath, false); unique_ptr<Scene> finalScene;
auto scene = _sceneBuildHelper(node, vBox, svgPath, false, isMaskWhite);
// mUseTransform = mUseTransform * mTranslate
Matrix mUseTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
if (node->transform) mUseTransform = *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) {
scene->translate(node->node.use.x, node->node.use.y); Matrix mTranslate = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
mUseTransform = mathMultiply(&mUseTransform, &mTranslate);
} }
if (node->node.use.w > 0.0f && node->node.use.h > 0.0f) {
//TODO: handle width/height properties if (node->node.use.symbol) {
auto symbol = node->node.use.symbol->node.symbol;
auto width = symbol.w;
if (node->node.use.isWidthSet) width = node->node.use.w;
auto height = symbol.h;
if (node->node.use.isHeightSet) height = node->node.use.h;
Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1};
if ((!mathEqual(width, symbol.vw) || !mathEqual(height, symbol.vh)) && symbol.vw > 0 && symbol.vh > 0) {
auto sx = width / symbol.vw;
auto sy = height / symbol.vh;
if (symbol.preserveAspect) {
if (sx < sy) sy = sx;
else sx = sy;
}
auto tvx = symbol.vx * sx;
auto tvy = symbol.vy * sy;
auto tvw = symbol.vw * sx;
auto tvh = symbol.vh * sy;
tvy -= (symbol.h - tvh) * 0.5f;
tvx -= (symbol.w - tvw) * 0.5f;
mViewBox = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
} else if (!mathZero(symbol.vx) || !mathZero(symbol.vy)) {
mViewBox = {1, 0, -symbol.vx, 0, 1, -symbol.vy, 0, 0, 1};
}
// mSceneTransform = mUseTransform * mSymbolTransform * mViewBox
Matrix mSceneTransform = mViewBox;
if (node->node.use.symbol->transform) {
mSceneTransform = mathMultiply(node->node.use.symbol->transform, &mViewBox);
}
mSceneTransform = mathMultiply(&mUseTransform, &mSceneTransform);
scene->transform(mSceneTransform);
if (node->node.use.symbol->node.symbol.overflowVisible) {
finalScene = move(scene);
} else {
auto viewBoxClip = Shape::gen();
viewBoxClip->appendRect(0, 0, width, height, 0, 0);
// mClipTransform = mUseTransform * mSymbolTransform
Matrix mClipTransform = mUseTransform;
if (node->node.use.symbol->transform) {
mClipTransform = mathMultiply(&mUseTransform, node->node.use.symbol->transform);
}
viewBoxClip->transform(mClipTransform);
auto compositeLayer = Scene::gen();
compositeLayer->composite(move(viewBoxClip), CompositeMethod::ClipPath);
compositeLayer->push(move(scene));
auto root = Scene::gen();
root->push(move(compositeLayer));
finalScene = move(root);
}
} else {
if (!mathIdentity((const Matrix*)(&mUseTransform))) scene->transform(mUseTransform);
finalScene = move(scene);
} }
return scene;
return finalScene;
} }
static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask) static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite)
{ {
if (_isGroupType(node->type) || mask) { if (_isGroupType(node->type) || mask) {
auto scene = Scene::gen(); auto scene = Scene::gen();
if (!mask && node->transform) scene->transform(*node->transform); // 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->display && node->style->opacity != 0) { if (node->display && node->style->opacity != 0) {
auto child = node->child.data; auto child = node->child.data;
for (uint32_t i = 0; i < node->child.count; ++i, ++child) { for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
if (_isGroupType((*child)->type)) { if (_isGroupType((*child)->type)) {
if ((*child)->type == SvgNodeType::Use) if ((*child)->type == SvgNodeType::Use)
scene->push(_useBuildHelper(*child, vBox, svgPath)); scene->push(_useBuildHelper(*child, vBox, svgPath, isMaskWhite));
else else
scene->push(_sceneBuildHelper(*child, vBox, svgPath, false)); scene->push(_sceneBuildHelper(*child, vBox, svgPath, false, isMaskWhite));
} else if ((*child)->type == SvgNodeType::Image) { } else if ((*child)->type == SvgNodeType::Image) {
auto image = _imageBuildHelper(*child, vBox, svgPath); auto image = _imageBuildHelper(*child, vBox, svgPath);
if (image) scene->push(move(image)); if (image) scene->push(move(image));
} else if ((*child)->type != SvgNodeType::Mask) { } else if ((*child)->type != SvgNodeType::Mask) {
auto shape = _shapeBuildHelper(*child, vBox, svgPath); auto shape = _shapeBuildHelper(*child, vBox, svgPath);
if (shape) scene->push(move(shape)); if (shape) {
if (isMaskWhite) {
uint8_t r, g, b;
shape->fillColor(&r, &g, &b, nullptr);
if (shape->fill() || r < 255 || g < 255 || b < 255 || shape->strokeFill() ||
(shape->strokeColor(&r, &g, &b, nullptr) == Result::Success && (r < 255 || g < 255 || b < 255))) {
*isMaskWhite = false;
}
}
scene->push(move(shape));
}
} }
} }
_applyComposition(scene.get(), node, vBox, svgPath); _applyComposition(scene.get(), node, vBox, svgPath);
@ -620,17 +706,13 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo
auto tvy = vy * scale; auto tvy = vy * scale;
auto tvw = vw * scale; auto tvw = vw * scale;
auto tvh = vh * scale; auto tvh = vh * scale;
if (vw > vh) tvy -= (h - tvh) * 0.5f; tvx -= (w - tvw) * 0.5f;
else tvx -= (w - tvw) * 0.5f; tvy -= (h - tvh) * 0.5f;
docNode->translate(-tvx, -tvy); docNode->translate(-tvx, -tvy);
} else { } else {
//Align //Align
auto tvx = vx * sx; auto tvx = vx * sx;
auto tvy = vy * sy; auto tvy = vy * sy;
auto tvw = vw * sx;
auto tvh = vh * sy;
if (tvw > tvh) tvy -= (h - tvh) * 0.5f;
else tvx -= (w - tvw) * 0.5f;
Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1}; Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
docNode->transform(m); docNode->transform(m);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -236,6 +236,14 @@ static SimpleXMLType _getXMLType(const char* itr, const char* itrEnd, size_t &to
} }
static char* _strndup(const char* src, unsigned len)
{
auto ret = (char*)malloc(len + 1);
if (!ret) return nullptr;
ret[len] = '\0';
return (char*)memcpy(ret, src, len);
}
/************************************************************************/ /************************************************************************/
/* External Class Implementation */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
@ -264,6 +272,7 @@ const char* simpleXmlNodeTypeToString(TVG_UNUSED SvgNodeType type)
"Video", "Video",
"ClipPath", "ClipPath",
"Mask", "Mask",
"Symbol",
"Unknown", "Unknown",
}; };
return TYPE_NAMES[(int) type]; return TYPE_NAMES[(int) type];
@ -450,7 +459,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb
} }
bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data) bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data)
{ {
const char* end; const char* end;
char* key; char* key;
@ -459,7 +468,7 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
if (!buf) return false; if (!buf) return false;
end = buf + strlen(buf); end = buf + bufLength;
key = (char*)alloca(end - buf + 1); key = (char*)alloca(end - buf + 1);
val = (char*)alloca(end - buf + 1); val = (char*)alloca(end - buf + 1);
@ -468,6 +477,11 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
do { do {
char* sep = (char*)strchr(buf, ':'); char* sep = (char*)strchr(buf, ':');
next = (char*)strchr(buf, ';'); next = (char*)strchr(buf, ';');
if (sep >= end) {
next = nullptr;
sep = nullptr;
}
if (next >= end) next = nullptr;
key[0] = '\0'; key[0] = '\0';
val[0] = '\0'; val[0] = '\0';
@ -509,6 +523,47 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
} }
/*
* Supported formats:
* tag {}, .name {}, tag.name{}
*/
const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength)
{
if (!buf) return nullptr;
*tag = *name = nullptr;
*attrsLength = 0;
auto itr = _simpleXmlSkipWhiteSpace(buf, buf + bufLength);
auto itrEnd = (const char*)memchr(buf, '{', bufLength);
if (!itrEnd || itr == itrEnd) return nullptr;
auto nextElement = (const char*)memchr(itrEnd, '}', bufLength - (itrEnd - buf));
if (!nextElement) return nullptr;
*attrs = itrEnd + 1;
*attrsLength = nextElement - *attrs;
const char *p;
itrEnd = _simpleXmlUnskipWhiteSpace(itrEnd, itr);
if (*(itrEnd - 1) == '.') return nullptr;
for (p = itr; p < itrEnd; p++) {
if (*p == '.') break;
}
if (p == itr) *tag = strdup("all");
else *tag = _strndup(itr, p - itr);
if (p == itrEnd) *name = nullptr;
else *name = _strndup(p + 1, itrEnd - p - 1);
return (nextElement ? nextElement + 1 : nullptr);
}
const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength) const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength)
{ {
const char *itr = buf, *itrEnd = buf + bufLength; const char *itr = buf, *itrEnd = buf + bufLength;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -32,7 +32,7 @@ const int xmlEntityLength[] = {6, 6, 6, 5, 4, 4, 6, 6};
enum class SimpleXMLType enum class SimpleXMLType
{ {
Open = 0, //!< \<tag attribute="value"\> Open = 0, //!< \<tag attribute="value"\>
OpenEmpty, //!< \<tag attribute="value" /\> OpenEmpty, //!< \<tag attribute="value" /\>
Close, //!< \</tag\> Close, //!< \</tag\>
Data, //!< tag text data Data, //!< tag text data
CData, //!< \<![cdata[something]]\> CData, //!< \<![cdata[something]]\>
@ -41,16 +41,17 @@ enum class SimpleXMLType
Doctype, //!< \<!doctype html Doctype, //!< \<!doctype html
Comment, //!< \<!-- something --\> Comment, //!< \<!-- something --\>
Ignored, //!< whatever is ignored by parser, like whitespace Ignored, //!< whatever is ignored by parser, like whitespace
DoctypeChild //!< \<!doctype_child DoctypeChild //!< \<!doctype_child
}; };
typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned int length); typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned int length);
typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value); typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value);
bool simpleXmlParseAttributes(const char* buf, unsigned buflen, simpleXMLAttributeCb func, const void* data); bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
bool simpleXmlParse(const char* buf, unsigned buflen, bool strip, simpleXMLCb func, const void* data); bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data);
bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data); bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
const char *simpleXmlFindAttributesTag(const char* buf, unsigned buflen); const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength);
const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength);
bool isIgnoreUnsupportedLogElements(const char* tagName); bool isIgnoreUnsupportedLogElements(const char* tagName);
const char* simpleXmlNodeTypeToString(SvgNodeType type); const char* simpleXmlNodeTypeToString(SvgNodeType type);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View File

@ -1,4 +1,4 @@
VERSION=0.7.1 VERSION=0.8.0
rm -rf AUTHORS inc LICENSE src *.zip rm -rf AUTHORS inc LICENSE src *.zip
curl -L -O https://github.com/Samsung/thorvg/archive/refs/tags/v$VERSION.zip curl -L -O https://github.com/Samsung/thorvg/archive/refs/tags/v$VERSION.zip
bsdtar --strip-components=1 -xvf *.zip bsdtar --strip-components=1 -xvf *.zip