JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / bin / javajs / export / PDFCreator.js
1 Clazz.declarePackage ("javajs.export");\r
2 Clazz.load (null, "javajs.export.PDFCreator", ["java.lang.Double", "java.util.Hashtable", "javajs.export.PDFObject", "javajs.util.Lst", "$.SB"], function () {\r
3 c$ = Clazz.decorateAsClass (function () {\r
4 this.os = null;\r
5 this.indirectObjects = null;\r
6 this.root = null;\r
7 this.graphics = null;\r
8 this.pt = 0;\r
9 this.xrefPt = 0;\r
10 this.count = 0;\r
11 this.height = 0;\r
12 this.width = 0;\r
13 this.fonts = null;\r
14 this.images = null;\r
15 Clazz.instantialize (this, arguments);\r
16 }, javajs["export"], "PDFCreator");\r
17 Clazz.makeConstructor (c$, \r
18 function () {\r
19 });\r
20 Clazz.defineMethod (c$, "setOutputStream", \r
21 function (os) {\r
22 this.os = os;\r
23 }, "java.io.OutputStream");\r
24 Clazz.defineMethod (c$, "newDocument", \r
25 function (paperWidth, paperHeight, isLandscape) {\r
26 this.width = (isLandscape ? paperHeight : paperWidth);\r
27 this.height = (isLandscape ? paperWidth : paperHeight);\r
28 System.out.println ("Creating PDF with width=" + this.width + " and height=" + this.height);\r
29 this.fonts =  new java.util.Hashtable ();\r
30 this.indirectObjects =  new javajs.util.Lst ();\r
31 this.root = this.newObject ("Catalog");\r
32 var pages = this.newObject ("Pages");\r
33 var page = this.newObject ("Page");\r
34 var pageContents = this.newObject (null);\r
35 this.graphics = this.newObject ("XObject");\r
36 this.root.addDef ("Pages", pages.getRef ());\r
37 pages.addDef ("Count", "1");\r
38 pages.addDef ("Kids", "[ " + page.getRef () + " ]");\r
39 page.addDef ("Parent", pages.getRef ());\r
40 page.addDef ("MediaBox", "[ 0 0 " + paperWidth + " " + paperHeight + " ]");\r
41 if (isLandscape) page.addDef ("Rotate", "90");\r
42 pageContents.addDef ("Length", "?");\r
43 pageContents.append ((isLandscape ? "q 0 1 1 0 0 0 " : "q 1 0 0 -1 0 " + (paperHeight)) + " cm /" + this.graphics.getID () + " Do Q");\r
44 page.addDef ("Contents", pageContents.getRef ());\r
45 this.addProcSet (page);\r
46 this.addProcSet (this.graphics);\r
47 this.graphics.addDef ("Subtype", "/Form");\r
48 this.graphics.addDef ("FormType", "1");\r
49 this.graphics.addDef ("BBox", "[0 0 " + this.width + " " + this.height + "]");\r
50 this.graphics.addDef ("Matrix", "[1 0 0 1 0 0]");\r
51 this.graphics.addDef ("Length", "?");\r
52 page.addResource ("XObject", this.graphics.getID (), this.graphics.getRef ());\r
53 this.g ("q 1 w 1 J 1 j 10 M []0 d q ");\r
54 this.clip (0, 0, this.width, this.height);\r
55 }, "~N,~N,~B");\r
56 Clazz.defineMethod (c$, "addProcSet", \r
57 ($fz = function (o) {\r
58 o.addResource (null, "ProcSet", "[/PDF /Text /ImageB /ImageC /ImageI]");\r
59 }, $fz.isPrivate = true, $fz), "javajs.export.PDFObject");\r
60 Clazz.defineMethod (c$, "clip", \r
61 ($fz = function (x1, y1, x2, y2) {\r
62 this.moveto (x1, y1);\r
63 this.lineto (x2, y1);\r
64 this.lineto (x2, y2);\r
65 this.lineto (x1, y2);\r
66 this.g ("h W n");\r
67 }, $fz.isPrivate = true, $fz), "~N,~N,~N,~N");\r
68 Clazz.defineMethod (c$, "moveto", \r
69 function (x, y) {\r
70 this.g (x + " " + y + " m");\r
71 }, "~N,~N");\r
72 Clazz.defineMethod (c$, "lineto", \r
73 function (x, y) {\r
74 this.g (x + " " + y + " l");\r
75 }, "~N,~N");\r
76 Clazz.defineMethod (c$, "newObject", \r
77 ($fz = function (type) {\r
78 var o =  new javajs["export"].PDFObject (++this.count);\r
79 if (type != null) o.addDef ("Type", "/" + type);\r
80 this.indirectObjects.addLast (o);\r
81 return o;\r
82 }, $fz.isPrivate = true, $fz), "~S");\r
83 Clazz.defineMethod (c$, "addInfo", \r
84 function (data) {\r
85 var info =  new java.util.Hashtable ();\r
86 for (var e, $e = data.entrySet ().iterator (); $e.hasNext () && ((e = $e.next ()) || true);) {\r
87 var value = "(" + e.getValue ().$replace (')', '_').$replace ('(', '_') + ")";\r
88 info.put (e.getKey (), value);\r
89 }\r
90 this.root.addDef ("Info", info);\r
91 }, "java.util.Map");\r
92 Clazz.defineMethod (c$, "addFontResource", \r
93 ($fz = function (fname) {\r
94 var f = this.newObject ("Font");\r
95 this.fonts.put (fname, f);\r
96 f.addDef ("BaseFont", fname);\r
97 f.addDef ("Encoding", "/WinAnsiEncoding");\r
98 f.addDef ("Subtype", "/Type1");\r
99 this.graphics.addResource ("Font", f.getID (), f.getRef ());\r
100 return f;\r
101 }, $fz.isPrivate = true, $fz), "~S");\r
102 Clazz.defineMethod (c$, "addImageResource", \r
103 function (newImage, width, height, buffer, isRGB) {\r
104 var imageObj = this.newObject ("XObject");\r
105 if (this.images == null) this.images =  new java.util.Hashtable ();\r
106 this.images.put (newImage, imageObj);\r
107 imageObj.addDef ("Subtype", "/Image");\r
108 imageObj.addDef ("Length", "?");\r
109 imageObj.addDef ("ColorSpace", isRGB ? "/DeviceRGB" : "/DeviceGray");\r
110 imageObj.addDef ("BitsPerComponent", "8");\r
111 imageObj.addDef ("Width", "" + width);\r
112 imageObj.addDef ("Height", "" + height);\r
113 this.graphics.addResource ("XObject", imageObj.getID (), imageObj.getRef ());\r
114 var n = buffer.length;\r
115 var stream =  Clazz.newByteArray (n * (isRGB ? 3 : 1), 0);\r
116 if (isRGB) {\r
117 for (var i = 0, pt = 0; i < n; i++) {\r
118 stream[pt++] = ((buffer[i] >> 16) & 0xFF);\r
119 stream[pt++] = ((buffer[i] >> 8) & 0xFF);\r
120 stream[pt++] = (buffer[i] & 0xFF);\r
121 }\r
122 } else {\r
123 for (var i = 0; i < n; i++) stream[i] = buffer[i];\r
124 \r
125 }imageObj.setStream (stream);\r
126 this.graphics.addResource ("XObject", imageObj.getID (), imageObj.getRef ());\r
127 }, "~O,~N,~N,~A,~B");\r
128 Clazz.defineMethod (c$, "g", \r
129 function (cmd) {\r
130 this.graphics.append (cmd).appendC ('\n');\r
131 }, "~S");\r
132 Clazz.defineMethod (c$, "output", \r
133 ($fz = function (s) {\r
134 var b = s.getBytes ();\r
135 this.os.write (b, 0, b.length);\r
136 this.pt += b.length;\r
137 }, $fz.isPrivate = true, $fz), "~S");\r
138 Clazz.defineMethod (c$, "closeDocument", \r
139 function () {\r
140 this.g ("Q Q");\r
141 this.outputHeader ();\r
142 this.writeObjects ();\r
143 this.writeXRefTable ();\r
144 this.writeTrailer ();\r
145 this.os.flush ();\r
146 this.os.close ();\r
147 });\r
148 Clazz.defineMethod (c$, "outputHeader", \r
149 ($fz = function () {\r
150 this.output ("%PDF-1.3\n%");\r
151 var b =  Clazz.newByteArray (-1, [-1, -1, -1, -1]);\r
152 this.os.write (b, 0, b.length);\r
153 this.pt += 4;\r
154 this.output ("\n");\r
155 }, $fz.isPrivate = true, $fz));\r
156 Clazz.defineMethod (c$, "writeTrailer", \r
157 ($fz = function () {\r
158 var trailer =  new javajs["export"].PDFObject (-2);\r
159 this.output ("trailer");\r
160 trailer.addDef ("Size", "" + this.indirectObjects.size ());\r
161 trailer.addDef ("Root", this.root.getRef ());\r
162 trailer.output (this.os);\r
163 this.output ("startxref\n");\r
164 this.output ("" + this.xrefPt + "\n");\r
165 this.output ("%%EOF\n");\r
166 }, $fz.isPrivate = true, $fz));\r
167 Clazz.defineMethod (c$, "writeObjects", \r
168 ($fz = function () {\r
169 var nObj = this.indirectObjects.size ();\r
170 for (var i = 0; i < nObj; i++) {\r
171 var o = this.indirectObjects.get (i);\r
172 if (!o.isFont ()) continue;\r
173 o.pt = this.pt;\r
174 this.pt += o.output (this.os);\r
175 }\r
176 for (var i = 0; i < nObj; i++) {\r
177 var o = this.indirectObjects.get (i);\r
178 if (o.isFont ()) continue;\r
179 o.pt = this.pt;\r
180 this.pt += o.output (this.os);\r
181 }\r
182 }, $fz.isPrivate = true, $fz));\r
183 Clazz.defineMethod (c$, "writeXRefTable", \r
184 ($fz = function () {\r
185 this.xrefPt = this.pt;\r
186 var nObj = this.indirectObjects.size ();\r
187 var sb =  new javajs.util.SB ();\r
188 sb.append ("xref\n0 " + (nObj + 1) + "\n0000000000 65535 f\r\n");\r
189 for (var i = 0; i < nObj; i++) {\r
190 var o = this.indirectObjects.get (i);\r
191 var s = "0000000000" + o.pt;\r
192 sb.append (s.substring (s.length - 10));\r
193 sb.append (" 00000 n\r\n");\r
194 }\r
195 this.output (sb.toString ());\r
196 }, $fz.isPrivate = true, $fz));\r
197 Clazz.defineMethod (c$, "canDoLineTo", \r
198 function () {\r
199 return true;\r
200 });\r
201 Clazz.defineMethod (c$, "fill", \r
202 function () {\r
203 this.g ("f");\r
204 });\r
205 Clazz.defineMethod (c$, "stroke", \r
206 function () {\r
207 this.g ("S");\r
208 });\r
209 Clazz.defineMethod (c$, "doCircle", \r
210 function (x, y, r, doFill) {\r
211 var d = r * 4 * (Math.sqrt (2) - 1) / 3;\r
212 var dx = x;\r
213 var dy = y;\r
214 this.g ((dx + r) + " " + dy + " m");\r
215 this.g ((dx + r) + " " + (dy + d) + " " + (dx + d) + " " + (dy + r) + " " + (dx) + " " + (dy + r) + " " + " c");\r
216 this.g ((dx - d) + " " + (dy + r) + " " + (dx - r) + " " + (dy + d) + " " + (dx - r) + " " + (dy) + " c");\r
217 this.g ((dx - r) + " " + (dy - d) + " " + (dx - d) + " " + (dy - r) + " " + (dx) + " " + (dy - r) + " c");\r
218 this.g ((dx + d) + " " + (dy - r) + " " + (dx + r) + " " + (dy - d) + " " + (dx + r) + " " + (dy) + " c");\r
219 this.g (doFill ? "f" : "s");\r
220 }, "~N,~N,~N,~B");\r
221 Clazz.defineMethod (c$, "doPolygon", \r
222 function (axPoints, ayPoints, nPoints, doFill) {\r
223 this.moveto (axPoints[0], ayPoints[0]);\r
224 for (var i = 1; i < nPoints; i++) this.lineto (axPoints[i], ayPoints[i]);\r
225 \r
226 this.g (doFill ? "f" : "s");\r
227 }, "~A,~A,~N,~B");\r
228 Clazz.defineMethod (c$, "doRect", \r
229 function (x, y, width, height, doFill) {\r
230 this.g (x + " " + y + " " + width + " " + height + " re " + (doFill ? "f" : "s"));\r
231 }, "~N,~N,~N,~N,~B");\r
232 Clazz.defineMethod (c$, "drawImage", \r
233 function (image, destX0, destY0, destX1, destY1, srcX0, srcY0, srcX1, srcY1) {\r
234 var imageObj = this.images.get (image);\r
235 if (imageObj == null) return;\r
236 this.g ("q");\r
237 this.clip (destX0, destY0, destX1, destY1);\r
238 var iw = Double.parseDouble (imageObj.getDef ("Width"));\r
239 var ih = Double.parseDouble (imageObj.getDef ("Height"));\r
240 var dw = (destX1 - destX0 + 1);\r
241 var dh = (destY1 - destY0 + 1);\r
242 var sw = (srcX1 - srcX0 + 1);\r
243 var sh = (srcY1 - srcY0 + 1);\r
244 var scaleX = dw / sw;\r
245 var scaleY = dh / sh;\r
246 var transX = destX0 - srcX0 * scaleX;\r
247 var transY = destY0 + (ih - srcY0) * scaleY;\r
248 this.g (scaleX * iw + " 0 0 " + -scaleY * ih + " " + transX + " " + transY + " cm");\r
249 this.g ("/" + imageObj.getID () + " Do");\r
250 this.g ("Q");\r
251 }, "~O,~N,~N,~N,~N,~N,~N,~N,~N");\r
252 Clazz.defineMethod (c$, "drawStringRotated", \r
253 function (s, x, y, angle) {\r
254 this.g ("q " + this.getRotation (angle) + " " + x + " " + y + " cm BT(" + s + ")Tj ET Q");\r
255 }, "~S,~N,~N,~N");\r
256 Clazz.defineMethod (c$, "getRotation", \r
257 function (angle) {\r
258 var cos = 0;\r
259 var sin = 0;\r
260 switch (angle) {\r
261 case 0:\r
262 cos = 1;\r
263 break;\r
264 case 90:\r
265 sin = 1;\r
266 break;\r
267 case -90:\r
268 sin = -1;\r
269 break;\r
270 case 180:\r
271 cos = -1;\r
272 break;\r
273 default:\r
274 var a = (angle / 180.0 * 3.141592653589793);\r
275 cos = Math.cos (a);\r
276 sin = Math.sin (a);\r
277 if (Math.abs (cos) < 0.0001) cos = 0;\r
278 if (Math.abs (sin) < 0.0001) sin = 0;\r
279 }\r
280 return cos + " " + sin + " " + sin + " " + -cos;\r
281 }, "~N");\r
282 Clazz.defineMethod (c$, "setColor", \r
283 function (rgb, isFill) {\r
284 this.g (rgb[0] + " " + rgb[1] + " " + rgb[2] + (isFill ? " rg" : " RG"));\r
285 }, "~A,~B");\r
286 Clazz.defineMethod (c$, "setFont", \r
287 function (fname, size) {\r
288 var f = this.fonts.get (fname);\r
289 if (f == null) f = this.addFontResource (fname);\r
290 this.g ("/" + f.getID () + " " + size + " Tf");\r
291 }, "~S,~N");\r
292 Clazz.defineMethod (c$, "setLineWidth", \r
293 function (width) {\r
294 this.g (width + " w");\r
295 }, "~N");\r
296 Clazz.defineMethod (c$, "translateScale", \r
297 function (x, y, scale) {\r
298 this.g (scale + " 0 0 " + scale + " " + x + " " + y + " cm");\r
299 }, "~N,~N,~N");\r
300 });\r