1
Fork 0

Overhaul blend mode handling

Now we decode a much nicer enum, instead of manually parsing
ints on both the PSD and rendering side
This commit is contained in:
Joshua Goins 2022-06-14 11:17:58 -04:00
parent 590c16da52
commit 981604d68d
2 changed files with 140 additions and 158 deletions

View file

@ -47,89 +47,60 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations {
}
func getPSDBlendMode(_ layer : SilicaLayer) -> PSDBlendModes {
if layer.data.blendMode == 1 {
switch(layer.data.blendMode) {
case .Normal:
return kPSDBlendModeNormal
case .Multiply:
return kPSDBlendModeMultiply
}
if layer.data.blendMode == 10 {
return kPSDBlendModeColorBurn
}
if layer.data.blendMode == 19 {
return kPSDBlendModeDarken
}
if layer.data.blendMode == 8 {
return kPSDBlendModeLinearBurn
}
if layer.data.blendMode == 4 {
return kPSDBlendModeLighten
}
if layer.data.blendMode == 2 {
case .Screen:
return kPSDBlendModeScreen
}
if layer.data.blendMode == 13 {
return kPSDBlendModeColor
}
if layer.data.blendMode == 9 {
return kPSDBlendModeColorDodge
}
if layer.data.blendMode == 3 {
case .Add:
return kPSDBlendModeAdd
}
if layer.data.blendMode == 0 && layer.data.blendMode != layer.data.extendedBlend {
if layer.data.extendedBlend == 25 {
return kPSDBlendModeDarkerColor
}
if layer.data.extendedBlend == 24 {
return kPSDBlendModeLighterColor
}
if layer.data.extendedBlend == 21 {
return kPSDBlendModeVividLight
}
if layer.data.extendedBlend == 22 {
return kPSdBlendModeLinearLight
}
if layer.data.extendedBlend == 23 {
return kPSDBlendModePinLight
}
if layer.data.extendedBlend == 20 {
return kPSDBlendModeHardMix
}
if layer.data.extendedBlend == 26 {
return kPSDBlendModeDivide
}
}
if layer.data.blendMode == 11 {
return kPSDBlendModeOverlay
}
if layer.data.blendMode == 17 {
return kPSDBlendSoftLight
}
if layer.data.blendMode == 12 {
return kPSDBlendModeHardLight
}
if layer.data.blendMode == 6 {
return kPSDBlendModeDifference
}
if layer.data.blendMode == 5 {
case .Lighten:
return kPSDBlendModeLighten
case .Exclusion:
return kPSDBlendModeExclusion
}
if layer.data.blendMode == 7 {
case .Difference:
return kPSDBlendModeDifference
case .Subtract:
return kPSDBlendModeSubtract
}
if layer.data.blendMode == 15 {
return kPSDBlendModeHue
}
if layer.data.blendMode == 16 {
return kPSDBlendModeSaturation
}
if layer.data.blendMode == 13 {
case .LinearBurn:
return kPSDBlendModeLinearBurn
case .ColorDodge:
return kPSDBlendModeColorDodge
case .ColorBurn:
return kPSDBlendModeColorBurn
case .Overlay:
return kPSDBlendModeOverlay
case .HardLight:
return kPSDBlendModeHardLight
case .Color:
return kPSDBlendModeColor
}
if layer.data.blendMode == 14 {
case .Luminosity:
return kPSDBlendModeLuminosity
case .Hue:
return kPSDBlendModeHue
case .Saturation:
return kPSDBlendModeSaturation
case .SoftLight:
return kPSDBlendSoftLight
case .Darken:
return kPSDBlendModeDarken
case .HardMix:
return kPSDBlendModeHardMix
case .VividLight:
return kPSDBlendModeVividLight
case .LinearLight:
return kPSdBlendModeLinearLight
case .PinLight:
return kPSDBlendModePinLight
case .LighterColor:
return kPSDBlendModeLighterColor
case .DarkerColor:
return kPSDBlendModeDarkerColor
case .Divide:
return kPSDBlendModeDivide
}
return kPSDBlendModeNormal
}
@IBAction func exportAction(_ sender: Any) {
@ -178,9 +149,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations {
if(layer.mask != nil) {
writer?.addLayer(with: document!.makeBlendImage(layer), andName: layer.name + " (Mask)", andOpacity: 1.0, andOffset: .zero)
writer?.addLayer(with: finalCgImage, andName: layer.name, andOpacity: Float(layer.data.opacity), andOffset: .zero, andBlendMode: Int(self.getPSDBlendMode(layer).rawValue), andIsNonBaseLayer: layer.clipped, andMaskLayerName: layer.name + " (Mask)")
} else {
writer?.addLayer(with: finalCgImage, andName: layer.name, andOpacity: Float(layer.data.opacity), andOffset: .zero, andBlendMode: Int(self.getPSDBlendMode(layer).rawValue), andIsNonBaseLayer: layer.clipped, andMaskLayerName: nil)
}
writer?.addLayer(with: finalCgImage, andName: layer.name, andOpacity: Float(layer.data.opacity), andOffset: .zero, andBlendMode: Int(self.getPSDBlendMode(layer).rawValue), andIsNonBaseLayer: layer.clipped)
}
let data = writer?.createPSDData()

View file

@ -10,9 +10,41 @@ struct SilicaChunk {
var image: CGImage?
}
// all supported Procreate 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,
// what is this mysterious 18?
Darken = 19,
// extended modes
HardMix = 20,
VividLight = 21,
LinearLight = 22,
PinLight = 23,
LighterColor = 24,
DarkerColor = 25,
Divide = 26
}
struct SilicaLayerData {
var blendMode: Int = 0
var extendedBlend: Int = 0
var blendMode: BlendMode = .Normal
var chunks: [SilicaChunk] = []
var opacity: Double = 1.0
var hidden: Bool = false
@ -193,92 +225,69 @@ class Document: NSDocument {
return NSRect(x: info.tileSize * x, y: info.height - (info.tileSize * y), width: width, height: height)
}
// TODO: convert to switch/case
func parseRawBlendMode(blendMode: Int, extendedBlend: Int) -> BlendMode? {
if blendMode == 0 && blendMode != extendedBlend {
return BlendMode(rawValue: extendedBlend)
} else {
return BlendMode(rawValue: blendMode)
}
}
func getBlendKernel(_ layer: SilicaLayer) -> CIBlendKernel? {
if layer.data.blendMode == 1 {
switch(layer.data.blendMode) {
case .Normal:
return .sourceOver
case .Multiply:
return .multiply
}
if layer.data.blendMode == 10 {
return .colorBurn
}
if layer.data.blendMode == 19 {
return .darken
}
if layer.data.blendMode == 8 {
return .linearBurn
}
if layer.data.blendMode == 4 {
return .lighten
}
if layer.data.blendMode == 2 {
case .Screen:
return .screen
}
if layer.data.blendMode == 13 {
return .color
}
if layer.data.blendMode == 9 {
return .colorDodge
}
if layer.data.blendMode == 3 {
case .Add:
return .componentAdd
}
if layer.data.blendMode == 0 && layer.data.blendMode != layer.data.extendedBlend {
if layer.data.extendedBlend == 25 {
return .darkerColor
}
if layer.data.extendedBlend == 24 {
return .lighterColor
}
if layer.data.extendedBlend == 21 {
return .vividLight
}
if layer.data.extendedBlend == 22 {
return .linearLight
}
if layer.data.extendedBlend == 23 {
return .pinLight
}
if layer.data.extendedBlend == 20 {
return .hardMix
}
if layer.data.extendedBlend == 26 {
return .divide
}
}
if layer.data.blendMode == 11 {
return .overlay
}
if layer.data.blendMode == 17 {
return .softLight
}
if layer.data.blendMode == 12 {
return .hardLight
}
if layer.data.blendMode == 6 {
return .difference
}
if layer.data.blendMode == 5 {
case .Lighten:
return .lighten
case .Exclusion:
return .exclusion
}
if layer.data.blendMode == 7 {
case .Difference:
return .difference
case .Subtract:
return .subtract
}
if layer.data.blendMode == 15 {
return .hue
}
if layer.data.blendMode == 16 {
return .saturation
}
if layer.data.blendMode == 13 {
case .LinearBurn:
return .linearBurn
case .ColorDodge:
return .colorDodge
case .ColorBurn:
return .colorBurn
case .Overlay:
return .overlay
case .HardLight:
return .hardLight
case .Color:
return .color
}
if layer.data.blendMode == 14 {
case .Luminosity:
return .luminosity
case .Hue:
return .hue
case .Saturation:
return .saturation
case .SoftLight:
return .softLight
case .Darken:
return .darken
case .HardMix:
return .hardMix
case .VividLight:
return .vividLight
case .LinearLight:
return .linearLight
case .PinLight:
return .pinLight
case .LighterColor:
return .lighterColor
case .DarkerColor:
return .darkerColor
case .Divide:
return .divide
}
return .sourceOver
}
func parseSilicaLayer(archive: Archive, dict: NSDictionary, isMask: Bool) -> SilicaLayer? {
@ -302,8 +311,8 @@ class Document: NSDocument {
let maskClassID = getClassID(id: maskKey)
let maskClass = objectsArray[maskClassID]
layer.data.blendMode = (dict["blend"] as? NSNumber)!.intValue
layer.data.extendedBlend = (dict["extendedBlend"] as? NSNumber)!.intValue
layer.data.blendMode = parseRawBlendMode(blendMode: (dict["blend"] as? NSNumber)!.intValue, extendedBlend: (dict["extendedBlend"] as? NSNumber)!.intValue)!
layer.data.opacity = (dict["opacity"] as? NSNumber)!.doubleValue
layer.data.hidden = (dict["hidden"] as? Bool)!
layer.clipped = (dict["clipped"] as? Bool)!