blob: abafde2a90c15a409582462ac88c5077e6cd7169 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@_exported import CoreGraphics
import Darwin
//===----------------------------------------------------------------------===//
// CGAffineTransform
//===----------------------------------------------------------------------===//
extension CGAffineTransform: Equatable {
public static func ==(lhs: CGAffineTransform,
rhs: CGAffineTransform) -> Bool {
return lhs.__equalTo(rhs)
}
}
//===----------------------------------------------------------------------===//
// CGColor
//===----------------------------------------------------------------------===//
extension CGColor {
@available(OSX 10.3, iOS 2.0, *)
public var components: [CGFloat]? {
guard let pointer = self.__unsafeComponents else { return nil }
let buffer = UnsafeBufferPointer(start: pointer, count: self.numberOfComponents)
return Array(buffer)
}
#if os(macOS)
public class var white: CGColor
{ return CGColor.__constantColor(for: CGColor.__whiteColorName)! }
public class var black: CGColor
{ return CGColor.__constantColor(for: CGColor.__blackColorName)! }
public class var clear: CGColor
{ return CGColor.__constantColor(for: CGColor.__clearColorName)! }
#endif
}
public protocol _CGColorInitTrampoline {
init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
}
extension _CGColorInitTrampoline {
public init(colorLiteralRed red: Float, green: Float, blue: Float,
alpha: Float) {
self.init(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue),
alpha: CGFloat(alpha))
}
}
extension CGColor : _CGColorInitTrampoline, _ExpressibleByColorLiteral { }
//===----------------------------------------------------------------------===//
// CGColorSpace
//===----------------------------------------------------------------------===//
extension CGColorSpace {
public var colorTable: [UInt8]? {
guard self.model == .indexed else { return nil }
var table = [UInt8](repeating: 0, count: self.__colorTableCount)
self.__unsafeGetColorTable(&table)
return table
}
}
//===----------------------------------------------------------------------===//
// CGContext
//===----------------------------------------------------------------------===//
extension CGContext {
public func setLineDash(phase: CGFloat, lengths: [CGFloat]) {
self.__setLineDash(phase: phase, lengths: lengths, count: lengths.count)
}
public func move(to point: CGPoint) {
self.__moveTo(x: point.x, y: point.y)
}
public func addLine(to point: CGPoint) {
self.__addLineTo(x: point.x, y: point.y)
}
public func addCurve(to end: CGPoint, control1: CGPoint, control2: CGPoint) {
self.__addCurveTo(cp1x: control1.x, cp1y: control1.y,
cp2x: control2.x, cp2y: control2.y, endingAtX: end.x, y: end.y)
}
public func addQuadCurve(to end: CGPoint, control: CGPoint) {
self.__addQuadCurveTo(cpx: control.x, cpy: control.y,
endingAtX: end.x, y: end.y)
}
public func addRects(_ rects: [CGRect]) {
self.__addRects(rects, count: rects.count)
}
public func addLines(between points: [CGPoint]) {
self.__addLines(between: points, count: points.count)
}
public func addArc(center: CGPoint, radius: CGFloat, startAngle: CGFloat,
endAngle: CGFloat, clockwise: Bool) {
self.__addArc(centerX: center.x, y: center.y, radius: radius,
startAngle: startAngle, endAngle: endAngle, clockwise: clockwise ? 1 : 0)
}
public func addArc(tangent1End: CGPoint, tangent2End: CGPoint,
radius: CGFloat) {
self.__addArc(x1: tangent1End.x, y1: tangent1End.y,
x2: tangent2End.x, y2: tangent2End.y, radius: radius)
}
/// Fills the current path using the specified rule (winding by default).
///
/// Any open subpath is implicitly closed.
public func fillPath(using rule: CGPathFillRule = .winding) {
switch rule {
case .winding: self.__fillPath()
case .evenOdd: self.__eoFillPath()
}
}
/// Intersects the current path with the current clipping region and uses the
/// result as the new clipping region for subsequent drawing.
///
/// Uses the specified fill rule (winding by default) to determine which
/// areas to treat as the interior of the clipping region. When evaluating
/// the path, any open subpath is implicitly closed.
public func clip(using rule: CGPathFillRule = .winding) {
switch rule {
case .winding: self.__clip()
case .evenOdd: self.__eoClip()
}
}
public func fill(_ rects: [CGRect]) {
self.__fill(rects, count: rects.count)
}
public func strokeLineSegments(between points: [CGPoint]) {
self.__strokeLineSegments(between: points, count: points.count)
}
public func clip(to rects: [CGRect]) {
self.__clip(to: rects, count: rects.count)
}
public func draw(_ image: CGImage, in rect: CGRect, byTiling: Bool = false) {
if byTiling {
self.__draw(in: rect, byTiling: image)
} else {
self.__draw(in: rect, image: image)
}
}
public var textPosition: CGPoint {
get { return self.__textPosition }
set { self.__setTextPosition(x: newValue.x, y: newValue.y) }
}
public func showGlyphs(_ glyphs: [CGGlyph], at positions: [CGPoint]) {
precondition(glyphs.count == positions.count)
self.__showGlyphs(glyphs, atPositions: positions, count: glyphs.count)
}
}
//===----------------------------------------------------------------------===//
// CGDataProvider
//===----------------------------------------------------------------------===//
// TODO: replace init(UnsafePointer<UInt8>) with init(String)
// blocked on rdar://problem/27444567
//===----------------------------------------------------------------------===//
// CGDirectDisplay
//===----------------------------------------------------------------------===//
#if os(macOS)
public func CGGetLastMouseDelta() -> (x: Int32, y: Int32) {
var pair: (x: Int32, y: Int32) = (0, 0)
__CGGetLastMouseDelta(&pair.x, &pair.y)
return pair
}
#endif
//===----------------------------------------------------------------------===//
// CGGeometry
//===----------------------------------------------------------------------===//
public extension CGPoint {
static var zero: CGPoint {
@_transparent // @fragile
get { return CGPoint(x: 0, y: 0) }
}
@_transparent // @fragile
init(x: Int, y: Int) {
self.init(x: CGFloat(x), y: CGFloat(y))
}
@_transparent // @fragile
init(x: Double, y: Double) {
self.init(x: CGFloat(x), y: CGFloat(y))
}
init?(dictionaryRepresentation dict: CFDictionary) {
var point = CGPoint()
if CGPoint.__setFromDictionaryRepresentation(dict, &point) {
self = point
} else {
return nil
}
}
}
extension CGPoint : CustomReflectable, CustomPlaygroundQuickLookable {
public var customMirror: Mirror {
return Mirror(self, children: ["x": x, "y": y], displayStyle: .`struct`)
}
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .point(Double(x), Double(y))
}
}
extension CGPoint : CustomDebugStringConvertible {
public var debugDescription: String {
return "(\(x), \(y))"
}
}
extension CGPoint : Equatable {
@_transparent // @fragile
public static func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
public extension CGSize {
static var zero: CGSize {
@_transparent // @fragile
get { return CGSize(width: 0, height: 0) }
}
@_transparent // @fragile
init(width: Int, height: Int) {
self.init(width: CGFloat(width), height: CGFloat(height))
}
@_transparent // @fragile
init(width: Double, height: Double) {
self.init(width: CGFloat(width), height: CGFloat(height))
}
init?(dictionaryRepresentation dict: CFDictionary) {
var size = CGSize()
if CGSize.__setFromDictionaryRepresentation(dict, &size) {
self = size
} else {
return nil
}
}
}
extension CGSize : CustomReflectable, CustomPlaygroundQuickLookable {
public var customMirror: Mirror {
return Mirror(
self,
children: ["width": width, "height": height],
displayStyle: .`struct`)
}
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .size(Double(width), Double(height))
}
}
extension CGSize : CustomDebugStringConvertible {
public var debugDescription : String {
return "(\(width), \(height))"
}
}
extension CGSize : Equatable {
@_transparent // @fragile
public static func == (lhs: CGSize, rhs: CGSize) -> Bool {
return lhs.width == rhs.width && lhs.height == rhs.height
}
}
public extension CGVector {
static var zero: CGVector {
@_transparent // @fragile
get { return CGVector(dx: 0, dy: 0) }
}
@_transparent // @fragile
init(dx: Int, dy: Int) {
self.init(dx: CGFloat(dx), dy: CGFloat(dy))
}
@_transparent // @fragile
init(dx: Double, dy: Double) {
self.init(dx: CGFloat(dx), dy: CGFloat(dy))
}
}
extension CGVector : Equatable {
@_transparent // @fragile
public static func == (lhs: CGVector, rhs: CGVector) -> Bool {
return lhs.dx == rhs.dx && lhs.dy == rhs.dy
}
}
extension CGVector : CustomDebugStringConvertible {
public var debugDescription : String {
return "(\(dx), \(dy))"
}
}
public extension CGRect {
static var zero: CGRect {
@_transparent // @fragile
get { return CGRect(x: 0, y: 0, width: 0, height: 0) }
}
@_transparent // @fragile
init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {
self.init(origin: CGPoint(x: x, y: y),
size: CGSize(width: width, height: height))
}
@_transparent // @fragile
init(x: Double, y: Double, width: Double, height: Double) {
self.init(origin: CGPoint(x: x, y: y),
size: CGSize(width: width, height: height))
}
@_transparent // @fragile
init(x: Int, y: Int, width: Int, height: Int) {
self.init(origin: CGPoint(x: x, y: y),
size: CGSize(width: width, height: height))
}
init?(dictionaryRepresentation dict: CFDictionary) {
var rect = CGRect()
if CGRect.__setFromDictionaryRepresentation(dict, &rect) {
self = rect
} else {
return nil
}
}
@_transparent // @fragile
func divided(atDistance: CGFloat, from fromEdge: CGRectEdge)
-> (slice: CGRect, remainder: CGRect)
{
var slice = CGRect.zero
var remainder = CGRect.zero
self.__divided(slice: &slice, remainder: &remainder, atDistance: atDistance,
from: fromEdge)
return (slice, remainder)
}
@available(*, unavailable, renamed: "minX")
public var x: CGFloat { return minX }
@available(*, unavailable, renamed: "minY")
public var y: CGFloat { return minY }
}
extension CGRect : CustomReflectable, CustomPlaygroundQuickLookable {
public var customMirror: Mirror {
return Mirror(
self,
children: ["origin": origin, "size": size],
displayStyle: .`struct`)
}
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .rectangle(
Double(origin.x), Double(origin.y),
Double(size.width), Double(size.height))
}
}
extension CGRect : CustomDebugStringConvertible {
public var debugDescription : String {
return "(\(origin.x), \(origin.y), \(size.width), \(size.height))"
}
}
extension CGRect : Equatable {
@_transparent // @fragile
public static func == (lhs: CGRect, rhs: CGRect) -> Bool {
return lhs.equalTo(rhs)
}
}
extension CGAffineTransform {
public static var identity: CGAffineTransform {
@_transparent // @fragile
get { return CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) }
}
}
//===----------------------------------------------------------------------===//
// CGImage
//===----------------------------------------------------------------------===//
extension CGImage {
public func copy(maskingColorComponents components: [CGFloat]) -> CGImage? {
return self.__copy(maskingColorComponents: UnsafePointer(components))
}
}
//===----------------------------------------------------------------------===//
// CGLayer
//===----------------------------------------------------------------------===//
// TODO: remove auxiliaryInfo parameter from CGLayer.init,
// or at least give it a default value (empty/nil)
// blocked on rdar://problem/27444567
extension CGContext {
public func draw(_ layer: CGLayer, in rect: CGRect) {
self.__draw(in: rect, layer: layer)
}
public func draw(_ layer: CGLayer, at point: CGPoint) {
self.__draw(at: point, layer: layer)
}
}
//===----------------------------------------------------------------------===//
// CGPath & CGMutablePath
//===----------------------------------------------------------------------===//
// TODO: Make this a nested type (CGPath.FillRule)
public enum CGPathFillRule: Int {
/// Nonzero winding number fill rule.
///
/// This rule plots a ray from the interior of the region to be evaluated
/// toward the bounds of the drawing, and sums the closed path elements
/// that the ray crosses: +1 for counterclockwise paths, -1 for clockwise.
/// If the sum is zero, the region is left empty; if the sum is nonzero,
/// the region is filled.
case winding
/// Even-Odd fill rule.
///
/// This rule plots a ray from the interior of the region to be evaluated
/// toward the bounds of the drawing, and sums the closed path elements
/// that the ray crosses.
/// If the sum is an even numner, the region is left empty; if the sum is
/// an odd number, the region is filled.
case evenOdd
}
extension CGPath {
public func copy(dashingWithPhase phase: CGFloat, lengths: [CGFloat],
transform: CGAffineTransform = .identity) -> CGPath {
return CGPath(__byDashing: self, transform: [transform],
phase: phase, lengths: lengths, count: lengths.count)!
// force unwrap / non-optional return ok: underlying func returns nil
// only on bad input that we've made impossible (self and transform)
}
public func copy(strokingWithWidth lineWidth: CGFloat, lineCap: CGLineCap,
lineJoin: CGLineJoin, miterLimit: CGFloat,
transform: CGAffineTransform = .identity) -> CGPath {
return CGPath(__byStroking: self, transform: [transform],
lineWidth: lineWidth, lineCap: lineCap, lineJoin: lineJoin,
miterLimit: miterLimit)!
// force unwrap / non-optional return ok: underlying func returns nil
// only on bad input that we've made impossible (self and transform)
}
public func contains(_ point: CGPoint, using rule: CGPathFillRule = .winding,
transform: CGAffineTransform = .identity) -> Bool {
return self.__containsPoint(transform: [transform],
point: point, eoFill: (rule == .evenOdd))
}
}
extension CGMutablePath {
public func addRoundedRect(in rect: CGRect, cornerWidth: CGFloat,
cornerHeight: CGFloat, transform: CGAffineTransform = .identity) {
self.__addRoundedRect(transform: [transform], rect: rect,
cornerWidth: cornerWidth, cornerHeight: cornerHeight)
}
public func move(to point: CGPoint,
transform: CGAffineTransform = .identity) {
self.__moveTo(transform: [transform], x: point.x, y: point.y)
}
public func addLine(to point: CGPoint,
transform: CGAffineTransform = .identity) {
self.__addLineTo(transform: [transform], x: point.x, y: point.y)
}
public func addQuadCurve(to end: CGPoint, control: CGPoint,
transform: CGAffineTransform = .identity) {
self.__addQuadCurve(transform: [transform], cpx: control.x, cpy: control.y,
endingAtX: end.x, y: end.y)
}
public func addCurve(to end: CGPoint, control1: CGPoint, control2: CGPoint,
transform: CGAffineTransform = .identity) {
self.__addCurve(transform: [transform], cp1x: control1.x, cp1y: control1.y,
cp2x: control2.x, cp2y: control2.y, endingAtX: end.x, y: end.y)
}
public func addRect(_ rect: CGRect,
transform: CGAffineTransform = .identity) {
self.__addRect(transform: [transform], rect: rect)
}
public func addRects(_ rects: [CGRect],
transform: CGAffineTransform = .identity) {
self.__addRects(transform: [transform], rects: rects, count: rects.count)
}
public func addLines(between points: [CGPoint],
transform: CGAffineTransform = .identity) {
self.__addLines(transform: [transform],
between: points, count: points.count)
}
public func addEllipse(in rect: CGRect,
transform: CGAffineTransform = .identity) {
self.__addEllipse(transform: [transform], rect: rect)
}
public func addRelativeArc(center: CGPoint, radius: CGFloat,
startAngle: CGFloat, delta: CGFloat,
transform: CGAffineTransform = .identity) {
self.__addRelativeArc(transform: [transform], x: center.x, y: center.y,
radius: radius, startAngle: startAngle, delta: delta)
}
public func addArc(center: CGPoint, radius: CGFloat,
startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool,
transform: CGAffineTransform = .identity) {
self.__addArc(transform: [transform], x: center.x, y: center.y,
radius: radius, startAngle: startAngle, endAngle: endAngle,
clockwise: clockwise)
}
public func addArc(tangent1End: CGPoint, tangent2End: CGPoint,
radius: CGFloat, transform: CGAffineTransform = .identity) {
self.__addArc(transform: [transform], x1: tangent1End.x, y1: tangent1End.y,
x2: tangent2End.x, y2: tangent2End.y, radius: radius)
}
public func addPath(_ path: CGPath,
transform: CGAffineTransform = .identity) {
self.__addPath(transform: [transform], path: path)
}
}