Understanding TextPosition getTextMatrix() method in pdfBox 2.0.3 - pdfbox

I am trying to discover the character positioning inside the pdf pages. I have implemented a class TextPosition which extends PDFTextStripper, and I have used setSortByPosition(true) to arrange the charactersByArticle according to page structure. I have a pdf (here is the link, refer to page 10) in which I have both landscape and potrait characters. My TextPosition class has all the sorted characters at every page. Now when I see page 10, The landscape characters come after the potrait characters order. Here is the code:
public static void main( String[] args ) throws IOException
{
TextExtractor textExtractor = new TextExtractor("C:\\Users\\prabhjot.rai\\Desktop\\Demo\\sbet201601.pdf");
PDFPage page = textExtractor.getPages().get(10);
for (List<TextPosition> article: page.getCharactersByArticle()) {
for (TextPosition text: article) {
System.out.print(text.getUnicode() + " ");
System.out.print(text.getX() + " ");
System.out.print(text.getTextMatrix() + " ");
System.out.println();
}
}
}
And here is the last lines of page 10 output:
1 406.46 [7.787,0.0,0.0,7.7706,406.46,64.9355]
4 410.64938 [7.787,0.0,0.0,7.7706,410.64938,64.9355]
Y 250.9882 [7.787,0.0,0.0,7.7706,250.9882,46.5761]
E 256.3768 [7.787,0.0,0.0,7.7706,256.3768,46.5761]
A 261.7654 [7.787,0.0,0.0,7.7706,261.7654,46.5761]
R 267.15402 [7.787,0.0,0.0,7.7706,267.15402,46.5761]
P 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,118.1203]
e 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,123.499886]
r 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,127.680466]
c 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,130.07147]
e 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,134.25516]
n 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,138.43575]
t 94.1495 [0.0,7.7706,-7.787,0.0,94.1495,142.61633]
9 486.465 [0.0,7.98,-7.98,0.0,486.465,37.2]
486.465 [0.0,7.98,-7.98,0.0,486.465,41.220325]
486.465 [0.0,7.98,-7.98,0.0,486.465,43.199364]
| 486.465 [0.0,7.98,-7.98,0.0,486.465,45.178402]
486.465 [0.0,7.98,-7.98,0.0,486.465,46.678642]
486.465 [0.0,7.98,-7.98,0.0,486.465,48.838825]
N 486.465 [0.0,7.98,-7.98,0.0,486.465,50.817863]
F 486.465 [0.0,7.98,-7.98,0.0,486.465,56.579422]
I 486.465 [0.0,7.98,-7.98,0.0,486.465,61.016304]
B 486.465 [0.0,7.98,-7.98,0.0,486.465,63.65609]
486.465 [0.0,7.98,-7.98,0.0,486.465,68.99631]
S 486.465 [0.0,7.98,-7.98,0.0,486.465,71.09585]
m 486.465 [0.0,7.98,-7.98,0.0,486.465,75.53273]
a 486.465 [0.0,7.98,-7.98,0.0,486.465,81.59274]
l 486.465 [0.0,7.98,-7.98,0.0,486.465,85.135864]
l 486.465 [0.0,7.98,-7.98,0.0,486.465,87.3543]
486.465 [0.0,7.98,-7.98,0.0,486.465,89.57274]
B 486.465 [0.0,7.98,-7.98,0.0,486.465,91.79278]
u 486.465 [0.0,7.98,-7.98,0.0,486.465,97.132996]
s 486.465 [0.0,7.98,-7.98,0.0,486.465,101.15252]
i 486.465 [0.0,7.98,-7.98,0.0,486.465,104.2727]
n 486.465 [0.0,7.98,-7.98,0.0,486.465,106.491135]
e 486.465 [0.0,7.98,-7.98,0.0,486.465,110.51146]
s 486.465 [0.0,7.98,-7.98,0.0,486.465,114.05458]
s 486.465 [0.0,7.98,-7.98,0.0,486.465,117.17476]
486.465 [0.0,7.98,-7.98,0.0,486.465,120.294136]
E 486.465 [0.0,7.98,-7.98,0.0,486.465,122.334625]
c 486.465 [0.0,7.98,-7.98,0.0,486.465,127.19444]
o 486.465 [0.0,7.98,-7.98,0.0,486.465,130.73756]
n 486.465 [0.0,7.98,-7.98,0.0,486.465,134.75789]
o 486.465 [0.0,7.98,-7.98,0.0,486.465,138.77742]
m 486.465 [0.0,7.98,-7.98,0.0,486.465,142.79774]
i 486.465 [0.0,7.98,-7.98,0.0,486.465,148.85776]
c 486.465 [0.0,7.98,-7.98,0.0,486.465,151.0762]
486.465 [0.0,7.98,-7.98,0.0,486.465,154.61932]
T 486.465 [0.0,7.98,-7.98,0.0,486.465,156.71886]
r 486.465 [0.0,7.98,-7.98,0.0,486.465,161.57947]
e 486.465 [0.0,7.98,-7.98,0.0,486.465,164.21924]
n 486.465 [0.0,7.98,-7.98,0.0,486.465,167.76236]
d 486.465 [0.0,7.98,-7.98,0.0,486.465,171.78268]
s 486.465 [0.0,7.98,-7.98,0.0,486.465,175.80222]
486.465 [0.0,7.98,-7.98,0.0,486.465,178.9224]
486.465 [0.0,7.98,-7.98,0.0,486.465,180.84238]
486.465 [0.0,7.98,-7.98,0.0,486.465,182.82141]
M 486.465 [0.0,7.98,-7.98,0.0,486.465,184.8]
o 486.465 [0.0,7.98,-7.98,0.0,486.465,191.46011]
n 486.465 [0.0,7.98,-7.98,0.0,486.465,195.48204]
t 486.465 [0.0,7.98,-7.98,0.0,486.465,199.50397]
h 486.465 [0.0,7.98,-7.98,0.0,486.465,201.72401]
l 486.465 [0.0,7.98,-7.98,0.0,486.465,205.74594]
y 486.465 [0.0,7.98,-7.98,0.0,486.465,207.96599]
486.465 [0.0,7.98,-7.98,0.0,486.465,211.50592]
R 486.465 [0.0,7.98,-7.98,0.0,486.465,213.48495]
e 486.465 [0.0,7.98,-7.98,0.0,486.465,218.34477]
p 486.465 [0.0,7.98,-7.98,0.0,486.465,221.8847]
o 486.465 [0.0,7.98,-7.98,0.0,486.465,225.90663]
r 486.465 [0.0,7.98,-7.98,0.0,486.465,229.92856]
t 486.465 [0.0,7.98,-7.98,0.0,486.465,233.04794]
I can definitely see that the getTextMatrix() yields different matrix for both landscape and potrait characters. (Potrait: [7.787,0.0,0.0,7.7706,406.46,64.9355], Landscape: [0.0,7.7706,-7.787,0.0,94.1495,118.1203], landscape starts with zero at first place in matrix). I want to understand the matrix more so that I can make a clear distinction between two types. I referred the documentation but couldn't comprehend much. Can anyone share some article or thoughts on this?

Related

AWK - Adding new line based on text in previous line?

