pdf generation - Using Cocoa, NSPrintOperation, How Do I correctly Create a PDF file from text in an NSView? -
using nsprintoperation, how correctly create pdf file text in nsview?
* * notice found workaround, shown @ bottom *
what have done: 1. put text nstextview.
- (nstextview *)printableviewwithrecipe:(recipe *)recipe { [_printview setstring:@""]; [_printview settextcolor:[nscolor textcolor]]; [_printview setfont:[nsfont userfontofsize:0]]; nsdictionary *titleattr; _printview = [[nstextview alloc] initwithframe:[[self printinfo] imageablepagebounds]]; [_printview setverticallyresizable:yes]; [_printview sethorizontallyresizable:no]; // begin add text [[_printview textstorage] beginediting]; // set attributes title [[_printview textstorage] beginediting]; titleattr = [nsdictionary dictionarywithobject:[(appdelegate*)[[nsapplication sharedapplication] delegate] tablefont] forkey:nsfontattributename]; // add title [ [_printview textstorage] appendattributedstring: [[nsattributedstring alloc] initwithstring:[recipe name] attributes:titleattr ] ]; // create couple returns between title , body [[_printview textstorage] appendattributedstring:[[nsattributedstring alloc] initwithstring:@"\n\n"]]; // add body text if([[recipe ingredients] length] ) [[_printview textstorage] appendattributedstring: [ [nsattributedstring alloc] initwithstring:[recipe ingredients] attributes:titleattr]]; // create couple returns between ingredients , directions [[_printview textstorage] appendattributedstring:[[nsattributedstring alloc] initwithstring:@"\n\n"]]; if([[recipe directions] length] ) [[_printview textstorage] appendattributedstring: [ [nsattributedstring alloc] initwithstring:[recipe directions] attributes:titleattr]]; // create couple returns between directions , comments [[_printview textstorage] appendattributedstring:[[nsattributedstring alloc] initwithstring:@"\n\n"]]; if([[recipe comments] length] ) [[_printview textstorage] appendattributedstring: [ [nsattributedstring alloc] initwithstring:[recipe comments] attributes:titleattr]]; // center title [_printview setalignment:nscentertextalignment range:nsmakerange(0, [[recipe name] length])]; [[_printview textstorage] endediting]; return _printview; } // end printableviewforrecipe
2.try create pdf file textview's text using method below:
- (pdfdocument *)exportpdffromview:(nstextview*)textview filenumber:(nsuinteger)filenumber { nsprintinfo *printinfo; nsprintinfo *sharedinfo; nsprintoperation *printop; nsmutabledictionary *printinfodict; nsmutabledictionary *shareddict; sharedinfo = [nsprintinfo sharedprintinfo]; shareddict = [sharedinfo dictionary]; printinfodict = [nsmutabledictionary dictionarywithdictionary: shareddict]; [printinfodict setobject:nsprintsavejob forkey:nsprintjobdisposition]; nsstring *tempfilename = [nsstring stringwithformat:@"%@_file_%lu.pdf", [[nsprocessinfo processinfo] globallyuniquestring], filenumber]; nsurl *potempfileurl = [_tempdirectoryurl urlbyappendingpathcomponent:tempfilename]; [printinfodict setobject:potempfileurl forkey:nsprintjobsavingurl]; printinfo = [[nsprintinfo alloc] initwithdictionary:printinfodict];//1 [printinfo sethorizontalpagination: nsautopagination];//2 [printinfo setverticalpagination: nsautopagination];//3 [printinfo setverticallycentered:no];//4 printop = [nsprintoperation printoperationwithview:textview printinfo:printinfo];//5 [printop setshowsprintpanel:no]; [printop setshowsprogresspanel:no];//6 dlog(@"potempfileurl=%@",potempfileurl); bool didrunok = [printop runoperation];//7 bool exists = [[nsfilemanager defaultmanager] fileexistsatpath:[potempfileurl path]]; dlog(@"potempfileurl=%@",potempfileurl); dlog(@"didrunok=%lu\nfileexists=%lu",didrunok,exists); pdfdocument *doc = [[pdfdocument alloc] initwithurl:potempfileurl]; return doc; }
run following code :
[self tempdirectoryurl];// invoke getter nslog(@"_tempdirectoryurl=%@",_tempdirectoryurl); _tempdirectoryurl=file:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/t/com.drumminggrouse.hungryme/
the getter follows:
- (nsurl *)tempdirectoryurl { //getter nsurl *tempurl; if(!_tempdirectoryurl){ tempurl = [nsurl fileurlwithpath:[nstemporarydirectory() stringbyappendingpathcomponent:[[nsprocessinfo processinfo] globallyuniquestring]] isdirectory:yes]; _tempdirectoryurl = tempurl; } return _tempdirectoryurl; }
after running code:
bool didrunok = [printop runoperation];//7
bool exists = [[nsfilemanager defaultmanager] fileexistsatpath:[potempfileurl path]]; dlog(@"didrunok=%lu\nfileexists=%lu",didrunok,exists); dlog(@"potempfileurl=%@",potempfileurl);
i expect pdf created at: potempfileurl value is: potempfileurl=file:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/t/com.drumminggrouse.hungryme/884b9b4c-907b-489e-869b-b5efe7a11b47-1821-000016435c134e56/7a196040-0d81-496d-b9f3-bf0b855f6bbc-1821-0000164a9446040f_file_0.pdf
console shows:
didrunok=1 fileexists=1
when following line of code runs:
bool didrunok = [printop runoperation];//7
the contents of printinfo printop are:
{ nsbottommargin = 90; nscopies = 1; nsdestinationformat = "application/pdf"; nsdetailederrorreporting = 0; nsfaxnumber = ""; nsfirstpage = 1; nshorizonalpagination = 0; nshorizontallycentered = 0; nsjobdisposition = nsprintsavejob; nsjobsavingfilenameextensionhidden = 0; nsjobsavingurl = "file:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/t/com.drumminggrouse.hungryme/2687b4cd-6abf-4826-b8f8-3d536ffaca66-1362-00001defa0b13d70/1f0483bf-00b4-4f65-a3c7-c4824f53c03e-1362-00001df033aad968_file_0.pdf"; nslastpage = 2147483647; nsleftmargin = 72; nsmustcollate = 1; nsorientation = 0; nspagesacross = 1; nspagesdown = 1; nspapername = "na-letter"; nspapersize = "nssize: {612, 792}"; nsprintallpages = 1; nsprintprotected = 0; nsprintselectiononly = 0; nsprinttime = "0000-12-30 00:00:00 +0000"; nsprinter = "{\n \"device description\" = {\n nsdeviceisprinter = yes;\n };\n \"language level\" = 3;\n name = \"hp deskjet 840c @ mark\\u2019s mac pro\";\n type = \"generic pcl laser printer\";\n}"; nsprintername = "hp deskjet 840c @ mark\u2019s mac pro"; nsrightmargin = 72; nssavepath = "/var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/t/com.drumminggrouse.hungryme/2687b4cd-6abf-4826-b8f8-3d536ffaca66-1362-00001defa0b13d70/1f0483bf-00b4-4f65-a3c7-c4824f53c03e-1362-00001df033aad968_file_0.pdf"; nsscalingfactor = 1; nstopmargin = 90; nsverticalpagination = 0; nsverticallycentered = 0; }
in xcode : po [[textview textstorage] string] produces text below labeled :
/// begin nstextview text ///
in finder when open file located @ potempfileurl, in preview, file has 4 pages (it should have 1 page), , appears empty pdf file in preview.
when open same "pdf" file in textedit, file contains content below labelled : /// begin text pdf tempfile ///
what need produce "proper" pdf file? can not pdf can open , read in preview.
po [doc pagecount] shows "4"
/// begin nstextview text /// - po [[textview textstorage] string]
french toast [french toast] preptime 0:03 cooktime 0:08 serves:1-2 egg 1 milk 3/4 cup ground cinnamon 1/8 tsp (optional) best bread 2 slices butter 4 tsp (two per side) maple syrup (to taste) [french toast] 1. add egg bowl , beat fork. 2. add milk , cinnamon egg , beat briefly. 3. heat heavy skillet medium high. add 2 tsp butter. 4. dip bread slice halves in batter , brown in skillet. flip , add additional butter. brown , serve syrup. serve pork sausage, chorizo or bacon.
/// end nstextview text ///
/// begin text pdf tempfile ///
%pdf-1.3 %ƒÂÚÂÎßÛ†–ƒ∆ 4 0 obj << /length 5 0 r /filter /flatedecode >> stream x+t�Á�„ endstream endobj 5 0 obj 11 endobj 2 0 obj << /type /page /parent 3 0 r /resources 6 0 r /contents 4 0 r /mediabox [0 0 612 792] >> endobj 6 0 obj << /procset [ /pdf ] >> endobj 8 0 obj << /length 9 0 r /filter /flatedecode >> stream x+t�Á�„ endstream endobj 9 0 obj 11 endobj 7 0 obj << /type /page /parent 3 0 r /resources 10 0 r /contents 8 0 r /mediabox [0 0 612 792] >> endobj 10 0 obj << /procset [ /pdf ] >> endobj 12 0 obj << /length 13 0 r /filter /flatedecode >> stream x+t�Á�„ endstream endobj 13 0 obj 11 endobj 11 0 obj << /type /page /parent 3 0 r /resources 14 0 r /contents 12 0 r /mediabox [0 0 612 792] >> endobj 14 0 obj << /procset [ /pdf ] >> endobj 16 0 obj << /length 17 0 r /filter /flatedecode >> stream x+t�Á�„ endstream endobj 17 0 obj 11 endobj 15 0 obj << /type /page /parent 3 0 r /resources 18 0 r /contents 16 0 r /mediabox [0 0 612 792] >> endobj 18 0 obj << /procset [ /pdf ] >> endobj 3 0 obj << /type /pages /mediabox [0 0 612 792] /count 4 /kids [ 2 0 r 7 0 r 11 0 r 15 0 r ] >> endobj 19 0 obj << /type /catalog /pages 3 0 r >> endobj 20 0 obj (untitled) endobj 21 0 obj (mac os x 10.10.3 quartz pdfcontext) endobj 22 0 obj (hungryme) endobj 23 0 obj (d:20150513191029z00'00') endobj 24 0 obj () endobj 25 0 obj [ ] endobj 1 0 obj << /title 20 0 r /producer 21 0 r /creator 22 0 r /creationdate 23 0 r /moddate 23 0 r /keywords 24 0 r /aapl:keywords 25 0 r >> endobj xref 0 26 0000000000 65535 f 0000001363 00000 n 0000000125 00000 n 0000001022 00000 n 0000000022 00000 n 0000000107 00000 n 0000000229 00000 n 0000000371 00000 n 0000000268 00000 n 0000000353 00000 n 0000000476 00000 n 0000000622 00000 n 0000000516 00000 n 0000000603 00000 n 0000000729 00000 n 0000000875 00000 n 0000000769 00000 n 0000000856 00000 n 0000000982 00000 n 0000001125 00000 n 0000001175 00000 n 0000001202 00000 n 0000001255 00000 n 0000001282 00000 n 0000001324 00000 n 0000001343 00000 n trailer << /size 26 /root 19 0 r /info 1 0 r /id [ <1abd1092f1d909274c086bf0f90d6200> <1abd1092f1d909274c086bf0f90d6200> ] >> startxref 1507 %%eof
/// end text pdf tempfile
if redo method exportpdffromview: filenumber: way,
- (pdfdocument *)exportpdffromview:(nstextview*)textview filenumber:(nsuinteger)filenumber { nsstring *tempfilename = [nsstring stringwithformat:@"%@_file_%lu.pdf", [[nsprocessinfo processinfo] globallyuniquestring], filenumber]; nsurl *potempfileurl = [_tempdirectoryurl urlbyappendingpathcomponent:tempfilename]; dlog(@"potempfileurl=%@",potempfileurl); nsrect r = [textview bounds]; nsdata *data = [textview datawithpdfinsiderect:r]; [data writetofile:potempfileurl.path atomically:yes]; pdfdocument *doc2 = [[pdfdocument alloc] initwithurl:potempfileurl]; dlog(@"doc2.pagecount=%lu",doc2.pagecount); ... return doc2; }
when view resultant pdf file @ url potempfileurl, has 1 page, correct. again pdf shows no text in preview. if view "pdf" textedit, contents below.
%pdf-1.3 %ƒÂÚÂÎßÛ†–ƒ∆ 4 0 obj << /length 5 0 r /filter /flatedecode >> stream x+tÁ„ endstream endobj 5 0 obj 11 endobj 2 0 obj << /type /page /parent 3 0 r /resources 6 0 r /contents 4 0 r /mediabox [0 0 576 734] >> endobj 6 0 obj << /procset [ /pdf ] >> endobj 3 0 obj << /type /pages /mediabox [0 0 576 734] /count 1 /kids [ 2 0 r ] >> endobj 7 0 obj << /type /catalog /pages 3 0 r >> endobj 8 0 obj (mac os x 10.10.3 quartz pdfcontext) endobj 9 0 obj (d:20150517134359z00'00') endobj 1 0 obj << /producer 8 0 r /creationdate 9 0 r /moddate 9 0 r >> endobj xref 0 10 0000000000 65535 f 0000000493 00000 n 0000000125 00000 n 0000000268 00000 n 0000000022 00000 n 0000000107 00000 n 0000000229 00000 n 0000000351 00000 n 0000000400 00000 n 0000000452 00000 n trailer << /size 10 /root 7 0 r /info 1 0 r /id [ <d86abf98c49359ba2092ad602722f659> <d86abf98c49359ba2092ad602722f659> ] >> startxref 565 %%eof
! ! ! !
i have found workaround me want go. still not explain me why seemingly endless attempts use
+ (nsprintoperation *)printoperationwithview:(nsview *)aview printinfo:(nsprintinfo *)aprintinfo
fail.
the workaround produces multipage pdf files can viewed in preview.
i hope useful others.
- (void)testquartz:(nsdata *)pdfdocumentdata savepath:(nsstring*)savepath { //create pdf document reference cgdataproviderref dataprovider = cgdataprovidercreatewithcfdata((cfdataref)pdfdocumentdata); cgpdfdocumentref document = cgpdfdocumentcreatewithprovider(dataprovider); //create pdf context cgpdfpageref page = cgpdfdocumentgetpage(document, 1); //pages numbered starting @ 1 cgrect pagerect = cgpdfpagegetboxrect(page, kcgpdfmediabox); cfmutabledataref mutabledata = cfdatacreatemutable(null, 0); //nslog(@"w:%2.2f, h:%2.2f",pagerect.size.width, pagerect.size.height); cgdataconsumerref dataconsumer = cgdataconsumercreatewithcfdata(mutabledata); cgcontextref pdfcontext = cgpdfcontextcreate(dataconsumer, &pagerect, null); if (cgpdfdocumentgetnumberofpages(document) > 0) { //draw page onto new context //page = cgpdfdocumentgetpage(document, 1); //pages numbered starting @ 1 cgpdfcontextbeginpage(pdfcontext, null); cgcontextdrawpdfpage(pdfcontext, page); cgpdfcontextendpage(pdfcontext); } else { nslog(@"failed create document"); } cgcontextrelease(pdfcontext); //release before writing data disk. //write disk [(__bridge nsdata *)mutabledata writetofile:savepath atomically:yes]; //clean cgdataproviderrelease(dataprovider); //release data provider cgdataconsumerrelease(dataconsumer); cgpdfdocumentrelease(document); cfrelease(mutabledata); } - (pdfdocument *)exportpdffromview:(nstextview*)textview filenumber:(nsuinteger)filenumber { nsstring *tempfilename = [nsstring stringwithformat:@"%@_file_%lu.pdf", [[nsprocessinfo processinfo] globallyuniquestring], filenumber]; nsurl *potempfileurl = [_tempdirectoryurl urlbyappendingpathcomponent:tempfilename]; dlog(@"potempfileurl=%@",potempfileurl); nsrect r = [textview bounds]; nsdata *data = [textview datawithpdfinsiderect:r]; [ self testquartz:(nsdata *)data savepath:potempfileurl.path ]; ... return adoc; }
if me , want publish single pdf, essays, beginning @ top of page in single pdf, want following take pages out of temporary input documents , move them single output pdf.
nsuinteger pagecountdoczero = [[inputdocuments objectatindex:0] pagecount]; nsuinteger pageindex = pagecountdoczero; (pdfdocument *document in inputdocuments) { (nsuinteger j = 0; j < [document pagecount]; j++) { pdfpage *page = [document pageatindex:j]; dlog(@"inserting pageindex:%lu i.e inputpage:%lu of %lu",pageindex,j+1,[document pagecount]); [outputdocument insertpage:page atindex:pageindex++]; } }
Comments
Post a Comment