--- /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.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();
+ }
+}