So I have some database table info in a file that looks like this:
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
Basically, I need it to look like this:
2.6 G 7.7 G qabc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G qabc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G qabc-def-ghi_2021-09-21_random_letters_random_numbers
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-wwwdef_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-wwwdef_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-wwwdef_2021-09-28_random_letters_random_numbers
55.1 K 165.3 K jkl-deghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-deghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-deghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-deghi-def_2021-09-26_random_letters_random_numbers
Where there is a new line after the start of each unique table-name prefix. Right now I'm having to do all of this manually for hundreds of table names. Also, if there is a way to count how many times each table name occurs, that would be great too.
Here is the code I got so far #Cyrus:
awk 'BEGIN{FS="[ _]+"} NR==1{last=$(NF-1)} NR>1 && last!=$(NF-1){printf RS} {last=$(NF-1); print}' test2.txt
Here is the output
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
This command works for table names like these:
2.6 G 7.7 G abc-def-ghi_2021-09-19
2.6 G 7.7 G abc-def-ghi_2021-09-20
2.6 G 7.8 G abc-def-ghi_2021-09-21
18.9 G 56.8 G def-abc-def_2021-09-21
110.3 M 331.0 M ghi-abc-def_2021-09-21
110.3 M 331.0 M ghi-abc-def_2021-09-27
110.4 M 331.2 M ghi-abc-def_2021-09-28
55.1 K 165.3 K jkl-ghi-def_2021-09-20
50.7 K 152.1 K jkl-ghi-def_2021-09-24
49.6 K 148.8 K jkl-ghi-def_2021-09-25
48.6 K 138.8 K jkl-ghi-def_2021-09-26
Seems like you can just do:
awk 'last && $5 != last { print count; count=0 } {last = $5; count++ } 1' FS='[ _]*'
eg:
$ cat input
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
$ awk 'last && $5 != last { print count; count=0 } {last = $5; count++ } 1' FS='[ _]*' input
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
3
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
1
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
3
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
$ awk -F'[[:space:]_]+' '(NR>1) && ($5 != prev){print ""} {print; prev=$5}' file
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
$ awk -F'[[:space:]_]+' '(NR>1) && ($5 != prev){print cnt; cnt=0} {print; prev=$5; cnt++} END{if (cnt) print cnt}' file
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
3
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
1
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
3
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
4
The if (cnt) in the END sections is just so you don't print a null string or zero if the input file is empty.
Assumptions:
all input lines have a total of 5 space-delimited fields that look like: #.# {G,K,M} #.# {G,K,M} <table-name-prefix>_YYYY-MM-DD_random_letters_random_numbers
input file has already been sorted by <table-name-prefix>
objective is to add a blank line to the output before we process a line with a new/different <table-name-prefix>
OP mentions keeping track of how many times each unique <table-name-prefix> is seen, but since there's no mention of what to do with said number I'll just print it on the new 'blank' line (for now)
expected output is to look like the 2nd block of data provided in the question (with proviso that <table-name-prefix> counts are placed in the 'blank' lines)
One awk idea:
awk '{ split($5,arr,"_") # split field #5 on "_" delimiter
tabname=arr[1] # grab table name
if (tabname != prevname && prevname != "" ) { # if this is a new table name then ...
printf "%s\n", count # print a new line with a count of the last table name and then ...
count=0
}
print # print current line
count++ # increment count for table name
prevname = tabname # keep track of previous table name
}
END { printf "%s\n", count } # flush last table name count to stdout
' test2.txt
This generates:
2.6 G 7.7 G abc-def-ghi_2021-09-19_random_letters_random_numbers
2.6 G 7.7 G abc-def-ghi_2021-09-20_random_letters_random_numbers
2.6 G 7.8 G abc-def-ghi_2021-09-21_random_letters_random_numbers
3
18.9 G 56.8 G def-abc-def_2021-09-21_random_letters_random_numbers
1
110.3 M 331.0 M ghi-abc-def_2021-09-21_random_letters_random_numbers
110.3 M 331.0 M ghi-abc-def_2021-09-27_random_letters_random_numbers
110.4 M 331.2 M ghi-abc-def_2021-09-28_random_letters_random_numbers
3
55.1 K 165.3 K jkl-ghi-def_2021-09-20_random_letters_random_numbers
50.7 K 152.1 K jkl-ghi-def_2021-09-24_random_letters_random_numbers
49.6 K 148.8 K jkl-ghi-def_2021-09-25_random_letters_random_numbers
48.6 K 138.8 K jkl-ghi-def_2021-09-26_random_letters_random_numbers
4

How to convince the typechecker that the types in the where clause match the toplevel type?

I'm trying to convince the type checker that the type specified in the where clause matches one of the types of the top level function.
For example:
interface SomeInterface (e: Type -> Type) where
label : e l -> l
f : (SomeInterface e) => e l -> c
f x = ?hole_f
where
g : e l
g = ?hole_g
The type of ?hole_g should be e l, but the typechecker is unable to match the l type in g : e l to the l type in the toplevel f : (SomeInterface e) => e l -> c type. So according to the typechecker the type of ?hole_g is e l1
One way to fix this is to include l as a separate type variable in the toplevel function f, like this:
f : (SomeInterface e) => e l -> l -> c
f x _ = ?hole_f
where
g : e l
g = ?hole_g
Notice that the l in the toplevel function is completely neglected due to the _. But the typechecker is now somehow convinced that the type variable of ?hole_g is e l, like the toplevel type.
My two questions are:
1) Why is the typechecker unable to "link" the types of function g to f?
2) How can i fix this without including an extra type variable?
f : (SomeInterface e) => e l -> c
f x {l} = ?hole_f_1
where
g : e l
g = ?hole_g
Does this do what you want? I believe since e l is a type, you can still get the implicit information about the l part.

Edit text in file(UTF16)

I want replace 1 word in text file (file format is not .txt)
file Unicode is (UTF16)
few text example:
I D = " f f 0 3 4 a 9 2 - d d 9 f - 4 3 7 4 - a 8 a d - f 5 5 4 0 0 2 a 4 1 9 b " I S S U E _ D A T E = " 2 0 1 7 - 0 2 - 1 6 T 1 7 : 2 9 : 1 8 . 9 7 0 2 2 9 4 Z " S E Q U E N C E = " 0 " M A N A G I N G _ A P P L I C A T I O N _ T O K E N = " " > < L I C E N S E P U B L I C _ I D = " 3 A A - U J F - 8 K P " U S E R N A M E = " N d a G 6 Z T w u v I X Z B i t h 8 g o d d Q x E r x 0 + O g M c t 0 2 3 f X K O E w = " P A S S W O R D = " F 9 b n 6 b v w l f I 5 Z A 2 t h M h 9 d d s x Q L w = " T Y P E = " T R I A L " F L A G S = " 4 " D I S P L A Y _ N A M E =
I want change T R I A L to other word
It's not too hard to modify your text file. Use the IO class to assign it to a text file, then use String.Replace(oldValue As String, newValue As String) to change your string. Then use IO again to save the string to the file. This should work so long as your file isn't open and being used in another program - regardless of file extensions.
An example, to help you, could be something such as this:
Dim myFileContents as String = IO.File.ReadAllText("Path\To\My\File\File.extension")
myFileContents = myFileContents.Replace("T R I A L", "Some other word")
IO.File.WriteAllText("Path\To\My\File\File.extension", myFileContents)
Modify the contents to suit your situation - however, this is only a basic implementation. Additionally, it is important to note that String.Replace() will change all occurrences of your word to the new word.

