Skip to content

Commit

Permalink
Merged cli support
Browse files Browse the repository at this point in the history
  • Loading branch information
insidegui committed Aug 10, 2024
2 parents 40c0df2 + cbb9817 commit 53c95f9
Show file tree
Hide file tree
Showing 17 changed files with 769 additions and 167 deletions.
4 changes: 2 additions & 2 deletions ACS/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.7</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>270</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Guilherme Rambo. All rights reserved.</string>
<key>NSPrincipalClass</key>
Expand Down
4 changes: 2 additions & 2 deletions ACS/Source/AssetCatalogReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Copyright © 2016 Guilherme Rambo. All rights reserved.
//

@import Cocoa;
#import <Cocoa/Cocoa.h>

/// The name of the asset
extern NSString *__nonnull const kACSNameKey;
Expand All @@ -16,7 +16,7 @@ extern NSString *__nonnull const kACSImageKey;
extern NSString *__nonnull const kACSThumbnailKey;
/// An NSString with the suggested filename for the asset
extern NSString *__nonnull const kACSFilenameKey;
/// An NSData containing PNG image data for the asset
/// An NSData containing "image" data for the asset (PNG, SVG, etc)
extern NSString *__nonnull const kACSContentsDataKey;
/// An NSBitmapImageRep containing a bitmap representation of the asset
extern NSString *__nonnull const kACSImageRepKey;
Expand Down
155 changes: 77 additions & 78 deletions ACS/Source/AssetCatalogReader.m
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,14 @@ - (void)readWithCompletionHandler:(void (^__nonnull)(void))callback progressHand
if ([self catalogHasRetinaContent] && weakSelf.resourceConstrained && namedImage.scale < 2) {
continue;
}

NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:image];
imageRep.size = namedImage.size;

NSDictionary *desc = [self imageDescriptionWithName:namedImage.name filename:filename representation:imageRep contentsData:^NSData *{
return [imageRep representationUsingType:NSPNGFileType properties:@{NSImageInterlaced:@(NO)}];
return [imageRep representationUsingType:NSBitmapImageFileTypePNG properties:@{NSImageInterlaced:@(NO)}];
}];

if (!desc) {
loadedItemCount++;
return;
Expand Down Expand Up @@ -258,8 +259,10 @@ - (void)readThemeStoreWithCompletionHandler:(void (^__nonnull)(void))callback pr
if ([self catalogHasRetinaContent] && weakSelf.resourceConstrained && rendition.scale < 2) {
return;
}

const BOOL coreSVGPresent = CGSVGDocumentGetCanvasSize != NULL && CGContextDrawSVGDocument != NULL && CGSVGDocumentWriteToData != NULL;
const BOOL isSVG = coreSVGPresent && rendition.isVectorBased && rendition.svgDocument;

if (isSVG) {
NSCustomImageRep *imageRep = [[NSCustomImageRep alloc] initWithSize:CGSVGDocumentGetCanvasSize(rendition.svgDocument) flipped:YES drawingHandler:^BOOL(NSRect dstRect) {
CGContextRef context = NSGraphicsContext.currentContext.CGContext;
Expand All @@ -277,29 +280,28 @@ - (void)readThemeStoreWithCompletionHandler:(void (^__nonnull)(void))callback pr
if (self.cancelled) return;
[self.mutableImages addObject:desc];
} else if (rendition.unslicedImage) {
NSString *const filename = [self filenameForAssetNamed:[self cleanupRenditionName:rendition.name] scale:rendition.scale presentationState:key.themeState];
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:rendition.unslicedImage];
imageRep.size = NSMakeSize(CGImageGetWidth(rendition.unslicedImage), CGImageGetHeight(rendition.unslicedImage));


NSString *const filename = [self filenameForAssetNamed:[self cleanupRenditionName:rendition.name] scale:rendition.scale presentationState:key.themeState];
NSDictionary *desc = [self imageDescriptionWithName:rendition.name filename:filename representation:imageRep contentsData:^NSData *{
return [imageRep representationUsingType:NSPNGFileType properties:@{NSImageInterlaced:@(NO)}];
return [imageRep representationUsingType:NSBitmapImageFileTypePNG properties:@{NSImageInterlaced:@(NO)}];
}];

BOOL ignore = [filename containsString:@"ZZPackedAsset"] && self.ignorePackedAssets;

if (!desc || ignore) {
loadedItemCount++;
return;
}

if (self.cancelled) return;

[self.mutableImages addObject:desc];
} else {
NSLog(@"The rendition %@ doesn't have an image, It is probably an effect or material.", rendition.name);
}

loadedItemCount++;
} @catch (NSException *exception) {
NSLog(@"Exception while reading theme store: %@", exception);
Expand Down Expand Up @@ -330,12 +332,10 @@ - (NSImage *)constrainImage:(NSImage *)image toSize:(NSSize)size
newHeight = size.height;
}

NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(newWidth, newHeight)];
[newImage lockFocus];
[image drawInRect:NSMakeRect(0, 0, newWidth, newHeight) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0];
[newImage unlockFocus];

return newImage;
return [NSImage imageWithSize:NSMakeSize(newWidth, newHeight) flipped:NO drawingHandler:^BOOL(NSRect dstRect) {
[image drawInRect:NSMakeRect(0, 0, newWidth, newHeight) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0];
return YES;
}];
}

