diff --git a/src/CanvasComponents/BrushStrokeCanvasComponent.cpp b/src/CanvasComponents/BrushStrokeCanvasComponent.cpp index 6a824a0..86f1b0a 100644 --- a/src/CanvasComponents/BrushStrokeCanvasComponent.cpp +++ b/src/CanvasComponents/BrushStrokeCanvasComponent.cpp @@ -53,6 +53,7 @@ std::optional BrushStrokeCanvasComponent::get_stroke_color() const { void BrushStrokeCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr& predrawData) const { SkPaint paint; paint.setColor4f(SkColor4f{d.color.x(), d.color.y(), d.color.z(), d.color.w()}); + paint.setAntiAlias(drawData.skiaAA); unsigned mipmapLevel = compContainer ? compContainer->get_mipmap_level(drawData) : 0; diff --git a/src/CanvasComponents/EllipseCanvasComponent.cpp b/src/CanvasComponents/EllipseCanvasComponent.cpp index 33ad21b..7687640 100644 --- a/src/CanvasComponents/EllipseCanvasComponent.cpp +++ b/src/CanvasComponents/EllipseCanvasComponent.cpp @@ -35,6 +35,7 @@ std::optional EllipseCanvasComponent::get_stroke_color() const { void EllipseCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr& predrawData) const { SkPaint p; + p.setAntiAlias(drawData.skiaAA); if(d.fillStrokeMode == 0 || d.fillStrokeMode == 2) { p.setStyle(SkPaint::kFill_Style); p.setColor4f(convert_vec4(d.fillColor)); diff --git a/src/CanvasComponents/ImageCanvasComponent.cpp b/src/CanvasComponents/ImageCanvasComponent.cpp index 77b4be3..aafd620 100644 --- a/src/CanvasComponents/ImageCanvasComponent.cpp +++ b/src/CanvasComponents/ImageCanvasComponent.cpp @@ -65,6 +65,7 @@ void ImageCanvasComponent::draw_download_progress_bar(SkCanvas* canvas, const Dr p.setStrokeWidth(10.0f); p.setStrokeCap(SkPaint::kRound_Cap); p.setColor4f(drawData.main->toolbar.io->theme->fillColor1); + p.setAntiAlias(drawData.skiaAA); Vector2f center = (d.p1 + d.p2) * 0.5f; const float DOWNLOAD_ARC_RADIUS = 50.0f; @@ -94,10 +95,12 @@ void ImageCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, cons canvas->saveLayerAlphaf(nullptr, 1.0f); SkPaint rectPaint; rectPaint.setColor4f(SkColor4f{0.0f, 0.0f, 0.0f, 0.5f}); + rectPaint.setAntiAlias(drawData.skiaAA); canvas->drawRect(rect_from_points(d.p1, d.p2), rectPaint); SkPaint openingRectPaint; openingRectPaint.setColor4f(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f}); openingRectPaint.setBlendMode(SkBlendMode::kSrc); + openingRectPaint.setAntiAlias(drawData.skiaAA); canvas->drawRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2), openingRectPaint); canvas->restore(); canvas->restore(); @@ -106,13 +109,16 @@ void ImageCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, cons bool isCropped = d.cropP1 != Vector2f{0.0f, 0.0f} || d.cropP2 != Vector2f{1.0f, 1.0f}; if(isCropped) { canvas->save(); - canvas->clipRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2)); + canvas->clipRect(get_cropped_rectangle(d.p1, d.p2, d.cropP1, d.cropP2), drawData.skiaAA); } if(display) display->draw(canvas, drawData, rect_from_points(d.p1, d.p2)); - else - canvas->drawRect(rect_from_points(d.p1, d.p2), SkPaint({0.5f, 0.5f, 0.5f, 0.5f})); + else { + SkPaint p(SkColor4f{0.5f, 0.5f, 0.5f, 0.5f}); + p.setAntiAlias(drawData.skiaAA); + canvas->drawRect(rect_from_points(d.p1, d.p2), p); + } if(isCropped) canvas->restore(); diff --git a/src/CanvasComponents/RectangleCanvasComponent.cpp b/src/CanvasComponents/RectangleCanvasComponent.cpp index 12d12e2..85addbf 100644 --- a/src/CanvasComponents/RectangleCanvasComponent.cpp +++ b/src/CanvasComponents/RectangleCanvasComponent.cpp @@ -42,15 +42,15 @@ std::unique_ptr RectangleCanvasComponent::get_data_copy() const } void RectangleCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr& predrawData) const { + SkPaint p; + p.setAntiAlias(drawData.skiaAA); if(d.fillStrokeMode == 0 || d.fillStrokeMode == 2) { - SkPaint p; p.setStyle(SkPaint::kFill_Style); p.setStrokeCap(SkPaint::kRound_Cap); p.setColor4f(convert_vec4(d.fillColor)); canvas->drawPath(rectPath, p); } if(d.fillStrokeMode == 1 || d.fillStrokeMode == 2) { - SkPaint p; p.setStyle(SkPaint::kStroke_Style); p.setStrokeCap(SkPaint::kRound_Cap); p.setColor4f(convert_vec4(d.strokeColor)); diff --git a/src/CanvasComponents/TextBoxCanvasComponent.cpp b/src/CanvasComponents/TextBoxCanvasComponent.cpp index 6f395f5..332af1d 100644 --- a/src/CanvasComponents/TextBoxCanvasComponent.cpp +++ b/src/CanvasComponents/TextBoxCanvasComponent.cpp @@ -83,6 +83,7 @@ void TextBoxCanvasComponent::draw(SkCanvas* canvas, const DrawData& drawData, co SkRect clipR = SkRect::MakeLTRB(d.p1.x(), d.p1.y(), d.p2.x(), d.p2.y()); if(d.editing) { SkPaint p; + p.setAntiAlias(drawData.skiaAA); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(0.0f); p.setColor4f({0.5f, 0.5f, 0.5f, 1.0f}); diff --git a/src/DrawData.hpp b/src/DrawData.hpp index 9e1988d..a4af1ec 100644 --- a/src/DrawData.hpp +++ b/src/DrawData.hpp @@ -17,6 +17,7 @@ struct DrawData { bool clampDrawBetween = true; bool drawGrids = true; bool transparentBackground = false; + bool skiaAA = false; WorldScalar clampDrawMinimum; WorldScalar mipMapLevelOne; WorldScalar mipMapLevelTwo; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index b181fcd..686ce41 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -512,7 +512,7 @@ bool DrawingProgram::prevent_undo_or_redo() { return drawTool->prevent_undo_or_redo(); } -SkPaint DrawingProgram::select_tool_line_paint() { +SkPaint DrawingProgram::select_tool_line_paint(const DrawData& drawData) { SkScalar intervals[] = {10, 5}; float timeSinceEpoch = std::chrono::duration_cast>(std::chrono::steady_clock::now().time_since_epoch()).count(); sk_sp lassoLineDashEffect = SkDashPathEffect::Make({intervals, 2}, -std::fmod(timeSinceEpoch * 50, 15)); @@ -523,6 +523,7 @@ SkPaint DrawingProgram::select_tool_line_paint() { selectLinePaint.setColor4f(world.canvasTheme.get_tool_front_color()); selectLinePaint.setPathEffect(lassoLineDashEffect); selectLinePaint.setBlender(CanvasTheme::get_visible_blend_mode()); + selectLinePaint.setAntiAlias(drawData.skiaAA); return selectLinePaint; } @@ -648,6 +649,7 @@ void DrawingProgram::draw_drag_circle(SkCanvas* canvas, const Vector2f& sPos, co SkPaint paintOutline(SkColor4f{0.95f, 0.95f, 0.95f, 1.0f}); paintOutline.setStroke(true); paintOutline.setStrokeWidth(constantThickness); + paintOutline.setAntiAlias(drawData.skiaAA); canvas->drawCircle(sPos.x(), sPos.y(), constantRadius, paintOutline); } diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 0232bd1..94b6b9c 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -85,7 +85,7 @@ class DrawingProgram { float drag_point_radius(); void draw_drag_circle(SkCanvas* canvas, const Vector2f& pos, const SkColor4f& c, const DrawData& drawData, float radiusMultiplier = 1.0f); - SkPaint select_tool_line_paint(); + SkPaint select_tool_line_paint(const DrawData& drawData); bool is_actual_selection_tool(DrawingProgramToolType typeToCheck); bool is_selection_allowing_tool(DrawingProgramToolType typeToCheck); diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 5b1b342..85a7d20 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -327,7 +327,6 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptrwindow.size != windowCache.size) { + if(windowCache.surface == nullptr) { allocate_window_cache_area(); refresh_all_draw_cache(drawData); window_cache_complete_refresh(drawData); diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index fd348a7..993e7fa 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -55,7 +55,6 @@ class DrawingProgramCache { sk_sp surface; DrawingProgramCache* attachedDrawingProgramCache = nullptr; std::optional> invalidBounds; - Vector2i size = {0, 0}; CoordSpaceHelper coords; }; static WindowCache windowCache; diff --git a/src/DrawingProgram/Tools/BrushTool.cpp b/src/DrawingProgram/Tools/BrushTool.cpp index f649b3a..533da3d 100644 --- a/src/DrawingProgram/Tools/BrushTool.cpp +++ b/src/DrawingProgram/Tools/BrushTool.cpp @@ -195,6 +195,7 @@ void BrushTool::draw(SkCanvas* canvas, const DrawData& drawData) { width += 1.0f; Vector2f pos = drawData.main->input.mouse.pos; SkPaint linePaint; + linePaint.setAntiAlias(drawData.skiaAA); linePaint.setColor4f({1.0f, 1.0f, 1.0f, 1.0f}); linePaint.setStyle(SkPaint::kStroke_Style); linePaint.setStrokeCap(SkPaint::kRound_Cap); diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 5763781..b1e699d 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -120,6 +120,7 @@ void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { if(relativeWidthResult.first.has_value()) { float width = relativeWidthResult.first.value() * 0.5f; SkPaint linePaint; + linePaint.setAntiAlias(drawData.skiaAA); linePaint.setColor4f({1.0f, 1.0f, 1.0f, 0.5f}); linePaint.setStyle(SkPaint::kStroke_Style); linePaint.setStrokeCap(SkPaint::kRound_Cap); diff --git a/src/DrawingProgram/Tools/EyeDropperTool.cpp b/src/DrawingProgram/Tools/EyeDropperTool.cpp index 8baa425..0bb4f43 100644 --- a/src/DrawingProgram/Tools/EyeDropperTool.cpp +++ b/src/DrawingProgram/Tools/EyeDropperTool.cpp @@ -44,7 +44,7 @@ void EyeDropperTool::input_mouse_button_on_canvas_callback(const InputManager::M auto& selectingStrokeColor = drawP.world.main.toolConfig.eyeDropper.selectingStrokeColor; if(button.button == InputManager::MouseButton::LEFT && button.down && !drawP.selection.is_being_transformed()) { - auto& surface = drawP.world.main.window.surface; + auto& surface = drawP.world.main.window.intermediateSurface; int xPos = std::clamp(button.pos.x(), 0, drawP.world.main.window.size.x() - 1); int yPos = std::clamp(button.pos.y(), 0, drawP.world.main.window.size.y() - 1); diff --git a/src/DrawingProgram/Tools/GridModifyTool.cpp b/src/DrawingProgram/Tools/GridModifyTool.cpp index b5b7c62..bfdd095 100644 --- a/src/DrawingProgram/Tools/GridModifyTool.cpp +++ b/src/DrawingProgram/Tools/GridModifyTool.cpp @@ -184,6 +184,7 @@ void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) { rectBoundsPaint.setColor4f(drawP.world.canvasTheme.get_tool_front_color()); rectBoundsPaint.setStroke(true); rectBoundsPaint.setStrokeWidth(0.0f); + rectBoundsPaint.setAntiAlias(drawData.skiaAA); canvas->drawRect(SkRect::MakeLTRB(bMin.x(), bMin.y(), bMax.x(), bMax.y()), rectBoundsPaint); if(selectionMode == 0 || selectionMode == 4) drawP.draw_drag_circle(canvas, bMax, {0.9f, 0.5f, 0.1f, 1.0f}, drawData); diff --git a/src/DrawingProgram/Tools/LassoSelectTool.cpp b/src/DrawingProgram/Tools/LassoSelectTool.cpp index f0462c3..c178b8a 100644 --- a/src/DrawingProgram/Tools/LassoSelectTool.cpp +++ b/src/DrawingProgram/Tools/LassoSelectTool.cpp @@ -136,7 +136,7 @@ void LassoSelectTool::draw(SkCanvas* canvas, const DrawData& drawData) { for(Vector2f& p : controls.lassoPoints | std::views::drop(1)) lassoPath.lineTo(convert_vec2(p)); - canvas->drawPath(lassoPath.detach(), drawP.select_tool_line_paint()); + canvas->drawPath(lassoPath.detach(), drawP.select_tool_line_paint(drawData)); canvas->restore(); } diff --git a/src/DrawingProgram/Tools/RectSelectTool.cpp b/src/DrawingProgram/Tools/RectSelectTool.cpp index de46eb9..6398cac 100644 --- a/src/DrawingProgram/Tools/RectSelectTool.cpp +++ b/src/DrawingProgram/Tools/RectSelectTool.cpp @@ -97,7 +97,7 @@ void RectSelectTool::draw(SkCanvas* canvas, const DrawData& drawData) { controls.coords.transform_sk_canvas(canvas, drawData); SkRect r = SkRect::MakeLTRB(newT[0].x(), newT[0].y(), newT[2].x(), newT[2].y()); - canvas->drawRect(r, drawP.select_tool_line_paint()); + canvas->drawRect(r, drawP.select_tool_line_paint(drawData)); canvas->restore(); } diff --git a/src/GUIStuff/Elements/CheckBox.cpp b/src/GUIStuff/Elements/CheckBox.cpp index d7f303e..224e874 100644 --- a/src/GUIStuff/Elements/CheckBox.cpp +++ b/src/GUIStuff/Elements/CheckBox.cpp @@ -21,7 +21,7 @@ void CheckBox::update(UpdateInputData& io, bool newIsTicked, const std::function } } -void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { auto bb = get_bb(command); canvas->save(); @@ -30,6 +30,7 @@ void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderComma canvas->translate(0.5f, 0.5f); SkPaint p; + p.setAntiAlias(skiaAA); if(isTicked) { SkRect checkBox = SkRect::MakeLTRB(-0.5f, -0.5f, 0.5f, 0.5f); p.setColor4f(convert_vec4(io.theme->fillColor1)); @@ -47,6 +48,7 @@ void CheckBox::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderComma if(isTicked) { SkPaint checkP; + checkP.setAntiAlias(skiaAA); checkP.setColor4f(io.theme->backColor1); checkP.setStyle(SkPaint::kFill_Style); checkP.setStrokeWidth(0.12); diff --git a/src/GUIStuff/Elements/CheckBox.hpp b/src/GUIStuff/Elements/CheckBox.hpp index c171dbc..601fc1f 100644 --- a/src/GUIStuff/Elements/CheckBox.hpp +++ b/src/GUIStuff/Elements/CheckBox.hpp @@ -6,7 +6,7 @@ namespace GUIStuff { class CheckBox : public Element { public: void update(UpdateInputData& io, bool newIsTicked, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; private: static constexpr float CHECKBOX_ANIMATION_TIME = 0.3; diff --git a/src/GUIStuff/Elements/ColorPicker.hpp b/src/GUIStuff/Elements/ColorPicker.hpp index d6566bd..0a3de65 100644 --- a/src/GUIStuff/Elements/ColorPicker.hpp +++ b/src/GUIStuff/Elements/ColorPicker.hpp @@ -77,20 +77,21 @@ template class ColorPicker : public Element { return isChanged; } - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { bb = get_bb(command); canvas->save(); canvas->translate(bb.min.x(), bb.min.y()); float svSelectionAreaSize = get_sv_selection_area_size(); canvas->scale(svSelectionAreaSize, svSelectionAreaSize); - canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f)); + canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA); SkPaint svSelectionAreaPaint; svSelectionAreaPaint.setShader(get_sv_selection_shader(savedHsv.x() / 360.0f)); canvas->drawPaint(svSelectionAreaPaint); SkPaint selectionLinePaint({1.0f, 1.0f, 1.0f, 1.0f}); + selectionLinePaint.setAntiAlias(skiaAA); selectionLinePaint.setStrokeWidth(2.0f / svSelectionAreaSize); canvas->drawLine(0.0f, 1.0f - savedHsv.z(), 1.0f, 1.0f - savedHsv.z(), selectionLinePaint); canvas->drawLine(savedHsv.y(), 0.0f, savedHsv.y(), 1.0f, selectionLinePaint); @@ -104,7 +105,7 @@ template class ColorPicker : public Element { canvas->save(); canvas->translate(hueBarPos.x(), hueBarPos.y()); canvas->scale(hueBarDim.x(), hueBarDim.y()); - canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f)); + canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, 1.0f, 1.0f), skiaAA); SkPaint hueBarPaint; hueBarPaint.setShader(get_hue_shader()); @@ -117,7 +118,7 @@ template class ColorPicker : public Element { Vector2f alphaBarDim = get_alpha_bar_dim(); canvas->save(); canvas->translate(alphaBarPos.x(), alphaBarPos.y()); - canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, alphaBarDim.x(), alphaBarDim.y())); + canvas->clipRect(SkRect::MakeXYWH(0.0f, 0.0f, alphaBarDim.x(), alphaBarDim.y()), skiaAA); SkPaint alphaBarPaint; if(selectAlpha) diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index 145d1ad..11d854c 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -139,7 +139,7 @@ class SelectionHelper { class Element { public: - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) = 0; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) = 0; virtual ~Element() = default; protected: diff --git a/src/GUIStuff/Elements/FontPicker.cpp b/src/GUIStuff/Elements/FontPicker.cpp index 23863b3..702237c 100644 --- a/src/GUIStuff/Elements/FontPicker.cpp +++ b/src/GUIStuff/Elements/FontPicker.cpp @@ -183,5 +183,5 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU return fontChangedFromSelection | fontChangedFromTextbox; } -void GUIStuff::FontPicker::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void GUIStuff::FontPicker::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { } diff --git a/src/GUIStuff/Elements/FontPicker.hpp b/src/GUIStuff/Elements/FontPicker.hpp index d143b8b..935bf0c 100644 --- a/src/GUIStuff/Elements/FontPicker.hpp +++ b/src/GUIStuff/Elements/FontPicker.hpp @@ -7,7 +7,7 @@ namespace GUIStuff { class FontPicker : public Element { public: bool update(UpdateInputData& io, std::string* fontName, GUIManager* gui); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; private: std::vector sortedFontList; diff --git a/src/GUIStuff/Elements/MovableTabList.cpp b/src/GUIStuff/Elements/MovableTabList.cpp index 7305059..c6a70ed 100644 --- a/src/GUIStuff/Elements/MovableTabList.cpp +++ b/src/GUIStuff/Elements/MovableTabList.cpp @@ -74,7 +74,7 @@ void MovableTabList::update(UpdateInputData& io, const std::vector>& tabNames, size_t& selectedTab, std::optional& closedTab, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; private: std::vector> oldTabNames; diff --git a/src/GUIStuff/Elements/NumberSlider.hpp b/src/GUIStuff/Elements/NumberSlider.hpp index 78cbffd..3f1d47c 100644 --- a/src/GUIStuff/Elements/NumberSlider.hpp +++ b/src/GUIStuff/Elements/NumberSlider.hpp @@ -35,7 +35,7 @@ template class NumberSlider : public Element { return isUpdating; } - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override { + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override { bb = get_bb(command); canvas->save(); @@ -59,10 +59,12 @@ template class NumberSlider : public Element { SkRect barEmpty = SkRect::MakeXYWH(holderPos, yChange, bb.width() - holderPos, holderRadius); SkPaint barFullP; + barFullP.setAntiAlias(skiaAA); barFullP.setColor(convert_vec4(io.theme->fillColor1)); canvas->drawRoundRect(barFull, 5.0f, 5.0f, barFullP); SkPaint barEmptyP; + barEmptyP.setAntiAlias(skiaAA); barEmptyP.setColor(convert_vec4(io.theme->backColor2)); canvas->drawRoundRect(barEmpty, 5.0f, 5.0f, barEmptyP); @@ -70,12 +72,14 @@ template class NumberSlider : public Element { SkRect holderRect = SkRect::MakeLTRB(-holderRadius, -holderHeight, holderRadius, holderHeight); SkPaint holderBorderP; + holderBorderP.setAntiAlias(skiaAA); holderBorderP.setStyle(SkPaint::kStroke_Style); holderBorderP.setStrokeWidth(3.0f); holderBorderP.setColor(convert_vec4(io.theme->fillColor1)); canvas->drawRoundRect(holderRect, holderRadius, holderRadius, holderBorderP); SkPaint holderP; + holderP.setAntiAlias(skiaAA); holderP.setColor(convert_vec4(io.theme->backColor2)); canvas->drawRoundRect(holderRect, holderRadius, holderRadius, holderP); diff --git a/src/GUIStuff/Elements/PaintCircleMenu.cpp b/src/GUIStuff/Elements/PaintCircleMenu.cpp index 1c07005..38805d2 100644 --- a/src/GUIStuff/Elements/PaintCircleMenu.cpp +++ b/src/GUIStuff/Elements/PaintCircleMenu.cpp @@ -64,27 +64,29 @@ void PaintCircleMenu::update(GUIManager& gui, const Data& data, const std::funct d = data; } -void PaintCircleMenu::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void PaintCircleMenu::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { bb = get_bb(command); canvas->save(); canvas->translate(bb.center().x(), bb.center().y()); - draw_rotate_bar(canvas, io); - draw_palette_bar(canvas, io); + draw_rotate_bar(canvas, io, skiaAA); + draw_palette_bar(canvas, io, skiaAA); SkPaint p; + p.setAntiAlias(skiaAA); p.setColor4f(color_mul_alpha(io.theme->backColor1, 0.5f)); canvas->drawCircle(0.0f, 0.0f, PALETTE_START, p); canvas->restore(); } -void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) { +void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) { if(!d.newRotationAngle) return; double rotationAngle = d.currentRotationAngle; float rotateBarMiddleRadius = (CIRCLE_END + ROTATE_START) / 2.0f; SkPaint rotateBarFill(io.theme->backColor2); + rotateBarFill.setAntiAlias(skiaAA); rotateBarFill.setStroke(true); rotateBarFill.setStrokeWidth(CIRCLE_END - ROTATE_START); canvas->drawCircle(0.0f, 0.0f, rotateBarMiddleRadius, rotateBarFill); @@ -93,12 +95,14 @@ void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) { for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) { Vector2f lineDir{std::cos(snapPos), -std::sin(snapPos)}; SkPaint p(snapPos == 0.0 ? io.theme->fillColor1 : io.theme->frontColor2); + p.setAntiAlias(skiaAA); p.setStrokeWidth(2.0f); canvas->drawLine(lineDir.x() * ROTATE_START, lineDir.y() * ROTATE_START, lineDir.x() * CIRCLE_END, lineDir.y() * CIRCLE_END, p); } } SkPaint rotateBarHolderFill; + rotateBarHolderFill.setAntiAlias(skiaAA); if(rotateBarSelect.held) rotateBarHolderFill.setColor4f(io.theme->fillColor1); else if(rotateBarSelect.hovered) @@ -109,18 +113,20 @@ void PaintCircleMenu::draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io) { Vector2f rotateBarHolderPos{std::cos(rotationAngle) * rotateBarMiddleRadius, -std::sin(rotationAngle) * rotateBarMiddleRadius}; canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderFill); SkPaint rotateBarHolderOutline(io.theme->frontColor1); + rotateBarHolderOutline.setAntiAlias(skiaAA); rotateBarHolderOutline.setStroke(true); rotateBarHolderOutline.setStrokeWidth(2.0f); canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderOutline); SkPaint rotateBarOutline(io.theme->frontColor2); + rotateBarOutline.setAntiAlias(skiaAA); rotateBarOutline.setStroke(true); rotateBarOutline.setStrokeWidth(2.0f); canvas->drawCircle(0.0f, 0.0f, ROTATE_START, rotateBarOutline); canvas->drawCircle(0.0f, 0.0f, CIRCLE_END, rotateBarOutline); } -void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) { +void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) { if(d.palette.empty() || !d.selectedColor) return; @@ -133,18 +139,21 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) { double angleEnd = (i + 1) * colorDistribution; SkPaint colorP(SkColor4f{d.palette[i].x(), d.palette[i].y(), d.palette[i].z(), 1.0f}); + colorP.setAntiAlias(skiaAA); colorP.setStroke(true); colorP.setStrokeWidth(ROTATE_START - PALETTE_START); canvas->drawArc(colorOval, angleStart * 180.0 / std::numbers::pi, (angleEnd - angleStart) * 180.0 / std::numbers::pi, false, colorP); Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)}; SkPaint lineP(io.theme->frontColor2); + lineP.setAntiAlias(skiaAA); lineP.setStrokeWidth(2.0f); lineP.setStroke(true); canvas->drawLine(lineDir1.x() * PALETTE_START, lineDir1.y() * PALETTE_START, lineDir1.x() * ROTATE_START, lineDir1.y() * ROTATE_START, lineP); } SkPaint barOutline(io.theme->frontColor2); + barOutline.setAntiAlias(skiaAA); barOutline.setStroke(true); barOutline.setStrokeWidth(2.0f); canvas->drawCircle(0.0f, 0.0f, PALETTE_START, barOutline); @@ -159,6 +168,7 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) { Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)}; Vector2f lineDir2{std::cos(angleEnd), std::sin(angleEnd)}; SkPaint lineP(io.theme->fillColor1); + lineP.setAntiAlias(skiaAA); lineP.setStrokeWidth(5.0f); lineP.setStroke(true); lineP.setStrokeJoin(SkPaint::kRound_Join); @@ -178,6 +188,7 @@ void PaintCircleMenu::draw_palette_bar(SkCanvas* canvas, UpdateInputData& io) { Vector2f lineDir1{std::cos(angleStart), std::sin(angleStart)}; Vector2f lineDir2{std::cos(angleEnd), std::sin(angleEnd)}; SkPaint lineP(io.theme->fillColor1); + lineP.setAntiAlias(skiaAA); lineP.setStrokeWidth(5.0f); lineP.setStroke(true); lineP.setStrokeJoin(SkPaint::kRound_Join); diff --git a/src/GUIStuff/Elements/PaintCircleMenu.hpp b/src/GUIStuff/Elements/PaintCircleMenu.hpp index 1bb6a77..6af9dca 100644 --- a/src/GUIStuff/Elements/PaintCircleMenu.hpp +++ b/src/GUIStuff/Elements/PaintCircleMenu.hpp @@ -14,10 +14,10 @@ class PaintCircleMenu : public Element { std::vector palette; }; void update(GUIManager& gui, const Data& data, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; private: - void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io); - void draw_palette_bar(SkCanvas* canvas, UpdateInputData& io); + void draw_rotate_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA); + void draw_palette_bar(SkCanvas* canvas, UpdateInputData& io, bool skiaAA); Data d; SCollision::AABB bb; SelectionHelper rotateBarSelect; diff --git a/src/GUIStuff/Elements/RadioButton.cpp b/src/GUIStuff/Elements/RadioButton.cpp index 25e79fc..4795a2f 100644 --- a/src/GUIStuff/Elements/RadioButton.cpp +++ b/src/GUIStuff/Elements/RadioButton.cpp @@ -19,7 +19,7 @@ void RadioButton::update(UpdateInputData& io, bool newIsTicked, const std::funct } } -void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { auto bb = get_bb(command); canvas->save(); @@ -29,11 +29,13 @@ void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCo if(isTicked) { SkPaint p; + p.setAntiAlias(skiaAA); p.setColor4f(convert_vec4(io.theme->fillColor1)); p.setStyle(SkPaint::kFill_Style); canvas->drawCircle(0.0f, 0.0f, 0.5f, p); SkPaint innerCircleP; + innerCircleP.setAntiAlias(skiaAA); innerCircleP.setColor4f(convert_vec4(io.theme->backColor2)); innerCircleP.setStyle(SkPaint::kFill_Style); @@ -45,6 +47,7 @@ void RadioButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCo } else { SkPaint p; + p.setAntiAlias(skiaAA); p.setColor4f(convert_vec4(selection.hovered ? io.theme->fillColor1 : io.theme->backColor2)); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(0.15f); diff --git a/src/GUIStuff/Elements/RadioButton.hpp b/src/GUIStuff/Elements/RadioButton.hpp index 71d1191..e513c6f 100644 --- a/src/GUIStuff/Elements/RadioButton.hpp +++ b/src/GUIStuff/Elements/RadioButton.hpp @@ -6,7 +6,7 @@ namespace GUIStuff { class RadioButton : public Element { public: void update(UpdateInputData& io, bool newIsTicked, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; private: static constexpr float RADIOBUTTON_ANIMATION_TIME = 0.3; diff --git a/src/GUIStuff/Elements/RotateWheel.cpp b/src/GUIStuff/Elements/RotateWheel.cpp index cef9138..8fc9a66 100644 --- a/src/GUIStuff/Elements/RotateWheel.cpp +++ b/src/GUIStuff/Elements/RotateWheel.cpp @@ -51,17 +51,17 @@ float RotateWheel::wheel_end() { return bb.width() * 0.5f; } -void RotateWheel::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void RotateWheel::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { bb = get_bb(command); canvas->save(); canvas->translate(bb.center().x(), bb.center().y()); - draw_rotate_wheel(canvas, io); + draw_rotate_wheel(canvas, io, skiaAA); canvas->restore(); } -void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) { +void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io, bool skiaAA) { float wheelStart = wheel_start(); float wheelEnd = wheel_end(); @@ -75,12 +75,14 @@ void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) { for(double snapPos = 0.0; snapPos < std::numbers::pi * 2.0; snapPos += ROTATE_BAR_SNAP_DISTRIBUTION) { Vector2f lineDir{std::cos(snapPos), -std::sin(snapPos)}; SkPaint p(snapPos == 0.0 ? io.theme->fillColor1 : io.theme->frontColor2); + p.setAntiAlias(skiaAA); p.setStrokeWidth(1.0f); canvas->drawLine(lineDir.x() * wheelStart, lineDir.y() * wheelStart, lineDir.x() * wheelEnd, lineDir.y() * wheelEnd, p); } } SkPaint rotateBarHolderFill; + rotateBarHolderFill.setAntiAlias(skiaAA); if(selection.held) rotateBarHolderFill.setColor4f(io.theme->fillColor1); else if(selection.hovered) @@ -91,11 +93,13 @@ void RotateWheel::draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io) { Vector2f rotateBarHolderPos{std::cos(rotateAngle) * rotateBarMiddleRadius, -std::sin(rotateAngle) * rotateBarMiddleRadius}; canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderFill); SkPaint rotateBarHolderOutline(io.theme->frontColor1); + rotateBarHolderOutline.setAntiAlias(skiaAA); rotateBarHolderOutline.setStroke(true); rotateBarHolderOutline.setStrokeWidth(2.0f); canvas->drawCircle(rotateBarHolderPos.x(), rotateBarHolderPos.y(), rotateBarHolderRadius, rotateBarHolderOutline); SkPaint rotateBarOutline(io.theme->frontColor2); + rotateBarOutline.setAntiAlias(skiaAA); rotateBarOutline.setStroke(true); rotateBarOutline.setStrokeWidth(1.0f); canvas->drawCircle(0.0f, 0.0f, wheelStart, rotateBarOutline); diff --git a/src/GUIStuff/Elements/RotateWheel.hpp b/src/GUIStuff/Elements/RotateWheel.hpp index c6501ca..377ed1a 100644 --- a/src/GUIStuff/Elements/RotateWheel.hpp +++ b/src/GUIStuff/Elements/RotateWheel.hpp @@ -6,12 +6,12 @@ namespace GUIStuff { class RotateWheel : public Element { public: void update(UpdateInputData& io, double* newRotationAnglePtr, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; private: float wheel_start(); float wheel_end(); - void draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io); + void draw_rotate_wheel(SkCanvas* canvas, UpdateInputData& io, bool skiaAA); double rotateAngle = 0.0f; SCollision::AABB bb; diff --git a/src/GUIStuff/Elements/SVGIcon.cpp b/src/GUIStuff/Elements/SVGIcon.cpp index a395e91..3861fab 100644 --- a/src/GUIStuff/Elements/SVGIcon.cpp +++ b/src/GUIStuff/Elements/SVGIcon.cpp @@ -26,7 +26,7 @@ void SVGIcon::update(UpdateInputData& io, const std::string& newSvgPath, bool ne } } -void SVGIcon::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void SVGIcon::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { if(!svgDom) return; diff --git a/src/GUIStuff/Elements/SVGIcon.hpp b/src/GUIStuff/Elements/SVGIcon.hpp index 8238320..b151ecf 100644 --- a/src/GUIStuff/Elements/SVGIcon.hpp +++ b/src/GUIStuff/Elements/SVGIcon.hpp @@ -6,7 +6,7 @@ namespace GUIStuff { class SVGIcon : public Element { public: void update(UpdateInputData& io, const std::string& newSvgPath, bool newIsHighlighted, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; private: bool highlighted; sk_sp svgDom; diff --git a/src/GUIStuff/Elements/SelectableButton.cpp b/src/GUIStuff/Elements/SelectableButton.cpp index b29e6f0..b9f5fe5 100644 --- a/src/GUIStuff/Elements/SelectableButton.cpp +++ b/src/GUIStuff/Elements/SelectableButton.cpp @@ -55,7 +55,7 @@ void SelectableButton::update(UpdateInputData& io, DrawType drawType, const std: } } -void SelectableButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +void SelectableButton::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) { } } diff --git a/src/GUIStuff/Elements/SelectableButton.hpp b/src/GUIStuff/Elements/SelectableButton.hpp index 1b7a319..241e05d 100644 --- a/src/GUIStuff/Elements/SelectableButton.hpp +++ b/src/GUIStuff/Elements/SelectableButton.hpp @@ -13,7 +13,7 @@ class SelectableButton : public Element { }; void update(UpdateInputData& io, DrawType drawType, const std::function& elemUpdate, bool isSelected); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; SelectionHelper selection; }; diff --git a/src/GUIStuff/Elements/TextBox.hpp b/src/GUIStuff/Elements/TextBox.hpp index c9a950a..72d8640 100644 --- a/src/GUIStuff/Elements/TextBox.hpp +++ b/src/GUIStuff/Elements/TextBox.hpp @@ -61,7 +61,7 @@ template class TextBox : public Element { return isUpdating; } - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override { + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override { if(!data || !textbox || !cur) return; diff --git a/src/GUIStuff/Elements/TextParagraph.cpp b/src/GUIStuff/Elements/TextParagraph.cpp index 7d7a941..5278537 100644 --- a/src/GUIStuff/Elements/TextParagraph.cpp +++ b/src/GUIStuff/Elements/TextParagraph.cpp @@ -18,7 +18,7 @@ void TextParagraph::update(UpdateInputData& io, std::unique_ptr paragraph, float width, const std::function& elemUpdate); - virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command, bool skiaAA) override; private: SCollision::AABB bb = SCollision::AABB({0.0f, 0.0f}, {0.0f, 0.0f}); std::unique_ptr data; diff --git a/src/GUIStuff/Elements/TreeListing.cpp b/src/GUIStuff/Elements/TreeListing.cpp index 1168a64..bb41c48 100644 --- a/src/GUIStuff/Elements/TreeListing.cpp +++ b/src/GUIStuff/Elements/TreeListing.cpp @@ -275,7 +275,7 @@ void TreeListing::select_and_unselect_parents(const std::vectorsave(); canvas->translate(windowPos.x(), windowPos.y()); @@ -106,6 +106,7 @@ void GUIManager::draw(SkCanvas* canvas) { ); SkPaint paint; + paint.setAntiAlias(skiaAA); paint.setStyle(SkPaint::kFill_Style); paint.setColor4f(convert_vec4(config->backgroundColor)); canvas->drawRRect(rrect, paint); @@ -137,6 +138,7 @@ void GUIManager::draw(SkCanvas* canvas) { SkPaint p; p.setColor4f(convert_vec4(config->color)); p.setStyle(SkPaint::kStroke_Style); + p.setAntiAlias(skiaAA); float halfLineWidth = 0.0f; // Top Left corner @@ -235,7 +237,7 @@ void GUIManager::draw(SkCanvas* canvas) { } case CLAY_RENDER_COMMAND_TYPE_CUSTOM: { Element* customElement = (Element*)command->renderData.custom.customData; - customElement->clay_draw(canvas, *io, command); + customElement->clay_draw(canvas, *io, command, skiaAA); break; } default: diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index 02787c2..975e071 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -36,7 +36,7 @@ class GUIManager { GUIManager(); void begin(); void end(); - void draw(SkCanvas* canvas); + void draw(SkCanvas* canvas, bool skiaAA); Vector2f windowPos = Vector2f{0.0f, 0.0f}; Vector2f windowSize = Vector2f{0.0f, 0.0f}; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index f4d6ae4..6eb672c 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -242,6 +242,8 @@ void MainProgram::load_config() { toolbar.load_licenses(); NetLibrary::copy_default_p2p_config_to_path(configPath / "p2p.json"); + + refresh_draw_surfaces(); } void MainProgram::set_vsync_value(int vsyncValue) { @@ -269,30 +271,49 @@ float MainProgram::get_scale_and_density_factor_gui() { return window.scale * window.density; } +void MainProgram::refresh_draw_surfaces() { + if(window.canCreateSurfaces) { + window.defaultMSAASampleCount = 0; + window.defaultMSAASurfaceProps = SkSurfaceProps(antialiasing == AntiAliasing::DYNAMIC_MSAA ? SkSurfaceProps::kDynamicMSAA_Flag : SkSurfaceProps::kDefault_Flag, kUnknown_SkPixelGeometry); + window.intermediateSurface = create_native_surface(window.size, true); + window.intermediateCanvas = window.intermediateSurface->getCanvas(); + + if(!window.intermediateCanvas) + throw std::runtime_error("[refresh_draw_surfaces] Could not create intermediate canvas"); + + DrawingProgramCache::delete_all_draw_cache(); + } +} + void MainProgram::draw(SkCanvas* canvas, std::shared_ptr worldToDraw, const DrawData& drawData) { canvas->clear(drawData.transparentBackground ? SkColor4f{0.0f, 0.0f, 0.0f, 0.0f} : worldToDraw->canvasTheme.get_back_color()); - worldToDraw->draw(canvas, drawData); + DrawData drawDataCopy = drawData; + drawDataCopy.skiaAA = antialiasing == AntiAliasing::SKIA; + worldToDraw->draw(canvas, drawDataCopy); if(!drawData.takingScreenshot) - toolbar.draw(canvas); + toolbar.draw(canvas, drawDataCopy.skiaAA); } sk_sp MainProgram::create_native_surface(Vector2i resolution, bool isMSAA) { - #ifdef USE_BACKEND_OPENGLES_3_0 - SkImageInfo imgInfo = SkImageInfo::Make(resolution.x(), resolution.y(), kRGBA_8888_SkColorType, kPremul_SkAlphaType); - #else - SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(resolution.x(), resolution.y()); - #endif - SkSurfaceProps defaultProps; - #ifdef USE_SKIA_BACKEND_GRAPHITE - auto surfaceToRet = SkSurfaces::RenderTarget(window.recorder(), imgInfo, skgpu::Mipmapped::kNo, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps); - #elif USE_SKIA_BACKEND_GANESH - auto surfaceToRet = SkSurfaces::RenderTarget(window.ctx.get(), skgpu::Budgeted::kNo, imgInfo, isMSAA ? window.defaultMSAASampleCount : 0, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps); - #endif + if(window.canCreateSurfaces) { + #ifdef USE_BACKEND_OPENGLES_3_0 + SkImageInfo imgInfo = SkImageInfo::Make(resolution.x(), resolution.y(), kRGBA_8888_SkColorType, kPremul_SkAlphaType); + #else + SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(resolution.x(), resolution.y()); + #endif + SkSurfaceProps defaultProps; + #ifdef USE_SKIA_BACKEND_GRAPHITE + auto surfaceToRet = SkSurfaces::RenderTarget(window.recorder(), imgInfo, skgpu::Mipmapped::kNo, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps); + #elif USE_SKIA_BACKEND_GANESH + auto surfaceToRet = SkSurfaces::RenderTarget(window.ctx.get(), skgpu::Budgeted::kNo, imgInfo, isMSAA ? window.defaultMSAASampleCount : 0, isMSAA ? &window.defaultMSAASurfaceProps : &defaultProps); + #endif - if(!surfaceToRet) - throw std::runtime_error("[MainProgram::create_native_surface] Could not make native surface"); + if(!surfaceToRet) + throw std::runtime_error("[MainProgram::create_native_surface] Could not make native surface"); - return surfaceToRet; + return surfaceToRet; + } + return nullptr; } void MainProgram::input_drop_file_callback(const InputManager::DropCallbackArgs& drop) { diff --git a/src/MainProgram.hpp b/src/MainProgram.hpp index 9c5dcbd..8fa6431 100644 --- a/src/MainProgram.hpp +++ b/src/MainProgram.hpp @@ -60,9 +60,12 @@ class MainProgram { #elif USE_SKIA_BACKEND_GANESH sk_sp ctx; #endif - sk_sp surface; + + sk_sp intermediateSurface; + SkCanvas* intermediateCanvas; SDL_Window* sdlWindow; + bool canCreateSurfaces = false; } window; struct Clipboard { @@ -89,6 +92,12 @@ class MainProgram { sk_sp create_native_surface(Vector2i resolution, bool isMSAA); bool setToQuit = false; + + enum class AntiAliasing { + NONE, + SKIA, + DYNAMIC_MSAA + } antialiasing = AntiAliasing::DYNAMIC_MSAA; void early_destroy(); @@ -107,6 +116,8 @@ class MainProgram { float get_scale_and_density_factor_gui(); bool app_close_requested(); + void refresh_draw_surfaces(); + std::filesystem::path homePath; std::filesystem::path configPath; std::filesystem::path documentsPath; @@ -148,3 +159,9 @@ class MainProgram { void gui(); void draw_grid(SkCanvas* canvas); }; + +NLOHMANN_JSON_SERIALIZE_ENUM(MainProgram::AntiAliasing, { + {MainProgram::AntiAliasing::NONE, "None"}, + {MainProgram::AntiAliasing::SKIA, "Skia"}, + {MainProgram::AntiAliasing::DYNAMIC_MSAA, "Dynamic MSAA"}, +}) diff --git a/src/ResourceDisplay/ImageResourceDisplay.cpp b/src/ResourceDisplay/ImageResourceDisplay.cpp index 1a3ae92..2e883a0 100644 --- a/src/ResourceDisplay/ImageResourceDisplay.cpp +++ b/src/ResourceDisplay/ImageResourceDisplay.cpp @@ -197,8 +197,11 @@ void ImageResourceDisplay::load_thread_func(unsigned mipmapLevel) { } void ImageResourceDisplay::draw(SkCanvas* canvas, const DrawData& drawData, const SkRect& imRect) { - if(!smallestMipmapLevelLoaded) - canvas->drawRect(imRect, SkPaint({0.5f, 0.5f, 0.5f, 0.5f})); + if(!smallestMipmapLevelLoaded) { + SkPaint p({0.5f, 0.5f, 0.5f, 0.5f}); + p.setAntiAlias(drawData.skiaAA); + canvas->drawRect(imRect, p); + } else { SkRect imRectPixelSize = canvas->getLocalToDeviceAs3x3().mapRect(imRect); unsigned mipmapLevel = get_exact_mipmap_level_for_dimensions({imRectPixelSize.width(), imRectPixelSize.height()}); diff --git a/src/RichText/TextBox.cpp b/src/RichText/TextBox.cpp index 784c2c7..be7542d 100644 --- a/src/RichText/TextBox.cpp +++ b/src/RichText/TextBox.cpp @@ -1249,6 +1249,7 @@ void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) { if(paintOpts.cursor.has_value()) { auto& cur = paintOpts.cursor.value(); SkPaint selectionP{SkColor4f{paintOpts.cursorColor.x(), paintOpts.cursorColor.y(), paintOpts.cursorColor.z(), 1.0f}}; + selectionP.setAntiAlias(paintOpts.skiaAA); if(cur.selectionBeginPos != cur.selectionEndPos) { canvas->saveLayerAlphaf(nullptr, 0.5f); rects_between_text_positions_func(cur.selectionBeginPos, cur.selectionEndPos, [&](const SkRect& rect) { @@ -1257,6 +1258,7 @@ void TextBox::paint(SkCanvas* canvas, const PaintOpts& paintOpts) { canvas->restore(); } SkPaint cursorP{SkColor4f{paintOpts.cursorColor.x(), paintOpts.cursorColor.y(), paintOpts.cursorColor.z(), 1.0f}}; + cursorP.setAntiAlias(paintOpts.skiaAA); canvas->drawRect(get_cursor_rect(cur.pos), cursorP); } } diff --git a/src/RichText/TextBox.hpp b/src/RichText/TextBox.hpp index 80c3e63..97d1c98 100644 --- a/src/RichText/TextBox.hpp +++ b/src/RichText/TextBox.hpp @@ -98,6 +98,7 @@ class TextBox { struct PaintOpts { Vector3f cursorColor = {1, 0, 0}; std::optional cursor; + bool skiaAA = false; }; TextPosition move(Movement movement, TextPosition pos, std::optional* previousX = nullptr, bool flipDependingOnTextDirection = false); diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 1e8f786..5ea5426 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -306,6 +306,7 @@ nlohmann::json Toolbar::get_config_json() { debugJson["showPerformance"] = showPerformance; debugJson["fpsLimit"] = main.fpsLimit; debugJson["jumpTransitionEasing"] = jumpTransitionEasing; + debugJson["antialiasing"] = main.antialiasing; debugJson["imageLoadMaxThreads"] = ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX; debugJson["cacheNodeResolution"] = DrawingProgramCache::CACHE_NODE_RESOLUTION; debugJson["maxCacheNodes"] = DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES; @@ -378,6 +379,7 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) { try{j.at("debug").at("showPerformance").get_to(showPerformance);} catch(...) {} try{j.at("debug").at("fpsLimit").get_to(main.fpsLimit);} catch(...) {} try{j.at("debug").at("jumpTransitionEasing").get_to(jumpTransitionEasing);} catch(...) {} + try{j.at("debug").at("antialiasing").get_to(main.antialiasing);} catch(...) {} try{j.at("debug").at("imageLoadMaxThreads").get_to(ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX);} catch(...) {} try{j.at("debug").at("cacheNodeResolution").get_to(DrawingProgramCache::CACHE_NODE_RESOLUTION);} catch(...) {} try{j.at("debug").at("maxCacheNodes").get_to(DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES);} catch(...) {} @@ -1907,6 +1909,13 @@ void Toolbar::options_menu() { gui.input_scalar_field("fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f); #endif gui.input_scalar_field("image load max threads", "Maximum image loading threads", &ImageResourceDisplay::IMAGE_LOAD_THREAD_COUNT_MAX, 1, 10000); + gui.text_label("Antialiasing:"); + MainProgram::AntiAliasing aa = main.antialiasing; + if(gui.radio_button_field("AntiAliasing None", "None", aa == MainProgram::AntiAliasing::NONE)) { main.antialiasing = MainProgram::AntiAliasing::NONE; } + if(gui.radio_button_field("AntiAliasing Skia", "Skia", aa == MainProgram::AntiAliasing::SKIA)) { main.antialiasing = MainProgram::AntiAliasing::SKIA; } + if(gui.radio_button_field("AntiAliasing Dynamic MSAA", "Dynamic MSAA", aa == MainProgram::AntiAliasing::DYNAMIC_MSAA)) { main.antialiasing = MainProgram::AntiAliasing::DYNAMIC_MSAA; } + if(main.antialiasing != aa) + main.refresh_draw_surfaces(); gui.text_label_light("Cache related settings"); gui.input_scalar_field("cache node resolution", "Cache node resolution", &DrawingProgramCache::CACHE_NODE_RESOLUTION, 256, 8192); gui.input_scalar_field("max cache nodes", "Maximum cached nodes", &DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES, 2, 10000); @@ -2456,9 +2465,9 @@ void Toolbar::end_gui() { end_io(); } -void Toolbar::draw(SkCanvas* canvas) { +void Toolbar::draw(SkCanvas* canvas, bool skiaAA) { canvas->save(); canvas->scale(final_gui_scale(), final_gui_scale()); - gui.draw(canvas); + gui.draw(canvas, skiaAA); canvas->restore(); } diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index 6d1b93a..884243b 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -47,7 +47,7 @@ class Toolbar { void input_finger_touch_callback(const InputManager::FingerTouchCallbackArgs& touch); void input_finger_motion_callback(const InputManager::FingerMotionCallbackArgs& motion); void update(); - void draw(SkCanvas* canvas); + void draw(SkCanvas* canvas, bool skiaAA); void color_selector_left(Vector4f* color); void color_selector_right(Vector4f* color); void paint_popup(Vector2f popupPos); diff --git a/src/main.cpp b/src/main.cpp index 777f370..95c95a7 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -136,8 +136,6 @@ struct MainStruct { SkCanvas* canvas; sk_sp surface; - sk_sp intermediateSurface; - SkCanvas* intermediateCanvas; SDL_Surface* iconSurface = nullptr; std::string iconData; @@ -312,13 +310,7 @@ void sdl_terminate(MainStruct& mS) { void resize_window(MainStruct& mS) { // Having intermediate surface allows for changing options more easily - mS.intermediateSurface = mS.m->create_native_surface(mS.m->window.size, true); - mS.intermediateCanvas = mS.intermediateSurface->getCanvas(); - - if(!mS.intermediateCanvas) - throw std::runtime_error("[resize_window] Could not create intermediate canvas"); - - mS.m->window.surface = mS.intermediateSurface; + mS.m->refresh_draw_surfaces(); #ifdef USE_BACKEND_VULKAN mS.vulkanWindowContext->resize(mS.m->window.size.x(), mS.m->window.size.y()); @@ -446,8 +438,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { mS.hiddenCursor = SDL_CreateCursor((Uint8 *)cursorData, (Uint8 *)cursorData, 8, 8, 4, 4); mS.m = std::make_unique(); - mS.m->window.defaultMSAASampleCount = 0; - mS.m->window.defaultMSAASurfaceProps = SkSurfaceProps(SkSurfaceProps::kDynamicMSAA_Flag, kUnknown_SkPixelGeometry); mS.m->logFile = &mS.logFile; mS.m->configPath = mS.configPath; mS.m->homePath = mS.homePath; @@ -552,6 +542,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { SDL_SetWindowFullscreen(mS.window, true); #endif + mS.m->window.canCreateSurfaces = true; resize_window(mS); if(listOfFilesToOpenFromCommand.empty()) { @@ -599,15 +590,15 @@ void attempt_redraw_and_swap_buffers(MainStruct& mS) { #endif mS.lastRenderTimePoint = std::chrono::steady_clock::now(); - mS.intermediateCanvas->save(); - mS.m->draw(mS.intermediateCanvas, mS.m->world, mS.m->world->drawData); - mS.intermediateCanvas->restore(); + mS.m->window.intermediateCanvas->save(); + mS.m->draw(mS.m->window.intermediateCanvas, mS.m->world, mS.m->world->drawData); + mS.m->window.intermediateCanvas->restore(); #ifdef USE_BACKEND_VULKAN mS.vulkanWindowContext->getBackbufferSurface()->getCanvas()->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); mS.ctx->flushAndSubmit(); #elif USE_BACKEND_OPENGL - mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); + mS.canvas->drawImage(mS.m->window.intermediateSurface->makeTemporaryImage(), 0, 0); mS.ctx->flushAndSubmit(); #endif } @@ -616,16 +607,16 @@ void attempt_redraw_and_swap_buffers(MainStruct& mS) { void regular_draw(MainStruct& mS) { mS.lastRenderTimePoint = std::chrono::steady_clock::now(); - mS.intermediateCanvas->save(); - mS.m->draw(mS.intermediateCanvas, mS.m->world, mS.m->world->drawData); - mS.intermediateCanvas->restore(); + mS.m->window.intermediateCanvas->save(); + mS.m->draw(mS.m->window.intermediateCanvas, mS.m->world, mS.m->world->drawData); + mS.m->window.intermediateCanvas->restore(); #ifdef USE_BACKEND_VULKAN mS.vulkanWindowContext->getBackbufferSurface()->getCanvas()->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); mS.ctx->flushAndSubmit(); mS.vulkanWindowContext->swapBuffers(); #elif USE_BACKEND_OPENGL - mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0); + mS.canvas->drawImage(mS.m->window.intermediateSurface->makeTemporaryImage(), 0, 0); mS.ctx->flushAndSubmit(); SDL_GL_SwapWindow(mS.window); #endif