Skip to content

Instantly share code, notes, and snippets.

@muizidn
Created August 21, 2019 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muizidn/1cf2fc96951159a6dd4187caaf9dff83 to your computer and use it in GitHub Desktop.
Save muizidn/1cf2fc96951159a6dd4187caaf9dff83 to your computer and use it in GitHub Desktop.
Canvas API using CoreGraphics
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