summaryrefslogtreecommitdiff
path: root/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h')
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h141
1 files changed, 93 insertions, 48 deletions
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
index abb57d7c45..52585162fc 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2023 the ThorVG project. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,17 +20,6 @@
* SOFTWARE.
*/
-struct Vertex
-{
- Point pt;
- Point uv;
-};
-
-struct Polygon
-{
- Vertex vertex[3];
-};
-
struct AALine
{
int32_t x[2];
@@ -80,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 (*blendMethod)(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
@@ -90,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 (*blendMethod)(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"
@@ -113,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 (*blendMethod)(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};
@@ -201,9 +190,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
dxdyb = dxdy[0];
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
@@ -222,9 +211,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
// Set right edge X-slope and perform subpixel pre-stepping
dxdyb = dxdy[2];
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
@@ -251,9 +240,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
ua = u[0] + dy * dudya + (off_y * dudya);
va = v[0] + dy * dvdya + (off_y * dvdya);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
@@ -275,9 +264,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
ua = u[1] + dy * dudya + (off_y * dudya);
va = v[1] + dy * dvdya + (off_y * dvdya);
- if (blendMethod) {
- if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod, aaSpans);
- else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod, aaSpans);
+ if (blender) {
+ if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blender, aaSpans);
+ else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blender, aaSpans);
} else {
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
@@ -287,18 +276,10 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
}
-static AASpans* _AASpans(const Vertex* vertices, const SwImage* image, const SwBBox* region)
+static AASpans* _AASpans(float ymin, float ymax, const SwImage* image, const SwBBox* region)
{
- //Initialize Y range
- float ys = FLT_MAX, ye = -1.0f;
-
- for (int i = 0; i < 4; i++) {
- if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
- if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
- }
-
- auto yStart = static_cast<int32_t>(ys);
- auto yEnd = static_cast<int32_t>(ye);
+ auto yStart = static_cast<int32_t>(ymin);
+ auto yEnd = static_cast<int32_t>(ymax);
if (!_arrange(image, region, yStart, yEnd)) return nullptr;
@@ -521,7 +502,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
auto offset = y * surface->stride;
//Left edge
- dst = surface->buffer + (offset + line->x[0]);
+ dst = surface->buf32 + (offset + line->x[0]);
if (line->x[0] > 1) pixel = *(dst - 1);
else pixel = *dst;
@@ -533,10 +514,10 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
}
//Right edge
- dst = surface->buffer + (offset + line->x[1] - 1);
+ dst = surface->buf32 + (offset + line->x[1] - 1);
if (line->x[1] < (int32_t)(surface->w - 1)) pixel = *(dst + 1);
else pixel = *dst;
-
+
pos = width;
while ((int32_t)(width - line->length[1]) < pos) {
*dst = INTERPOLATE(255 - (line->coverage[1] * (line->length[1] - (width - pos))), *dst, pixel);
@@ -562,12 +543,12 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
0 -- 1
| / |
| / |
- 3 -- 2
+ 3 -- 2
*/
-static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(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 (!region && image->rle->size == 0) return false;
+ if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
/* Prepare vertices.
shift XY coordinates to match the sub-pixeling technique. */
@@ -577,9 +558,15 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}};
vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}};
- for (int i = 0; i < 4; i++) mathMultiply(&vertices[i].pt, transform);
+ float ys = FLT_MAX, ye = -1.0f;
+ for (int i = 0; i < 4; i++) {
+ mathMultiply(&vertices[i].pt, transform);
- auto aaSpans = _AASpans(vertices, image, region);
+ if (vertices[i].pt.y < ys) ys = vertices[i].pt.y;
+ if (vertices[i].pt.y > ye) ye = vertices[i].pt.y;
+ }
+
+ auto aaSpans = _AASpans(ys, ye, image, region);
if (!aaSpans) return true;
Polygon polygon;
@@ -589,14 +576,72 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
polygon.vertex[1] = vertices[1];
polygon.vertex[2] = vertices[3];
- _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
+ _rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
//Draw the second polygon
polygon.vertex[0] = vertices[1];
polygon.vertex[1] = vertices[2];
polygon.vertex[2] = vertices[3];
- _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
+ _rasterPolygonImage(surface, image, region, opacity, polygon, blender, aaSpans);
return _apply(surface, aaSpans);
}
+
+
+/*
+ Provide any number of triangles to draw a mesh using the supplied image.
+ Indexes are not used, so each triangle (Polygon) vertex has to be defined, even if they copy the previous one.
+ Example:
+
+ 0 -- 1 0 -- 1 0
+ | / | --> | / / |
+ | / | | / / |
+ 2 -- 3 2 1 -- 2
+
+ 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, uint8_t(*blender)(uint8_t*))
+{
+ //Exceptions: No dedicated drawing area?
+ if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
+
+ // Step polygons once to transform
+ auto transformedTris = (Polygon*)malloc(sizeof(Polygon) * mesh->triangleCnt);
+ 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);
+
+ 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;
+ if (transformedTris[i].vertex[1].pt.y < ys) ys = transformedTris[i].vertex[1].pt.y;
+ else if (transformedTris[i].vertex[1].pt.y > ye) ye = transformedTris[i].vertex[1].pt.y;
+ if (transformedTris[i].vertex[2].pt.y < ys) ys = transformedTris[i].vertex[2].pt.y;
+ else if (transformedTris[i].vertex[2].pt.y > ye) ye = transformedTris[i].vertex[2].pt.y;
+
+ // Convert normalized UV coordinates to image coordinates
+ transformedTris[i].vertex[0].uv.x *= (float)image->w;
+ transformedTris[i].vertex[0].uv.y *= (float)image->h;
+ transformedTris[i].vertex[1].uv.x *= (float)image->w;
+ transformedTris[i].vertex[1].uv.y *= (float)image->h;
+ transformedTris[i].vertex[2].uv.x *= (float)image->w;
+ transformedTris[i].vertex[2].uv.y *= (float)image->h;
+ }
+
+ // Get AA spans and step polygons again to draw
+ auto aaSpans = _AASpans(ys, ye, image, region);
+ if (aaSpans) {
+ for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
+ _rasterPolygonImage(surface, image, region, opacity, transformedTris[i], blender, aaSpans);
+ }
+ // Apply to surface (note: frees the AA spans)
+ _apply(surface, aaSpans);
+ }
+ free(transformedTris);
+
+ return true;
+}