refactor: recreate texture only if device orientation is changed

This commit is contained in:
dscyrescotti
2024-06-26 20:57:52 +07:00
parent d5c1cd6653
commit b9dbcc4506
11 changed files with 127 additions and 90 deletions

View File

@@ -12,5 +12,5 @@ protocol RenderPass {
var label: String { get }
var descriptor: MTLRenderPassDescriptor? { get set }
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer)
func draw(into commandBuffer: MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer)
func draw(into commandBuffer: MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool
}

View File

@@ -65,7 +65,7 @@ extension Canvas {
let graphicContext = canvas.graphicContext
self?.graphicContext.object = graphicContext
self?.graphicContext.loadStrokes(bounds)
context.refreshAllObjects()
context.refresh(canvas, mergeChanges: false)
DispatchQueue.main.async { [weak self] in
self?.state = .loaded
}

View File

@@ -60,17 +60,23 @@ final class Renderer {
self.viewPortRenderPass.view = canvasView
}
func resize(on view: MTKView, to size: CGSize) {
if !updatesViewPort {
photoBackgroundRenderPass.resize(on: view, to: size, with: self)
strokeRenderPass.resize(on: view, to: size, with: self)
graphicRenderPass.resize(on: view, to: size, with: self)
cacheRenderPass.resize(on: view, to: size, with: self)
}
viewPortRenderPass.resize(on: view, to: size, with: self)
func setUpdatesViewPort(_ value: Bool) {
updatesViewPort = value
}
func setRedrawsGraphicRender() {
redrawsGraphicRender = true
}
func resize(on view: MTKView, to size: CGSize) {
photoBackgroundRenderPass.resize(on: view, to: size, with: self)
strokeRenderPass.resize(on: view, to: size, with: self)
graphicRenderPass.resize(on: view, to: size, with: self)
cacheRenderPass.resize(on: view, to: size, with: self)
viewPortRenderPass.resize(on: view, to: size, with: self)
setRedrawsGraphicRender()
}
func draw(in view: MTKView, on canvas: Canvas) {
guard let commandBuffer = commandQueue.makeCommandBuffer() else {
NSLog("[Memola] - Unable to create command buffer")
@@ -94,6 +100,7 @@ final class Renderer {
cacheRenderPass.draw(into: commandBuffer, on: canvas, with: self)
viewPortRenderPass.descriptor = view.currentRenderPassDescriptor
viewPortRenderPass.excludesPhotoBackground = photoBackgroundRenderPass.clearsTexture
viewPortRenderPass.photoBackgroundTexture = photoBackgroundRenderPass.photoBackgroundTexture
viewPortRenderPass.cacheTexture = cacheRenderPass.cacheTexture
viewPortRenderPass.draw(into: commandBuffer, on: canvas, with: self)

View File

@@ -34,14 +34,15 @@ class CacheRenderPass: RenderPass {
cacheTexture = Textures.createCacheTexture(from: renderer, size: size, pixelFormat: view.colorPixelFormat)
}
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
guard let descriptor else { return }
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let descriptor else { return false }
// MARK: - Copying texture
guard let graphicTexture, let cacheTexture else { return }
guard let cachePipelineState else { return }
guard let graphicTexture, let cacheTexture else { return false }
guard let cachePipelineState else { return false }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else {
return
return false
}
computeEncoder.label = "Cache Compute Encoder"
@@ -58,7 +59,7 @@ class CacheRenderPass: RenderPass {
computeEncoder.endEncoding()
// MARK: - Drawing
guard let graphicPipelineState else { return }
guard let graphicPipelineState else { return false }
descriptor.colorAttachments[0].texture = cacheTexture
descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 1, blue: 1, alpha: 0)
descriptor.colorAttachments[0].loadAction = clearsTexture ? .clear : .load
@@ -67,23 +68,25 @@ class CacheRenderPass: RenderPass {
let graphicContext = canvas.graphicContext
if let element = graphicContext.currentElement {
let elementGroup = ElementGroup(element)
var status: Bool?
switch elementGroup.type {
case .stroke:
canvas.setGraphicRenderType(.inProgress)
strokeRenderPass?.elementGroup = elementGroup
strokeRenderPass?.graphicDescriptor = descriptor
strokeRenderPass?.graphicPipelineState = graphicPipelineState
strokeRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
status = strokeRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
case .eraser:
eraserRenderPass?.elementGroup = elementGroup
eraserRenderPass?.descriptor = descriptor
eraserRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
status = eraserRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
case .photo:
photoRenderPass?.elementGroup = elementGroup
photoRenderPass?.descriptor = descriptor
photoRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
status = photoRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
}
clearsTexture = false
clearsTexture = !(status ?? false)
}
return true
}
}

View File

@@ -26,19 +26,20 @@ class EraserRenderPass: RenderPass {
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) { }
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
guard let elementGroup else { return }
guard let descriptor else { return }
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let elementGroup else { return false }
guard let descriptor else { return false }
// MARK: - Generating vertices
guard !elementGroup.isEmpty, let quadPipelineState else { return }
guard !elementGroup.isEmpty, let quadPipelineState else { return false }
let eraserStrokes = elementGroup.elements.compactMap { element -> EraserStroke? in
guard case .stroke(let anyStroke) = element else { return nil }
return anyStroke.value as? EraserStroke
}
let quads = eraserStrokes.flatMap { $0.quads }
guard !quads.isEmpty else { return }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return }
guard !quads.isEmpty else { return false }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return false }
computeEncoder.label = "Quad Compute Encoder"
@@ -58,10 +59,10 @@ class EraserRenderPass: RenderPass {
computeEncoder.endEncoding()
// MARK: - Rendering eraser
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return false }
renderEncoder.label = "Stroke Render Encoder"
guard let eraserPipelineState else { return }
guard let eraserPipelineState else { return false }
renderEncoder.setRenderPipelineState(eraserPipelineState)
canvas.setUniformsBuffer(device: renderer.device, renderEncoder: renderEncoder)
@@ -77,5 +78,6 @@ class EraserRenderPass: RenderPass {
)
}
renderEncoder.endEncoding()
return true
}
}

