SlideShare a Scribd company logo
Gestire i PDF con iOS



Maurizio Moriconi - @bugman79
Mobilesoft
Chi sono: Maurizio Moriconi


    • CTO presso Mobilesoft                       • Co-founder
    • Mobile Developer                            • Main Developer


                  http://www.linkedin.com/in/bugman


                 @bugman79


                  http://www.facebook.com/maurizio.moriconi

2
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: specifiche
            http://www.adobe.com/devnet/pdf/
                    pdf_reference.html


    Ultima versione:

    PDF Reference, sixth edition APDF version 1.7

    1310 pagine!!!




9
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 pagina
     CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
     CGPDFPageRetain(page);

     // Determino la grandezza del PDF
     CGRect 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 base
     UIGraphicsBeginImageContext(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 pagine
     NSURL *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
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




31
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-)
     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




35
Metadati




36
Titolo ed autore del pdf
     CGPDFDictionaryRef 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


CGPDFDictionaryRef dict = CGPDFDocumentGetCatalog(pdf);


CGPDFDictionaryRef ret;

if(        (CGPDFDictionaryGetDictionary(dict, "Outline", &ret))
      ||   (CGPDFDictionaryGetDictionary(dict, "Outlines", &ret)))

       {

      }


41
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

More Related Content

Similar to Gestire i pdf con iOS

m-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Netm-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Net
Mauro Servienti
 
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Corso WebApp iOS - Lezione 06:   Web Development for iOS DevicesCorso WebApp iOS - Lezione 06:   Web Development for iOS Devices
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Andrea Picchi
 
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, PiacenzaSviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
Marco Breveglieri
 
L'Arte del Templating: Typoscript, Fluid e Grid Elements
L'Arte del Templating: Typoscript, Fluid e Grid ElementsL'Arte del Templating: Typoscript, Fluid e Grid Elements
L'Arte del Templating: Typoscript, Fluid e Grid Elements
Elena Bartolotti
 
SkyMedia: La tecnologia al servizio dell'intrattenimento
SkyMedia: La tecnologia al servizio dell'intrattenimentoSkyMedia: La tecnologia al servizio dell'intrattenimento
SkyMedia: La tecnologia al servizio dell'intrattenimento
Mavigex srl
 
Progetto su iPhone - Seminario di Reti Wireless
Progetto su iPhone - Seminario di Reti WirelessProgetto su iPhone - Seminario di Reti Wireless
Progetto su iPhone - Seminario di Reti Wireless
Silvio Daminato
 
Livin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzioneLivin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzione
giacomos
 
I linguaggi del web - seconda edizione (3° giornata)
I linguaggi del web - seconda edizione (3° giornata)I linguaggi del web - seconda edizione (3° giornata)
I linguaggi del web - seconda edizione (3° giornata)
Diego La Monica
 
Node.js - Server Side Javascript
Node.js - Server Side JavascriptNode.js - Server Side Javascript
Node.js - Server Side Javascript
Matteo Napolitano
 
Integrare Zend Framework in Wordpress
Integrare Zend Framework in WordpressIntegrare Zend Framework in Wordpress
Integrare Zend Framework in Wordpress
Enrico Zimuel
 
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache CordovaDrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
DrupalDay
 
Mob03 what's new in windows phone
Mob03   what's new in windows phoneMob03   what's new in windows phone
Mob03 what's new in windows phoneDotNetCampus
 
Blazor with .net 5 - di Gerardo Greco
Blazor with .net 5 - di Gerardo GrecoBlazor with .net 5 - di Gerardo Greco
Blazor with .net 5 - di Gerardo Greco
Giuneco S.r.l
 
Html5
Html5Html5
Drupal Day 2012 - DRUPAL 8: I CAMBIAMENTI CHE CI ASPETTANO
Drupal Day 2012 - DRUPAL 8:  I CAMBIAMENTI CHE CI ASPETTANODrupal Day 2012 - DRUPAL 8:  I CAMBIAMENTI CHE CI ASPETTANO
Drupal Day 2012 - DRUPAL 8: I CAMBIAMENTI CHE CI ASPETTANO
DrupalDay
 
Introduzione a TypeScript
Introduzione a TypeScriptIntroduzione a TypeScript
Introduzione a TypeScriptSinergia Totale
 
UI Composition
UI CompositionUI Composition
UI Composition
DotNetMarche
 

Similar to Gestire i pdf con iOS (20)

m-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Netm-v-vm @ UgiAlt.Net
m-v-vm @ UgiAlt.Net
 
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
Corso WebApp iOS - Lezione 06:   Web Development for iOS DevicesCorso WebApp iOS - Lezione 06:   Web Development for iOS Devices
Corso WebApp iOS - Lezione 06: Web Development for iOS Devices
 
