mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
Fix qr code rendering
This commit is contained in:
@@ -12,7 +12,33 @@ public enum QrCodeIcon {
|
||||
case custom(UIImage?)
|
||||
}
|
||||
|
||||
public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M") -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
private func floorToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
|
||||
var scale = scale ?? UIScreenScale
|
||||
return floor(value * scale) / scale
|
||||
}
|
||||
|
||||
private func roundToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
|
||||
var scale = scale ?? UIScreenScale
|
||||
return round(value * scale) / scale
|
||||
}
|
||||
|
||||
public func qrCodeCutout(size: Int, dimensions: CGSize, scale: CGFloat?) -> (Int, CGRect, CGFloat) {
|
||||
var cutoutSize = Int(round(CGFloat(size) * 0.297))
|
||||
if size == 39 {
|
||||
cutoutSize = 11
|
||||
} else if cutoutSize % 2 == 0 {
|
||||
cutoutSize += 1
|
||||
}
|
||||
cutoutSize = min(23, cutoutSize)
|
||||
|
||||
let quadSize = floorToContextPixels(dimensions.width / CGFloat(size), scale: scale)
|
||||
let cutoutSide = quadSize * CGFloat(cutoutSize - 2)
|
||||
let cutoutRect = CGRect(x: floorToContextPixels((dimensions.width - cutoutSide) / 2.0, scale: scale), y: floorToContextPixels((dimensions.height - cutoutSide) / 2.0, scale: scale), width: cutoutSide, height: cutoutSide)
|
||||
|
||||
return (cutoutSize, cutoutRect, quadSize)
|
||||
}
|
||||
|
||||
public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M") -> Signal<(Int, (TransformImageArguments) -> DrawingContext?), NoError> {
|
||||
return Signal<(Data, Int, Int), NoError> { subscriber in
|
||||
if let data = string.data(using: .isoLatin1, allowLossyConversion: false), let filter = CIFilter(name: "CIQRCodeGenerator") {
|
||||
filter.setValue(data, forKey: "inputMessage")
|
||||
@@ -43,29 +69,20 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
||||
return EmptyDisposable
|
||||
}
|
||||
|> map { data, size, bytesPerRow in
|
||||
return { arguments in
|
||||
return (size, { arguments in
|
||||
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
|
||||
let side = floorToScreenPixels(arguments.drawingSize.width / CGFloat(size))
|
||||
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0)
|
||||
|
||||
|
||||
let drawingRect = arguments.drawingRect
|
||||
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
|
||||
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
|
||||
|
||||
let codeScale: CGFloat = 1.10256
|
||||
let clipSide = fittedRect.width * 0.23124
|
||||
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
|
||||
|
||||
let (cutoutSize, clipRect, side) = qrCodeCutout(size: size, dimensions: fittedSize, scale: arguments.scale)
|
||||
let padding: CGFloat = roundToContextPixels((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0, scale: arguments.scale)
|
||||
|
||||
let cutout: (Int, Int)?
|
||||
if case .none = icon {
|
||||
cutout = nil
|
||||
} else {
|
||||
var cutoutSize = Int(ceil((clipSide + side * 2.0) / side))
|
||||
if size == 39 {
|
||||
cutoutSize = 11
|
||||
} else if cutoutSize % 2 == 0 {
|
||||
cutoutSize += 1
|
||||
}
|
||||
let start = (size - cutoutSize) / 2
|
||||
cutout = (start, start + cutoutSize - 1)
|
||||
}
|
||||
@@ -211,7 +228,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
||||
c.setStrokeColor(color.cgColor)
|
||||
c.setFillColor(color.cgColor)
|
||||
|
||||
let markerSide = floorToScreenPixels(CGFloat(markerSize - 1) * squareSize.width * 1.05)
|
||||
let markerSide = floorToContextPixels(CGFloat(markerSize - 1) * squareSize.width * 1.05, scale: arguments.scale)
|
||||
|
||||
func drawMarker(x: CGFloat, y: CGFloat) {
|
||||
var path = UIBezierPath(roundedRect: CGRect(x: x + squareSize.width / 2.0, y: y + squareSize.width / 2.0, width: markerSide, height: markerSide), cornerRadius: markerSide / 3.5)
|
||||
@@ -233,7 +250,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
||||
|
||||
switch icon {
|
||||
case .proxy:
|
||||
let iconScale = fittedRect.width / 420.0 * codeScale
|
||||
let iconScale = clipRect.size.width * 0.01111
|
||||
let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale)
|
||||
let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0)
|
||||
c.translateBy(x: point.x, y: point.y)
|
||||
@@ -268,6 +285,6 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user