Gestire i pdf con iOS
-
Upload
maurizio-moriconi -
Category
Technology
-
view
1.832 -
download
1
Transcript of Gestire i pdf con iOS
Maurizio Moriconi - @bugman79Mobilesoft
Gestire i PDF con iOS
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
Editoria digitale
3
4
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
5
Editoria su iOS
• Varie possibilità:
– App Native– Uso di PDF con eventuale aggiunta di elementi nativi (multimedia ed interazione)
– HTML 5
6
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...)
7
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
8
PDF: specifichehttp://www.adobe.com/devnet/pdf/
pdf_reference.html
9
Ultima versione:
PDF Reference, sixth edition APDF version 1.7
1310 pagine!!!
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
10
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];
11
Show me the code...
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
13
Classi che ci interessano
• CGPDFDocument• CGPDFPage• CGPDFObject
• CGContext
14
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);
15
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);
16
Show me the code...
17
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
18
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);}
19
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;
20
Show me the code...
21
Gestire lo Zoom
• Scrollview con dentro Scrollviews :)
– Ogni pagina è una scrollview!
• Utilizzando per lo zoom il delegato:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
22
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
23
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]; ! } }}
24
Show me the code...
25
il Pdf è vettoriale!!!
26
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:
27
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
28
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
28
TileSize
• E’ la grandezza massima di ogni singolo tile usato nel layer
• Di base è 256x256
• Ci sono problemi con iPad 3 :(
29
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
30
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
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;}
32
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);}
33
Show me the code...
34
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
Metadati
36
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);
37
Accesso ai dati PDF• CGPDFDocument
• CGPDFDocumentGetCatalog
• CGPDFPage
• CGPDFPageGetDictionary
• CGPDFObjectGetObject, CGPDFDictionaryGetBoolean, CGPDFDictionaryGetInteger, CGPDFDictionaryGetString, CGPDFDictionaryGetArray...
38
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
39
Outline Document
40
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)))
{
}
Show me the code...
42
Altre possibilità... che non vedremo :)
• Links• Annotations (cap. 8.4)• Thumbnail (cap 8.2.3)• Ricerca testuale (estrazione full text)
43