Skip to content

Commit

Permalink
Remove the initial clip for Surface and fix rendering issues with inv…
Browse files Browse the repository at this point in the history
…erse fill paths.
  • Loading branch information
domchen committed Jan 22, 2025
1 parent 59ca683 commit c36ea7b
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 57 deletions.
1 change: 0 additions & 1 deletion include/tgfx/core/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ class Canvas {
std::stack<std::unique_ptr<CanvasState>> stateStack;

explicit Canvas(DrawContext* drawContext);
Canvas(DrawContext* drawContext, const Path& initClip);
void drawClip(const FillStyle& style);
void drawShape(std::shared_ptr<Shape> shape, const MCState& state, const FillStyle& style);
void drawImage(std::shared_ptr<Image> image, const SamplingOptions& sampling, const Paint* paint,
Expand Down
6 changes: 0 additions & 6 deletions src/core/Canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,12 @@ Canvas::Canvas(DrawContext* drawContext)
mcState = std::make_unique<MCState>();
}

Canvas::Canvas(DrawContext* drawContext, const Path& initClip)
: surface(drawContext->getSurface()), drawContext(drawContext) {
mcState = std::make_unique<MCState>(initClip);
}

int Canvas::save() {
stateStack.push(std::make_unique<CanvasState>(*mcState));
return static_cast<int>(stateStack.size()) - 1;
}

int Canvas::saveLayer(const Paint* paint) {

auto layer = std::make_unique<CanvasLayer>(drawContext, paint);
drawContext = layer->layerContext.get();
stateStack.push(std::make_unique<CanvasState>(*mcState, std::move(layer)));
Expand Down
8 changes: 7 additions & 1 deletion src/core/vectors/freetype/FTMask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,18 @@ void FTMask::onFillPath(const Path& path, const Matrix& matrix, bool antiAlias,
totalMatrix.postScale(1, -1);
totalMatrix.postTranslate(0, static_cast<float>(pixelRef->height()));
finalPath.transform(totalMatrix);
if (finalPath.isInverseFillType()) {
Path maskPath = {};
maskPath.addRect(Rect::MakeWH(info.width(), info.height()));
finalPath.addPath(maskPath, PathOp::Intersect);
}
auto bounds = finalPath.getBounds();
bounds.roundOut();
markContentDirty(bounds, true);
FTPath ftPath = {};
finalPath.decompose(Iterator, &ftPath);
ftPath.setFillType(path.getFillType());
auto fillType = finalPath.getFillType();
ftPath.setEvenOdd(fillType == PathFillType::EvenOdd || fillType == PathFillType::InverseEvenOdd);
auto outlines = ftPath.getOutlines();
auto ftLibrary = FTLibrary::Get();
if (!needsGammaCorrection) {
Expand Down
15 changes: 1 addition & 14 deletions src/core/vectors/freetype/FTPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,7 @@ bool FTPath::finalizeOutline(FreetypeOutline* outline, size_t startPointIndex) c
outline->outline.contours = reinterpret_cast<unsigned short*>(outline->contours.data());
outline->outline.n_points = static_cast<unsigned short>(endPointIndex + 1);
outline->outline.n_contours = static_cast<unsigned short>(outline->contours.size());
switch (getFillType()) {
case PathFillType::EvenOdd:
outline->outline.flags = FT_OUTLINE_EVEN_ODD_FILL;
break;
case PathFillType::InverseEvenOdd:
outline->outline.flags = FT_OUTLINE_EVEN_ODD_FILL | FT_OUTLINE_REVERSE_FILL;
break;
case PathFillType::Winding:
outline->outline.flags = FT_OUTLINE_NONE;
break;
case PathFillType::InverseWinding:
outline->outline.flags = FT_OUTLINE_REVERSE_FILL;
break;
}
outline->outline.flags = evenOdd ? FT_OUTLINE_EVEN_ODD_FILL : FT_OUTLINE_NONE;
return true;
}

Expand Down
10 changes: 5 additions & 5 deletions src/core/vectors/freetype/FTPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ struct FreetypeOutline {

class FTPath {
public:
PathFillType getFillType() const {
return fillType;
bool isEvenOdd() const {
return evenOdd;
}

void setFillType(PathFillType type) {
fillType = type;
void setEvenOdd(bool value) {
evenOdd = value;
}

bool isEmpty() const;
Expand All @@ -53,6 +53,6 @@ class FTPath {
std::vector<PathVerb> verbs = {};
std::vector<char> tags = {};
std::vector<size_t> contours = {};
PathFillType fillType = PathFillType::Winding;
bool evenOdd = false;
};
} // namespace tgfx
49 changes: 28 additions & 21 deletions src/gpu/RenderContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,26 @@ void RenderContext::drawRRect(const RRect& rRect, const MCState& state, const Fi
addDrawOp(std::move(drawOp), rRect.rect, state, style);
}

static Rect ToLocalBounds(const Rect& bounds, const Matrix& viewMatrix) {
Matrix invertMatrix = {};
if (!viewMatrix.invert(&invertMatrix)) {
return Rect::MakeEmpty();
}
auto localBounds = bounds;
invertMatrix.mapRect(&localBounds);
return localBounds;
}

void RenderContext::drawShape(std::shared_ptr<Shape> shape, const MCState& state,
const FillStyle& style) {
DEBUG_ASSERT(shape != nullptr);
auto maxScale = state.matrix.getMaxScale();
if (maxScale <= 0.0f) {
return;
}
auto bounds = shape->getBounds(maxScale);
auto clipBounds = getClipBounds(state.clip);
auto bounds = shape->isInverseFillType() ? ToLocalBounds(clipBounds, state.matrix)
: shape->getBounds(maxScale);
auto drawOp =
ShapeDrawOp::Make(style.color.premultiply(), std::move(shape), state.matrix, clipBounds);
addDrawOp(std::move(drawOp), bounds, state, style);
Expand Down Expand Up @@ -208,14 +219,10 @@ void RenderContext::drawLayer(std::shared_ptr<Picture> picture, std::shared_ptr<
const MCState& state, const FillStyle& style) {
DEBUG_ASSERT(style.shader == nullptr);
Matrix viewMatrix = {};
auto bounds = Rect::MakeEmpty();
Rect bounds = {};
if (filter || style.maskFilter) {
if (picture->hasUnboundedFill()) {
Matrix invertMatrix = {};
if (state.matrix.invert(&invertMatrix)) {
bounds = getClipBounds(state.clip);
invertMatrix.mapRect(&bounds);
}
bounds = ToLocalBounds(getClipBounds(state.clip), state.matrix);
} else {
bounds = picture->getBounds();
}
Expand Down Expand Up @@ -305,22 +312,22 @@ static void FlipYIfNeeded(Rect* rect, const RenderTargetProxy* renderTarget) {
std::pair<std::optional<Rect>, bool> RenderContext::getClipRect(const Path& clip,
const Rect* deviceBounds) {
auto rect = Rect::MakeEmpty();
if (clip.isRect(&rect)) {
if (deviceBounds != nullptr && !rect.intersect(*deviceBounds)) {
return {{}, false};
}
auto renderTarget = opContext->renderTarget();
FlipYIfNeeded(&rect, renderTarget);
if (IsPixelAligned(rect)) {
rect.round();
if (rect != Rect::MakeWH(renderTarget->width(), renderTarget->height())) {
return {rect, true};
}
return {Rect::MakeEmpty(), false};
if (clip.isInverseFillType() || !clip.isRect(&rect)) {
return {{}, false};
}
if (deviceBounds != nullptr && !rect.intersect(*deviceBounds)) {
return {{}, false};
}
auto renderTarget = opContext->renderTarget();
FlipYIfNeeded(&rect, renderTarget);
if (IsPixelAligned(rect)) {
rect.round();
if (rect != Rect::MakeWH(renderTarget->width(), renderTarget->height())) {
return {rect, true};
}
return {rect, false};
return {Rect::MakeEmpty(), false};
}
return {{}, false};
return {rect, false};
}

std::shared_ptr<TextureProxy> RenderContext::getClipTexture(const Path& clip, AAType aaType) {
Expand Down
8 changes: 1 addition & 7 deletions src/gpu/Surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,10 @@ HardwareBufferRef Surface::getHardwareBuffer() {
return texture->getHardwareBuffer();
}

static Path GetInitClip(int width, int height) {
Path path = {};
path.addRect(Rect::MakeWH(width, height));
return path;
}

Canvas* Surface::getCanvas() {
if (canvas == nullptr) {
renderContext = new RenderContext(this);
canvas = new Canvas(renderContext, GetInitClip(width(), height()));
canvas = new Canvas(renderContext);
}
return canvas;
}
Expand Down
4 changes: 2 additions & 2 deletions test/baseline/version.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"Path_addArc_reversed7": "4802e56",
"Path_addArc_reversed8": "4802e56",
"Path_complex": "e031f25",
"Picture": "002c391",
"Picture": "59ca683",
"PictureImage": "3b0ec3b",
"PictureImage_Path": "2212c4e",
"PictureImage_Text": "b062b9a",
Expand All @@ -39,7 +39,7 @@
"filter_mode_nearest": "d010fb8",
"hardware_render_target_blend": "d010fb8",
"inversePath_rect": "6fd4617",
"inversePath_text": "3b0ec3b",
"inversePath_text": "59ca683",
"merge_draw_call_rect": "d010fb8",
"merge_draw_call_rrect": "d010fb8",
"merge_draw_clear_op": "d010fb8",
Expand Down
1 change: 1 addition & 0 deletions test/src/CanvasTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ TGFX_TEST(CanvasTest, merge_draw_clear_op) {
auto surface = Surface::Make(context, width, height);
auto canvas = surface->getCanvas();
canvas->clear(Color::White());
canvas->clipRect(Rect::MakeWH(width, height));
canvas->save();
Path path;
path.addRect(Rect::MakeXYWH(0.f, 0.f, 10.f, 10.f));
Expand Down

0 comments on commit c36ea7b

Please sign in to comment.