diff --git a/inc/thorvg.h b/inc/thorvg.h index 1b37ab1d..97eb1dbb 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -391,4 +391,4 @@ public: } #endif -#endif //_THORVG_H_ +#endif //_THORVG_H_ \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 595df607..168a31f9 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -218,8 +218,7 @@ struct SwImage SwRleData* rle = nullptr; uint32_t* data = nullptr; SwBBox bbox; - uint32_t width; - uint32_t height; + uint32_t w, h; }; struct SwCompositor @@ -325,7 +324,7 @@ void mpoolRetStrokeOutline(unsigned idx); bool rasterCompositor(SwSurface* surface); bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); -bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform); +bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterClear(SwSurface* surface); diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index ac75097e..cefcc079 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -133,13 +133,13 @@ void imageReset(SwImage* image) bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform) { - image->outline = mpoolReqOutline(tid); - auto outline = image->outline; - float w, h; pdata->viewbox(nullptr, nullptr, &w, &h); if (w == 0 || h == 0) return false; + image->outline = mpoolReqOutline(tid); + auto outline = image->outline; + outline->reservedPtsCnt = 5; outline->pts = static_cast(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint))); outline->types = static_cast(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t))); @@ -162,14 +162,15 @@ bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const M ++outline->cntrsCnt; outline->opened = false; - image->outline = outline; - image->width = w; - image->height = h; + image->outline = outline; + image->w = w; + image->h = h; + return true; } void imageFree(SwImage* image) { rleFree(image->rle); -} +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 4557d422..c1878c42 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -142,25 +142,21 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c } -static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, uint32_t opacity, const Matrix* invTransform, uint32_t w, uint32_t h) +static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, uint32_t w, uint32_t h, uint32_t opacity, const Matrix* invTransform) { auto span = rle->spans; for (uint32_t i = 0; i < rle->size; ++i) { - for (uint32_t x = 0; x < span->len; ++x) { - auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13)); - auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23)); - + auto ey1 = span->y * invTransform->e12 + invTransform->e13; + auto ey2 = span->y * invTransform->e22 + invTransform->e23; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + ey1)); + auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + ey2)); if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; - - auto dst = &surface->buffer[span->y * surface->stride + span->x + x]; - auto index = rY * w + rX; //TODO: need to use image's stride - if (dst && img && img[index]) { - auto alpha = ALPHA_MULTIPLY(span->coverage, opacity); - auto src = ALPHA_BLEND(img[index], alpha); - auto invAlpha = 255 - surface->comp.alpha(src); - *dst = src + ALPHA_BLEND(*dst, invAlpha); - } + auto alpha = ALPHA_MULTIPLY(span->coverage, opacity); + auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride + *dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); } ++span; } @@ -168,26 +164,20 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint3 } -static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, const Matrix* invTransform, uint32_t w, uint32_t h) +static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, uint32_t w, uint32_t h, const Matrix* invTransform) { - if (!rle) return false; - auto span = rle->spans; for (uint32_t i = 0; i < rle->size; ++i) { - for (uint32_t x = 0; x < span->len; ++x) { - auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + span->y * invTransform->e12 + invTransform->e13)); - auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + span->y * invTransform->e22 + invTransform->e23)); - + auto ey1 = span->y * invTransform->e12 + invTransform->e13; + auto ey2 = span->y * invTransform->e22 + invTransform->e23; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + auto rX = static_cast(roundf((span->x + x) * invTransform->e11 + ey1)); + auto rY = static_cast(roundf((span->x + x) * invTransform->e21 + ey2)); if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; - - auto dst = &surface->buffer[span->y * surface->stride + span->x + x]; - auto index = rY * w + rX; //TODO: need to use image's stride - if (dst && img && img[index]) { - auto src = ALPHA_BLEND(img[index], span->coverage); - auto invAlpha = 255 - surface->comp.alpha(src); - *dst = src + ALPHA_BLEND(*dst, invAlpha); - } + auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride + *dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); } ++span; } @@ -195,88 +185,55 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, c } -static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t opacity,const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h) +static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t h, uint32_t opacity, const SwBBox& region, const Matrix* invTransform) { - for (auto y = region.min.y; y < region.max.y; y++) { - for (auto x = region.min.x; x < region.max.x; x++) { - auto rX = static_cast(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13)); - auto rY = static_cast(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23)); - + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = &surface->buffer[y * surface->stride + region.min.x]; + auto ey1 = y * invTransform->e12 + invTransform->e13; + auto ey2 = y * invTransform->e22 + invTransform->e23; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + auto rX = static_cast(roundf(x * invTransform->e11 + ey1)); + auto rY = static_cast(roundf(x * invTransform->e21 + ey2)); if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; - - auto dst = &surface->buffer[y * surface->stride + x]; - auto index = rX + (rY * w); //TODO: need to use image's stride - if (dst && img && img[index]) { - auto src = ALPHA_BLEND(img[index], opacity); - auto invAlpha = 255 - surface->comp.alpha(src); - *dst = src + ALPHA_BLEND(*dst, invAlpha); - } + auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride + *dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); } } return true; } -static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, uint32_t w, uint32_t h) +static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t h, const SwBBox& region) { - for (auto y = region.min.y; y < region.max.y; y++) { - for (auto x = region.min.x; x < region.max.x; x++) { - auto dst = &surface->buffer[y * surface->stride + x]; - auto index = x + (y * w); //TODO: need to use image's stride - if (dst && img && img[index]) { - auto src = img[index]; - auto invAlpha = 255 - surface->comp.alpha(src); - *dst = src + ALPHA_BLEND(*dst, invAlpha); - } + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = &surface->buffer[y * surface->stride + region.min.x]; + auto src = img + region.min.x + (y * w); //TODO: need to use image's stride + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + *dst = *src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(*src)); } } return true; } -static bool _rasterImage(SwSurface* surface, uint32_t *img, const SwBBox& region, const Matrix* invTransform, uint32_t w, uint32_t h) +static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t h, const SwBBox& region, const Matrix* invTransform) { - for (auto y = region.min.y; y < region.max.y; y++) { - for (auto x = region.min.x; x < region.max.x; x++) { - auto rX = static_cast(roundf(x * invTransform->e11 + y * invTransform->e12 + invTransform->e13)); - auto rY = static_cast(roundf(x * invTransform->e21 + y * invTransform->e22 + invTransform->e23)); - + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = &surface->buffer[y * surface->stride + region.min.x]; + auto ey1 = y * invTransform->e12 + invTransform->e13; + auto ey2 = y * invTransform->e22 + invTransform->e23; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + auto rX = static_cast(roundf(x * invTransform->e11 + ey1)); + auto rY = static_cast(roundf(x * invTransform->e21 + ey2)); if (rX < 0 || rX >= w || rY < 0 || rY >= h) continue; - - auto dst = &surface->buffer[y * surface->stride + x]; - auto index = rX + (rY * w); //TODO: need to use image's stride - if (dst && img && img[index]) { - auto src = img[index]; - auto invAlpha = 255 - surface->comp.alpha(src); - *dst = src + ALPHA_BLEND(*dst, invAlpha); - } + auto src = img[rX + (rY * w)]; //TODO: need to use image's stride + *dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); } } return true; } -bool rasterImage(SwSurface* surface, SwImage* image, uint8_t opacity, const Matrix* transform) -{ - Matrix invTransform = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; - if (transform) _inverse(transform, &invTransform); - if (image->rle) { - if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, opacity, &invTransform, image->width, image->height ); - return _rasterImageRle(surface, image->rle, image->data, &invTransform, image->width, image->height ); - } - else { - // Fast track - if (_identify(transform)) { - return _rasterImage(surface, image->data, image->bbox, image->width, image->height); - } - else { - if (opacity < 255) return _rasterTranslucentImage(surface, image->data, opacity, image->bbox, &invTransform, image->width, image->height); - return _rasterImage(surface, image->data, image->bbox, &invTransform, image->width, image->height); - } - } -} - - static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color) { if (!rle) return false; @@ -538,3 +495,27 @@ bool rasterClear(SwSurface* surface) } return true; } + + +bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity) +{ + Matrix invTransform; + + if (transform) _inverse(transform, &invTransform); + else invTransform = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; + + if (image->rle) { + if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, image->w, image->h, opacity, &invTransform); + return _rasterImageRle(surface, image->rle, image->data, image->w, image->h, &invTransform); + } + else { + // Fast track + if (_identify(transform)) { + return _rasterImage(surface, image->data, image->w, image->h, image->bbox); + } + else { + if (opacity < 255) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, image->bbox, &invTransform); + return _rasterImage(surface, image->data, image->w, image->h, image->bbox, &invTransform); + } + } +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index daf65f00..5607c78d 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -243,7 +243,7 @@ bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data) auto task = static_cast(data); task->done(); - return rasterImage(surface, &task->image, task->opacity, task->transform); + return rasterImage(surface, &task->image, task->transform, task->opacity); } bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)