Created
August 21, 2019 06:21
-
-
Save muizidn/1cf2fc96951159a6dd4187caaf9dff83 to your computer and use it in GitHub Desktop.
Canvas API using CoreGraphics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
final class CanvasRenderingContext2D { | |
private let ctx: CGContext | |
private let bounds: CGRect | |
init?(fitIn bounds: CGRect = .zero) { | |
guard let ctx = UIGraphicsGetCurrentContext() else { return nil } | |
self.ctx = ctx | |
self.bounds = bounds | |
} | |
} | |
// Properties | |
extension CanvasRenderingContext2D { | |
var canvas: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var currentTransform: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var direction: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var fillStyle: String { | |
get { | |
fatalError() | |
} | |
set { | |
ctx.setFillColor( | |
color(newValue).cgColor | |
) | |
} | |
} | |
var filter: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var font: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var globalAlpha: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var globalCompositeOperation: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var imageSmoothingEnabled: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var imageSmoothingQuality: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var lineCap: String { | |
get { | |
fatalError() | |
} | |
set { | |
let cap: CGLineCap | |
switch newValue { | |
case "butt": cap = .butt | |
case "round": cap = .round | |
case "square": cap = .square | |
default: cap = .butt | |
} | |
ctx.setLineCap(cap) | |
} | |
} | |
var lineDashOffset: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var lineJoin: String { | |
get { | |
fatalError() | |
} | |
set { | |
let join: CGLineJoin | |
switch newValue { | |
case "bevel": join = .bevel | |
case "round": join = .round | |
case "miter": join = .miter | |
default: join = .miter | |
} | |
ctx.setLineJoin(join) | |
} | |
} | |
var lineWidth: CGFloat { | |
get { | |
fatalError() | |
} | |
set { | |
ctx.setLineWidth(newValue) | |
} | |
} | |
var miterLimit: CGFloat { | |
get { | |
fatalError() | |
} | |
set { | |
ctx.setMiterLimit(newValue) | |
} | |
} | |
var shadowBlur: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var shadowColor: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var shadowOffsetX: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var shadowOffsetY: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var strokeStyle: String { | |
get { | |
fatalError() | |
} | |
set { | |
ctx.setStrokeColor( | |
color(newValue).cgColor | |
) | |
} | |
} | |
var textAlign: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
var textBaseline: String { | |
get { | |
fatalError() | |
} | |
set { | |
_ = newValue | |
} | |
} | |
} | |
extension CanvasRenderingContext2D { | |
private func color(_ string: String) -> UIColor { | |
var color: UIColor = .clear | |
if string.starts(with: "#") { | |
color = UIColor.fromHex(string)! | |
} else if let cssColor = CSSPredefinedColor(rawValue: string) { | |
color = UIColor.fromHex(cssColor.hexColor)! | |
} else { | |
if string.hasPrefix("rgb") { | |
guard let openP = string.firstIndex(of: "(") else { fatalError() } | |
guard let closeP = string.firstIndex(of: ")") else { fatalError() } | |
let values = string[string.index(after: openP)...string.index(before: closeP)] | |
.replacingOccurrences(of: " ", with: "") | |
.split(separator: ",") | |
.map({ String($0) }) | |
.compactMap({ Int($0) }) | |
.map({ CGFloat($0) }) | |
if values.count == 3 { | |
color = UIColor.init(red: values[0], | |
green: values[1], | |
blue: values[2], | |
alpha: 1) | |
} else if values.count == 4 { | |
color = UIColor.init(red: values[0], | |
green: values[1], | |
blue: values[2], | |
alpha: values[3]) | |
} else { | |
fatalError() | |
// FIXME: HSL | |
} | |
} | |
} | |
return color | |
} | |
} | |
// Methods | |
extension CanvasRenderingContext2D { | |
func addHitRegion() { | |
fatalError() | |
} | |
func arc() { | |
fatalError() | |
} | |
func arcTo() { | |
fatalError() | |
} | |
func beginPath() { | |
ctx.beginPath() | |
} | |
func bezierCurveTo(_ cp1x: CGFloat, | |
_ cp1y: CGFloat, | |
_ cp2x: CGFloat, | |
_ cp2y: CGFloat, | |
_ x: CGFloat, | |
_ y: CGFloat) { | |
ctx.addCurve(to: CGPoint(x: x, y: y), | |
control1: CGPoint(x: cp1x, y: cp1y), | |
control2: CGPoint(x: cp2x, y: cp2y)) | |
} | |
func clearHitRegions() { | |
fatalError() | |
} | |
func clearRect() { | |
fatalError() | |
} | |
func clip() { | |
ctx.clip() | |
} | |
func closePath() { | |
ctx.closePath() | |
} | |
func createImageData() { | |
fatalError() | |
} | |
func createLinearGradient() { | |
fatalError() | |
} | |
func createPattern() { | |
fatalError() | |
} | |
func createRadialGradient() { | |
fatalError() | |
} | |
func drawFocusIfNeeded() { | |
fatalError() | |
} | |
func drawImage() { | |
fatalError() | |
} | |
func drawWidgetAsOnScreen() { | |
fatalError() | |
} | |
func drawWindow() { | |
fatalError() | |
} | |
func ellipse() { | |
fatalError() | |
} | |
func fill() { | |
ctx.fillPath() | |
} | |
func fillRect() { | |
fatalError() | |
} | |
func fillText() { | |
fatalError() | |
} | |
func getImageData() { | |
fatalError() | |
} | |
func getLineDash() { | |
fatalError() | |
} | |
func isPointInPath() { | |
fatalError() | |
} | |
func isPointInStroke() { | |
fatalError() | |
} | |
func lineTo(_ x: CGFloat, _ y: CGFloat) { | |
ctx.addLine(to: CGPoint(x: x, y: y)) | |
} | |
func measureText() { | |
fatalError() | |
} | |
func moveTo(_ x: CGFloat, _ y: CGFloat) { | |
ctx.move(to: CGPoint(x: x, y: y)) | |
} | |
func putImageData() { | |
fatalError() | |
} | |
func quadraticCurveTo() { | |
fatalError() | |
} | |
func rect() { | |
fatalError() | |
} | |
func removeHitRegion() { | |
fatalError() | |
} | |
func resetTransform() { | |
fatalError() | |
} | |
func restore() { | |
ctx.restoreGState() | |
} | |
func rotate() { | |
fatalError() | |
} | |
func save() { | |
ctx.saveGState() | |
} | |
func scale(_ x: CGFloat, _ y: CGFloat) { | |
ctx.scaleBy(x: x, y: y) | |
} | |
func scrollPathIntoView() { | |
fatalError() | |
} | |
func setLineDash() { | |
fatalError() | |
} | |
func setTransform() { | |
fatalError() | |
} | |
func stroke() { | |
ctx.strokePath() | |
} | |
func strokeRect( _ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) { | |
ctx.stroke(CGRect(x: x, | |
y: y, | |
width: width, | |
height: height)) | |
} | |
func strokeText() { | |
fatalError() | |
} | |
func transform() { | |
fatalError() | |
} | |
func translate(_ x: CGFloat, _ y: CGFloat) { | |
ctx.translateBy(x: x, y: y) | |
} | |
} | |
// https://www.w3schools.com/colors/colors_names.asp | |
enum CSSPredefinedColor: String { | |
case aliceblue = "aliceblue" | |
case antiquewhite = "antiquewhite" | |
case aqua = "aqua" | |
case aquamarine = "aquamarine" | |
case azure = "azure" | |
case beige = "beige" | |
case bisque = "bisque" | |
case black = "black" | |
case blanchedalmond = "blanchedalmond" | |
case blue = "blue" | |
case blueviolet = "blueviolet" | |
case brown = "brown" | |
case burlywood = "burlywood" | |
case cadetblue = "cadetblue" | |
case chartreuse = "chartreuse" | |
case chocolate = "chocolate" | |
case coral = "coral" | |
case cornflowerblue = "cornflowerblue" | |
case cornsilk = "cornsilk" | |
case crimson = "crimson" | |
case cyan = "cyan" | |
case darkblue = "darkblue" | |
case darkcyan = "darkcyan" | |
case darkgoldenrod = "darkgoldenrod" | |
case darkgray = "darkgray" | |
case darkgrey = "darkgrey" | |
case darkgreen = "darkgreen" | |
case darkkhaki = "darkkhaki" | |
case darkmagenta = "darkmagenta" | |
case darkolivegreen = "darkolivegreen" | |
case darkorange = "darkorange" | |
case darkorchid = "darkorchid" | |
case darkred = "darkred" | |
case darksalmon = "darksalmon" | |
case darkseagreen = "darkseagreen" | |
case darkslateblue = "darkslateblue" | |
case darkslategray = "darkslategray" | |
case darkslategrey = "darkslategrey" | |
case darkturquoise = "darkturquoise" | |
case darkviolet = "darkviolet" | |
case deeppink = "deeppink" | |
case deepskyblue = "deepskyblue" | |
case dimgray = "dimgray" | |
case dimgrey = "dimgrey" | |
case dodgerblue = "dodgerblue" | |
case firebrick = "firebrick" | |
case floralwhite = "floralwhite" | |
case forestgreen = "forestgreen" | |
case fuchsia = "fuchsia" | |
case gainsboro = "gainsboro" | |
case ghostwhite = "ghostwhite" | |
case gold = "gold" | |
case goldenrod = "goldenrod" | |
case gray = "gray" | |
case grey = "grey" | |
case green = "green" | |
case greenyellow = "greenyellow" | |
case honeydew = "honeydew" | |
case hotpink = "hotpink" | |
case indianred = "indianred" | |
case indigo = "indigo" | |
case ivory = "ivory" | |
case khaki = "khaki" | |
case lavender = "lavender" | |
case lavenderblush = "lavenderblush" | |
case lawngreen = "lawngreen" | |
case lemonchiffon = "lemonchiffon" | |
case lightblue = "lightblue" | |
case lightcoral = "lightcoral" | |
case lightcyan = "lightcyan" | |
case lightgoldenrodyellow = "lightgoldenrodyellow" | |
case lightgray = "lightgray" | |
case lightgrey = "lightgrey" | |
case lightgreen = "lightgreen" | |
case lightpink = "lightpink" | |
case lightsalmon = "lightsalmon" | |
case lightseagreen = "lightseagreen" | |
case lightskyblue = "lightskyblue" | |
case lightslategray = "lightslategray" | |
case lightslategrey = "lightslategrey" | |
case lightsteelblue = "lightsteelblue" | |
case lightyellow = "lightyellow" | |
case lime = "lime" | |
case limegreen = "limegreen" | |
case linen = "linen" | |
case magenta = "magenta" | |
case maroon = "maroon" | |
case mediumaquamarine = "mediumaquamarine" | |
case mediumblue = "mediumblue" | |
case mediumorchid = "mediumorchid" | |
case mediumpurple = "mediumpurple" | |
case mediumseagreen = "mediumseagreen" | |
case mediumslateblue = "mediumslateblue" | |
case mediumspringgreen = "mediumspringgreen" | |
case mediumturquoise = "mediumturquoise" | |
case mediumvioletred = "mediumvioletred" | |
case midnightblue = "midnightblue" | |
case mintcream = "mintcream" | |
case mistyrose = "mistyrose" | |
case moccasin = "moccasin" | |
case navajowhite = "navajowhite" | |
case navy = "navy" | |
case oldlace = "oldlace" | |
case olive = "olive" | |
case olivedrab = "olivedrab" | |
case orange = "orange" | |
case orangered = "orangered" | |
case orchid = "orchid" | |
case palegoldenrod = "palegoldenrod" | |
case palegreen = "palegreen" | |
case paleturquoise = "paleturquoise" | |
case palevioletred = "palevioletred" | |
case papayawhip = "papayawhip" | |
case peachpuff = "peachpuff" | |
case peru = "peru" | |
case pink = "pink" | |
case plum = "plum" | |
case powderblue = "powderblue" | |
case purple = "purple" | |
case rebeccapurple = "rebeccapurple" | |
case red = "red" | |
case rosybrown = "rosybrown" | |
case royalblue = "royalblue" | |
case saddlebrown = "saddlebrown" | |
case salmon = "salmon" | |
case sandybrown = "sandybrown" | |
case seagreen = "seagreen" | |
case seashell = "seashell" | |
case sienna = "sienna" | |
case silver = "silver" | |
case skyblue = "skyblue" | |
case slateblue = "slateblue" | |
case slategray = "slategray" | |
case slategrey = "slategrey" | |
case snow = "snow" | |
case springgreen = "springgreen" | |
case steelblue = "steelblue" | |
case tan = "tan" | |
case teal = "teal" | |
case thistle = "thistle" | |
case tomato = "tomato" | |
case turquoise = "turquoise" | |
case violet = "violet" | |
case wheat = "wheat" | |
case white = "white" | |
case whitesmoke = "whitesmoke" | |
case yellow = "yellow" | |
case yellowgreen = "yellowgreen" | |
var hexColor: String { | |
switch self { | |
case .aliceblue: return "#f0f8ff" | |
case .antiquewhite: return "#faebd7" | |
case .aqua: return "#00ffff" | |
case .aquamarine: return "#7fffd4" | |
case .azure: return "#f0ffff" | |
case .beige: return "#f5f5dc" | |
case .bisque: return "#ffe4c4" | |
case .black: return "#000000" | |
case .blanchedalmond: return "#ffebcd" | |
case .blue: return "#0000ff" | |
case .blueviolet: return "#8a2be2" | |
case .brown: return "#a52a2a" | |
case .burlywood: return "#deb887" | |
case .cadetblue: return "#5f9ea0" | |
case .chartreuse: return "#7fff00" | |
case .chocolate: return "#d2691e" | |
case .coral: return "#ff7f50" | |
case .cornflowerblue: return "#6495ed" | |
case .cornsilk: return "#fff8dc" | |
case .crimson: return "#dc143c" | |
case .cyan: return "#00ffff" | |
case .darkblue: return "#00008b" | |
case .darkcyan: return "#008b8b" | |
case .darkgoldenrod: return "#b8860b" | |
case .darkgray: return "#a9a9a9" | |
case .darkgrey: return "#a9a9a9" | |
case .darkgreen: return "#006400" | |
case .darkkhaki: return "#bdb76b" | |
case .darkmagenta: return "#8b008b" | |
case .darkolivegreen: return "#556b2f" | |
case .darkorange: return "#ff8c00" | |
case .darkorchid: return "#9932cc" | |
case .darkred: return "#8b0000" | |
case .darksalmon: return "#e9967a" | |
case .darkseagreen: return "#8fbc8f" | |
case .darkslateblue: return "#483d8b" | |
case .darkslategray: return "#2f4f4f" | |
case .darkslategrey: return "#2f4f4f" | |
case .darkturquoise: return "#00ced1" | |
case .darkviolet: return "#9400d3" | |
case .deeppink: return "#ff1493" | |
case .deepskyblue: return "#00bfff" | |
case .dimgray: return "#696969" | |
case .dimgrey: return "#696969" | |
case .dodgerblue: return "#1e90ff" | |
case .firebrick: return "#b22222" | |
case .floralwhite: return "#fffaf0" | |
case .forestgreen: return "#228b22" | |
case .fuchsia: return "#ff00ff" | |
case .gainsboro: return "#dcdcdc" | |
case .ghostwhite: return "#f8f8ff" | |
case .gold: return "#ffd700" | |
case .goldenrod: return "#daa520" | |
case .gray: return "#808080" | |
case .grey: return "#808080" | |
case .green: return "#008000" | |
case .greenyellow: return "#adff2f" | |
case .honeydew: return "#f0fff0" | |
case .hotpink: return "#ff69b4" | |
case .indianred: return "#cd5c5c" | |
case .indigo: return "#4b0082" | |
case .ivory: return "#fffff0" | |
case .khaki: return "#f0e68c" | |
case .lavender: return "#e6e6fa" | |
case .lavenderblush: return "#fff0f5" | |
case .lawngreen: return "#7cfc00" | |
case .lemonchiffon: return "#fffacd" | |
case .lightblue: return "#add8e6" | |
case .lightcoral: return "#f08080" | |
case .lightcyan: return "#e0ffff" | |
case .lightgoldenrodyellow: return "#fafad2" | |
case .lightgray: return "#d3d3d3" | |
case .lightgrey: return "#d3d3d3" | |
case .lightgreen: return "#90ee90" | |
case .lightpink: return "#ffb6c1" | |
case .lightsalmon: return "#ffa07a" | |
case .lightseagreen: return "#20b2aa" | |
case .lightskyblue: return "#87cefa" | |
case .lightslategray: return "#778899" | |
case .lightslategrey: return "#778899" | |
case .lightsteelblue: return "#b0c4de" | |
case .lightyellow: return "#ffffe0" | |
case .lime: return "#00ff00" | |
case .limegreen: return "#32cd32" | |
case .linen: return "#faf0e6" | |
case .magenta: return "#ff00ff" | |
case .maroon: return "#800000" | |
case .mediumaquamarine: return "#66cdaa" | |
case .mediumblue: return "#0000cd" | |
case .mediumorchid: return "#ba55d3" | |
case .mediumpurple: return "#9370db" | |
case .mediumseagreen: return "#3cb371" | |
case .mediumslateblue: return "#7b68ee" | |
case .mediumspringgreen: return "#00fa9a" | |
case .mediumturquoise: return "#48d1cc" | |
case .mediumvioletred: return "#c71585" | |
case .midnightblue: return "#191970" | |
case .mintcream: return "#f5fffa" | |
case .mistyrose: return "#ffe4e1" | |
case .moccasin: return "#ffe4b5" | |
case .navajowhite: return "#ffdead" | |
case .navy: return "#000080" | |
case .oldlace: return "#fdf5e6" | |
case .olive: return "#808000" | |
case .olivedrab: return "#6b8e23" | |
case .orange: return "#ffa500" | |
case .orangered: return "#ff4500" | |
case .orchid: return "#da70d6" | |
case .palegoldenrod: return "#eee8aa" | |
case .palegreen: return "#98fb98" | |
case .paleturquoise: return "#afeeee" | |
case .palevioletred: return "#db7093" | |
case .papayawhip: return "#ffefd5" | |
case .peachpuff: return "#ffdab9" | |
case .peru: return "#cd853f" | |
case .pink: return "#ffc0cb" | |
case .plum: return "#dda0dd" | |
case .powderblue: return "#b0e0e6" | |
case .purple: return "#800080" | |
case .rebeccapurple: return "#663399" | |
case .red: return "#ff0000" | |
case .rosybrown: return "#bc8f8f" | |
case .royalblue: return "#4169e1" | |
case .saddlebrown: return "#8b4513" | |
case .salmon: return "#fa8072" | |
case .sandybrown: return "#f4a460" | |
case .seagreen: return "#2e8b57" | |
case .seashell: return "#fff5ee" | |
case .sienna: return "#a0522d" | |
case .silver: return "#c0c0c0" | |
case .skyblue: return "#87ceeb" | |
case .slateblue: return "#6a5acd" | |
case .slategray: return "#708090" | |
case .slategrey: return "#708090" | |
case .snow: return "#fffafa" | |
case .springgreen: return "#00ff7f" | |
case .steelblue: return "#4682b4" | |
case .tan: return "#d2b48c" | |
case .teal: return "#008080" | |
case .thistle: return "#d8bfd8" | |
case .tomato: return "#ff6347" | |
case .turquoise: return "#40e0d0" | |
case .violet: return "#ee82ee" | |
case .wheat: return "#f5deb3" | |
case .white: return "#ffffff" | |
case .whitesmoke: return "#f5f5f5" | |
case .yellow: return "#ffff00" | |
case .yellowgreen: return "#9acd32" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment