Swiftgram/submodules/DrawingUI/Sources/DrawingTools.swift
2023-05-15 15:12:51 +04:00

152 lines
4.3 KiB
Swift

import Foundation
import UIKit
import Display
import MediaEditor
final class MarkerTool: DrawingElement {
let uuid: UUID
let drawingSize: CGSize
let color: DrawingColor
let renderLineWidth: CGFloat
var translation = CGPoint()
var points: [CGPoint] = []
weak var metalView: DrawingMetalView?
var isValid: Bool {
return self.points.count > 6
}
var bounds: CGRect {
var minX: CGFloat = .greatestFiniteMagnitude
var minY: CGFloat = .greatestFiniteMagnitude
var maxX: CGFloat = 0.0
var maxY: CGFloat = 0.0
for point in self.points {
if point.x < minX {
minX = point.x
}
if point.x > maxX {
maxX = point.x
}
if point.y < minY {
minY = point.y
}
if point.y > maxY {
maxY = point.y
}
}
return normalizeDrawingRect(CGRect(x: minX, y: minY, width: maxX - minX, height: maxY - minY).insetBy(dx: -80.0, dy: -80.0), drawingSize: self.drawingSize)
}
required init(drawingSize: CGSize, color: DrawingColor, lineWidth: CGFloat) {
self.uuid = UUID()
self.drawingSize = drawingSize
self.color = color
let minLineWidth = max(10.0, max(drawingSize.width, drawingSize.height) * 0.01)
let maxLineWidth = max(20.0, max(drawingSize.width, drawingSize.height) * 0.09)
let lineWidth = minLineWidth + (maxLineWidth - minLineWidth) * lineWidth
self.renderLineWidth = lineWidth
}
func setupRenderView(screenSize: CGSize) -> DrawingRenderView? {
return nil
}
func setupRenderLayer() -> DrawingRenderLayer? {
return nil
}
private var didSetup = false
func updatePath(_ point: DrawingPoint, state: DrawingGesturePipeline.DrawingGestureState, zoomScale: CGFloat) {
let filterDistance: CGFloat = 10.0 / zoomScale
if let lastPoint = self.points.last, lastPoint.distance(to: point.location) < filterDistance {
} else {
self.points.append(point.location)
}
self.didSetup = true
self.metalView?.updated(point, state: state, brush: .marker, color: self.color, size: self.renderLineWidth)
}
func draw(in context: CGContext, size: CGSize) {
guard !self.points.isEmpty else {
return
}
context.saveGState()
context.translateBy(x: self.translation.x, y: self.translation.y)
self.metalView?.drawInContext(context)
self.metalView?.clear()
context.restoreGState()
}
}
final class FillTool: DrawingElement {
let uuid: UUID
let drawingSize: CGSize
let color: DrawingColor
let isBlur: Bool
var blurredImage: UIImage?
var translation = CGPoint()
var isValid: Bool {
return true
}
var bounds: CGRect {
return CGRect(origin: .zero, size: self.drawingSize)
}
required init(drawingSize: CGSize, color: DrawingColor, blur: Bool, blurredImage: UIImage?) {
self.uuid = UUID()
self.drawingSize = drawingSize
self.color = color
self.isBlur = blur
self.blurredImage = blurredImage
}
func setupRenderView(screenSize: CGSize) -> DrawingRenderView? {
return nil
}
func setupRenderLayer() -> DrawingRenderLayer? {
return nil
}
func updatePath(_ path: DrawingPoint, state: DrawingGesturePipeline.DrawingGestureState, zoomScale: CGFloat) {
}
func draw(in context: CGContext, size: CGSize) {
context.setShouldAntialias(false)
context.setBlendMode(.copy)
if self.isBlur {
if let blurredImage = self.blurredImage?.cgImage {
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
context.draw(blurredImage, in: CGRect(origin: .zero, size: size))
}
} else {
context.setFillColor(self.color.toCGColor())
context.fill(CGRect(origin: .zero, size: size))
}
context.setBlendMode(.normal)
}
}