- (BOOL)isProThemeStoreAtPath:(NSString *)path
Expand Down Expand Up @@ -382,7 +382,6 @@ - (NSDictionary *)imageDescriptionWithName:(NSString *)name filename:(NSString *
};
} else {
NSData *pngData = contentsData();

if (!pngData.length) {
NSLog(@"Unable to get PNG data from rendition named %@", name);
return nil;
Expand Down Expand Up @@ -428,71 +427,71 @@ - (NSString *)filenameForAssetNamed:(NSString *)name scale:(CGFloat)scale presen
- (NSString *)filenameForVectorAssetNamed:(NSString *)name renderingMode:(UIImageSymbolRenderingMode)renderingMode weight:(UIImageSymbolWeight)weight size:(UIImageSymbolScale)size {
NSString *weightName;
switch (weight) {
case UIImageSymbolWeightUnspecified:
weightName = @"unspecified";
break;
case UIImageSymbolWeightUltraLight:
weightName = @"ultraLight";
break;
case UIImageSymbolWeightThin:
weightName = @"thin";
break;
case UIImageSymbolWeightLight:
weightName = @"light";
break;
case UIImageSymbolWeightRegular:
weightName = @"regular";
break;
case UIImageSymbolWeightMedium:
weightName = @"medium";
break;
case UIImageSymbolWeightSemibold:
weightName = @"semibold";
break;
case UIImageSymbolWeightBold:
weightName = @"bold";
break;
case UIImageSymbolWeightHeavy:
weightName = @"heavy";
break;
case UIImageSymbolWeightBlack:
weightName = @"black";
break;
case UIImageSymbolWeightUnspecified:
weightName = @"unspecified";
break;
case UIImageSymbolWeightUltraLight:
weightName = @"ultraLight";
break;
case UIImageSymbolWeightThin:
weightName = @"thin";
break;
case UIImageSymbolWeightLight:
weightName = @"light";
break;
case UIImageSymbolWeightRegular:
weightName = @"regular";
break;
case UIImageSymbolWeightMedium:
weightName = @"medium";
break;
case UIImageSymbolWeightSemibold:
weightName = @"semibold";
break;
case UIImageSymbolWeightBold:
weightName = @"bold";
break;
case UIImageSymbolWeightHeavy:
weightName = @"heavy";
break;
case UIImageSymbolWeightBlack:
weightName = @"black";
break;
}

NSString *sizeName;
switch (size) {
case UIImageSymbolScaleDefault:
sizeName = @"default";
break;
case UIImageSymbolScaleUnspecified:
sizeName = @"unspecified";
break;
case UIImageSymbolScaleSmall:
sizeName = @"small";
break;
case UIImageSymbolScaleMedium:
sizeName = @"medium";
break;
case UIImageSymbolScaleLarge:
sizeName = @"large";
break;
case UIImageSymbolScaleDefault:
sizeName = @"default";
break;
case UIImageSymbolScaleUnspecified:
sizeName = @"unspecified";
break;
case UIImageSymbolScaleSmall:
sizeName = @"small";
break;
case UIImageSymbolScaleMedium:
sizeName = @"medium";
break;
case UIImageSymbolScaleLarge:
sizeName = @"large";
break;
}

NSString *renderingModeName;
switch (renderingMode) {
case UIImageSymbolRenderingModeAutomatic:
renderingModeName = @"automatic";
break;
case UIImageSymbolRenderingModeTemplate:
renderingModeName = @"template";
break;
case UIImageSymbolRenderingModeMulticolor:
renderingModeName = @"multicolor";
break;
case UIImageSymbolRenderingModeHierarchical:
renderingModeName = @"hierarchical";
break;
case UIImageSymbolRenderingModeAutomatic:
renderingModeName = @"automatic";
break;
case UIImageSymbolRenderingModeTemplate:
renderingModeName = @"template";
break;
case UIImageSymbolRenderingModeMulticolor:
renderingModeName = @"multicolor";
break;
case UIImageSymbolRenderingModeHierarchical:
renderingModeName = @"hierarchical";
break;
}
return [NSString stringWithFormat:@"%@_%@_%@_%@.svg", name, weightName, sizeName, renderingModeName];
}
Expand Down
61 changes: 61 additions & 0 deletions ACS/Source/ImageExporter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Cocoa

public struct ImageExporter {
public let images: [[String: NSObject]]

public init(images: [[String : NSObject]]) {
self.images = images
}

@available(macOS 10.15, *)
public func export(toDirectoryAt url: URL) async {
await withCheckedContinuation { continuation in
export(toDirectoryAt: url) {
continuation.resume()
}
}
}

public func export(toDirectoryAt url: URL, completionHandler: (() -> Void)? = nil) {
DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {
images.forEach { image in
guard let filename = image[kACSFilenameKey] as? String else { return }

var pathComponents = url.pathComponents

pathComponents.append(filename)

guard let pngData = image[kACSContentsDataKey] as? Data else { return }

let path = self.nextAvailablePath(filePath: NSString.path(withComponents: pathComponents) as String)
do {
try pngData.write(to: URL(fileURLWithPath: path), options: .atomic)
} catch {
NSLog("ERROR: Unable to write \(filename) to \(path); \(error)")
}
}

DispatchQueue.main.async {
completionHandler?()
}
}
}

private func nextAvailablePath(filePath: String) -> String {
let fileManager = FileManager.default
let originalURL = URL(fileURLWithPath: filePath)
let directory = originalURL.deletingLastPathComponent()
let baseFilename = originalURL.deletingPathExtension().lastPathComponent
let fileExtension = originalURL.pathExtension

var counter = 1
var newFilename = baseFilename

while fileManager.fileExists(atPath: directory.appendingPathComponent(newFilename).appendingPathExtension(fileExtension).path) && counter < 100 {
newFilename = "\(baseFilename)_\(counter)"
counter += 1
}

return directory.appendingPathComponent(newFilename).appendingPathExtension(fileExtension).path
}
}
Loading

0 comments on commit 53c95f9

Please sign in to comment.