Render stroke and text items in image coordinates, not canvas coordinates.

pull/2/head
Matthew Chen 6 years ago
parent 7aa826748a
commit 674cf2e01f

@ -173,6 +173,7 @@ public class ImageEditorCanvasView: UIView {
contentLayerMap.removeAll() contentLayerMap.removeAll()
let viewSize = clipView.bounds.size let viewSize = clipView.bounds.size
let transform = model.currentTransform()
if viewSize.width > 0, if viewSize.width > 0,
viewSize.height > 0 { viewSize.height > 0 {
@ -183,6 +184,7 @@ public class ImageEditorCanvasView: UIView {
for item in model.items() { for item in model.items() {
guard let layer = ImageEditorCanvasView.layerForItem(item: item, guard let layer = ImageEditorCanvasView.layerForItem(item: item,
model: model, model: model,
transform: transform,
viewSize: viewSize) else { viewSize: viewSize) else {
continue continue
} }
@ -217,6 +219,7 @@ public class ImageEditorCanvasView: UIView {
} }
let viewSize = clipView.bounds.size let viewSize = clipView.bounds.size
let transform = model.currentTransform()
if viewSize.width > 0, if viewSize.width > 0,
viewSize.height > 0 { viewSize.height > 0 {
@ -234,6 +237,7 @@ public class ImageEditorCanvasView: UIView {
// Item was inserted or updated. // Item was inserted or updated.
guard let layer = ImageEditorCanvasView.layerForItem(item: item, guard let layer = ImageEditorCanvasView.layerForItem(item: item,
model: model, model: model,
transform: transform,
viewSize: viewSize) else { viewSize: viewSize) else {
continue continue
} }
@ -320,6 +324,7 @@ public class ImageEditorCanvasView: UIView {
private class func layerForItem(item: ImageEditorItem, private class func layerForItem(item: ImageEditorItem,
model: ImageEditorModel, model: ImageEditorModel,
transform: ImageEditorTransform,
viewSize: CGSize) -> CALayer? { viewSize: CGSize) -> CALayer? {
AssertIsOnMainThread() AssertIsOnMainThread()
@ -332,7 +337,10 @@ public class ImageEditorCanvasView: UIView {
owsFailDebug("Item has unexpected type: \(type(of: item)).") owsFailDebug("Item has unexpected type: \(type(of: item)).")
return nil return nil
} }
return strokeLayerForItem(item: strokeItem, viewSize: viewSize) return strokeLayerForItem(item: strokeItem,
model: model,
transform: transform,
viewSize: viewSize)
case .text: case .text:
guard let textItem = item as? ImageEditorTextItem else { guard let textItem = item as? ImageEditorTextItem else {
owsFailDebug("Item has unexpected type: \(type(of: item)).") owsFailDebug("Item has unexpected type: \(type(of: item)).")
@ -340,11 +348,14 @@ public class ImageEditorCanvasView: UIView {
} }
return textLayerForItem(item: textItem, return textLayerForItem(item: textItem,
model: model, model: model,
transform: transform,
viewSize: viewSize) viewSize: viewSize)
} }
} }
private class func strokeLayerForItem(item: ImageEditorStrokeItem, private class func strokeLayerForItem(item: ImageEditorStrokeItem,
model: ImageEditorModel,
transform: ImageEditorTransform,
viewSize: CGSize) -> CALayer? { viewSize: CGSize) -> CALayer? {
AssertIsOnMainThread() AssertIsOnMainThread()
@ -361,9 +372,9 @@ public class ImageEditorCanvasView: UIView {
shapeLayer.strokeColor = item.color.cgColor shapeLayer.strokeColor = item.color.cgColor
shapeLayer.frame = CGRect(origin: .zero, size: viewSize) shapeLayer.frame = CGRect(origin: .zero, size: viewSize)
let imageFrame = ImageEditorCanvasView.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, transform: transform)
let transformSampleToPoint = { (unitSample: CGPoint) -> CGPoint in let transformSampleToPoint = { (unitSample: CGPoint) -> CGPoint in
return CGPoint(x: viewSize.width * unitSample.x, return unitSample.fromUnitCoordinates(viewBounds: imageFrame)
y: viewSize.height * unitSample.y)
} }
// Use bezier curves to smooth stroke. // Use bezier curves to smooth stroke.
@ -436,11 +447,11 @@ public class ImageEditorCanvasView: UIView {
private class func textLayerForItem(item: ImageEditorTextItem, private class func textLayerForItem(item: ImageEditorTextItem,
model: ImageEditorModel, model: ImageEditorModel,
transform: ImageEditorTransform,
viewSize: CGSize) -> CALayer? { viewSize: CGSize) -> CALayer? {
AssertIsOnMainThread() AssertIsOnMainThread()
let imageFrame = self.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, let imageFrame = ImageEditorCanvasView.imageFrame(forViewSize: viewSize, imageSize: model.srcImageSizePixels, transform: transform)
transform: model.currentTransform())
// We need to adjust the font size to reflect the current output scale, // We need to adjust the font size to reflect the current output scale,
// using the image width as reference. // using the image width as reference.
@ -476,8 +487,7 @@ public class ImageEditorCanvasView: UIView {
.font: item.font.withSize(fontSize) .font: item.font.withSize(fontSize)
], ],
context: nil) context: nil)
let center = CGPoint(x: viewSize.width * item.unitCenter.x, let center = item.unitCenter.fromUnitCoordinates(viewBounds: imageFrame)
y: viewSize.height * item.unitCenter.y)
let layerSize = CGSizeCeil(textBounds.size) let layerSize = CGSizeCeil(textBounds.size)
layer.frame = CGRect(origin: CGPoint(x: center.x - layerSize.width * 0.5, layer.frame = CGRect(origin: CGPoint(x: center.x - layerSize.width * 0.5,
y: center.y - layerSize.height * 0.5), y: center.y - layerSize.height * 0.5),
@ -535,24 +545,24 @@ public class ImageEditorCanvasView: UIView {
transform: ImageEditorTransform) -> CGPoint { transform: ImageEditorTransform) -> CGPoint {
let locationInView = gestureRecognizer.location(in: view) let locationInView = gestureRecognizer.location(in: view)
return locationUnit(forLocationInView: locationInView, return locationUnit(forLocationInView: locationInView,
viewSize: view.bounds.size, viewBounds: view.bounds,
transform: transform) transform: transform)
} }
public func locationUnit(forLocationInView locationInView: CGPoint, public func locationUnit(forLocationInView locationInView: CGPoint,
transform: ImageEditorTransform) -> CGPoint { transform: ImageEditorTransform) -> CGPoint {
let viewSize = self.clipView.bounds.size let viewBounds = self.clipView.bounds
return ImageEditorCanvasView.locationUnit(forLocationInView: locationInView, return ImageEditorCanvasView.locationUnit(forLocationInView: locationInView,
viewSize: viewSize, viewBounds: viewBounds,
transform: transform) transform: transform)
} }
public class func locationUnit(forLocationInView locationInView: CGPoint, public class func locationUnit(forLocationInView locationInView: CGPoint,
viewSize: CGSize, viewBounds: CGRect,
transform: ImageEditorTransform) -> CGPoint { transform: ImageEditorTransform) -> CGPoint {
let affineTransformStart = transform.affineTransform(viewSize: viewSize) let affineTransformStart = transform.affineTransform(viewSize: viewBounds.size)
let locationInContent = locationInView.applyingInverse(affineTransformStart) let locationInContent = locationInView.minus(viewBounds.center).applyingInverse(affineTransformStart).plus(viewBounds.center)
let locationUnit = locationInContent.toUnitCoordinates(viewSize: viewSize, shouldClamp: false) let locationUnit = locationInContent.toUnitCoordinates(viewSize: viewBounds.size, shouldClamp: false)
return locationUnit return locationUnit
} }
@ -608,6 +618,7 @@ public class ImageEditorCanvasView: UIView {
for item in model.items() { for item in model.items() {
guard let layer = layerForItem(item: item, guard let layer = layerForItem(item: item,
model: model, model: model,
transform: transform,
viewSize: viewSize) else { viewSize: viewSize) else {
owsFailDebug("Couldn't create layer for item.") owsFailDebug("Couldn't create layer for item.")
continue continue

@ -149,9 +149,13 @@ public extension CGPoint {
return toUnitCoordinates(viewBounds: CGRect(origin: .zero, size: viewSize), shouldClamp: shouldClamp) 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 { public func fromUnitCoordinates(viewSize: CGSize) -> CGPoint {
return CGPoint(x: x.lerp(0, viewSize.width), return fromUnitCoordinates(viewBounds: CGRect(origin: .zero, size: viewSize))
y: y.lerp(0, viewSize.height))
} }
public func inverse() -> CGPoint { public func inverse() -> CGPoint {

Loading…
Cancel
Save