View File

@@ -30,16 +30,18 @@ class GraphicRenderPass: RenderPass {
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) {
guard size != .zero else { return }
graphicTexture = Textures.createGraphicTexture(from: renderer, size: size, pixelFormat: view.colorPixelFormat)
clearsTexture = true
}
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
descriptor?.colorAttachments[0].texture = graphicTexture
descriptor?.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 1, blue: 1, alpha: 0)
descriptor?.colorAttachments[0].storeAction = .store
let graphicContext = canvas.graphicContext
if renderer.redrawsGraphicRender {
clearsTexture = true
photoBackgroundRenderPass?.clearsTexture = true
canvas.setGraphicRenderType(.finished)
var elementGroup: ElementGroup?
let start = Date.now.timeIntervalSince1970 * 1000
@@ -51,7 +53,7 @@ class GraphicRenderPass: RenderPass {
let _elementGroup = ElementGroup(_element)
elementGroup = _elementGroup
} else {
guard let _elementGroup = elementGroup else { return }
guard let _elementGroup = elementGroup else { continue }
if _elementGroup.isSameElement(_element) {
_elementGroup.add(_element)
} else {
@@ -75,6 +77,7 @@ class GraphicRenderPass: RenderPass {
draw(for: elementGroup, into: commandBuffer, on: canvas, with: renderer)
graphicContext.previousElement = nil
}
return true
}
private func draw(for elementGroup: ElementGroup, into commandBuffer: MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
@@ -84,24 +87,33 @@ class GraphicRenderPass: RenderPass {
strokeRenderPass?.elementGroup = elementGroup
strokeRenderPass?.graphicDescriptor = descriptor
strokeRenderPass?.graphicPipelineState = graphicPipelineState
strokeRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
clearsTexture = false
let status = strokeRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
if clearsTexture, let status {
clearsTexture = !status
}
case .eraser:
descriptor?.colorAttachments[0].loadAction = clearsTexture ? .clear : .load
eraserRenderPass?.elementGroup = elementGroup
eraserRenderPass?.descriptor = descriptor
eraserRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
clearsTexture = false
let status = eraserRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
if clearsTexture, let status {
clearsTexture = !status
}
case .photo:
descriptor?.colorAttachments[0].loadAction = clearsTexture ? .clear : .load
photoRenderPass?.elementGroup = elementGroup
photoRenderPass?.descriptor = descriptor
photoRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
let photoStatus = photoRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
photoBackgroundRenderPass?.elementGroup = elementGroup
photoBackgroundRenderPass?.clearsTexture = clearsTexture
photoBackgroundRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
clearsTexture = false
let photoBackgroundStatus = photoBackgroundRenderPass?.draw(into: commandBuffer, on: canvas, with: renderer)
if clearsTexture, let photoStatus {
clearsTexture = !photoStatus
}
if photoBackgroundRenderPass?.clearsTexture == true, let photoBackgroundStatus {
photoBackgroundRenderPass?.clearsTexture = !photoBackgroundStatus
}
}
}
}

View File

@@ -27,30 +27,31 @@ class PhotoBackgroundRenderPass: RenderPass {
photoBackgroundPipelineState = PipelineStates.createPhotoPipelineState(from: renderer)
}
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) {
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) {
guard size != .zero else { return }
photoBackgroundTexture = Textures.createPhotoBackgroundTexture(from: renderer, size: size, pixelFormat: renderer.pixelFormat)
}
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
guard let elementGroup else { return }
guard let descriptor else { return }
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let elementGroup else { return false }
guard let descriptor else { return false }
descriptor.colorAttachments[0].texture = photoBackgroundTexture
descriptor.colorAttachments[0].storeAction = .store
descriptor.colorAttachments[0].loadAction = clearsTexture ? .clear : .load
descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 1, blue: 1, alpha: 0)
guard !elementGroup.isEmpty else { return }
guard !elementGroup.isEmpty else { return false }
let photos = elementGroup.elements.compactMap { element -> Photo? in
guard case .photo(let photo) = element else { return nil }
return photo
}
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return false }
renderEncoder.label = "Photo Background Render Encoder"
guard let photoBackgroundPipelineState else { return }
guard let photoBackgroundPipelineState else { return false }
renderEncoder.setRenderPipelineState(photoBackgroundPipelineState)
canvas.setUniformsBuffer(device: renderer.device, renderEncoder: renderEncoder)
@@ -60,5 +61,6 @@ class PhotoBackgroundRenderPass: RenderPass {
}
renderEncoder.endEncoding()
return true
}
}

