--- /dev/null
+/*
+ * 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"
+ );
+ }
+ }
+}