ThorVG: Update to 0.13.7
This commit is contained in:
parent
5833f59786
commit
18650de06a
|
@ -882,7 +882,7 @@ instead of `miniz.h` as an external dependency.
|
|||
## thorvg
|
||||
|
||||
- Upstream: https://github.com/thorvg/thorvg
|
||||
- Version: 0.13.3 (6235068cad8cad176ccd0cbcf82f25e985fbc258, 2024)
|
||||
- Version: 0.13.7 (d2c0428a99f7305c086caffe0c730add601ebd6e, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
@ -13,5 +13,5 @@
|
|||
// For internal debugging:
|
||||
//#define THORVG_LOG_ENABLED
|
||||
|
||||
#define THORVG_VERSION_STRING "0.13.5"
|
||||
#define THORVG_VERSION_STRING "0.13.7"
|
||||
#endif
|
||||
|
|
|
@ -80,7 +80,7 @@ enum class Result
|
|||
InsufficientCondition, ///< The value returned in case the request cannot be processed - e.g. asking for properties of an object, which does not exist.
|
||||
FailedAllocation, ///< The value returned in case of unsuccessful memory allocation.
|
||||
MemoryCorruption, ///< The value returned in the event of bad memory handling - e.g. failing in pointer releasing or casting
|
||||
NonSupport, ///< The value returned in case of choosing unsupported options.
|
||||
NonSupport, ///< The value returned in case of choosing unsupported engine features(options).
|
||||
Unknown ///< The value returned in all other cases.
|
||||
};
|
||||
|
||||
|
@ -982,7 +982,7 @@ public:
|
|||
*
|
||||
* @param[in] width The width of the stroke. The default value is 0.
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed.
|
||||
*/
|
||||
Result stroke(float width) noexcept;
|
||||
|
||||
|
@ -994,7 +994,7 @@ public:
|
|||
* @param[in] b The blue color channel value in the range [0 ~ 255]. The default value is 0.
|
||||
* @param[in] a The alpha channel value in the range [0 ~ 255], where 0 is completely transparent and 255 is opaque. The default value is 0.
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed.
|
||||
*/
|
||||
Result stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept;
|
||||
|
||||
|
@ -1004,8 +1004,7 @@ public:
|
|||
* @param[in] f The gradient fill.
|
||||
*
|
||||
* @retval Result::Success When succeed.
|
||||
* @retval Result::FailedAllocation An internal error with a memory allocation for an object to be filled.
|
||||
* @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument.
|
||||
* @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument or an error with accessing it.
|
||||
*/
|
||||
Result stroke(std::unique_ptr<Fill> f) noexcept;
|
||||
|
||||
|
@ -1029,7 +1028,7 @@ public:
|
|||
*
|
||||
* @param[in] cap The cap style value. The default value is @c StrokeCap::Square.
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed.
|
||||
*/
|
||||
Result stroke(StrokeCap cap) noexcept;
|
||||
|
||||
|
@ -1040,22 +1039,37 @@ public:
|
|||
*
|
||||
* @param[in] join The join style value. The default value is @c StrokeJoin::Bevel.
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed.
|
||||
*/
|
||||
Result stroke(StrokeJoin join) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the stroke miterlimit.
|
||||
*
|
||||
* @param[in] miterlimit The miterlimit imposes a limit on the extent of the stroke join, when the @c StrokeJoin::Miter join style is set. The default value is 4.
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::NonSupport unsupported value, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed or Result::InvalidArgument for @p miterlimit values less than zero.
|
||||
*
|
||||
* @since 0.11
|
||||
*/
|
||||
Result strokeMiterlimit(float miterlimit) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Sets the trim of the stroke along the defined path segment, allowing control over which part of the stroke is visible.
|
||||
*
|
||||
* The values of the arguments @p begin, @p end, and @p offset are in the range of 0.0 to 1.0, representing the beginning of the path and the end, respectively.
|
||||
*
|
||||
* @param[in] begin Specifies the start of the segment to display along the path.
|
||||
* @param[in] end Specifies the end of the segment to display along the path.
|
||||
* @param[in] simultaneous Determines how to trim multiple paths within a single shape. If set to @c true (default), trimming is applied simultaneously to all paths;
|
||||
* Otherwise, all paths are treated as a single entity with a combined length equal to the sum of their individual lengths and are trimmed as such.
|
||||
*
|
||||
* @retval Result::Success when succeed.
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
Result strokeTrim(float begin, float end, bool simultaneous = true) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Sets the solid color for all of the figures from the path.
|
||||
*
|
||||
|
@ -1095,19 +1109,17 @@ public:
|
|||
*/
|
||||
Result fill(FillRule r) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the rendering order of the stroke and the fill.
|
||||
*
|
||||
* @param[in] strokeFirst If @c true the stroke is rendered before the fill, otherwise the stroke is rendered as the second one (the default option).
|
||||
*
|
||||
* @retval Result::Success when succeed, Result::FailedAllocation otherwise.
|
||||
* @retval Result::Success when succeed.
|
||||
*
|
||||
* @since 0.10
|
||||
*/
|
||||
Result order(bool strokeFirst) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the commands data of the path.
|
||||
*
|
||||
|
@ -1210,6 +1222,18 @@ public:
|
|||
*/
|
||||
float strokeMiterlimit() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Gets the trim of the stroke along the defined path segment.
|
||||
*
|
||||
* @param[out] begin The starting point of the segment to display along the path.
|
||||
* @param[out] end Specifies the end of the segment to display along the path.
|
||||
*
|
||||
* @retval @c true if trimming is applied simultaneously to all paths of the shape, @c false otherwise.
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
bool strokeTrim(float* begin, float* end) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Creates a new Shape object.
|
||||
*
|
||||
|
|
|
@ -472,4 +472,19 @@ size_t b64Decode(const char* encoded, const size_t len, char** decoded)
|
|||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* DJB2 Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
unsigned long djb2Encode(const char* str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
|
||||
while ((c = *str++)) {
|
||||
hash = ((hash << 5) + hash) + c; // hash * 33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace tvg
|
|||
uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits);
|
||||
uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes);
|
||||
size_t b64Decode(const char* encoded, const size_t len, char** decoded);
|
||||
unsigned long djb2Encode(const char* str);
|
||||
}
|
||||
|
||||
#endif //_TVG_COMPRESSOR_H_
|
||||
|
|
|
@ -47,23 +47,14 @@ bool mathInverse(const Matrix* m, Matrix* out)
|
|||
}
|
||||
|
||||
|
||||
Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs)
|
||||
bool mathIdentity(const Matrix* m)
|
||||
{
|
||||
Matrix m;
|
||||
|
||||
m.e11 = lhs->e11 * rhs->e11 + lhs->e12 * rhs->e21 + lhs->e13 * rhs->e31;
|
||||
m.e12 = lhs->e11 * rhs->e12 + lhs->e12 * rhs->e22 + lhs->e13 * rhs->e32;
|
||||
m.e13 = lhs->e11 * rhs->e13 + lhs->e12 * rhs->e23 + lhs->e13 * rhs->e33;
|
||||
|
||||
m.e21 = lhs->e21 * rhs->e11 + lhs->e22 * rhs->e21 + lhs->e23 * rhs->e31;
|
||||
m.e22 = lhs->e21 * rhs->e12 + lhs->e22 * rhs->e22 + lhs->e23 * rhs->e32;
|
||||
m.e23 = lhs->e21 * rhs->e13 + lhs->e22 * rhs->e23 + lhs->e23 * rhs->e33;
|
||||
|
||||
m.e31 = lhs->e31 * rhs->e11 + lhs->e32 * rhs->e21 + lhs->e33 * rhs->e31;
|
||||
m.e32 = lhs->e31 * rhs->e12 + lhs->e32 * rhs->e22 + lhs->e33 * rhs->e32;
|
||||
m.e33 = lhs->e31 * rhs->e13 + lhs->e32 * rhs->e23 + lhs->e33 * rhs->e33;
|
||||
|
||||
return m;
|
||||
if (m->e11 != 1.0f || m->e12 != 0.0f || m->e13 != 0.0f ||
|
||||
m->e21 != 0.0f || m->e22 != 1.0f || m->e23 != 0.0f ||
|
||||
m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,21 +73,41 @@ void mathRotate(Matrix* m, float degree)
|
|||
}
|
||||
|
||||
|
||||
bool mathIdentity(const Matrix* m)
|
||||
Matrix operator*(const Matrix& lhs, const Matrix& rhs)
|
||||
{
|
||||
if (m->e11 != 1.0f || m->e12 != 0.0f || m->e13 != 0.0f ||
|
||||
m->e21 != 0.0f || m->e22 != 1.0f || m->e23 != 0.0f ||
|
||||
m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) {
|
||||
Matrix m;
|
||||
|
||||
m.e11 = lhs.e11 * rhs.e11 + lhs.e12 * rhs.e21 + lhs.e13 * rhs.e31;
|
||||
m.e12 = lhs.e11 * rhs.e12 + lhs.e12 * rhs.e22 + lhs.e13 * rhs.e32;
|
||||
m.e13 = lhs.e11 * rhs.e13 + lhs.e12 * rhs.e23 + lhs.e13 * rhs.e33;
|
||||
|
||||
m.e21 = lhs.e21 * rhs.e11 + lhs.e22 * rhs.e21 + lhs.e23 * rhs.e31;
|
||||
m.e22 = lhs.e21 * rhs.e12 + lhs.e22 * rhs.e22 + lhs.e23 * rhs.e32;
|
||||
m.e23 = lhs.e21 * rhs.e13 + lhs.e22 * rhs.e23 + lhs.e23 * rhs.e33;
|
||||
|
||||
m.e31 = lhs.e31 * rhs.e11 + lhs.e32 * rhs.e21 + lhs.e33 * rhs.e31;
|
||||
m.e32 = lhs.e31 * rhs.e12 + lhs.e32 * rhs.e22 + lhs.e33 * rhs.e32;
|
||||
m.e33 = lhs.e31 * rhs.e13 + lhs.e32 * rhs.e23 + lhs.e33 * rhs.e33;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const Matrix& lhs, const Matrix& rhs)
|
||||
{
|
||||
if (!mathEqual(lhs.e11, rhs.e11) || !mathEqual(lhs.e12, rhs.e12) || !mathEqual(lhs.e13, rhs.e13) ||
|
||||
!mathEqual(lhs.e21, rhs.e21) || !mathEqual(lhs.e22, rhs.e22) || !mathEqual(lhs.e23, rhs.e23) ||
|
||||
!mathEqual(lhs.e31, rhs.e31) || !mathEqual(lhs.e32, rhs.e32) || !mathEqual(lhs.e33, rhs.e33)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void mathMultiply(Point* pt, const Matrix* transform)
|
||||
void operator*=(Point& pt, const Matrix& m)
|
||||
{
|
||||
auto tx = pt->x * transform->e11 + pt->y * transform->e12 + transform->e13;
|
||||
auto ty = pt->x * transform->e21 + pt->y * transform->e22 + transform->e23;
|
||||
pt->x = tx;
|
||||
pt->y = ty;
|
||||
auto tx = pt.x * m.e11 + pt.y * m.e12 + m.e13;
|
||||
auto ty = pt.x * m.e21 + pt.y * m.e22 + m.e23;
|
||||
pt.x = tx;
|
||||
pt.y = ty;
|
||||
}
|
||||
|
|
|
@ -38,11 +38,9 @@
|
|||
#define mathMax(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
|
||||
bool mathInverse(const Matrix* m, Matrix* out);
|
||||
Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs);
|
||||
void mathRotate(Matrix* m, float degree);
|
||||
bool mathIdentity(const Matrix* m);
|
||||
void mathMultiply(Point* pt, const Matrix* transform);
|
||||
/************************************************************************/
|
||||
/* General functions */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
static inline float mathDeg2Rad(float degree)
|
||||
|
@ -63,28 +61,21 @@ static inline bool mathZero(float a)
|
|||
}
|
||||
|
||||
|
||||
static inline bool mathZero(const Point& p)
|
||||
{
|
||||
return mathZero(p.x) && mathZero(p.y);
|
||||
}
|
||||
|
||||
|
||||
static inline bool mathEqual(float a, float b)
|
||||
{
|
||||
return mathZero(a - b);
|
||||
}
|
||||
|
||||
|
||||
static inline bool mathEqual(const Matrix& a, const Matrix& b)
|
||||
{
|
||||
if (!mathEqual(a.e11, b.e11) || !mathEqual(a.e12, b.e12) || !mathEqual(a.e13, b.e13) ||
|
||||
!mathEqual(a.e21, b.e21) || !mathEqual(a.e22, b.e22) || !mathEqual(a.e23, b.e23) ||
|
||||
!mathEqual(a.e31, b.e31) || !mathEqual(a.e32, b.e32) || !mathEqual(a.e33, b.e33)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/************************************************************************/
|
||||
/* Matrix functions */
|
||||
/************************************************************************/
|
||||
|
||||
void mathRotate(Matrix* m, float degree);
|
||||
bool mathInverse(const Matrix* m, Matrix* out);
|
||||
bool mathIdentity(const Matrix* m);
|
||||
Matrix operator*(const Matrix& lhs, const Matrix& rhs);
|
||||
bool operator==(const Matrix& lhs, const Matrix& rhs);
|
||||
|
||||
static inline bool mathRightAngle(const Matrix* m)
|
||||
{
|
||||
|
@ -114,15 +105,6 @@ static inline void mathIdentity(Matrix* m)
|
|||
}
|
||||
|
||||
|
||||
static inline void mathTransform(Matrix* transform, Point* coord)
|
||||
{
|
||||
auto x = coord->x;
|
||||
auto y = coord->y;
|
||||
coord->x = x * transform->e11 + y * transform->e12 + transform->e13;
|
||||
coord->y = x * transform->e21 + y * transform->e22 + transform->e23;
|
||||
}
|
||||
|
||||
|
||||
static inline void mathScale(Matrix* m, float sx, float sy)
|
||||
{
|
||||
m->e11 *= sx;
|
||||
|
@ -158,12 +140,37 @@ static inline void mathTranslateR(Matrix* m, float x, float y)
|
|||
}
|
||||
|
||||
|
||||
static inline bool operator!=(const Matrix& lhs, const Matrix& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
static inline void operator*=(Matrix& lhs, const Matrix& rhs)
|
||||
{
|
||||
lhs = lhs * rhs;
|
||||
}
|
||||
|
||||
|
||||
static inline void mathLog(Matrix* m)
|
||||
{
|
||||
TVGLOG("MATH", "Matrix: [%f %f %f] [%f %f %f] [%f %f %f]", m->e11, m->e12, m->e13, m->e21, m->e22, m->e23, m->e31, m->e32, m->e33);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Point functions */
|
||||
/************************************************************************/
|
||||
|
||||
void operator*=(Point& pt, const Matrix& m);
|
||||
|
||||
|
||||
static inline bool mathZero(const Point& p)
|
||||
{
|
||||
return mathZero(p.x) && mathZero(p.y);
|
||||
}
|
||||
|
||||
|
||||
static inline float mathLength(const Point* a, const Point* b)
|
||||
{
|
||||
auto x = b->x - a->x;
|
||||
|
@ -182,6 +189,18 @@ static inline float mathLength(const Point& a)
|
|||
}
|
||||
|
||||
|
||||
static inline bool operator==(const Point& lhs, const Point& rhs)
|
||||
{
|
||||
return mathEqual(lhs.x, rhs.x) && mathEqual(lhs.y, rhs.y);
|
||||
}
|
||||
|
||||
|
||||
static inline bool operator!=(const Point& lhs, const Point& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
static inline Point operator-(const Point& lhs, const Point& rhs)
|
||||
{
|
||||
return {lhs.x - rhs.x, lhs.y - rhs.y};
|
||||
|
@ -212,6 +231,10 @@ static inline Point operator/(const Point& lhs, const float rhs)
|
|||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Interpolation functions */
|
||||
/************************************************************************/
|
||||
|
||||
template <typename T>
|
||||
static inline T mathLerp(const T &start, const T &end, float t)
|
||||
{
|
||||
|
|
|
@ -709,7 +709,7 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
|
|||
*ref = _idFromUrl((const char*)(str + 3));
|
||||
return true;
|
||||
} else if (len >= 10 && (str[0] == 'h' || str[0] == 'H') && (str[1] == 's' || str[1] == 'S') && (str[2] == 'l' || str[2] == 'L') && str[3] == '(' && str[len - 1] == ')') {
|
||||
float th, ts, tb;
|
||||
float_t th, ts, tb;
|
||||
const char *content, *hue, *satuation, *brightness;
|
||||
content = str + 4;
|
||||
content = _skipSpace(content, nullptr);
|
||||
|
@ -840,14 +840,14 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
|||
if (state == MatrixState::Matrix) {
|
||||
if (ptCount != 6) goto error;
|
||||
Matrix tmp = {points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1};
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else if (state == MatrixState::Translate) {
|
||||
if (ptCount == 1) {
|
||||
Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1};
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else if (ptCount == 2) {
|
||||
Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1};
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else goto error;
|
||||
} else if (state == MatrixState::Rotate) {
|
||||
//Transform to signed.
|
||||
|
@ -857,14 +857,14 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
|||
auto s = sinf(mathDeg2Rad(points[0]));
|
||||
if (ptCount == 1) {
|
||||
Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else if (ptCount == 3) {
|
||||
Matrix tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
@ -874,17 +874,17 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
|||
auto sy = sx;
|
||||
if (ptCount == 2) sy = points[1];
|
||||
Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else if (state == MatrixState::SkewX) {
|
||||
if (ptCount != 1) goto error;
|
||||
auto deg = tanf(mathDeg2Rad(points[0]));
|
||||
Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
} else if (state == MatrixState::SkewY) {
|
||||
if (ptCount != 1) goto error;
|
||||
auto deg = tanf(mathDeg2Rad(points[0]));
|
||||
Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 };
|
||||
*matrix = mathMultiply(matrix, &tmp);
|
||||
*matrix *= tmp;
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
|
|
|
@ -203,9 +203,9 @@ static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape*
|
|||
if (node->transform) finalTransform = *node->transform;
|
||||
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
||||
Matrix m = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
|
||||
finalTransform = mathMultiply(&finalTransform, &m);
|
||||
finalTransform *= m;
|
||||
}
|
||||
if (child->transform) finalTransform = mathMultiply(child->transform, &finalTransform);
|
||||
if (child->transform) finalTransform = *child->transform * finalTransform;
|
||||
|
||||
return _appendClipShape(loaderData, child, shape, vBox, svgPath, mathIdentity((const Matrix*)(&finalTransform)) ? nullptr : &finalTransform);
|
||||
}
|
||||
|
@ -228,13 +228,13 @@ static Matrix _compositionTransform(Paint* paint, const SvgNode* node, const Svg
|
|||
m = *node->transform;
|
||||
}
|
||||
if (compNode->transform) {
|
||||
m = mathMultiply(&m, compNode->transform);
|
||||
m *= *compNode->transform;
|
||||
}
|
||||
if (!compNode->node.clip.userSpace) {
|
||||
float x, y, w, h;
|
||||
P(paint)->bounds(&x, &y, &w, &h, false, false);
|
||||
Matrix mBBox = {w, 0, x, 0, h, y, 0, 0, 1};
|
||||
m = mathMultiply(&m, &mBBox);
|
||||
m *= mBBox;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
@ -474,7 +474,10 @@ static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* sh
|
|||
auto ptsCnt = shape->pathCoords(&pts);
|
||||
|
||||
auto p = const_cast<Point*>(pts) + currentPtsCnt;
|
||||
while (currentPtsCnt++ < ptsCnt) mathMultiply(p++, m);
|
||||
while (currentPtsCnt++ < ptsCnt) {
|
||||
*p *= *m;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
_applyProperty(loaderData, node, shape, vBox, svgPath, true);
|
||||
|
@ -505,6 +508,7 @@ static constexpr struct
|
|||
} imageMimeTypes[] = {
|
||||
{"jpeg", sizeof("jpeg"), imageMimeTypeEncoding::base64},
|
||||
{"png", sizeof("png"), imageMimeTypeEncoding::base64},
|
||||
{"webp", sizeof("webp"), imageMimeTypeEncoding::base64},
|
||||
{"svg+xml", sizeof("svg+xml"), imageMimeTypeEncoding::base64 | imageMimeTypeEncoding::utf8},
|
||||
};
|
||||
|
||||
|
@ -615,7 +619,7 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||
auto sy = node->node.image.h / h;
|
||||
m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
|
||||
}
|
||||
if (node->transform) m = mathMultiply(node->transform, &m);
|
||||
if (node->transform) m = *node->transform * m;
|
||||
picture->transform(m);
|
||||
|
||||
_applyComposition(loaderData, picture.get(), node, vBox, svgPath);
|
||||
|
@ -708,7 +712,7 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
|||
if (node->transform) mUseTransform = *node->transform;
|
||||
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
||||
Matrix mTranslate = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
|
||||
mUseTransform = mathMultiply(&mUseTransform, &mTranslate);
|
||||
mUseTransform *= mTranslate;
|
||||
}
|
||||
|
||||
if (node->node.use.symbol) {
|
||||
|
@ -732,9 +736,9 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
|||
// mSceneTransform = mUseTransform * mSymbolTransform * mViewBox
|
||||
Matrix mSceneTransform = mViewBox;
|
||||
if (node->node.use.symbol->transform) {
|
||||
mSceneTransform = mathMultiply(node->node.use.symbol->transform, &mViewBox);
|
||||
mSceneTransform = *node->node.use.symbol->transform * mViewBox;
|
||||
}
|
||||
mSceneTransform = mathMultiply(&mUseTransform, &mSceneTransform);
|
||||
mSceneTransform = mUseTransform * mSceneTransform;
|
||||
scene->transform(mSceneTransform);
|
||||
|
||||
if (node->node.use.symbol->node.symbol.overflowVisible) {
|
||||
|
@ -746,7 +750,7 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
|||
// mClipTransform = mUseTransform * mSymbolTransform
|
||||
Matrix mClipTransform = mUseTransform;
|
||||
if (node->node.use.symbol->transform) {
|
||||
mClipTransform = mathMultiply(&mUseTransform, node->node.use.symbol->transform);
|
||||
mClipTransform = mUseTransform * *node->node.use.symbol->transform;
|
||||
}
|
||||
viewBoxClip->transform(mClipTransform);
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr
|
|||
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
||||
|
||||
if (isTransformation) {
|
||||
if (transform) gradTransform = mathMultiply(transform, &gradTransform);
|
||||
if (transform) gradTransform = *transform * gradTransform;
|
||||
} else if (transform) {
|
||||
gradTransform = *transform;
|
||||
isTransformation = true;
|
||||
|
@ -216,7 +216,7 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix* tr
|
|||
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
||||
|
||||
if (transform) {
|
||||
if (isTransformation) gradTransform = mathMultiply(transform, &gradTransform);
|
||||
if (isTransformation) gradTransform = *transform * gradTransform;
|
||||
else {
|
||||
gradTransform = *transform;
|
||||
isTransformation = true;
|
||||
|
|
|
@ -81,7 +81,7 @@ SwMpool* mpoolInit(uint32_t threads)
|
|||
{
|
||||
auto allocSize = threads + 1;
|
||||
|
||||
auto mpool = static_cast<SwMpool*>(calloc(sizeof(SwMpool), 1));
|
||||
auto mpool = static_cast<SwMpool*>(calloc(1, sizeof(SwMpool)));
|
||||
mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||
mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||
mpool->dashOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||
|
|
|
@ -1108,7 +1108,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
|||
|
||||
float ys = FLT_MAX, ye = -1.0f;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (transform) mathMultiply(&vertices[i].pt, transform);
|
||||
if (transform) vertices[i].pt *= *transform;
|
||||
if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
|
||||
if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
|
||||
}
|
||||
|
@ -1169,9 +1169,9 @@ static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, c
|
|||
float ys = FLT_MAX, ye = -1.0f;
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
transformedTris[i] = mesh->triangles[i];
|
||||
mathMultiply(&transformedTris[i].vertex[0].pt, transform);
|
||||
mathMultiply(&transformedTris[i].vertex[1].pt, transform);
|
||||
mathMultiply(&transformedTris[i].vertex[2].pt, transform);
|
||||
transformedTris[i].vertex[0].pt *= *transform;
|
||||
transformedTris[i].vertex[1].pt *= *transform;
|
||||
transformedTris[i].vertex[2].pt *= *transform;
|
||||
|
||||
if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y;
|
||||
else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y;
|
||||
|
|
|
@ -78,7 +78,6 @@ struct SwShapeTask : SwTask
|
|||
{
|
||||
SwShape shape;
|
||||
const RenderShape* rshape = nullptr;
|
||||
bool cmpStroking = false;
|
||||
bool clipper = false;
|
||||
|
||||
/* We assume that if the stroke width is greater than 2,
|
||||
|
|
|
@ -928,7 +928,7 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren
|
|||
rw.cellYCnt = rw.cellMax.y - rw.cellMin.y;
|
||||
rw.ySpan = 0;
|
||||
rw.outline = const_cast<SwOutline*>(outline);
|
||||
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64
|
||||
rw.bandSize = rw.bufferSize / (sizeof(Cell) * 2); //bandSize: 256
|
||||
rw.bandShoot = 0;
|
||||
rw.antiAlias = antiAlias;
|
||||
|
||||
|
@ -966,10 +966,7 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren
|
|||
|
||||
if (cellMod > 0) cellStart += sizeof(Cell) - cellMod;
|
||||
|
||||
auto cellEnd = rw.bufferSize;
|
||||
cellEnd -= cellEnd % sizeof(Cell);
|
||||
|
||||
auto cellsMax = reinterpret_cast<Cell*>((char*)rw.buffer + cellEnd);
|
||||
auto cellsMax = reinterpret_cast<Cell*>((char*)rw.buffer + rw.bufferSize);
|
||||
rw.cells = reinterpret_cast<Cell*>((char*)rw.buffer + cellStart);
|
||||
|
||||
if (rw.cells >= cellsMax) goto reduce_bands;
|
||||
|
|
|
@ -107,7 +107,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans
|
|||
if (mathZero(len)) {
|
||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||
//draw the current line fully
|
||||
} else if (len < dash.curLen) {
|
||||
} else if (len <= dash.curLen) {
|
||||
dash.curLen -= len;
|
||||
if (!dash.curOpGap) {
|
||||
if (dash.move) {
|
||||
|
@ -168,7 +168,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
|
|||
//draw the current line fully
|
||||
if (mathZero(len)) {
|
||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||
} else if (len < dash.curLen) {
|
||||
} else if (len <= dash.curLen) {
|
||||
dash.curLen -= len;
|
||||
if (!dash.curOpGap) {
|
||||
if (dash.move) {
|
||||
|
@ -245,7 +245,86 @@ static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const
|
|||
}
|
||||
|
||||
|
||||
static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform, float length, SwMpool* mpool, unsigned tid)
|
||||
static void _trimPattern(SwDashStroke* dash, const RenderShape* rshape, float length)
|
||||
{
|
||||
auto begin = length * rshape->stroke->trim.begin;
|
||||
auto end = length * rshape->stroke->trim.end;
|
||||
|
||||
//default
|
||||
if (end > begin) {
|
||||
if (begin > 0.0f) dash->cnt = 4;
|
||||
else dash->cnt = 2;
|
||||
//looping
|
||||
} else dash->cnt = 3;
|
||||
|
||||
if (dash->cnt == 2) {
|
||||
dash->pattern[0] = end - begin;
|
||||
dash->pattern[1] = length - (end - begin);
|
||||
} else if (dash->cnt == 3) {
|
||||
dash->pattern[0] = end;
|
||||
dash->pattern[1] = (begin - end);
|
||||
dash->pattern[2] = length - begin;
|
||||
} else {
|
||||
dash->pattern[0] = 0; //zero dash to start with a space.
|
||||
dash->pattern[1] = begin;
|
||||
dash->pattern[2] = end - begin;
|
||||
dash->pattern[3] = length - end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static float _outlineLength(const RenderShape* rshape, uint32_t shiftPts, uint32_t shiftCmds, bool subpath)
|
||||
{
|
||||
const PathCommand* cmds = rshape->path.cmds.data + shiftCmds;
|
||||
auto cmdCnt = rshape->path.cmds.count - shiftCmds;
|
||||
const Point* pts = rshape->path.pts.data + shiftPts;
|
||||
auto ptsCnt = rshape->path.pts.count - shiftPts;
|
||||
|
||||
//No actual shape data
|
||||
if (cmdCnt <= 0 || ptsCnt <= 0) return 0.0f;
|
||||
|
||||
const Point* close = nullptr;
|
||||
auto length = 0.0f;
|
||||
|
||||
//must begin with moveTo
|
||||
if (cmds[0] == PathCommand::MoveTo) {
|
||||
close = pts;
|
||||
cmds++;
|
||||
pts++;
|
||||
cmdCnt--;
|
||||
}
|
||||
|
||||
while (cmdCnt-- > 0) {
|
||||
switch (*cmds) {
|
||||
case PathCommand::Close: {
|
||||
length += mathLength(pts - 1, close);
|
||||
if (subpath) return length;
|
||||
break;
|
||||
}
|
||||
case PathCommand::MoveTo: {
|
||||
if (subpath) return length;
|
||||
close = pts;
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
case PathCommand::LineTo: {
|
||||
length += mathLength(pts - 1, pts);
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
case PathCommand::CubicTo: {
|
||||
length += bezLength({*(pts - 1), *pts, *(pts + 1), *(pts + 2)});
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++cmds;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* transform, bool trimmed, SwMpool* mpool, unsigned tid)
|
||||
{
|
||||
const PathCommand* cmds = rshape->path.cmds.data;
|
||||
auto cmdCnt = rshape->path.cmds.count;
|
||||
|
@ -255,49 +334,23 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
//No actual shape data
|
||||
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
||||
|
||||
auto startPts = pts;
|
||||
auto startCmds = cmds;
|
||||
|
||||
SwDashStroke dash;
|
||||
auto offset = 0.0f;
|
||||
auto trimmed = false;
|
||||
|
||||
dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset);
|
||||
auto simultaneous = rshape->stroke->trim.simultaneous;
|
||||
|
||||
//dash by trimming.
|
||||
if (length > 0.0f && dash.cnt == 0) {
|
||||
auto begin = length * rshape->stroke->trim.begin;
|
||||
auto end = length * rshape->stroke->trim.end;
|
||||
|
||||
//TODO: mix trimming + dash style
|
||||
|
||||
//default
|
||||
if (end > begin) {
|
||||
if (begin > 0.0f) dash.cnt += 4;
|
||||
else dash.cnt += 2;
|
||||
//looping
|
||||
} else dash.cnt += 3;
|
||||
|
||||
dash.pattern = (float*)malloc(sizeof(float) * dash.cnt);
|
||||
|
||||
if (dash.cnt == 2) {
|
||||
dash.pattern[0] = end - begin;
|
||||
dash.pattern[1] = length - (end - begin);
|
||||
} else if (dash.cnt == 3) {
|
||||
dash.pattern[0] = end;
|
||||
dash.pattern[1] = (begin - end);
|
||||
dash.pattern[2] = length - begin;
|
||||
if (dash.cnt == 0) {
|
||||
if (trimmed) dash.pattern = (float*)malloc(sizeof(float) * 4);
|
||||
else return nullptr;
|
||||
} else {
|
||||
dash.pattern[0] = 0; //zero dash to start with a space.
|
||||
dash.pattern[1] = begin;
|
||||
dash.pattern[2] = end - begin;
|
||||
dash.pattern[3] = length - end;
|
||||
//TODO: handle dash + trim - for now trimming ignoring is forced
|
||||
trimmed = false;
|
||||
}
|
||||
|
||||
trimmed = true;
|
||||
//just a dasy style.
|
||||
} else {
|
||||
if (dash.cnt == 0) return nullptr;
|
||||
}
|
||||
|
||||
//offset?
|
||||
//offset
|
||||
auto patternLength = 0.0f;
|
||||
uint32_t offIdx = 0;
|
||||
if (!mathZero(offset)) {
|
||||
|
@ -319,6 +372,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
|
||||
//must begin with moveTo
|
||||
if (cmds[0] == PathCommand::MoveTo) {
|
||||
if (trimmed) _trimPattern(&dash, rshape, _outlineLength(rshape, 0, 0, simultaneous));
|
||||
_dashMoveTo(dash, offIdx, offset, pts);
|
||||
cmds++;
|
||||
pts++;
|
||||
|
@ -331,8 +385,12 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
break;
|
||||
}
|
||||
case PathCommand::MoveTo: {
|
||||
if (rshape->stroke->trim.individual) _dashMoveTo(dash, pts);
|
||||
else _dashMoveTo(dash, offIdx, offset, pts);
|
||||
if (trimmed) {
|
||||
if (simultaneous) {
|
||||
_trimPattern(&dash, rshape, _outlineLength(rshape, pts - startPts, cmds - startCmds, true));
|
||||
_dashMoveTo(dash, offIdx, offset, pts);
|
||||
} else _dashMoveTo(dash, pts);
|
||||
} else _dashMoveTo(dash, offIdx, offset, pts);
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
|
@ -358,56 +416,6 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
}
|
||||
|
||||
|
||||
static float _outlineLength(const RenderShape* rshape)
|
||||
{
|
||||
const PathCommand* cmds = rshape->path.cmds.data;
|
||||
auto cmdCnt = rshape->path.cmds.count;
|
||||
const Point* pts = rshape->path.pts.data;
|
||||
auto ptsCnt = rshape->path.pts.count;
|
||||
|
||||
//No actual shape data
|
||||
if (cmdCnt == 0 || ptsCnt == 0) return 0.0f;
|
||||
|
||||
const Point* close = nullptr;
|
||||
auto length = 0.0f;
|
||||
auto slength = -1.0f;
|
||||
auto simultaneous = !rshape->stroke->trim.individual;
|
||||
|
||||
//Compute the whole length
|
||||
while (cmdCnt-- > 0) {
|
||||
switch (*cmds) {
|
||||
case PathCommand::Close: {
|
||||
length += mathLength(pts - 1, close);
|
||||
//retrieve the max length of the shape if the simultaneous mode.
|
||||
if (simultaneous) {
|
||||
if (slength < length) slength = length;
|
||||
length = 0.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PathCommand::MoveTo: {
|
||||
close = pts;
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
case PathCommand::LineTo: {
|
||||
length += mathLength(pts - 1, pts);
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
case PathCommand::CubicTo: {
|
||||
length += bezLength({*(pts - 1), *pts, *(pts + 1), *(pts + 2)});
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++cmds;
|
||||
}
|
||||
if (simultaneous && slength > length) return slength;
|
||||
else return length;
|
||||
}
|
||||
|
||||
|
||||
static bool _axisAlignedRect(const SwOutline* outline)
|
||||
{
|
||||
//Fast Track: axis-aligned rectangle?
|
||||
|
@ -584,11 +592,10 @@ bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix*
|
|||
auto dashStroking = false;
|
||||
auto ret = true;
|
||||
|
||||
auto length = rshape->strokeTrim() ? _outlineLength(rshape) : 0.0f;
|
||||
|
||||
//Dash style (+trimming)
|
||||
if (rshape->stroke->dashCnt > 0 || length > 0) {
|
||||
shapeOutline = _genDashOutline(rshape, transform, length, mpool, tid);
|
||||
auto trimmed = rshape->strokeTrim();
|
||||
if (rshape->stroke->dashCnt > 0 || trimmed) {
|
||||
shapeOutline = _genDashOutline(rshape, transform, trimmed, mpool, tid);
|
||||
if (!shapeOutline) return false;
|
||||
dashStroking = true;
|
||||
//Normal style
|
||||
|
|
|
@ -75,13 +75,13 @@ static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform
|
|||
auto v2 = *pt3;
|
||||
|
||||
if (rTransform) {
|
||||
mathMultiply(&v1, &rTransform->m);
|
||||
mathMultiply(&v2, &rTransform->m);
|
||||
v1 *= rTransform->m;
|
||||
v2 *= rTransform->m;
|
||||
}
|
||||
|
||||
if (pTransform) {
|
||||
mathMultiply(&v1, &pTransform->m);
|
||||
mathMultiply(&v2, &pTransform->m);
|
||||
v1 *= pTransform->m;
|
||||
v2 *= pTransform->m;
|
||||
}
|
||||
|
||||
//sorting
|
||||
|
@ -327,7 +327,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme
|
|||
|
||||
//Compute the AABB after transformation
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mathMultiply(&pt[i], m);
|
||||
pt[i] *= *m;
|
||||
|
||||
if (pt[i].x < x1) x1 = pt[i].x;
|
||||
if (pt[i].x > x2) x2 = pt[i].x;
|
||||
|
|
|
@ -47,7 +47,7 @@ void RenderTransform::update()
|
|||
|
||||
mathScale(&m, scale, scale);
|
||||
|
||||
if (!mathZero(degree)) mathRotate(&m, degree);
|
||||
mathRotate(&m, degree);
|
||||
|
||||
mathTranslate(&m, x, y);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void RenderTransform::update()
|
|||
|
||||
RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs)
|
||||
{
|
||||
if (lhs && rhs) m = mathMultiply(&lhs->m, &rhs->m);
|
||||
if (lhs && rhs) m = lhs->m * rhs->m;
|
||||
else if (lhs) m = lhs->m;
|
||||
else if (rhs) m = rhs->m;
|
||||
else mathIdentity(&m);
|
||||
|
|
|
@ -142,7 +142,7 @@ struct RenderStroke
|
|||
struct {
|
||||
float begin = 0.0f;
|
||||
float end = 1.0f;
|
||||
bool individual = false;
|
||||
bool simultaneous = true;
|
||||
} trim;
|
||||
|
||||
~RenderStroke()
|
||||
|
|
|
@ -287,16 +287,14 @@ const Fill* Shape::fill() const noexcept
|
|||
|
||||
Result Shape::order(bool strokeFirst) noexcept
|
||||
{
|
||||
if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeFirst(strokeFirst);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
Result Shape::stroke(float width) noexcept
|
||||
{
|
||||
if (!pImpl->strokeWidth(width)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeWidth(width);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
@ -309,8 +307,7 @@ float Shape::strokeWidth() const noexcept
|
|||
|
||||
Result Shape::stroke(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
|
||||
{
|
||||
if (!pImpl->strokeColor(r, g, b, a)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeColor(r, g, b, a);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
@ -349,27 +346,25 @@ uint32_t Shape::strokeDash(const float** dashPattern) const noexcept
|
|||
|
||||
Result Shape::stroke(StrokeCap cap) noexcept
|
||||
{
|
||||
if (!pImpl->strokeCap(cap)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeCap(cap);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
Result Shape::stroke(StrokeJoin join) noexcept
|
||||
{
|
||||
if (!pImpl->strokeJoin(join)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeJoin(join);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
Result Shape::strokeMiterlimit(float miterlimit) noexcept
|
||||
{
|
||||
// https://www.w3.org/TR/SVG2/painting.html#LineJoin
|
||||
// - A negative value for stroke-miterlimit must be treated as an illegal value.
|
||||
if (miterlimit < 0.0f) return Result::NonSupport;
|
||||
if (miterlimit < 0.0f) return Result::InvalidArguments;
|
||||
// TODO Find out a reasonable max value.
|
||||
if (!pImpl->strokeMiterlimit(miterlimit)) return Result::FailedAllocation;
|
||||
|
||||
pImpl->strokeMiterlimit(miterlimit);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
@ -385,12 +380,26 @@ StrokeJoin Shape::strokeJoin() const noexcept
|
|||
return pImpl->rs.strokeJoin();
|
||||
}
|
||||
|
||||
|
||||
float Shape::strokeMiterlimit() const noexcept
|
||||
{
|
||||
return pImpl->rs.strokeMiterlimit();
|
||||
}
|
||||
|
||||
|
||||
Result Shape::strokeTrim(float begin, float end, bool simultaneous) noexcept
|
||||
{
|
||||
pImpl->strokeTrim(begin, end, simultaneous);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
bool Shape::strokeTrim(float* begin, float* end) const noexcept
|
||||
{
|
||||
return pImpl->strokeTrim(begin, end);
|
||||
}
|
||||
|
||||
|
||||
Result Shape::fill(FillRule r) noexcept
|
||||
{
|
||||
pImpl->rs.rule = r;
|
||||
|
|
|
@ -207,60 +207,81 @@ struct Shape::Impl
|
|||
flag |= RenderUpdateFlag::Path;
|
||||
}
|
||||
|
||||
bool strokeWidth(float width)
|
||||
void strokeWidth(float width)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->width = width;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strokeTrim(float begin, float end, bool individual)
|
||||
void strokeTrim(float begin, float end, bool simultaneous)
|
||||
{
|
||||
if (!rs.stroke) {
|
||||
if (begin == 0.0f && end == 1.0f) return true;
|
||||
if (begin == 0.0f && end == 1.0f) return;
|
||||
rs.stroke = new RenderStroke();
|
||||
}
|
||||
|
||||
if (mathEqual(rs.stroke->trim.begin, begin) && mathEqual(rs.stroke->trim.end, end)) return true;
|
||||
if (mathEqual(rs.stroke->trim.begin, begin) && mathEqual(rs.stroke->trim.end, end) &&
|
||||
rs.stroke->trim.simultaneous == simultaneous) return;
|
||||
|
||||
auto loop = true;
|
||||
|
||||
if (begin > 1.0f && end > 1.0f) loop = false;
|
||||
if (begin < 0.0f && end < 0.0f) loop = false;
|
||||
if (begin >= 0.0f && begin <= 1.0f && end >= 0.0f && end <= 1.0f) loop = false;
|
||||
|
||||
if (begin > 1.0f) begin -= 1.0f;
|
||||
if (begin < 0.0f) begin += 1.0f;
|
||||
if (end > 1.0f) end -= 1.0f;
|
||||
if (end < 0.0f) end += 1.0f;
|
||||
|
||||
if ((loop && begin < end) || (!loop && begin > end)) {
|
||||
auto tmp = begin;
|
||||
begin = end;
|
||||
end = tmp;
|
||||
}
|
||||
|
||||
rs.stroke->trim.begin = begin;
|
||||
rs.stroke->trim.end = end;
|
||||
rs.stroke->trim.individual = individual;
|
||||
rs.stroke->trim.simultaneous = simultaneous;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strokeCap(StrokeCap cap)
|
||||
bool strokeTrim(float* begin, float* end)
|
||||
{
|
||||
if (rs.stroke) {
|
||||
if (begin) *begin = rs.stroke->trim.begin;
|
||||
if (end) *end = rs.stroke->trim.end;
|
||||
return rs.stroke->trim.simultaneous;
|
||||
} else {
|
||||
if (begin) *begin = 0.0f;
|
||||
if (end) *end = 1.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void strokeCap(StrokeCap cap)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->cap = cap;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strokeJoin(StrokeJoin join)
|
||||
void strokeJoin(StrokeJoin join)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->join = join;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strokeMiterlimit(float miterlimit)
|
||||
void strokeMiterlimit(float miterlimit)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->miterlimit = miterlimit;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
void strokeColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
if (rs.stroke->fill) {
|
||||
|
@ -275,8 +296,6 @@ struct Shape::Impl
|
|||
rs.stroke->color[3] = a;
|
||||
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Result strokeFill(unique_ptr<Fill> f)
|
||||
|
@ -335,13 +354,11 @@ struct Shape::Impl
|
|||
return rs.stroke->strokeFirst;
|
||||
}
|
||||
|
||||
bool strokeFirst(bool strokeFirst)
|
||||
void strokeFirst(bool strokeFirst)
|
||||
{
|
||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||
rs.stroke->strokeFirst = strokeFirst;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void update(RenderUpdateFlag flag)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
VERSION=0.13.5
|
||||
VERSION=0.13.7
|
||||
|
||||
cd thirdparty/thorvg/ || true
|
||||
rm -rf AUTHORS LICENSE inc/ src/ *.zip *.tar.gz tmp/
|
||||
|
|
Loading…
Reference in New Issue