You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Merge pull request #105093 from Chubercik/thorvg-0.15.12
thorvg: Update to 0.15.12
This commit is contained in:
3
thirdparty/README.md
vendored
3
thirdparty/README.md
vendored
@@ -955,7 +955,7 @@ Patches:
|
|||||||
## thorvg
|
## thorvg
|
||||||
|
|
||||||
- Upstream: https://github.com/thorvg/thorvg
|
- Upstream: https://github.com/thorvg/thorvg
|
||||||
- Version: 0.15.11 (61360cf6db0a05a8dd2ebdcc44d4cbbc315692ec, 2025)
|
- Version: 0.15.12 (91bd6f35b94e92abfc1a320632e66cd124943524, 2025)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
@@ -966,6 +966,7 @@ Files extracted from upstream source:
|
|||||||
Patches:
|
Patches:
|
||||||
|
|
||||||
- `0001-revert-tvglines-bezier-precision.patch` (GH-96658)
|
- `0001-revert-tvglines-bezier-precision.patch` (GH-96658)
|
||||||
|
- `0002-png-explicit-variable-scope.patch` (GH-105093)
|
||||||
|
|
||||||
|
|
||||||
## tinyexr
|
## tinyexr
|
||||||
|
|||||||
2
thirdparty/thorvg/inc/config.h
vendored
2
thirdparty/thorvg/inc/config.h
vendored
@@ -15,5 +15,5 @@
|
|||||||
// For internal debugging:
|
// For internal debugging:
|
||||||
//#define THORVG_LOG_ENABLED
|
//#define THORVG_LOG_ENABLED
|
||||||
|
|
||||||
#define THORVG_VERSION_STRING "0.15.11"
|
#define THORVG_VERSION_STRING "0.15.12"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
13
thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch
vendored
Normal file
13
thirdparty/thorvg/patches/0002-png-explicit-variable-scope.patch
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
|
||||||
|
index 71bf25a62b..c362403125 100644
|
||||||
|
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
|
||||||
|
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
|
||||||
|
@@ -88,7 +88,7 @@ bool PngLoader::read()
|
||||||
|
|
||||||
|
if (w == 0 || h == 0) return false;
|
||||||
|
|
||||||
|
- if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
|
||||||
|
+ if (ImageLoader::cs == ColorSpace::ARGB8888 || ImageLoader::cs == ColorSpace::ARGB8888S) {
|
||||||
|
image->format = PNG_FORMAT_BGRA;
|
||||||
|
surface.cs = ColorSpace::ARGB8888S;
|
||||||
|
} else {
|
||||||
@@ -88,7 +88,7 @@ bool PngLoader::read()
|
|||||||
|
|
||||||
if (w == 0 || h == 0) return false;
|
if (w == 0 || h == 0) return false;
|
||||||
|
|
||||||
if (cs == ColorSpace::ARGB8888 || cs == ColorSpace::ARGB8888S) {
|
if (ImageLoader::cs == ColorSpace::ARGB8888 || ImageLoader::cs == ColorSpace::ARGB8888S) {
|
||||||
image->format = PNG_FORMAT_BGRA;
|
image->format = PNG_FORMAT_BGRA;
|
||||||
surface.cs = ColorSpace::ARGB8888S;
|
surface.cs = ColorSpace::ARGB8888S;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ WebpLoader::WebpLoader() : ImageLoader(FileType::Webp)
|
|||||||
|
|
||||||
WebpLoader::~WebpLoader()
|
WebpLoader::~WebpLoader()
|
||||||
{
|
{
|
||||||
this->done();
|
done();
|
||||||
|
|
||||||
if (freeData) free(data);
|
if (freeData) free(data);
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ JpgLoader::JpgLoader() : ImageLoader(FileType::Jpg)
|
|||||||
|
|
||||||
JpgLoader::~JpgLoader()
|
JpgLoader::~JpgLoader()
|
||||||
{
|
{
|
||||||
|
done();
|
||||||
clear();
|
clear();
|
||||||
free(surface.buf8);
|
free(surface.buf8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,6 +405,27 @@ static char* _idFromUrl(const char* url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static size_t _srcFromUrl(const char* url, char*& src)
|
||||||
|
{
|
||||||
|
src = (char*)strchr(url, '(');
|
||||||
|
auto close = strchr(url, ')');
|
||||||
|
if (!src || !close || src >= close) return 0;
|
||||||
|
|
||||||
|
src = strchr(src, '\'');
|
||||||
|
if (!src || src >= close) return 0;
|
||||||
|
++src;
|
||||||
|
|
||||||
|
close = strchr(src, '\'');
|
||||||
|
if (!close || close == src) return 0;
|
||||||
|
--close;
|
||||||
|
|
||||||
|
while (src < close && *src == ' ') ++src;
|
||||||
|
while (src < close && *close == ' ') --close;
|
||||||
|
|
||||||
|
return close - src + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned char _parseColor(const char* value, char** end)
|
static unsigned char _parseColor(const char* value, char** end)
|
||||||
{
|
{
|
||||||
float r;
|
float r;
|
||||||
@@ -2005,6 +2026,42 @@ static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char* _unquote(const char* str)
|
||||||
|
{
|
||||||
|
auto len = str ? strlen(str) : 0;
|
||||||
|
if (len >= 2 && str[0] == '\'' && str[len - 1] == '\'') return strDuplicate(str + 1, len - 2);
|
||||||
|
return strdup(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool _attrParseFontFace(void* data, const char* key, const char* value)
|
||||||
|
{
|
||||||
|
if (!key || !value) return false;
|
||||||
|
|
||||||
|
key = _skipSpace(key, nullptr);
|
||||||
|
value = _skipSpace(value, nullptr);
|
||||||
|
|
||||||
|
auto loader = (SvgLoaderData*)data;
|
||||||
|
auto& font = loader->fonts.last();
|
||||||
|
|
||||||
|
if (!strcmp(key, "font-family")) {
|
||||||
|
if (font.name) free(font.name);
|
||||||
|
font.name = _unquote(value);
|
||||||
|
} else if (!strcmp(key, "src")) {
|
||||||
|
font.srcLen = _srcFromUrl(value, font.src);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _createFontFace(SvgLoaderData* loader, const char* buf, unsigned bufLength, parseAttributes func)
|
||||||
|
{
|
||||||
|
loader->fonts.push(FontFace());
|
||||||
|
func(buf, bufLength, _attrParseFontFace, loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static SvgNode* _getDefsNode(SvgNode* node)
|
static SvgNode* _getDefsNode(SvgNode* node)
|
||||||
{
|
{
|
||||||
if (!node) return nullptr;
|
if (!node) return nullptr;
|
||||||
@@ -3455,6 +3512,8 @@ static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* conte
|
|||||||
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
|
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
|
||||||
} else if (!strcmp(tag, "all")) {
|
} else if (!strcmp(tag, "all")) {
|
||||||
if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
|
if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
|
||||||
|
} else if (!strcmp(tag, "@font-face")) { //css at-rule specifying font
|
||||||
|
_createFontFace(loader, attrs, attrsLength, simpleXmlParseW3CAttribute);
|
||||||
} else if (!isIgnoreUnsupportedLogElements(tag)) {
|
} else if (!isIgnoreUnsupportedLogElements(tag)) {
|
||||||
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
|
TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
|
||||||
}
|
}
|
||||||
@@ -3829,7 +3888,7 @@ SvgLoader::SvgLoader() : ImageLoader(FileType::Svg)
|
|||||||
|
|
||||||
SvgLoader::~SvgLoader()
|
SvgLoader::~SvgLoader()
|
||||||
{
|
{
|
||||||
this->done();
|
done();
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -555,6 +555,14 @@ struct SvgNodeIdPair
|
|||||||
char *id;
|
char *id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FontFace
|
||||||
|
{
|
||||||
|
char* name = nullptr;
|
||||||
|
char* src = nullptr;
|
||||||
|
size_t srcLen = 0;
|
||||||
|
char* decoded = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
enum class OpenedTagType : uint8_t
|
enum class OpenedTagType : uint8_t
|
||||||
{
|
{
|
||||||
Other = 0,
|
Other = 0,
|
||||||
@@ -574,6 +582,7 @@ struct SvgLoaderData
|
|||||||
Array<SvgNodeIdPair> cloneNodes;
|
Array<SvgNodeIdPair> cloneNodes;
|
||||||
Array<SvgNodeIdPair> nodesToStyle;
|
Array<SvgNodeIdPair> nodesToStyle;
|
||||||
Array<char*> images; //embedded images
|
Array<char*> images; //embedded images
|
||||||
|
Array<FontFace> fonts;
|
||||||
int level = 0;
|
int level = 0;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
OpenedTagType openedTag = OpenedTagType::Other;
|
OpenedTagType openedTag = OpenedTagType::Other;
|
||||||
|
|||||||
@@ -573,8 +573,6 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||||||
if (!node->node.image.href || !strlen(node->node.image.href)) return nullptr;
|
if (!node->node.image.href || !strlen(node->node.image.href)) return nullptr;
|
||||||
auto picture = Picture::gen();
|
auto picture = Picture::gen();
|
||||||
|
|
||||||
TaskScheduler::async(false); //force to load a picture on the same thread
|
|
||||||
|
|
||||||
const char* href = node->node.image.href;
|
const char* href = node->node.image.href;
|
||||||
if (!strncmp(href, "data:", sizeof("data:") - 1)) {
|
if (!strncmp(href, "data:", sizeof("data:") - 1)) {
|
||||||
href += sizeof("data:") - 1;
|
href += sizeof("data:") - 1;
|
||||||
@@ -586,14 +584,12 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||||||
auto size = b64Decode(href, strlen(href), &decoded);
|
auto size = b64Decode(href, strlen(href), &decoded);
|
||||||
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
||||||
free(decoded);
|
free(decoded);
|
||||||
TaskScheduler::async(true);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto size = svgUtilURLDecode(href, &decoded);
|
auto size = svgUtilURLDecode(href, &decoded);
|
||||||
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
||||||
free(decoded);
|
free(decoded);
|
||||||
TaskScheduler::async(true);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,7 +601,6 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||||||
const char *dot = strrchr(href, '.');
|
const char *dot = strrchr(href, '.');
|
||||||
if (dot && !strcmp(dot, ".svg")) {
|
if (dot && !strcmp(dot, ".svg")) {
|
||||||
TVGLOG("SVG", "Embedded svg file is disabled.");
|
TVGLOG("SVG", "Embedded svg file is disabled.");
|
||||||
TaskScheduler::async(true);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
string imagePath = href;
|
string imagePath = href;
|
||||||
@@ -614,13 +609,10 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||||||
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) {
|
if (picture->load(imagePath) != Result::Success) {
|
||||||
TaskScheduler::async(true);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskScheduler::async(true);
|
|
||||||
|
|
||||||
float w, h;
|
float w, h;
|
||||||
Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
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) {
|
||||||
@@ -900,6 +892,41 @@ static void _updateInvalidViewSize(const Scene* scene, Box& vBox, float& w, floa
|
|||||||
if (!validHeight) h *= vBox.h;
|
if (!validHeight) h *= vBox.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _loadFonts(Array<FontFace>& fonts)
|
||||||
|
{
|
||||||
|
if (fonts.empty()) return;
|
||||||
|
|
||||||
|
static constexpr struct {
|
||||||
|
const char* prefix;
|
||||||
|
size_t len;
|
||||||
|
} prefixes[] = {
|
||||||
|
{"data:font/ttf;base64,", sizeof("data:font/ttf;base64,") - 1},
|
||||||
|
{"data:application/font-ttf;base64,", sizeof("data:application/font-ttf;base64,") - 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < fonts.count; ++i) {
|
||||||
|
auto p = &fonts[i];
|
||||||
|
if (!p->name) continue;
|
||||||
|
|
||||||
|
size_t shift = 0;
|
||||||
|
for (const auto& prefix : prefixes) {
|
||||||
|
if (p->srcLen > prefix.len && !memcmp(p->src, prefix.prefix, prefix.len)) {
|
||||||
|
shift = prefix.len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shift == 0) {
|
||||||
|
TVGLOG("SVG", "The embedded font \"%s\" data not loaded properly.", p->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = b64Decode(p->src + shift, p->srcLen - shift, &p->decoded);
|
||||||
|
|
||||||
|
if (Text::load(p->name, p->decoded, size) != Result::Success) TVGERR("SVG", "Error while loading the ttf font named \"%s\".", p->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -910,6 +937,8 @@ Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, Aspe
|
|||||||
|
|
||||||
if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr;
|
if (!loaderData.doc || (loaderData.doc->type != SvgNodeType::Doc)) return nullptr;
|
||||||
|
|
||||||
|
_loadFonts(loaderData.fonts);
|
||||||
|
|
||||||
auto docNode = _sceneBuildHelper(loaderData, loaderData.doc, vBox, svgPath, false, 0);
|
auto docNode = _sceneBuildHelper(loaderData, loaderData.doc, vBox, svgPath, false, 0);
|
||||||
|
|
||||||
if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag);
|
if (!(viewFlag & SvgViewFlag::Viewbox)) _updateInvalidViewSize(docNode.get(), vBox, w, h, viewFlag);
|
||||||
|
|||||||
@@ -483,6 +483,14 @@ bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAt
|
|||||||
do {
|
do {
|
||||||
char* sep = (char*)strchr(buf, ':');
|
char* sep = (char*)strchr(buf, ':');
|
||||||
next = (char*)strchr(buf, ';');
|
next = (char*)strchr(buf, ';');
|
||||||
|
|
||||||
|
if (auto src = strstr(buf, "src")) {//src tag from css font-face contains extra semicolon
|
||||||
|
if (src < sep) {
|
||||||
|
if (next + 1 < end) next = (char*)strchr(next + 1, ';');
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sep >= end) {
|
if (sep >= end) {
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
sep = nullptr;
|
sep = nullptr;
|
||||||
|
|||||||
@@ -314,10 +314,10 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fastTrack) {
|
if (fastTrack) {
|
||||||
renderRegion.min.x = static_cast<SwCoord>(nearbyint(xMin / 64.0f));
|
renderRegion.min.x = static_cast<SwCoord>(round(xMin / 64.0f));
|
||||||
renderRegion.max.x = static_cast<SwCoord>(nearbyint(xMax / 64.0f));
|
renderRegion.max.x = static_cast<SwCoord>(round(xMax / 64.0f));
|
||||||
renderRegion.min.y = static_cast<SwCoord>(nearbyint(yMin / 64.0f));
|
renderRegion.min.y = static_cast<SwCoord>(round(yMin / 64.0f));
|
||||||
renderRegion.max.y = static_cast<SwCoord>(nearbyint(yMax / 64.0f));
|
renderRegion.max.y = static_cast<SwCoord>(round(yMax / 64.0f));
|
||||||
} else {
|
} else {
|
||||||
renderRegion.min.x = xMin >> 6;
|
renderRegion.min.x = xMin >> 6;
|
||||||
renderRegion.max.x = (xMax + 63) >> 6;
|
renderRegion.max.x = (xMax + 63) >> 6;
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix& trans
|
|||||||
{
|
{
|
||||||
Line cur = {dash.ptCur, *to};
|
Line cur = {dash.ptCur, *to};
|
||||||
auto len = cur.length();
|
auto len = cur.length();
|
||||||
|
|
||||||
if (tvg::zero(len)) {
|
if (tvg::zero(len)) {
|
||||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||||
//draw the current line fully
|
//draw the current line fully
|
||||||
@@ -117,7 +116,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix& trans
|
|||||||
}
|
}
|
||||||
//draw the current line partially
|
//draw the current line partially
|
||||||
} else {
|
} else {
|
||||||
while (len - dash.curLen > 0.0001f) {
|
while (len - dash.curLen > DASH_PATTERN_THRESHOLD) {
|
||||||
Line left, right;
|
Line left, right;
|
||||||
if (dash.curLen > 0) {
|
if (dash.curLen > 0) {
|
||||||
len -= dash.curLen;
|
len -= dash.curLen;
|
||||||
@@ -178,7 +177,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
|
|||||||
}
|
}
|
||||||
//draw the current line partially
|
//draw the current line partially
|
||||||
} else {
|
} else {
|
||||||
while ((len - dash.curLen) > 0.0001f) {
|
while ((len - dash.curLen) > DASH_PATTERN_THRESHOLD) {
|
||||||
Bezier left, right;
|
Bezier left, right;
|
||||||
if (dash.curLen > 0) {
|
if (dash.curLen > 0) {
|
||||||
len -= dash.curLen;
|
len -= dash.curLen;
|
||||||
|
|||||||
21
thirdparty/thorvg/src/renderer/tvgLoadModule.h
vendored
21
thirdparty/thorvg/src/renderer/tvgLoadModule.h
vendored
@@ -23,6 +23,8 @@
|
|||||||
#ifndef _TVG_LOAD_MODULE_H_
|
#ifndef _TVG_LOAD_MODULE_H_
|
||||||
#define _TVG_LOAD_MODULE_H_
|
#define _TVG_LOAD_MODULE_H_
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include "tvgCommon.h"
|
||||||
#include "tvgRender.h"
|
#include "tvgRender.h"
|
||||||
#include "tvgInlist.h"
|
#include "tvgInlist.h"
|
||||||
|
|
||||||
@@ -38,7 +40,7 @@ struct LoadModule
|
|||||||
};
|
};
|
||||||
|
|
||||||
FileType type; //current loader file type
|
FileType type; //current loader file type
|
||||||
uint16_t sharing = 0; //reference count
|
atomic<uint16_t> sharing{}; //reference count
|
||||||
bool readied = false; //read done already.
|
bool readied = false; //read done already.
|
||||||
bool pathcache = false; //cached by path
|
bool pathcache = false; //cached by path
|
||||||
|
|
||||||
@@ -77,7 +79,7 @@ struct LoadModule
|
|||||||
|
|
||||||
struct ImageLoader : LoadModule
|
struct ImageLoader : LoadModule
|
||||||
{
|
{
|
||||||
static ColorSpace cs; //desired value
|
static atomic<ColorSpace> cs; //desired value
|
||||||
|
|
||||||
float w = 0, h = 0; //default image size
|
float w = 0, h = 0; //default image size
|
||||||
RenderSurface surface;
|
RenderSurface surface;
|
||||||
@@ -95,14 +97,21 @@ struct ImageLoader : LoadModule
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FontMetrics
|
||||||
|
{
|
||||||
|
//TODO: add necessary metrics
|
||||||
|
float minw;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct FontLoader : LoadModule
|
struct FontLoader : LoadModule
|
||||||
{
|
{
|
||||||
float scale = 1.0f;
|
|
||||||
|
|
||||||
FontLoader(FileType type) : LoadModule(type) {}
|
FontLoader(FileType type) : LoadModule(type) {}
|
||||||
|
|
||||||
virtual bool request(Shape* shape, char* text) = 0;
|
using LoadModule::read;
|
||||||
virtual bool transform(Paint* paint, float fontSize, bool italic) = 0;
|
|
||||||
|
virtual bool read(Shape* shape, char* text, FontMetrics& out) = 0;
|
||||||
|
virtual float transform(Paint* paint, FontMetrics& mertrics, float fontSize, bool italic) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_TVG_LOAD_MODULE_H_
|
#endif //_TVG_LOAD_MODULE_H_
|
||||||
|
|||||||
27
thirdparty/thorvg/src/renderer/tvgLoader.cpp
vendored
27
thirdparty/thorvg/src/renderer/tvgLoader.cpp
vendored
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include "tvgInlist.h"
|
#include "tvgInlist.h"
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
#include "tvgLock.h"
|
#include "tvgLock.h"
|
||||||
@@ -66,9 +67,10 @@ uintptr_t HASH_KEY(const char* data)
|
|||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
ColorSpace ImageLoader::cs = ColorSpace::ARGB8888;
|
//TODO: remove it.
|
||||||
|
atomic<ColorSpace> ImageLoader::cs{ColorSpace::ARGB8888};
|
||||||
|
|
||||||
static Key key;
|
static Key _key;
|
||||||
static Inlist<LoadModule> _activeLoaders;
|
static Inlist<LoadModule> _activeLoaders;
|
||||||
|
|
||||||
|
|
||||||
@@ -215,7 +217,7 @@ static LoadModule* _findByType(const string& mimeType)
|
|||||||
|
|
||||||
static LoadModule* _findFromCache(const string& path)
|
static LoadModule* _findFromCache(const string& path)
|
||||||
{
|
{
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
|
|
||||||
auto loader = _activeLoaders.head;
|
auto loader = _activeLoaders.head;
|
||||||
|
|
||||||
@@ -235,11 +237,10 @@ static LoadModule* _findFromCache(const char* data, uint32_t size, const string&
|
|||||||
auto type = _convert(mimeType);
|
auto type = _convert(mimeType);
|
||||||
if (type == FileType::Unknown) return nullptr;
|
if (type == FileType::Unknown) return nullptr;
|
||||||
|
|
||||||
ScopedLock lock(key);
|
|
||||||
auto loader = _activeLoaders.head;
|
|
||||||
|
|
||||||
auto key = HASH_KEY(data);
|
auto key = HASH_KEY(data);
|
||||||
|
ScopedLock lock(_key);
|
||||||
|
|
||||||
|
auto loader = _activeLoaders.head;
|
||||||
while (loader) {
|
while (loader) {
|
||||||
if (loader->type == type && loader->hashkey == key) {
|
if (loader->type == type && loader->hashkey == key) {
|
||||||
++loader->sharing;
|
++loader->sharing;
|
||||||
@@ -285,9 +286,9 @@ bool LoaderMgr::term()
|
|||||||
bool LoaderMgr::retrieve(LoadModule* loader)
|
bool LoaderMgr::retrieve(LoadModule* loader)
|
||||||
{
|
{
|
||||||
if (!loader) return false;
|
if (!loader) return false;
|
||||||
|
|
||||||
if (loader->close()) {
|
if (loader->close()) {
|
||||||
if (loader->cached()) {
|
if (loader->cached()) {
|
||||||
ScopedLock lock(key);
|
|
||||||
_activeLoaders.remove(loader);
|
_activeLoaders.remove(loader);
|
||||||
}
|
}
|
||||||
delete(loader);
|
delete(loader);
|
||||||
@@ -316,7 +317,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
|
|||||||
loader->hashpath = strdup(path.c_str());
|
loader->hashpath = strdup(path.c_str());
|
||||||
loader->pathcache = true;
|
loader->pathcache = true;
|
||||||
{
|
{
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,7 +333,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
|
|||||||
loader->hashpath = strdup(path.c_str());
|
loader->hashpath = strdup(path.c_str());
|
||||||
loader->pathcache = true;
|
loader->pathcache = true;
|
||||||
{
|
{
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,7 +391,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
|
|||||||
if (loader->open(data, size, copy)) {
|
if (loader->open(data, size, copy)) {
|
||||||
if (allowCache) {
|
if (allowCache) {
|
||||||
loader->hashkey = HASH_KEY(data);
|
loader->hashkey = HASH_KEY(data);
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
}
|
}
|
||||||
return loader;
|
return loader;
|
||||||
@@ -407,7 +408,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
|
|||||||
if (loader->open(data, size, copy)) {
|
if (loader->open(data, size, copy)) {
|
||||||
if (allowCache) {
|
if (allowCache) {
|
||||||
loader->hashkey = HASH_KEY(data);
|
loader->hashkey = HASH_KEY(data);
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
}
|
}
|
||||||
return loader;
|
return loader;
|
||||||
@@ -433,7 +434,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool
|
|||||||
if (loader->open(data, w, h, copy)) {
|
if (loader->open(data, w, h, copy)) {
|
||||||
if (!copy) {
|
if (!copy) {
|
||||||
loader->hashkey = HASH_KEY((const char*)data);
|
loader->hashkey = HASH_KEY((const char*)data);
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
}
|
}
|
||||||
return loader;
|
return loader;
|
||||||
@@ -455,7 +456,7 @@ LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size,
|
|||||||
if (loader->open(data, size, copy)) {
|
if (loader->open(data, size, copy)) {
|
||||||
loader->hashpath = strdup(name);
|
loader->hashpath = strdup(name);
|
||||||
loader->pathcache = true;
|
loader->pathcache = true;
|
||||||
ScopedLock lock(key);
|
ScopedLock lock(_key);
|
||||||
_activeLoaders.back(loader);
|
_activeLoaders.back(loader);
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|||||||
2
thirdparty/thorvg/src/renderer/tvgRender.h
vendored
2
thirdparty/thorvg/src/renderer/tvgRender.h
vendored
@@ -35,6 +35,8 @@ namespace tvg
|
|||||||
using RenderData = void*;
|
using RenderData = void*;
|
||||||
using pixel_t = uint32_t;
|
using pixel_t = uint32_t;
|
||||||
|
|
||||||
|
#define DASH_PATTERN_THRESHOLD 0.001f
|
||||||
|
|
||||||
enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255};
|
enum RenderUpdateFlag : uint8_t {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, Blend = 128, All = 255};
|
||||||
enum CompositionFlag : uint8_t {Invalid = 0, Opacity = 1, Blending = 2, Masking = 4, PostProcessing = 8}; //Composition Purpose
|
enum CompositionFlag : uint8_t {Invalid = 0, Opacity = 1, Blending = 2, Masking = 4, PostProcessing = 8}; //Composition Purpose
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ static TaskSchedulerImpl* inst = nullptr;
|
|||||||
|
|
||||||
#ifdef THORVG_THREAD_SUPPORT
|
#ifdef THORVG_THREAD_SUPPORT
|
||||||
|
|
||||||
static thread_local bool _async = true;
|
|
||||||
|
|
||||||
struct TaskQueue {
|
struct TaskQueue {
|
||||||
Inlist<Task> taskDeque;
|
Inlist<Task> taskDeque;
|
||||||
mutex mtx;
|
mutex mtx;
|
||||||
@@ -157,7 +155,7 @@ struct TaskSchedulerImpl
|
|||||||
void request(Task* task)
|
void request(Task* task)
|
||||||
{
|
{
|
||||||
//Async
|
//Async
|
||||||
if (threads.count > 0 && _async) {
|
if (threads.count > 0) {
|
||||||
task->prepare();
|
task->prepare();
|
||||||
auto i = idx++;
|
auto i = idx++;
|
||||||
for (uint32_t n = 0; n < threads.count; ++n) {
|
for (uint32_t n = 0; n < threads.count; ++n) {
|
||||||
@@ -178,8 +176,6 @@ struct TaskSchedulerImpl
|
|||||||
|
|
||||||
#else //THORVG_THREAD_SUPPORT
|
#else //THORVG_THREAD_SUPPORT
|
||||||
|
|
||||||
static bool _async = true;
|
|
||||||
|
|
||||||
struct TaskSchedulerImpl
|
struct TaskSchedulerImpl
|
||||||
{
|
{
|
||||||
TaskSchedulerImpl(TVG_UNUSED uint32_t threadCnt) {}
|
TaskSchedulerImpl(TVG_UNUSED uint32_t threadCnt) {}
|
||||||
@@ -220,10 +216,3 @@ uint32_t TaskScheduler::threads()
|
|||||||
if (inst) return inst->threadCnt();
|
if (inst) return inst->threadCnt();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TaskScheduler::async(bool on)
|
|
||||||
{
|
|
||||||
//toggle async tasking for each thread on/off
|
|
||||||
_async = on;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ struct TaskScheduler
|
|||||||
static void init(uint32_t threads);
|
static void init(uint32_t threads);
|
||||||
static void term();
|
static void term();
|
||||||
static void request(Task* task);
|
static void request(Task* task);
|
||||||
static void async(bool on);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|||||||
18
thirdparty/thorvg/src/renderer/tvgText.h
vendored
18
thirdparty/thorvg/src/renderer/tvgText.h
vendored
@@ -24,6 +24,7 @@
|
|||||||
#define _TVG_TEXT_H
|
#define _TVG_TEXT_H
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "tvgMath.h"
|
||||||
#include "tvgShape.h"
|
#include "tvgShape.h"
|
||||||
#include "tvgFill.h"
|
#include "tvgFill.h"
|
||||||
#include "tvgLoader.h"
|
#include "tvgLoader.h"
|
||||||
@@ -33,6 +34,7 @@ struct Text::Impl
|
|||||||
FontLoader* loader = nullptr;
|
FontLoader* loader = nullptr;
|
||||||
Text* paint;
|
Text* paint;
|
||||||
Shape* shape;
|
Shape* shape;
|
||||||
|
FontMetrics metrics;
|
||||||
char* utf8 = nullptr;
|
char* utf8 = nullptr;
|
||||||
float fontSize;
|
float fontSize;
|
||||||
bool italic = false;
|
bool italic = false;
|
||||||
@@ -40,6 +42,7 @@ struct Text::Impl
|
|||||||
|
|
||||||
Impl(Text* p) : paint(p), shape(Shape::gen().release())
|
Impl(Text* p) : paint(p), shape(Shape::gen().release())
|
||||||
{
|
{
|
||||||
|
shape->fill(FillRule::EvenOdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Impl()
|
~Impl()
|
||||||
@@ -94,27 +97,26 @@ struct Text::Impl
|
|||||||
return PP(shape)->render(renderer);
|
return PP(shape)->render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load()
|
float load()
|
||||||
{
|
{
|
||||||
if (!loader) return false;
|
if (!loader) return 0.0f;
|
||||||
|
|
||||||
loader->request(shape, utf8);
|
|
||||||
//reload
|
//reload
|
||||||
if (changed) {
|
if (changed) {
|
||||||
loader->read();
|
loader->read(shape, utf8, metrics);
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
return loader->transform(shape, fontSize, italic);
|
return loader->transform(shape, metrics, fontSize, italic);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
RenderData update(RenderMethod* renderer, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, TVG_UNUSED bool clipper)
|
||||||
{
|
{
|
||||||
if (!load()) return nullptr;
|
auto scale = 1.0f / load();
|
||||||
|
if (tvg::zero(scale)) return nullptr;
|
||||||
|
|
||||||
//transform the gradient coordinates based on the final scaled font.
|
//transform the gradient coordinates based on the final scaled font.
|
||||||
auto fill = P(shape)->rs.fill;
|
auto fill = P(shape)->rs.fill;
|
||||||
if (fill && P(shape)->rFlag & RenderUpdateFlag::Gradient) {
|
if (fill && P(shape)->rFlag & RenderUpdateFlag::Gradient) {
|
||||||
auto scale = 1.0f / loader->scale;
|
|
||||||
if (fill->type() == Type::LinearGradient) {
|
if (fill->type() == Type::LinearGradient) {
|
||||||
P(static_cast<LinearGradient*>(fill))->x1 *= scale;
|
P(static_cast<LinearGradient*>(fill))->x1 *= scale;
|
||||||
P(static_cast<LinearGradient*>(fill))->y1 *= scale;
|
P(static_cast<LinearGradient*>(fill))->y1 *= scale;
|
||||||
@@ -134,7 +136,7 @@ struct Text::Impl
|
|||||||
|
|
||||||
bool bounds(float* x, float* y, float* w, float* h, TVG_UNUSED bool stroking)
|
bool bounds(float* x, float* y, float* w, float* h, TVG_UNUSED bool stroking)
|
||||||
{
|
{
|
||||||
if (!load()) return false;
|
if (load() == 0.0f) return false;
|
||||||
PP(shape)->bounds(x, y, w, h, true, true, false);
|
PP(shape)->bounds(x, y, w, h, true, true, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
2
thirdparty/thorvg/update-thorvg.sh
vendored
2
thirdparty/thorvg/update-thorvg.sh
vendored
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
VERSION=0.15.11
|
VERSION=0.15.12
|
||||||
# Uncomment and set a git hash to use specific commit instead of tag.
|
# Uncomment and set a git hash to use specific commit instead of tag.
|
||||||
#GIT_COMMIT=
|
#GIT_COMMIT=
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user