Post on 18-Jun-2015
Maurizio Moriconi - @bugman79Mobilesoft
Gestire i PDF con iOS
giovedì 24 maggio 12
Chi sono: Maurizio Moriconi
2
• CTO presso Mobilesoft• Mobile Developer
• Co-founder• Main Developer
http://www.facebook.com/maurizio.moriconi
http://www.linkedin.com/in/bugman
@bugman79
giovedì 24 maggio 12
Editoria digitale
3giovedì 24 maggio 12
4giovedì 24 maggio 12
Funzionalità MobilePaper• Visualizzazione in portrait e landscape (2 pagine affiancate)
• Zoom della pagina tramite pinch o con doppio tap
• Possibilità di passare alle pagine successive o precedenti
• Visualizzazione delle pagine tramite elenco e/o miniature
• Visualizzazione dell'indice (capitoli e paragrafi del pdf)
• Memorizzazione dei segnalibri (preferiti)
• Scelta della musica di sottofondo
• Inserimento di note
• Ricerca di testo all'interno della rivista
• Disponibile su iOS ed Android
5giovedì 24 maggio 12
Editoria su iOS
• Varie possibilità:
– App Native– Uso di PDF con eventuale aggiunta di elementi nativi (multimedia ed interazione)
– HTML 5
6giovedì 24 maggio 12
Il formato Pdf• Portable Document Format
• File basato su un linguaggio di descrizione pagina
• Sviluppato da Adobe System nel 1993
• Nel 2007 è diventato standard ISO 32000
• Ci sono vari sottoformati (PDF/A, PDF/X, PDF/E...)
7giovedì 24 maggio 12
PDF/A• PDF/A (PDF/Archiving) per l’archiviazione a lungo
termine (ha 2 sottoformati /A-1a /A-1b)
• Standard ISO 19005-1:2005 dal 2005
• Basato sulla vesione 1.4 del formato PDF di Adobe
• Documenti “auto contenuti”– Include i font che utilizza!!– Include immagini, colori, altri dati–Non ci sono fonti esterne
• Nel sottoformato PDF/A-2 si basa PDF v. 1.7
8giovedì 24 maggio 12
PDF: specifichehttp://www.adobe.com/devnet/pdf/
pdf_reference.html
9
Ultima versione:
PDF Reference, sixth edition APDF version 1.7
1310 pagine!!!
giovedì 24 maggio 12
Uso della webview• Vantaggi
– Facile da realizzare
– Possibilità di usare pdf “online”
– Funzionamento dei link interni
• Svantaggi– Poca interazione lato utente
– Scrollview verticale
– Nessuna paginazione
10giovedì 24 maggio 12
Caricare Pdf in una webview
NSString *pdfPath = [[NSBundle mainBundle] pathForResource:@"file" ofType:@"pdf"];
NSURL *url = [NSURL fileURLWithPath:pdfPath];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlRequest];
11giovedì 24 maggio 12
Show me the code...
12giovedì 24 maggio 12
Uso di Quartz
• Motore di rendering di Darwin chiamato “per gli amici” con il nome di Core Graphics
• Quartz 2D: – libreria grafica ereditata da QuickDraw– usa il formato PDF per il disegno!!!– si basa sulla versione 1.4 Adobe PDF
13giovedì 24 maggio 12
Classi che ci interessano
• CGPDFDocument• CGPDFPage• CGPDFObject
• CGContext
14giovedì 24 maggio 12
Caricamento del Pdf#import <QuartzCore/QuartzCore.h>
NSURL *pdfURL = [[NSBundle mainBundle] URLForResource:@"TestPage.pdf" withExtension:nil];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
// Prendo la prima paginaCGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);CGPDFPageRetain(page);
// Determino la grandezza del PDFCGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);pdfScale = self.imageView.frame.size.width/pageRect.size.width;pageRect.size = CGSizeMake(pageRect.size.width*pdfScale, pageRect.size.height*pdfScale);
15giovedì 24 maggio 12
Visualizzazione baseUIGraphicsBeginImageContext(pageRect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);CGContextFillRect(context,pageRect); CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, pageRect.size.height);CGContextScaleCTM(context, 1.0, -1.0); CGContextScaleCTM(context, pdfScale,pdfScale);!CGContextDrawPDFPage(context, page);CGContextRestoreGState(context); UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [self.imageView setImage:image]; CGPDFPageRelease(page);CGPDFDocumentRelease(pdf);
16giovedì 24 maggio 12
Show me the code...
17giovedì 24 maggio 12
Scorrimento pagine• Uso di scrollview con paginazione
• Creare una classe per la singola pagina ereditando da UIView
• Pre-caricare più pagine ma...
• Attenzione alla memoria!– Scaricare / Caricare una “finestra” di pagine
18giovedì 24 maggio 12
Pdf View- (id)initWithFrame:(CGRect)frame andPdfPage:(CGPDFPageRef)page{ self = [super initWithFrame:frame]; if (self) { pagina = page; pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); pdfScale = self.frame.size.width/pageRect.size.width; pageRect.size = CGSizeMake(pageRect.size.width*pdfScale, pageRect.size.height*pdfScale); } return self;}
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); CGContextFillRect(context,pageRect); CGContextSaveGState(context); CGContextTranslateCTM(context, 0.0, pageRect.size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextScaleCTM(context, pdfScale,pdfScale);! CGContextDrawPDFPage(context, pagina); CGContextRestoreGState(context);}
19giovedì 24 maggio 12
Impostare numero di pagineNSURL *pdfURL = [[NSBundle mainBundle] URLForResource:@"test.pdf" withExtension:nil];
pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)pdfURL); numberOfPages = CGPDFDocumentGetNumberOfPages(pdf);
myScrollview.contentSize = CGSizeMake( self.myScrollview.frame.size.width * numberOfPages, self.myScrollview.frame.size.height); myScrollview.pagingEnabled = YES;
20giovedì 24 maggio 12
Show me the code...
21giovedì 24 maggio 12
Gestire lo Zoom
• Scrollview con dentro Scrollviews :)
– Ogni pagina è una scrollview!
• Utilizzando per lo zoom il delegato:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
22giovedì 24 maggio 12
Zoom con doppio tap
• Intercettarlo tramite touchesBegan
• Permettere lo zoom in base a dove si è fatto il tap!
• Tornare a zoom scale = 1 con ulteriore doppio tap
23giovedì 24 maggio 12
Zoom con doppio tap- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{! CGPoint punto = [[touches anyObject] locationInView:self];! CGRect frameToZoom ; NSInteger radius = self.frame.size.width / 5; frameToZoom = CGRectMake(punto.x-radius, punto.y-radius, radius*2, radius*2); ! UITouch *touch = [touches anyObject];! if([touch tapCount] == 2) { if(self.zoomScale == 1.0) ! { ! ! [self zoomToRect:frameToZoom animated:YES]; } ! else ! { ! ! [self setZoomScale:1.0 animated:YES]; ! } }}
24giovedì 24 maggio 12
Show me the code...
25giovedì 24 maggio 12
il Pdf è vettoriale!!!
26giovedì 24 maggio 12
CATiledLayer• Presente dentro QuartzCore!
• Poca documentazione (4 properties, 1 Class Method)
• Esempio: Applicazione Mappe
• Ogni view possiede un CALayer
– CATiledLayer è una sottoclasse di CALayer!
• Per il disegno usare drawLayer:inContext:
27giovedì 24 maggio 12
LevelofDetail e LevelOfDetailBias• Level Of Detail il num di livelli di dettaglio per il layer
• Level Of Detail Bias è il num di livelli magnified di dettaglio per il layer
• Ogni LODB/LOD è una potenza di due o più rispetto al livello di dettaglio
28giovedì 24 maggio 12
TileSize
• E’ la grandezza massima di ogni singolo tile usato nel layer
• Di base è 256x256
• Ci sono problemi con iPad 3 :(
29giovedì 24 maggio 12
LevelofDetail e LevelOfDetailBias• UIScrollview con zoom
– minimumZoomScale 0.125f
– maximumZoomScale 8.0f
– Zoom di fattore 8
• Potremmo scegliere LevelOfDetail 7 e LevelOfDetailBias 3
– 7 configurazioni di level of detail
– ogni livello è la metà di risoluzione del precedente
– primi 3 sono a risoluzione “magnified”
– il 4 è a risoluzione normale
– gli ultimi 3 sono a risoluzione ridotta
30giovedì 24 maggio 12
31
Level 0 8192×8192
Level 1 4096×4096
Level 2 2048×2048
Level 3 1024×1024
Level 4 512×512
Level 5 256×256
Level 6 128×128
giovedì 24 maggio 12
CATiledLayer#import <QuartzCore/QuartzCore.h>
@implementation QuartzView
- (id)initWithFrame:(CGRect)frame andPdfPage:(CGPDFPageRef)page{ self = [super initWithFrame:frame]; if (self) { CATiledLayer *tiledLayer = (CATiledLayer *)[self layer]; tiledLayer.levelsOfDetail = 7;! ! tiledLayer.levelsOfDetailBias = 3;! ! tiledLayer.tileSize = CGSizeMake(512.0, 512.0);
pagina = page; pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); pdfScale = self.frame.size.width/pageRect.size.width; pageRect.size = CGSizeMake(pageRect.size.width*pdfScale, pageRect.size.height*pdfScale);
} return self;}
32giovedì 24 maggio 12
CATiledLayer+ (Class)layerClass {! return [CATiledLayer class];}
- (void)drawRect:(CGRect)rect{}
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context{! CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); CGContextFillRect(context,pageRect);!! CGContextSaveGState(context);! CGContextTranslateCTM(context, 0.0, pageRect.size.height);! CGContextScaleCTM(context, 1.0, -1.0);!! CGContextScaleCTM(context, pdfScale,pdfScale);!! CGContextDrawPDFPage(context, pagina);! CGContextRestoreGState(context);}
33giovedì 24 maggio 12
Show me the code...
34giovedì 24 maggio 12
Metadati• Dalle specifiche sono presenti al capitolo
10.2 Metadata• Sono in un formato “particolare”• Si possono estrarre con CoreGraphics 8-)
35
1 0 obj<< /Title ( PostScript Language Reference, Third Edition )
/Author (Adobe Systems Incorporated)/Creator (Adobe FrameMaker 5.5.3 for Power Macintosh®) /Producer (Acrobat Distiller 3.01 for Power Macintosh) /CreationDate (D:19970915110347-08'00')/ModDate (D:19990209153925-08'00')
>> endobj
giovedì 24 maggio 12
Metadati
36giovedì 24 maggio 12
Titolo ed autore del pdfCGPDFDictionaryRef info = CGPDFDocumentGetInfo(pdf);
CGPDFStringRef titleStringRef;CGPDFDictionaryGetString(info, "Title", &titleStringRef);const unsigned char *titleCstring = CGPDFStringGetBytePtr(titleStringRef);
printf("Titolo: %s", titleCstring);
CGPDFStringRef authorStringRef;CGPDFDictionaryGetString(info, "Author", &authorStringRef);const unsigned char *authorCstring = CGPDFStringGetBytePtr(authorStringRef);
printf("\nAutore: %s", authorCstring);
37giovedì 24 maggio 12
Accesso ai dati PDF• CGPDFDocument
• CGPDFDocumentGetCatalog
• CGPDFPage
• CGPDFPageGetDictionary
• CGPDFObjectGetObject, CGPDFDictionaryGetBoolean, CGPDFDictionaryGetInteger, CGPDFDictionaryGetString, CGPDFDictionaryGetArray...
38giovedì 24 maggio 12
Indice
• Non è sempre presente :)
• In base alla versione ed al formato potrebbe cambiare... (gestire più casi!)
• Dalle specifiche presente nel capitolo
8.2 Document-Level Navigation
39giovedì 24 maggio 12
Outline Document
40giovedì 24 maggio 12
Outline Item• Chiavi:
– Title– Parent / Prev / Next
– First / Last
– Count– Dest / A / SE
41
CGPDFDictionaryRef dict = CGPDFDocumentGetCatalog(pdf);
CGPDFDictionaryRef ret; if( (CGPDFDictionaryGetDictionary(dict, "Outline", &ret)) || (CGPDFDictionaryGetDictionary(dict, "Outlines", &ret)))
{
}
giovedì 24 maggio 12
Show me the code...
42giovedì 24 maggio 12
Altre possibilità... che non vedremo :)
• Links• Annotations (cap. 8.4)• Thumbnail (cap 8.2.3)• Ricerca testuale (estrazione full text)
43giovedì 24 maggio 12