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
|
## thorvg
|
||||||
|
|
||||||
- Upstream: https://github.com/thorvg/thorvg
|
- Upstream: https://github.com/thorvg/thorvg
|
||||||
- Version: 0.13.3 (6235068cad8cad176ccd0cbcf82f25e985fbc258, 2024)
|
- Version: 0.13.7 (d2c0428a99f7305c086caffe0c730add601ebd6e, 2024)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
// For internal debugging:
|
// For internal debugging:
|
||||||
//#define THORVG_LOG_ENABLED
|
//#define THORVG_LOG_ENABLED
|
||||||
|
|
||||||
#define THORVG_VERSION_STRING "0.13.5"
|
#define THORVG_VERSION_STRING "0.13.7"
|
||||||
#endif
|
#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.
|
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.
|
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
|
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.
|
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.
|
* @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;
|
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] 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.
|
* @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;
|
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.
|
* @param[in] f The gradient fill.
|
||||||
*
|
*
|
||||||
* @retval Result::Success When succeed.
|
* @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 or an error with accessing it.
|
||||||
* @retval Result::MemoryCorruption In case a @c nullptr is passed as the argument.
|
|
||||||
*/
|
*/
|
||||||
Result stroke(std::unique_ptr<Fill> f) noexcept;
|
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.
|
* @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;
|
Result stroke(StrokeCap cap) noexcept;
|
||||||
|
|
||||||
|
@ -1040,22 +1039,37 @@ public:
|
||||||
*
|
*
|
||||||
* @param[in] join The join style value. The default value is @c StrokeJoin::Bevel.
|
* @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;
|
Result stroke(StrokeJoin join) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the stroke miterlimit.
|
* @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.
|
* @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
|
* @since 0.11
|
||||||
*/
|
*/
|
||||||
Result strokeMiterlimit(float miterlimit) noexcept;
|
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.
|
* @brief Sets the solid color for all of the figures from the path.
|
||||||
*
|
*
|
||||||
|
@ -1095,19 +1109,17 @@ public:
|
||||||
*/
|
*/
|
||||||
Result fill(FillRule r) noexcept;
|
Result fill(FillRule r) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the rendering order of the stroke and the fill.
|
* @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).
|
* @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
|
* @since 0.10
|
||||||
*/
|
*/
|
||||||
Result order(bool strokeFirst) noexcept;
|
Result order(bool strokeFirst) noexcept;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the commands data of the path.
|
* @brief Gets the commands data of the path.
|
||||||
*
|
*
|
||||||
|
@ -1210,6 +1222,18 @@ public:
|
||||||
*/
|
*/
|
||||||
float strokeMiterlimit() const noexcept;
|
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.
|
* @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* 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);
|
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);
|
size_t b64Decode(const char* encoded, const size_t len, char** decoded);
|
||||||
|
unsigned long djb2Encode(const char* str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //_TVG_COMPRESSOR_H_
|
#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;
|
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.e11 = lhs->e11 * rhs->e11 + lhs->e12 * rhs->e21 + lhs->e13 * rhs->e31;
|
m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) {
|
||||||
m.e12 = lhs->e11 * rhs->e12 + lhs->e12 * rhs->e22 + lhs->e13 * rhs->e32;
|
return false;
|
||||||
m.e13 = lhs->e11 * rhs->e13 + lhs->e12 * rhs->e23 + lhs->e13 * rhs->e33;
|
}
|
||||||
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 ||
|
Matrix m;
|
||||||
m->e21 != 0.0f || m->e22 != 1.0f || m->e23 != 0.0f ||
|
|
||||||
m->e31 != 0.0f || m->e32 != 0.0f || m->e33 != 1.0f) {
|
m.e11 = lhs.e11 * rhs.e11 + lhs.e12 * rhs.e21 + lhs.e13 * rhs.e31;
|
||||||
return false;
|
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;
|
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 tx = pt.x * m.e11 + pt.y * m.e12 + m.e13;
|
||||||
auto ty = pt->x * transform->e21 + pt->y * transform->e22 + transform->e23;
|
auto ty = pt.x * m.e21 + pt.y * m.e22 + m.e23;
|
||||||
pt->x = tx;
|
pt.x = tx;
|
||||||
pt->y = ty;
|
pt.y = ty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,9 @@
|
||||||
#define mathMax(x, y) (((x) > (y)) ? (x) : (y))
|
#define mathMax(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
|
|
||||||
|
|
||||||
bool mathInverse(const Matrix* m, Matrix* out);
|
/************************************************************************/
|
||||||
Matrix mathMultiply(const Matrix* lhs, const Matrix* rhs);
|
/* General functions */
|
||||||
void mathRotate(Matrix* m, float degree);
|
/************************************************************************/
|
||||||
bool mathIdentity(const Matrix* m);
|
|
||||||
void mathMultiply(Point* pt, const Matrix* transform);
|
|
||||||
|
|
||||||
|
|
||||||
static inline float mathDeg2Rad(float degree)
|
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)
|
static inline bool mathEqual(float a, float b)
|
||||||
{
|
{
|
||||||
return mathZero(a - b);
|
return mathZero(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool mathEqual(const Matrix& a, const Matrix& b)
|
/************************************************************************/
|
||||||
{
|
/* Matrix functions */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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)
|
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)
|
static inline void mathScale(Matrix* m, float sx, float sy)
|
||||||
{
|
{
|
||||||
m->e11 *= sx;
|
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)
|
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);
|
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)
|
static inline float mathLength(const Point* a, const Point* b)
|
||||||
{
|
{
|
||||||
auto x = b->x - a->x;
|
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)
|
static inline Point operator-(const Point& lhs, const Point& rhs)
|
||||||
{
|
{
|
||||||
return {lhs.x - rhs.x, lhs.y - rhs.y};
|
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>
|
template <typename T>
|
||||||
static inline T mathLerp(const T &start, const T &end, float 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));
|
*ref = _idFromUrl((const char*)(str + 3));
|
||||||
return true;
|
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] == ')') {
|
} 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;
|
const char *content, *hue, *satuation, *brightness;
|
||||||
content = str + 4;
|
content = str + 4;
|
||||||
content = _skipSpace(content, nullptr);
|
content = _skipSpace(content, nullptr);
|
||||||
|
@ -840,14 +840,14 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
||||||
if (state == MatrixState::Matrix) {
|
if (state == MatrixState::Matrix) {
|
||||||
if (ptCount != 6) goto error;
|
if (ptCount != 6) goto error;
|
||||||
Matrix tmp = {points[0], points[2], points[4], points[1], points[3], points[5], 0, 0, 1};
|
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) {
|
} else if (state == MatrixState::Translate) {
|
||||||
if (ptCount == 1) {
|
if (ptCount == 1) {
|
||||||
Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1};
|
Matrix tmp = {1, 0, points[0], 0, 1, 0, 0, 0, 1};
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else if (ptCount == 2) {
|
} else if (ptCount == 2) {
|
||||||
Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1};
|
Matrix tmp = {1, 0, points[0], 0, 1, points[1], 0, 0, 1};
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else goto error;
|
} else goto error;
|
||||||
} else if (state == MatrixState::Rotate) {
|
} else if (state == MatrixState::Rotate) {
|
||||||
//Transform to signed.
|
//Transform to signed.
|
||||||
|
@ -857,14 +857,14 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
||||||
auto s = sinf(mathDeg2Rad(points[0]));
|
auto s = sinf(mathDeg2Rad(points[0]));
|
||||||
if (ptCount == 1) {
|
if (ptCount == 1) {
|
||||||
Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
|
Matrix tmp = { c, -s, 0, s, c, 0, 0, 0, 1 };
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else if (ptCount == 3) {
|
} else if (ptCount == 3) {
|
||||||
Matrix tmp = { 1, 0, points[1], 0, 1, points[2], 0, 0, 1 };
|
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 };
|
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 };
|
tmp = { 1, 0, -points[1], 0, 1, -points[2], 0, 0, 1 };
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else {
|
} else {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -874,17 +874,17 @@ static Matrix* _parseTransformationMatrix(const char* value)
|
||||||
auto sy = sx;
|
auto sy = sx;
|
||||||
if (ptCount == 2) sy = points[1];
|
if (ptCount == 2) sy = points[1];
|
||||||
Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
|
Matrix tmp = { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else if (state == MatrixState::SkewX) {
|
} else if (state == MatrixState::SkewX) {
|
||||||
if (ptCount != 1) goto error;
|
if (ptCount != 1) goto error;
|
||||||
auto deg = tanf(mathDeg2Rad(points[0]));
|
auto deg = tanf(mathDeg2Rad(points[0]));
|
||||||
Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 };
|
Matrix tmp = { 1, deg, 0, 0, 1, 0, 0, 0, 1 };
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
} else if (state == MatrixState::SkewY) {
|
} else if (state == MatrixState::SkewY) {
|
||||||
if (ptCount != 1) goto error;
|
if (ptCount != 1) goto error;
|
||||||
auto deg = tanf(mathDeg2Rad(points[0]));
|
auto deg = tanf(mathDeg2Rad(points[0]));
|
||||||
Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 };
|
Matrix tmp = { 1, 0, 0, deg, 1, 0, 0, 0, 1 };
|
||||||
*matrix = mathMultiply(matrix, &tmp);
|
*matrix *= tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matrix;
|
return matrix;
|
||||||
|
|
|
@ -203,9 +203,9 @@ static bool _appendClipUseNode(SvgLoaderData& loaderData, SvgNode* node, Shape*
|
||||||
if (node->transform) finalTransform = *node->transform;
|
if (node->transform) finalTransform = *node->transform;
|
||||||
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
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};
|
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);
|
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;
|
m = *node->transform;
|
||||||
}
|
}
|
||||||
if (compNode->transform) {
|
if (compNode->transform) {
|
||||||
m = mathMultiply(&m, compNode->transform);
|
m *= *compNode->transform;
|
||||||
}
|
}
|
||||||
if (!compNode->node.clip.userSpace) {
|
if (!compNode->node.clip.userSpace) {
|
||||||
float x, y, w, h;
|
float x, y, w, h;
|
||||||
P(paint)->bounds(&x, &y, &w, &h, false, false);
|
P(paint)->bounds(&x, &y, &w, &h, false, false);
|
||||||
Matrix mBBox = {w, 0, x, 0, h, y, 0, 0, 1};
|
Matrix mBBox = {w, 0, x, 0, h, y, 0, 0, 1};
|
||||||
m = mathMultiply(&m, &mBBox);
|
m *= mBBox;
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,10 @@ static bool _appendClipShape(SvgLoaderData& loaderData, SvgNode* node, Shape* sh
|
||||||
auto ptsCnt = shape->pathCoords(&pts);
|
auto ptsCnt = shape->pathCoords(&pts);
|
||||||
|
|
||||||
auto p = const_cast<Point*>(pts) + currentPtsCnt;
|
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);
|
_applyProperty(loaderData, node, shape, vBox, svgPath, true);
|
||||||
|
@ -505,6 +508,7 @@ static constexpr struct
|
||||||
} imageMimeTypes[] = {
|
} imageMimeTypes[] = {
|
||||||
{"jpeg", sizeof("jpeg"), imageMimeTypeEncoding::base64},
|
{"jpeg", sizeof("jpeg"), imageMimeTypeEncoding::base64},
|
||||||
{"png", sizeof("png"), imageMimeTypeEncoding::base64},
|
{"png", sizeof("png"), imageMimeTypeEncoding::base64},
|
||||||
|
{"webp", sizeof("webp"), imageMimeTypeEncoding::base64},
|
||||||
{"svg+xml", sizeof("svg+xml"), imageMimeTypeEncoding::base64 | imageMimeTypeEncoding::utf8},
|
{"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;
|
auto sy = node->node.image.h / h;
|
||||||
m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
|
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);
|
picture->transform(m);
|
||||||
|
|
||||||
_applyComposition(loaderData, picture.get(), node, vBox, svgPath);
|
_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->transform) mUseTransform = *node->transform;
|
||||||
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
|
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};
|
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) {
|
if (node->node.use.symbol) {
|
||||||
|
@ -732,9 +736,9 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
||||||
// mSceneTransform = mUseTransform * mSymbolTransform * mViewBox
|
// mSceneTransform = mUseTransform * mSymbolTransform * mViewBox
|
||||||
Matrix mSceneTransform = mViewBox;
|
Matrix mSceneTransform = mViewBox;
|
||||||
if (node->node.use.symbol->transform) {
|
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);
|
scene->transform(mSceneTransform);
|
||||||
|
|
||||||
if (node->node.use.symbol->node.symbol.overflowVisible) {
|
if (node->node.use.symbol->node.symbol.overflowVisible) {
|
||||||
|
@ -746,7 +750,7 @@ static unique_ptr<Scene> _useBuildHelper(SvgLoaderData& loaderData, const SvgNod
|
||||||
// mClipTransform = mUseTransform * mSymbolTransform
|
// mClipTransform = mUseTransform * mSymbolTransform
|
||||||
Matrix mClipTransform = mUseTransform;
|
Matrix mClipTransform = mUseTransform;
|
||||||
if (node->node.use.symbol->transform) {
|
if (node->node.use.symbol->transform) {
|
||||||
mClipTransform = mathMultiply(&mUseTransform, node->node.use.symbol->transform);
|
mClipTransform = mUseTransform * *node->node.use.symbol->transform;
|
||||||
}
|
}
|
||||||
viewBoxClip->transform(mClipTransform);
|
viewBoxClip->transform(mClipTransform);
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ bool _prepareLinear(SwFill* fill, const LinearGradient* linear, const Matrix* tr
|
||||||
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
||||||
|
|
||||||
if (isTransformation) {
|
if (isTransformation) {
|
||||||
if (transform) gradTransform = mathMultiply(transform, &gradTransform);
|
if (transform) gradTransform = *transform * gradTransform;
|
||||||
} else if (transform) {
|
} else if (transform) {
|
||||||
gradTransform = *transform;
|
gradTransform = *transform;
|
||||||
isTransformation = true;
|
isTransformation = true;
|
||||||
|
@ -216,7 +216,7 @@ bool _prepareRadial(SwFill* fill, const RadialGradient* radial, const Matrix* tr
|
||||||
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
bool isTransformation = !mathIdentity((const Matrix*)(&gradTransform));
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (isTransformation) gradTransform = mathMultiply(transform, &gradTransform);
|
if (isTransformation) gradTransform = *transform * gradTransform;
|
||||||
else {
|
else {
|
||||||
gradTransform = *transform;
|
gradTransform = *transform;
|
||||||
isTransformation = true;
|
isTransformation = true;
|
||||||
|
|
|
@ -81,7 +81,7 @@ SwMpool* mpoolInit(uint32_t threads)
|
||||||
{
|
{
|
||||||
auto allocSize = threads + 1;
|
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->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * allocSize));
|
||||||
mpool->strokeOutline = 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));
|
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;
|
float ys = FLT_MAX, ye = -1.0f;
|
||||||
for (int i = 0; i < 4; i++) {
|
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 < ys) ys = vertices[i].pt.y;
|
||||||
if (vertices[i].pt.y > ye) ye = 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;
|
float ys = FLT_MAX, ye = -1.0f;
|
||||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||||
transformedTris[i] = mesh->triangles[i];
|
transformedTris[i] = mesh->triangles[i];
|
||||||
mathMultiply(&transformedTris[i].vertex[0].pt, transform);
|
transformedTris[i].vertex[0].pt *= *transform;
|
||||||
mathMultiply(&transformedTris[i].vertex[1].pt, transform);
|
transformedTris[i].vertex[1].pt *= *transform;
|
||||||
mathMultiply(&transformedTris[i].vertex[2].pt, transform);
|
transformedTris[i].vertex[2].pt *= *transform;
|
||||||
|
|
||||||
if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y;
|
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;
|
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;
|
SwShape shape;
|
||||||
const RenderShape* rshape = nullptr;
|
const RenderShape* rshape = nullptr;
|
||||||
bool cmpStroking = false;
|
|
||||||
bool clipper = false;
|
bool clipper = false;
|
||||||
|
|
||||||
/* We assume that if the stroke width is greater than 2,
|
/* 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.cellYCnt = rw.cellMax.y - rw.cellMin.y;
|
||||||
rw.ySpan = 0;
|
rw.ySpan = 0;
|
||||||
rw.outline = const_cast<SwOutline*>(outline);
|
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.bandShoot = 0;
|
||||||
rw.antiAlias = antiAlias;
|
rw.antiAlias = antiAlias;
|
||||||
|
|
||||||
|
@ -966,10 +966,7 @@ SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& ren
|
||||||
|
|
||||||
if (cellMod > 0) cellStart += sizeof(Cell) - cellMod;
|
if (cellMod > 0) cellStart += sizeof(Cell) - cellMod;
|
||||||
|
|
||||||
auto cellEnd = rw.bufferSize;
|
auto cellsMax = reinterpret_cast<Cell*>((char*)rw.buffer + rw.bufferSize);
|
||||||
cellEnd -= cellEnd % sizeof(Cell);
|
|
||||||
|
|
||||||
auto cellsMax = reinterpret_cast<Cell*>((char*)rw.buffer + cellEnd);
|
|
||||||
rw.cells = reinterpret_cast<Cell*>((char*)rw.buffer + cellStart);
|
rw.cells = reinterpret_cast<Cell*>((char*)rw.buffer + cellStart);
|
||||||
|
|
||||||
if (rw.cells >= cellsMax) goto reduce_bands;
|
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)) {
|
if (mathZero(len)) {
|
||||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||||
//draw the current line fully
|
//draw the current line fully
|
||||||
} else if (len < dash.curLen) {
|
} else if (len <= dash.curLen) {
|
||||||
dash.curLen -= len;
|
dash.curLen -= len;
|
||||||
if (!dash.curOpGap) {
|
if (!dash.curOpGap) {
|
||||||
if (dash.move) {
|
if (dash.move) {
|
||||||
|
@ -168,7 +168,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
|
||||||
//draw the current line fully
|
//draw the current line fully
|
||||||
if (mathZero(len)) {
|
if (mathZero(len)) {
|
||||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||||
} else if (len < dash.curLen) {
|
} else if (len <= dash.curLen) {
|
||||||
dash.curLen -= len;
|
dash.curLen -= len;
|
||||||
if (!dash.curOpGap) {
|
if (!dash.curOpGap) {
|
||||||
if (dash.move) {
|
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;
|
const PathCommand* cmds = rshape->path.cmds.data;
|
||||||
auto cmdCnt = rshape->path.cmds.count;
|
auto cmdCnt = rshape->path.cmds.count;
|
||||||
|
@ -255,49 +334,23 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
||||||
//No actual shape data
|
//No actual shape data
|
||||||
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
||||||
|
|
||||||
|
auto startPts = pts;
|
||||||
|
auto startCmds = cmds;
|
||||||
|
|
||||||
SwDashStroke dash;
|
SwDashStroke dash;
|
||||||
auto offset = 0.0f;
|
auto offset = 0.0f;
|
||||||
auto trimmed = false;
|
|
||||||
|
|
||||||
dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset);
|
dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset);
|
||||||
|
auto simultaneous = rshape->stroke->trim.simultaneous;
|
||||||
|
|
||||||
//dash by trimming.
|
if (dash.cnt == 0) {
|
||||||
if (length > 0.0f && dash.cnt == 0) {
|
if (trimmed) dash.pattern = (float*)malloc(sizeof(float) * 4);
|
||||||
auto begin = length * rshape->stroke->trim.begin;
|
else return nullptr;
|
||||||
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;
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
trimmed = true;
|
|
||||||
//just a dasy style.
|
|
||||||
} else {
|
} else {
|
||||||
if (dash.cnt == 0) return nullptr;
|
//TODO: handle dash + trim - for now trimming ignoring is forced
|
||||||
|
trimmed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//offset?
|
//offset
|
||||||
auto patternLength = 0.0f;
|
auto patternLength = 0.0f;
|
||||||
uint32_t offIdx = 0;
|
uint32_t offIdx = 0;
|
||||||
if (!mathZero(offset)) {
|
if (!mathZero(offset)) {
|
||||||
|
@ -319,6 +372,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
||||||
|
|
||||||
//must begin with moveTo
|
//must begin with moveTo
|
||||||
if (cmds[0] == PathCommand::MoveTo) {
|
if (cmds[0] == PathCommand::MoveTo) {
|
||||||
|
if (trimmed) _trimPattern(&dash, rshape, _outlineLength(rshape, 0, 0, simultaneous));
|
||||||
_dashMoveTo(dash, offIdx, offset, pts);
|
_dashMoveTo(dash, offIdx, offset, pts);
|
||||||
cmds++;
|
cmds++;
|
||||||
pts++;
|
pts++;
|
||||||
|
@ -331,8 +385,12 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::MoveTo: {
|
case PathCommand::MoveTo: {
|
||||||
if (rshape->stroke->trim.individual) _dashMoveTo(dash, pts);
|
if (trimmed) {
|
||||||
else _dashMoveTo(dash, offIdx, offset, pts);
|
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;
|
++pts;
|
||||||
break;
|
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)
|
static bool _axisAlignedRect(const SwOutline* outline)
|
||||||
{
|
{
|
||||||
//Fast Track: axis-aligned rectangle?
|
//Fast Track: axis-aligned rectangle?
|
||||||
|
@ -584,11 +592,10 @@ bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix*
|
||||||
auto dashStroking = false;
|
auto dashStroking = false;
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
|
|
||||||
auto length = rshape->strokeTrim() ? _outlineLength(rshape) : 0.0f;
|
|
||||||
|
|
||||||
//Dash style (+trimming)
|
//Dash style (+trimming)
|
||||||
if (rshape->stroke->dashCnt > 0 || length > 0) {
|
auto trimmed = rshape->strokeTrim();
|
||||||
shapeOutline = _genDashOutline(rshape, transform, length, mpool, tid);
|
if (rshape->stroke->dashCnt > 0 || trimmed) {
|
||||||
|
shapeOutline = _genDashOutline(rshape, transform, trimmed, mpool, tid);
|
||||||
if (!shapeOutline) return false;
|
if (!shapeOutline) return false;
|
||||||
dashStroking = true;
|
dashStroking = true;
|
||||||
//Normal style
|
//Normal style
|
||||||
|
|
|
@ -75,13 +75,13 @@ static Result _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform
|
||||||
auto v2 = *pt3;
|
auto v2 = *pt3;
|
||||||
|
|
||||||
if (rTransform) {
|
if (rTransform) {
|
||||||
mathMultiply(&v1, &rTransform->m);
|
v1 *= rTransform->m;
|
||||||
mathMultiply(&v2, &rTransform->m);
|
v2 *= rTransform->m;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pTransform) {
|
if (pTransform) {
|
||||||
mathMultiply(&v1, &pTransform->m);
|
v1 *= pTransform->m;
|
||||||
mathMultiply(&v2, &pTransform->m);
|
v2 *= pTransform->m;
|
||||||
}
|
}
|
||||||
|
|
||||||
//sorting
|
//sorting
|
||||||
|
@ -327,7 +327,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme
|
||||||
|
|
||||||
//Compute the AABB after transformation
|
//Compute the AABB after transformation
|
||||||
for (int i = 0; i < 4; i++) {
|
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 < x1) x1 = pt[i].x;
|
||||||
if (pt[i].x > x2) x2 = pt[i].x;
|
if (pt[i].x > x2) x2 = pt[i].x;
|
||||||
|
|
|
@ -47,7 +47,7 @@ void RenderTransform::update()
|
||||||
|
|
||||||
mathScale(&m, scale, scale);
|
mathScale(&m, scale, scale);
|
||||||
|
|
||||||
if (!mathZero(degree)) mathRotate(&m, degree);
|
mathRotate(&m, degree);
|
||||||
|
|
||||||
mathTranslate(&m, x, y);
|
mathTranslate(&m, x, y);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ void RenderTransform::update()
|
||||||
|
|
||||||
RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs)
|
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 (lhs) m = lhs->m;
|
||||||
else if (rhs) m = rhs->m;
|
else if (rhs) m = rhs->m;
|
||||||
else mathIdentity(&m);
|
else mathIdentity(&m);
|
||||||
|
|
|
@ -142,7 +142,7 @@ struct RenderStroke
|
||||||
struct {
|
struct {
|
||||||
float begin = 0.0f;
|
float begin = 0.0f;
|
||||||
float end = 1.0f;
|
float end = 1.0f;
|
||||||
bool individual = false;
|
bool simultaneous = true;
|
||||||
} trim;
|
} trim;
|
||||||
|
|
||||||
~RenderStroke()
|
~RenderStroke()
|
||||||
|
|
|
@ -287,16 +287,14 @@ const Fill* Shape::fill() const noexcept
|
||||||
|
|
||||||
Result Shape::order(bool strokeFirst) noexcept
|
Result Shape::order(bool strokeFirst) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->strokeFirst(strokeFirst)) return Result::FailedAllocation;
|
pImpl->strokeFirst(strokeFirst);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Shape::stroke(float width) noexcept
|
Result Shape::stroke(float width) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->strokeWidth(width)) return Result::FailedAllocation;
|
pImpl->strokeWidth(width);
|
||||||
|
|
||||||
return Result::Success;
|
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
|
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;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,27 +346,25 @@ uint32_t Shape::strokeDash(const float** dashPattern) const noexcept
|
||||||
|
|
||||||
Result Shape::stroke(StrokeCap cap) noexcept
|
Result Shape::stroke(StrokeCap cap) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->strokeCap(cap)) return Result::FailedAllocation;
|
pImpl->strokeCap(cap);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Shape::stroke(StrokeJoin join) noexcept
|
Result Shape::stroke(StrokeJoin join) noexcept
|
||||||
{
|
{
|
||||||
if (!pImpl->strokeJoin(join)) return Result::FailedAllocation;
|
pImpl->strokeJoin(join);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Result Shape::strokeMiterlimit(float miterlimit) noexcept
|
Result Shape::strokeMiterlimit(float miterlimit) noexcept
|
||||||
{
|
{
|
||||||
// https://www.w3.org/TR/SVG2/painting.html#LineJoin
|
// https://www.w3.org/TR/SVG2/painting.html#LineJoin
|
||||||
// - A negative value for stroke-miterlimit must be treated as an illegal value.
|
// - 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.
|
// TODO Find out a reasonable max value.
|
||||||
if (!pImpl->strokeMiterlimit(miterlimit)) return Result::FailedAllocation;
|
pImpl->strokeMiterlimit(miterlimit);
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,12 +380,26 @@ StrokeJoin Shape::strokeJoin() const noexcept
|
||||||
return pImpl->rs.strokeJoin();
|
return pImpl->rs.strokeJoin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float Shape::strokeMiterlimit() const noexcept
|
float Shape::strokeMiterlimit() const noexcept
|
||||||
{
|
{
|
||||||
return pImpl->rs.strokeMiterlimit();
|
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
|
Result Shape::fill(FillRule r) noexcept
|
||||||
{
|
{
|
||||||
pImpl->rs.rule = r;
|
pImpl->rs.rule = r;
|
||||||
|
|
|
@ -207,60 +207,81 @@ struct Shape::Impl
|
||||||
flag |= RenderUpdateFlag::Path;
|
flag |= RenderUpdateFlag::Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeWidth(float width)
|
void strokeWidth(float width)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->width = width;
|
rs.stroke->width = width;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
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 (!rs.stroke) {
|
||||||
if (begin == 0.0f && end == 1.0f) return true;
|
if (begin == 0.0f && end == 1.0f) return;
|
||||||
rs.stroke = new RenderStroke();
|
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.begin = begin;
|
||||||
rs.stroke->trim.end = end;
|
rs.stroke->trim.end = end;
|
||||||
rs.stroke->trim.individual = individual;
|
rs.stroke->trim.simultaneous = simultaneous;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
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();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->cap = cap;
|
rs.stroke->cap = cap;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeJoin(StrokeJoin join)
|
void strokeJoin(StrokeJoin join)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->join = join;
|
rs.stroke->join = join;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeMiterlimit(float miterlimit)
|
void strokeMiterlimit(float miterlimit)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->miterlimit = miterlimit;
|
rs.stroke->miterlimit = miterlimit;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
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) rs.stroke = new RenderStroke();
|
||||||
if (rs.stroke->fill) {
|
if (rs.stroke->fill) {
|
||||||
|
@ -275,8 +296,6 @@ struct Shape::Impl
|
||||||
rs.stroke->color[3] = a;
|
rs.stroke->color[3] = a;
|
||||||
|
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result strokeFill(unique_ptr<Fill> f)
|
Result strokeFill(unique_ptr<Fill> f)
|
||||||
|
@ -335,13 +354,11 @@ struct Shape::Impl
|
||||||
return rs.stroke->strokeFirst;
|
return rs.stroke->strokeFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strokeFirst(bool strokeFirst)
|
void strokeFirst(bool strokeFirst)
|
||||||
{
|
{
|
||||||
if (!rs.stroke) rs.stroke = new RenderStroke();
|
if (!rs.stroke) rs.stroke = new RenderStroke();
|
||||||
rs.stroke->strokeFirst = strokeFirst;
|
rs.stroke->strokeFirst = strokeFirst;
|
||||||
flag |= RenderUpdateFlag::Stroke;
|
flag |= RenderUpdateFlag::Stroke;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(RenderUpdateFlag flag)
|
void update(RenderUpdateFlag flag)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
VERSION=0.13.5
|
VERSION=0.13.7
|
||||||
|
|
||||||
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