thorvg: Update to 0.14.10
More fixes to rendering of SVG files with broken text tags.
Also backports upstream patch to fix #97078.
(cherry picked from commit 0c0336f704
)
This commit is contained in:
parent
99a8821a71
commit
f273c7c773
|
@ -882,7 +882,7 @@ instead of `miniz.h` as an external dependency.
|
||||||
## thorvg
|
## thorvg
|
||||||
|
|
||||||
- Upstream: https://github.com/thorvg/thorvg
|
- Upstream: https://github.com/thorvg/thorvg
|
||||||
- Version: 0.14.9 (81a0fbfd590873b21e53c3af77969c71d3d9b586, 2024)
|
- Version: 0.14.10 (366dcd72850c360b49e841e568fc5a154d7cce9e, 2024)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
// For internal debugging:
|
// For internal debugging:
|
||||||
//#define THORVG_LOG_ENABLED
|
//#define THORVG_LOG_ENABLED
|
||||||
|
|
||||||
#define THORVG_VERSION_STRING "0.14.9"
|
#define THORVG_VERSION_STRING "0.14.10"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
From 41d67213607e7ff20b7a3ca833f1cfde9780da65 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hermet Park <hermet@lottiefiles.com>
|
|
||||||
Date: Sat, 7 Sep 2024 01:35:09 +0900
|
|
||||||
Subject: [PATCH] renderer: ++reliability in text drawing
|
|
||||||
|
|
||||||
Allow the canvas to pass through
|
|
||||||
even if text elements are not properly supported.
|
|
||||||
|
|
||||||
issue: https://github.com/thorvg/thorvg/issues/2715
|
|
||||||
---
|
|
||||||
src/renderer/tvgText.h | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/thirdparty/thorvg/src/renderer/tvgText.h b/thirdparty/thorvg/src/renderer/tvgText.h
|
|
||||||
index 746b85bea6..55d33ffd4b 100644
|
|
||||||
--- a/thirdparty/thorvg/src/renderer/tvgText.h
|
|
||||||
+++ b/thirdparty/thorvg/src/renderer/tvgText.h
|
|
||||||
@@ -89,6 +89,7 @@ struct Text::Impl
|
|
||||||
|
|
||||||
bool render(RenderMethod* renderer)
|
|
||||||
{
|
|
||||||
+ if (!loader) return true;
|
|
||||||
renderer->blend(paint->blend(), true);
|
|
||||||
return PP(shape)->render(renderer);
|
|
||||||
}
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
From 8009c75465e5b35da2d5f53532bc65f6df202a3a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hermet Park <hermet@lottiefiles.com>
|
||||||
|
Date: Tue, 17 Sep 2024 11:35:48 +0900
|
||||||
|
Subject: [PATCH] renderer: hotfix a crash
|
||||||
|
|
||||||
|
prevent a nullptr memory access
|
||||||
|
regression by f5337015e971d24379d2ee664895503ab8945e13
|
||||||
|
|
||||||
|
issue: https://github.com/godotengine/godot/issues/97078
|
||||||
|
---
|
||||||
|
src/renderer/tvgShape.h | 6 ++++--
|
||||||
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h
|
||||||
|
index 221931dee..e120a85c6 100644
|
||||||
|
--- a/src/renderer/tvgShape.h
|
||||||
|
+++ b/src/renderer/tvgShape.h
|
||||||
|
@@ -51,8 +51,9 @@ struct Shape::Impl
|
||||||
|
|
||||||
|
bool render(RenderMethod* renderer)
|
||||||
|
{
|
||||||
|
+ if (!rd) return false;
|
||||||
|
+
|
||||||
|
Compositor* cmp = nullptr;
|
||||||
|
- bool ret;
|
||||||
|
|
||||||
|
renderer->blend(shape->blend());
|
||||||
|
|
||||||
|
@@ -61,7 +62,7 @@ struct Shape::Impl
|
||||||
|
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = renderer->renderShape(rd);
|
||||||
|
+ auto ret = renderer->renderShape(rd);
|
||||||
|
if (cmp) renderer->endComposite(cmp);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -117,6 +118,7 @@ struct Shape::Impl
|
||||||
|
|
||||||
|
RenderRegion bounds(RenderMethod* renderer)
|
||||||
|
{
|
||||||
|
+ if (!rd) return {0, 0, 0, 0};
|
||||||
|
return renderer->region(rd);
|
||||||
|
}
|
||||||
|
|
|
@ -229,6 +229,14 @@ char* strDuplicate(const char *str, size_t n)
|
||||||
return (char *) memcpy(ret, str, n);
|
return (char *) memcpy(ret, str, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* strAppend(char* lhs, const char* rhs, size_t n)
|
||||||
|
{
|
||||||
|
if (!rhs) return lhs;
|
||||||
|
if (!lhs) return strDuplicate(rhs, n);
|
||||||
|
lhs = (char*)realloc(lhs, strlen(lhs) + n + 1);
|
||||||
|
return strncat(lhs, rhs, n);
|
||||||
|
}
|
||||||
|
|
||||||
char* strDirname(const char* path)
|
char* strDirname(const char* path)
|
||||||
{
|
{
|
||||||
const char *ptr = strrchr(path, '/');
|
const char *ptr = strrchr(path, '/');
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace tvg
|
||||||
float strToFloat(const char *nPtr, char **endPtr); //convert to float
|
float strToFloat(const char *nPtr, char **endPtr); //convert to float
|
||||||
int str2int(const char* str, size_t n); //convert to integer
|
int str2int(const char* str, size_t n); //convert to integer
|
||||||
char* strDuplicate(const char *str, size_t n); //copy the string
|
char* strDuplicate(const char *str, size_t n); //copy the string
|
||||||
|
char* strAppend(char* lhs, const char* rhs, size_t n); //append the rhs to the lhs
|
||||||
char* strDirname(const char* path); //return the full directory name
|
char* strDirname(const char* path); //return the full directory name
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2183,6 +2183,7 @@ static SvgNode* _createTextNode(SvgLoaderData* loader, SvgNode* parent, const ch
|
||||||
//TODO: support the def font and size as used in a system?
|
//TODO: support the def font and size as used in a system?
|
||||||
loader->svgParse->node->node.text.fontSize = 10.0f;
|
loader->svgParse->node->node.text.fontSize = 10.0f;
|
||||||
loader->svgParse->node->node.text.fontFamily = nullptr;
|
loader->svgParse->node->node.text.fontFamily = nullptr;
|
||||||
|
loader->svgParse->node->node.text.text = nullptr;
|
||||||
|
|
||||||
func(buf, bufLength, _attrParseTextNode, loader);
|
func(buf, bufLength, _attrParseTextNode, loader);
|
||||||
|
|
||||||
|
@ -3400,8 +3401,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
|
||||||
static void _svgLoaderParserText(SvgLoaderData* loader, const char* content, unsigned int length)
|
static void _svgLoaderParserText(SvgLoaderData* loader, const char* content, unsigned int length)
|
||||||
{
|
{
|
||||||
auto text = &loader->svgParse->node->node.text;
|
auto text = &loader->svgParse->node->node.text;
|
||||||
if (text->text) free(text->text);
|
text->text = strAppend(text->text, content, length);
|
||||||
text->text = strDuplicate(content, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,7 @@ static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNU
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: BlendMethod could remove the alpha parameter.
|
//TODO: BlendMethod could remove the alpha parameter.
|
||||||
static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, uint8_t a)
|
static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
|
||||||
{
|
{
|
||||||
//if (s > d) => s - d
|
//if (s > d) => s - d
|
||||||
//else => d - s
|
//else => d - s
|
||||||
|
@ -404,7 +404,7 @@ static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t
|
||||||
return JOIN(255, c1, c2, c3);
|
return JOIN(255, c1, c2, c3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a)
|
static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
|
||||||
{
|
{
|
||||||
// s * d
|
// s * d
|
||||||
auto c1 = MULTIPLY(C1(s), C1(d));
|
auto c1 = MULTIPLY(C1(s), C1(d));
|
||||||
|
@ -413,11 +413,6 @@ static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a)
|
||||||
return JOIN(255, c1, c2, c3);
|
return JOIN(255, c1, c2, c3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, uint8_t a)
|
|
||||||
{
|
|
||||||
return opBlendDirectMultiply(s, d, a) + ALPHA_BLEND(d, IA(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
|
static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
|
||||||
{
|
{
|
||||||
// if (2 * d < da) => 2 * s * d,
|
// if (2 * d < da) => 2 * s * d,
|
||||||
|
@ -570,7 +565,7 @@ bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8
|
||||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity);
|
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity);
|
||||||
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
|
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
|
||||||
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val = 0);
|
||||||
void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len);
|
||||||
void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len);
|
void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len);
|
||||||
void rasterUnpremultiply(Surface* surface);
|
void rasterUnpremultiply(Surface* surface);
|
||||||
|
|
|
@ -423,12 +423,11 @@ static bool _rasterBlendingRect(SwSurface* surface, const SwBBox& region, uint8_
|
||||||
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 color = surface->join(r, g, b, a);
|
auto color = surface->join(r, g, b, a);
|
||||||
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto ialpha = 255 - a;
|
|
||||||
|
|
||||||
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];
|
||||||
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||||
*dst = surface->blender(color, *dst, ialpha);
|
*dst = surface->blender(color, *dst, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -595,17 +594,16 @@ static bool _rasterBlendingRle(SwSurface* surface, const SwRleData* rle, uint8_t
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
auto color = surface->join(r, g, b, a);
|
auto color = surface->join(r, g, b, a);
|
||||||
auto ialpha = 255 - a;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
*dst = surface->blender(color, *dst, ialpha);
|
*dst = surface->blender(color, *dst, 255);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
auto tmp = surface->blender(color, *dst, ialpha);
|
auto tmp = surface->blender(color, *dst, 255);
|
||||||
*dst = INTERPOLATE(tmp, *dst, span->coverage);
|
*dst = INTERPOLATE(tmp, *dst, span->coverage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,9 +811,8 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima
|
||||||
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
|
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
|
||||||
SCALED_IMAGE_RANGE_X
|
SCALED_IMAGE_RANGE_X
|
||||||
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
|
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
|
||||||
if (opacity < 255) src = ALPHA_BLEND(src, opacity);
|
|
||||||
auto tmp = surface->blender(src, *dst, 255);
|
auto tmp = surface->blender(src, *dst, 255);
|
||||||
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
|
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(alpha, A(src)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,18 +978,12 @@ static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* ima
|
||||||
auto alpha = MULTIPLY(span->coverage, opacity);
|
auto alpha = MULTIPLY(span->coverage, opacity);
|
||||||
if (alpha == 255) {
|
if (alpha == 255) {
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
|
||||||
*dst = surface->blender(*img, *dst, IA(*img));
|
*dst = surface->blender(*img, *dst, 255);
|
||||||
}
|
|
||||||
} else if (opacity == 255) {
|
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
|
|
||||||
auto tmp = surface->blender(*img, *dst, 255);
|
|
||||||
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(*img)));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) {
|
||||||
auto src = ALPHA_BLEND(*img, opacity);
|
auto tmp = surface->blender(*img, *dst, 255);
|
||||||
auto tmp = surface->blender(src, *dst, IA(src));
|
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(alpha, A(*img)));
|
||||||
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1164,9 +1155,8 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image,
|
||||||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
|
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
|
||||||
SCALED_IMAGE_RANGE_X
|
SCALED_IMAGE_RANGE_X
|
||||||
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
|
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize);
|
||||||
if (opacity < 255) ALPHA_BLEND(src, opacity);
|
|
||||||
auto tmp = surface->blender(src, *dst, 255);
|
auto tmp = surface->blender(src, *dst, 255);
|
||||||
*dst = INTERPOLATE(tmp, *dst, A(src));
|
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(opacity, A(src)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1348,11 +1338,13 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c
|
||||||
auto src = sbuffer;
|
auto src = sbuffer;
|
||||||
if (opacity == 255) {
|
if (opacity == 255) {
|
||||||
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
||||||
*dst = MULTIPLY(A(*src), alpha(cmp));
|
auto tmp = MULTIPLY(A(*src), alpha(cmp));
|
||||||
|
*dst = tmp + MULTIPLY(*dst, 255 - tmp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
||||||
*dst = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp)));
|
auto tmp = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp)));
|
||||||
|
*dst = tmp + MULTIPLY(*dst, 255 - tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer += surface->stride;
|
buffer += surface->stride;
|
||||||
|
@ -1384,9 +1376,8 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
||||||
auto tmp = ALPHA_BLEND(*src, opacity);
|
auto tmp = surface->blender(*src, *dst, 255);
|
||||||
auto tmp2 = surface->blender(tmp, *dst, 255);
|
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(opacity, A(*src)));
|
||||||
*dst = INTERPOLATE(tmp2, *dst, A(tmp));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dbuffer += surface->stride;
|
dbuffer += surface->stride;
|
||||||
|
@ -1442,12 +1433,52 @@ static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const S
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity)
|
||||||
|
{
|
||||||
|
if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
TVGERR("SW_ENGINE", "Not supported grayscale image!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
|
auto csize = surface->compositor->image.channelSize;
|
||||||
|
auto alpha = surface->alpha(surface->compositor->method);
|
||||||
|
auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
|
||||||
|
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
|
||||||
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
|
auto dst = buffer;
|
||||||
|
auto cmp = cbuffer;
|
||||||
|
auto src = sbuffer;
|
||||||
|
if (opacity == 255) {
|
||||||
|
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
||||||
|
auto tmp = ALPHA_BLEND(*src, alpha(cmp));
|
||||||
|
*dst = INTERPOLATE(surface->blender(tmp, *dst, 255), *dst, A(tmp));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) {
|
||||||
|
auto tmp = ALPHA_BLEND(*src, alpha(cmp));
|
||||||
|
*dst = INTERPOLATE(surface->blender(tmp, *dst, 255), *dst, MULTIPLY(opacity, A(tmp)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer += surface->stride;
|
||||||
|
cbuffer += surface->compositor->image.stride * csize;
|
||||||
|
sbuffer += image->stride;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent]
|
//Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent]
|
||||||
static bool _directImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity)
|
static bool _directImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity)
|
||||||
{
|
{
|
||||||
if (_compositing(surface)) {
|
if (_compositing(surface)) {
|
||||||
if (_matting(surface)) return _rasterDirectMattedImage(surface, image, region, opacity);
|
if (_matting(surface)) {
|
||||||
else return _rasterDirectMaskedImage(surface, image, region, opacity);
|
if (_blending(surface)) return _rasterDirectMattedBlendingImage(surface, image, region, opacity);
|
||||||
|
else return _rasterDirectMattedImage(surface, image, region, opacity);
|
||||||
|
} else return _rasterDirectMaskedImage(surface, image, region, opacity);
|
||||||
} else if (_blending(surface)) {
|
} else if (_blending(surface)) {
|
||||||
return _rasterDirectBlendingImage(surface, image, region, opacity);
|
return _rasterDirectBlendingImage(surface, image, region, opacity);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1843,7 +1874,7 @@ bool rasterCompositor(SwSurface* surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val)
|
||||||
{
|
{
|
||||||
if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false;
|
if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false;
|
||||||
|
|
||||||
|
@ -1851,11 +1882,11 @@ bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_
|
||||||
if (surface->channelSize == sizeof(uint32_t)) {
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
//full clear
|
//full clear
|
||||||
if (w == surface->stride) {
|
if (w == surface->stride) {
|
||||||
rasterPixel32(surface->buf32, 0x00000000, surface->stride * y, w * h);
|
rasterPixel32(surface->buf32, val, surface->stride * y, w * h);
|
||||||
//partial clear
|
//partial clear
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < h; i++) {
|
for (uint32_t i = 0; i < h; i++) {
|
||||||
rasterPixel32(surface->buf32, 0x00000000, (surface->stride * y + x) + (surface->stride * i), w);
|
rasterPixel32(surface->buf32, val, (surface->stride * y + x) + (surface->stride * i), w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//8 bits
|
//8 bits
|
||||||
|
|
|
@ -446,7 +446,7 @@ bool SwRenderer::renderShape(RenderData data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SwRenderer::blend(BlendMethod method, bool direct)
|
bool SwRenderer::blend(BlendMethod method)
|
||||||
{
|
{
|
||||||
if (surface->blendMethod == method) return true;
|
if (surface->blendMethod == method) return true;
|
||||||
surface->blendMethod = method;
|
surface->blendMethod = method;
|
||||||
|
@ -459,7 +459,7 @@ bool SwRenderer::blend(BlendMethod method, bool direct)
|
||||||
surface->blender = opBlendScreen;
|
surface->blender = opBlendScreen;
|
||||||
break;
|
break;
|
||||||
case BlendMethod::Multiply:
|
case BlendMethod::Multiply:
|
||||||
surface->blender = direct ? opBlendDirectMultiply : opBlendMultiply;
|
surface->blender = opBlendMultiply;
|
||||||
break;
|
break;
|
||||||
case BlendMethod::Overlay:
|
case BlendMethod::Overlay:
|
||||||
surface->blender = opBlendOverlay;
|
surface->blender = opBlendOverlay;
|
||||||
|
@ -606,7 +606,10 @@ Compositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs)
|
||||||
cmp->w = cmp->compositor->image.w;
|
cmp->w = cmp->compositor->image.w;
|
||||||
cmp->h = cmp->compositor->image.h;
|
cmp->h = cmp->compositor->image.h;
|
||||||
|
|
||||||
rasterClear(cmp, x, y, w, h);
|
/* TODO: Currently, only blending might work.
|
||||||
|
Blending and composition must be handled together. */
|
||||||
|
auto color = (surface->blender && !surface->compositor) ? 0x00ffffff : 0x00000000;
|
||||||
|
rasterClear(cmp, x, y, w, h, color);
|
||||||
|
|
||||||
//Switch render target
|
//Switch render target
|
||||||
surface = cmp;
|
surface = cmp;
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
RenderRegion region(RenderData data) override;
|
RenderRegion region(RenderData data) override;
|
||||||
RenderRegion viewport() override;
|
RenderRegion viewport() override;
|
||||||
bool viewport(const RenderRegion& vp) override;
|
bool viewport(const RenderRegion& vp) override;
|
||||||
bool blend(BlendMethod method, bool direct) override;
|
bool blend(BlendMethod method) override;
|
||||||
ColorSpace colorSpace() override;
|
ColorSpace colorSpace() override;
|
||||||
const Surface* mainSurface() override;
|
const Surface* mainSurface() override;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ bool Picture::Impl::needComposition(uint8_t opacity)
|
||||||
bool Picture::Impl::render(RenderMethod* renderer)
|
bool Picture::Impl::render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
renderer->blend(picture->blend(), true);
|
renderer->blend(picture->blend());
|
||||||
|
|
||||||
if (surface) return renderer->renderImage(rd);
|
if (surface) return renderer->renderImage(rd);
|
||||||
else if (paint) {
|
else if (paint) {
|
||||||
|
|
|
@ -296,7 +296,7 @@ public:
|
||||||
virtual RenderRegion region(RenderData data) = 0;
|
virtual RenderRegion region(RenderData data) = 0;
|
||||||
virtual RenderRegion viewport() = 0;
|
virtual RenderRegion viewport() = 0;
|
||||||
virtual bool viewport(const RenderRegion& vp) = 0;
|
virtual bool viewport(const RenderRegion& vp) = 0;
|
||||||
virtual bool blend(BlendMethod method, bool direct = false) = 0;
|
virtual bool blend(BlendMethod method) = 0;
|
||||||
virtual ColorSpace colorSpace() = 0;
|
virtual ColorSpace colorSpace() = 0;
|
||||||
virtual const Surface* mainSurface() = 0;
|
virtual const Surface* mainSurface() = 0;
|
||||||
|
|
||||||
|
|
|
@ -51,17 +51,18 @@ struct Shape::Impl
|
||||||
|
|
||||||
bool render(RenderMethod* renderer)
|
bool render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
Compositor* cmp = nullptr;
|
if (!rd) return false;
|
||||||
bool ret;
|
|
||||||
|
|
||||||
renderer->blend(shape->blend(), !needComp);
|
Compositor* cmp = nullptr;
|
||||||
|
|
||||||
|
renderer->blend(shape->blend());
|
||||||
|
|
||||||
if (needComp) {
|
if (needComp) {
|
||||||
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
|
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
|
||||||
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
|
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = renderer->renderShape(rd);
|
auto ret = renderer->renderShape(rd);
|
||||||
if (cmp) renderer->endComposite(cmp);
|
if (cmp) renderer->endComposite(cmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +118,7 @@ struct Shape::Impl
|
||||||
|
|
||||||
RenderRegion bounds(RenderMethod* renderer)
|
RenderRegion bounds(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
|
if (!rd) return {0, 0, 0, 0};
|
||||||
return renderer->region(rd);
|
return renderer->region(rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct Text::Impl
|
||||||
bool render(RenderMethod* renderer)
|
bool render(RenderMethod* renderer)
|
||||||
{
|
{
|
||||||
if (!loader) return true;
|
if (!loader) return true;
|
||||||
renderer->blend(paint->blend(), true);
|
renderer->blend(paint->blend());
|
||||||
return PP(shape)->render(renderer);
|
return PP(shape)->render(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
VERSION=0.14.9
|
VERSION=0.14.10
|
||||||
# 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=
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue