OSDN Git Service

053d94dbb455cb157408ad575a530c4c74e84644
[dvibrowser/dvi2epub.git] / src / jp / sourceforge / dvibrowser / dvicore / special / EmbeddedPostScript.java
1 /*
2  * Copyright (c) 2009, Takeyuki Nagao
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or
6  * without modification, are permitted provided that the
7  * following conditions are met:
8  * 
9  *  * Redistributions of source code must retain the above
10  *    copyright notice, this list of conditions and the
11  *    following disclaimer.
12  *  * Redistributions in binary form must reproduce the above
13  *    copyright notice, this list of conditions and the
14  *    following disclaimer in the documentation and/or other
15  *    materials provided with the distribution.
16  *    
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
29  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30  * OF SUCH DAMAGE.
31  */
32
33 package jp.sourceforge.dvibrowser.dvicore.special;
34
35 import java.io.File;
36 import java.io.PrintWriter;
37 import java.io.StringWriter;
38 import java.util.HashMap;
39 import java.util.Vector;
40
41 import jp.sourceforge.dvibrowser.dvicore.DviException;
42 import jp.sourceforge.dvibrowser.dvicore.DviObject;
43 import jp.sourceforge.dvibrowser.dvicore.DviUnit;
44 import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
45 import jp.sourceforge.dvibrowser.dvicore.util.DviUtils;
46
47
48 public class EmbeddedPostScript
49 {
50 //  private static final Logger LOGGER = Logger.getLogger(EmbeddedPostScript.class.getName());
51   
52   private final Vector<Prologue> prologues = new Vector<Prologue>();
53   private final Vector<Global> globals = new Vector<Global>();
54   private final HashMap<Integer, Vector<Local>> page2locals
55     = new HashMap<Integer, Vector<Local>>();
56
57   private Vector<Local> locals = null;
58
59   public void beginPage(int pageNum)
60   {
61     if (page2locals.containsKey(pageNum)) {
62       locals = page2locals.get(pageNum);
63     } else {
64       locals = new Vector<Local>();
65       page2locals.put(pageNum, locals);
66     }
67   }
68
69   public void endPage()
70   {
71     locals = null;
72   }
73
74   public void add(Prologue a)
75   {
76     prologues.add(a);
77   }
78
79   public void add(Global a)
80   {
81     globals.add(a);
82   }
83
84   public void add(Local a)
85   {
86     locals.add(a);
87   }
88
89   private static void writePostScript(Vector<? extends Element> ce,
90       PrintWriter pw, Config cfg) throws DviException
91   {
92     for (Element e : ce) {
93       e.writePostScript(pw, cfg);
94     }
95   }
96
97   public String toPostScript(int pageNum, int dpi) 
98   throws DviException
99   {
100     if (!page2locals.containsKey(pageNum))
101       return null;
102
103     Vector<Local> ls = page2locals.get(pageNum);
104
105     if (ls == null || ls.size() == 0)
106       return null;
107
108     Config cfg = new Config(dpi);
109
110     try {
111       StringWriter sw = new StringWriter();
112       PrintWriter pw = new PrintWriter(sw);
113
114       pw.println("%!PS-Adobe-2.0");
115       pw.println("%%Pages: 1");
116       pw.println("%%BoundingBox: 0 0 595 842"); // Change bounding box depending on paper sizes.
117       pw.println("%%EndComments");
118       pw.println("%!");
119
120       writePostScript(prologues, pw, cfg);
121
122       // TODO: Use the paper size to set the bounding boxes
123       pw.println(
124           "TeXDict begin"
125         + " 39158280 55380996 "
126         + " 1000 "
127         + dpi + " " + dpi
128         + " (a.dvi) "
129         + " @start end "
130       );
131       pw.println("TeXDict begin 1 0 bop 0 0 a");
132
133       writePostScript(globals, pw, cfg);
134
135       writePostScript(ls, pw, cfg);
136
137       pw.println("end");
138       pw.println("showpage");
139       pw.close();
140       sw.flush();
141       return sw.toString();
142     } catch (Exception ex) {
143       throw new DviException(ex);
144     }
145   }
146
147   private static class Config
148   {
149     public final int dpi;
150     private Config(int dpi) {
151       this.dpi = dpi;
152     }
153   }
154
155   private static interface Element
156   {
157     public abstract void writePostScript(PrintWriter pw, Config cfg) throws DviException;
158   }
159
160   public static interface Local extends Element {}
161   public static interface Global extends Element {}
162   public static interface Prologue extends Element {}
163
164   public static class ProloguePostScript
165   {
166     public final String postScript;
167     public ProloguePostScript(String postScript) {
168       this.postScript = postScript;
169     }
170
171     public void writePostScript(PrintWriter pw, Config cfg)
172     {
173       pw.println(postScript);
174     }
175   }
176   
177   // TODO: support encoding.
178   private static String escapeFilenameForPS(String s)
179   {
180     return s.replaceAll("\\\\", "\\\\\\\\");
181   }
182
183   public static class PrologueFile
184   extends DviObject
185   implements Prologue
186   {
187     public final String fileName;
188     public PrologueFile(DviContextSupport dcs, String fileName) {
189       super(dcs);
190       this.fileName = fileName;
191     }
192
193     public void writePostScript(PrintWriter pw, Config cfg) throws DviException
194     {
195       File file = DviUtils.toLocalFile(getDviContext().getDviResource(fileName));
196       if (file == null || !file.exists())
197         throw new DviException("Cannot find postscript prologue: " + fileName);
198
199       String escapedFilename = escapeFilenameForPS(file.getAbsolutePath());
200       pw.println(
201           " (" + escapedFilename + ") run"
202       );
203     }
204   }
205
206   public static class HeaderSpecial
207   implements Global
208   {
209     public final String fileName;
210     public HeaderSpecial(String fileName) {
211       this.fileName = fileName;
212     }
213
214     public void writePostScript(PrintWriter pw, Config cfg)
215     {
216       String escapedFilename = escapeFilenameForPS(fileName);
217       pw.println(
218         " (" + escapedFilename + ") run"
219       );
220     }
221   }
222
223   public static class BangSpecial
224   implements Global
225   {
226     public final String postScript;
227     public BangSpecial(String postScript) {
228       this.postScript = postScript;
229     }
230
231     public void writePostScript(PrintWriter pw, Config cfg)
232     {
233       pw.println(
234         " @defspecial " + postScript + " @fedspecial"
235       );
236     }
237   }
238
239   private static class WithReferencePoint
240   implements Local
241   {
242     public final int h;
243     public final int v;
244     public final DviUnit dviUnit;
245     private WithReferencePoint(int h, int v, DviUnit dviUnit)
246     {
247       this.h = h;
248       this.v = v;
249       this.dviUnit = dviUnit;
250     }
251
252     public void writePostScript(PrintWriter pw, Config cfg)
253     {
254       double psH = dviUnit.mapToPixelDouble(h, cfg.dpi);
255       double psV = dviUnit.mapToPixelDouble(v, cfg.dpi);
256       pw.println(
257         " " + psH + " " + psV + " moveto "
258       );
259     }
260   }
261
262   public static class PSFileSpecial
263   extends WithReferencePoint
264   {
265     public final String fileName;
266     public final int llx;
267     public final int lly;
268     public final int urx;
269     public final int ury;
270     public final int rwi;
271     public final int rhi;
272     public final int angle;
273     public PSFileSpecial(
274       int h, int v, DviUnit dviUnit,
275       String fileName,
276       int llx, int lly, int urx, int ury,
277       int rwi, int rhi, int angle
278     ) {
279       super(h, v, dviUnit);
280       this.fileName = fileName;
281       this.llx = llx;
282       this.lly = lly;
283       this.urx = urx;
284       this.ury = ury;
285       this.rwi = rwi;
286       this.rhi = rhi;
287       this.angle = angle;
288     }
289
290     public void writePostScript(PrintWriter pw, Config cfg)
291     {
292       super.writePostScript(pw, cfg);
293       String escapedFilename = escapeFilenameForPS(fileName);
294 //      if (new File(realFile).exists()) {
295         pw.println(
296             " @beginspecial"
297           + " " + llx + " @llx"
298           + " " + lly + " @lly"
299           + " " + urx + " @urx"
300           + " " + ury + " @ury"
301           + ((rwi != 0) ? (" " + rwi + " @rwi") : "")
302           + ((rhi != 0) ? (" " + rhi + " @rhi") : "")
303           + ((angle != 0) ? (" " + angle + " @angle") : "")
304           + " @setspecial"
305           + " (" + escapedFilename + ") run"
306           + " @endspecial"
307         );
308 //      } else {
309 //      }
310     }
311   }
312
313   public static class PSSpecial
314   extends WithReferencePoint
315   {
316     public final String postScript;
317     public PSSpecial(int h, int v, DviUnit dviUnit, String postScript)
318     {
319       super(h, v, dviUnit);
320       this.postScript = postScript;
321     }
322
323     public void writePostScript(PrintWriter pw, Config cfg)
324     {
325       super.writePostScript(pw, cfg);
326       pw.println(
327         " " + postScript
328       );
329     }
330   }
331
332   public static class QuoteSpecial
333   extends PSSpecial
334   {
335     public QuoteSpecial(int h, int v, DviUnit dviUnit, String postScript)
336     {
337       super(h, v, dviUnit, postScript);
338     }
339
340     public void writePostScript(PrintWriter pw, Config cfg)
341     {
342       super.writePostScript(pw, cfg);
343       pw.println(
344           " @beginspecial"
345         + " @setspecial"
346         + " " + postScript
347         + " @endspecial"
348       );
349     }
350   }
351 }