Fast and Lean PDF Viewer for iPhone / iPad / iOs - tips and hints? -
there has been many questions drawing pdf's.
yes, can render pdf's uiwebview
cant give performance , functionality expect pdf viewer.
you can draw pdf page to calayer or uiimage. apple have sample code show how draw large pdf in zoomable uiscrollview
but same issues keep cropping up.
uiimage method:
- pdf's in
uiimage
don't optically scale layer approach. - the cpu , memory hit on generating
uiimages
pdfcontext
limits/prevents using create real-time render of new zoom-levels.
catiledlayer method:
- theres significant overhead (time) drawing full pdf page
calayer
: individual tiles can seen rendering (even tilesize tweak) calayers
cant prepared ahead of time (rendered off-screen).
generally pdf viewers pretty heavy on memory too. monitor memory usage of apple's zoomable pdf example.
in current project, i'm developing pdf viewer , rendering uiimage
of page in separate thread (issues here too!) , presenting while scale x1. catiledlayer
rendering kicks in once scale >1. ibooks takes similar double take approach if scroll pages can see lower res version of page less second before crisp version appears.
im rendering 2 pages each side of page in focus pdf image ready mask layer before starts drawing.pages destroyed again when +2 pages away focused page.
does have insights, no matter how small or obvious improve performance/ memory handling of drawing pdf's? or other issues discussed here?
edit: tips (credit- luke mcneice,vdesmedt,matt gallagher,johann):
save media disk when can.
use larger tilesizes if rendering on tiledlayers
init used arrays placeholder objects, alternitively design approach this one
note images render faster
cgpdfpageref
use
nsoperations
or gcd & blocks prepare pages ahead of time.call
cgcontextsetinterpolationquality(ctx, kcginterpolationhigh); cgcontextsetrenderingintent(ctx, kcgrenderingintentdefault);
beforecgcontextdrawpdfpage
reduce memory usage while drawinginit'ing
nsoperations
docref bad idea (memory), wrap docref singleton.cancel needless
nsoperations
when can, if using memory, beware of leaving contexts open though!recycle page objects , destroy unused views
close open contexts don't need them
on receiving memory warnings release , reload docref , page caches
other pdf features:
getting links inside pdf (and here , here)
getting target of link (getting page number
/dest
array)
getting raw text (and here , here , here (positioning focused))
searching(and here) (doesn't work pdfs (some show weird characters, guess it's encoding issue i'm not sure) -credit brainfeeder)
calayer , off-screen rendering - render next page fast/smooth display
documentation
- quartz pdfobjects (used meta info, annotations, thumbs)
- abobe pdf spec
example projects
- apple/ zoomingpdf - zooming,
uiscrollview
,catiledlayer
- vfr/ reader - zooming, paging,
uiscrollview
,catiledview
- brow/ leaves - paging nice transitions
- / skim - seems (pdf reader/editor osx)
i have build such kind of application using approximatively same approach except :
- i cache generated image on disk , generate 2 3 images in advance in separate thread.
- i don't overlay
uiimage
instead draw image in layer when zooming 1. tiles released automatically when memory warnings issued.
whenever user start zooming, acquire cgpdfpage
, render using appropriate ctm. code in - (void)drawlayer: (calayer*)layer incontext: (cgcontextref) context
:
cgaffinetransform currentctm = cgcontextgetctm(context); if (currentctm.a == 1.0 && baseimage) { //calculate ideal scale cgfloat scaleforwidth = baseimage.size.width/self.bounds.size.width; cgfloat scaleforheight = baseimage.size.height/self.bounds.size.height; cgfloat imagescalefactor = max(scaleforwidth, scaleforheight); cgsize imagesize = cgsizemake(baseimage.size.width/imagescalefactor, baseimage.size.height/imagescalefactor); cgrect imagerect = cgrectmake((self.bounds.size.width-imagesize.width)/2, (self.bounds.size.height-imagesize.height)/2, imagesize.width, imagesize.height); cgcontextdrawimage(context, imagerect, [baseimage cgimage]); } else { @synchronized(issue) { cgpdfpageref pdfpage = cgpdfdocumentgetpage(issue.pdfdoc, pageindex+1); pdftopagetransform = cgpdfpagegetdrawingtransform(pdfpage, kcgpdfmediabox, layer.bounds, 0, true); cgcontextconcatctm(context, pdftopagetransform); cgcontextdrawpdfpage(context, pdfpage); } }
issue object containg cgpdfdocumentref
. synchronize part access pdfdoc
property because release , recreate when receiving memorywarnings. seems cgpdfdocumentref
object internal caching did not find how rid of.
Comments
Post a Comment