140 lines
3.7 KiB
Swift
140 lines
3.7 KiB
Swift
import Foundation
|
|
|
|
/// Represents a image chunk
|
|
struct SilicaChunk {
|
|
var x: Int = 0
|
|
var y: Int = 0
|
|
var image: CGImage?
|
|
}
|
|
|
|
/// Supported Silica blend modes, including extended blend modes
|
|
enum BlendMode : Int {
|
|
case Normal = 0,
|
|
Multiply = 1,
|
|
Screen = 2,
|
|
Add = 3,
|
|
Lighten = 4,
|
|
Exclusion = 5,
|
|
Difference = 6,
|
|
Subtract = 7,
|
|
LinearBurn = 8,
|
|
ColorDodge = 9,
|
|
ColorBurn = 10,
|
|
Overlay = 11,
|
|
HardLight = 12,
|
|
Color = 13,
|
|
Luminosity = 14,
|
|
Hue = 15,
|
|
Saturation = 16,
|
|
SoftLight = 17,
|
|
// TODO: where is 18?
|
|
Darken = 19,
|
|
|
|
// extended modes
|
|
HardMix = 20,
|
|
VividLight = 21,
|
|
LinearLight = 22,
|
|
PinLight = 23,
|
|
LighterColor = 24,
|
|
DarkerColor = 25,
|
|
Divide = 26
|
|
}
|
|
|
|
/// Represents the image data for a Silica Layer, may not be an actual layer present to the user, such as a mask.
|
|
struct SilicaLayerData {
|
|
var blendMode: BlendMode = .Normal
|
|
var chunks: [SilicaChunk] = []
|
|
var opacity: Double = 1.0
|
|
var hidden: Bool = false
|
|
}
|
|
|
|
/// A Silica Layer, which equates to a real layer present in the document
|
|
struct SilicaLayer : Equatable {
|
|
static func == (lhs: SilicaLayer, rhs: SilicaLayer) -> Bool {
|
|
return lhs.name == rhs.name && lhs.clipped == rhs.clipped
|
|
}
|
|
|
|
var name: String = ""
|
|
var data: SilicaLayerData = SilicaLayerData()
|
|
var mask: SilicaLayerData?
|
|
var clipped: Bool = false
|
|
}
|
|
|
|
/// Container for the Silica Document format
|
|
struct SilicaDocument {
|
|
var trackedTime: Int = 0
|
|
var tileSize: Int = 0
|
|
var orientation: Int = 0
|
|
var flippedHorizontally: Bool = false
|
|
var flippedVertically: Bool = false
|
|
var name: String = ""
|
|
var authorName: String = ""
|
|
var strokeCount: Int = 0
|
|
|
|
var backgroundColor: CGColor = .white
|
|
var colorSpace: CGColorSpace = CGColorSpaceCreateDeviceRGB()
|
|
|
|
var width: Int = 0
|
|
var height: Int = 0
|
|
|
|
var rows: Int = 0
|
|
var columns: Int = 0
|
|
|
|
var remainderWidth: Int = 0
|
|
var remainderHeight: Int = 0
|
|
|
|
var layers: [SilicaLayer] = []
|
|
|
|
var videoFrame: (Int, Int) = (0, 0)
|
|
|
|
func nsSize() -> NSSize {
|
|
return NSSize(width: width, height: height)
|
|
}
|
|
|
|
func cgSize() -> CGSize {
|
|
return CGSize(width: width, height: height)
|
|
}
|
|
|
|
func cgRect() -> CGRect {
|
|
return CGRect(origin: .zero, size: cgSize())
|
|
}
|
|
|
|
/// Calculates the correct tile size, taking into account the remainder between tile size and image size.
|
|
/// - Parameters:
|
|
/// - x: The X position of the tile.
|
|
/// - y: The Y position of the tile.
|
|
/// - Returns: A tuple containing the correct tile size.
|
|
func getTileSize(_ x: Int, _ y: Int) -> (Int, Int) {
|
|
var tileWidth: Int = tileSize
|
|
var tileHeight: Int = tileSize
|
|
|
|
if((x + 1) == columns) {
|
|
tileWidth -= remainderWidth
|
|
}
|
|
|
|
if(y == rows) {
|
|
tileHeight -= remainderHeight
|
|
}
|
|
|
|
return (tileWidth, tileHeight)
|
|
}
|
|
|
|
/// Calculates a `NSRect` for a `SilicaChunk`.
|
|
/// - Parameter chunk: The `SilicaChunk` to return a `NSRect` for.
|
|
/// - Returns: A `NSRect` containg the rectangle for the chunk.
|
|
func getChunkRect(_ chunk: SilicaChunk) -> NSRect {
|
|
let x = chunk.x
|
|
var y = chunk.y
|
|
|
|
let (tileWidth, tileHeight) = getTileSize(x, y)
|
|
|
|
if y == rows {
|
|
y = 0
|
|
}
|
|
|
|
return NSRect(x: tileSize * x,
|
|
y: height - (tileSize * y),
|
|
width: tileWidth,
|
|
height: tileHeight)
|
|
}
|
|
}
|