mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Autoscale builtin pattern thumbnail
This commit is contained in:
parent
dad3eca855
commit
01c5299c00
@ -121,22 +121,28 @@ public final class CachedPatternWallpaperMaskRepresentation: CachedMediaResource
|
|||||||
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
|
public let keepDuration: CachedMediaRepresentationKeepDuration = .general
|
||||||
|
|
||||||
public let size: CGSize?
|
public let size: CGSize?
|
||||||
|
public let scaleFromCenter: CGFloat?
|
||||||
|
|
||||||
public var uniqueId: String {
|
public var uniqueId: String {
|
||||||
if let size = self.size {
|
if let size = self.size {
|
||||||
return "pattern-wallpaper-mask-\(Int(size.width))x\(Int(size.height))"
|
var result = "pattern-wallpaper-mask-\(Int(size.width))x\(Int(size.height))"
|
||||||
|
if let scaleFromCenter = self.scaleFromCenter {
|
||||||
|
result.append("-scale\(scaleFromCenter)")
|
||||||
|
}
|
||||||
|
return result
|
||||||
} else {
|
} else {
|
||||||
return "pattern-wallpaper-mask"
|
return "pattern-wallpaper-mask"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(size: CGSize?) {
|
public init(size: CGSize?, scaleFromCenter: CGFloat?) {
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.scaleFromCenter = scaleFromCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
|
public func isEqual(to: CachedMediaResourceRepresentation) -> Bool {
|
||||||
if let to = to as? CachedPatternWallpaperMaskRepresentation {
|
if let to = to as? CachedPatternWallpaperMaskRepresentation {
|
||||||
return self.size == to.size
|
return self.size == to.size && self.scaleFromCenter == to.scaleFromCenter
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -411,6 +411,10 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if !entries.isEmpty {
|
||||||
|
entries = [entries[0]]
|
||||||
|
}*/
|
||||||
|
|
||||||
let previous = previousEntries.swap(entries)
|
let previous = previousEntries.swap(entries)
|
||||||
return (preparedThemeGridEntryTransition(context: context, from: previous ?? [], to: entries, interaction: interaction), previous == nil)
|
return (preparedThemeGridEntryTransition(context: context, from: previous ?? [], to: entries, interaction: interaction), previous == nil)
|
||||||
|
@ -851,7 +851,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
let dimensions = file.file.dimensions ?? PixelDimensions(width: 1440, height: 2960)
|
let dimensions = file.file.dimensions ?? PixelDimensions(width: 1440, height: 2960)
|
||||||
|
|
||||||
let size = dimensions.cgSize.fitted(CGSize(width: 1280.0, height: 1280.0))
|
let size = dimensions.cgSize.fitted(CGSize(width: 1280.0, height: 1280.0))
|
||||||
let _ = self.context.account.postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
|
let _ = self.context.account.postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: nil), complete: false, fetch: true).start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor);
|
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor, CGFloat scaleFromCenter);
|
||||||
|
|
||||||
#endif /* Lottie_h */
|
#endif /* Lottie_h */
|
||||||
|
@ -83,7 +83,7 @@ CGSize aspectFillSize(CGSize size, CGSize bounds) {
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor) {
|
UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *backgroundColor, UIColor *foregroundColor, CGFloat scaleFromCenter) {
|
||||||
NSDate *startTime = [NSDate date];
|
NSDate *startTime = [NSDate date];
|
||||||
|
|
||||||
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
|
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
|
||||||
@ -104,9 +104,9 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
|
|||||||
[xmlString replaceOccurrencesOfString:[NSString stringWithFormat:@"class=\"%@\"", styleName] withString:[NSString stringWithFormat:@"style=\"%@\"", styleValue] options:0 range:NSMakeRange(0, xmlString.length)];
|
[xmlString replaceOccurrencesOfString:[NSString stringWithFormat:@"class=\"%@\"", styleName] withString:[NSString stringWithFormat:@"style=\"%@\"", styleValue] options:0 range:NSMakeRange(0, xmlString.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
char *zeroTerminatedData = xmlString.UTF8String;
|
const char *zeroTerminatedData = xmlString.UTF8String;
|
||||||
|
|
||||||
NSVGimage *image = nsvgParse(zeroTerminatedData, "px", 96);
|
NSVGimage *image = nsvgParse((char *)zeroTerminatedData, "px", 96);
|
||||||
if (image == nil || image->width < 1.0f || image->height < 1.0f) {
|
if (image == nil || image->width < 1.0f || image->height < 1.0f) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@ -128,6 +128,10 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
|
|||||||
|
|
||||||
CGContextScaleCTM(context, scale, scale);
|
CGContextScaleCTM(context, scale, scale);
|
||||||
CGContextTranslateCTM(context, (size.width - drawingSize.width) / 2.0, (size.height - drawingSize.height) / 2.0);
|
CGContextTranslateCTM(context, (size.width - drawingSize.width) / 2.0, (size.height - drawingSize.height) / 2.0);
|
||||||
|
|
||||||
|
CGContextTranslateCTM(context, size.width / 2.0f, size.height / 2.0f);
|
||||||
|
CGContextScaleCTM(context, scaleFromCenter, scaleFromCenter);
|
||||||
|
CGContextTranslateCTM(context, -size.width / 2.0f, -size.height / 2.0f);
|
||||||
|
|
||||||
for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
|
for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
|
||||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) {
|
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) {
|
||||||
@ -135,7 +139,6 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shape->fill.type != NSVG_PAINT_NONE) {
|
if (shape->fill.type != NSVG_PAINT_NONE) {
|
||||||
//CGContextSetFillColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor);
|
|
||||||
CGContextSetFillColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
|
CGContextSetFillColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
|
||||||
|
|
||||||
bool isFirst = true;
|
bool isFirst = true;
|
||||||
@ -173,7 +176,6 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shape->stroke.type != NSVG_PAINT_NONE) {
|
if (shape->stroke.type != NSVG_PAINT_NONE) {
|
||||||
//CGContextSetStrokeColorWithColor(context, UIColorRGBA(shape->fill.color, shape->opacity).CGColor);
|
|
||||||
CGContextSetStrokeColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
|
CGContextSetStrokeColorWithColor(context, [foregroundColor colorWithAlphaComponent:shape->opacity].CGColor);
|
||||||
CGContextSetMiterLimit(context, shape->miterLimit);
|
CGContextSetMiterLimit(context, shape->miterLimit);
|
||||||
|
|
||||||
@ -196,10 +198,10 @@ UIImage * _Nullable drawSvgImage(NSData * _Nonnull data, CGSize size, UIColor *b
|
|||||||
CGContextSetLineJoin(context, kCGLineJoinBevel);
|
CGContextSetLineJoin(context, kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
case NSVG_JOIN_MITER:
|
case NSVG_JOIN_MITER:
|
||||||
CGContextSetLineCap(context, kCGLineJoinMiter);
|
CGContextSetLineJoin(context, kCGLineJoinMiter);
|
||||||
break;
|
break;
|
||||||
case NSVG_JOIN_ROUND:
|
case NSVG_JOIN_ROUND:
|
||||||
CGContextSetLineCap(context, kCGLineJoinRound);
|
CGContextSetLineJoin(context, kCGLineJoinRound);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -424,7 +424,7 @@ private func fetchCachedPatternWallpaperMaskRepresentation(resource: MediaResour
|
|||||||
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
|
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
|
||||||
let size = representation.size ?? CGSize(width: 1440.0, height: 2960.0)
|
let size = representation.size ?? CGSize(width: 1440.0, height: 2960.0)
|
||||||
|
|
||||||
if let image = drawSvgImage(data, size, .black, .white) {
|
if let image = drawSvgImage(data, size, .black, .white, representation.scaleFromCenter ?? 1.0) {
|
||||||
if let alphaDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
if let alphaDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
||||||
CGImageDestinationSetProperties(alphaDestination, [:] as CFDictionary)
|
CGImageDestinationSetProperties(alphaDestination, [:] as CFDictionary)
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ private func fetchCachedPatternWallpaperRepresentation(resource: MediaResource,
|
|||||||
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
|
if data.count > 5, let string = String(data: data.subdata(in: 0 ..< 5), encoding: .utf8), string == "<?xml" {
|
||||||
let defaultSize = CGSize(width: 1440.0, height: 2960.0)
|
let defaultSize = CGSize(width: 1440.0, height: 2960.0)
|
||||||
size = defaultSize
|
size = defaultSize
|
||||||
if let image = drawSvgImage(data, defaultSize, .black, .white) {
|
if let image = drawSvgImage(data, defaultSize, .black, .white, 1.0) {
|
||||||
maskImage = image
|
maskImage = image
|
||||||
}
|
}
|
||||||
} else if let image = UIImage(data: data) {
|
} else if let image = UIImage(data: data) {
|
||||||
|
@ -362,13 +362,18 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
|
|||||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||||
|
|
||||||
let size: CGSize?
|
let size: CGSize?
|
||||||
|
var scaleFromCenter: CGFloat?
|
||||||
switch mode {
|
switch mode {
|
||||||
case .thumbnail:
|
case .thumbnail:
|
||||||
size = largestRepresentation.dimensions.cgSize.fitted(CGSize(width: 640.0, height: 640.0))
|
size = largestRepresentation.dimensions.cgSize.fitted(CGSize(width: 640.0, height: 640.0))
|
||||||
|
let factor = smallestRepresentation.dimensions.cgSize.width / largestRepresentation.dimensions.cgSize.width
|
||||||
|
if smallestRepresentation.dimensions.height >= 700 && abs(factor - 1.0) <= .ulpOfOne {
|
||||||
|
scaleFromCenter = 2.1
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
size = nil
|
size = nil
|
||||||
}
|
}
|
||||||
let maybeFullSize = combineLatest(accountManager.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: false), account.postbox.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: false))
|
let maybeFullSize = combineLatest(accountManager.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: false), account.postbox.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: false))
|
||||||
|
|
||||||
let signal = maybeFullSize
|
let signal = maybeFullSize
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -388,12 +393,12 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
|
|||||||
|
|
||||||
let thumbnailData = Signal<Data?, NoError> { subscriber in
|
let thumbnailData = Signal<Data?, NoError> { subscriber in
|
||||||
let fetchedDisposable = fetchedThumbnail.start()
|
let fetchedDisposable = fetchedThumbnail.start()
|
||||||
let thumbnailDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start(next: { next in
|
let thumbnailDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start(next: { next in
|
||||||
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
|
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
|
||||||
|
|
||||||
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
|
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
|
||||||
accountManager.mediaBox.storeResourceData(representations[smallestIndex].representation.resource.id, data: data)
|
accountManager.mediaBox.storeResourceData(representations[smallestIndex].representation.resource.id, data: data)
|
||||||
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
|
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[smallestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start()
|
||||||
}
|
}
|
||||||
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
|
||||||
@ -405,12 +410,12 @@ private func patternWallpaperDatas(account: Account, accountManager: AccountMana
|
|||||||
|
|
||||||
let fullSizeData = Signal<(Data?, Bool), NoError> { subscriber in
|
let fullSizeData = Signal<(Data?, Bool), NoError> { subscriber in
|
||||||
let fetchedFullSizeDisposable = fetchedFullSize.start()
|
let fetchedFullSizeDisposable = fetchedFullSize.start()
|
||||||
let fullSizeDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start(next: { next in
|
let fullSizeDisposable = account.postbox.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start(next: { next in
|
||||||
subscriber.putNext((next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete))
|
subscriber.putNext((next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete))
|
||||||
|
|
||||||
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
|
if next.complete, let data = try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedRead) {
|
||||||
accountManager.mediaBox.storeResourceData(representations[largestIndex].representation.resource.id, data: data)
|
accountManager.mediaBox.storeResourceData(representations[largestIndex].representation.resource.id, data: data)
|
||||||
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size), complete: false, fetch: true).start()
|
let _ = accountManager.mediaBox.cachedResourceRepresentation(representations[largestIndex].representation.resource, representation: CachedPatternWallpaperMaskRepresentation(size: size, scaleFromCenter: scaleFromCenter), complete: false, fetch: true).start()
|
||||||
}
|
}
|
||||||
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
|
||||||
@ -535,6 +540,7 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
|
|||||||
let overlayImage = generateImage(arguments.drawingRect.size, rotatedContext: { size, c in
|
let overlayImage = generateImage(arguments.drawingRect.size, rotatedContext: { size, c in
|
||||||
c.clear(CGRect(origin: CGPoint(), size: size))
|
c.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
let image = customArguments.preview ? (scaledSizeImage ?? fullSizeImage) : fullSizeImage
|
let image = customArguments.preview ? (scaledSizeImage ?? fullSizeImage) : fullSizeImage
|
||||||
|
|
||||||
if let image = image {
|
if let image = image {
|
||||||
var fittedSize = CGSize(width: image.width, height: image.height)
|
var fittedSize = CGSize(width: image.width, height: image.height)
|
||||||
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {
|
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user