Dojo nuovo look alle vostre applicazioni web Domino
Dojo nuovo look alle vostre applicazioni web DominoDojo nuovo look alle vostre applicazioni web Domino
Dojo nuovo look alle vostre applicazioni web Domino
 
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, PiacenzaSviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
Sviluppo Web con React e Delphi - Seminario Delphi Day 2016, Piacenza
 
L'Arte del Templating: Typoscript, Fluid e Grid Elements
L'Arte del Templating: Typoscript, Fluid e Grid ElementsL'Arte del Templating: Typoscript, Fluid e Grid Elements
L'Arte del Templating: Typoscript, Fluid e Grid Elements
 
SkyMedia: La tecnologia al servizio dell'intrattenimento
SkyMedia: La tecnologia al servizio dell'intrattenimentoSkyMedia: La tecnologia al servizio dell'intrattenimento
SkyMedia: La tecnologia al servizio dell'intrattenimento
 
Progetto su iPhone - Seminario di Reti Wireless
Progetto su iPhone - Seminario di Reti WirelessProgetto su iPhone - Seminario di Reti Wireless
Progetto su iPhone - Seminario di Reti Wireless
 
Livin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzioneLivin' with Docker - dallo sviluppo alla produzione
Livin' with Docker - dallo sviluppo alla produzione
 
App Engine + Python
App Engine + PythonApp Engine + Python
App Engine + Python
 
I linguaggi del web - seconda edizione (3° giornata)
I linguaggi del web - seconda edizione (3° giornata)I linguaggi del web - seconda edizione (3° giornata)
I linguaggi del web - seconda edizione (3° giornata)
 
Web frameworks
Web frameworksWeb frameworks
Web frameworks
 
Node.js - Server Side Javascript
Node.js - Server Side JavascriptNode.js - Server Side Javascript
Node.js - Server Side Javascript
 
Integrare Zend Framework in Wordpress
Integrare Zend Framework in WordpressIntegrare Zend Framework in Wordpress
Integrare Zend Framework in Wordpress
 
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache CordovaDrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
DrupalGap: crea una app Android (ed iOS) con Drupal, Drupalgap ed Apache Cordova
 
Mob03 what's new in windows phone
Mob03   what's new in windows phoneMob03   what's new in windows phone
Mob03 what's new in windows phone
 
Blazor with .net 5 - di Gerardo Greco
Blazor with .net 5 - di Gerardo GrecoBlazor with .net 5 - di Gerardo Greco
Blazor with .net 5 - di Gerardo Greco
 
Html5
Html5Html5
Html5
 
Drupal Day 2012 - DRUPAL 8: I CAMBIAMENTI CHE CI ASPETTANO
Drupal Day 2012 - DRUPAL 8:  I CAMBIAMENTI CHE CI ASPETTANODrupal Day 2012 - DRUPAL 8:  I CAMBIAMENTI CHE CI ASPETTANO
Drupal Day 2012 - DRUPAL 8: I CAMBIAMENTI CHE CI ASPETTANO
 
Introduzione a TypeScript
Introduzione a TypeScriptIntroduzione a TypeScript
Introduzione a TypeScript
 
UI Composition
UI CompositionUI Composition
UI Composition
 

More from Maurizio Moriconi

Azure Bot Service with Node.js
Azure Bot Service with Node.jsAzure Bot Service with Node.js
Azure Bot Service with Node.js
Maurizio Moriconi
 
Connected & Disconnected Apps with Azure Mobile Apps
Connected & Disconnected Apps with Azure Mobile AppsConnected & Disconnected Apps with Azure Mobile Apps
Connected & Disconnected Apps with Azure Mobile Apps
Maurizio Moriconi
 
Client authentication and authorization
Client authentication and authorizationClient authentication and authorization
Client authentication and authorization
Maurizio Moriconi
 
Backend as a Service: Parse
Backend as a Service: ParseBackend as a Service: Parse
Backend as a Service: Parse
Maurizio Moriconi
 
Cocos2d: creare videogiochi con facilità!
Cocos2d: creare videogiochi con facilità!Cocos2d: creare videogiochi con facilità!
Cocos2d: creare videogiochi con facilità!
Maurizio Moriconi
 
Box2D: Un motore fisico opensource multipiattaforma
Box2D: Un motore fisico opensource multipiattaformaBox2D: Un motore fisico opensource multipiattaforma
Box2D: Un motore fisico opensource multipiattaformaMaurizio Moriconi
 

More from Maurizio Moriconi (6)

