/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 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
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
#include "tvgSwCommon.h"
#include "tvgBezier.h"
#include <float.h>
{
if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return false;
outline.reservedCntrsCnt = outline.cntrsCnt + n;
- outline.cntrs = static_cast<uint16_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint16_t)));
+ outline.cntrs = static_cast<uint32_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t)));
return true;
}
auto outlineCntrsCnt = 0;
for (uint32_t i = 0; i < cmdCnt; ++i) {
- switch(*(cmds + i)) {
+ switch (*(cmds + i)) {
case PathCommand::Close: {
++outlinePtsCnt;
break;
_growOutlineContour(*dash.outline, outlineCntrsCnt * 20);
while (cmdCnt-- > 0) {
- switch(*cmds) {
+ switch (*cmds) {
case PathCommand::Close: {
_dashLineTo(dash, &dash.ptStart, transform);
break;
}
-static bool _fastTrack(const SwOutline* outline, SwBBox& bbox)
+static bool _axisAlignedRect(const SwOutline* outline)
{
- //Fast Track: Othogonal rectangle?
+ //Fast Track: axis-aligned rectangle?
if (outline->ptsCnt != 5) return false;
- /* NOTICE: If the antialiased pixels matter, we can turn off the fast track
- in case the pixels have the pixel fraction. */
-
auto pt1 = outline->pts + 0;
auto pt2 = outline->pts + 1;
auto pt3 = outline->pts + 2;
auto a = SwPoint{pt1->x, pt3->y};
auto b = SwPoint{pt3->x, pt1->y};
- //Matched!
- if ((*pt2 == a && *pt4 == b) || (*pt2 == b && *pt4 == a)) {
- //Since no antialiasing is applied in the Fast Track case,
- //the rasterization region has to be rearranged.
- //https://github.com/Samsung/thorvg/issues/916
- auto corner1 = outline->pts;
- auto corner3 = outline->pts + 2;
-
- auto xMin = corner1->x;
- auto xMax = corner3->x;
- if (xMin > xMax) {
- xMax = xMin;
- xMin = corner3->x;
- }
-
- auto yMin = corner1->y;
- auto yMax = corner3->y;
- if (yMin > yMax) {
- yMax = yMin;
- yMin = corner3->y;
- }
-
- bbox.min.x = static_cast<SwCoord>(round(xMin / 64.0f));
- bbox.max.x = static_cast<SwCoord>(round(xMax / 64.0f));
- bbox.min.y = static_cast<SwCoord>(round(yMin / 64.0f));
- bbox.max.y = static_cast<SwCoord>(round(yMax / 64.0f));
-
- return true;
- }
+ if ((*pt2 == a && *pt4 == b) || (*pt2 == b && *pt4 == a)) return true;
return false;
}
-static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid)
+static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid, bool hasComposite)
{
const PathCommand* cmds = nullptr;
auto cmdCnt = sdata->pathCommands(&cmds);
auto closeCnt = 0;
for (uint32_t i = 0; i < cmdCnt; ++i) {
- switch(*(cmds + i)) {
+ switch (*(cmds + i)) {
case PathCommand::Close: {
++outlinePtsCnt;
++closeCnt;
//Generate Outlines
while (cmdCnt-- > 0) {
- switch(*cmds) {
+ switch (*cmds) {
case PathCommand::Close: {
_outlineClose(*outline);
break;
outline->fillRule = sdata->fillRule();
shape->outline = outline;
+ shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
return true;
}
/* External Class Implementation */
/************************************************************************/
-bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
+bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
{
- if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
- if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion)) return false;
+ if (!_genOutline(shape, sdata, transform, mpool, tid, hasComposite)) return false;
+ if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
//Keep it for Rasterization Region
shape->bbox = renderRegion;
}
-bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias, bool hasComposite)
+bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias)
{
//FIXME: Should we draw it?
//Case: Stroke Line
//if (shape.outline->opened) return true;
//Case A: Fast Track Rectangle Drawing
- if (!hasComposite && (shape->rect = _fastTrack(shape->outline, shape->bbox))) return true;
+ if (shape->fastTrack) return true;
//Case B: Normal Shape RLE Drawing
if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true;
{
rleReset(shape->rle);
rleReset(shape->strokeRle);
- shape->rect = false;
+ shape->fastTrack = false;
shape->bbox.reset();
}
//Normal Style stroke
} else {
if (!shape->outline) {
- if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
+ if (!_genOutline(shape, sdata, transform, mpool, tid, false)) return false;
}
shapeOutline = shape->outline;
}
}
strokeOutline = strokeExportOutline(shape->stroke, mpool, tid);
- if (!strokeOutline) {
- ret = false;
- goto fail;
- }
- if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion)) {
+ if (!mathUpdateOutlineBBox(strokeOutline, clipRegion, renderRegion, false)) {
ret = false;
goto fail;
}