OSDN Git Service

Change directory structure.
[dvibrowser/dvi2epub.git] / src / main / java / jp / sourceforge / dvibrowser / dvicore / special / EmbeddedPostScript.java
diff --git a/src/main/java/jp/sourceforge/dvibrowser/dvicore/special/EmbeddedPostScript.java b/src/main/java/jp/sourceforge/dvibrowser/dvicore/special/EmbeddedPostScript.java
new file mode 100644 (file)
index 0000000..053d94d
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2009, Takeyuki Nagao
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ * 
+ *  * Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *    
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+package jp.sourceforge.dvibrowser.dvicore.special;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Vector;
+
+import jp.sourceforge.dvibrowser.dvicore.DviException;
+import jp.sourceforge.dvibrowser.dvicore.DviObject;
+import jp.sourceforge.dvibrowser.dvicore.DviUnit;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
+import jp.sourceforge.dvibrowser.dvicore.util.DviUtils;
+
+
+public class EmbeddedPostScript
+{
+//  private static final Logger LOGGER = Logger.getLogger(EmbeddedPostScript.class.getName());
+  
+  private final Vector<Prologue> prologues = new Vector<Prologue>();
+  private final Vector<Global> globals = new Vector<Global>();
+  private final HashMap<Integer, Vector<Local>> page2locals
+    = new HashMap<Integer, Vector<Local>>();
+
+  private Vector<Local> locals = null;
+
+  public void beginPage(int pageNum)
+  {
+    if (page2locals.containsKey(pageNum)) {
+      locals = page2locals.get(pageNum);
+    } else {
+      locals = new Vector<Local>();
+      page2locals.put(pageNum, locals);
+    }
+  }
+
+  public void endPage()
+  {
+    locals = null;
+  }
+
+  public void add(Prologue a)
+  {
+    prologues.add(a);
+  }
+
+  public void add(Global a)
+  {
+    globals.add(a);
+  }
+
+  public void add(Local a)
+  {
+    locals.add(a);
+  }
+
+  private static void writePostScript(Vector<? extends Element> ce,
+      PrintWriter pw, Config cfg) throws DviException
+  {
+    for (Element e : ce) {
+      e.writePostScript(pw, cfg);
+    }
+  }
+
+  public String toPostScript(int pageNum, int dpi) 
+  throws DviException
+  {
+    if (!page2locals.containsKey(pageNum))
+      return null;
+
+    Vector<Local> ls = page2locals.get(pageNum);
+
+    if (ls == null || ls.size() == 0)
+      return null;
+
+    Config cfg = new Config(dpi);
+
+    try {
+      StringWriter sw = new StringWriter();
+      PrintWriter pw = new PrintWriter(sw);
+
+      pw.println("%!PS-Adobe-2.0");
+      pw.println("%%Pages: 1");
+      pw.println("%%BoundingBox: 0 0 595 842"); // Change bounding box depending on paper sizes.
+      pw.println("%%EndComments");
+      pw.println("%!");
+
+      writePostScript(prologues, pw, cfg);
+
+      // TODO: Use the paper size to set the bounding boxes
+      pw.println(
+          "TeXDict begin"
+        + " 39158280 55380996 "
+        + " 1000 "
+        + dpi + " " + dpi
+        + " (a.dvi) "
+        + " @start end "
+      );
+      pw.println("TeXDict begin 1 0 bop 0 0 a");
+
+      writePostScript(globals, pw, cfg);
+
+      writePostScript(ls, pw, cfg);
+
+      pw.println("end");
+      pw.println("showpage");
+      pw.close();
+      sw.flush();
+      return sw.toString();
+    } catch (Exception ex) {
+      throw new DviException(ex);
+    }
+  }
+
+  private static class Config
+  {
+    public final int dpi;
+    private Config(int dpi) {
+      this.dpi = dpi;
+    }
+  }
+
+  private static interface Element
+  {
+    public abstract void writePostScript(PrintWriter pw, Config cfg) throws DviException;
+  }
+
+  public static interface Local extends Element {}
+  public static interface Global extends Element {}
+  public static interface Prologue extends Element {}
+
+  public static class ProloguePostScript
+  {
+    public final String postScript;
+    public ProloguePostScript(String postScript) {
+      this.postScript = postScript;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      pw.println(postScript);
+    }
+  }
+  
+  // TODO: support encoding.
+  private static String escapeFilenameForPS(String s)
+  {
+    return s.replaceAll("\\\\", "\\\\\\\\");
+  }
+
+  public static class PrologueFile
+  extends DviObject
+  implements Prologue
+  {
+    public final String fileName;
+    public PrologueFile(DviContextSupport dcs, String fileName) {
+      super(dcs);
+      this.fileName = fileName;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg) throws DviException
+    {
+      File file = DviUtils.toLocalFile(getDviContext().getDviResource(fileName));
+      if (file == null || !file.exists())
+        throw new DviException("Cannot find postscript prologue: " + fileName);
+
+      String escapedFilename = escapeFilenameForPS(file.getAbsolutePath());
+      pw.println(
+          " (" + escapedFilename + ") run"
+      );
+    }
+  }
+
+  public static class HeaderSpecial
+  implements Global
+  {
+    public final String fileName;
+    public HeaderSpecial(String fileName) {
+      this.fileName = fileName;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      String escapedFilename = escapeFilenameForPS(fileName);
+      pw.println(
+        " (" + escapedFilename + ") run"
+      );
+    }
+  }
+
+  public static class BangSpecial
+  implements Global
+  {
+    public final String postScript;
+    public BangSpecial(String postScript) {
+      this.postScript = postScript;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      pw.println(
+        " @defspecial " + postScript + " @fedspecial"
+      );
+    }
+  }
+
+  private static class WithReferencePoint
+  implements Local
+  {
+    public final int h;
+    public final int v;
+    public final DviUnit dviUnit;
+    private WithReferencePoint(int h, int v, DviUnit dviUnit)
+    {
+      this.h = h;
+      this.v = v;
+      this.dviUnit = dviUnit;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      double psH = dviUnit.mapToPixelDouble(h, cfg.dpi);
+      double psV = dviUnit.mapToPixelDouble(v, cfg.dpi);
+      pw.println(
+        " " + psH + " " + psV + " moveto "
+      );
+    }
+  }
+
+  public static class PSFileSpecial
+  extends WithReferencePoint
+  {
+    public final String fileName;
+    public final int llx;
+    public final int lly;
+    public final int urx;
+    public final int ury;
+    public final int rwi;
+    public final int rhi;
+    public final int angle;
+    public PSFileSpecial(
+      int h, int v, DviUnit dviUnit,
+      String fileName,
+      int llx, int lly, int urx, int ury,
+      int rwi, int rhi, int angle
+    ) {
+      super(h, v, dviUnit);
+      this.fileName = fileName;
+      this.llx = llx;
+      this.lly = lly;
+      this.urx = urx;
+      this.ury = ury;
+      this.rwi = rwi;
+      this.rhi = rhi;
+      this.angle = angle;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      super.writePostScript(pw, cfg);
+      String escapedFilename = escapeFilenameForPS(fileName);
+//      if (new File(realFile).exists()) {
+        pw.println(
+            " @beginspecial"
+          + " " + llx + " @llx"
+          + " " + lly + " @lly"
+          + " " + urx + " @urx"
+          + " " + ury + " @ury"
+          + ((rwi != 0) ? (" " + rwi + " @rwi") : "")
+          + ((rhi != 0) ? (" " + rhi + " @rhi") : "")
+          + ((angle != 0) ? (" " + angle + " @angle") : "")
+          + " @setspecial"
+          + " (" + escapedFilename + ") run"
+          + " @endspecial"
+        );
+//      } else {
+//      }
+    }
+  }
+
+  public static class PSSpecial
+  extends WithReferencePoint
+  {
+    public final String postScript;
+    public PSSpecial(int h, int v, DviUnit dviUnit, String postScript)
+    {
+      super(h, v, dviUnit);
+      this.postScript = postScript;
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      super.writePostScript(pw, cfg);
+      pw.println(
+        " " + postScript
+      );
+    }
+  }
+
+  public static class QuoteSpecial
+  extends PSSpecial
+  {
+    public QuoteSpecial(int h, int v, DviUnit dviUnit, String postScript)
+    {
+      super(h, v, dviUnit, postScript);
+    }
+
+    public void writePostScript(PrintWriter pw, Config cfg)
+    {
+      super.writePostScript(pw, cfg);
+      pw.println(
+          " @beginspecial"
+        + " @setspecial"
+        + " " + postScript
+        + " @endspecial"
+      );
+    }
+  }
+}