Azure Bot Service with Node.js
Azure Bot Service with Node.jsAzure Bot Service with Node.js
Azure Bot Service with Node.js
 
Connected & Disconnected Apps with Azure Mobile Apps
Connected & Disconnected Apps with Azure Mobile AppsConnected & Disconnected Apps with Azure Mobile Apps
Connected & Disconnected Apps with Azure Mobile Apps
 
Client authentication and authorization
Client authentication and authorizationClient authentication and authorization
Client authentication and authorization
 
Backend as a Service: Parse
Backend as a Service: ParseBackend as a Service: Parse
Backend as a Service: Parse
 
Cocos2d: creare videogiochi con facilità!
Cocos2d: creare videogiochi con facilità!Cocos2d: creare videogiochi con facilità!
Cocos2d: creare videogiochi con facilità!
 
Box2D: Un motore fisico opensource multipiattaforma
Box2D: Un motore fisico opensource multipiattaformaBox2D: Un motore fisico opensource multipiattaforma
Box2D: Un motore fisico opensource multipiattaforma
 

Gestire i pdf con iOS

  • 1. Gestire i PDF con iOS Maurizio Moriconi - @bugman79 Mobilesoft
  • 2. Chi sono: Maurizio Moriconi • CTO presso Mobilesoft • Co-founder • Mobile Developer • Main Developer http://www.linkedin.com/in/bugman @bugman79 http://www.facebook.com/maurizio.moriconi 2
  • 4. 4
  • 5. 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
  • 6. Editoria su iOS • Varie possibilità: – App Native – Uso di PDF con eventuale aggiunta di elementi nativi (multimedia ed interazione) – HTML 5 6
  • 7. 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
  • 8. 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
  • 9. PDF: specifiche http://www.adobe.com/devnet/pdf/ pdf_reference.html Ultima versione: PDF Reference, sixth edition APDF version 1.7 1310 pagine!!! 9
  • 10. 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
  • 11. 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
  • 12. Show me the code... 12
  • 13. 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
  • 14. Classi che ci interessano • CGPDFDocument • CGPDFPage • CGPDFObject • CGContext 14
  • 15. Caricamento del Pdf #import <QuartzCore/QuartzCore.h> NSURL *pdfURL = [[NSBundle mainBundle] URLForResource:@"TestPage.pdf" withExtension:nil]; CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL); // Prendo la prima pagina CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1); CGPDFPageRetain(page); // Determino la grandezza del PDF CGRect 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
  • 16. Visualizzazione base UIGraphicsBeginImageContext(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
  • 17. Show me the code... 17
  • 18. 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
  • 19. 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
  • 20. Impostare numero di pagine NSURL *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
  • 21. Show me the code... 21
  • 22. Gestire lo Zoom • Scrollview con dentro Scrollviews :) – Ogni pagina è una scrollview! • Utilizzando per lo zoom il delegato: - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 22
  • 23. 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
  • 24. 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
  • 25. Show me the code... 25
  • 26. il Pdf è vettoriale!!! 26
  • 27. 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
  • 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
  • 29. 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
  • 30. TileSize • E’ la grandezza massima di ogni singolo tile usato nel layer • Di base è 256x256 • Ci sono problemi con iPad 3 :( 29
  • 31. 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
  • 32. 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 31
  • 33. 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
  • 34. 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
  • 35. Show me the code... 34
  • 36. Metadati • Dalle specifiche sono presenti al capitolo 10.2 Metadata • Sono in un formato “particolare” • Si possono estrarre con CoreGraphics 8-) 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 35
  • 38. Titolo ed autore del pdf CGPDFDictionaryRef 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
  • 39. Accesso ai dati PDF • CGPDFDocument • CGPDFDocumentGetCatalog • CGPDFPage • CGPDFPageGetDictionary • CGPDFObjectGetObject, CGPDFDictionaryGetBoolean, CGPDFDictionaryGetInteger, CGPDFDictionaryGetString, CGPDFDictionaryGetArray... 38
  • 40. 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
  • 42. Outline Item • Chiavi: – Title – Parent / Prev / Next – First / Last – Count – Dest / A / SE CGPDFDictionaryRef dict = CGPDFDocumentGetCatalog(pdf); CGPDFDictionaryRef ret; if( (CGPDFDictionaryGetDictionary(dict, "Outline", &ret)) || (CGPDFDictionaryGetDictionary(dict, "Outlines", &ret))) { } 41
  • 43. Show me the code... 42
  • 44. Altre possibilità... che non vedremo :) • Links • Annotations (cap. 8.4) • Thumbnail (cap 8.2.3) • Ricerca testuale (estrazione full text) 43