ThorVG: Update to 0.14.2
+ Fixes SVG: Graphical objects stored in <defs> shouldn't be rendered directly.
This commit is contained in:
parent
97b8ad1af0
commit
bf444545be
|
@ -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.1 (70b2f2dad158316dd08166d613b425248b36fd27, 2024)
|
- Version: 0.14.2 (f6c4d8a94e0b2194fe911d6e19a550683055dd50, 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.1"
|
#define THORVG_VERSION_STRING "0.14.2"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -281,6 +281,9 @@ public:
|
||||||
* The rotational axis passes through the point on the object with zero coordinates.
|
* The rotational axis passes through the point on the object with zero coordinates.
|
||||||
*
|
*
|
||||||
* @param[in] degree The value of the angle in degrees.
|
* @param[in] degree The value of the angle in degrees.
|
||||||
|
*
|
||||||
|
* @retval Result::InsufficientCondition in case a custom transform is applied.
|
||||||
|
* @see Paint::transform()
|
||||||
*/
|
*/
|
||||||
Result rotate(float degree) noexcept;
|
Result rotate(float degree) noexcept;
|
||||||
|
|
||||||
|
@ -288,6 +291,9 @@ public:
|
||||||
* @brief Sets the scale value of the object.
|
* @brief Sets the scale value of the object.
|
||||||
*
|
*
|
||||||
* @param[in] factor The value of the scaling factor. The default value is 1.
|
* @param[in] factor The value of the scaling factor. The default value is 1.
|
||||||
|
*
|
||||||
|
* @retval Result::InsufficientCondition in case a custom transform is applied.
|
||||||
|
* @see Paint::transform()
|
||||||
*/
|
*/
|
||||||
Result scale(float factor) noexcept;
|
Result scale(float factor) noexcept;
|
||||||
|
|
||||||
|
@ -299,6 +305,9 @@ public:
|
||||||
*
|
*
|
||||||
* @param[in] x The value of the horizontal shift.
|
* @param[in] x The value of the horizontal shift.
|
||||||
* @param[in] y The value of the vertical shift.
|
* @param[in] y The value of the vertical shift.
|
||||||
|
*
|
||||||
|
* @retval Result::InsufficientCondition in case a custom transform is applied.
|
||||||
|
* @see Paint::transform()
|
||||||
*/
|
*/
|
||||||
Result translate(float x, float y) noexcept;
|
Result translate(float x, float y) noexcept;
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@ float bezAngleAt(const Bezier& bz, float t)
|
||||||
pt.x *= 3;
|
pt.x *= 3;
|
||||||
pt.y *= 3;
|
pt.y *= 3;
|
||||||
|
|
||||||
return mathRad2Deg(atan2(pt.x, pt.y));
|
return mathRad2Deg(mathAtan2(pt.y, pt.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
#define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include "tvgTaskScheduler.h"
|
||||||
|
|
||||||
namespace tvg {
|
namespace tvg {
|
||||||
|
|
||||||
|
@ -42,14 +43,18 @@ namespace tvg {
|
||||||
|
|
||||||
ScopedLock(Key& k)
|
ScopedLock(Key& k)
|
||||||
{
|
{
|
||||||
|
if (TaskScheduler::threads() > 0) {
|
||||||
k.mtx.lock();
|
k.mtx.lock();
|
||||||
key = &k;
|
key = &k;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~ScopedLock()
|
~ScopedLock()
|
||||||
{
|
{
|
||||||
|
if (TaskScheduler::threads() > 0) {
|
||||||
key->mtx.unlock();
|
key->mtx.unlock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,20 @@
|
||||||
|
|
||||||
#include "tvgMath.h"
|
#include "tvgMath.h"
|
||||||
|
|
||||||
|
//see: https://en.wikipedia.org/wiki/Remez_algorithm
|
||||||
|
float mathAtan2(float y, float x)
|
||||||
|
{
|
||||||
|
if (y == 0.0f && x == 0.0f) return 0.0f;
|
||||||
|
|
||||||
|
auto a = std::min(fabsf(x), fabsf(y)) / std::max(fabsf(x), fabsf(y));
|
||||||
|
auto s = a * a;
|
||||||
|
auto r = ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a;
|
||||||
|
if (fabsf(y) > fabsf(x)) r = 1.57079637f - r;
|
||||||
|
if (x < 0) r = 3.14159274f - r;
|
||||||
|
if (y < 0) return -r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool mathInverse(const Matrix* m, Matrix* out)
|
bool mathInverse(const Matrix* m, Matrix* out)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
/* General functions */
|
/* General functions */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
float mathAtan2(float y, float x);
|
||||||
|
|
||||||
static inline float mathDeg2Rad(float degree)
|
static inline float mathDeg2Rad(float degree)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +80,7 @@ bool operator==(const Matrix& lhs, const Matrix& rhs);
|
||||||
|
|
||||||
static inline bool mathRightAngle(const Matrix* m)
|
static inline bool mathRightAngle(const Matrix* m)
|
||||||
{
|
{
|
||||||
auto radian = fabsf(atan2f(m->e21, m->e11));
|
auto radian = fabsf(mathAtan2(m->e21, m->e11));
|
||||||
if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
|
if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,9 +647,9 @@ static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*red = static_cast<uint8_t>(ceil(_red * 255.0f));
|
*red = (uint8_t)nearbyint(_red * 255.0f);
|
||||||
*green = static_cast<uint8_t>(ceil(_green * 255.0f));
|
*green = (uint8_t)nearbyint(_green * 255.0f);
|
||||||
*blue = static_cast<uint8_t>(ceil(_blue * 255.0f));
|
*blue = (uint8_t)nearbyint(_blue * 255.0f);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3254,19 +3254,34 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content)
|
static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content, unsigned int length)
|
||||||
{
|
{
|
||||||
|
const char* itr = nullptr;
|
||||||
|
int sz = length;
|
||||||
|
char tagName[20] = "";
|
||||||
|
|
||||||
content = _skipSpace(content, nullptr);
|
content = _skipSpace(content, nullptr);
|
||||||
|
itr = content;
|
||||||
|
while ((itr != nullptr) && *itr != '>') itr++;
|
||||||
|
|
||||||
|
if (itr) {
|
||||||
|
sz = itr - content;
|
||||||
|
while ((sz > 0) && (isspace(content[sz - 1]))) sz--;
|
||||||
|
if ((unsigned int)sz >= sizeof(tagName)) sz = sizeof(tagName) - 1;
|
||||||
|
strncpy(tagName, content, sz);
|
||||||
|
tagName[sz] = '\0';
|
||||||
|
}
|
||||||
|
else return;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sizeof(groupTags) / sizeof(groupTags[0]); i++) {
|
for (unsigned int i = 0; i < sizeof(groupTags) / sizeof(groupTags[0]); i++) {
|
||||||
if (!strncmp(content, groupTags[i].tag, groupTags[i].sz - 1)) {
|
if (!strncmp(tagName, groupTags[i].tag, sz)) {
|
||||||
loader->stack.pop();
|
loader->stack.pop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sizeof(graphicsTags) / sizeof(graphicsTags[0]); i++) {
|
for (unsigned int i = 0; i < sizeof(graphicsTags) / sizeof(graphicsTags[0]); i++) {
|
||||||
if (!strncmp(content, graphicsTags[i].tag, graphicsTags[i].sz - 1)) {
|
if (!strncmp(tagName, graphicsTags[i].tag, sz)) {
|
||||||
loader->currentGraphicsNode = nullptr;
|
loader->currentGraphicsNode = nullptr;
|
||||||
loader->stack.pop();
|
loader->stack.pop();
|
||||||
break;
|
break;
|
||||||
|
@ -3437,7 +3452,7 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SimpleXMLType::Close: {
|
case SimpleXMLType::Close: {
|
||||||
_svgLoaderParserXmlClose(loader, content);
|
_svgLoaderParserXmlClose(loader, content, length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SimpleXMLType::Data:
|
case SimpleXMLType::Data:
|
||||||
|
|
|
@ -194,10 +194,10 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P
|
||||||
//We dont' use arccos (as per w3c doc), see
|
//We dont' use arccos (as per w3c doc), see
|
||||||
//http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
|
//http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
|
||||||
//Note: atan2 (0.0, 1.0) == 0.0
|
//Note: atan2 (0.0, 1.0) == 0.0
|
||||||
at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
at = mathAtan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
||||||
theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
|
theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
|
||||||
|
|
||||||
nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
nat = mathAtan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
||||||
deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
|
deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
|
||||||
|
|
||||||
if (sweep) {
|
if (sweep) {
|
||||||
|
|
|
@ -114,8 +114,8 @@ bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transfor
|
||||||
|
|
||||||
//Fast track: Non-transformed image but just shifted.
|
//Fast track: Non-transformed image but just shifted.
|
||||||
if (image->direct) {
|
if (image->direct) {
|
||||||
image->ox = -static_cast<int32_t>(round(transform->e13));
|
image->ox = -static_cast<int32_t>(nearbyint(transform->e13));
|
||||||
image->oy = -static_cast<int32_t>(round(transform->e23));
|
image->oy = -static_cast<int32_t>(nearbyint(transform->e23));
|
||||||
//Figure out the scale factor by transform matrix
|
//Figure out the scale factor by transform matrix
|
||||||
} else {
|
} else {
|
||||||
auto scaleX = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21));
|
auto scaleX = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21));
|
||||||
|
|
|
@ -164,8 +164,8 @@ void mathRotate(SwPoint& pt, SwFixed angle)
|
||||||
auto cosv = cosf(radian);
|
auto cosv = cosf(radian);
|
||||||
auto sinv = sinf(radian);
|
auto sinv = sinf(radian);
|
||||||
|
|
||||||
pt.x = SwCoord(roundf((v.x * cosv - v.y * sinv) * 64.0f));
|
pt.x = SwCoord(nearbyint((v.x * cosv - v.y * sinv) * 64.0f));
|
||||||
pt.y = SwCoord(roundf((v.x * sinv + v.y * cosv) * 64.0f));
|
pt.y = SwCoord(nearbyint((v.x * sinv + v.y * cosv) * 64.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ SwFixed mathTan(SwFixed angle)
|
||||||
SwFixed mathAtan(const SwPoint& pt)
|
SwFixed mathAtan(const SwPoint& pt)
|
||||||
{
|
{
|
||||||
if (pt.zero()) return 0;
|
if (pt.zero()) return 0;
|
||||||
return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
return SwFixed(mathAtan2(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,10 +309,10 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S
|
||||||
//the rasterization region has to be rearranged.
|
//the rasterization region has to be rearranged.
|
||||||
//https://github.com/Samsung/thorvg/issues/916
|
//https://github.com/Samsung/thorvg/issues/916
|
||||||
if (fastTrack) {
|
if (fastTrack) {
|
||||||
renderRegion.min.x = static_cast<SwCoord>(round(xMin / 64.0f));
|
renderRegion.min.x = static_cast<SwCoord>(nearbyint(xMin / 64.0f));
|
||||||
renderRegion.max.x = static_cast<SwCoord>(round(xMax / 64.0f));
|
renderRegion.max.x = static_cast<SwCoord>(nearbyint(xMax / 64.0f));
|
||||||
renderRegion.min.y = static_cast<SwCoord>(round(yMin / 64.0f));
|
renderRegion.min.y = static_cast<SwCoord>(nearbyint(yMin / 64.0f));
|
||||||
renderRegion.max.y = static_cast<SwCoord>(round(yMax / 64.0f));
|
renderRegion.max.y = static_cast<SwCoord>(nearbyint(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;
|
||||||
|
|
|
@ -383,7 +383,8 @@ static bool _rasterMattedRect(SwSurface* surface, const SwBBox& region, uint8_t
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
auto cmp = &cbuffer[y * surface->compositor->image.stride * csize];
|
auto cmp = &cbuffer[y * surface->compositor->image.stride * csize];
|
||||||
for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
|
for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
|
||||||
*dst = INTERPOLATE(color, *dst, alpha(cmp));
|
auto tmp = ALPHA_BLEND(color, alpha(cmp));
|
||||||
|
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//8bits grayscale
|
//8bits grayscale
|
||||||
|
@ -674,7 +675,7 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
|
||||||
auto sy = (y) * itransform->e22 + itransform->e23 - 0.49f; \
|
auto sy = (y) * itransform->e22 + itransform->e23 - 0.49f; \
|
||||||
if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image->h) continue; \
|
if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image->h) continue; \
|
||||||
if (scaleMethod == _interpDownScaler) { \
|
if (scaleMethod == _interpDownScaler) { \
|
||||||
auto my = (int32_t)round(sy); \
|
auto my = (int32_t)nearbyint(sy); \
|
||||||
miny = my - (int32_t)sampleSize; \
|
miny = my - (int32_t)sampleSize; \
|
||||||
if (miny < 0) miny = 0; \
|
if (miny < 0) miny = 0; \
|
||||||
maxy = my + (int32_t)sampleSize; \
|
maxy = my + (int32_t)sampleSize; \
|
||||||
|
|
|
@ -197,7 +197,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
constexpr auto MAX_SPANS = 256;
|
|
||||||
constexpr auto PIXEL_BITS = 8; //must be at least 6 bits!
|
constexpr auto PIXEL_BITS = 8; //must be at least 6 bits!
|
||||||
constexpr auto ONE_PIXEL = (1L << PIXEL_BITS);
|
constexpr auto ONE_PIXEL = (1L << PIXEL_BITS);
|
||||||
|
|
||||||
|
@ -240,10 +239,6 @@ struct RleWorker
|
||||||
|
|
||||||
SwOutline* outline;
|
SwOutline* outline;
|
||||||
|
|
||||||
SwSpan spans[MAX_SPANS];
|
|
||||||
int spansCnt;
|
|
||||||
int ySpan;
|
|
||||||
|
|
||||||
int bandSize;
|
int bandSize;
|
||||||
int bandShoot;
|
int bandShoot;
|
||||||
|
|
||||||
|
@ -301,26 +296,6 @@ static inline SwCoord HYPOT(SwPoint pt)
|
||||||
return ((pt.x > pt.y) ? (pt.x + (3 * pt.y >> 3)) : (pt.y + (3 * pt.x >> 3)));
|
return ((pt.x > pt.y) ? (pt.x + (3 * pt.y >> 3)) : (pt.y + (3 * pt.x >> 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _genSpan(SwRleData* rle, const SwSpan* spans, uint32_t count)
|
|
||||||
{
|
|
||||||
auto newSize = rle->size + count;
|
|
||||||
|
|
||||||
/* allocate enough memory for new spans */
|
|
||||||
/* alloc is required to prevent free and reallocation */
|
|
||||||
/* when the rle needs to be regenerated because of attribute change. */
|
|
||||||
if (rle->alloc < newSize) {
|
|
||||||
rle->alloc = (newSize * 2);
|
|
||||||
//OPTIMIZE: use mempool!
|
|
||||||
rle->spans = static_cast<SwSpan*>(realloc(rle->spans, rle->alloc * sizeof(SwSpan)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy the new spans to the allocated memory
|
|
||||||
SwSpan* lastSpan = rle->spans + rle->size;
|
|
||||||
memcpy(lastSpan, spans, count * sizeof(SwSpan));
|
|
||||||
|
|
||||||
rle->size = newSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord acount)
|
static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoord acount)
|
||||||
{
|
{
|
||||||
|
@ -344,25 +319,26 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
||||||
if (coverage > 255) coverage = 255;
|
if (coverage > 255) coverage = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coverage == 0) return;
|
||||||
|
|
||||||
//span has ushort coordinates. check limit overflow
|
//span has ushort coordinates. check limit overflow
|
||||||
if (x >= SHRT_MAX) {
|
if (x >= SHRT_MAX) {
|
||||||
TVGERR("SW_ENGINE", "X-coordiante overflow!");
|
TVGERR("SW_ENGINE", "X-coordinate overflow!");
|
||||||
x = SHRT_MAX;
|
return;
|
||||||
}
|
}
|
||||||
if (y >= SHRT_MAX) {
|
if (y >= SHRT_MAX) {
|
||||||
TVGERR("SW_ENGINE", "Y Coordiante overflow!");
|
TVGERR("SW_ENGINE", "Y-coordinate overflow!");
|
||||||
y = SHRT_MAX;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coverage > 0) {
|
auto rle = rw.rle;
|
||||||
|
|
||||||
if (!rw.antiAlias) coverage = 255;
|
if (!rw.antiAlias) coverage = 255;
|
||||||
auto count = rw.spansCnt;
|
|
||||||
auto span = rw.spans + count - 1;
|
|
||||||
|
|
||||||
//see whether we can add this span to the current list
|
//see whether we can add this span to the current list
|
||||||
if ((count > 0) && (rw.ySpan == y) &&
|
if (rle->size > 0) {
|
||||||
(span->x + span->len == x) && (span->coverage == coverage)) {
|
auto span = rle->spans + rle->size - 1;
|
||||||
|
if ((span->coverage == coverage) && (span->y == y) && (span->x + span->len == x)) {
|
||||||
//Clip x range
|
//Clip x range
|
||||||
SwCoord xOver = 0;
|
SwCoord xOver = 0;
|
||||||
if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x);
|
if (x + acount >= rw.cellMax.x) xOver -= (x + acount - rw.cellMax.x);
|
||||||
|
@ -372,14 +348,15 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
||||||
span->len += (acount + xOver);
|
span->len += (acount + xOver);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count >= MAX_SPANS) {
|
//span pool is full, grow it.
|
||||||
_genSpan(rw.rle, rw.spans, count);
|
if (rle->size >= rle->alloc) {
|
||||||
rw.spansCnt = 0;
|
auto newSize = (rle->size > 0) ? (rle->size * 2) : 256;
|
||||||
rw.ySpan = 0;
|
if (rle->alloc < newSize) {
|
||||||
span = rw.spans;
|
rle->alloc = newSize;
|
||||||
} else {
|
rle->spans = static_cast<SwSpan*>(realloc(rle->spans, rle->alloc * sizeof(SwSpan)));
|
||||||
++span;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clip x range
|
//Clip x range
|
||||||
|
@ -394,13 +371,12 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor
|
||||||
if (acount + xOver <= 0) return;
|
if (acount + xOver <= 0) return;
|
||||||
|
|
||||||
//add a span to the current list
|
//add a span to the current list
|
||||||
|
auto span = rle->spans + rle->size;
|
||||||
span->x = x;
|
span->x = x;
|
||||||
span->y = y;
|
span->y = y;
|
||||||
span->len = (acount + xOver);
|
span->len = (acount + xOver);
|
||||||
span->coverage = coverage;
|
span->coverage = coverage;
|
||||||
++rw.spansCnt;
|
rle->size++;
|
||||||
rw.ySpan = y;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,9 +384,6 @@ static void _sweep(RleWorker& rw)
|
||||||
{
|
{
|
||||||
if (rw.cellsCnt == 0) return;
|
if (rw.cellsCnt == 0) return;
|
||||||
|
|
||||||
rw.spansCnt = 0;
|
|
||||||
rw.ySpan = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < rw.yCnt; ++y) {
|
for (int y = 0; y < rw.yCnt; ++y) {
|
||||||
auto cover = 0;
|
auto cover = 0;
|
||||||
auto x = 0;
|
auto x = 0;
|
||||||
|
@ -427,8 +400,6 @@ static void _sweep(RleWorker& rw)
|
||||||
|
|
||||||
if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x);
|
if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rw.spansCnt > 0) _genSpan(rw.rle, rw.spans, rw.spansCnt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -926,7 +897,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren
|
||||||
rw.cellMax = renderRegion.max;
|
rw.cellMax = renderRegion.max;
|
||||||
rw.cellXCnt = rw.cellMax.x - rw.cellMin.x;
|
rw.cellXCnt = rw.cellMax.x - rw.cellMin.x;
|
||||||
rw.cellYCnt = rw.cellMax.y - rw.cellMin.y;
|
rw.cellYCnt = rw.cellMax.y - rw.cellMin.y;
|
||||||
rw.ySpan = 0;
|
|
||||||
rw.outline = const_cast<SwOutline*>(outline);
|
rw.outline = const_cast<SwOutline*>(outline);
|
||||||
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 2); //bandSize: 256
|
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 2); //bandSize: 256
|
||||||
rw.bandShoot = 0;
|
rw.bandShoot = 0;
|
||||||
|
@ -1019,7 +989,6 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(rw.rle);
|
free(rw.rle);
|
||||||
rw.rle = nullptr;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ static Result _compFastTrack(RenderMethod* renderer, Paint* cmpTarget, const Ren
|
||||||
|
|
||||||
if (ptsCnt != 4) return Result::InsufficientCondition;
|
if (ptsCnt != 4) return Result::InsufficientCondition;
|
||||||
|
|
||||||
if (rTransform) rTransform->update();
|
if (rTransform && (cmpTarget->pImpl->renderFlag & RenderUpdateFlag::Transform)) rTransform->update();
|
||||||
|
|
||||||
//No rotation and no skewing, still can try out clipping the rect region.
|
//No rotation and no skewing, still can try out clipping the rect region.
|
||||||
auto tryClip = false;
|
auto tryClip = false;
|
||||||
|
@ -181,13 +181,14 @@ Paint* Paint::Impl::duplicate()
|
||||||
bool Paint::Impl::rotate(float degree)
|
bool Paint::Impl::rotate(float degree)
|
||||||
{
|
{
|
||||||
if (rTransform) {
|
if (rTransform) {
|
||||||
|
if (rTransform->overriding) return false;
|
||||||
if (mathEqual(degree, rTransform->degree)) return true;
|
if (mathEqual(degree, rTransform->degree)) return true;
|
||||||
} else {
|
} else {
|
||||||
if (mathZero(degree)) return true;
|
if (mathZero(degree)) return true;
|
||||||
rTransform = new RenderTransform();
|
rTransform = new RenderTransform();
|
||||||
}
|
}
|
||||||
rTransform->degree = degree;
|
rTransform->degree = degree;
|
||||||
if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform;
|
renderFlag |= RenderUpdateFlag::Transform;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -196,13 +197,14 @@ bool Paint::Impl::rotate(float degree)
|
||||||
bool Paint::Impl::scale(float factor)
|
bool Paint::Impl::scale(float factor)
|
||||||
{
|
{
|
||||||
if (rTransform) {
|
if (rTransform) {
|
||||||
|
if (rTransform->overriding) return false;
|
||||||
if (mathEqual(factor, rTransform->scale)) return true;
|
if (mathEqual(factor, rTransform->scale)) return true;
|
||||||
} else {
|
} else {
|
||||||
if (mathEqual(factor, 1.0f)) return true;
|
if (mathEqual(factor, 1.0f)) return true;
|
||||||
rTransform = new RenderTransform();
|
rTransform = new RenderTransform();
|
||||||
}
|
}
|
||||||
rTransform->scale = factor;
|
rTransform->scale = factor;
|
||||||
if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform;
|
renderFlag |= RenderUpdateFlag::Transform;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -211,14 +213,15 @@ bool Paint::Impl::scale(float factor)
|
||||||
bool Paint::Impl::translate(float x, float y)
|
bool Paint::Impl::translate(float x, float y)
|
||||||
{
|
{
|
||||||
if (rTransform) {
|
if (rTransform) {
|
||||||
if (mathEqual(x, rTransform->x) && mathEqual(y, rTransform->y)) return true;
|
if (rTransform->overriding) return false;
|
||||||
|
if (mathEqual(x, rTransform->m.e13) && mathEqual(y, rTransform->m.e23)) return true;
|
||||||
} else {
|
} else {
|
||||||
if (mathZero(x) && mathZero(y)) return true;
|
if (mathZero(x) && mathZero(y)) return true;
|
||||||
rTransform = new RenderTransform();
|
rTransform = new RenderTransform();
|
||||||
}
|
}
|
||||||
rTransform->x = x;
|
rTransform->m.e13 = x;
|
||||||
rTransform->y = y;
|
rTransform->m.e23 = y;
|
||||||
if (!rTransform->overriding) renderFlag |= RenderUpdateFlag::Transform;
|
renderFlag |= RenderUpdateFlag::Transform;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -263,10 +266,7 @@ RenderData Paint::Impl::update(RenderMethod* renderer, const RenderTransform* pT
|
||||||
this->renderer = renderer;
|
this->renderer = renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderFlag & RenderUpdateFlag::Transform) {
|
if (renderFlag & RenderUpdateFlag::Transform) rTransform->update();
|
||||||
if (!rTransform) return nullptr;
|
|
||||||
rTransform->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1. Composition Pre Processing */
|
/* 1. Composition Pre Processing */
|
||||||
RenderData trd = nullptr; //composite target render data
|
RenderData trd = nullptr; //composite target render data
|
||||||
|
@ -390,28 +390,28 @@ Paint :: ~Paint()
|
||||||
Result Paint::rotate(float degree) noexcept
|
Result Paint::rotate(float degree) noexcept
|
||||||
{
|
{
|
||||||
if (pImpl->rotate(degree)) return Result::Success;
|
if (pImpl->rotate(degree)) return Result::Success;
|
||||||
return Result::FailedAllocation;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Paint::scale(float factor) noexcept
|
Result Paint::scale(float factor) noexcept
|
||||||
{
|
{
|
||||||
if (pImpl->scale(factor)) return Result::Success;
|
if (pImpl->scale(factor)) return Result::Success;
|
||||||
return Result::FailedAllocation;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Paint::translate(float x, float y) noexcept
|
Result Paint::translate(float x, float y) noexcept
|
||||||
{
|
{
|
||||||
if (pImpl->translate(x, y)) return Result::Success;
|
if (pImpl->translate(x, y)) return Result::Success;
|
||||||
return Result::FailedAllocation;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Paint::transform(const Matrix& m) noexcept
|
Result Paint::transform(const Matrix& m) noexcept
|
||||||
{
|
{
|
||||||
if (pImpl->transform(m)) return Result::Success;
|
if (pImpl->transform(m)) return Result::Success;
|
||||||
return Result::FailedAllocation;
|
return Result::InsufficientCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,6 @@ namespace tvg
|
||||||
if (!rTransform) {
|
if (!rTransform) {
|
||||||
if (mathIdentity(&m)) return true;
|
if (mathIdentity(&m)) return true;
|
||||||
rTransform = new RenderTransform();
|
rTransform = new RenderTransform();
|
||||||
if (!rTransform) return false;
|
|
||||||
}
|
}
|
||||||
rTransform->override(m);
|
rTransform->override(m);
|
||||||
renderFlag |= RenderUpdateFlag::Transform;
|
renderFlag |= RenderUpdateFlag::Transform;
|
||||||
|
@ -98,7 +97,7 @@ namespace tvg
|
||||||
Matrix* transform()
|
Matrix* transform()
|
||||||
{
|
{
|
||||||
if (rTransform) {
|
if (rTransform) {
|
||||||
rTransform->update();
|
if (renderFlag & RenderUpdateFlag::Transform) rTransform->update();
|
||||||
return &rTransform->m;
|
return &rTransform->m;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -92,18 +92,19 @@ struct Picture::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const RenderTransform* pTransform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod* renderer, const RenderTransform* pTransform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
auto flag = load();
|
auto flag = static_cast<RenderUpdateFlag>(pFlag | load());
|
||||||
|
|
||||||
if (surface) {
|
if (surface) {
|
||||||
|
if (flag == RenderUpdateFlag::None) return rd;
|
||||||
auto transform = resizeTransform(pTransform);
|
auto transform = resizeTransform(pTransform);
|
||||||
rd = renderer->prepare(surface, &rm, rd, &transform, clips, opacity, static_cast<RenderUpdateFlag>(pFlag | flag));
|
rd = renderer->prepare(surface, &rm, rd, &transform, clips, opacity, flag);
|
||||||
} else if (paint) {
|
} else if (paint) {
|
||||||
if (resizing) {
|
if (resizing) {
|
||||||
loader->resize(paint, w, h);
|
loader->resize(paint, w, h);
|
||||||
resizing = false;
|
resizing = false;
|
||||||
}
|
}
|
||||||
needComp = needComposition(opacity) ? true : false;
|
needComp = needComposition(opacity) ? true : false;
|
||||||
rd = paint->pImpl->update(renderer, pTransform, clips, opacity, static_cast<RenderUpdateFlag>(pFlag | flag), clipper);
|
rd = paint->pImpl->update(renderer, pTransform, clips, opacity, flag, clipper);
|
||||||
}
|
}
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
@ -200,6 +201,7 @@ struct Picture::Impl
|
||||||
if (loader) {
|
if (loader) {
|
||||||
dup->loader = loader;
|
dup->loader = loader;
|
||||||
++dup->loader->sharing;
|
++dup->loader->sharing;
|
||||||
|
PP(ret)->renderFlag |= RenderUpdateFlag::Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
dup->surface = surface;
|
dup->surface = surface;
|
||||||
|
|
|
@ -32,6 +32,20 @@
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
|
uint32_t RenderMethod::ref()
|
||||||
|
{
|
||||||
|
ScopedLock lock(key);
|
||||||
|
return (++refCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t RenderMethod::unref()
|
||||||
|
{
|
||||||
|
ScopedLock lock(key);
|
||||||
|
return (--refCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderTransform::override(const Matrix& m)
|
void RenderTransform::override(const Matrix& m)
|
||||||
{
|
{
|
||||||
this->m = m;
|
this->m = m;
|
||||||
|
@ -43,13 +57,18 @@ void RenderTransform::update()
|
||||||
{
|
{
|
||||||
if (overriding) return;
|
if (overriding) return;
|
||||||
|
|
||||||
mathIdentity(&m);
|
m.e11 = 1.0f;
|
||||||
|
m.e12 = 0.0f;
|
||||||
|
|
||||||
|
m.e21 = 0.0f;
|
||||||
|
m.e22 = 1.0f;
|
||||||
|
|
||||||
|
m.e31 = 0.0f;
|
||||||
|
m.e32 = 0.0f;
|
||||||
|
m.e33 = 1.0f;
|
||||||
|
|
||||||
mathScale(&m, scale, scale);
|
mathScale(&m, scale, scale);
|
||||||
|
|
||||||
mathRotate(&m, degree);
|
mathRotate(&m, degree);
|
||||||
|
|
||||||
mathTranslate(&m, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -112,9 +112,7 @@ struct RenderRegion
|
||||||
|
|
||||||
struct RenderTransform
|
struct RenderTransform
|
||||||
{
|
{
|
||||||
Matrix m; //3x3 Matrix Elements
|
Matrix m;
|
||||||
float x = 0.0f;
|
|
||||||
float y = 0.0f;
|
|
||||||
float degree = 0.0f; //rotation degree
|
float degree = 0.0f; //rotation degree
|
||||||
float scale = 1.0f; //scale factor
|
float scale = 1.0f; //scale factor
|
||||||
bool overriding = false; //user transform?
|
bool overriding = false; //user transform?
|
||||||
|
@ -122,7 +120,11 @@ struct RenderTransform
|
||||||
void update();
|
void update();
|
||||||
void override(const Matrix& m);
|
void override(const Matrix& m);
|
||||||
|
|
||||||
RenderTransform() {}
|
RenderTransform()
|
||||||
|
{
|
||||||
|
m.e13 = m.e23 = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -246,17 +248,8 @@ private:
|
||||||
Key key;
|
Key key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32_t ref()
|
uint32_t ref();
|
||||||
{
|
uint32_t unref();
|
||||||
ScopedLock lock(key);
|
|
||||||
return (++refCnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t unref()
|
|
||||||
{
|
|
||||||
ScopedLock lock(key);
|
|
||||||
return (--refCnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~RenderMethod() {}
|
virtual ~RenderMethod() {}
|
||||||
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0;
|
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0;
|
||||||
|
|
|
@ -97,6 +97,8 @@ struct Shape::Impl
|
||||||
|
|
||||||
RenderData update(RenderMethod* renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
RenderData update(RenderMethod* renderer, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper)
|
||||||
{
|
{
|
||||||
|
if (static_cast<RenderUpdateFlag>(pFlag | flag) == RenderUpdateFlag::None) return rd;
|
||||||
|
|
||||||
if ((needComp = needComposition(opacity))) {
|
if ((needComp = needComposition(opacity))) {
|
||||||
/* Overriding opacity value. If this scene is half-translucent,
|
/* Overriding opacity value. If this scene is half-translucent,
|
||||||
It must do intermeidate composition with that opacity value. */
|
It must do intermeidate composition with that opacity value. */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
VERSION=0.14.1
|
VERSION=0.14.2
|
||||||
|
|
||||||
cd thirdparty/thorvg/ || true
|
cd thirdparty/thorvg/ || true
|
||||||
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
|
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
|
||||||
|
|
Loading…
Reference in New Issue