OSDN Git Service

Change directory structure.
[dvibrowser/dvi2epub.git] / src / main / java / jp / sourceforge / dvibrowser / dvicore / font / PackedGlyphRasterizer.java
diff --git a/src/main/java/jp/sourceforge/dvibrowser/dvicore/font/PackedGlyphRasterizer.java b/src/main/java/jp/sourceforge/dvibrowser/dvicore/font/PackedGlyphRasterizer.java
new file mode 100644 (file)
index 0000000..9a00e64
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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.font;
+
+import jp.sourceforge.dvibrowser.dvicore.DviException;
+import jp.sourceforge.dvibrowser.dvicore.api.BinaryDevice;
+
+// not thread-safe.
+
+public final class PackedGlyphRasterizer
+{
+  private PkGlyph glyph;
+  private byte [] buf;
+  private int dynF, dynG, dynH;
+  private boolean highNyb;
+  private int offset;
+
+  public void begin(PkGlyph glyph)
+  {
+    this.glyph = glyph;
+    buf = glyph.raster();
+    dynF = glyph.dynF();
+    dynG = ((13-dynF) << 4) + dynF + 1;
+    dynH = ((dynF+1)<<4) - dynF - 1; // 15 * (dynF + 1)
+    offset = 0;
+    highNyb = true;
+  }
+
+  public void end()
+  {
+    glyph = null;
+    buf = null;
+  }
+
+  private int getNybble()
+  throws DviException
+  {
+    if (highNyb) {
+      highNyb = false;
+      return ((buf[offset] >> 4) & 15);
+    } else {
+      highNyb = true;
+      return (buf[offset++] & 15);
+    }
+  }
+
+  private int repeat = 0;
+
+  private int getPackedNumInternal(boolean recursed)
+  throws DviException
+  {
+    int i = getNybble();
+    if (i == 0) {
+      int j;
+      do {
+        j = getNybble();
+        i++;
+      } while (j == 0);
+      while (i-- > 0) {
+        j = (j << 4) | getNybble();
+      }
+      return j - 16 + dynG;
+    } else {
+      if (i <= dynF) {
+        return i;
+      } else if (i < 14) { // dynF < i < 14
+        return (i << 4) + getNybble() - dynH;
+      } else {
+        if (recursed)
+          throw new IllegalStateException
+            ("too many levels of recursion");
+        if (i == 14) {
+          repeat = getPackedNumInternal(true);
+        } else // i == 15
+          repeat = 1;
+        return getPackedNumInternal(true);
+      }
+    }
+  }
+
+  public int getPackedNum()
+  throws DviException
+  {
+    return getPackedNumInternal(false);
+  }
+
+  public void rasterizeTo(final BinaryDevice out)
+  throws DviException 
+  {
+    boolean paintFlag = glyph.turnOn();
+    int w = glyph.width();
+    int h = glyph.height();
+    if (w <= 0 || h <= 0)
+      return;
+    if (out.beginRaster(w, h)) {
+      out.beginLine();
+      while (h > 0) {
+        int count = getPackedNum();
+        while (count > 0) {
+          if (count < w) {
+            out.putBits(count, paintFlag);
+            w -= count;
+            break;
+          } else {
+            out.putBits(w, paintFlag);
+            out.endLine(repeat);
+            count -= w;
+            h -= repeat + 1;
+            w = glyph.width();
+            repeat = 0;
+            out.beginLine();
+          }
+        }
+        paintFlag = !paintFlag;
+      }
+    }
+    out.endRaster();
+  }
+}