Update thorvg to 0.8.4
This commit is contained in:
parent
dbf1a7277f
commit
cfed867da1
|
@ -686,7 +686,7 @@ instead of `miniz.h` as an external dependency.
|
|||
## thorvg
|
||||
|
||||
- Upstream: https://github.com/Samsung/thorvg
|
||||
- Version: 0.8.3 (a0fcf51f80a75f63a066df085f60cdaf715188b6, 2022)
|
||||
- Version: 0.8.4 (b0b7f207c6235691d694fc3f76e0b96e4858e606, 2023)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
@ -4,7 +4,7 @@ Junsu Choi <jsuya.choi@samsung.com>
|
|||
Pranay Samanta <pranay.ks@samsung.com>
|
||||
Mateusz Palkowski <m.palkowski@samsung.com>
|
||||
Subhransu Mohanty <sub.mohanty@samsung.com>
|
||||
Mira Grudzinska <m.grudzinska@samsung.com>
|
||||
Mira Grudzinska <veleveta@gmail.com>
|
||||
Michal Szczecinski <m.szczecinsk@partner.samsung.com>
|
||||
Shinwoo Kim <cinoo.kim@samsung.com>
|
||||
Piotr Kalota <p.kalota@samsung.com>
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
|
||||
#define THORVG_JPG_LOADER_SUPPORT 1
|
||||
|
||||
#define THORVG_VERSION_STRING "0.8.3"
|
||||
#define THORVG_VERSION_STRING "0.8.4"
|
||||
#endif
|
||||
|
|
|
@ -335,6 +335,20 @@ public:
|
|||
*/
|
||||
CompositeMethod composite(const Paint** target) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Gets the composition source object and the composition method.
|
||||
*
|
||||
* @param[out] source The paint of the composition source object.
|
||||
* @param[out] method The method used to composite the source object with the target.
|
||||
*
|
||||
* @return Result::Success when the paint object used as a composition target, Result::InsufficientCondition otherwise.
|
||||
*
|
||||
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
||||
*
|
||||
* @BETA_API
|
||||
*/
|
||||
Result composite(const Paint** source, CompositeMethod* method) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the unique id value of the paint instance.
|
||||
*
|
||||
|
|
|
@ -76,7 +76,9 @@ struct SwShapeTask : SwTask
|
|||
|
||||
void run(unsigned tid) override
|
||||
{
|
||||
if (opacity == 0) return; //Invisible
|
||||
auto compMethod = CompositeMethod::None;
|
||||
auto usedAsClip = (sdata->composite(nullptr, &compMethod) == Result::Success) && (compMethod == CompositeMethod::ClipPath);
|
||||
if (opacity == 0 && !usedAsClip) return; //Invisible
|
||||
|
||||
uint8_t strokeAlpha = 0;
|
||||
auto visibleStroke = false;
|
||||
|
@ -98,7 +100,7 @@ struct SwShapeTask : SwTask
|
|||
sdata->fillColor(nullptr, nullptr, nullptr, &alpha);
|
||||
alpha = static_cast<uint8_t>(static_cast<uint32_t>(alpha) * opacity / 255);
|
||||
visibleFill = (alpha > 0 || sdata->fill());
|
||||
if (visibleFill || visibleStroke) {
|
||||
if (visibleFill || visibleStroke || usedAsClip) {
|
||||
shapeReset(&shape);
|
||||
if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err;
|
||||
}
|
||||
|
@ -110,7 +112,7 @@ struct SwShapeTask : SwTask
|
|||
|
||||
//Fill
|
||||
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
|
||||
if (visibleFill) {
|
||||
if (visibleFill || usedAsClip) {
|
||||
/* We assume that if stroke width is bigger than 2,
|
||||
shape outline below stroke could be full covered by stroke drawing.
|
||||
Thus it turns off antialising in that condition.
|
||||
|
@ -291,7 +293,7 @@ bool SwRenderer::viewport(const RenderRegion& vp)
|
|||
}
|
||||
|
||||
|
||||
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs)
|
||||
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace)
|
||||
{
|
||||
if (!buffer || stride == 0 || w == 0 || h == 0 || w > stride) return false;
|
||||
|
||||
|
@ -301,7 +303,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
surface->stride = stride;
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->cs = cs;
|
||||
surface->cs = colorSpace;
|
||||
|
||||
vport.x = vport.y = 0;
|
||||
vport.w = surface->w;
|
||||
|
@ -644,6 +646,13 @@ SwRenderer::SwRenderer():mpool(globalMpool)
|
|||
}
|
||||
|
||||
|
||||
uint32_t SwRenderer::colorSpace()
|
||||
{
|
||||
if (surface) return surface->cs;
|
||||
return tvg::SwCanvas::ARGB8888;
|
||||
}
|
||||
|
||||
|
||||
bool SwRenderer::init(uint32_t threads)
|
||||
{
|
||||
if ((initEngineCnt++) > 0) return true;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
bool clear() override;
|
||||
bool sync() override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t colorSpace);
|
||||
bool mempool(bool shared);
|
||||
|
||||
Compositor* target(const RenderRegion& region) override;
|
||||
|
@ -56,6 +56,8 @@ public:
|
|||
bool endComposite(Compositor* cmp) override;
|
||||
void clearCompositors();
|
||||
|
||||
uint32_t colorSpace() override;
|
||||
|
||||
static SwRenderer* gen();
|
||||
static bool init(uint32_t threads);
|
||||
static int32_t init();
|
||||
|
|
|
@ -72,7 +72,7 @@ Accessor::~Accessor()
|
|||
}
|
||||
|
||||
|
||||
Accessor::Accessor()
|
||||
Accessor::Accessor() : pImpl(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
float vw = 0;
|
||||
float vh = 0;
|
||||
float w = 0, h = 0; //default image size
|
||||
uint32_t colorSpace = SwCanvas::ARGB8888;
|
||||
|
||||
virtual ~LoadModule() {}
|
||||
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
|
||||
virtual bool read() = 0;
|
||||
virtual bool close() = 0;
|
||||
virtual unique_ptr<Surface> bitmap() { return nullptr; }
|
||||
virtual unique_ptr<Surface> bitmap(uint32_t colorSpace) { return nullptr; }
|
||||
virtual unique_ptr<Paint> paint() { return nullptr; }
|
||||
};
|
||||
|
||||
|
|
|
@ -53,6 +53,12 @@ static inline bool mathRightAngle(const Matrix* m)
|
|||
}
|
||||
|
||||
|
||||
static inline bool mathSkewed(const Matrix* m)
|
||||
{
|
||||
return (fabsf(m->e21 + m->e12) > FLT_EPSILON);
|
||||
}
|
||||
|
||||
|
||||
static inline bool mathIdentity(const Matrix* m)
|
||||
{
|
||||
if (!mathEqual(m->e11, 1.0f) || !mathZero(m->e12) || !mathZero(m->e13) ||
|
||||
|
|
|
@ -38,9 +38,9 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
|
|||
|
||||
if (rTransform) rTransform->update();
|
||||
|
||||
//No rotational.
|
||||
if (pTransform && !mathRightAngle(&pTransform->m)) return false;
|
||||
if (rTransform && !mathRightAngle(&rTransform->m)) return false;
|
||||
//No rotation and no skewing
|
||||
if (pTransform && (!mathRightAngle(&pTransform->m) || mathSkewed(&pTransform->m))) return false;
|
||||
if (rTransform && (!mathRightAngle(&rTransform->m) || mathSkewed(&rTransform->m))) return false;
|
||||
|
||||
//Perpendicular Rectangle?
|
||||
auto pt1 = pts + 0;
|
||||
|
@ -384,6 +384,19 @@ CompositeMethod Paint::composite(const Paint** target) const noexcept
|
|||
}
|
||||
|
||||
|
||||
Result Paint::composite(const Paint** source, CompositeMethod* method) const noexcept
|
||||
{
|
||||
if (source) *source = pImpl->compSource;
|
||||
auto met = (pImpl->compSource && pImpl->compSource->pImpl->compData ?
|
||||
pImpl->compSource->pImpl->compData->method : CompositeMethod::None);
|
||||
if (method) *method = met;
|
||||
|
||||
if (pImpl->compSource != nullptr && met != CompositeMethod::None)
|
||||
return Result::Success;
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
|
||||
Result Paint::opacity(uint8_t o) noexcept
|
||||
{
|
||||
if (pImpl->opacity == o) return Result::Success;
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace tvg
|
|||
StrategyMethod* smethod = nullptr;
|
||||
RenderTransform* rTransform = nullptr;
|
||||
Composite* compData = nullptr;
|
||||
Paint* compSource = nullptr;
|
||||
uint32_t renderFlag = RenderUpdateFlag::None;
|
||||
uint32_t ctxFlag = ContextFlag::Invalid;
|
||||
uint32_t id;
|
||||
|
@ -136,6 +137,7 @@ namespace tvg
|
|||
if (!target && method == CompositeMethod::None) return true;
|
||||
compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
|
||||
}
|
||||
target->pImpl->compSource = source;
|
||||
compData->target = target;
|
||||
compData->source = source;
|
||||
compData->method = method;
|
||||
|
|
|
@ -66,6 +66,7 @@ struct Picture::Impl
|
|||
void* rdata = nullptr; //engine data
|
||||
float w = 0, h = 0;
|
||||
bool resizing = false;
|
||||
uint32_t rendererColorSpace = 0;
|
||||
|
||||
~Impl()
|
||||
{
|
||||
|
@ -100,7 +101,7 @@ struct Picture::Impl
|
|||
}
|
||||
}
|
||||
free(surface);
|
||||
if ((surface = loader->bitmap().release())) {
|
||||
if ((surface = loader->bitmap(rendererColorSpace).release())) {
|
||||
loader->close();
|
||||
return RenderUpdateFlag::Image;
|
||||
}
|
||||
|
@ -124,6 +125,7 @@ struct Picture::Impl
|
|||
|
||||
void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
|
||||
{
|
||||
rendererColorSpace = renderer.colorSpace();
|
||||
auto flag = reload();
|
||||
|
||||
if (surface) {
|
||||
|
|
|
@ -106,6 +106,8 @@ public:
|
|||
virtual Compositor* target(const RenderRegion& region) = 0;
|
||||
virtual bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) = 0;
|
||||
virtual bool endComposite(Compositor* cmp) = 0;
|
||||
|
||||
virtual uint32_t colorSpace() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
Scene::Scene() : pImpl(new Impl())
|
||||
Scene::Scene() : pImpl(new Impl(this))
|
||||
{
|
||||
Paint::pImpl->id = TVG_CLASS_ID_SCENE;
|
||||
Paint::pImpl->method(new PaintMethod<Scene::Impl>(pImpl));
|
||||
|
|
|
@ -60,6 +60,11 @@ struct Scene::Impl
|
|||
Array<Paint*> paints;
|
||||
uint8_t opacity; //for composition
|
||||
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
||||
Scene* scene = nullptr;
|
||||
|
||||
Impl(Scene* s) : scene(s)
|
||||
{
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
|
@ -81,8 +86,14 @@ struct Scene::Impl
|
|||
|
||||
bool needComposition(uint32_t opacity)
|
||||
{
|
||||
if (opacity == 0 || paints.count == 0) return false;
|
||||
|
||||
//Masking may require composition (even if opacity == 255)
|
||||
auto compMethod = scene->composite(nullptr);
|
||||
if (compMethod != CompositeMethod::None && compMethod != CompositeMethod::ClipPath) return true;
|
||||
|
||||
//Half translucent requires intermediate composition.
|
||||
if (opacity == 255 || opacity == 0) return false;
|
||||
if (opacity == 255) return false;
|
||||
|
||||
//If scene has several children or only scene, it may require composition.
|
||||
if (paints.count > 1) return true;
|
||||
|
|
|
@ -42,6 +42,24 @@ static void _premultiply(uint32_t* data, uint32_t w, uint32_t h)
|
|||
}
|
||||
|
||||
|
||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
||||
{
|
||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
||||
}
|
||||
|
||||
|
||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
||||
{
|
||||
auto buffer = data;
|
||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
||||
auto src = buffer;
|
||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
||||
*src = CHANGE_COLORSPACE(*src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PngLoader::PngLoader()
|
||||
{
|
||||
image = static_cast<png_imagep>(calloc(1, sizeof(png_image)));
|
||||
|
@ -110,16 +128,21 @@ bool PngLoader::close()
|
|||
return true;
|
||||
}
|
||||
|
||||
unique_ptr<Surface> PngLoader::bitmap()
|
||||
unique_ptr<Surface> PngLoader::bitmap(uint32_t colorSpace)
|
||||
{
|
||||
if (!content) return nullptr;
|
||||
if (this->colorSpace != colorSpace) {
|
||||
this->colorSpace = colorSpace;
|
||||
_changeColorSpace(content, w, h);
|
||||
}
|
||||
|
||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
||||
surface->buffer = (uint32_t*)(content);
|
||||
surface->buffer = content;
|
||||
surface->stride = w;
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->cs = SwCanvas::ARGB8888;
|
||||
surface->cs = colorSpace;
|
||||
|
||||
return unique_ptr<Surface>(surface);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
bool read() override;
|
||||
bool close() override;
|
||||
|
||||
unique_ptr<Surface> bitmap() override;
|
||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
||||
|
||||
private:
|
||||
png_imagep image = nullptr;
|
||||
const uint32_t* content = nullptr;
|
||||
uint32_t* content = nullptr;
|
||||
};
|
||||
|
||||
#endif //_TVG_PNG_LOADER_H_
|
||||
|
|
|
@ -28,6 +28,24 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
||||
{
|
||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
||||
}
|
||||
|
||||
|
||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
||||
{
|
||||
auto buffer = data;
|
||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
||||
auto src = buffer;
|
||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
||||
*src = CHANGE_COLORSPACE(*src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JpgLoader::clear()
|
||||
{
|
||||
jpgdDelete(decoder);
|
||||
|
@ -110,18 +128,22 @@ bool JpgLoader::close()
|
|||
}
|
||||
|
||||
|
||||
unique_ptr<Surface> JpgLoader::bitmap()
|
||||
unique_ptr<Surface> JpgLoader::bitmap(uint32_t colorSpace)
|
||||
{
|
||||
this->done();
|
||||
|
||||
if (!image) return nullptr;
|
||||
if (this->colorSpace != colorSpace) {
|
||||
this->colorSpace = colorSpace;
|
||||
_changeColorSpace(reinterpret_cast<uint32_t*>(image), w, h);
|
||||
}
|
||||
|
||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
||||
surface->buffer = (uint32_t*)(image);
|
||||
surface->buffer = reinterpret_cast<uint32_t*>(image);
|
||||
surface->stride = static_cast<uint32_t>(w);
|
||||
surface->w = static_cast<uint32_t>(w);
|
||||
surface->h = static_cast<uint32_t>(h);
|
||||
surface->cs = SwCanvas::ARGB8888;
|
||||
surface->cs = colorSpace;
|
||||
|
||||
return unique_ptr<Surface>(surface);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
bool read() override;
|
||||
bool close() override;
|
||||
|
||||
unique_ptr<Surface> bitmap() override;
|
||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
||||
void run(unsigned tid) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,23 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static inline uint32_t CHANGE_COLORSPACE(uint32_t c)
|
||||
{
|
||||
return (c & 0xff000000) + ((c & 0x00ff0000)>>16) + (c & 0x0000ff00) + ((c & 0x000000ff)<<16);
|
||||
}
|
||||
|
||||
|
||||
static void _changeColorSpace(uint32_t* data, uint32_t w, uint32_t h)
|
||||
{
|
||||
auto buffer = data;
|
||||
for (uint32_t y = 0; y < h; ++y, buffer += w) {
|
||||
auto src = buffer;
|
||||
for (uint32_t x = 0; x < w; ++x, ++src) {
|
||||
*src = CHANGE_COLORSPACE(*src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
@ -54,7 +71,7 @@ bool RawLoader::open(const uint32_t* data, uint32_t w, uint32_t h, bool copy)
|
|||
if (!content) return false;
|
||||
memcpy((void*)content, data, sizeof(uint32_t) * w * h);
|
||||
}
|
||||
else content = data;
|
||||
else content = const_cast<uint32_t*>(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -72,16 +89,20 @@ bool RawLoader::close()
|
|||
}
|
||||
|
||||
|
||||
unique_ptr<Surface> RawLoader::bitmap()
|
||||
unique_ptr<Surface> RawLoader::bitmap(uint32_t colorSpace)
|
||||
{
|
||||
if (!content) return nullptr;
|
||||
if (this->colorSpace != colorSpace) {
|
||||
this->colorSpace = colorSpace;
|
||||
_changeColorSpace(content, w, h);
|
||||
}
|
||||
|
||||
auto surface = static_cast<Surface*>(malloc(sizeof(Surface)));
|
||||
surface->buffer = (uint32_t*)(content);
|
||||
surface->stride = (uint32_t)w;
|
||||
surface->w = (uint32_t)w;
|
||||
surface->h = (uint32_t)h;
|
||||
surface->cs = SwCanvas::ARGB8888;
|
||||
surface->buffer = content;
|
||||
surface->stride = static_cast<uint32_t>(w);
|
||||
surface->w = static_cast<uint32_t>(w);
|
||||
surface->h = static_cast<uint32_t>(h);
|
||||
surface->cs = colorSpace;
|
||||
|
||||
return unique_ptr<Surface>(surface);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
class RawLoader : public LoadModule
|
||||
{
|
||||
public:
|
||||
const uint32_t* content = nullptr;
|
||||
uint32_t* content = nullptr;
|
||||
bool copy = false;
|
||||
|
||||
~RawLoader();
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
bool read() override;
|
||||
bool close() override;
|
||||
|
||||
unique_ptr<Surface> bitmap() override;
|
||||
unique_ptr<Surface> bitmap(uint32_t colorSpace) override;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -180,9 +180,9 @@ static float _toFloat(const SvgParser* svgParse, const char* str, SvgParserLengt
|
|||
else if (type == SvgParserLengthType::Horizontal) parsedValue = (parsedValue / 100.0) * svgParse->global.w;
|
||||
else //if other then it's radius
|
||||
{
|
||||
float max = (float)svgParse->global.w;
|
||||
float max = svgParse->global.w;
|
||||
if (max < svgParse->global.h)
|
||||
max = (float)svgParse->global.h;
|
||||
max = svgParse->global.h;
|
||||
parsedValue = (parsedValue / 100.0) * max;
|
||||
}
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ static void _parseDashArray(SvgLoaderData* loader, const char *str, SvgDash* das
|
|||
++end;
|
||||
//Refers to the diagonal length of the viewport.
|
||||
//https://www.w3.org/TR/SVG2/coords.html#Units
|
||||
parsedValue = (sqrtf(pow(loader->svgParse->global.w, 2) + pow(loader->svgParse->global.h, 2)) / sqrtf(2.0f)) * (parsedValue / 100.0f);
|
||||
parsedValue = (sqrtf(powf(loader->svgParse->global.w, 2) + powf(loader->svgParse->global.h, 2)) / sqrtf(2.0f)) * (parsedValue / 100.0f);
|
||||
}
|
||||
(*dash).array.push(parsedValue);
|
||||
str = end;
|
||||
|
@ -376,7 +376,7 @@ static char* _idFromUrl(const char* url)
|
|||
}
|
||||
|
||||
|
||||
static unsigned char _parserColor(const char* value, char** end)
|
||||
static unsigned char _parseColor(const char* value, char** end)
|
||||
{
|
||||
float r;
|
||||
|
||||
|
@ -586,11 +586,11 @@ static void _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
|
|||
*b = strtol(tmp, nullptr, 16);
|
||||
}
|
||||
} else if (len >= 10 && (str[0] == 'r' || str[0] == 'R') && (str[1] == 'g' || str[1] == 'G') && (str[2] == 'b' || str[2] == 'B') && str[3] == '(' && str[len - 1] == ')') {
|
||||
tr = _parserColor(str + 4, &red);
|
||||
tr = _parseColor(str + 4, &red);
|
||||
if (red && *red == ',') {
|
||||
tg = _parserColor(red + 1, &green);
|
||||
tg = _parseColor(red + 1, &green);
|
||||
if (green && *green == ',') {
|
||||
tb = _parserColor(green + 1, &blue);
|
||||
tb = _parseColor(green + 1, &blue);
|
||||
if (blue && blue[0] == ')' && blue[1] == '\0') {
|
||||
*r = tr;
|
||||
*g = tg;
|
||||
|
@ -840,13 +840,13 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
|
|||
if (_parseNumber(&value, &doc->vy)) {
|
||||
if (_parseNumber(&value, &doc->vw)) {
|
||||
_parseNumber(&value, &doc->vh);
|
||||
loader->svgParse->global.h = (uint32_t)doc->vh;
|
||||
loader->svgParse->global.h = doc->vh;
|
||||
}
|
||||
loader->svgParse->global.w = (uint32_t)doc->vw;
|
||||
loader->svgParse->global.w = doc->vw;
|
||||
}
|
||||
loader->svgParse->global.y = (int)doc->vy;
|
||||
loader->svgParse->global.y = doc->vy;
|
||||
}
|
||||
loader->svgParse->global.x = (int)doc->vx;
|
||||
loader->svgParse->global.x = doc->vx;
|
||||
} else if (!strcmp(key, "preserveAspectRatio")) {
|
||||
_parseAspectRatio(&value, &doc->align, &doc->meetOrSlice);
|
||||
} else if (!strcmp(key, "style")) {
|
||||
|
@ -1300,11 +1300,11 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
|
|||
|
||||
if (loader->svgParse->global.w == 0) {
|
||||
if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1;
|
||||
else loader->svgParse->global.w = (uint32_t)doc->w;
|
||||
else loader->svgParse->global.w = doc->w;
|
||||
}
|
||||
if (loader->svgParse->global.h == 0) {
|
||||
if (doc->h < FLT_EPSILON) loader->svgParse->global.h = 1;
|
||||
else loader->svgParse->global.h = (uint32_t)doc->h;
|
||||
else loader->svgParse->global.h = doc->h;
|
||||
}
|
||||
|
||||
return loader->svgParse->node;
|
||||
|
@ -2375,7 +2375,7 @@ static void _recalcRadialFyAttr(SvgLoaderData* loader, SvgRadialGradient* radial
|
|||
static void _recalcRadialRAttr(SvgLoaderData* loader, SvgRadialGradient* radial, bool userSpace)
|
||||
{
|
||||
// scaling factor based on the Units paragraph from : https://www.w3.org/TR/2015/WD-SVG2-20150915/coords.html
|
||||
if (userSpace && !radial->isRPercentage) radial->r = radial->r / (sqrtf(pow(loader->svgParse->global.h, 2) + pow(loader->svgParse->global.w, 2)) / sqrtf(2.0));
|
||||
if (userSpace && !radial->isRPercentage) radial->r = radial->r / (sqrtf(powf(loader->svgParse->global.h, 2) + powf(loader->svgParse->global.w, 2)) / sqrtf(2.0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -3180,6 +3180,12 @@ SvgLoader::~SvgLoader()
|
|||
|
||||
void SvgLoader::run(unsigned tid)
|
||||
{
|
||||
//According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering
|
||||
if (renderingDisabled) {
|
||||
root = Scene::gen();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return;
|
||||
|
||||
if (loaderData.doc) {
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
private:
|
||||
AspectRatioAlign align = AspectRatioAlign::XMidYMid;
|
||||
AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet;
|
||||
bool renderingDisabled = false;
|
||||
|
||||
bool header();
|
||||
void clear();
|
||||
|
|
|
@ -425,8 +425,7 @@ struct SvgParser
|
|||
SvgStopStyleFlags flags;
|
||||
struct
|
||||
{
|
||||
int x, y;
|
||||
uint32_t w, h;
|
||||
float x, y, w, h;
|
||||
} global;
|
||||
struct
|
||||
{
|
||||
|
|
|
@ -255,7 +255,6 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
|
|||
node->style->clipPath.applying = true;
|
||||
|
||||
auto comp = Shape::gen();
|
||||
comp->fill(255, 255, 255, 255);
|
||||
if (node->transform) comp->transform(*node->transform);
|
||||
|
||||
auto child = compNode->child.data;
|
||||
|
@ -348,7 +347,7 @@ static void _applyProperty(SvgNode* node, Shape* vg, const Box& vBox, const stri
|
|||
|
||||
//If stroke property is nullptr then do nothing
|
||||
if (style->stroke.paint.none) {
|
||||
//Do nothing
|
||||
vg->stroke(0.0f);
|
||||
} else if (style->stroke.paint.gradient) {
|
||||
Box bBox = vBox;
|
||||
if (!style->stroke.paint.gradient->userSpace) bBox = _boundingBox(vg);
|
||||
|
|
|
@ -137,7 +137,11 @@ float svgUtilStrtof(const char *nPtr, char **endPtr)
|
|||
pow10 *= 10ULL;
|
||||
}
|
||||
}
|
||||
} else if (isspace(*iter)) { //skip if there is a space after the dot.
|
||||
a = iter;
|
||||
goto success;
|
||||
}
|
||||
|
||||
val += static_cast<float>(decimalPart) / static_cast<float>(pow10);
|
||||
a = iter;
|
||||
}
|
||||
|
|
|
@ -304,38 +304,38 @@ bool isIgnoreUnsupportedLogElements(TVG_UNUSED const char* tagName)
|
|||
bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data)
|
||||
{
|
||||
const char *itr = buf, *itrEnd = buf + bufLength;
|
||||
char* tmpBuf = (char*)alloca(bufLength + 1);
|
||||
char* tmpBuf = (char*)malloc(bufLength + 1);
|
||||
|
||||
if (!buf || !func) return false;
|
||||
if (!buf || !func || !tmpBuf) goto error;
|
||||
|
||||
while (itr < itrEnd) {
|
||||
const char* p = _skipWhiteSpacesAndXmlEntities(itr, itrEnd);
|
||||
const char *key, *keyEnd, *value, *valueEnd;
|
||||
char* tval;
|
||||
|
||||
if (p == itrEnd) return true;
|
||||
if (p == itrEnd) goto success;
|
||||
|
||||
key = p;
|
||||
for (keyEnd = key; keyEnd < itrEnd; keyEnd++) {
|
||||
if ((*keyEnd == '=') || (isspace((unsigned char)*keyEnd))) break;
|
||||
}
|
||||
if (keyEnd == itrEnd) return false;
|
||||
if (keyEnd == itrEnd) goto error;
|
||||
if (keyEnd == key) continue;
|
||||
|
||||
if (*keyEnd == '=') value = keyEnd + 1;
|
||||
else {
|
||||
value = (const char*)memchr(keyEnd, '=', itrEnd - keyEnd);
|
||||
if (!value) return false;
|
||||
if (!value) goto error;
|
||||
value++;
|
||||
}
|
||||
keyEnd = _simpleXmlUnskipXmlEntities(keyEnd, key);
|
||||
|
||||
value = _skipWhiteSpacesAndXmlEntities(value, itrEnd);
|
||||
if (value == itrEnd) return false;
|
||||
if (value == itrEnd) goto error;
|
||||
|
||||
if ((*value == '"') || (*value == '\'')) {
|
||||
valueEnd = (const char*)memchr(value + 1, *value, itrEnd - value);
|
||||
if (!valueEnd) return false;
|
||||
if (!valueEnd) goto error;
|
||||
value++;
|
||||
} else {
|
||||
valueEnd = _simpleXmlFindWhiteSpace(value, itrEnd);
|
||||
|
@ -364,7 +364,14 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
success:
|
||||
free(tmpBuf);
|
||||
return true;
|
||||
|
||||
error:
|
||||
free(tmpBuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
VERSION=0.8.3
|
||||
VERSION=0.8.4
|
||||
rm -rf AUTHORS inc LICENSE src *.zip
|
||||
curl -L -O https://github.com/Samsung/thorvg/archive/v$VERSION.zip
|
||||
curl -L -O https://github.com/thorvg/thorvg/archive/v$VERSION.zip
|
||||
bsdtar --strip-components=1 -xvf *.zip
|
||||
rm *.zip
|
||||
rm -rf .github docs pc res test tools tvgcompat .git* *.md *.txt wasm_build.sh
|
||||
|
|
Loading…
Reference in New Issue