mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
sw_engine: ++8bit grayscale rasterizer.
These rasterizers are added for 8bit maskings.
This commit is contained in:
parent
737b89471a
commit
3376f44de5
8 changed files with 395 additions and 230 deletions
|
@ -241,7 +241,7 @@ struct SwImage
|
|||
struct SwBlender
|
||||
{
|
||||
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
uint32_t (*lumaValue)(uint32_t c);
|
||||
uint8_t (*luma)(uint8_t* c);
|
||||
};
|
||||
|
||||
struct SwCompositor;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -82,8 +82,14 @@ static void avxRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_
|
|||
}
|
||||
|
||||
|
||||
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (surface->channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
|
@ -125,8 +131,14 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
|
|||
}
|
||||
|
||||
|
||||
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
||||
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (surface->channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
auto span = rle->spans;
|
||||
uint32_t src;
|
||||
|
||||
|
|
|
@ -20,43 +20,70 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
static void inline cRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
||||
template<typename PIXEL_T>
|
||||
static void inline cRasterPixels(PIXEL_T* dst, uint32_t val, uint32_t offset, int32_t len)
|
||||
{
|
||||
dst += offset;
|
||||
while (len--) *dst++ = val;
|
||||
}
|
||||
|
||||
|
||||
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
||||
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
auto span = rle->spans;
|
||||
uint32_t src;
|
||||
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
|
||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||
else src = color;
|
||||
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
//32bit channels
|
||||
if (surface->channelSize == sizeof(uint32_t)) {
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
uint32_t src;
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||
else src = color;
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
}
|
||||
}
|
||||
//8bit grayscale
|
||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||
uint8_t src;
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||
if (span->coverage < 255) src = _multiply<uint8_t>(span->coverage, a);
|
||||
else src = a;
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||
*dst = src + _multiply<uint8_t>(*dst, ~src);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||
static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto ialpha = _ialpha(color);
|
||||
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface->stride];
|
||||
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||
*dst = color + ALPHA_BLEND(*dst, ialpha);
|
||||
//32bits channels
|
||||
if (surface->channelSize == sizeof(uint32_t)) {
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||
auto ialpha = _ialpha(color);
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface->stride];
|
||||
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||
*dst = color + ALPHA_BLEND(*dst, ialpha);
|
||||
}
|
||||
}
|
||||
//8bit grayscale
|
||||
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||
auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface->stride];
|
||||
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||
*dst = a + _multiply<uint8_t>(*dst, ~a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -49,8 +49,14 @@ static void neonRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32
|
|||
}
|
||||
|
||||
|
||||
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color)
|
||||
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (surface->channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
auto span = rle->spans;
|
||||
uint32_t src;
|
||||
uint8x8_t *vDst = nullptr;
|
||||
|
@ -88,8 +94,14 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
|
|||
}
|
||||
|
||||
|
||||
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (surface->channelSize != sizeof(uint32_t)) {
|
||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
|
|
|
@ -69,7 +69,7 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in
|
|||
}
|
||||
|
||||
|
||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blender)(uint32_t), AASpans* aaSpans)
|
||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||
{
|
||||
#define TEXMAP_TRANSLUCENT
|
||||
#define TEXMAP_MASKING
|
||||
|
@ -79,7 +79,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
|||
}
|
||||
|
||||
|
||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blender)(uint32_t), AASpans* aaSpans)
|
||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||
{
|
||||
#define TEXMAP_MASKING
|
||||
#include "tvgSwRasterTexmapInternal.h"
|
||||
|
@ -102,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
|||
|
||||
|
||||
/* This mapping algorithm is based on Mikael Kalms's. */
|
||||
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blender)(uint32_t), AASpans* aaSpans)
|
||||
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
|
||||
{
|
||||
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
|
||||
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
|
||||
|
@ -545,7 +545,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
|||
| / |
|
||||
3 -- 2
|
||||
*/
|
||||
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t))
|
||||
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
|
||||
{
|
||||
//Exceptions: No dedicated drawing area?
|
||||
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||
|
@ -602,7 +602,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
|||
Should provide two Polygons, one for each triangle.
|
||||
// TODO: region?
|
||||
*/
|
||||
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t))
|
||||
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
|
||||
{
|
||||
//Exceptions: No dedicated drawing area?
|
||||
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
SwSpan* span = nullptr; //used only when rle based.
|
||||
|
||||
#ifdef TEXMAP_MASKING
|
||||
uint32_t* cmp;
|
||||
uint8_t* cmp;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
#endif
|
||||
|
||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||
|
@ -94,7 +95,7 @@
|
|||
x = x1;
|
||||
|
||||
#ifdef TEXMAP_MASKING
|
||||
cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1];
|
||||
cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
|
||||
#endif
|
||||
//Draw horizontal line
|
||||
while (x++ < x2) {
|
||||
|
@ -130,9 +131,9 @@
|
|||
px = INTERPOLATE(ab, px, px2);
|
||||
}
|
||||
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
|
||||
auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blender(*cmp)));
|
||||
auto src = ALPHA_BLEND(px, _multiply<uint32_t>(opacity, blender(cmp)));
|
||||
#elif defined(TEXMAP_MASKING)
|
||||
auto src = ALPHA_BLEND(px, blender(*cmp));
|
||||
auto src = ALPHA_BLEND(px, blender(cmp));
|
||||
#elif defined(TEXMAP_TRANSLUCENT)
|
||||
auto src = ALPHA_BLEND(px, opacity);
|
||||
#else
|
||||
|
@ -141,7 +142,7 @@
|
|||
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
|
||||
++buf;
|
||||
#ifdef TEXMAP_MASKING
|
||||
++cmp;
|
||||
cmp += csize;
|
||||
#endif
|
||||
//Step UV horizontally
|
||||
u += _dudx;
|
||||
|
|
|
@ -167,8 +167,7 @@ bool Paint::Impl::render(RenderMethod& renderer)
|
|||
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
|
||||
auto region = smethod->bounds(renderer);
|
||||
if (region.w == 0 || region.h == 0) return true;
|
||||
//cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
|
||||
cmp = renderer.target(region, renderer.colorSpace());
|
||||
cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
|
||||
if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) {
|
||||
compData->target->pImpl->render(renderer);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue