refactor: save quads right after they are added

This commit is contained in:
dscyrescotti
2024-05-31 21:00:41 +07:00
parent fc6639b514
commit eebf45b20a
5 changed files with 31 additions and 72 deletions
+5 -4
View File
@@ -154,11 +154,12 @@ extension GraphicContext {
func endStroke(at point: CGPoint) { func endStroke(at point: CGPoint) {
guard currentPoint != nil, let currentStroke else { return } guard currentPoint != nil, let currentStroke else { return }
currentStroke.finish(at: point) currentStroke.finish(at: point)
currentStroke.saveQuads(to: currentStroke.quads.endIndex) withPersistence(\.backgroundContext) { [currentStroke] context in
withPersistence(\.backgroundContext) { context in guard let stroke = currentStroke.stroke(as: PenStroke.self) else { return }
stroke.object?.bounds = stroke.bounds
try context.saveIfNeeded() try context.saveIfNeeded()
if let stroke = currentStroke.stroke(as: PenStroke.self)?.object { if let object = stroke.object {
context.refresh(stroke, mergeChanges: false) context.refresh(object, mergeChanges: false)
} }
} }
previousStroke = currentStroke previousStroke = currentStroke
@@ -18,8 +18,6 @@ protocol Stroke: AnyObject, Drawable, Hashable, Equatable {
var quads: [Quad] { get set } var quads: [Quad] { get set }
var penStyle: any PenStyle { get set } var penStyle: any PenStyle { get set }
var batchIndex: Int { get set }
var quadIndex: Int { get set }
var keyPoints: [CGPoint] { get set } var keyPoints: [CGPoint] { get set }
var movingAverage: MovingAverage { get set } var movingAverage: MovingAverage { get set }
@@ -32,8 +30,6 @@ protocol Stroke: AnyObject, Drawable, Hashable, Equatable {
func finish(at point: CGPoint) func finish(at point: CGPoint)
func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape) func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape)
func removeQuads(from index: Int)
func saveQuads(to index: Int)
} }
extension Stroke { extension Stroke {
@@ -78,11 +74,6 @@ extension Stroke {
) )
quads.append(quad) quads.append(quad)
} }
func removeQuads(from index: Int) {
let dropCount = quads.endIndex - max(1, index)
quads.removeLast(dropCount)
}
} }
extension Stroke { extension Stroke {
@@ -29,9 +29,6 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
let control = CGPoint.middle(p1: start, p2: end) let control = CGPoint.middle(p1: start, p2: end)
addCurve(from: start, to: end, by: control, on: stroke) addCurve(from: start, to: end, by: control, on: stroke)
case 3: case 3:
let quadIndex = stroke.quadIndex + 1
stroke.removeQuads(from: quadIndex)
stroke.saveQuads(to: quadIndex)
let index = stroke.keyPoints.endIndex - 1 let index = stroke.keyPoints.endIndex - 1
var start = stroke.keyPoints[index - 2] var start = stroke.keyPoints[index - 2]
var end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1]) var end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
@@ -42,7 +39,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index]) end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
addCurve(from: start, to: end, by: control, on: stroke) addCurve(from: start, to: end, by: control, on: stroke)
default: default:
smoothOutPath(on: stroke) adjustKeyPoint(on: stroke)
let index = stroke.keyPoints.endIndex - 1 let index = stroke.keyPoints.endIndex - 1
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1]) let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
let control = stroke.keyPoints[index - 1] let control = stroke.keyPoints[index - 1]
@@ -60,29 +57,6 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
} }
} }
private func smoothOutPath(on stroke: any Stroke) {
let quadIndex = stroke.quadIndex + 1
stroke.removeQuads(from: quadIndex)
stroke.saveQuads(to: quadIndex)
adjustKeyPoint(on: stroke)
switch stroke.keyPoints.endIndex {
case 4:
let index = stroke.keyPoints.endIndex - 2
let start = stroke.keyPoints[index - 2]
let end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
let control = CGPoint.middle(p1: start, p2: end)
addCurve(from: start, to: end, by: control, on: stroke)
fallthrough
default:
let index = stroke.keyPoints.endIndex - 2
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
let control = stroke.keyPoints[index - 1]
let end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
addCurve(from: start, to: end, by: control, on: stroke)
}
stroke.quadIndex = stroke.quads.endIndex - 1
}
private func adjustKeyPoint(on stroke: any Stroke) { private func adjustKeyPoint(on stroke: any Stroke) {
let index = stroke.keyPoints.endIndex - 1 let index = stroke.keyPoints.endIndex - 1
let prev = stroke.keyPoints[index - 1] let prev = stroke.keyPoints[index - 1]
@@ -18,8 +18,6 @@ final class EraserStroke: Stroke, @unchecked Sendable {
var quads: [Quad] var quads: [Quad]
var penStyle: any PenStyle var penStyle: any PenStyle
var batchIndex: Int = 0
var quadIndex: Int = -1
var keyPoints: [CGPoint] = [] var keyPoints: [CGPoint] = []
var movingAverage: MovingAverage = MovingAverage(windowSize: 3) var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
@@ -43,8 +41,4 @@ final class EraserStroke: Stroke, @unchecked Sendable {
self.quads = quads self.quads = quads
self.penStyle = style.penStyle self.penStyle = style.penStyle
} }
func saveQuads(to index: Int) {
}
} }
@@ -19,8 +19,6 @@ final class PenStroke: Stroke, @unchecked Sendable {
var quads: [Quad] var quads: [Quad]
var penStyle: any PenStyle var penStyle: any PenStyle
var batchIndex: Int = 0
var quadIndex: Int = -1
var keyPoints: [CGPoint] = [] var keyPoints: [CGPoint] = []
var movingAverage: MovingAverage = MovingAverage(windowSize: 3) var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
@@ -71,30 +69,31 @@ final class PenStroke: Stroke, @unchecked Sendable {
} }
} }
func saveQuads(to index: Int) { func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape) {
let quads = Array(quads[batchIndex..<index]) let quad = Quad(
batchIndex = index origin: point,
withPersistence(\.backgroundContext) { [weak self, object] context in size: thickness,
guard let self else { return } rotation: rotation,
var topLeft: CGPoint = CGPoint(x: bounds[0], y: bounds[1]) shape: shape.rawValue,
var bottomRight: CGPoint = CGPoint(x: bounds[2], y: bounds[3]) color: color
for _quad in quads { )
let quad = QuadObject(\.backgroundContext) quads.append(quad)
quad.originX = _quad.originX.cgFloat bounds = [
quad.originY = _quad.originY.cgFloat min(quad.originX.cgFloat, bounds[0]),
quad.size = _quad.size.cgFloat min(quad.originY.cgFloat, bounds[1]),
quad.rotation = _quad.rotation.cgFloat max(quad.originX.cgFloat, bounds[2]),
quad.shape = _quad.shape max(quad.originY.cgFloat, bounds[3])
quad.color = _quad.getColor() ]
quad.stroke = object withPersistence(\.backgroundContext) { [object, _quad = quad] context in
object?.quads.add(quad) let quad = QuadObject(\.backgroundContext)
topLeft.x = min(quad.originX, topLeft.x) quad.originX = _quad.originX.cgFloat
topLeft.y = min(quad.originY, topLeft.y) quad.originY = _quad.originY.cgFloat
bottomRight.x = max(quad.originX, bottomRight.x) quad.size = _quad.size.cgFloat
bottomRight.y = max(quad.originY, bottomRight.y) quad.rotation = _quad.rotation.cgFloat
} quad.shape = _quad.shape
bounds = [topLeft.x, topLeft.y, bottomRight.x, bottomRight.y] quad.color = _quad.getColor()
object?.bounds = bounds quad.stroke = object
object?.quads.add(quad)
} }
} }
} }