Access the page of a .pdf I load (using pdfbox) (and i'm using RPG)

I am trying to modify a .pdf that I load using PDFBOX. I am using RPG and I have found the Java code to access a page from a loaded .pdf
PDPage page = (pdpage)pdDoc.getDocumentCatalog().getallPages().get(0)
The other code I have seen is
List pages = doc.getDocumentCatalog().getAllPages();
PDPage page = (PDPage)pages.get( i );
The problem I am having is translating that code to RPG.
The code I have right now is just to load my .pdf template create a document catalog and create my list and save it (the XLEnvVar is where I'm getting my classpath).
/free
XLSEnvVar();
// Load an existing PDF
myPath = jstring_new('/tmp/PDFtemplate.pdf');
File = File_new(myPath);
myDocument = PDdocument_load(File);
myCatalog = PDDocumentCatalog_new(myDocument);
myList = getAllPages(myCatalog);
// Done with this file, so save it
myFile = jstring_new('/tmp/PDFBox-demo.pdf');
PDDocument_save(myDocument:myFile);
// Close the document object in memory to free all allocated space
PDDocument_close(myDocument);
// Done
*INLR = *On;
/end-free
get prototype
D get...
D PR
D EXTPROC(*JAVA:
D 'java.util.List':
D 'get')
ORIGINAL POST ABOVE
I thought I would post my PDFBOX program so there is another example of using PDFBOX in RPG out here on the interwebs. This is a fully working example (It uses my companies service programs and the SQL is just an example shell so if someone were to use this they would have to change those. But I explained what those service programs are doing so you can use your own companies service programs or write the code to do what those service programs do). Fell free to take this and post it elsewhere just leave the "written by" block. Hope this helps anyone working with PDFBOX.
h/include QCpySrc,HSpecStd
//*****************************************************************
// Written By: Phillip Simmons Date: 05 20, 2013 *
// Special thanks to Spencer (co-worker) *
// and dhanuxp (code400 forums) and *
// http://wiki.midrange.com/index.php/PDFBox *
// for the intial example that I started with. *
// *
// Purpose: Load a pdf template, modify the template *
// then save the modified document. Using PDFBOX * / //*****************************************************************
/Include QCPYSRC,xCommandP
//Service program to return path on IFS
/Include QCPYSRC,GETIFSPTHP
//Service program to return document name
/Include QCPYSRC,GETIFSNAMP
//Service program for document to adopt authority of the
//folder above
/Include qcpysrc,ifsadoptp
//***************************************************************
// Data structure for SQL statement *
//***************************************************************
D Rcd DS qualified
D EMPLID LIKE(EMPLID)
D LNAME 90A VARYING
D ADDR1 LIKE(ADDR1)
D ADDR2 LIKE(ADDR2)
D CSZ 50A VARYING
D SDS
D ProgramName 1 10
//****************************************************************
// Prototypes for PDFBOX *
// Full documentation of PDFBox is available at *
// http://pdfbox.apache.org/index.html *
// Api Docs http://pdfbox.apache.org/apidocs/ *
//****************************************************************
/Copy QSYSINC/QRPGLESRC,JNI
*Classpath
D XLSEnvVar PR extpgm('XLSENVVAR')
*-----------------------------------------------------------------
* Global Constants
D DEFAULT_USERSPACE_UNIT_DPI...
D C 72
* Page sizes in mm
D PAGE_SIZE_A0 S Like(PDRectangle)
D PAGE_SIZE_A1 S Like(PDRectangle)
D PAGE_SIZE_A2 S Like(PDRectangle)
D PAGE_SIZE_A3 S Like(PDRectangle)
D PAGE_SIZE_A4 S Like(PDRectangle)
D PAGE_SIZE_A5 S Like(PDRectangle)
D PAGE_SIZE_A6 S Like(PDRectangle)
D PAGE_SIZE_A0_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A1_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A2_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A3_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A4_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A5_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_SIZE_A6_LANDSCAPE...
D S Like(PDRectangle)
D PAGE_WIDTH_A0 C 841
D PAGE_HEIGHT_A0 C 1189
D PAGE_WIDTH_A1 C 594
D PAGE_HEIGHT_A1 C 841
D PAGE_WIDTH_A2 C 420
D PAGE_HEIGHT_A2 C 594
D PAGE_WIDTH_A3 C 297
D PAGE_HEIGHT_A3 C 420
*210 orginal size
D PAGE_WIDTH_A4 C 216
*297 orginal size
D PAGE_HEIGHT_A4 C 279
D PAGE_WIDTH_A5 C 148
D PAGE_HEIGHT_A5 C 210
D PAGE_WIDTH_A6 C 105
D PAGE_HEIGHT_A6 C 148
*American pages slightly different size than ISO standard
*-----------------------------------------------------------------
* PDRectangle
D PDRectangleClass...
D C 'org.apache.pdfbox.pdmodel.common.PD-
D Rectangle'
D PDRectangle S O CLASS(*JAVA:PDRectangleClass)
* PDRectangle()
D PDRectangle_new...
D PR like(PDRectangle)
D EXTPROC(*JAVA:
D PDRectangleClass:
D *CONSTRUCTOR)
D width like(jfloat) Value
D height like(jfloat) Value
*-----------------------------------------------------------------
*PDDocumentCatalog
D DocumentCatalog...
D S O CLASS(*JAVA :
D PDDocumentCatalogClass)
D PDDocumentCatalogClass...
D C 'org.apache.pdfbox.pdmodel.PDDocumen-
D tCatalog'
D getDocumentCatalog...
D PR O CLASS(*JAVA :
D PDDocumentCatalogClass)
D EXTPROC(*JAVA :
D PDDocumentClass: 'getDocumen+
D tCatalog' )
*
D getAllPages PR O CLASS(*JAVA : 'java.util.List' )
D EXTPROC(*JAVA :
D PDDocumentCatalogClass : 'get+
D AllPages' )
*-----------------------------------------------------------------
*java.lang.String
D jStringClass...
D C 'java.lang.String'
D jstring_new PR like(jString)
D EXTPROC(*JAVA
D :jStringClass
D :*CONSTRUCTOR)
D create_from 1024A Varying const
*-----------------------------------------------------------------
*PDDocument
D PDDocumentClass...
D C 'org.apache.pdfbox.pdmodel.PDDocumen-
D t'
D PDDocument S O CLASS(*JAVA:PDDocumentClass)
* PDDocument()
D PDDocument_new...
D PR like(PDDocument)
D EXTPROC(*JAVA:
D PDDocumentClass:
D *CONSTRUCTOR)
* PDDocument.addPage()
D PDDocument_addPage...
D PR
D EXTPROC(*JAVA:
D PDDocumentClass:
D 'addPage')
D ppage like(PDPage)
*PDDocument.load()
D PDDocument_load...
D PR like(PDDocument)
D EXTPROC(*JAVA : PDDocumentClass:
D 'load' )
D STATIC
D path like(jstring)
D PDDocument_save...
D PR EXTPROC(*JAVA : PDDocumentClass:
D 'save' )
D savepath like(jstring)
*
D importPage PR O CLASS(*JAVA : 'org.apache.pdfbox.p+
D dmodel.PDPage' )
D EXTPROC(*JAVA : 'org.apache.pdfbox+
D .pdmodel.PDDocument' : 'importPage+
D ' )
D* Parameter prototype declaration for Java type: PDPage
D PDpage like(PDPage)
* PDDocument.close()
D PDDocument_close...
D PR
D EXTPROC(*JAVA:
D PDDocumentClass:
D 'close')
*-----------------------------------------------------------------
* Font Classes
D PDFontClass C 'org.apache.pdfbox.pdmodel.font.PDFo-
D nt'
D PDFont S O CLASS(*JAVA:PDFontClass)
*-----------------------------------------------------------------
* PDPage
D PDPageClass C 'org.apache.pdfbox.pdmodel.PDPage'
D PDPage S O CLASS(*JAVA:PDPageClass)
D PDPage_get PR O CLASS(*JAVA : 'java.lang.Object' )
D EXTPROC(*JAVA : 'java.util.List' :
D 'get' )
D indexNo 10I 0 VALUE
*-----------------------------------------------------------------
* PDType1Font
D PDType1FontClass...
D C 'org.apache.pdfbox.pdmodel.font.PDTy-
D pe1Font'
D PDType1Font S O CLASS(*JAVA:PDType1FontClass)
* PDType1Font()
D PDType1Font_new...
D PR like(PDType1Font)
D EXTPROC(*JAVA:
D PDType1FontClass:
D *CONSTRUCTOR)
D fontname like(jString) Options(*Omit)
* PDType1Font.getStandardFont
D PDType1Font_getStandardFont...
D PR like(PDType1Font)
D EXTPROC(*JAVA:
D PDType1FontClass:
D 'getStandardFont')
D STATIC
D fontname like(jString)
*-----------------------------------------------------------------
* PDPageContentStream
D PDPageContentStreamClass...
D C 'org.apache.pdfbox.pdmodel.edit.PDPa-
D geContentStream'
D PDPageContentStream...
D S O CLASS(*JAVA:
D PDPageContentStreamClass)
* PDPageContentStream()
D PDPageContentStream_new...
D PR like(PDPageContentStream)
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D *CONSTRUCTOR)
D pdocument like(PDDocument)
D ppage like(PDPage)
D appendcontent N value
D compress N value
* PDPageContentStream.beginText()
D PDPageContentStream_beginText...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'beginText')
* PDPageContentStream.setFont()
D PDPageContentStream_setFont...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'setFont')
D font like(PDFont)
D fontSize like(jfloat) Value
* PDPageContentStream.moveTextPositionByAmount()
D PDPageContentStream_moveTextPositionByAmount...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'moveTextPositionByAmount')
D x like(jfloat) Value
D y like(jfloat) Value
* PDPageContentStream.drawString()
D PDPageContentStream_drawString...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'drawString')
D text like(jstring)
* PDPageContentStream.endText()
D PDPageContentStream_endText...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'endText')
* PDPageContentStream.close()
D PDPageContentStream_close...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'close')
*-----------------------------------------------------------------
* java.awt.Color
D jColorClass...
D C 'java.awt.Color'
D jColor S O CLASS(*JAVA:
D jColorClass)
// new Color(int, int, int)
D jColor_new_fromIntRGB...
D PR like(jColor)
D EXTPROC(*JAVA
D :jColorClass
D :*CONSTRUCTOR)
D R like(jint) value
D G like(jint) value
D B like(jint) value
* PDPageContentStream.setNonStrokingColor(java.awt.Color color)
D PDPageContentStream_setNonStrokingColor...
D PR
D EXTPROC(*JAVA:
D PDPageContentStreamClass:
D 'setNonStrokingColor')
D color like(jColor)
*-----------------------------------------------------------------
* Utilities
D mmToUnits PR Like(jfloat)
D pmm Like(jfloat) Value
D createPageSizes...
D PR
*-----------------------------------------------------------------
*PDFBOX variables
D myFontName S like(jstring)
D myFont S like(PDType1Font)
D myPageContent S like(PDPageContentStream)
D myColor S like(jColor)
D sourceDoc S like(PDDocument)
D targetDoc S like(PDDocument)
D DocumentCat S like(DocumentCatalog)
D pdf_path1 S like(jstring)
D pdf_save S like(jstring)
D myPage S like(PDPage)
D newPage S like(PDPage)
D myAllPages S O CLASS(*JAVA : 'java.util.List' )
D importPageRet S like(PDPage)
*RPG variables
D DocName S 255A VARYING
D pageNumber S 10I 0
D Tdate S d
D Cdate S 10 VARYING
D tempsave S 150 VARYING
D tempload S 150 VARYING
D Directorys S 150 VARYING
D Directoryl S 150 VARYING
D CDirectory S 150 VARYING
D loadstring S 150 VARYING
D checkstring S 150 VARYING
D SqlStm S 1000A VARYING
D Q S 1A INZ(x'7D')
D Cmds S 1500A Varying
D Cmdl S 1500A Varying
D*--------------------------------------------------
D* Procedure name: addText
D* Purpose:
D* Returns:
D* Parameter: myText
D*--------------------------------------------------
D addText PR
D myText 5000A VARYING CONST
D indent 10I 0 CONST
D offset 10I 0 CONST
*
D myString S like(jstring)
/free
Tdate = %Date();
Cdate = %char(Tdate:*usa/);
//The page of the loaded pdf that I am going to want to retrieve
pageNumber = 0;
//Contains the classpath
XLSENVVAR();
//GETIFSPTH AND GETIFSNAM are service programs that my company uses
//to get the path for a document. Further down in PDF_path1(loadstring)
//you can pass a hardcoded string ex PDF_path1('/tmp/demodoc.pdf');
// Get the requested template file
DocName = %Trim(GETIFSPTH(ProgramName:1)) +
%Trim(GETIFSNAM(ProgramName:1));
//Directory the file will be moved into
Directoryl = %Trim(GETIFSPTH(ProgramName:2));
//getting path to load the pdf document
checkstring = %Trim(GETIFSPTH(ProgramName:3)) +
%Trim(GETIFSNAM(ProgramName:3));
//Check to see if template already exists if it does dlt it
//this is needed because later when I move the document to its final
//destination if the document to be moved already exists the move will
//fail. This will cause a modified template to be left behind and when
//the program is ran later the earlier cpy obj will fail and I will
//load an already modified templete.
CallP(E) xCommand('DEL OBJLNK('+Q+%Trim(checkstring)+Q+')');
//String to pass to xcommand()
Cmdl = 'CPY OBJ(' +Q + %trim(DocName) +Q + ')' +
' TODIR(' +Q + %trim(Directoryl) +Q + ')';
xcommand(Cmdl);
//Create a blank pdf document. This will be the page to be modified.
targetDoc = PDDocument_new();
//getting path to load the pdf document
loadstring = %Trim(GETIFSPTH(ProgramName:3)) +
%Trim(GETIFSNAM(ProgramName:3));
//The string that holds the path for where the pdf template is
pdf_path1 = jstring_new(loadstring);
//Load the pdf document
sourceDoc = PDDocument_load(pdf_path1);
//Get the document catalog
DocumentCat = getDocumentCatalog(sourceDoc);
//Get the list of pages
myAllPages = getAllPages(DocumentCat);
//Get the specific page I want
myPage = PDPage_get(myAllPages:pageNumber);
sqlstm = 'SELECT EMPLID,LNAME, ADDR1' +
' ADDR2, CSZ'
' from empmst';
Exec SQL
Prepare S1 From :SqlStm;
Exec SQL
Declare Rcd Cursor for S1;
Exec SQL
Open Rcd;
Exec SQL
Fetch Rcd into :Rcd;
Dow SQLCOD = 0;
//Import and copy to a new page. This is the page to be used
//in the content stream.
importpageret = importpage(targetdoc:myPage);
// Create a content stream so we can add content to the page
// Modifying an existing page so append is *ON
// Compression is *Off
myPageContent = PDPageContentStream_new(targetdoc:importpageret:
*ON:*Off);
//Adding text to preloaded pdf
addtext(Rcd.EMPLID :23 :240);
addtext(Rcd.LNAME :23 :231);
addtext(Rcd.ADDR1 :23 : 227);
addtext(Rcd.ADDR2 :23 : 223);
addtext(Rcd.CSZ :23 : 219);
addtext(Cdate :180 : 240);
EXEC SQL
Fetch Rcd into :Rcd;
ENDDO;
//Temparaly saving to /tmp then will move with mov command
tempsave = %Trim(GETIFSPTH(ProgramName:3)) +
%Trim(GETIFSNAM(ProgramName:3));
//The string that holds the path for where the pdf will be saved
pdf_save = jstring_new(tempsave);
//Done with the file, so save it
PDDocument_save(targetDoc : pdf_save);
// Close the document object in memory to free all allocated space
PDDocument_close(sourceDoc);
PDDocument_close(targetDoc);
//Create the directory that the file will be moved to
CDirectory = %Trim(GETIFSPTH(ProgramName:4))+
%char(%subdt(%date():*YEARS));
xcommand('CRTDIR DIR(' +Q + CDIRECTORY +Q +')');
//retrieve the path the file will be saved to
Directorys = %Trim(GETIFSPTH(ProgramName:4)) +
%char(%subdt(%date():*YEARS)) + '/' +
%Trim(GETIFSNAM(ProgramName:4));
//move the file to the correct directory
Cmds = 'MOV OBJ(' +Q + tempsave +Q + ')' +
' TOOBJ(' +Q + %trim(Directorys)+ Q + ')';
xcommand(Cmds);
//Adopt the auth of the folder
ifsadopt(Directorys);
Exec SQL
Close Rcd;
*Inlr = *On;
/end-free
* mmToUnits
P mmToUnits B
D Pi Like(jfloat)
D pmm value like(jfloat)
D funits S Like(jfloat)
/free
funits = 1 / (25.4) *
DEFAULT_USERSPACE_UNIT_DPI *
pmm;
return funits;
/end-free
P mmToUnits E
* creatPageSizes
P createPageSizes...
P B
D Pi
/free
PAGE_SIZE_A0 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A0):
mmToUnits(PAGE_HEIGHT_A0));
PAGE_SIZE_A1 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A1):
mmToUnits(PAGE_HEIGHT_A1));
PAGE_SIZE_A2 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A2):
mmToUnits(PAGE_HEIGHT_A2));
PAGE_SIZE_A3 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A3):
mmToUnits(PAGE_HEIGHT_A3));
PAGE_SIZE_A4 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A4):
mmToUnits(PAGE_HEIGHT_A4));
PAGE_SIZE_A5 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A5):
mmToUnits(PAGE_HEIGHT_A5));
PAGE_SIZE_A6 = PDRectangle_new(mmToUnits(PAGE_WIDTH_A6):
mmToUnits(PAGE_HEIGHT_A6));
PAGE_SIZE_A0_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A0):
mmToUnits(PAGE_WIDTH_A0));
PAGE_SIZE_A1_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A1):
mmToUnits(PAGE_WIDTH_A1));
PAGE_SIZE_A2_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A2):
mmToUnits(PAGE_WIDTH_A2));
PAGE_SIZE_A3_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A3):
mmToUnits(PAGE_WIDTH_A3));
PAGE_SIZE_A4_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A4):
mmToUnits(PAGE_WIDTH_A4));
PAGE_SIZE_A5_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A5):
mmToUnits(PAGE_WIDTH_A5));
PAGE_SIZE_A6_LANDSCAPE = PDRectangle_new(mmToUnits(PAGE_HEIGHT_A6):
mmToUnits(PAGE_WIDTH_A6));
return;
/end-free
P E
*
*
P*--------------------------------------------------
P* Procedure name: addText
P* Purpose: Write text to a PDPage
P* Returns:
P* Parameter: myText
P*--------------------------------------------------
P addText B
D addText PI
D myText 5000A VARYING CONST
D indent 10I 0 CONST
D offset 10I 0 CONST
*
D myString S like(jstring)
/FREE
// Set font type
myFontName = jstring_new('Times-Roman');
myFont = PDType1Font_getStandardFont(myFontName);
PDPageContentStream_setFont(myPageContent:myFont:10);
// Set the color of the font to add
// This isn't needed if writing to a blank page but since
// adding text to a loaded page need to set the color of the text.
myColor = jColor_new_fromIntRGB(0:0:0);
PDPageContentStream_setNonStrokingColor(myPageContent:myColor);
// Prepare to write text to the content stream
PDPageContentStream_beginText(myPageContent);
// Move the cursor possition,indent is x mm from left of page
// offset x mm from bottom of page.
PDPageContentStream_moveTextPositionByAmount(myPageContent:
mmtounits(indent):mmtounits(offset));
// Create the text string we want to write
myString = jstring_new(myText);
// Write the string to the content stream
PDPageContentStream_drawString(myPageContent:myString);
// We are done writing text to this content stream
PDPageContentStream_endText(myPageContent);
//We are done with this content stream
PDPageContentStream_close(myPageContent);
/END-FREE
P addText E
Thought I would add a couple of comments after reading my code. I have to make a new folder for each year. That is what the crtdir is doing. If the directory already exists that is fine the contents in the already created directory are safe, the crtdir doesn't overwrite the directory. The reason that I am loading the template from one location to /tmp and then saving to /tmp before moving again is when I was working with PDFBOX the jstring_new(' ') was maxing out at 30 characters (including / and spaces and . ). so myString = jstring_new('/tmp/2013/myreportnamethatistoolong.pdf') that string is 39 characters long and that string will become truncated. olong.pdf will be lost when I make the string. I can make a string with rpg code and pass that string to jString_new() and be longer than 30 characters and it works.
You will want your List.get() to return org.apache.pdfbox.pdmodel.PDPage RPG is strongly typed, so we can't cast the same way Java can. Instead, we create the prototype to return the object we want to manipulate. Along those lines, you may end up using get() to retrieve several different kind of List elements. RPG doesn't do overloading either. What I'd do is create a separate get() prototype for each object I'd handle. So I'd have a getPage() and a getThread() and so on. Each one would be 'java.util.List:get' but return a different object type.
The RPG list at www.midrange.com is another good source for help with RPG.

