mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
common: spec out TexMap
Spec out this incomplete experimental feature, this is a still promising one, we will reintroduce this officially after 1.0 release size: -2kb issue: https://github.com/thorvg/thorvg/issues/1372
This commit is contained in:
parent
eb462c6e32
commit
65c808fc02
26 changed files with 81 additions and 619 deletions
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 - 2024 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
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Example.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* ThorVG Drawing Contents */
|
||||
/************************************************************************/
|
||||
|
||||
struct UserExample : tvgexam::Example
|
||||
{
|
||||
bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h) override
|
||||
{
|
||||
if (!canvas) return false;
|
||||
|
||||
//Background
|
||||
auto shape = tvg::Shape::gen();
|
||||
shape->appendRect(0, 0, w, h);
|
||||
shape->fill(255, 255, 255);
|
||||
|
||||
canvas->push(std::move(shape));
|
||||
|
||||
//Raw Image
|
||||
string path(EXAMPLE_DIR"/image/rawimage_200x300.raw");
|
||||
|
||||
ifstream file(path, ios::binary);
|
||||
if (!file.is_open()) return false;
|
||||
auto data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300));
|
||||
file.read(reinterpret_cast<char *>(data), sizeof (uint32_t) * 200 * 300);
|
||||
file.close();
|
||||
|
||||
//Picture
|
||||
auto picture = tvg::Picture::gen();
|
||||
if (!tvgexam::verify(picture->load(data, 200, 300, true))) return false;
|
||||
|
||||
//Composing Meshes
|
||||
tvg::Polygon triangles[4];
|
||||
triangles[0].vertex[0] = {{100, 125}, {0, 0}};
|
||||
triangles[0].vertex[1] = {{300, 100}, {0.5, 0}};
|
||||
triangles[0].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[1].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[1].vertex[1] = {{350, 450}, {0.5, 1}};
|
||||
triangles[1].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[2].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[2].vertex[1] = {{500, 200}, {1, 0}};
|
||||
triangles[2].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
triangles[3].vertex[0] = {{500, 200}, {1, 0}};
|
||||
triangles[3].vertex[1] = {{450, 450}, {1, 1}};
|
||||
triangles[3].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
if (!tvgexam::verify(picture->mesh(triangles, 4))) return false;
|
||||
|
||||
//Masking + Opacity
|
||||
auto picture2 = tvg::cast<tvg::Picture>(picture->duplicate());
|
||||
picture2->translate(400, 400);
|
||||
picture2->opacity(200);
|
||||
|
||||
auto mask = tvg::Shape::gen();
|
||||
mask->appendCircle(700, 700, 200, 200);
|
||||
mask->fill(255, 255, 255);
|
||||
picture2->composite(std::move(mask), tvg::CompositeMethod::AlphaMask);
|
||||
|
||||
canvas->push(std::move(picture));
|
||||
canvas->push(std::move(picture2));
|
||||
|
||||
free(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Entry Point */
|
||||
/************************************************************************/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return tvgexam::main(new UserExample, argc, argv, 1024, 1024);
|
||||
}
|
|
@ -28,39 +28,10 @@ using namespace std;
|
|||
/* ThorVG Saving Contents */
|
||||
/************************************************************************/
|
||||
|
||||
unique_ptr<tvg::Paint> tvgTexmap(uint32_t * data, int width, int heigth)
|
||||
{
|
||||
auto texmap = tvg::Picture::gen();
|
||||
if (!tvgexam::verify(texmap->load(data, width, heigth, true))) return nullptr;
|
||||
texmap->translate(100, 100);
|
||||
|
||||
//Composing Meshes
|
||||
tvg::Polygon triangles[4];
|
||||
triangles[0].vertex[0] = {{100, 125}, {0, 0}};
|
||||
triangles[0].vertex[1] = {{300, 100}, {0.5, 0}};
|
||||
triangles[0].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[1].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[1].vertex[1] = {{350, 450}, {0.5, 1}};
|
||||
triangles[1].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[2].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[2].vertex[1] = {{500, 200}, {1, 0}};
|
||||
triangles[2].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
triangles[3].vertex[0] = {{500, 200}, {1, 0}};
|
||||
triangles[3].vertex[1] = {{450, 450}, {1, 1}};
|
||||
triangles[3].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
texmap->mesh(triangles, 4);
|
||||
|
||||
return texmap;
|
||||
}
|
||||
|
||||
unique_ptr<tvg::Paint> tvgClippedImage(uint32_t * data, int width, int heigth)
|
||||
unique_ptr<tvg::Paint> tvgClippedImage(uint32_t * data, int width, int height)
|
||||
{
|
||||
auto image = tvg::Picture::gen();
|
||||
if (!tvgexam::verify(image->load(data, width, heigth, true))) return nullptr;
|
||||
if (!tvgexam::verify(image->load(data, width, height, true))) return nullptr;
|
||||
image->translate(400, 0);
|
||||
image->scale(2);
|
||||
|
||||
|
@ -193,10 +164,6 @@ void exportTvg()
|
|||
file.read(reinterpret_cast<char*>(data), sizeof(uint32_t) * width * height);
|
||||
file.close();
|
||||
|
||||
//texmap image
|
||||
auto texmap = tvgTexmap(data, width, height);
|
||||
scene->push(std::move(texmap));
|
||||
|
||||
//clipped image
|
||||
auto image = tvgClippedImage(data, width, height);
|
||||
scene->push(std::move(image));
|
||||
|
|
|
@ -65,7 +65,6 @@ source_file = [
|
|||
'StrokeMiterlimit.cpp',
|
||||
'StrokeTrim.cpp',
|
||||
'Svg.cpp',
|
||||
'Texmap.cpp',
|
||||
'Text.cpp',
|
||||
'Transform.cpp',
|
||||
'Tvg.cpp',
|
||||
|
|
63
inc/thorvg.h
63
inc/thorvg.h
|
@ -234,34 +234,6 @@ struct Matrix
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A data structure representing a texture mesh vertex
|
||||
*
|
||||
* @param pt The vertex coordinate
|
||||
* @param uv The normalized texture coordinate in the range (0.0..1.0, 0.0..1.0)
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
struct Vertex
|
||||
{
|
||||
Point pt;
|
||||
Point uv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A data structure representing a triange in a texture mesh
|
||||
*
|
||||
* @param vertex The three vertices that make up the polygon
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
struct Polygon
|
||||
{
|
||||
Vertex vertex[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class Paint
|
||||
*
|
||||
|
@ -1302,41 +1274,6 @@ public:
|
|||
*/
|
||||
const Paint* paint(uint32_t id) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Sets or removes the triangle mesh to deform the image.
|
||||
*
|
||||
* If a mesh is provided, the transform property of the Picture will apply to the triangle mesh, and the
|
||||
* image data will be used as the texture.
|
||||
*
|
||||
* If @p triangles is @c nullptr, or @p triangleCnt is 0, the mesh will be removed.
|
||||
*
|
||||
* Only raster image types are supported at this time (png, jpg). Vector types like svg and tvg do not support.
|
||||
* mesh deformation. However, if required you should be able to render a vector image to a raster image and then apply a mesh.
|
||||
*
|
||||
* @param[in] triangles An array of Polygons(triangles) that make up the mesh, or null to remove the mesh.
|
||||
* @param[in] triangleCnt The number of Polygons(triangles) provided, or 0 to remove the mesh.
|
||||
*
|
||||
* @note The Polygons are copied internally, so modifying them after calling Mesh::mesh has no affect.
|
||||
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
Result mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Return the number of triangles in the mesh, and optionally get a pointer to the array of triangles in the mesh.
|
||||
*
|
||||
* @param[out] triangles Optional. A pointer to the array of Polygons used by this mesh.
|
||||
*
|
||||
* @return The number of polygons in the array.
|
||||
*
|
||||
* @note Modifying the triangles returned by this method will modify them directly within the mesh.
|
||||
* @warning Please do not use it, this API is not official one. It could be modified in the next version.
|
||||
*
|
||||
* @note Experimental API
|
||||
*/
|
||||
uint32_t mesh(const Polygon** triangles) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Creates a new Picture object.
|
||||
*
|
||||
|
|
|
@ -418,21 +418,6 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint)
|
|||
|
||||
return true;
|
||||
}
|
||||
case TVG_TAG_PICTURE_MESH: {
|
||||
if (block.length < 1 * SIZE(uint32_t)) return false;
|
||||
|
||||
auto ptr = block.data;
|
||||
uint32_t meshCnt;
|
||||
READ_UI32(&meshCnt, ptr);
|
||||
ptr += SIZE(uint32_t);
|
||||
|
||||
auto size = meshCnt * SIZE(Polygon);
|
||||
if (block.length != SIZE(uint32_t) + size) return false;
|
||||
|
||||
picture->mesh((Polygon*) ptr, meshCnt);
|
||||
|
||||
return true;
|
||||
}
|
||||
//Base Paint Properties
|
||||
default: {
|
||||
if (_parsePaintProperty(block, picture)) return true;
|
||||
|
|
|
@ -58,115 +58,57 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GlGeometry::tesselate(const Surface* image, const RenderMesh* mesh, RenderUpdateFlag flag)
|
||||
bool GlGeometry::tesselate(const Surface* image, RenderUpdateFlag flag)
|
||||
{
|
||||
if (flag & RenderUpdateFlag::Image) {
|
||||
fillVertex.clear();
|
||||
fillIndex.clear();
|
||||
|
||||
if (mesh && mesh->triangleCnt) {
|
||||
fillVertex.reserve(mesh->triangleCnt * 3 * 5);
|
||||
fillIndex.reserve(mesh->triangleCnt * 3);
|
||||
fillVertex.reserve(5 * 4);
|
||||
fillIndex.reserve(6);
|
||||
|
||||
uint32_t index = 0;
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].pt.y);
|
||||
float left = 0.f;
|
||||
float top = 0.f;
|
||||
float right = image->w;
|
||||
float bottom = image->h;
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].uv.y);
|
||||
// left top point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(top);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].pt.y);
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(1.f);
|
||||
// left bottom point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(bottom);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].uv.y);
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(0.f);
|
||||
// right top point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(top);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].pt.y);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
// right bottom point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(bottom);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].uv.y);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
|
||||
fillIndex.push(index);
|
||||
fillIndex.push(index + 1);
|
||||
fillIndex.push(index + 2);
|
||||
index += 3;
|
||||
}
|
||||
fillIndex.push(0);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(2);
|
||||
|
||||
float left = mesh->triangles[0].vertex[0].pt.x;
|
||||
float top = mesh->triangles[0].vertex[0].pt.y;
|
||||
float right = mesh->triangles[0].vertex[0].pt.x;
|
||||
float bottom = mesh->triangles[0].vertex[0].pt.y;
|
||||
fillIndex.push(2);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(3);
|
||||
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
left = min(left, mesh->triangles[i].vertex[0].pt.x);
|
||||
left = min(left, mesh->triangles[i].vertex[1].pt.x);
|
||||
left = min(left, mesh->triangles[i].vertex[2].pt.x);
|
||||
top = min(top, mesh->triangles[i].vertex[0].pt.y);
|
||||
top = min(top, mesh->triangles[i].vertex[1].pt.y);
|
||||
top = min(top, mesh->triangles[i].vertex[2].pt.y);
|
||||
|
||||
right = max(right, mesh->triangles[i].vertex[0].pt.x);
|
||||
right = max(right, mesh->triangles[i].vertex[1].pt.x);
|
||||
right = max(right, mesh->triangles[i].vertex[2].pt.x);
|
||||
bottom = max(bottom, mesh->triangles[i].vertex[0].pt.y);
|
||||
bottom = max(bottom, mesh->triangles[i].vertex[1].pt.y);
|
||||
bottom = max(bottom, mesh->triangles[i].vertex[2].pt.y);
|
||||
}
|
||||
|
||||
mBounds.x = static_cast<int32_t>(left);
|
||||
mBounds.y = static_cast<int32_t>(top);
|
||||
mBounds.w = static_cast<int32_t>(right - left);
|
||||
mBounds.h = static_cast<int32_t>(bottom - top);
|
||||
|
||||
} else {
|
||||
fillVertex.reserve(5 * 4);
|
||||
fillIndex.reserve(6);
|
||||
|
||||
float left = 0.f;
|
||||
float top = 0.f;
|
||||
float right = image->w;
|
||||
float bottom = image->h;
|
||||
|
||||
// left top point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(top);
|
||||
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(1.f);
|
||||
// left bottom point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(bottom);
|
||||
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(0.f);
|
||||
// right top point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(top);
|
||||
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
// right bottom point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(bottom);
|
||||
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
|
||||
fillIndex.push(0);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(2);
|
||||
|
||||
fillIndex.push(2);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(3);
|
||||
|
||||
mBounds.x = 0;
|
||||
mBounds.y = 0;
|
||||
mBounds.w = image->w;
|
||||
mBounds.h = image->h;
|
||||
}
|
||||
mBounds.x = 0;
|
||||
mBounds.y = 0;
|
||||
mBounds.w = image->w;
|
||||
mBounds.h = image->h;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -190,7 +190,7 @@ public:
|
|||
~GlGeometry();
|
||||
|
||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
|
||||
bool tesselate(const Surface* image, const RenderMesh* mesh, RenderUpdateFlag flag);
|
||||
bool tesselate(const Surface* image, RenderUpdateFlag flag);
|
||||
void disableVertex(uint32_t location);
|
||||
bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag);
|
||||
void updateTransform(const Matrix& m);
|
||||
|
|
|
@ -417,7 +417,7 @@ static GLuint _genTexture(Surface* image)
|
|||
return tex;
|
||||
}
|
||||
|
||||
RenderData GlRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
RenderData GlRenderer::prepare(Surface* image, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
{
|
||||
if (flags == RenderUpdateFlag::None) return data;
|
||||
|
||||
|
@ -433,14 +433,14 @@ RenderData GlRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderDat
|
|||
sdata->texId = _genTexture(image);
|
||||
sdata->opacity = opacity;
|
||||
sdata->texColorSpace = image->cs;
|
||||
sdata->texFlipY = (mesh && mesh->triangleCnt) ? 0 : 1;
|
||||
sdata->texFlipY = 1;
|
||||
sdata->geometry = make_unique<GlGeometry>();
|
||||
}
|
||||
|
||||
sdata->geometry->updateTransform(transform);
|
||||
sdata->geometry->setViewport(mViewport);
|
||||
|
||||
sdata->geometry->tesselate(image, mesh, flags);
|
||||
sdata->geometry->tesselate(image, flags);
|
||||
|
||||
if (!clips.empty()) sdata->clips.push(clips);
|
||||
|
||||
|
@ -1231,4 +1231,5 @@ void GlRenderer::endRenderPass(Compositor* cmp)
|
|||
task->setParentSize(static_cast<uint32_t>(currentPass()->getViewport().w), static_cast<uint32_t>(currentPass()->getViewport().h));
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
||||
}
|
|
@ -54,7 +54,7 @@ public:
|
|||
};
|
||||
|
||||
RenderData prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override;
|
||||
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
RenderData prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
bool preRender() override;
|
||||
bool renderShape(RenderData data) override;
|
||||
bool renderImage(RenderData data) override;
|
||||
|
|
|
@ -519,7 +519,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
|||
SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
|
||||
void strokeFree(SwStroke* stroke);
|
||||
|
||||
bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
||||
bool imagePrepare(SwImage* image, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
|
||||
bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias);
|
||||
void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
|
||||
void imageReset(SwImage* image);
|
||||
|
@ -564,7 +564,7 @@ void mpoolRetDashOutline(SwMpool* mpool, unsigned idx);
|
|||
bool rasterCompositor(SwSurface* surface);
|
||||
bool rasterGradientShape(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
|
||||
bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix& transform, const SwBBox& bbox, uint8_t opacity);
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity);
|
||||
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity);
|
||||
bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
|
|
|
@ -34,7 +34,7 @@ static inline bool _onlyShifted(const Matrix& m)
|
|||
}
|
||||
|
||||
|
||||
static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix& transform, SwMpool* mpool, unsigned tid)
|
||||
static bool _genOutline(SwImage* image, const Matrix& transform, SwMpool* mpool, unsigned tid)
|
||||
{
|
||||
image->outline = mpoolReqOutline(mpool, tid);
|
||||
auto outline = image->outline;
|
||||
|
@ -45,48 +45,12 @@ static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix& tr
|
|||
outline->closed.reserve(1);
|
||||
|
||||
Point to[4];
|
||||
if (mesh->triangleCnt > 0) {
|
||||
// TODO: Optimise me. We appear to calculate this exact min/max bounding area in multiple
|
||||
// places. We should be able to re-use one we have already done? Also see:
|
||||
// tvgPicture.h --> bounds
|
||||
// tvgSwRasterTexmap.h --> _rasterTexmapPolygonMesh
|
||||
//
|
||||
// TODO: Should we calculate the exact path(s) of the triangle mesh instead?
|
||||
// i.e. copy tvgSwShape.capp -> _genOutline?
|
||||
//
|
||||
// TODO: Cntrs?
|
||||
auto triangles = mesh->triangles;
|
||||
auto min = triangles[0].vertex[0].pt;
|
||||
auto max = triangles[0].vertex[0].pt;
|
||||
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; ++i) {
|
||||
if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
|
||||
else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
|
||||
if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
|
||||
else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
|
||||
|
||||
if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
|
||||
else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
|
||||
if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
|
||||
else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
|
||||
|
||||
if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
|
||||
else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
|
||||
if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
|
||||
else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
|
||||
}
|
||||
to[0] = {min.x, min.y};
|
||||
to[1] = {max.x, min.y};
|
||||
to[2] = {max.x, max.y};
|
||||
to[3] = {min.x, max.y};
|
||||
} else {
|
||||
auto w = static_cast<float>(image->w);
|
||||
auto h = static_cast<float>(image->h);
|
||||
to[0] = {0, 0};
|
||||
to[1] = {w, 0};
|
||||
to[2] = {w, h};
|
||||
to[3] = {0, h};
|
||||
}
|
||||
auto w = static_cast<float>(image->w);
|
||||
auto h = static_cast<float>(image->h);
|
||||
to[0] = {0, 0};
|
||||
to[1] = {w, 0};
|
||||
to[2] = {w, h};
|
||||
to[3] = {0, h};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
outline->pts.push(mathTransform(&to[i], transform));
|
||||
|
@ -108,7 +72,7 @@ static bool _genOutline(SwImage* image, const RenderMesh* mesh, const Matrix& tr
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
||||
bool imagePrepare(SwImage* image, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
|
||||
{
|
||||
image->direct = _onlyShifted(transform);
|
||||
|
||||
|
@ -126,7 +90,7 @@ bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix& transfor
|
|||
else image->scaled = false;
|
||||
}
|
||||
|
||||
if (!_genOutline(image, mesh, transform, mpool, tid)) return false;
|
||||
if (!_genOutline(image, transform, mpool, tid)) return false;
|
||||
return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion, image->direct);
|
||||
}
|
||||
|
||||
|
|
|
@ -1987,13 +1987,12 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint
|
|||
}
|
||||
|
||||
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix& transform, const SwBBox& bbox, uint8_t opacity)
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity)
|
||||
{
|
||||
//Outside of the viewport, skip the rendering
|
||||
if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return true;
|
||||
|
||||
if (mesh && mesh->triangleCnt > 0) return _rasterTexmapPolygonMesh(surface, image, mesh, transform, &bbox, opacity);
|
||||
else return _rasterImage(surface, image, transform, bbox, opacity);
|
||||
return _rasterImage(surface, image, transform, bbox, opacity);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1135,68 +1135,3 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
|||
#endif
|
||||
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, uint8_t opacity)
|
||||
{
|
||||
if (surface->channelSize == sizeof(uint8_t)) {
|
||||
TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon mesh!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//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];
|
||||
transformedTris[i].vertex[0].pt *= transform;
|
||||
transformedTris[i].vertex[1].pt *= transform;
|
||||
transformedTris[i].vertex[2].pt *= transform;
|
||||
|
||||
if (transformedTris[i].vertex[0].pt.y < ys) ys = transformedTris[i].vertex[0].pt.y;
|
||||
else if (transformedTris[i].vertex[0].pt.y > ye) ye = transformedTris[i].vertex[0].pt.y;
|
||||
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
|
||||
if (auto aaSpans = _AASpans(ys, ye, image, region)) {
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
_rasterPolygonImage(surface, image, region, transformedTris[i], aaSpans, opacity);
|
||||
}
|
||||
#if 0
|
||||
if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) {
|
||||
_compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox);
|
||||
}
|
||||
#endif
|
||||
_apply(surface, aaSpans);
|
||||
}
|
||||
free(transformedTris);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,6 @@ struct SwImageTask : SwTask
|
|||
{
|
||||
SwImage image;
|
||||
Surface* source; //Image source
|
||||
const RenderMesh* mesh = nullptr; //Should be valid ptr in action
|
||||
|
||||
bool clip(SwRleData* target) override
|
||||
{
|
||||
|
@ -236,10 +235,9 @@ struct SwImageTask : SwTask
|
|||
imageReset(&image);
|
||||
if (!image.data || image.w == 0 || image.h == 0) goto end;
|
||||
|
||||
if (!imagePrepare(&image, mesh, transform, clipRegion, bbox, mpool, tid)) goto end;
|
||||
if (!imagePrepare(&image, transform, clipRegion, bbox, mpool, tid)) goto end;
|
||||
|
||||
// TODO: How do we clip the triangle mesh? Only clip non-meshed images for now
|
||||
if (mesh->triangleCnt == 0 && clips.count > 0) {
|
||||
if (clips.count > 0) {
|
||||
if (!imageGenRle(&image, bbox, false)) goto end;
|
||||
if (image.rle) {
|
||||
//Clear current task memorypool here if the clippers would use the same memory pool
|
||||
|
@ -423,7 +421,7 @@ bool SwRenderer::renderImage(RenderData data)
|
|||
|
||||
if (task->opacity == 0) return true;
|
||||
|
||||
return rasterImage(surface, &task->image, task->mesh, task->transform, task->bbox, task->opacity);
|
||||
return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
|
||||
}
|
||||
|
||||
|
||||
|
@ -632,7 +630,7 @@ bool SwRenderer::endComposite(Compositor* cmp)
|
|||
//Default is alpha blending
|
||||
if (p->method == CompositeMethod::None) {
|
||||
Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||
return rasterImage(surface, &p->image, nullptr, m, p->bbox, p->opacity);
|
||||
return rasterImage(surface, &p->image, m, p->bbox, p->opacity);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -697,7 +695,7 @@ void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Arr
|
|||
}
|
||||
|
||||
|
||||
RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
RenderData SwRenderer::prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
{
|
||||
//prepare task
|
||||
auto task = static_cast<SwImageTask*>(data);
|
||||
|
@ -705,7 +703,6 @@ RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD
|
|||
else task->done();
|
||||
|
||||
task->source = surface;
|
||||
task->mesh = mesh;
|
||||
|
||||
return prepareCommon(task, transform, clips, opacity, flags);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class SwRenderer : public RenderMethod
|
|||
{
|
||||
public:
|
||||
RenderData prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override;
|
||||
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
RenderData prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
bool preRender() override;
|
||||
bool renderShape(RenderData data) override;
|
||||
bool renderImage(RenderData data) override;
|
||||
|
|
|
@ -200,23 +200,6 @@ Result Picture::size(float* w, float* h) const noexcept
|
|||
}
|
||||
|
||||
|
||||
Result Picture::mesh(const Polygon* triangles, uint32_t triangleCnt) noexcept
|
||||
{
|
||||
if (!triangles && triangleCnt > 0) return Result::InvalidArguments;
|
||||
if (triangles && triangleCnt == 0) return Result::InvalidArguments;
|
||||
|
||||
pImpl->mesh(triangles, triangleCnt);
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
uint32_t Picture::mesh(const Polygon** triangles) const noexcept
|
||||
{
|
||||
if (triangles) *triangles = pImpl->rm.triangles;
|
||||
return pImpl->rm.triangleCnt;
|
||||
}
|
||||
|
||||
|
||||
const Paint* Picture::paint(uint32_t id) noexcept
|
||||
{
|
||||
struct Value
|
||||
|
|
|
@ -63,7 +63,6 @@ struct Picture::Impl
|
|||
Surface* surface = nullptr; //bitmap picture uses
|
||||
RenderData rd = nullptr; //engine data
|
||||
float w = 0, h = 0;
|
||||
RenderMesh rm; //mesh data
|
||||
Picture* picture = nullptr;
|
||||
bool resizing = false;
|
||||
bool needComp = false; //need composition
|
||||
|
@ -102,7 +101,7 @@ struct Picture::Impl
|
|||
auto scale = sx < sy ? sx : sy;
|
||||
auto m = transform * Matrix{scale, 0, 0, 0, scale, 0, 0, 0, 1};
|
||||
|
||||
rd = renderer->prepare(surface, &rm, rd, m, clips, opacity, flag);
|
||||
rd = renderer->prepare(surface, rd, m, clips, opacity, flag);
|
||||
} else if (paint) {
|
||||
if (resizing) {
|
||||
loader->resize(paint, w, h);
|
||||
|
@ -116,37 +115,10 @@ struct Picture::Impl
|
|||
|
||||
bool bounds(float* x, float* y, float* w, float* h, bool stroking)
|
||||
{
|
||||
if (rm.triangleCnt > 0) {
|
||||
auto triangles = rm.triangles;
|
||||
auto min = triangles[0].vertex[0].pt;
|
||||
auto max = triangles[0].vertex[0].pt;
|
||||
|
||||
for (uint32_t i = 0; i < rm.triangleCnt; ++i) {
|
||||
if (triangles[i].vertex[0].pt.x < min.x) min.x = triangles[i].vertex[0].pt.x;
|
||||
else if (triangles[i].vertex[0].pt.x > max.x) max.x = triangles[i].vertex[0].pt.x;
|
||||
if (triangles[i].vertex[0].pt.y < min.y) min.y = triangles[i].vertex[0].pt.y;
|
||||
else if (triangles[i].vertex[0].pt.y > max.y) max.y = triangles[i].vertex[0].pt.y;
|
||||
|
||||
if (triangles[i].vertex[1].pt.x < min.x) min.x = triangles[i].vertex[1].pt.x;
|
||||
else if (triangles[i].vertex[1].pt.x > max.x) max.x = triangles[i].vertex[1].pt.x;
|
||||
if (triangles[i].vertex[1].pt.y < min.y) min.y = triangles[i].vertex[1].pt.y;
|
||||
else if (triangles[i].vertex[1].pt.y > max.y) max.y = triangles[i].vertex[1].pt.y;
|
||||
|
||||
if (triangles[i].vertex[2].pt.x < min.x) min.x = triangles[i].vertex[2].pt.x;
|
||||
else if (triangles[i].vertex[2].pt.x > max.x) max.x = triangles[i].vertex[2].pt.x;
|
||||
if (triangles[i].vertex[2].pt.y < min.y) min.y = triangles[i].vertex[2].pt.y;
|
||||
else if (triangles[i].vertex[2].pt.y > max.y) max.y = triangles[i].vertex[2].pt.y;
|
||||
}
|
||||
if (x) *x = min.x;
|
||||
if (y) *y = min.y;
|
||||
if (w) *w = max.x - min.x;
|
||||
if (h) *h = max.y - min.y;
|
||||
} else {
|
||||
if (x) *x = 0;
|
||||
if (y) *y = 0;
|
||||
if (w) *w = this->w;
|
||||
if (h) *h = this->h;
|
||||
}
|
||||
if (x) *x = 0;
|
||||
if (y) *y = 0;
|
||||
if (w) *w = this->w;
|
||||
if (h) *h = this->h;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -181,19 +153,6 @@ struct Picture::Impl
|
|||
return load(loader);
|
||||
}
|
||||
|
||||
void mesh(const Polygon* triangles, const uint32_t triangleCnt)
|
||||
{
|
||||
if (triangles && triangleCnt > 0) {
|
||||
this->rm.triangleCnt = triangleCnt;
|
||||
this->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * triangleCnt);
|
||||
memcpy(this->rm.triangles, triangles, sizeof(Polygon) * triangleCnt);
|
||||
} else {
|
||||
free(this->rm.triangles);
|
||||
this->rm.triangles = nullptr;
|
||||
this->rm.triangleCnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Paint* duplicate(Paint* ret)
|
||||
{
|
||||
if (ret) TVGERR("RENDERER", "TODO: duplicate()");
|
||||
|
@ -216,12 +175,6 @@ struct Picture::Impl
|
|||
dup->h = h;
|
||||
dup->resizing = resizing;
|
||||
|
||||
if (rm.triangleCnt > 0) {
|
||||
dup->rm.triangleCnt = rm.triangleCnt;
|
||||
dup->rm.triangles = (Polygon*)malloc(sizeof(Polygon) * rm.triangleCnt);
|
||||
memcpy(dup->rm.triangles, rm.triangles, sizeof(Polygon) * rm.triangleCnt);
|
||||
}
|
||||
|
||||
return picture;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,15 +86,15 @@ struct Compositor
|
|||
uint8_t opacity;
|
||||
};
|
||||
|
||||
struct RenderMesh
|
||||
struct Vertex
|
||||
{
|
||||
Polygon* triangles = nullptr;
|
||||
uint32_t triangleCnt = 0;
|
||||
Point pt;
|
||||
Point uv;
|
||||
};
|
||||
|
||||
~RenderMesh()
|
||||
{
|
||||
free(triangles);
|
||||
}
|
||||
struct Polygon
|
||||
{
|
||||
Vertex vertex[3];
|
||||
};
|
||||
|
||||
struct RenderRegion
|
||||
|
@ -287,7 +287,7 @@ public:
|
|||
|
||||
virtual ~RenderMethod() {}
|
||||
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) = 0;
|
||||
virtual RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0;
|
||||
virtual RenderData prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) = 0;
|
||||
virtual bool preRender() = 0;
|
||||
virtual bool renderShape(RenderData data) = 0;
|
||||
virtual bool renderImage(RenderData data) = 0;
|
||||
|
|
|
@ -282,26 +282,6 @@ void WgGeometryData::appendBlitBox()
|
|||
}
|
||||
|
||||
|
||||
void WgGeometryData::appendMesh(const RenderMesh* rmesh)
|
||||
{
|
||||
assert(rmesh);
|
||||
positions.pts.reserve(rmesh->triangleCnt * 3);
|
||||
texCoords.reserve(rmesh->triangleCnt * 3);
|
||||
indexes.reserve(rmesh->triangleCnt * 3);
|
||||
for (uint32_t i = 0; i < rmesh->triangleCnt; i++) {
|
||||
positions.appendPoint(rmesh->triangles[i].vertex[0].pt);
|
||||
positions.appendPoint(rmesh->triangles[i].vertex[1].pt);
|
||||
positions.appendPoint(rmesh->triangles[i].vertex[2].pt);
|
||||
texCoords.push(rmesh->triangles[i].vertex[0].uv);
|
||||
texCoords.push(rmesh->triangles[i].vertex[1].uv);
|
||||
texCoords.push(rmesh->triangles[i].vertex[2].uv);
|
||||
indexes.push(i*3 + 0);
|
||||
indexes.push(i*3 + 1);
|
||||
indexes.push(i*3 + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WgGeometryData::appendStrokeDashed(const WgPolyline* polyline, const RenderStroke *stroke)
|
||||
{
|
||||
assert(stroke);
|
||||
|
|
|
@ -117,7 +117,6 @@ struct WgGeometryData
|
|||
void appendCircle(WgPoint center, float radius);
|
||||
void appendImageBox(float w, float h);
|
||||
void appendBlitBox();
|
||||
void appendMesh(const RenderMesh* rmesh);
|
||||
void appendStrokeDashed(const WgPolyline* polyline, const RenderStroke *stroke);
|
||||
void appendStrokeJoin(const WgPoint& v0, const WgPoint& v1, const WgPoint& v2,
|
||||
StrokeJoin join, float halfWidth, float miterLimit);
|
||||
|
|
|
@ -427,7 +427,6 @@ void WgRenderDataShapePool::release(WgContext& context)
|
|||
|
||||
void WgRenderDataPicture::release(WgContext& context)
|
||||
{
|
||||
meshData.release(context);
|
||||
imageData.release(context);
|
||||
bindGroupPicture.release();
|
||||
WgRenderDataPaint::release(context);
|
||||
|
|
|
@ -98,7 +98,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
}
|
||||
|
||||
|
||||
RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
RenderData WgRenderer::prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
{
|
||||
// get or create render data shape
|
||||
auto renderDataPicture = (WgRenderDataPicture*)data;
|
||||
|
@ -116,8 +116,7 @@ RenderData WgRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderD
|
|||
// update image data
|
||||
if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Image)) {
|
||||
WgGeometryData geometryData;
|
||||
if (mesh->triangleCnt == 0) geometryData.appendImageBox(surface->w, surface->h);
|
||||
else geometryData.appendMesh(mesh);
|
||||
geometryData.appendImageBox(surface->w, surface->h);
|
||||
renderDataPicture->meshData.release(mContext);
|
||||
renderDataPicture->meshData.update(mContext, &geometryData);
|
||||
renderDataPicture->imageData.update(mContext, surface);
|
||||
|
|
|
@ -34,7 +34,7 @@ private:
|
|||
void release();
|
||||
public:
|
||||
RenderData prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override;
|
||||
RenderData prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
RenderData prepare(Surface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) override;
|
||||
bool preRender() override;
|
||||
bool renderShape(RenderData data) override;
|
||||
bool renderImage(RenderData data) override;
|
||||
|
|
|
@ -635,20 +635,6 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* p
|
|||
cnt += writeData(pixels, imgSize);
|
||||
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
||||
|
||||
//mesh: currently only available in bitmap image.
|
||||
const Polygon* triangles = nullptr;
|
||||
auto triangleCnt = picture->mesh(&triangles);
|
||||
if (triangles && triangleCnt > 0) {
|
||||
TvgBinCounter triangleCntSize = SIZE(triangleCnt);
|
||||
TvgBinCounter trianglesSize = triangleCnt * SIZE(triangles[0]);
|
||||
|
||||
writeTag(TVG_TAG_PICTURE_MESH);
|
||||
writeCount(triangleCntSize + trianglesSize);
|
||||
cnt += writeData(&triangleCnt, triangleCntSize);
|
||||
cnt += writeData(triangles, trianglesSize);
|
||||
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
||||
}
|
||||
|
||||
//Bitmap picture needs the transform info.
|
||||
cnt += writeTransform(cTransform, TVG_TAG_PAINT_TRANSFORM);
|
||||
|
||||
|
|
Binary file not shown.
|
@ -100,67 +100,6 @@ TEST_CASE("Load RAW file and render", "[tvgPicture]")
|
|||
free(data);
|
||||
}
|
||||
|
||||
TEST_CASE("Texture mesh", "[tvgPicture]")
|
||||
{
|
||||
auto picture = Picture::gen();
|
||||
REQUIRE(picture);
|
||||
|
||||
ifstream file(TEST_DIR"/rawimage_200x300.raw");
|
||||
if (!file.is_open()) return;
|
||||
auto data = (uint32_t*)malloc(sizeof(uint32_t) * (200*300));
|
||||
file.read(reinterpret_cast<char *>(data), sizeof (uint32_t) * 200 * 300);
|
||||
file.close();
|
||||
|
||||
REQUIRE(picture->load(data, 200, 300, false) == Result::Success);
|
||||
|
||||
//Composing Meshes
|
||||
tvg::Polygon triangles[4];
|
||||
triangles[0].vertex[0] = {{100, 125}, {0, 0}};
|
||||
triangles[0].vertex[1] = {{300, 100}, {0.5, 0}};
|
||||
triangles[0].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[1].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[1].vertex[1] = {{350, 450}, {0.5, 1}};
|
||||
triangles[1].vertex[2] = {{200, 550}, {0, 1}};
|
||||
|
||||
triangles[2].vertex[0] = {{300, 100}, {0.5, 0}};
|
||||
triangles[2].vertex[1] = {{500, 200}, {1, 0}};
|
||||
triangles[2].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
triangles[3].vertex[0] = {{500, 200}, {1, 0}};
|
||||
triangles[3].vertex[1] = {{450, 450}, {1, 1}};
|
||||
triangles[3].vertex[2] = {{350, 450}, {0.5, 1}};
|
||||
|
||||
//Negative cases
|
||||
const tvg::Polygon* triangles2 = nullptr;
|
||||
REQUIRE(picture->mesh(nullptr, 4) == tvg::Result::InvalidArguments);
|
||||
REQUIRE(picture->mesh(nullptr) == 0);
|
||||
REQUIRE(picture->mesh(&triangles2) == 0);
|
||||
REQUIRE(picture->mesh(triangles, 0) == tvg::Result::InvalidArguments);
|
||||
REQUIRE(picture->mesh(nullptr) == 0);
|
||||
REQUIRE(picture->mesh(&triangles2) == 0);
|
||||
|
||||
//Positive cases
|
||||
REQUIRE(picture->mesh(triangles, 4) == tvg::Result::Success);
|
||||
REQUIRE(picture->mesh(nullptr) == 4);
|
||||
REQUIRE(picture->mesh(&triangles2) == 4);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
for(int j = 0; j < 3; j++) {
|
||||
REQUIRE(triangles[i].vertex[j].pt.x == triangles2[i].vertex[j].pt.x);
|
||||
REQUIRE(triangles[i].vertex[j].pt.y == triangles2[i].vertex[j].pt.y);
|
||||
REQUIRE(triangles[i].vertex[j].uv.x == triangles2[i].vertex[j].uv.x);
|
||||
REQUIRE(triangles[i].vertex[j].uv.y == triangles2[i].vertex[j].uv.y);
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(picture->mesh(nullptr, 0) == tvg::Result::Success);
|
||||
REQUIRE(picture->mesh(nullptr) == 0);
|
||||
REQUIRE(picture->mesh(&triangles2) == 0);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
TEST_CASE("Picture Size", "[tvgPicture]")
|
||||
{
|
||||
auto picture = Picture::gen();
|
||||
|
|
Loading…
Add table
Reference in a new issue