From 674cf2e01f3c11fa21447b3070a2a8af7fb37d51 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 21 Feb 2019 16:40:42 -0500 Subject: [PATCH] Render stroke and text items in image coordinates, not canvas coordinates. --- .../ImageEditor/ImageEditorCanvasView.swift | 39 ++++++++++++------- SignalMessaging/categories/UIView+OWS.swift | 8 +++- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift b/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift index ce696a272..a8c1c2759 100644 --- a/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift +++ b/SignalMessaging/Views/ImageEditor/ImageEditorCanvasView.swift @@ -173,6 +173,7 @@ public class ImageEditorCanvasView: UIView { contentLayerMap.removeAll() let viewSize = clipView.bounds.size + let transform = model.currentTransform() if viewSize.width > 0, viewSize.height > 0 { @@ -183,6 +184,7 @@ public class ImageEditorCanvasView: UIView { for item in model.items() { guard let layer = ImageEditorCanvasView.layerForItem(item: item, model: model, + transform: transform, viewSize: viewSize) else { continue } @@ -217,6 +219,7 @@ public class ImageEditorCanvasView: UIView { } let viewSize = clipView.bounds.size + let transform = model.currentTransform() if viewSize.width > 0, viewSize.height > 0 { @@ -234,6 +237,7 @@ public class ImageEditorCanvasView: UIView { // Item was inserted or updated. guard let layer = ImageEditorCanvasView.layerForItem(item: item, model: model, + transform: transform, viewSize: viewSize) else { continue } @@ -320,6 +324,7 @@ public class ImageEditorCanvasView: UIView { private class func layerForItem(item: ImageEditorItem, model: ImageEditorModel, + transform: ImageEditorTransform, viewSize: CGSize) -> CALayer? { AssertIsOnMainThread() @@ -332,7 +337,10 @@ public class ImageEditorCanvasView: UIView { owsFailDebug("Item has unexpected type: \(type(of: item)).") return nil } - return strokeLayerForItem(item: strokeItem, viewSize: viewSize) + return strokeLayerForItem(item: strokeItem, + model: model, + transform: transform, + viewSize: viewSize) case .text: guard let textItem = item as? ImageEditorTextItem else { owsFailDebug("Item has unexpected type: \(type(of: item)).") @@ -340,11 +348,14 @@ public class ImageEditorCanvasView: UIView { } return textLayerForItem(item: textItem, model: model, + transform: transform, viewSize: viewSize) } } private class func strokeLayerForItem(item: ImageEditorStrokeItem, + model: ImageEditorModel, + transform: ImageEditorTransform, viewSize: CGSize) -> CALayer? { AssertIsOnMainThread() @@ -361,9 +372,9 @@ public class ImageEditorCanvasView: UIView { shapeLayer.strokeColor = item.color.cgColor shapeLayer.frame = CGRect(origin: .zero, size: viewSize) + let imageFrame = ImageEditorCanvasView.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, transform: transform) let transformSampleToPoint = { (unitSample: CGPoint) -> CGPoint in - return CGPoint(x: viewSize.width * unitSample.x, - y: viewSize.height * unitSample.y) + return unitSample.fromUnitCoordinates(viewBounds: imageFrame) } // Use bezier curves to smooth stroke. @@ -436,11 +447,11 @@ public class ImageEditorCanvasView: UIView { private class func textLayerForItem(item: ImageEditorTextItem, model: ImageEditorModel, + transform: ImageEditorTransform, viewSize: CGSize) -> CALayer? { AssertIsOnMainThread() - let imageFrame = self.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, - transform: model.currentTransform()) + let imageFrame = ImageEditorCanvasView.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, transform: transform) // We need to adjust the font size to reflect the current output scale, // using the image width as reference. @@ -476,8 +487,7 @@ public class ImageEditorCanvasView: UIView { .font: item.font.withSize(fontSize) ], context: nil) - let center = CGPoint(x: viewSize.width * item.unitCenter.x, - y: viewSize.height * item.unitCenter.y) + let center = item.unitCenter.fromUnitCoordinates(viewBounds: imageFrame) let layerSize = CGSizeCeil(textBounds.size) layer.frame = CGRect(origin: CGPoint(x: center.x - layerSize.width * 0.5, y: center.y - layerSize.height * 0.5), @@ -535,24 +545,24 @@ public class ImageEditorCanvasView: UIView { transform: ImageEditorTransform) -> CGPoint { let locationInView = gestureRecognizer.location(in: view) return locationUnit(forLocationInView: locationInView, - viewSize: view.bounds.size, + viewBounds: view.bounds, transform: transform) } public func locationUnit(forLocationInView locationInView: CGPoint, transform: ImageEditorTransform) -> CGPoint { - let viewSize = self.clipView.bounds.size + let viewBounds = self.clipView.bounds return ImageEditorCanvasView.locationUnit(forLocationInView: locationInView, - viewSize: viewSize, + viewBounds: viewBounds, transform: transform) } public class func locationUnit(forLocationInView locationInView: CGPoint, - viewSize: CGSize, + viewBounds: CGRect, transform: ImageEditorTransform) -> CGPoint { - let affineTransformStart = transform.affineTransform(viewSize: viewSize) - let locationInContent = locationInView.applyingInverse(affineTransformStart) - let locationUnit = locationInContent.toUnitCoordinates(viewSize: viewSize, shouldClamp: false) + let affineTransformStart = transform.affineTransform(viewSize: viewBounds.size) + let locationInContent = locationInView.minus(viewBounds.center).applyingInverse(affineTransformStart).plus(viewBounds.center) + let locationUnit = locationInContent.toUnitCoordinates(viewSize: viewBounds.size, shouldClamp: false) return locationUnit } @@ -608,6 +618,7 @@ public class ImageEditorCanvasView: UIView { for item in model.items() { guard let layer = layerForItem(item: item, model: model, + transform: transform, viewSize: viewSize) else { owsFailDebug("Couldn't create layer for item.") continue diff --git a/SignalMessaging/categories/UIView+OWS.swift b/SignalMessaging/categories/UIView+OWS.swift index 5082dea68..3a7fa6ca9 100644 --- a/SignalMessaging/categories/UIView+OWS.swift +++ b/SignalMessaging/categories/UIView+OWS.swift @@ -149,9 +149,13 @@ public extension CGPoint { return toUnitCoordinates(viewBounds: CGRect(origin: .zero, size: viewSize), shouldClamp: shouldClamp) } + public func fromUnitCoordinates(viewBounds: CGRect) -> CGPoint { + return CGPoint(x: viewBounds.origin.x + x.lerp(0, viewBounds.size.width), + y: viewBounds.origin.y + y.lerp(0, viewBounds.size.height)) + } + public func fromUnitCoordinates(viewSize: CGSize) -> CGPoint { - return CGPoint(x: x.lerp(0, viewSize.width), - y: y.lerp(0, viewSize.height)) + return fromUnitCoordinates(viewBounds: CGRect(origin: .zero, size: viewSize)) } public func inverse() -> CGPoint {