mirror of
https://github.com/ogoguel/activegs-ios.git
synced 2024-10-31 15:05:47 +00:00
364 lines
9.5 KiB
Plaintext
364 lines
9.5 KiB
Plaintext
/*
|
|
ActiveGS, Copyright 2004-2016 Olivier Goguel, https://github.com/ogoguel/ActiveGS
|
|
Based on Kegs, Copyright 2004 Kent Dickey, https://kegs.sourceforge.net
|
|
This code is covered by the GNU GPL licence
|
|
*/
|
|
|
|
#include "activegsAppDelegate.h"
|
|
#import "AsyncImageView.h"
|
|
#include "../common/CEmulatorCtrl.h"
|
|
|
|
|
|
static asyncImageQueue* queue = nil;
|
|
static UIActivityIndicatorView* asyncloader=nil;
|
|
|
|
|
|
@implementation asyncImageQueue
|
|
|
|
@synthesize theQueue = _theQueue;
|
|
@synthesize theConnection = _theConnection;
|
|
|
|
|
|
+(void) initialize{
|
|
|
|
// singleton
|
|
queue = [[asyncImageQueue alloc] init];
|
|
queue.theQueue = [[NSMutableArray alloc] init ];
|
|
queue.theConnection = nil;
|
|
|
|
asyncloader = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
|
|
|
|
|
|
}
|
|
|
|
+(asyncImageQueue*)sharedQueue
|
|
{
|
|
return queue;
|
|
}
|
|
|
|
|
|
-(void)prioritizeItem:(UIImageView*)_mytarget {
|
|
|
|
int nb = [self.theQueue count];
|
|
for(int i=0;i<nb;i++)
|
|
{
|
|
AsyncImageView* o = [self.theQueue objectAtIndex:i];
|
|
if (o.target==_mytarget)
|
|
{
|
|
// le remet au début de la pile = A FAIRE DANS CETTE ORDRE
|
|
[self.theQueue removeObject:o];
|
|
[self.theQueue addObject:o];
|
|
debug_printf("image put on top of the cache %s\n",[o.url UTF8String]);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)nextDownload {
|
|
|
|
debug_printf("next download");
|
|
if (self.theConnection)
|
|
{
|
|
debug_printf("*wait\n");
|
|
return ;
|
|
}
|
|
|
|
AsyncImageView* obj = [self.theQueue lastObject];
|
|
if (obj)
|
|
{
|
|
[obj processDownload];
|
|
}
|
|
else
|
|
{
|
|
debug_printf("*nothing to unqueue*\n");
|
|
}
|
|
|
|
}
|
|
-(void)removeObject:(id)_obj
|
|
{
|
|
debug_printf("remove object");
|
|
[self.theQueue removeObject:_obj];
|
|
// [self.theConnection release];
|
|
self.theConnection = nil;
|
|
[self nextDownload];
|
|
}
|
|
@end
|
|
|
|
@implementation AsyncImageView
|
|
|
|
@synthesize data = _data;
|
|
@synthesize target = _target;
|
|
@synthesize url = _url;
|
|
|
|
|
|
|
|
- (void)processDownload {
|
|
|
|
// printf("processDownload (%s)\n",[url UTF8String]);
|
|
|
|
[asyncloader removeFromSuperview];
|
|
|
|
CGRect r = self.target.frame;
|
|
CGRect f = asyncloader.frame;
|
|
f.origin.x = (r.size.width-f.size.width)/2;
|
|
f.origin.y = (r.size.height-f.size.height)/2;
|
|
asyncloader.frame = f;
|
|
[ self.target addSubview:asyncloader];
|
|
[asyncloader startAnimating];
|
|
|
|
NSURL* urlnoescape = [[NSURL alloc] initWithString:[ self.url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] ;
|
|
|
|
NSURLRequest* request = [NSURLRequest requestWithURL:urlnoescape cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0] ;
|
|
|
|
queue.theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self] ;
|
|
|
|
if (!queue.theConnection)
|
|
printf("NSURLConnection failed\n");
|
|
|
|
|
|
}
|
|
|
|
- (void)initImage:(const char*)_thumb target:(UIImageView*)_mytarget width:(int)_width height:(int)_height
|
|
{
|
|
thumb = _thumb;
|
|
width = _width;
|
|
height = _height;
|
|
self.target = _mytarget;
|
|
|
|
}
|
|
|
|
//- (void)loadImage:(const char*)_thumb target:(UIImageView*)_target width:(int)_width height:(int)_height
|
|
- (void)loadImage:(id)_sender
|
|
{
|
|
|
|
|
|
if (thumb.IsEmpty()) return ;
|
|
NSString* str = [NSString stringWithUTF8String:thumb.c_str()];
|
|
if ( self.data!=nil)
|
|
{
|
|
self.data =nil;
|
|
}
|
|
if (!str) return ;
|
|
|
|
|
|
// regarde si l'image générée est dans le cache
|
|
|
|
MyString fnoext =getfilenoext(getfile(thumb.c_str()));
|
|
MyString cache;
|
|
cache.Format("%s_%d_%d.%s",fnoext.c_str(),width,height,getext(thumb.c_str()));
|
|
CDownload dl("***ERROR***");
|
|
dl.getPersistentDirectoryFile(cache.c_str(),IPHONETHUMB,cachedURL);
|
|
NSString* strc = [NSString stringWithUTF8String:cachedURL.c_str()] ;
|
|
UIImage* imageView = [UIImage imageWithContentsOfFile:strc] ;
|
|
if (imageView)
|
|
{
|
|
debug_printf("target image loaded from cache %s\n",getfile(cachedURL.c_str()));
|
|
self.target.image = imageView;
|
|
return ;
|
|
}
|
|
|
|
// non : regarde si l'image original a déjà été téléchargé
|
|
|
|
if ([str length] > 7 && [[str substringToIndex:7] compare:@"http://"])
|
|
{
|
|
NSString *str2;
|
|
if (thumb.at(0) != '/')
|
|
{
|
|
// ressource image
|
|
str2 = [[NSBundle mainBundle] pathForResource:str ofType:nil];
|
|
}
|
|
else
|
|
{
|
|
// absolute path
|
|
str2 = str ; //[NSString stringWithUTF8String:str];
|
|
}
|
|
imageView = [UIImage imageWithContentsOfFile:str2]; // to mimic init
|
|
if (!imageView)
|
|
{
|
|
printf("init image failed (%s)\n",[str2 UTF8String]);
|
|
return ;
|
|
}
|
|
debug_printf("image loaded from resource %s\n",getfile([str2 UTF8String]));
|
|
|
|
}
|
|
else
|
|
{
|
|
self.url = str;
|
|
|
|
// regarde si l'image est dans le cache
|
|
|
|
dl.getPersistentDirectoryFile([self.url UTF8String],IPHONETHUMB,cache);
|
|
NSString* strcache = [NSString stringWithUTF8String:cache.c_str()];
|
|
imageView = [UIImage imageWithContentsOfFile:strcache];
|
|
if (imageView)
|
|
{
|
|
debug_printf("image loaded from cache %s\n",getfile(cache.c_str()));
|
|
}
|
|
else
|
|
{
|
|
|
|
asyncImageQueue* q = [asyncImageQueue sharedQueue];
|
|
[q.theQueue addObject:self];
|
|
[q nextDownload];
|
|
|
|
return ;
|
|
}
|
|
|
|
}
|
|
|
|
[self setImageForCell:imageView];
|
|
|
|
|
|
}
|
|
|
|
|
|
//the URL connection calls this repeatedly as data arrives
|
|
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incrementalData {
|
|
if (self.data==nil) { self.data = [[NSMutableData alloc] initWithCapacity:2048]; }
|
|
[self.data appendData:incrementalData];
|
|
}
|
|
|
|
//the URL connection calls this once all the data has downloaded
|
|
- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
|
|
|
|
[asyncloader removeFromSuperview];
|
|
[asyncloader stopAnimating];
|
|
|
|
UIImage* imageView = [[UIImage alloc] initWithData:self.data] ;
|
|
if (!imageView)
|
|
{
|
|
printf("init image failed (%s)\n",[self.url UTF8String]);
|
|
}
|
|
else
|
|
{
|
|
// process l'image
|
|
NSData * png = self.data;
|
|
MyString cache;
|
|
CDownload dl("***ERROR***");
|
|
dl.getPersistentDirectoryFile([self.url UTF8String],IPHONETHUMB,cache);
|
|
FILE* f = fopen(cache.c_str(),"wb");
|
|
if (f)
|
|
{
|
|
fwrite(png.bytes,1,png.length,f);
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
printf("cannot update cache %s\n",cache.c_str());
|
|
}
|
|
|
|
debug_printf("image downloaded (%s)\n",getfile([self.url UTF8String]));
|
|
[self performSelectorOnMainThread:@selector(setImageForCell:) withObject:imageView waitUntilDone:NO];
|
|
|
|
}
|
|
|
|
self.data=nil;
|
|
|
|
[[asyncImageQueue sharedQueue] removeObject:self];
|
|
|
|
}
|
|
|
|
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
|
|
{
|
|
printf("didFailWithError (%s)\n",[self.url UTF8String]);
|
|
|
|
[asyncloader removeFromSuperview];
|
|
[asyncloader stopAnimating];
|
|
|
|
self.data=nil;
|
|
|
|
[[asyncImageQueue sharedQueue] removeObject:self];
|
|
|
|
}
|
|
|
|
+(UIImage*)processImage:(UIImage*)_img width:(int)_width height:(int)_height
|
|
{
|
|
#define IMAGESCALE 1
|
|
#define SHADOW 2
|
|
#define LEFTMARGIN 6
|
|
#define BOTTOMMARGIN 0
|
|
#define TOPMARGIN 0
|
|
|
|
const float s = [pManager dpiRatio];
|
|
|
|
CGRect r = CGRectMake(0,0,_width*s,_height*s);
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGContextRef context = CGBitmapContextCreate(nil, (int)r.size.width,(int)r.size.height, 8, (int)r.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast/*kCGImageAlphaNone*/);
|
|
|
|
float ovalWidth=14*s,ovalHeight=14*s;
|
|
CGContextSaveGState(context);
|
|
CGContextTranslateCTM (context, CGRectGetMinX(r), CGRectGetMinY(r));
|
|
CGContextScaleCTM (context, ovalWidth, ovalHeight);
|
|
float fw = CGRectGetWidth (r) / ovalWidth;
|
|
float fh = CGRectGetHeight (r) / ovalHeight;
|
|
CGContextMoveToPoint(context, fw, fh/2);
|
|
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
|
|
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
|
|
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
|
|
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
|
|
CGContextClosePath(context);
|
|
CGContextRestoreGState(context);
|
|
CGContextClip(context);
|
|
//CGContextSetInterpolationQuality(context,kCGInterpolationHigh);
|
|
CGContextDrawImage(context,r,[_img CGImage]);
|
|
CGImageRef imageRef2 = CGBitmapContextCreateImage(context);
|
|
// Crée une nouvelle image pour le shadow
|
|
CGRect r2 = CGRectMake(0,0,r.size.width+(LEFTMARGIN+SHADOW)*s,r.size.height+(SHADOW*2+BOTTOMMARGIN+TOPMARGIN)*s);
|
|
CGContextRef context2 = CGBitmapContextCreate(nil,(int)r2.size.width,(int)r2.size.height, 8, (int)r2.size.width*4,colorSpace,kCGImageAlphaPremultipliedLast/*kCGImageAlphaNone*/);
|
|
|
|
CGContextSaveGState(context2);
|
|
CGContextSetShadowWithColor(context2, CGSizeMake(SHADOW*s, -SHADOW*s), 4, [[UIColor grayColor] CGColor]);
|
|
|
|
CGRect rdest = r;
|
|
rdest.origin.x = LEFTMARGIN*s;
|
|
rdest.origin.y = (BOTTOMMARGIN+SHADOW)*s;
|
|
//CGContextSetInterpolationQuality(context2,kCGInterpolationHigh);
|
|
|
|
CGContextDrawImage(context2,rdest,imageRef2);
|
|
CGContextRestoreGState(context2);
|
|
|
|
CGImageRef imageRef = CGBitmapContextCreateImage(context2);
|
|
UIImage* newImage = [UIImage imageWithCGImage:imageRef];
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
CGContextRelease(context);
|
|
CFRelease(imageRef);
|
|
CGContextRelease(context2);
|
|
CFRelease(imageRef2);
|
|
|
|
return newImage;
|
|
|
|
}
|
|
|
|
-(void)setImageForCell:(UIImage*) _img
|
|
{
|
|
debug_printf("setImageForCell");
|
|
|
|
UIImage* img2 = [AsyncImageView processImage:_img width:width height:height];
|
|
|
|
[self.target setNeedsDisplay];
|
|
|
|
[UIView beginAnimations:@"ToggleSiblings" context:nil];
|
|
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft /*UIViewAnimationTransitionCurlUp*/ forView:self.target cache:YES];
|
|
[UIView setAnimationDuration:1.0];
|
|
self.target.image = img2;
|
|
[UIView commitAnimations];
|
|
|
|
// sauve dans le cache
|
|
NSData *png = UIImagePNGRepresentation(img2);
|
|
|
|
FILE* f = fopen(cachedURL.c_str(),"wb");
|
|
if (f)
|
|
{
|
|
fwrite(png.bytes,1,png.length,f);
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
printf("cannot update cache %s\n",cachedURL.c_str());
|
|
}
|
|
|
|
|
|
}
|
|
@end
|