@@ -50,6 +50,14 @@ typealias objectiveCMethodImp = @convention(c) (AnyObject, Selector, UnsafeRawPo
5050 AnyObject
5151> ?
5252
53+ private struct MultisizeSetInfo {
54+ let name : String
55+ let element : UInt
56+ let part : UInt
57+ let identifier : UInt
58+ let sizeIndexes : [ ( idiom: UInt , subtype: UInt ) ]
59+ }
60+
5361enum AssetUtil {
5462 private static func idiomToString( _ idiom: UInt ? ) -> String ? {
5563 guard let idiom = idiom else { return nil }
@@ -105,15 +113,62 @@ enum AssetUtil {
105113 let ( structuredThemeStore, assetKeys) = initializeCatalog ( from: file)
106114
107115 var images : [ String : ( cgImage: CGImage , format: String ) ] = [ : ]
108-
109- for key in assetKeys {
116+
117+ // First pass: Build map of multisize sets and cache renditions for performance
118+ var multisizeSets : [ MultisizeSetInfo ] = [ ]
119+ var renditionCache : [ Int : NSObject ] = [ : ]
120+
121+ for (index, key) in assetKeys. enumerated ( ) {
110122 let keyList = unsafeBitCast (
111123 key. perform ( Selector ( ( " keyList " ) ) ) ,
112124 to: UnsafeMutableRawPointer . self
113125 )
114126 guard let rendition = createRendition ( from: structuredThemeStore, keyList) else {
115127 continue
116128 }
129+ renditionCache [ index] = rendition
130+
131+ let type = rendition. getUInt ( forKey: " type " ) ?? 0
132+ if type == 1010 { // Multisize image set
133+ let renditionTypeName = rendition. perform ( Selector ( ( " name " ) ) ) . takeUnretainedValue ( ) as! String
134+ let keyElement = key. getUInt ( forKey: " themeElement " ) ?? 0
135+ let keyPart = key. getUInt ( forKey: " themePart " ) ?? 0
136+ let keyIdentifier = key. getUInt ( forKey: " themeIdentifier " ) ?? 0
137+
138+ // Extract size indexes to identify which images belong to this set
139+ var sizeIndexes : [ ( idiom: UInt , subtype: UInt ) ] = [ ]
140+ if rendition. responds ( to: Selector ( ( " sizeIndexes " ) ) ) ,
141+ let sizeIndexesResult = rendition. perform ( Selector ( ( " sizeIndexes " ) ) ) ,
142+ let sizeIndexesArray = sizeIndexesResult. takeUnretainedValue ( ) as? NSArray {
143+ for sizeIndexObj in sizeIndexesArray {
144+ if let obj = sizeIndexObj as? NSObject {
145+ let idiom = obj. getUInt ( forKey: " idiom " ) ?? 0
146+ let subtype = obj. getUInt ( forKey: " subtype " ) ?? 0
147+ sizeIndexes. append ( ( idiom: idiom, subtype: subtype) )
148+ }
149+ }
150+ }
151+
152+ multisizeSets. append ( MultisizeSetInfo (
153+ name: renditionTypeName,
154+ element: keyElement,
155+ part: keyPart,
156+ identifier: keyIdentifier,
157+ sizeIndexes: sizeIndexes
158+ ) )
159+ }
160+ }
161+
162+ // Second pass: Process all assets using cached renditions
163+ for (index, key) in assetKeys. enumerated ( ) {
164+ guard let rendition = renditionCache [ index] else {
165+ continue
166+ }
167+
168+ let keyList = unsafeBitCast (
169+ key. perform ( Selector ( ( " keyList " ) ) ) ,
170+ to: UnsafeMutableRawPointer . self
171+ )
117172
118173 let data = rendition. value ( forKey: " _srcData " ) as! Data
119174 let length = UInt ( data. count)
@@ -163,13 +218,7 @@ enum AssetUtil {
163218 var unslicedImage : CGImage ?
164219
165220 if isMultisizeImageSet {
166- // Look up the actual image rendition from the multisize set
167- if let result = findImageForMultisizeSet ( rendition, key, assetKeys, structuredThemeStore) {
168- unslicedImage = result. image
169- width = result. width
170- height = result. height
171- images [ imageId] = ( cgImage: unslicedImage!, format: " png " )
172- }
221+ continue
173222 } else {
174223 // Get image dimensions from regular rendition
175224 ( width, height, unslicedImage) = resolveImageDimensions ( rendition, isVector)
@@ -183,11 +232,19 @@ enum AssetUtil {
183232
184233 let idiomValue = key. getUInt ( forKey: " themeIdiom " )
185234 let colorSpaceID = rendition. getUInt ( forKey: " colorSpaceID " )
235+
236+ // Include multisize set name in the name field if it exists
237+ let finalName : String
238+ if let setName = findMultisizeSetName ( key, in: multisizeSets) {
239+ finalName = " \( setName) / \( name) "
240+ } else {
241+ finalName = name
242+ }
186243
187244 let asset = AssetCatalogEntry (
188245 imageId: imageId,
189246 size: length,
190- name: name ,
247+ name: finalName ,
191248 vector: isVector,
192249 width: width,
193250 height: height,
@@ -293,65 +350,6 @@ enum AssetUtil {
293350 }
294351 return true
295352 }
296-
297- private static func findImageForMultisizeSet(
298- _ rendition: NSObject ,
299- _ key: NSObject ,
300- _ assetKeys: [ NSObject ] ,
301- _ structuredThemeStore: NSObject
302- ) -> ( image: CGImage , width: Int , height: Int ) ? {
303- // Get the sizeIndexes to find the actual image
304- guard rendition. responds ( to: Selector ( ( " sizeIndexes " ) ) ) ,
305- let sizeIndexesResult = rendition. perform ( Selector ( ( " sizeIndexes " ) ) ) ,
306- let sizeIndexesArray = sizeIndexesResult. takeUnretainedValue ( ) as? NSArray ,
307- sizeIndexesArray. count > 0 else {
308- return nil
309- }
310-
311- // Get the first size index
312- let sizeIndexObj = sizeIndexesArray. object ( at: 0 ) as! NSObject
313-
314- // Get the idiom and subtype from the size index
315- let idiom = sizeIndexObj. getUInt ( forKey: " idiom " ) ?? 0
316- let subtype = sizeIndexObj. getUInt ( forKey: " subtype " ) ?? 0
317- let keyElement = key. getUInt ( forKey: " themeElement " ) ?? 0
318-
319- // Look for a rendition with matching idiom and subtype in the asset keys
320- for otherKey in assetKeys {
321- let otherKeyIdiom = otherKey. getUInt ( forKey: " themeIdiom " ) ?? 0
322- let otherKeySubtype = otherKey. getUInt ( forKey: " themeSubtype " ) ?? 0
323- let otherKeyElement = otherKey. getUInt ( forKey: " themeElement " ) ?? 0
324-
325- // Find a key with matching element, idiom, and subtype
326- guard otherKeyElement == keyElement,
327- otherKeyIdiom == idiom,
328- otherKeySubtype == subtype else {
329- continue
330- }
331-
332- let otherKeyList = unsafeBitCast (
333- otherKey. perform ( Selector ( ( " keyList " ) ) ) ,
334- to: UnsafeMutableRawPointer . self
335- )
336-
337- guard let imageRendition = createRendition ( from: structuredThemeStore, otherKeyList) else {
338- continue
339- }
340-
341- let renditionType = imageRendition. getUInt ( forKey: " type " ) ?? 0
342-
343- // Skip if this is another multisize set (type 1010)
344- guard renditionType != 1010 ,
345- let result = imageRendition. perform ( Selector ( ( " unslicedImage " ) ) ) else {
346- continue
347- }
348-
349- let image = result. takeUnretainedValue ( ) as! CGImage
350- return ( image, image. width, image. height)
351- }
352-
353- return nil
354- }
355353
356354 private static func determineAssetType( _ key: NSObject ) -> AssetType {
357355 let themeElement = key. getUInt ( forKey: " themeElement " ) ?? 0
@@ -364,6 +362,30 @@ enum AssetUtil {
364362 }
365363 return . image
366364 }
365+
366+ private static func findMultisizeSetName(
367+ _ key: NSObject ,
368+ in multisizeSets: [ MultisizeSetInfo ]
369+ ) -> String ? {
370+ let element = key. getUInt ( forKey: " themeElement " ) ?? 0
371+ let identifier = key. getUInt ( forKey: " themeIdentifier " ) ?? 0
372+ let idiom = key. getUInt ( forKey: " themeIdiom " ) ?? 0
373+ let subtype = key. getUInt ( forKey: " themeSubtype " ) ?? 0
374+
375+ for setInfo in multisizeSets {
376+ guard setInfo. element == element,
377+ setInfo. identifier == identifier else {
378+ continue
379+ }
380+
381+ for sizeIndex in setInfo. sizeIndexes {
382+ if sizeIndex. idiom == idiom && sizeIndex. subtype == subtype {
383+ return setInfo. name
384+ }
385+ }
386+ }
387+ return nil
388+ }
367389
368390 private static func resolveRenditionName(
369391 _ structuredThemeStore: NSObject ,
0 commit comments