I've been looking a way to obtain the source code of a PDF file, not the HEX code but a plain text code, my intention is to code a PDF file from plain text, that way I can create a PDF report with a ESP32 or maybe an Arduino board, uploading the source code to a program, save it to an SD card and rename it with a .pdf extension.
I know it's more complicated than just add lines and Strings like you would do with an HTML document. If I add or delete an object the file will be corrupted, but the plan is to generate a "PDF Layout just like this one:
PDF Layout Example
PDF Layout Table Example
That way I wouldn't be deleting or adding any objects, just modifying the String that already exists. I found I can generate PDF files from a text editor like NotePad using plain text like this example:
%PDF-1.4
1 0 obj
<< /Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
>>
endobj
2 0 obj
<< /Type /Outlines
/Count 0
>>
endobj
3 0 obj
<< /Type /Pages
/Kids [ 4 0 R ]
/Count 1
>>
endobj
4 0 obj
<< /Type /Page
/Parent 3 0 R
/MediaBox [ 0 0 612 792 ]
/Contents 5 0 R
/Resources << /ProcSet 6 0 R
/Font << /F1 7 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 73 >>
stream
BT
/F1 24 Tf
100 100 Td
( Hello World ) Tj
ET
endstream
endobj
6 0 obj
[ /PDF /Text ]
endobj
7 0 obj
<< /Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000364 00000 n
0000000466 00000 n
0000000496 00000 n
trailer
<< /Size 8
/Root 1 0 R
>>
startxref
625
%%EOF
So I've been searching a way to extract that kind of code from my PDF layout but I've been only capable of extracting the HEX code which is kind of useless for my purpose. I would be grateful on any help or guidance on this project.
For what you propose one potential solution is MuPDF/MuTool If you wish to decompile An existing PDF there are options in MuPDF-GL for windows using option A to convert to Ascii and "PrettyPrint"
You can write your own PDF as text but it can have limitations this is accepted as a working PDF
%PDF-1.2 4 0 obj << >> stream BT/ 36 Tf((Hello World!))' ET endstream endobj 3 0 obj << /Type /Page /Parent 2 0 R /Contents 4 0 R >> endobj 2 0 obj << /Kids [3 0 R ] /Count 1 /Type /Pages /MediaBox [ -195 -442 400 400 ] >> endobj 1 0 obj << /Pages 2 0 R /Type /Catalog >> endobj trailer << /Root 1 0 R > %%EOF
courtesy of Thomas see Create Memorystream of type pdf and return to browser
If you are "Hand balling" with UTF 16 chars on a "small device" it becomes a step harder see https://stackoverflow.com/a/68442444/10802527
More useful to producing your own many RaspberryPi users Compile PDF via MuTool Create https://mupdf.com/docs/manual-mutool-create.html
The Input Text to be translated during compilation is much simpler especially for image handling
%%MediaBox 0 0 612 792
%%Font TmRm Times-Roman
%%Font Helv-C Helvetica Cyrillic
%%Font Helv-G Helvetica Greek
%%Image I0 logo/ClientLogo.png
% Draw the image.
q
480 0 0 480 50 250 cm
/I0 Do
Q
% Draw a triangle. (Can be rectangles or a grid etc)
q
1 0 0 rg
50 50 m
100 200 l
200 50 l
f
Q
% Show some text. (Remember we humans work downwards, so 50 in then 760,730,700, etc. downwards)
q
0 0 1 rg
BT /TmRm 24 Tf 50 760 Td (Hello, from EPS32!) Tj ET
BT /Helv-C 24 Tf 50 730 Td <fac4d2c1d7d3d4d7d5cad4c521> Tj ET
BT /Helv-G 24 Tf 50 700 Td ( I am Line 3) Tj ET
Q
I found a solution with the Software PDFEdit.
http://pdfedit.cz/en/pdfedit_windows.html
There is an option called Decode in the Debug Section, it generates a .decode file wich i then opened with NotePad, i was able to get a readeable, modifiable code(modifiable in the parts that i needed, such as Dates,Hour Names, Temperatures, Routes, etc).
You can try it and modify some text, then save it as a .pdf and you will be able to se the changes.
Evidence:
Original Document unmodified
"Source Code" viewed in NotePad
after changing some text i saved it as .pdf and saw the changes i wanted.
[Documen modified with NotePad3
The code is really extensive(5000 lines) but maybe i can generate some really simple template and reduce this lines. Thanks To everyone!
Localhost is fine but when uploaded to server not working
My Code
public function printSalesRecord()
{
$setPaperSize = 'A4';
$pdf = App::make('dompdf');
$pdf = PDF::loadView('salesrecord/PrintSalesRecord')->setPaper($setPaperSize)->setOrientation('portraite');
return $pdf->stream();
}
This is what i get on my browser
%PDF-1.3 1 0 obj << /Type /Catalog /Outlines 2 0 R /Pages 3 0 R >> endobj 2 0 obj << /Type /Outlines /Count 0 >> endobj 3 0 obj << /Type /Pages /Kids [6 0 R ] /Count 1 /Resources << /ProcSet 4 0 R /Font << /F1 8 0 R >> >> /MediaBox [0.000 0.000 595.280 841.890] >> endobj 4 0 obj [/PDF /Text ] endobj 5 0 obj << /Creator (DOMPDF) /CreationDate (D:20161122092040+00'00') /ModDate (D:20161122092040+00'00') >> endobj 6 0 obj << /Type /Page /Parent 3 0 R /Contents 7 0 R >> endobj 7 0 obj << /Filter /FlateDecode /Length 73 >> stream x��2�300P#&�ҹ�B�M���-L�L�,BR����B��5JR�K�Drr�f�B���k��� endstream endobj 8 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >> endobj xref 0 9 0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000274 00000 n 0000000303 00000 n 0000000417 00000 n 0000000480 00000 n 0000000624 00000 n trailer << /Size 9 /Root 1 0 R /Info 5 0 R >> startxref 733 %%EOF
Please double check for vendor:publish
It's look like your pdf may contain utf-8 character.
Tip: UTF-8 support
You need to add this in your template file if you want to have support for UTF-8
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
Another possibility;
Can you change font directory from /BaseFont/dompdf/lib/fonts/Times-Roman to /BaseFont/Times-Roman?
Had the same problem, add this at the end of the script or function:
exit();
Try adding response header to your Laravel code
Response::header('Content-type', 'application/pdf');
Or just add .pdf extension to your route .
Or use download() function instead of stream()
Add support for UTF-8 in the file you are loading. Here is a sample code that worked for me
$checkedProducts = $request->input('products');
$pdf = App::make( 'dompdf.wrapper' );
$html ='<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"</head><body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Dashboard</div>
<div class="panel-body">
<table class="table">
<thead>
<th>Product Name</th>
</thead>
<tbody>';
for($i = 0; $i<count($checkedProducts); $i++){
$products = DB::table('products')->where('id', $checkedProducts[$i] )->value('name');
$html.= '<tr><td>'. $products .'</td></tr>';
}
$html.= '</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html> ';
$pdf->loadHTML($html);
return $pdf->download( 'quote.pdf' );
}
I had loaded the PDF file without the html tags and got the same problem as yours. I added them and also added the meta tag with UTF-8 support and worked fine.
Using NSPrintOperation, How Do I correctly Create a PDF file from text in an NSView?
*
* NOTICE I FOUND A WORKAROUND, WHICH IS SHOWN AT THE BOTTOM
*
What I have done:
1. Put text into an 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 to ADD THE TEXT
[[_printView textStorage] beginEditing];
// Set the attributes for the title
[[_printView textStorage] beginEditing];
titleAttr =
[NSDictionary dictionaryWithObject:[(AppDelegate*)[[NSApplication sharedApplication] delegate] tableFont] forKey:NSFontAttributeName];
// Add the title
[
[_printView textStorage] appendAttributedString:
[[NSAttributedString alloc] initWithString:[recipe name] attributes:titleAttr ]
];
// Create a couple returns between the title and the body
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
// Add the body text
if([[recipe ingredients] length] )
[[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
initWithString:[recipe ingredients] attributes:titleAttr]];
// Create a couple returns between the ingredients and the directions
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
if([[recipe directions] length] )
[[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
initWithString:[recipe directions] attributes:titleAttr]];
// Create a couple returns between the directions and the comments
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:#"\n\n"]];
if([[recipe comments] length] )
[[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
initWithString:[recipe comments] attributes:titleAttr]];
// Center the title
[_printView setAlignment:NSCenterTextAlignment range:NSMakeRange(0, [[recipe name] length])];
[[_printView textStorage] endEditing];
return _printView;
} // end printableViewForRecipe
2.Try to Create a PDF file from the TextView's Text using the 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 the 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 this 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 a PDF to be created at: poTempfileURL where it 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 the following line of code runs:
BOOL didRunOK = [printOp runOperation];//7
The contents of printInfo for the 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 the text below labeled :
/// BEGIN NSTextView TEXT ///
In Finder when I open the file located at poTempFileURL,
in Preview, the file has four pages (it should have only one page),
and appears to be an empty PDF file in Preview.
When I open this same "PDF" file in TextEdit, the file contains the
content below which is labelled : /// BEGIN TEXT PDF Tempfile ///
What do I need to do to produce a "proper" PDF file? I can not get a PDF that I can open and 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 to a bowl and beat with a fork.
2. Add milk and cinnamon to egg and beat briefly.
3. Heat heavy skillet to medium high. Add 2 tsp butter.
4. Dip bread slice halves in batter and brown in skillet. Flip and add additional butter. Brown and serve with syrup.
Serve with 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 I redo the method exportPDFfromView: fileNumber: this 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 I view the resultant PDF file at URL poTempfileURL, it has one page, which is correct. But again the PDF
shows no text in Preview. If I view this "PDF" with TextEdit, the contents are 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 a workaround that will get me where I want to go. This still does not explain to me why all my seemingly endless attempts to use
+ (NSPrintOperation *)printOperationWithView:(NSView *)aView
printInfo:(NSPrintInfo *)aPrintInfo
fail.
The workaround produces multipage PDF files that can be viewed in Preview.
I do hope this is useful to others.
- (void)testQuartz:(NSData *)pdfDocumentData savePath:(NSString*)savePath
{
//Create the pdf document reference
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFDataRef)pdfDocumentData);
CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(dataProvider);
//Create the pdf context
CGPDFPageRef page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 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 the page onto the new context
//page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 1
CGPDFContextBeginPage(pdfContext, NULL);
CGContextDrawPDFPage(pdfContext, page);
CGPDFContextEndPage(pdfContext);
}
else
{
NSLog(#"Failed to create the document");
}
CGContextRelease(pdfContext); //Release before writing data to disk.
//Write to disk
[(__bridge NSData *)mutableData writeToFile:savePath atomically:YES];
//Clean up
CGDataProviderRelease(dataProvider); //Release the 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 you are like me and want to publish a single PDF, with say essays, all beginning at the top of a page in the single PDF, you will probably want something like the following to take pages out of temporary input documents and move them all into the single output PDF.
NSUInteger pageCountDocZero = [[inputDocuments objectAtIndex:0] pageCount];
NSUInteger pageIndex = pageCountDocZero;
for (PDFDocument *document in inputDocuments) {
for (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++];
}
}
Initially the question was about making a pdf signature visible with Ruby. That i can do now with the code below.
My only problem now is with the validity icon. It shows up on FoxIt Reader, but not on Acrobat Reader (i'm using XI right now)
This is what I have right now
require 'openssl'
begin
require 'origami'
rescue LoadError
ORIGAMIDIR = "C:\RailsInstaller\Ruby1.9.3\lib\ruby\gems\1.9.1\gems\origami-1.2.4\lib"
$: << ORIGAMIDIR
require 'origami'
end
include Origami
def draw_signature(name, attr = {})
load! if #instructions.nil?
x, y = attr[:x], attr[:y]
#instructions << PDF::Instruction.new('q')
#instructions << PDF::Instruction.new('cm', 1, 0, 0, 1, x, y)
#instructions << PDF::Instruction.new('Do', name)
#instructions << PDF::Instruction.new('Q')
end
def SignPdf(inputF)
#inputfile = String.new(inputF)
outputF = #inputfile.insert(inputF.rindex("."),"_signed8")
certFile = "cert.pem"
rsakeyFile = "pk.pem"
passphrase = "mypass"
key4pem=File.read rsakeyFile
key = OpenSSL::PKey::RSA.new key4pem, passphrase
cert = OpenSSL::X509::Certificate.new(File.read certFile)
pdf = PDF.read(inputF)
page = pdf.get_page(1)
#signature image
imageobject = Origami::Graphics::ImageXObject.from_image_file('c:\rails_projects\RecibosOnline\app\assets\images\logo.jpg', 'jpg')
imageobject.Width = 200
imageobject.Height = 141
#formobject = Origami::Graphics::FormXObject.new
#formobject.write("Teste")
width = 300
height=141
x=201
y=186
signedby = "My Company"
location = "Portugal"#pdf.signature[pdf.signature.keys[5]]
contact = "mail#mail.com" #pdf.signature[pdf.signature.keys[6]]
reason = "Testing" #pdf.signature[pdf.signature.keys[7]]
date = Time.now
caption="Digitally Signed By: #{signedby}\nContact: #{contact}\nLocation: #{location}\nReason: #{reason}\nDate: #{date} "
n0 = Annotation::AppearanceStream.new
n0.Type=Origami::Name.new("XObject")
n0.BBox = [ 0, 0, 100, 100 ]
n0.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n0.set_indirect(true)
n0.Resources = Resources.new
n0.Resources.ProcSet = [Origami::Name.new("PDF"),Origami::Name.new("Text"),Origami::Name.new("Text"),Origami::Name.new("ImageB"),Origami::Name.new("ImageC"),Origami::Name.new("ImageI")]
n0.draw_stream('% DSBlank')
#n0.write(Origami::Name.new("% DSBlank"))
n2 = Annotation::AppearanceStream.new
n2.Type = Origami::Name.new("XObject")
#n2.Subtype = Origami::Name.new("Form")
n2.Resources = Resources.new
n2.Resources.ProcSet = [Origami::Name.new("Text")]
n2.set_indirect(true)
n2.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n2.BBox = [ 0, 0, width, height ]
n2.write(caption,:x => 40, :y => height-35, :size => 15)
#n2.draw_stream("q 0 0 198 48 re W n BT /Helv 7.645 Tf 0 g 0 40.135 Td (Digitally ) Tj 28.889 0 Td (signed ) Tj 24.652 0 Td (by ) Tj10.198 0 Td (James ) Tj 24.641 0 Td (Pravetz ) Tj-88.38 -9.174 Td (DN: ) Tj 15.29 0 Td (cn=James ) Tj37.18 0 Td (Pravetz, ) Tj 30.165 0 Td (c=CA, ) Tj 23.156 0 Td0 -9.174 Td (Reason: ) Tj 30.599 0 Td (I ) Tj 4.248 0 Td(have ) Tj 18.702 0 Td (reviewed ) Tj 32.719 0 Td(this ) Tj 14.02 0 Td (document ) Tj -100.288 -9.174 Td(Date: ) Tj 20.397 0 Td (2006.06.08 ) Tj 40.386 0 Td(13:39:35 ) Tj 31.883 0 Td (-07'00') Tj ET Q")
#Sets the root dictionary element
frm = Annotation::AppearanceStream.new
frm.set_indirect(true)
#frm.Type = Origami::Name.new("XObject")
#frm.Subtype = Origami::Name.new("Form")
frm.Resources = Resources.new
frm.Resources.ProcSet = [Origami::Name.new("PDF")]
frm.Resources.add_xobject(Origami::Name.new("n0"), n0)
frm.Resources.add_xobject(Origami::Name.new("n2"), n2)
frm.Matrix = [ 1, 0, 0, 1, 0, 0 ]
frm.BBox = [ 0, 0, width, height ]
frm.draw_stream('q 1 0 0 1 0 0 cm /n0 Do Q')
frm.draw_stream('q 1 0 0 1 0 0 cm /n2 Do Q')
xo17 = Annotation::Widget::Signature.new
#xo17 = Annotation::Widget::Signature.new
xo17.Rect = Rectangle[ llx: x, lly: y, urx: x+width, ury: y+height ]
#xo17.Resources = Resources.new
#xo17.Resources.add_xobject(Origami::Name.new("FRM"), frm)
xo17.F = Annotation::Flags::PRINT #sets the print mode on
xo17.H = Annotation::Widget::Highlight::INVERT
streamN = Annotation::AppearanceStream.new #.setFilter(:FlateDecode)
streamN.set_indirect(true)
streamN.BBox = [ 0, 0, width, height ]
streamN.Resources = Resources.new
streamN.Resources.ProcSet = [Origami::Name.new("PDF")]
streamN.Resources.add_xobject(Origami::Name.new("FRM"), frm)
streamN.Subtype = nil
#cs = ContentStream.new('q 1 0 0 1 0 0 cm /FRM Do Q',streamN)
streamN.draw_stream('q 1 0 0 1 0 0 cm /FRM Do Q')
#streamN.draw_image(Origami::Name.new("FRM"),{x:x,y:y})
#streamN.write(caption,:x => 40, :y => height-35, :size => 15)
xo17.set_normal_appearance(streamN)
# page.add_xobject(Origami::Name.new("FRM"),frm)
# page.add_xobject(Origami::Name.new("n0"),n0)
# page.add_xobject(Origami::Name.new("n2"),n2)
page.add_annot(xo17)
# Sign the PDF with the specified keys
pdf.sign(cert, key,
:method => 'adbe.pkcs7.sha1',
:annotation => xo17,
:location => location,
:contact => contact,
:reason => reason
)
# Save the resulting file
pdf.save(outputF)
end
SignPdf("Sample.pdf")
EDIT 2
Following mkl intervention, i went a little further into the source...
I noticed the xobject.rb file, with the following code for drawing an image
def draw_image(name, attr = {})
load! if #instructions.nil?
x, y = attr[:x], attr[:y]
#instructions << PDF::Instruction.new('q')
#instructions << PDF::Instruction.new('cm', 300, 0, 0, 300, x, y)
#instructions << PDF::Instruction.new('Do', name)
#instructions << PDF::Instruction.new('Q')
end
I have then created the method below on that same file
def draw_stream(name)
load! if #instructions.nil?
#instructions << PDF::Instruction.new(name)
end
which allows me to control the stream from its input.
I also went to ISO32000:2008, and iterated a bit thorugh my code, but got nowhere further.
Here is my currently generated pdf file , and the part of it that relates to signatures:
16 0 obj
<<
/Rect [ 201 186 501 327 ]
/F 4
/H /I
/AP <<
/N 18 0 R
>>
/P 1 0 R
/V 17 0 R
/T (undef28504)
/Subtype /Widget
/FT /Sig
/DA (/F1 10 Tf 0 g)
>>
endobj
17 0 obj
<<
/Type /Sig
/SubFilter /adbe.pkcs7.sha1
/Reason <54657374696E67>
/Prop_Build <<
/Filter <<
/Name /Adobe.PPKMS
/R 131101
/Date (2013-04-03 14:18:41 +0100)
>>
/SigQ <<
/Preview false
/R 131101
>>
/PubSec <<
/NonEFontNoWarn false
/Date (2013-04-03 14:18:41 +0100)
/R 131101
>>
/App <<
/TrustedMode false
/OS [ /Win ]
/R 458752
/Name /Exchange-Pro
>>
>>
/M (D:20130403131841Z00'00)
/Location <506F72747567616C>
/Filter /Adobe.PPKMS
/Contents <308207AE06092A864886F70D010702A082079F3082079B020101310B300906052B0E03021A0500302306092A864886F70D010701A0160414BBA1B7480DDB1B75B136B4DFA2A4C120EC7972DFA0820597308205933082047BA0030201020204426F938C300D06092A864886F70D0101050500303E310B300906035504061302707431153013060355040A130C4D554C5449434552542D4341311830160603550403130F4D554C5449434552542D4341203032301E170D3133303332303137303134375A170D3134303332303136343733365A3081A5310B300906035504061302505431153013060355040A130C4D554C5449434552542D434131163014060355040B130D4345525449504F52202D20524131123010060355040B1309436F72706F726174653120301E060355040B13174553435249544120494E54454C4947454E5445204C444131183016060355040B130F576562204170706C69636174696F6E311730150603550403130E52454349424F53204F4E4C494E4530819F300D06092A864886F70D010101050003818D0030818902818100ACCEA4069031B578896C450D77C83C13DD75C668BF2762368DB0A0B1591B1800E58C1ACDBB25DA15501AF931F9F6BAE0F8F64C481686E959DE005AEC82B33D0D32665037D18BF36BF77C4D56620C42FBBA92D3FF397F9D8377FEABBA93478FCEF009216483D346ACCC76CA10C9B8653B80B8F6EB49BD93897A43DF062D0D9ED30203010001A38202B3308202AF300B0603551D0F0404030203F8303806082B06010505070101042C302A302806082B06010505073001861C687474703A2F2F6F6373702E6D756C7469636572742E636F6D2F63613081E00603551D200481D83081D5304D06092B06010401B03C0A023040303E06082B060105050702011632687474703A2F2F7777772E6D756C7469636572742E636F6D2F6370732F6D756C7469636572742D63612D6370732E68746D6C308183060B2B06010401B03C0A0288063074307206082B0601050507020230661E640068007400740070003A002F002F007700770077002E006D0075006C007400690063006500720074002E0063006F006D002F00630070002F006D0075006C007400690063006500720074002D00630061002D0031003000330030002E00680074006D006C301106096086480186F84201010404030204B030200603551D11041930178115696E666F4072656369626F736F6E6C696E652E7074308201010603551D1F0481F93081F630819AA08197A08194862F687474703A2F2F7777772E6D756C7469636572742E636F6D2F63612F6D756C7469636572742D63612D30322E63726C86616C6461703A2F2F6C6461702E6D756C7469636572742E636F6D2F636E3D4D554C5449434552542D434125323030322C6F3D4D554C5449434552542D43412C633D50543F63657274696669636174655265766F636174696F6E4C6973743F626173653057A055A053A451304F310B300906035504061302707431153013060355040A130C4D554C5449434552542D4341311830160603550403130F4D554C5449434552542D4341203032310F300D0603550403130643524C323935301F0603551D230418301680141DC3B988A518BE60A72CA663CA662AFC0C27C1BD301D0603551D0E0416041406D81F7236619EEB17369C299E2D74FFD038301930090603551D1304023000300D06092A864886F70D0101050500038201010041511FCD5C7561981B0D54326B57F7B87C435AACB7A2962808768313892AB1407237E957577B875414DE810A41323F9E0A768E9AC45C0F66AE093C32C11453C6463F856FEF62E27821134DD09F75208000040E89A814E6309623C5D04163C03CFDE33153908AC3DFCA5B1C66C3DCB89644A3030FE794D50BD255D396535A7AF267C3A538147B9371D05F23D8CA481AEBC7D7A7D97C2E7FB5AB49C4E4554E4800648BC76B1AF5612A1D9361D172084E70690928A911FC209833C506219CF186B6507B599E4C0F42F3BF23C2B8F0A078D01D9BF5FD4746D97253EE4FE8F472489B3DC26F7072C6587218825BB3061074B9C240F8928D36FEFC0F708897752CD946318201C7308201C30201013046303E310B300906035504061302707431153013060355040A130C4D554C5449434552542D4341311830160603550403130F4D554C5449434552542D43412030320204426F938C300906052B0E03021A0500A081D8301806092A864886F70D010903310B06092A864886F70D010701301C06092A864886F70D010905310F170D3133303430333133313834315A302306092A864886F70D010904311604142948A25663C43F9571225B0F12B9097DFE7149DB307906092A864886F70D01090F316C306A300B060960864801650304012A300B0609608648016503040116300B0609608648016503040102300A06082A864886F70D0307300E06082A864886F70D030202020080300D06082A864886F70D0302020140300706052B0E030207300D06082A864886F70D0302020128300D06092A864886F70D010101050004818021F8A3A104E8B6EC1D9026CA9A822C4357EEBAABD5D87422BE6199802F45E83E9D2417711CE26DCB28A8246ACE119B128956394A8FA641346E5F3CBBDD84ED7E36B2F947DD5D92EC1C2C078A1630A729773F17027FC3B64C18844C26F7FA18A7B4FC9DE334741235E178280ED25CD8840A83A91FCE240646EB84117E348BF82E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>
/ContactInfo <6D61696C406D61696C2E636F6D>
/ByteRange [ 0 12880 17078 2366 ]
>>
endobj
18 0 obj
<<
/BBox [ 0 0 300 141 ]
/Resources <<
/ProcSet [ /PDF ]
/XObject <<
/FRM 19 0 R
>>
/Font <<
/F1 <<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
/Name /F1
>>
>>
>>
/Length 27
/Subtype /Form
>>stream
q 1 0 0 1 0 0 cm /FRM Do Q
endstream
endobj
19 0 obj
<<
/Resources <<
/ProcSet [ /PDF ]
/XObject <<
/n0 20 0 R
/n2 21 0 R
>>
/Font <<
/F1 <<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
/Name /F1
>>
>>
>>
/Matrix [ 1 0 0 1 0 0 ]
/BBox [ 0 0 300 141 ]
/Length 52
/Subtype /Form
>>stream
q 1 0 0 1 0 0 cm /n0 Do Q
q 1 0 0 1 0 0 cm /n2 Do Q
endstream
endobj
20 0 obj
<<
/Type /XObject
/BBox [ 0 0 100 100 ]
/Matrix [ 1 0 0 1 0 0 ]
/Resources <<
/ProcSet [ /PDF /Text /Text /ImageB /ImageC /ImageI ]
/Font <<
/F1 <<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
/Name /F1
>>
>>
>>
/Length 10
/Subtype /Form
>>stream
% DSBlank
endstream
endobj
21 0 obj
<<
/Type /XObject
/Resources <<
/ProcSet [ /Text ]
/Font <<
/F1 <<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
/Name /F1
>>
>>
>>
/Matrix [ 1 0 0 1 0 0 ]
/BBox [ 0 0 300 141 ]
/Length 176
/Subtype /Form
>>stream
BT
/F1 15 Tf
40 106 Td
20 TL
(Digitally Signed By: My Company) Tj
(Contact: mail#mail.com) '
(Location: Portugal) '
(Reason: Testing) '
(Date: 2013-04-03 14:18:41 +0100 ) '
ET
endstream
endobj
22 0 obj
<<
/Fields [ 16 0 R ]
/SigFlags 3
>>
endobj
What am I missing?
Sometimes, a man just need to know how to actually understand what he reads over and over again...
The ppkappearances file had it all there. I didn't even went as far as I expected i would have with complying with the dictionary structure they recommend there.
I just needed to add the n1 and n3 layers, and the stream content could even be just "% DS Blank". the question mark string stream you find was the one i took from PdfSignatureAppearance.cs file from iText solution. If I use that one Foxit Reader presents the question mark (even if the signature is valid). For Adobe it doesn't matter i use that or DSBlank.
require 'openssl'
begin
require 'origami'
rescue LoadError
ORIGAMIDIR = "C:\RailsInstaller\Ruby1.9.3\lib\ruby\gems\1.9.1\gems\origami-1.2.4\lib"
$: << ORIGAMIDIR
require 'origami'
end
include Origami
def draw_signature(name, attr = {})
load! if #instructions.nil?
x, y = attr[:x], attr[:y]
#instructions << PDF::Instruction.new('q')
#instructions << PDF::Instruction.new('cm', 1, 0, 0, 1, x, y)
#instructions << PDF::Instruction.new('Do', name)
#instructions << PDF::Instruction.new('Q')
end
def SignPdf(inputF)
#inputfile = String.new(inputF)
outputF = #inputfile.insert(inputF.rindex("."),"_signed8")
certFile = "cert.pem"
rsakeyFile = "pk.pem"
passphrase = "mypass"
key4pem=File.read rsakeyFile
key = OpenSSL::PKey::RSA.new key4pem, passphrase
cert = OpenSSL::X509::Certificate.new(File.read certFile)
pdf = PDF.read(inputF)
page = pdf.get_page(1)
#signature image
imageobject = Origami::Graphics::ImageXObject.from_image_file('c:\rails_projects\RecibosOnline\app\assets\images\logo.jpg', 'jpg')
imageobject.Width = 200
imageobject.Height = 141
#formobject = Origami::Graphics::FormXObject.new
#formobject.write("Teste")
width = 300
height=141
x=201
y=186
signedby = "My Company"
location = "Portugal"#pdf.signature[pdf.signature.keys[5]]
contact = "mail#mail.com" #pdf.signature[pdf.signature.keys[6]]
reason = "Testing" #pdf.signature[pdf.signature.keys[7]]
date = Time.now
caption="Digitally Signed By: #{signedby}\nContact: #{contact}\nLocation: #{location}\nReason: #{reason}\nDate: #{date} "
#DSBlankstream= "% DSBLank"
questionMark = "% DSUnknown\n" +
"q\n" +
"1 G\n" +
"1 g\n" +
"0.1 0 0 0.1 9 0 cm\n" +
"0 J 0 j 4 M []0 d\n" +
"1 i \n" +
"0 g\n" +
"313 292 m\n" +
"313 404 325 453 432 529 c\n" +
"478 561 504 597 504 645 c\n" +
"504 736 440 760 391 760 c\n" +
"286 760 271 681 265 626 c\n" +
"265 625 l\n" +
"100 625 l\n" +
"100 828 253 898 381 898 c\n" +
"451 898 679 878 679 650 c\n" +
"679 555 628 499 538 435 c\n" +
"488 399 467 376 467 292 c\n" +
"313 292 l\n" +
"h\n" +
"308 214 170 -164 re\n" +
"f\n" +
"0.44 G\n" +
"1.2 w\n" +
"1 1 0.4 rg\n" +
"287 318 m\n" +
"287 430 299 479 406 555 c\n" +
"451 587 478 623 478 671 c\n" +
"478 762 414 786 365 786 c\n" +
"260 786 245 707 239 652 c\n" +
"239 651 l\n" +
"74 651 l\n" +
"74 854 227 924 355 924 c\n" +
"425 924 653 904 653 676 c\n" +
"653 581 602 525 512 461 c\n" +
"462 425 441 402 441 318 c\n" +
"287 318 l\n" +
"h\n" +
"282 240 170 -164 re\n" +
"B\n" +
"Q\n";
n0 = Annotation::AppearanceStream.new
n0.Type=Origami::Name.new("XObject")
n0.BBox = [ 0, 0, 100, 100 ]
n0.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n0.set_indirect(true)
n0.Resources = Resources.new
n0.Resources.ProcSet = [Origami::Name.new("PDF"),Origami::Name.new("Text"),Origami::Name.new("Text"),Origami::Name.new("ImageB"),Origami::Name.new("ImageC"),Origami::Name.new("ImageI")]
n0.draw_stream('% DSBlank')
#n0.write(Origami::Name.new("% DSBlank"))
n1 = Annotation::AppearanceStream.new
n1.Type=Origami::Name.new("XObject")
n1.BBox = [ 0, 0, 100, 100 ]
n1.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n1.set_indirect(true)
n1.Resources = Resources.new
n1.Resources.ProcSet = [Origami::Name.new("PDF"),Origami::Name.new("Text"),Origami::Name.new("Text"),Origami::Name.new("ImageB"),Origami::Name.new("ImageC"),Origami::Name.new("ImageI")]
n1.draw_stream('% DSBlank')
n3 = Annotation::AppearanceStream.new
n3.Type=Origami::Name.new("XObject")
n3.BBox = [ 0, 0, 100, 100 ]
n3.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n3.set_indirect(true)
n3.Resources = Resources.new
n3.Resources.ProcSet = [Origami::Name.new("PDF"),Origami::Name.new("Text"),Origami::Name.new("Text"),Origami::Name.new("ImageB"),Origami::Name.new("ImageC"),Origami::Name.new("ImageI")]
n3.draw_stream('% DSBlank')
n2 = Annotation::AppearanceStream.new
n2.Type = Origami::Name.new("XObject")
#n2.Subtype = Origami::Name.new("Form")
n2.Resources = Resources.new
n2.Resources.ProcSet = [Origami::Name.new("Text")]
n2.set_indirect(true)
n2.Matrix = [ 1, 0, 0, 1, 0, 0 ]
n2.BBox = [ 0, 0, width, height ]
n2.write(caption,:x => 40, :y => height-35, :size => 15)
#n2.draw_stream("q 0 0 198 48 re W n BT /Helv 7.645 Tf 0 g 0 40.135 Td (Digitally ) Tj 28.889 0 Td (signed ) Tj 24.652 0 Td (by ) Tj10.198 0 Td (James ) Tj 24.641 0 Td (Pravetz ) Tj-88.38 -9.174 Td (DN: ) Tj 15.29 0 Td (cn=James ) Tj37.18 0 Td (Pravetz, ) Tj 30.165 0 Td (c=CA, ) Tj 23.156 0 Td0 -9.174 Td (Reason: ) Tj 30.599 0 Td (I ) Tj 4.248 0 Td(have ) Tj 18.702 0 Td (reviewed ) Tj 32.719 0 Td(this ) Tj 14.02 0 Td (document ) Tj -100.288 -9.174 Td(Date: ) Tj 20.397 0 Td (2006.06.08 ) Tj 40.386 0 Td(13:39:35 ) Tj 31.883 0 Td (-07'00') Tj ET Q")
##Sets the root dictionary element
frm = Annotation::AppearanceStream.new
frm.set_indirect(true)
#frm.Type = Origami::Name.new("XObject")
#frm.Subtype = Origami::Name.new("Form")
frm.Resources = Resources.new
frm.Resources.ProcSet = [Origami::Name.new("PDF")]
frm.Resources.add_xobject(Origami::Name.new("n0"), n0)
frm.Resources.add_xobject(Origami::Name.new("n1"), n1)
frm.Resources.add_xobject(Origami::Name.new("n2"), n2)
frm.Resources.add_xobject(Origami::Name.new("n3"), n3)
frm.Matrix = [ 1, 0, 0, 1, 0, 0 ]
frm.BBox = [ 0, 0, width, height ]
frm.draw_stream('q 1 0 0 1 0 0 cm /n0 Do Q')
frm.draw_stream('q 1 0 0 1 0 0 cm /n1 Do Q')
frm.draw_stream('q 1 0 0 1 0 0 cm /n2 Do Q')
frm.draw_stream('q 1 0 0 1 0 0 cm /n3 Do Q')
xo17 = Annotation::Widget::Signature.new
#xo17 = Annotation::Widget::Signature.new
xo17.Rect = Rectangle[ llx: x, lly: y, urx: x+width, ury: y+height ]
#xo17.Resources = Resources.new
#xo17.Resources.add_xobject(Origami::Name.new("FRM"), frm)
xo17.F = Annotation::Flags::PRINT #sets the print mode on
xo17.H = Annotation::Widget::Highlight::INVERT
streamN = Annotation::AppearanceStream.new #.setFilter(:FlateDecode)
streamN.set_indirect(true)
streamN.BBox = [ 0, 0, width, height ]
streamN.Resources = Resources.new
streamN.Resources.ProcSet = [Origami::Name.new("PDF")]
streamN.Resources.add_xobject(Origami::Name.new("FRM"), frm)
streamN.Subtype = nil
#cs = ContentStream.new('q 1 0 0 1 0 0 cm /FRM Do Q',streamN)
streamN.draw_stream('q 1 0 0 1 0 0 cm /FRM Do Q')
#streamN.draw_image(Origami::Name.new("FRM"),{x:x,y:y})
#streamN.write(caption,:x => 40, :y => height-35, :size => 15)
xo17.set_normal_appearance(streamN)
# page.add_xobject(Origami::Name.new("FRM"),frm)
# page.add_xobject(Origami::Name.new("n0"),n0)
# page.add_xobject(Origami::Name.new("n2"),n2)
page.add_annot(xo17)
# Sign the PDF with the specified keys
pdf.sign(cert, key,
:method => 'adbe.pkcs7.sha1',
:annotation => xo17,
:location => location,
:contact => contact,
:reason => reason
)
# Save the resulting file
pdf.save(outputF)
end
SignPdf("Sample.pdf")
What a fight!
I feel like saying :
In the end, the winners are the ones that you will find standing in the middle of the battle field. Sadly looking around them into the battle field, and wondering why it had to be like that. Only if they knew how to read...then nothing of that would have happened. At the same time though, if it wouldn't have happened, they wouldn't know they didn't know how to read with the right focus.