View File

@@ -24,21 +24,22 @@ class PhotoRenderPass: RenderPass {
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) { }
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
guard let elementGroup else { return }
guard let descriptor else { return }
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let elementGroup else { return false }
guard let descriptor else { return false }
guard !elementGroup.isEmpty else { return }
guard !elementGroup.isEmpty else { return false }
let photos = elementGroup.elements.compactMap { element -> Photo? in
guard case .photo(let photo) = element else { return nil }
return photo
}
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return false }
renderEncoder.label = "Photo Render Encoder"
guard let photoPipelineState else { return }
guard let photoPipelineState else { return false }
renderEncoder.setRenderPipelineState(photoPipelineState)
canvas.setUniformsBuffer(device: renderer.device, renderEncoder: renderEncoder)
@@ -48,5 +49,6 @@ class PhotoRenderPass: RenderPass {
}
renderEncoder.endEncoding()
return true
}
}

View File

@@ -34,12 +34,13 @@ class StrokeRenderPass: RenderPass {
strokeTexture = Textures.createStrokeTexture(from: renderer, size: size, pixelFormat: view.colorPixelFormat)
}
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
guard let elementGroup else { return }
guard let descriptor else { return }
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let elementGroup else { return false }
guard let descriptor else { return false }
// MARK: - Generating vertices
guard !elementGroup.isEmpty, let quadPipelineState else { return }
guard !elementGroup.isEmpty, let quadPipelineState else { return false }
let penStrokes = elementGroup.elements.compactMap { element -> PenStroke? in
guard case .stroke(let anyStroke) = element else { return nil }
return anyStroke.value as? PenStroke
@@ -47,8 +48,8 @@ class StrokeRenderPass: RenderPass {
let penStroke = penStrokes.first
let quads = penStrokes.flatMap { $0.quads }
let erasedQuads = Set(penStrokes.flatMap { $0.eraserStrokes }).flatMap { $0.quads }
guard !quads.isEmpty else { return }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return }
guard !quads.isEmpty else { return false }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return false }
computeEncoder.label = "Quad Compute Encoder"
@@ -68,16 +69,16 @@ class StrokeRenderPass: RenderPass {
computeEncoder.endEncoding()
// MARK: - Rendering stroke
guard let strokeTexture else { return }
guard let strokeTexture else { return false }
descriptor.colorAttachments[0].texture = strokeTexture
descriptor.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 1, blue: 1, alpha: 0)
descriptor.colorAttachments[0].loadAction = .clear
descriptor.colorAttachments[0].storeAction = .store
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return false }
renderEncoder.label = "Stroke Render Encoder"
guard let strokePipelineState else { return }
guard let strokePipelineState else { return false }
renderEncoder.setRenderPipelineState(strokePipelineState)
canvas.setUniformsBuffer(device: renderer.device, renderEncoder: renderEncoder)
@@ -100,7 +101,7 @@ class StrokeRenderPass: RenderPass {
// MARK: Erasing path
if let eraserPipelineState = eraserRenderPass?.eraserPipelineState, !erasedQuads.isEmpty {
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return }
guard let computeEncoder = commandBuffer.makeComputeCommandEncoder() else { return false }
computeEncoder.label = "Erased Quad Compute Encoder"
@@ -120,7 +121,7 @@ class StrokeRenderPass: RenderPass {
computeEncoder.endEncoding()
descriptor.colorAttachments[0].loadAction = .load
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else { return false }
renderEncoder.label = "Stroke Eraser Render Encoder"
renderEncoder.setRenderPipelineState(eraserPipelineState)
@@ -140,8 +141,8 @@ class StrokeRenderPass: RenderPass {
}
// MARK: Drawing on graphic texture
guard let graphicDescriptor, let graphicPipelineState else { return }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: graphicDescriptor) else { return }
guard let graphicDescriptor, let graphicPipelineState else { return false }
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: graphicDescriptor) else { return false }
renderEncoder.label = "Stroke Graphic Render Encoder"
renderEncoder.setRenderPipelineState(graphicPipelineState)
@@ -151,5 +152,7 @@ class StrokeRenderPass: RenderPass {
renderEncoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 11)
canvas.renderGraphic(device: renderer.device, renderEncoder: renderEncoder)
renderEncoder.endEncoding()
return true
}
}