iTextSharp: reading radio button, check box states from a non-form PDF

I have a pdf document (created by a 3rd party using RealObjects PDFreactor), which is not a form. I'm trying to extract information from that PDF using iTextSharp. I'm able to extract all the plain text (using SimpleTextExtractionStrategy), but there is some information that is represented with radio buttons, which does not come across in the plain text extracted. I'm a complete beginner with iTextSharp, so I might be overlooking something very simple. PdfReader.AcroForm returns null, and PdfReader.AcroFields.Fields has 0 keys. How can I figure out the state of radio buttons and checkboxes throughout the document? The documents all have the same structure, so I don't really need the radio buttons & checkboxes to be labelled; just having a list of items, and knowing whether they are checked or not would be sufficient.
I've confirmed that the radio buttons are not just images using this approach.
I made a feeble attempt at finding all the BTN objects on a page by modifying the code to extract images, but I apparently messed up because it doesn't return anything on a page that contains radio buttons:
private List<PdfObject> GetBTNFromPdfDict(PdfDictionary dict, PdfReader doc)
{
List<PdfObject> objects = new List<PdfObject>();
foreach (PdfName name in dict.Keys)
{
PdfObject obj = dict.Get(name);
PdfDictionary tg = PdfReader.GetPdfObject(obj) as PdfDictionary;
if (null != tg)
{
PdfName subtype = (PdfName)(PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)));
if (obj.IsIndirect())
{
if (PdfName.BTN.Equals(subtype))
{
int xrefIdx = ((PRIndirectReference)obj).Number;
PdfObject pdfObj = doc.GetPdfObject(xrefIdx);
objects.Add(pdfObj);
}
else if (PdfName.FORM.Equals(subtype) || PdfName.GROUP.Equals(subtype))
{
objects.AddRange(GetBTNFromPdfDict(tg, doc));
}
}
else objects.AddRange(GetBTNFromPdfDict(tg, doc));
}
}
return objects;
}
I also looked at the content for the page using PdfContentReaderTool; the output didn't include any BTN, so I'm not sure what is going on. Here's the output (I replaced all the lines of text with [TEXT]). Just looking at the content stream section, it seems trivial to extract all strings (everything between brackets followed by Tj), but I can't seem to figure out radio buttons and checkboxes. (I had to abridge the output, the question was too long)
==============Page 2====================
- - - - - Dictionary - - - - - -
(/Type=/Page, /TrimBox=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject], /Contents=Stream, /Parent=Dictionary of type: /Pages, /Group=Dictionary of type: /Group, /BleedBox=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject], /Resources=Dictionary, /MediaBox=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject])
Subdictionary /Parent = (/Count=10, /Type=/Pages, /Parent=Dictionary of type: /Pages, /Kids=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject])
Subdictionary /Parent = (/Count=39, /Type=/Pages, /ITXT=2.1.6, /Kids=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject])
Subdictionary /Group = (/Type=/Group, /S=/Transparency, /CS=/DeviceRGB)
Subdictionary /Resources = (/ColorSpace=Dictionary, /ProcSet=System.Collections.Generic.List`1[iTextSharp.text.pdf.PdfObject], /Font=Dictionary)
Subdictionary /ColorSpace = (/CS=/DeviceRGB)
Subdictionary /Font = (/F1=Dictionary of type: /Font, /F3=Dictionary of type: /Font, /F2=Dictionary of type: /Font, /F4=Dictionary of type: /Font)
Subdictionary /F1 = (/Type=/Font, /BaseFont=/Helvetica, /Subtype=/Type1, /Encoding=/WinAnsiEncoding)
Subdictionary /F3 = (/Type=/Font, /BaseFont=/Times-Bold, /Subtype=/Type1, /Encoding=/WinAnsiEncoding)
Subdictionary /F2 = (/Type=/Font, /BaseFont=/Times-Roman, /Subtype=/Type1, /Encoding=/WinAnsiEncoding)
Subdictionary /F4 = (/Type=/Font, /BaseFont=/Times-Italic, /Subtype=/Type1, /Encoding=/WinAnsiEncoding)
- - - - - XObject Summary - - - - - -
No XObjects
- - - - - Content Stream - - - - - -
q
BT
36 805.89 Td
ET
Q
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
1 w
2 J
0 j
10 M
[]0 d
q
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0 841.89 m
595.29 841.89 l
595.29 0 l
0 0 l
0 841.89 l
h
W
n
0 0 0 rg
BT
/F1 233.33 Tf
0.03 0 0 0.03 540.69 4.71 Tm
12.63 Tc
(TEXT)Tj
0 Tc
ET
BT
/F1 233.33 Tf
0.03 0 0 0.03 129.18 4.71 Tm
11.37 Tc
(TEXT)Tj
0 Tc
ET
0.8 0.8 0.8 rg
15 826.89 m
580.29 826.89 l
580.29 494.79 l
15 494.79 l
15 826.89 l
h
f
0 0 0 rg
20.1 826.89 m
575.16 826.89 l
574.41 826.14 l
20.85 826.14 l
h
f
20.85 495.54 m
574.41 495.54 l
575.16 494.79 l
20.1 494.79 l
h
f
20.1 826.89 m
20.85 826.14 l
20.85 495.54 l
20.1 494.79 l
h
f
574.41 826.14 m
575.16 826.89 l
575.16 494.79 l
574.41 495.54 l
h
f
1 1 1 rg
20.85 826.14 m
574.41 826.14 l
574.41 495.54 l
20.85 495.54 l
20.85 826.14 l
h
f
0 0 0 rg
28.35 818.64 m
566.91 818.64 l
566.91 799.14 l
28.35 799.14 l
28.35 818.64 l
h
f
1 1 1 rg
BT
/F3 350 Tf
0.03 0 0 0.03 31.35 804.69 Tm
6.52 Tc
(I. )Tj
0 Tc
ET
BT
/F3 350 Tf
0.03 0 0 0.03 41.07 804.69 Tm
27.57 Tc
(TEXT)Tj
0 Tc
ET
0 0 0 rg
BT
/F2 300 Tf
0.03 0 0 0.03 28.35 789.54 Tm
( )Tj
ET
28.35 787.14 m
566.91 787.14 l
566.16 786.39 l
29.1 786.39 l
h
f
29.1 728.64 m
566.16 728.64 l
566.91 727.89 l
28.35 727.89 l
h
f
28.35 787.14 m
29.1 786.39 l
29.1 728.64 l
28.35 727.89 l
h
f
566.16 786.39 m
566.91 787.14 l
566.91 727.89 l
566.16 728.64 l
h
f
29.1 729.39 m
296.88 729.39 l
297.63 728.64 l
29.1 728.64 l
h
f
296.88 786.39 m
297.63 786.39 l
297.63 728.64 l
296.88 729.39 l
h
f
BT
/F2 250 Tf
0.03 0 0 0.03 32.1 775.14 Tm
19.36 Tc
(TEXT)Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
32.1 772.89 m
293.88 772.89 l
292.38 771.39 l
33.6 771.39 l
h
f
0.87843 0.87843 0.87843 rg
292.38 771.39 m
293.88 772.89 l
293.88 744.39 l
292.38 745.14 l
h
f
0.37647 0.37647 0.37647 rg
32.1 772.89 m
33.6 771.39 l
33.6 745.14 l
32.1 744.39 l
h
f
0 0 0 rg
33.6 745.14 m
292.38 745.14 l
293.88 744.39 l
32.1 744.39 l
h
f
1 1 1 rg
33.6 771.39 m
292.38 771.39 l
292.38 745.14 l
33.6 745.14 l
33.6 771.39 l
h
f
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
33.72 766.14 m
287.13 766.14 l
287.13 750.39 l
33.72 750.39 l
33.72 766.14 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
33.72 766.14 m
33.72 750.39 l
287.13 750.39 l
287.13 766.14 l
h
W
n
1 1 1 rg
33.72 766.14 m
287.13 766.14 l
287.13 750.39 l
33.72 750.39 l
33.72 766.14 l
h
f
33.72 766.14 m
287.13 766.14 l
287.13 750.39 l
33.72 750.39 l
33.72 766.14 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
33.72 766.14 m
33.72 750.39 l
287.13 750.39 l
287.13 766.14 l
h
W
n
0 0 0 rg
BT
/F2 18 Tf
0.74973 0 0 0.75 33.72 753.31 Tm
2.02 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 76.53 753.31 Tm
( )Tj
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 80.63 753.31 Tm
1.85 Tc
(TEXT)Tj
0 Tc
ET
Q
Q
Q
Q
Q
Q
0 0 0 rg
297.63 729.39 m
566.16 729.39 l
566.16 728.64 l
297.63 728.64 l
h
f
BT
/F2 250 Tf
0.03 0 0 0.03 300.63 775.14 Tm
18.42 Tc
(TEXT)Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
300.63 772.89 m
563.16 772.89 l
561.66 771.39 l
302.13 771.39 l
h
f
0.87843 0.87843 0.87843 rg
561.66 771.39 m
563.16 772.89 l
563.16 744.39 l
561.66 745.14 l
h
f
0.37647 0.37647 0.37647 rg
300.63 772.89 m
302.13 771.39 l
302.13 745.14 l
300.63 744.39 l
h
f
0 0 0 rg
302.13 745.14 m
561.66 745.14 l
563.16 744.39 l
300.63 744.39 l
h
f
1 1 1 rg
302.13 771.39 m
561.66 771.39 l
561.66 745.14 l
302.13 745.14 l
302.13 771.39 l
h
f
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
302.25 766.14 m
556.41 766.14 l
556.41 750.39 l
302.25 750.39 l
302.25 766.14 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
302.25 766.14 m
302.25 750.39 l
556.41 750.39 l
556.41 766.14 l
h
W
n
1 1 1 rg
302.25 766.14 m
556.41 766.14 l
556.41 750.39 l
302.25 750.39 l
302.25 766.14 l
h
f
302.25 766.14 m
556.41 766.14 l
556.41 750.39 l
302.25 750.39 l
302.25 766.14 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
302.25 766.14 m
302.25 750.39 l
556.41 750.39 l
556.41 766.14 l
h
W
n
0 0 0 rg
BT
/F2 18 Tf
0.74973 0 0 0.75 302.25 753.31 Tm
1.42 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 344.3 753.31 Tm
( )Tj
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 348.4 753.31 Tm
1.8 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 431.64 753.31 Tm
( )Tj
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 435.75 753.31 Tm
1.23 Tc
(TEXT)Tj
0 Tc
ET
Q
Q
Q
Q
Q
Q
0 0 0 rg
28.35 727.89 m
566.91 727.89 l
566.16 727.14 l
29.1 727.14 l
h
f
29.1 503.79 m
566.16 503.79 l
566.91 503.04 l
28.35 503.04 l
h
f
28.35 727.89 m
29.1 727.14 l
29.1 503.79 l
28.35 503.04 l
h
f
566.16 727.14 m
566.91 727.89 l
566.91 503.04 l
566.16 503.79 l
h
f
29.1 670.14 m
296.88 670.14 l
297.63 669.39 l
29.1 669.39 l
h
f
296.88 727.14 m
297.63 727.14 l
297.63 669.39 l
296.88 670.14 l
h
f
BT
/F2 250 Tf
0.03 0 0 0.03 32.1 715.89 Tm
19.68 Tc
(TEXT )Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
32.1 713.64 m
293.88 713.64 l
292.38 712.14 l
33.6 712.14 l
h
f
0.87843 0.87843 0.87843 rg
292.38 712.14 m
293.88 713.64 l
293.88 685.14 l
292.38 685.89 l
h
f
0.37647 0.37647 0.37647 rg
32.1 713.64 m
33.6 712.14 l
33.6 685.89 l
32.1 685.14 l
h
f
0 0 0 rg
33.6 685.89 m
292.38 685.89 l
293.88 685.14 l
32.1 685.14 l
h
f
1 1 1 rg
33.6 712.14 m
292.38 712.14 l
292.38 685.89 l
33.6 685.89 l
33.6 712.14 l
h
f
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
33.72 706.89 m
287.13 706.89 l
287.13 691.14 l
33.72 691.14 l
33.72 706.89 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
33.72 706.89 m
33.72 691.14 l
287.13 691.14 l
287.13 706.89 l
h
W
n
1 1 1 rg
33.72 706.89 m
287.13 706.89 l
287.13 691.14 l
33.72 691.14 l
33.72 706.89 l
h
f
33.72 706.89 m
287.13 706.89 l
287.13 691.14 l
33.72 691.14 l
33.72 706.89 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
33.72 706.89 m
33.72 691.14 l
287.13 691.14 l
287.13 706.89 l
h
W
n
0 0 0 rg
BT
/F2 18 Tf
0.74973 0 0 0.75 33.72 694.06 Tm
1.8 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 77.19 694.06 Tm
( )Tj
ET
BT
/F2 18 Tf
0.74973 0 0 0.75 81.3 694.06 Tm
1.89 Tc
(TEXT)Tj
0 Tc
ET
Q
Q
Q
Q
Q
Q
0 0 0 rg
297.63 670.14 m
566.16 670.14 l
566.16 669.39 l
297.63 669.39 l
h
f
BT
/F2 250 Tf
0.03 0 0 0.03 300.63 715.89 Tm
22.9 Tc
(TEXT )Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
300.63 713.64 m
563.16 713.64 l
561.66 712.14 l
302.13 712.14 l
h
f
0.87843 0.87843 0.87843 rg
561.66 712.14 m
563.16 713.64 l
563.16 685.14 l
561.66 685.89 l
h
f
0.37647 0.37647 0.37647 rg
300.63 713.64 m
302.13 712.14 l
302.13 685.89 l
300.63 685.14 l
h
f
0 0 0 rg
302.13 685.89 m
561.66 685.89 l
563.16 685.14 l
300.63 685.14 l
h
f
1 1 1 rg
302.13 712.14 m
561.66 712.14 l
561.66 685.89 l
302.13 685.89 l
302.13 712.14 l
h
f
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
302.25 706.89 m
556.41 706.89 l
556.41 691.14 l
302.25 691.14 l
302.25 706.89 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
302.25 706.89 m
302.25 691.14 l
556.41 691.14 l
556.41 706.89 l
h
W
n
1 1 1 rg
302.25 706.89 m
556.41 706.89 l
556.41 691.14 l
302.25 691.14 l
302.25 706.89 l
h
f
302.25 706.89 m
556.41 706.89 l
556.41 691.14 l
302.25 691.14 l
302.25 706.89 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.74987 w
2 J
0 j
10 M
[]0 d
q
302.25 706.89 m
302.25 691.14 l
556.41 691.14 l
556.41 706.89 l
h
W
n
Q
Q
Q
Q
Q
Q
0 0 0 rg
29.1 504.54 m
566.16 504.54 l
566.16 503.79 l
29.1 503.79 l
h
f
0.86667 0.86667 0.86667 rg
29.1 669.39 m
566.16 669.39 l
566.16 504.54 l
29.1 504.54 l
29.1 669.39 l
h
f
0 0 0 rg
BT
/F2 250 Tf
0.03 0 0 0.03 32.1 658.14 Tm
19.96 Tc
(TEXT)Tj
0 Tc
ET
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
54.6 647.46 m
61.35 647.46 l
61.35 640.71 l
54.6 640.71 l
54.6 647.46 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
54.6 647.46 m
54.6 640.71 l
61.35 640.71 l
61.35 647.46 l
h
W
n
Q
Q
Q
q
47.85 654.21 m
68.1 654.21 l
68.1 633.96 l
47.85 633.96 l
47.85 654.21 l
h
W
n
1 1 1 rg
61.35 644.08 m
61.35 642.22 59.84 640.71 57.97 640.71 c
56.11 640.71 54.6 642.22 54.6 644.08 c
54.6 645.95 56.11 647.46 57.97 647.46 c
59.84 647.46 61.35 645.95 61.35 644.08 c
h
f
Q
q
47.85 654.21 m
68.1 654.21 l
68.1 633.96 l
47.85 633.96 l
47.85 654.21 l
h
W
n
0 0 0 rg
57.97 646.71 m
59.42 646.71 60.6 645.53 60.6 644.08 c
60.6 642.64 59.42 641.46 57.97 641.46 c
56.53 641.46 55.35 642.64 55.35 644.08 c
55.35 645.53 56.53 646.71 57.97 646.71 c
h
57.97 647.46 m
56.11 647.46 54.6 645.95 54.6 644.08 c
54.6 642.22 56.11 640.71 57.97 640.71 c
59.84 640.71 61.35 642.22 61.35 644.08 c
61.35 645.95 59.84 647.46 57.97 647.46 c
h
f
Q
Q
BT
/F2 250 Tf
0.03 0 0 0.03 64.35 642.39 Tm
21.62 Tc
(TEXT)Tj
0 Tc
ET
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
54.6 630.39 m
61.35 630.39 l
61.35 623.64 l
54.6 623.64 l
54.6 630.39 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
54.6 630.39 m
54.6 623.64 l
61.35 623.64 l
61.35 630.39 l
h
W
n
Q
Q
Q
q
47.85 637.14 m
68.1 637.14 l
68.1 616.89 l
47.85 616.89 l
47.85 637.14 l
h
W
n
1 1 1 rg
61.35 627.01 m
61.35 625.15 59.84 623.64 57.97 623.64 c
56.11 623.64 54.6 625.15 54.6 627.01 c
54.6 628.88 56.11 630.39 57.97 630.39 c
59.84 630.39 61.35 628.88 61.35 627.01 c
h
f
Q
q
47.85 637.14 m
68.1 637.14 l
68.1 616.89 l
47.85 616.89 l
47.85 637.14 l
h
W
n
0 0 0 rg
57.97 629.64 m
59.42 629.64 60.6 628.46 60.6 627.01 c
60.6 625.57 59.42 624.39 57.97 624.39 c
56.53 624.39 55.35 625.57 55.35 627.01 c
55.35 628.46 56.53 629.64 57.97 629.64 c
h
57.97 630.39 m
56.11 630.39 54.6 628.88 54.6 627.01 c
54.6 625.15 56.11 623.64 57.97 623.64 c
59.84 623.64 61.35 625.15 61.35 627.01 c
61.35 628.88 59.84 630.39 57.97 630.39 c
h
f
59.66 627.01 m
59.66 626.08 58.91 625.33 57.97 625.33 c
57.04 625.33 56.29 626.08 56.29 627.01 c
56.29 627.95 57.04 628.7 57.97 628.7 c
58.91 628.7 59.66 627.95 59.66 627.01 c
h
f
Q
Q
BT
/F2 250 Tf
0.03 0 0 0.03 64.35 625.32 Tm
18.25 Tc
(TEXT)Tj
0 Tc
ET
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
65.1 610.32 m
71.85 610.32 l
71.85 603.57 l
65.1 603.57 l
65.1 610.32 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
65.1 610.32 m
65.1 603.57 l
71.85 603.57 l
71.85 610.32 l
h
W
n
Q
Q
Q
q
58.35 617.07 m
78.6 617.07 l
78.6 596.82 l
58.35 596.82 l
58.35 617.07 l
h
W
n
1 1 1 rg
71.85 606.94 m
71.85 605.08 70.34 603.57 68.47 603.57 c
66.61 603.57 65.1 605.08 65.1 606.94 c
65.1 608.81 66.61 610.32 68.47 610.32 c
70.34 610.32 71.85 608.81 71.85 606.94 c
h
f
Q
q
58.35 617.07 m
78.6 617.07 l
78.6 596.82 l
58.35 596.82 l
58.35 617.07 l
h
W
n
0 0 0 rg
68.47 609.57 m
69.92 609.57 71.1 608.39 71.1 606.94 c
71.1 605.5 69.92 604.32 68.47 604.32 c
67.03 604.32 65.85 605.5 65.85 606.94 c
65.85 608.39 67.03 609.57 68.47 609.57 c
h
68.47 610.32 m
66.61 610.32 65.1 608.81 65.1 606.94 c
65.1 605.08 66.61 603.57 68.47 603.57 c
70.34 603.57 71.85 605.08 71.85 606.94 c
71.85 608.81 70.34 610.32 68.47 610.32 c
h
f
70.16 606.94 m
70.16 606.01 69.41 605.26 68.47 605.26 c
67.54 605.26 66.79 606.01 66.79 606.94 c
66.79 607.88 67.54 608.63 68.47 608.63 c
69.41 608.63 70.16 607.88 70.16 606.94 c
h
f
Q
Q
BT
/F2 250 Tf
0.03 0 0 0.03 74.85 605.25 Tm
21.69 Tc
( TEXT)Tj
0 Tc
ET
BT
/F2 250 Tf
0.03 0 0 0.03 399.88 605.25 Tm
( )Tj
ET
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
65.1 593.25 m
71.85 593.25 l
71.85 586.5 l
65.1 586.5 l
65.1 593.25 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
65.1 593.25 m
65.1 586.5 l
71.85 586.5 l
71.85 593.25 l
h
W
n
Q
Q
Q
q
58.35 600 m
78.6 600 l
78.6 579.75 l
58.35 579.75 l
58.35 600 l
h
W
n
1 1 1 rg
71.85 589.87 m
71.85 588.01 70.34 586.5 68.47 586.5 c
66.61 586.5 65.1 588.01 65.1 589.87 c
65.1 591.74 66.61 593.25 68.47 593.25 c
70.34 593.25 71.85 591.74 71.85 589.87 c
h
f
Q
q
58.35 600 m
78.6 600 l
78.6 579.75 l
58.35 579.75 l
58.35 600 l
h
W
n
0 0 0 rg
68.47 592.5 m
69.92 592.5 71.1 591.32 71.1 589.87 c
71.1 588.43 69.92 587.25 68.47 587.25 c
67.03 587.25 65.85 588.43 65.85 589.87 c
65.85 591.32 67.03 592.5 68.47 592.5 c
h
68.47 593.25 m
66.61 593.25 65.1 591.74 65.1 589.87 c
65.1 588.01 66.61 586.5 68.47 586.5 c
70.34 586.5 71.85 588.01 71.85 589.87 c
71.85 591.74 70.34 593.25 68.47 593.25 c
h
f
Q
Q
BT
/F2 250 Tf
0.03 0 0 0.03 74.85 588.18 Tm
23.16 Tc
( TEXT)Tj
0 Tc
ET
BT
/F2 250 Tf
0.03 0 0 0.03 407.97 588.18 Tm
( )Tj
ET
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
65.1 576.18 m
71.85 576.18 l
71.85 569.43 l
65.1 569.43 l
65.1 576.18 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
65.1 576.18 m
65.1 569.43 l
71.85 569.43 l
71.85 576.18 l
h
W
n
Q
Q
Q
q
58.35 582.93 m
78.6 582.93 l
78.6 562.68 l
58.35 562.68 l
58.35 582.93 l
h
W
n
1 1 1 rg
71.85 572.8 m
71.85 570.94 70.34 569.43 68.47 569.43 c
66.61 569.43 65.1 570.94 65.1 572.8 c
65.1 574.67 66.61 576.18 68.47 576.18 c
70.34 576.18 71.85 574.67 71.85 572.8 c
h
f
Q
q
58.35 582.93 m
78.6 582.93 l
78.6 562.68 l
58.35 562.68 l
58.35 582.93 l
h
W
n
0 0 0 rg
68.47 575.43 m
69.92 575.43 71.1 574.25 71.1 572.8 c
71.1 571.36 69.92 570.18 68.47 570.18 c
67.03 570.18 65.85 571.36 65.85 572.8 c
65.85 574.25 67.03 575.43 68.47 575.43 c
h
68.47 576.18 m
66.61 576.18 65.1 574.67 65.1 572.8 c
65.1 570.94 66.61 569.43 68.47 569.43 c
70.34 569.43 71.85 570.94 71.85 572.8 c
71.85 574.67 70.34 576.18 68.47 576.18 c
h
f
Q
Q
BT
/F2 250 Tf
0.03 0 0 0.03 74.85 571.11 Tm
23.08 Tc
( TEXT )Tj
0 Tc
ET
BT
/F2 250 Tf
0.03 0 0 0.03 78 560.04 Tm
23.94 Tc
(TEXT )Tj
0 Tc
ET
BT
/F4 250 Tf
0.03 0 0 0.03 168.51 560.04 Tm
26.34 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 250 Tf
0.03 0 0 0.03 183.81 560.04 Tm
22.63 Tc
(TEXT)Tj
0 Tc
ET
BT
/F2 250 Tf
0.03 0 0 0.03 78 539.97 Tm
20.99 Tc
(TEXT)Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
111.57 558.54 m
179.94 558.54 l
178.44 557.04 l
113.07 557.04 l
h
f
0.87843 0.87843 0.87843 rg
178.44 557.04 m
179.94 558.54 l
179.94 530.04 l
178.44 530.79 l
h
f
0.37647 0.37647 0.37647 rg
111.57 558.54 m
113.07 557.04 l
113.07 530.79 l
111.57 530.04 l
h
f
0 0 0 rg
113.07 530.79 m
178.44 530.79 l
179.94 530.04 l
111.57 530.04 l
h
f
1 1 1 rg
113.07 557.04 m
178.44 557.04 l
178.44 530.79 l
113.07 530.79 l
113.07 557.04 l
h
f
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.03 w
2 J
0 j
10 M
[]0 d
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
113.19 551.79 m
173.19 551.79 l
173.19 536.04 l
113.19 536.04 l
113.19 551.79 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
113.19 551.79 m
113.19 536.04 l
173.19 536.04 l
173.19 551.79 l
h
W
n
1 1 1 rg
113.19 551.79 m
173.19 551.79 l
173.19 536.04 l
113.19 536.04 l
113.19 551.79 l
h
f
113.19 551.79 m
173.19 551.79 l
173.19 536.04 l
113.19 536.04 l
113.19 551.79 l
h
W
n
q
0 841.89 m
0 0 l
595.29 0 l
595.29 841.89 l
h
W
n
0.75 w
2 J
0 j
10 M
[]0 d
q
113.19 551.79 m
113.19 536.04 l
173.19 536.04 l
173.19 551.79 l
h
W
n
Q
Q
Q
Q
Q
Q
0 0 0 rg
BT
/F2 250 Tf
0.03 0 0 0.03 179.94 539.97 Tm
(TEXT)Tj
ET
BT
/F2 250 Tf
0.03 0 0 0.03 197.04 539.97 Tm
20.99 Tc
(TEXT)Tj
0 Tc
ET
0.37647 0.37647 0.37647 rg
230.61 558.54 m
298.98 558.54 l
297.48 557.04 l
232.11 557.04 l
h
f
0.87843 0.87843 0.87843 rg
297.48 557.04 m
298.98 558.54 l
298.98 530.04 l
297.48 530.79 l
h
f
0.37647 0.37647 0.37647 rg
230.61 558.54 m
232.11 557.04 l
232.11 530.79 l
230.61 530.04 l
h
f
0 0 0 rg
232.11 530.79 m
297.48 530.79 l
298.98 530.04 l
230.61 530.04 l
h
f
<snip!>
I figured this out, at least for the documents I'm dealing with. This is not a generic solution that would work with all sorts of pdf documents. In my case, I was dealing a software-generated pdf, which always produced the same 'graphic paths' for checkboxes and radio buttons. Thus, I was able to use some regexes on each page's content:
private string GetPageContent(PdfReader pdfReader, int page)
{
StringBuilder sb = new StringBuilder();
// from http://www.java2s.com/Open-Source/CSharp/PDF/iTextSharp/iTextSharp/text/pdf/parser/PdfContentReaderTool.cs.htm
RandomAccessFileOrArray f = pdfReader.SafeFile;
byte[] contentBytes = pdfReader.GetPageContent(page, f);
f.Close();
foreach (byte b in contentBytes)
sb.Append((char)b);
return sb.ToString();
}
For example, an unchecked radio button always looked like this:
1 1 1 rg
61.35 644.08 m
61.35 642.22 59.84 640.71 57.97 640.71 c
56.11 640.71 54.6 642.22 54.6 644.08 c
54.6 645.95 56.11 647.46 57.97 647.46 c
59.84 647.46 61.35 645.95 61.35 644.08 c
h
f
Q
q
47.85 654.21 m
68.1 654.21 l
68.1 633.96 l
47.85 633.96 l
47.85 654.21 l
h
W
n
0 0 0 rg
57.97 646.71 m
59.42 646.71 60.6 645.53 60.6 644.08 c
60.6 642.64 59.42 641.46 57.97 641.46 c
56.53 641.46 55.35 642.64 55.35 644.08 c
55.35 645.53 56.53 646.71 57.97 646.71 c
h
57.97 647.46 m
56.11 647.46 54.6 645.95 54.6 644.08 c
54.6 642.22 56.11 640.71 57.97 640.71 c
59.84 640.71 61.35 642.22 61.35 644.08 c
61.35 645.95 59.84 647.46 57.97 647.46 c
h
f
3 concentric circles, while a checked radio button always had 4 concentric circles. The annotation always followed the concentric circles. Similarly for checkboxes.