View File

@@ -22,6 +22,8 @@ class ViewPortRenderPass: RenderPass {
weak var view: MTKView?
var excludesPhotoBackground: Bool = false
init(renderer: Renderer) {
pointGridPipelineState = PipelineStates.createPointGridPipelineState(from: renderer)
lineGridPipelineState = PipelineStates.createLineGridPipelineState(from: renderer)
@@ -31,12 +33,13 @@ class ViewPortRenderPass: RenderPass {
func resize(on view: MTKView, to size: CGSize, with renderer: Renderer) { }
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) {
@discardableResult
func draw(into commandBuffer: any MTLCommandBuffer, on canvas: Canvas, with renderer: Renderer) -> Bool {
guard let descriptor else {
return
return false
}
guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor) else {
return
return false
}
renderEncoder.label = "View Port Render Encoder"
@@ -44,36 +47,40 @@ class ViewPortRenderPass: RenderPass {
case .none:
break
case .point:
guard let pointGridPipelineState else { return }
guard let pointGridPipelineState else { return false }
renderEncoder.setRenderPipelineState(pointGridPipelineState)
canvas.renderPointGrid(device: renderer.device, renderEncoder: renderEncoder)
case .line:
guard let lineGridPipelineState else { return }
guard let lineGridPipelineState else { return false }
renderEncoder.setRenderPipelineState(lineGridPipelineState)
canvas.renderLineGrid(device: renderer.device, renderEncoder: renderEncoder)
}
if renderer.updatesViewPort {
guard let viewPortUpdatePipelineState else {
return
return false
}
renderEncoder.setRenderPipelineState(viewPortUpdatePipelineState)
renderEncoder.setFragmentTexture(photoBackgroundTexture, index: 0)
canvas.renderViewPortUpdate(device: renderer.device, renderEncoder: renderEncoder)
if !excludesPhotoBackground {
renderEncoder.setFragmentTexture(photoBackgroundTexture, index: 0)
canvas.renderViewPortUpdate(device: renderer.device, renderEncoder: renderEncoder)
}
renderEncoder.setFragmentTexture(cacheTexture, index: 0)
canvas.renderViewPortUpdate(device: renderer.device, renderEncoder: renderEncoder)
} else {
guard let viewPortPipelineState else {
return
return false
}
renderEncoder.setRenderPipelineState(viewPortPipelineState)
renderEncoder.setFragmentTexture(photoBackgroundTexture, index: 0)
canvas.renderViewPort(device: renderer.device, renderEncoder: renderEncoder)
if !excludesPhotoBackground {
renderEncoder.setFragmentTexture(photoBackgroundTexture, index: 0)
canvas.renderViewPort(device: renderer.device, renderEncoder: renderEncoder)
}
renderEncoder.setFragmentTexture(cacheTexture, index: 0)
canvas.renderViewPort(device: renderer.device, renderEncoder: renderEncoder)
@@ -82,9 +89,10 @@ class ViewPortRenderPass: RenderPass {
renderEncoder.endEncoding()
guard let drawable = view?.currentDrawable else {
return
return false
}
commandBuffer.present(drawable)
commandBuffer.commit()
return true
}
}

View File

@@ -259,7 +259,7 @@ extension CanvasViewController: UIScrollViewDelegate {
func scrollViewDidZoom(_ scrollView: UIScrollView) {
canvas.setZoomScale(scrollView.zoomScale)
renderer.resize(on: renderView, to: renderView.drawableSize)
// renderer.resize(on: renderView, to: renderView.drawableSize)
renderView.draw()
}
@@ -274,7 +274,7 @@ extension CanvasViewController: UIScrollViewDelegate {
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
renderer.resize(on: renderView, to: renderView.drawableSize)
// renderer.resize(on: renderView, to: renderView.drawableSize)
renderView.draw()
}
@@ -302,12 +302,12 @@ extension CanvasViewController {
drawingView.touchCancelled()
canvas.updateClipBounds(scrollView, on: drawingView)
drawingView.disableUserInteraction()
renderer.updatesViewPort = true
renderer.setUpdatesViewPort(true)
}
func magnificationEnded() {
renderer.updatesViewPort = false
renderer.resize(on: renderView, to: renderView.drawableSize)
renderer.setUpdatesViewPort(false)
renderer.setRedrawsGraphicRender()
renderView.draw()
drawingView.enableUserInteraction()
}
@@ -316,12 +316,12 @@ extension CanvasViewController {
guard !renderer.updatesViewPort else { return }
canvas.updateClipBounds(scrollView, on: drawingView)
drawingView.disableUserInteraction()
renderer.updatesViewPort = true
renderer.setUpdatesViewPort(true)
}
func draggingEnded() {
renderer.updatesViewPort = false
renderer.resize(on: renderView, to: renderView.drawableSize)
renderer.setUpdatesViewPort(false)
renderer.setRedrawsGraphicRender()
renderView.draw()
drawingView.enableUserInteraction()
}
@@ -371,7 +371,7 @@ extension CanvasViewController {
func gridModeChanged(_ mode: GridMode) {
drawingView.disableUserInteraction()
renderer.resize(on: renderView, to: renderView.drawableSize)
renderer.setRedrawsGraphicRender()
renderView.draw()
drawingView.enableUserInteraction()
}
@@ -382,8 +382,7 @@ extension CanvasViewController {
guard let event = history.undo() else { return }
drawingView.disableUserInteraction()
canvas.graphicContext.undoGraphic(for: event)
renderer.redrawsGraphicRender = true
renderer.resize(on: renderView, to: renderView.drawableSize)
renderer.setRedrawsGraphicRender()
renderView.draw()
drawingView.enableUserInteraction()
}
@@ -392,8 +391,7 @@ extension CanvasViewController {
guard let event = history.redo() else { return }
drawingView.disableUserInteraction()
canvas.graphicContext.redoGraphic(for: event)
renderer.redrawsGraphicRender = true
renderer.resize(on: renderView, to: renderView.drawableSize)
renderer.setRedrawsGraphicRender()
renderView.draw()
drawingView.enableUserInteraction()
}