From: adam Date: Sun, 8 Feb 2004 21:08:18 +0000 (+0000) Subject: fixed empty org/ibex/translators files X-Git-Tag: RC3~67 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=9bc90f867f60607607b7e84980264a3c473a622e fixed empty org/ibex/translators files darcs-hash:20040208210818-5007d-b6c3b80bd28be0c17e675bc48afd5ea3d5a40ab7.gz --- diff --git a/src/org/ibex/translators/Freetype.c b/src/org/ibex/translators/Freetype.c index adef007..2a1c798 100644 --- a/src/org/ibex/translators/Freetype.c +++ b/src/org/ibex/translators/Freetype.c @@ -1 +1,107 @@ // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] + +#include +#include + +/* NOTE: _user_info is defined in crt0.c. It points to a 4096 byte + block of memory that contains 1024 32-bit values that can be set + with the setUserInfo() method of MIPSEmu. + + The VM will pause after initialization. When unpaused, it expects + that: + + user_info[0] = ptr to font byte stream in memory + user_info[1] = length of font stream + user_info[2] = unicode index of first glyph to render + user_info[3] = unicode index of last glyph to render + user_info[4] = point size to render in + + The VM will then iterate over the requested glyphs, performing the + following actions for each glyph: + + - render the glyph + - store the address of the glyph bitmap in user_info[5] + - store the width of the glyph bitmap in user_info[6] + - store the height of the glyph bitmap in user_info[7] + - store the font's ascender into user_info[8] + - store the font's height into user_info[9] + - store the glyph's ascender into user_info[10] + - store the glyph's advance into user_info[11] + + The VM will then pause after each glyph. The VM should not be + unpaused after the last glyph until the next glyph set has been + configured in user_info (ie it does not pause twice). + +*/ + +extern char *user_info[1024]; + +#define FT_Check(expr) do { \ + if((expr) != 0) { \ + errprint(#expr " failed\n"); \ + exit(EXIT_FAILURE); \ + } \ +} while(0) + +#define max(a, b) ((a) > (b) ? (a) : (b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static int errprint(const char *s) { + int l = strlen(s); + int n; + while(l) { + n = write(STDERR_FILENO,s,l); + if(n < 0) return n; + l -= n; + s += n; + } + return 0; +} + +extern void _pause(); + +int freetype_main() { + char *fontdata; + int glyph_index; + short charcode; + FT_Library library; /* handle to library */ + FT_Face face; /* handle to face object */ + + FT_Check(FT_Init_FreeType(&library)); + FT_Check(FT_New_Memory_Face(library, user_info[0], (int)user_info[1], 0, &face)); + + for(;;) { + + _pause(); + FT_Check(FT_Set_Char_Size(face, 0, ((int)user_info[4]) * 64, 72, 72)); + for(charcode = (int)user_info[2]; charcode <= (int)user_info[3]; charcode++) { + + glyph_index = FT_Get_Char_Index(face, charcode); + FT_Check(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT)); + FT_Check(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)); + + user_info[5] = (char*)face->glyph->bitmap.buffer; + user_info[6] = (char*)face->glyph->bitmap.width; + user_info[7] = (char*)face->glyph->bitmap.rows; + user_info[8] = (char*)(face->size->metrics.ascender >> 6); + user_info[9] = (char*)((-1 * face->size->metrics.descender) >> 6); + user_info[10] = (char*)(face->glyph->metrics.horiBearingY >> 6); + user_info[11] = (char*)(face->glyph->advance.x >> 6); + + } + } +} + + +// Kerning code; add back in later +/* +if (old_glyph_index != -1) { + if (FT_HAS_KERNING(face)) { + FT_Check(FT_Get_Kerning(face, old_glyph_index, glyph_index, 0, &kerning)); + x += kerning.x >> 6; + } else { + x += face->glyph->advance.x >> 6; + } +} +old_glyph_index = glyph_index; +*/ diff --git a/src/org/ibex/translators/Freetype.java b/src/org/ibex/translators/Freetype.java index e69de29..8131dfe 100644 --- a/src/org/ibex/translators/Freetype.java +++ b/src/org/ibex/translators/Freetype.java @@ -0,0 +1,67 @@ +package org.ibex.translators; +import org.ibex.*; +import org.ibex.util.*; +import java.io.*; +import java.util.zip.*; +import java.util.*; +import org.bouncycastle.util.encoders.Base64; + +import org.xwt.mips.Runtime; + +// FEATURE: use streams, not memoryfont's +// FEATURE: kerning pairs +public class Freetype { + + public Freetype() { } + + private int mem_allocated = 0; + private Runtime vm = null; + + private Stream loadedStream = null; + + public void loadFontByteStream(Stream res) { + try { + Log.info(this, "loading font " + res); + loadedStream = res; + InputStream is = Stream.getInputStream(res); + byte[] fontstream = InputStreamToByteArray.convert(is); + vm = (Runtime)Class.forName("org.ibex.translators.MIPSApps").newInstance(); + int baseAddr = vm.sbrk(fontstream.length); + vm.copyout(fontstream, baseAddr, fontstream.length); + vm.setUserInfo(0, baseAddr); + vm.setUserInfo(1, fontstream.length); + vm.start(new String[]{ "freetype" }); + vm.execute(); + if(vm.getState() == Runtime.DONE) throw new Error("Freetype VM exited: " + vm.exitStatus()); + } catch (Exception e) { + Log.info(this, e); + } + } + + public synchronized void renderGlyph(Font.Glyph glyph) throws IOException { + try { + Log.debug(this, "rasterizing glyph " + glyph.c + " of font " + glyph.font); + if (loadedStream != glyph.font.stream) loadFontByteStream(glyph.font.stream); + vm.setUserInfo(2, (int)glyph.c); + vm.setUserInfo(3, (int)glyph.c); + vm.setUserInfo(4, glyph.font.pointsize); + long start = System.currentTimeMillis(); + vm.execute(); + glyph.font.max_ascent = vm.getUserInfo(8); + glyph.font.max_descent = vm.getUserInfo(9); + glyph.baseline = vm.getUserInfo(10); + glyph.advance = vm.getUserInfo(11); + + glyph.width = vm.getUserInfo(6); + glyph.height = vm.getUserInfo(7); + + glyph.data = new byte[glyph.width * glyph.height]; + int addr = vm.getUserInfo(5); + vm.copyin(addr, glyph.data, glyph.width * glyph.height); + glyph.isLoaded = true; + + } catch (Exception e) { + Log.info(this, e); + } + } +} diff --git a/src/org/ibex/translators/GIF.java b/src/org/ibex/translators/GIF.java index e69de29..26b1a40 100644 --- a/src/org/ibex/translators/GIF.java +++ b/src/org/ibex/translators/GIF.java @@ -0,0 +1,446 @@ +/* + * This file was adapted from D J Hagberg's GifDecoder.java + * + * This software is copyrighted by D. J. Hagberg, Jr., and other parties. + * The following terms apply to all files associated with the software + * unless explicitly disclaimed in individual files. + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + * MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf of the + * U.S. government, the Government shall have only "Restricted Rights" + * in the software and related documentation as defined in the Federal + * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + * are acquiring the software on behalf of the Department of Defense, the + * software shall be classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in Clause + * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the + * authors grant the U.S. Government and others acting in its behalf + * permission to use and distribute the software in accordance with the + * terms specified in this license. + * + */ +package org.ibex.translators; + +import org.ibex.*; +import org.ibex.util.*; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.PrintWriter; + +/** Converts an InputStream carrying a GIF image into an ARGB int[] */ +public class GIF { + + // Public Methods ///////////////////////////////////////////////////////// + + private GIF() { } + + private static Queue instances = new Queue(10); + + public static void load(InputStream is, Picture p) { + GIF g = (GIF)instances.remove(false); + if (g == null) g = new GIF(); + try { + g._load(is, p); + } catch (Exception e) { + if (Log.on) Log.info(GIF.class, e); + return; + } + // FIXME: must reset fields + // if (instances.size() < 10) instances.append(g); + } + + private void _load(InputStream is, Picture p) throws IOException { + this.p = p; + if (is instanceof BufferedInputStream) _in = (BufferedInputStream)is; + else _in = new BufferedInputStream(is); + decodeAsBufferedImage(0); + p.isLoaded = true; + p = null; + _in = null; + } + + + /** Decode a particular frame from the GIF file. Frames must be decoded in order, starting with 0. */ + private void decodeAsBufferedImage(int page) throws IOException, IOException { + + // If the user requested a page already decoded, we cannot go back. + if (page <= index ) return; + + // If we just started reading this stream, initialize the global info. + if (index < 0 ) { + if (!readIntoBuf(6) || _buf[0] != 'G' || _buf[1] != 'I' || _buf[2] != 'F' || + _buf[3] != '8' || !(_buf[4] == '7' || _buf[4] == '9') || _buf[5] != 'a') + throw new IOException("Not a GIF8Xa file."); + if (!readGlobalImageDescriptor()) throw new IOException("Unable to read GIF header."); + } + + // Loop through the blocks in the image. + int block_identifier; + while (true) { + if(!readIntoBuf(1)) throw new IOException("Unexpected EOF(1)"); + block_identifier = _buf[0]; + if (block_identifier == ';') throw new IOException("No image data"); + if (block_identifier == '!') { + if (!readExtensionBlock()) throw new IOException("Unexpected EOF(2)"); + continue; + } + + // not a valid start character -- ignore it. + if (block_identifier != ',') continue; + + if (!readLocalImageDescriptor()) throw new IOException("Unexpected EOF(3)"); + p.data = new int[p.width * p.height]; + readImage(); + + // If we did not decode the requested index, need to go on + // to the next one (future implementations should consider + // caching already-decoded images here to allow for random + // access to animated GIF pages). + index++; + if (index < page) continue; + + // If we did decode the requested index, we can return. + break; + } + + // Return the image thus-far decoded + return; + } + + /** Actually read the image data */ + private void readImage() + throws IOException, IOException { + int len = p.width; + int rows = p.height; + int initialCodeSize; + int v; + int xpos = 0, ypos = 0, pass = 0, i; + int prefix[] = new int[(1 << MAX_LWZ_BITS)]; + int append[] = new int[(1 << MAX_LWZ_BITS)]; + int stack[] = new int[(1 << MAX_LWZ_BITS)*2]; + int top_idx; + int codeSize, clearCode, inCode, endCode, oldCode, maxCode, code, firstCode; + + // Initialize the decoder + if (!readIntoBuf(1)) throw new IOException("Unexpected EOF decoding image"); + initialCodeSize = _buf[0]; + + // Look at the right color map, setting up transparency if called for. + int[] cmap = global_color_map; + if (hascmap) cmap = color_map; + if (trans_idx >= 0) cmap[trans_idx] = 0x00000000; + + /* Initialize the decoder */ + /* Set values for "special" numbers: + * clear code reset the decoder + * end code stop decoding + * code size size of the next code to retrieve + * max code next available table position + */ + clearCode = 1 << initialCodeSize; + endCode = clearCode + 1; + codeSize = initialCodeSize + 1; + maxCode = clearCode + 2; + oldCode = -1; + firstCode = -1; + + for (i = 0; i < clearCode; i++) append[i] = i; + top_idx = 0; // top of stack. + + bitsInWindow = 0; + bytes = 0; + window = 0L; + done = false; + c = -1; + + /* Read until we finish the image */ + ypos = 0; + for (i = 0; i < rows; i++) { + for (xpos = 0; xpos < len;) { + + if (top_idx == 0) { + /* Bummer -- our stack is empty. Now we have to work! */ + code = getCode(codeSize); + if (code < 0) return; + + if (code > maxCode || code == endCode) return; + if (code == clearCode) { + codeSize = initialCodeSize + 1; + maxCode = clearCode + 2; + oldCode = -1; + continue; + } + + // Last pass reset the decoder, so the first code we + // see must be a singleton. Seed the stack with it, + // and set up the old/first code pointers for + // insertion into the string table. We can't just + // roll this into the clearCode test above, because + // at that point we have not yet read the next code. + if (oldCode == -1) { + stack[top_idx++] = append[code]; + oldCode = code; + firstCode = code; + continue; + } + + inCode = code; + + // maxCode is always one bigger than our + // highest assigned code. If the code we see + // is equal to maxCode, then we are about to + // add a new string to the table. ??? + if (code == maxCode) { + stack[top_idx++] = firstCode; + code = oldCode; + } + + // Populate the stack by tracing the string in the + // string table from its tail to its head + while (code > clearCode) { + stack[top_idx++] = append[code]; + code = prefix[code]; + } + firstCode = append[code]; + + // If there's no more room in our string table, quit. + // Otherwise, add a new string to the table + if (maxCode >= (1 << MAX_LWZ_BITS)) return; + + // Push the head of the string onto the stack + stack[top_idx++] = firstCode; + + // Add a new string to the string table + prefix[maxCode] = oldCode; + append[maxCode] = firstCode; + maxCode++; + + // maxCode tells us the maximum code value we can accept. + // If we see that we need more bits to represent it than + // we are requesting from the unpacker, we need to increase + // the number we ask for. + if ((maxCode >= (1 << codeSize)) && (maxCode < (1<= rows) { + pass++; + if (pass > 3) return; + ypos = _interlaceStart[pass]; + } + } else ypos++; + } + return; + } + + /** Extract the next compression code from the file. */ + private int getCode(int code_size) throws IOException { + int ret; + + while (bitsInWindow < code_size) { + // Not enough bits in our window to cover the request + if (done) return -1; + + if (bytes == 0) { + // Not enough bytes in our buffer to add to the window + bytes = getDataBlock(); + c = 0; + if (bytes <= 0) { + done = true; + break; + } + } + // Tack another byte onto the window, see if that's enough + window += (_buf[c]) << bitsInWindow; + ++c; + bitsInWindow += 8; + bytes--; + } + + + // The next code will always be the last code_size bits of the window + ret = ((int)window) & ((1 << code_size) - 1); + + // Shift data in the window to put the next code at the end + window >>= code_size; + bitsInWindow -= code_size; + return ret; + } + + /** Read the global image descriptor and optional global color map. Sets global_* variables. */ + private boolean readGlobalImageDescriptor() throws IOException { + int packed; + int aspect; // we ignore this. + int ofs; + + if (!readIntoBuf(7) ) return false; + global_width = _buf[0] | (_buf[1] << 8); + global_height = _buf[2] | (_buf[3] << 8); + packed = _buf[4]; + global_bgcolor = _buf[5]; + aspect = _buf[6]; + global_cmapsize = 2 << (packed & 0x07); + global_hascmap = (packed & GLOBALCOLORMAP) == GLOBALCOLORMAP; + global_color_map = null; + + // Read the color map, if we have one. + if (global_hascmap) { + if (!readColorMap(global_cmapsize,true)) { + return false; + } + } + + return true; + } + + /** Read a local image descriptor and optional local color map. */ + private boolean readLocalImageDescriptor() throws IOException { + int packed; + + if (!readIntoBuf(9) ) return false; + + left = _buf[0] | (_buf[1] << 8); + top = _buf[2] | (_buf[3] << 8); + p.width = _buf[4] | (_buf[5] << 8); + p.height = _buf[6] | (_buf[7] << 8); + packed = _buf[8]; + hascmap = (packed & LOCALCOLORMAP) == LOCALCOLORMAP; + cmapsize = 2 << (packed & 0x07); + interlaced = (packed & INTERLACE) == INTERLACE; + color_map = null; + + // Read the local color table, if there is one. + return !(hascmap && !readColorMap(cmapsize,false)); + } + + /** Read a color map (global or local). */ + private boolean readColorMap(int nColors, boolean isGlobal) + throws IOException { + int[] map = new int[nColors]; + for( int i=0; i < nColors; ++i) { + if (!readIntoBuf(3) ) return false; + map[i] = (_buf[0] << 16) | (_buf[1] << 8) | _buf[2] | 0xFF000000; + } + if (isGlobal) global_color_map = map; + else color_map = map; + return true; + } + + /** Read the contents of a GIF89a Graphical Extension Block. */ + private boolean readExtensionBlock() throws IOException { + if (!readIntoBuf(1) ) return false; + int label = _buf[0]; + int count = -1; + switch (label) { + case 0x01: // Plain Text Extension + case 0xff: // Application Extension + case 0xfe: // Comment Extension + break; + case 0xf9: // Graphic Control Extension + count = getDataBlock(); + if (count < 0) return true; + // Check for transparency setting. + if ((_buf[0] & HASTRANSPARENCY) != 0) trans_idx = _buf[3]; + else trans_idx = -1; + } + do { count = getDataBlock(); } while (count > 0); + return true; + } + + /** Read a block of data from the GIF file. */ + private int getDataBlock() throws IOException { + if (!readIntoBuf(1) ) return -1; + int count = _buf[0]; + if (count != 0) if (!readIntoBuf(count) ) return -1; + return count; + } + + /** Read the indicated number of bytes into _buf, our instance-wide buffer. */ + private boolean readIntoBuf(int count) throws IOException { + for(int i = 0; i < count; i++) if ((_buf[i] = _in.read()) == -1) return false; + return true; + } + + // Private Data ////////////////////////////////////////////////////////// + + private Picture p; + + // State management stuff + private int index = -1; + private BufferedInputStream _in = null; + private int[] _buf = new int[BUFSIZE]; + + // Transparency settings + private int trans_idx = -1; + + // Global image descriptor contents + private int global_width = 0; + private int global_height = 0; + private int global_bgcolor = 0; + private int global_cmapsize = 0; + private boolean global_hascmap = false; + private int[] global_color_map = null; + + // Local image descriptor contents + private int left = 0; + private int top = 0; + private int cmapsize = 0; + private boolean hascmap = false; + private boolean interlaced = false; + private int[] color_map = null; + + // Variables used in getCode(...) to track sliding bit-window. + private int bytes = 0; + private boolean done; + private int c; + private long window; + private int bitsInWindow = 0; + + // Class-wide constants. + private static final int INTERLACE = 0x40; + private static final int GLOBALCOLORMAP = 0x80; + private static final int LOCALCOLORMAP = 0x80; + private static final int HASTRANSPARENCY = 0x01; + private static final int MAX_LWZ_BITS = 12; + private static final int BUFSIZE = 280; + private static final int[] _interlaceStep = { 8, 8, 4, 2 }; + private static final int[] _interlaceStart = { 0, 4, 2, 1 }; +} + + + diff --git a/src/org/ibex/translators/HTML.java b/src/org/ibex/translators/HTML.java index e69de29..5b0811f 100644 --- a/src/org/ibex/translators/HTML.java +++ b/src/org/ibex/translators/HTML.java @@ -0,0 +1,341 @@ +// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] +package org.ibex.translators; + +import java.util.*; +import java.net.*; +import java.io.*; +import org.ibex.js.*; +import org.ibex.util.*; + +/* + * While entities are limited to a subset of Unicode characters , + * numeric character references can specify any character. Numeric + * character references may be given in decimal or hexadecimal, though + * browser support is stronger for decimal references. Decimal + * references are of the form &#number; while hexadecimal references + * take the case-insensitive form &#xnumber;. Examples of numeric + * character references include © or © for the copyright + * symbol, Α or Α for the Greek capital letter alpha, and + * ا or ا for the Arabic letter ALEF. + * + * http://www.htmlhelp.com/reference/html40/entities/special.html + * http://www.htmlhelp.com/reference/html40/entities/symbols.html + * http://www.htmlhelp.com/reference/html40/entities/latin1.html + */ + +/** + * This class parses an InputStream containing HTML and returns it + * as an XWT DOM tree. Each HTML Element is returned as a struct, + * with the following members: + * + * Since HTML may have multiple top level elements (unlike XML), + * this class will search all top level elements for one with a tag + * name 'html'. If such a node is found, only it is returned. If no + * top-level element has the tag name 'html', such a node is + * fabricated, and all top level elements become the children of + * that node, which is then returned. + */ +public class HTML { + + private final static String[] noEndTag = + new String[] { "area", "base", "basefont", "br", "col", "frame", "hr", "img", + "input", "isindex", "link", "meta", "param" }; + + /** we keep a char[] around for use by removeRedundantWhitespace() */ + private static char[] cbuf = null; + + /** we keep a StringBuffer around for use by removeRedundantWhitespace() */ + private static StringBuffer sbuf = null; + + /** true iff we have encountered an LI more recently than the last OL/UL */ + private static boolean withinLI = false; + + public static synchronized JS parseReader(Reader r) throws IOException, JSExn { + CharStream cs = new CharStream(r); + JS h = new JS(); + + withinLI = false; + h.put("$name", "html"); + + try { + while (true) parseBody(cs, h, null); + } catch (EOFException e) { + // continue until we get an EOFException + } + + /* FIXME + Object[] ids = h.keys(); + for(int i=0; ih. The + * CharStream should be positioned immediately after the + * open bracket. + * + * If a close tag not matching this open tag is found, the + * tagname on the close tag will be returned in order to + * facilitate correcting broken HTML. Otherwise, this returns + * null. + */ + private static String parseElement(CharStream cs, JS h) throws IOException, JSExn { + // scan element name + while(Character.isSpace(cs.peek())) cs.get(); + String elementName = parseElementName(cs); + + boolean saveWithinLI = withinLI; + if (elementName.equals("li")) { + if (withinLI) { + cs.unread(new char[] { '<', 'l', 'i', ' ' }); + return "li"; + } else { + withinLI = true; + } + } else if (elementName.equals("ol") || elementName.equals("ul")) { + withinLI = false; + } + + h.put("$name", elementName); + if (elementName.equals("!--")) { + h.put("0", parseComment(cs)); + h.put("$numchildren", new Integer(0)); + return null; + } + + // scan attributes + while (cs.peek() != '>') { + String name = parseAttributeName(cs); + if (name.equals("")) break; + String value = expandEntities(parseAttributeValue(cs)); + h.put(name, value); + } + + // eat the close-angle bracket + cs.get(); + + // bodyless tags return here + for(int i=0; i 0) { + h.put(String.valueOf(length), expanded); + h.put("$numchildren", new Integer(++length)); + } + cdata = ""; + + } catch (EOFException e) { + String expanded = removeRedundantWhitespace(expandEntities(cdata)); + if (expanded.length() > 0) { + h.put(String.valueOf(length), expanded); + h.put("$numchildren", new Integer(++length)); + } + throw e; + } + + try { + // scan subelement + if (cs.peek() != '/') { + JS kid = new JS(); + closetag = parseElement(cs, kid); + h.put(String.valueOf(length), kid); + h.put("$numchildren", new Integer(++length)); + + // scan close-tag + } else { + cs.get(); // drop the slash + closetag = parseElementName(cs); + while(cs.get() != '>'); + } + } catch (EOFException e) { + throw e; + + } + + if (closetag != null) + return closetag.equals(elementName) ? null : closetag; + } + } + + /** Parses an element name and returns it. The CharStream should + * be positioned at the first character of the name. + */ + private static String parseElementName(CharStream cs) throws IOException, JSExn { + String ret = ""; + while (cs.peek() != '>' && !Character.isSpace(cs.peek())) ret += cs.get(); + return ret.toLowerCase(); + } + + /** Parses an attribute name and returns it. The CharStream should + * be positioned at the first character of the name, possibly + * with intervening whitespace. + */ + private static String parseAttributeName(CharStream cs) throws IOException, JSExn { + while(Character.isSpace(cs.peek())) cs.get(); + String ret = ""; + while(!Character.isSpace(cs.peek()) && cs.peek() != '=' && cs.peek() != '>') ret += cs.get(); + return ret.toLowerCase(); + } + + /** Parses an attribute value and returns it. The CharStream + * should be positioned at the equals sign, possibly with + * intervening whitespace. + */ + private static String parseAttributeValue(CharStream cs) throws IOException, JSExn { + + // eat whitespace and equals sign + while(Character.isSpace(cs.peek())) cs.get(); + if (cs.peek() != '=') return ""; + cs.get(); + while(Character.isSpace(cs.peek())) cs.get(); + + boolean doublequoted = false; + boolean singlequoted = false; + String ret = ""; + + if (cs.peek() == '\"') { doublequoted = true; cs.get(); } + else if (cs.peek() == '\'') { singlequoted = true; cs.get(); } + + while(true) { + char c = cs.peek(); + if (!doublequoted && !singlequoted && (Character.isSpace(c) || c == '>')) break; + if (singlequoted && c == '\'') { cs.get(); break; } + if (doublequoted && c == '\"') { cs.get(); break; } + ret += cs.get(); + } + return ret; + } + + /** Parses a comment and returns its body. The CharStream should + * be positioned immediately after the <!-- + */ + private static String parseComment(CharStream cs) throws IOException, JSExn { + int dashes = 0; + String ret = ""; + while(true) { + char c = cs.get(); + if (c == '>' && dashes == 2) return ret.substring(0, ret.length() - 2); + if (c == '-') dashes++; + else dashes = 0; + ret += c; + } + } + + /** Expands all SGML entities in string s */ + public static String expandEntities(String s) throws IOException, JSExn { + if (s.indexOf('&') == -1) return s; + StringBuffer sb = new StringBuffer(); + int i=0; + int nextamp = 0; + while(nextamp != -1) { + nextamp = s.indexOf('&', i); + sb.append(nextamp == -1 ? s.substring(i) : s.substring(i, nextamp)); + if (nextamp == -1) break; + if (s.regionMatches(nextamp, "&", 0, 5)) { + sb.append("&"); + i = nextamp + 5; + } else if (s.regionMatches(nextamp, ">", 0, 4)) { + sb.append(">"); + i = nextamp + 4; + } else if (s.regionMatches(nextamp, "<", 0, 4)) { + sb.append("<"); + i = nextamp + 4; + } else if (s.regionMatches(nextamp, """, 0, 6)) { + sb.append("\""); + i = nextamp + 6; + } else if (s.regionMatches(nextamp, " ", 0, 6)) { + // FEATURE: perhaps we should distinguish this somehow + sb.append(" "); + i = nextamp + 6; + } else { + sb.append("&"); + i = nextamp + 1; + } + } + return sb.toString(); + } + + /** removes all redundant whitespace */ + private static String removeRedundantWhitespace(String s) throws JSExn { + + if (s.indexOf(' ') == -1 && s.indexOf('\n') == -1 && s.indexOf('\t') == -1 && s.indexOf('\r') == -1) return s; + + int len = s.length(); + if (cbuf == null || cbuf.length < len) { + cbuf = new char[len * 2]; + sbuf = new StringBuffer(len * 2); + } + sbuf.setLength(0); + s.getChars(0, len, cbuf, 0); + + int last = 0; + boolean lastWasWhitespace = false; + for(int i=0; i +#include +#include +#include +#include + +#include "mspack.h" + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX_MEMBERS 64 + +char *xstrdup(const char *s) { + char *ret = strdup(s); + if(ret == NULL) exit(1); + return ret; +} + +typedef struct { + char *addr; + int pos; + int size; + int length; + int writable; +} mem_buf_t; + +static mem_buf_t *cab_mem_buf = NULL; + +static void mem_buf_grow(mem_buf_t *buf,size_t newsize) { + size_t new_len; + char *p; + if(buf->length < 0) exit(1); + if(newsize <= buf->length) return; + new_len = MAX(buf->length ? buf->length*2 : 65536,newsize); + p = realloc(buf->addr,new_len); + if(p == NULL) exit(1); + buf->addr = p; + buf->length = new_len; +} + +static struct { + char *filename; + mem_buf_t buf; +} write_buf_table[MAX_MEMBERS]; + +static struct { + char *filename; + char *data; + int length; +} output_table[MAX_MEMBERS+1]; + +static struct mspack_file *my_open(struct mspack_system *sys, char *filename, int mode) { + mem_buf_t *buf = NULL; + int i; + if(strcmp(filename,"/dev/cab")==0) { + if(mode != MSPACK_SYS_OPEN_READ) return NULL; + buf = cab_mem_buf; + } else { + if(mode != MSPACK_SYS_OPEN_WRITE) return NULL; + + for(i=0;iwritable = 1; + break; + } + } + } + + return (struct mspack_file *) buf; +} + +static void my_close(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + /* NO OP */ +} + +static int my_read(struct mspack_file *buf_, void *out, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + count = MIN(buf->size - buf->pos, count); + memcpy(out,buf->addr + buf->pos,count); + buf->pos += count; + return count; +} + +static int my_write(struct mspack_file *buf_, void *in, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + if(!buf->writable) return -1; + if(buf->length < buf->pos + count) mem_buf_grow(buf,buf->pos + count); + memcpy(buf->addr+buf->pos,in,count); + buf->pos += count; + buf->size = MAX(buf->size,buf->pos); + return count; +} + +static int my_seek(struct mspack_file *buf_, off_t off, int mode) { + mem_buf_t *buf = (mem_buf_t*) buf_; + int newpos; + switch(mode) { + case MSPACK_SYS_SEEK_START: newpos = off; break; + case MSPACK_SYS_SEEK_CUR: newpos = buf->pos + off; break; + case MSPACK_SYS_SEEK_END: newpos = buf->size - off; break; + default: return -1; + } + if(newpos < 0) return -1; + if(newpos > buf->size) { + if(!buf->writable) return -1; + if(newpos > buf->length) + mem_buf_grow(buf,newpos); + } + buf->pos = newpos; + return 0; +} + +static off_t my_tell(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + return buf ? buf->pos : 0; +} + +// FEATURE: Remove this to possibly avoid pulling in stdio from libc +// (it may be getting pulled in anyway from malloc or something) +static void my_message(struct mspack_file *file, char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc((int) '\n', stderr); + fflush(stderr); +} + +static void *my_alloc(struct mspack_system *sys, size_t size) { return malloc(size); } +static void my_free(void *p) { free(p); } +static void my_copy(void *src, void *dest, size_t bytes) { memcpy(dest, src, bytes); } + +static struct mspack_system my_system = { + &my_open, + &my_close, + &my_read, + &my_write, + &my_seek, + &my_tell, + &my_message, + &my_alloc, + &my_free, + &my_copy, + NULL +}; + +extern char *user_info[1024]; + +int mspack_main() { + struct mscab_decompressor *decomp; + struct mscabd_cabinet *cab; + struct mscabd_file *file; + mem_buf_t mem_buf; + size_t size = (size_t)user_info[1]; + int i; + + mem_buf.addr = user_info[0]; + mem_buf.pos = mem_buf.writable = 0; + mem_buf.length = -1; + mem_buf.size = size; + + cab_mem_buf = &mem_buf; + + decomp = mspack_create_cab_decompressor(&my_system); + if(!decomp) exit(1); + + cab = decomp->search(decomp,"/dev/cab"); + if(!cab) exit(2); + + for(file = cab->files;file;file=file->next) + decomp->extract(decomp,file,file->filename); + + decomp->close(decomp,cab); + mspack_destroy_cab_decompressor(decomp); + + for(i=0;i 0;) { + newPalette[--i] = trans[--transLength]; + newPalette[--i] = palette[--len]; + newPalette[--i] = palette[--len]; + newPalette[--i] = palette[--len]; + } + palette = newPalette; + + } else { + inputStream.skip(chunkLength); + } + } + + /// Helper functions for IDAT /////////////////////////////////////////////////////////////////////////////////////////// + + /** Read Image data in off of a compression stream */ + private void readImageData() throws IOException { + InputStream dataStream = new SequenceInputStream(new IDATEnumeration(this)); + DataInputStream dis = new DataInputStream(new BufferedInputStream(new InflaterInputStream(dataStream, new Inflater()))); + int bps, filterOffset; + switch (colorType) { + case 0: case 3: bps = depth; break; + case 2: bps = 3 * depth; break; + case 4: bps = depth<<1; break; + case 6: bps = depth<<2; break; + default: throw new IOException("Unknown color type encountered."); + } + + filterOffset = (bps + 7) >> 3; + + for (pass = (multipass ? 1 : 0); pass < 8; pass++) { + int pass = this.pass; + int rInc = rowInc[pass]; + int cInc = colInc[pass]; + int sCol = startingCol[pass]; + int val = (p.width - sCol + cInc - 1) / cInc; + int samples = val * filterOffset; + int rowSize = (val * bps)>>3; + int sRow = startingRow[pass]; + if (p.height <= sRow || rowSize == 0) continue; + int sInc = rInc * p.width; + byte inbuf[] = new byte[rowSize]; + int pix[] = new int[rowSize]; + int upix[] = null; + int temp[] = new int[rowSize]; + int nextY = sRow; // next Y value and number of rows to report to sendPixels + int rows = 0; + int rowStart = sRow * p.width; + + for (int y = sRow; y < p.height; y += rInc, rowStart += sInc) { + rows += rInc; + int rowFilter = dis.read(); + dis.readFully(inbuf); + if (!filterRow(inbuf, pix, upix, rowFilter, filterOffset)) throw new IOException("Unknown filter type: " + rowFilter); + insertPixels(pix, rowStart + sCol, samples); + if (multipass && (pass < 6)) blockFill(rowStart); + upix = pix; + pix = temp; + temp = upix; + } + if (!multipass) break; + } + while(dis.read() != -1) System.err.println("Leftover data encountered."); + + // 24-bit color is our native format + if (colorType == 2 || colorType == 6) { + data = (int[])pixels; + if (colorType == 2) { + for(int i=0; i> depth) << (8 - depth); + data[i] = + (alpha << 24) | + (val << 16) | + (val << 8) | + val; + } + } + } + + } + + private void insertGreyPixels(int pix[], int offset, int samples) { + int p = pix[0]; + int ipix[] = ipixels; + int cInc = colInc[pass]; + int rs = 0; + + if (colorType == 0) { + switch (depth) { + case 1: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs--; + else { rs = 7; p = pix[j>>3]; } + ipix[offset] = (p>>rs) & 0x1; + } + break; + case 2: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs -= 2; + else { rs = 6; p = pix[j>>2]; } + ipix[offset] = (p>>rs) & 0x3; + } + break; + case 4: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs = 0; + else { rs = 4; p = pix[j>>1]; } + ipix[offset] = (p>>rs) & 0xf; + } + break; + case 8: + for (int j = 0; j < samples; offset += cInc) ipix[offset] = (byte) pix[j++]; + break; + case 16: + samples = samples<<1; + for (int j = 0; j < samples; j += 2, offset += cInc) ipix[offset] = pix[j]; + break; + default: break; + } + } else if (colorType == 4) { + if (depth == 8) { + for (int j = 0; j < samples; offset += cInc) ipix[offset] = (pix[j++]<<8) | pix[j++]; + } else { + samples = samples<<1; + for (int j = 0; j < samples; j += 2, offset += cInc) ipix[offset] = (pix[j]<<8) | pix[j+=2]; + } + } + } + + private void insertPalettedPixels(int pix[], int offset, int samples) { + int rs = 0; + int p = pix[0]; + byte bpix[] = bpixels; + int cInc = colInc[pass]; + + switch (depth) { + case 1: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs--; + else { rs = 7; p = pix[j>>3]; } + bpix[offset] = (byte) ((p>>rs) & 0x1); + } + break; + case 2: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs -= 2; + else { rs = 6; p = pix[j>>2]; } + bpix[offset] = (byte) ((p>>rs) & 0x3); + } + break; + case 4: + for (int j = 0; j < samples; j++, offset += cInc) { + if (rs != 0) rs = 0; + else { rs = 4; p = pix[j>>1]; } + bpix[offset] = (byte) ((p>>rs) & 0xf); + } + break; + case 8: + for (int j = 0; j < samples; j++, offset += cInc) bpix[offset] = (byte) pix[j]; + break; + } + } + + private void insertPixels(int pix[], int offset, int samples) { + switch (colorType) { + case 0: + case 4: + insertGreyPixels(pix, offset, samples); + break; + case 2: { + int j = 0; + int ipix[] = ipixels; + int cInc = colInc[pass]; + if (depth == 8) { + for (j = 0; j < samples; offset += cInc) + ipix[offset] = (pix[j++]<<16) | (pix[j++]<<8) | pix[j++]; + } else { + samples = samples<<1; + for (j = 0; j < samples; j += 2, offset += cInc) + ipix[offset] = (pix[j]<<16) | (pix[j+=2]<<8) | pix[j+=2]; + } + break; } + case 3: + insertPalettedPixels(pix, offset, samples); + break; + case 6: { + int j = 0; + int ipix[] = ipixels; + int cInc = colInc[pass]; + if (depth == 8) { + for (j = 0; j < samples; offset += cInc) { + ipix[offset] = (pix[j++]<<16) | (pix[j++]<<8) | pix[j++] | + (pix[j++]<<24); + } + } else { + samples = samples<<1; + for (j = 0; j < samples; j += 2, offset += cInc) { + ipix[offset] = (pix[j]<<16) | (pix[j+=2]<<8) | pix[j+=2] | + (pix[j+=2]<<24); + } + } + break; } + default: + break; + } + } + + private void blockFill(int rowStart) { + int counter; + int dw = p.width; + int pass = this.pass; + int w = blockWidth[pass]; + int sCol = startingCol[pass]; + int cInc = colInc[pass]; + int wInc = cInc - w; + int maxW = rowStart + dw - w; + int len; + int h = blockHeight[pass]; + int maxH = rowStart + (dw * h); + int startPos = rowStart + sCol; + counter = startPos; + + if (colorType == 3) { + byte bpix[] = bpixels; + byte pixel; + len = bpix.length; + for (; counter <= maxW;) { + int end = counter + w; + pixel = bpix[counter++]; + for (; counter < end; counter++) bpix[counter] = pixel; + counter += wInc; + } + maxW += w; + if (counter < maxW) + for (pixel = bpix[counter++]; counter < maxW; counter++) + bpix[counter] = pixel; + if (len < maxH) maxH = len; + for (counter = startPos + dw; counter < maxH; counter += dw) + System.arraycopy(bpix, startPos, bpix, counter, dw - sCol); + } else { + int ipix[] = ipixels; + int pixel; + len = ipix.length; + for (; counter <= maxW;) { + int end = counter + w; + pixel = ipix[counter++]; + for (; counter < end; counter++) + ipix[counter] = pixel; + counter += wInc; + } + maxW += w; + if (counter < maxW) + for (pixel = ipix[counter++]; counter < maxW; counter++) + ipix[counter] = pixel; + if (len < maxH) maxH = len; + for (counter = startPos + dw; counter < maxH; counter += dw) + System.arraycopy(ipix, startPos, ipix, counter, dw - sCol); + } + } + + private boolean filterRow(byte inbuf[], int pix[], int upix[], int rowFilter, int boff) { + int rowWidth = pix.length; + switch (rowFilter) { + case 0: { + for (int x = 0; x < rowWidth; x++) pix[x] = 0xff & inbuf[x]; + break; } + case 1: { + int x = 0; + for ( ; x < boff; x++) pix[x] = 0xff & inbuf[x]; + for ( ; x < rowWidth; x++) pix[x] = 0xff & (inbuf[x] + pix[x - boff]); + break; } + case 2: { + if (upix != null) { + for (int x = 0; x < rowWidth; x++) + pix[x] = 0xff & (upix[x] + inbuf[x]); + } else { + for (int x = 0; x < rowWidth; x++) + pix[x] = 0xff & inbuf[x]; + } + break; } + case 3: { + if (upix != null) { + int x = 0; + for ( ; x < boff; x++) { + int rval = upix[x]; + pix[x] = 0xff & ((rval>>1) + inbuf[x]); + } + for ( ; x < rowWidth; x++) { + int rval = upix[x] + pix[x - boff]; + pix[x] = 0xff & ((rval>>1) + inbuf[x]); + } + } else { + int x = 0; + for ( ; x < boff; x++) pix[x] = 0xff & inbuf[x]; + for ( ; x < rowWidth; x++) { + int rval = pix[x - boff]; + pix[x] = 0xff & ((rval>>1) + inbuf[x]); + } + } + break; } + case 4: { + if (upix != null) { + int x = 0; + for ( ; x < boff; x++) pix[x] = 0xff & (upix[x] + inbuf[x]); + for ( ; x < rowWidth; x++) { + int a, b, c, p, pa, pb, pc, rval; + a = pix[x - boff]; + b = upix[x]; + c = upix[x - boff]; + p = a + b - c; + pa = p > a ? p - a : a - p; + pb = p > b ? p - b : b - p; + pc = p > c ? p - c : c - p; + if ((pa <= pb) && (pa <= pc)) rval = a; + else if (pb <= pc) rval = b; + else rval = c; + pix[x] = 0xff & (rval + inbuf[x]); + } + } else { + int x = 0; + for ( ; x < boff; x++) pix[x] = 0xff & inbuf[x]; + for ( ; x < rowWidth; x++) { + int rval = pix[x - boff]; + pix[x] = 0xff & (rval + inbuf[x]); + } + } + break; } + default: return false; + } + return true; + } + + // Private Data /////////////////////////////////////////////////////////////////////////////////////// + + private int target_offset = 0; + private int sigmask = 0xffff; + private Object pixels = null; + private int ipixels[] = null; + private byte bpixels[] = null; + private boolean multipass = false; + private boolean complete = false; + private boolean error = false; + + int[] data = null; + + private InputStream underlyingStream = null; + private DataInputStream inputStream = null; + private Thread controlThread = null; + private boolean infoAvailable = false; + private int updateDelay = 750; + + // Image decoding state variables + private boolean headerFound = false; + private int compressionMethod = -1; + private int depth = -1; + private int colorType = -1; + private int filterMethod = -1; + private int interlaceMethod = -1; + private int pass = 0; + private byte palette[] = null; + private int mask = 0x0; + private int smask = 0x0; + private boolean transparency = false; + + private int chunkLength = 0; + private int chunkType = 0; + private boolean needChunkInfo = true; + + private static final int CHUNK_bKGD = 0x624B4744; // "bKGD" + private static final int CHUNK_cHRM = 0x6348524D; // "cHRM" + private static final int CHUNK_gAMA = 0x67414D41; // "gAMA" + private static final int CHUNK_hIST = 0x68495354; // "hIST" + private static final int CHUNK_IDAT = 0x49444154; // "IDAT" + private static final int CHUNK_IEND = 0x49454E44; // "IEND" + private static final int CHUNK_IHDR = 0x49484452; // "IHDR" + private static final int CHUNK_PLTE = 0x504C5445; // "PLTE" + private static final int CHUNK_pHYs = 0x70485973; // "pHYs" + private static final int CHUNK_sBIT = 0x73424954; // "sBIT" + private static final int CHUNK_tEXt = 0x74455874; // "tEXt" + private static final int CHUNK_tIME = 0x74494D45; // "tIME" + private static final int CHUNK_tRNS = 0x74524E53; // "tIME" + private static final int CHUNK_zTXt = 0x7A545874; // "zTXt" + + private static final int startingRow[] = { 0, 0, 0, 4, 0, 2, 0, 1 }; + private static final int startingCol[] = { 0, 0, 4, 0, 2, 0, 1, 0 }; + private static final int rowInc[] = { 1, 8, 8, 8, 4, 4, 2, 2 }; + private static final int colInc[] = { 1, 8, 8, 4, 4, 2, 2, 1 }; + private static final int blockHeight[] = { 1, 8, 8, 4, 4, 2, 2, 1 }; + private static final int blockWidth[] = { 1, 8, 4, 4, 2, 2, 1, 1 }; + + // Helper Classes //////////////////////////////////////////////////////////////////// + + private static class MeteredInputStream extends FilterInputStream { + int bytesLeft; + int marked; + + public MeteredInputStream(InputStream in, int size) { + super(in); + bytesLeft = size; + } + + public final int read() throws IOException { + if (bytesLeft > 0) { + int val = in.read(); + if (val != -1) bytesLeft--; + return val; + } + return -1; + } + + public final int read(byte b[]) throws IOException { + return read(b, 0, b.length); + } + + public final int read(byte b[], int off, int len) throws IOException { + if (bytesLeft > 0) { + len = (len > bytesLeft ? bytesLeft : len); + int read = in.read(b, off, len); + if (read > 0) bytesLeft -= read; + return read; + } + return -1; + } + + public final long skip(long n) throws IOException { + n = (n > bytesLeft ? bytesLeft : n); + long skipped = in.skip(n); + if (skipped > 0) bytesLeft -= skipped; + return skipped; + } + + public final int available() throws IOException { + int n = in.available(); + return (n > bytesLeft ? bytesLeft : n); + } + + public final void close() throws IOException { /* Eat this */ } + + public final void mark(int readlimit) { + marked = bytesLeft; + in.mark(readlimit); + } + + public final void reset() throws IOException { + in.reset(); + bytesLeft = marked; + } + + public final boolean markSupported() { return in.markSupported(); } + } + + /** Support class, used to eat the IDAT headers dividing up the deflated stream */ + private static class IDATEnumeration implements Enumeration { + InputStream underlyingStream; + PNG owner; + boolean firstStream = true; + + public IDATEnumeration(PNG owner) { + this.owner = owner; + this.underlyingStream = owner.underlyingStream; + } + + public Object nextElement() { + firstStream = false; + return new MeteredInputStream(underlyingStream, owner.chunkLength); + } + + public boolean hasMoreElements() { + DataInputStream dis = new DataInputStream(underlyingStream); + if (!firstStream) { + try { + int crc = dis.readInt(); + owner.needChunkInfo = false; + owner.chunkLength = dis.readInt(); + owner.chunkType = dis.readInt(); + } catch (IOException ioe) { + return false; + } + } + if (owner.chunkType == PNG.CHUNK_IDAT) return true; + return false; + } + } + +} diff --git a/src/org/ibex/translators/SVG.java b/src/org/ibex/translators/SVG.java index e69de29..b8f73f9 100644 --- a/src/org/ibex/translators/SVG.java +++ b/src/org/ibex/translators/SVG.java @@ -0,0 +1,428 @@ +// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] +package org.ibex.translators; +import java.util.*; + +// FIXME: need to support style sheets and the 'style=' attribute +// FIXME: need to convert markers into subboxes +public class SVG { + + /* + public static void parseNode(String name, String[] keys, Object[] vals, Template t) { + Hash h = new Hash(); + for(int i=0; iname property * / + Hashtable glyphByName = new Hashtable(); + + / ** linked list of glyphs, stored by the first character of their unicode property * / + Hashtable glyphByUnicode = new Hashtable(); + + // a Glyph in an VectorGraphics font + public static class Glyph { + + // FIXME: lang attribute + boolean isVerticallyOriented = false; + Template t = null; + Box b = null; + + float horiz_adv_x = 0; + float vert_origin_x = 0; + float vert_origin_y = 0; + float vert_adv_y = 0; + + String unicode = null; + + // forms the linked list in glyphByUnicode; glyphs appear in the order specified in the font + public Glyph next = null; + + Glyph(String name, String unicode, Template t, VectorGraphics.Font f) { + if (unicode != null) + if (f.glyphByUnicode.get(unicode.substring(0, 1)) == null) { + f.glyphByUnicode.put(unicode.substring(0, 1), this); + } else { + Glyph g; + for(g = (Glyph)f.glyphByUnicode.get(unicode.substring(0, 1)); g.next != null; g = g.next); + g.next = this; + } + if (name != null) f.glyphByUnicode.put(name, this); + this.unicode = unicode; + this.t = t; + horiz_adv_x = f.horiz_adv_x; + vert_origin_x = f.vert_origin_x; + vert_origin_y = f.vert_origin_y; + vert_adv_y = f.vert_adv_y; + } + public void render(DoubleBuffer buf, int x, int y, int fillcolor, int strokecolor, float scaleFactor) { + // FEATURE: make b double-buffered for increased performance + if (b == null) { + b = new Box(t, new org.ibex.util.Vec(), new org.ibex.util.Vec(), null, 0, 0); + b.put("absolute", Boolean.TRUE); + b.prerender(); + t = null; + } + // FIXME + b.put("width", new Integer(1000)); + b.put("height", new Integer(1000)); + b.fillcolor = fillcolor; + b.strokecolor = strokecolor; + + // we toss an extra flip on the ctm so that fonts stick "up" instead of down + b.render(0, 0, buf.getWidth(), buf.getHeight(), buf, + Affine.flip(false, true).multiply(Affine.scale(scaleFactor, scaleFactor).multiply(Affine.translate(x, y))).multiply(buf.a)); + } + } + } + */ + + + /** Copied verbatim from the SVG specification */ + public static Hashtable colors = new Hashtable(400); + static { + colors.put("aliceblue", new Integer((240 << 16) | (248 << 8) | 255)); + colors.put("antiquewhite", new Integer((250 << 16) | (235 << 8) | 215)); + colors.put("aqua", new Integer((0 << 16) | (255 << 8) | 255)); + colors.put("aquamarine", new Integer((127 << 16) | (255 << 8) | 212)); + colors.put("azure", new Integer((240 << 16) | (255 << 8) | 255)); + colors.put("beige", new Integer((245 << 16) | (245 << 8) | 220)); + colors.put("bisque", new Integer((255 << 16) | (228 << 8) | 196)); + colors.put("black", new Integer((0 << 16) | (0 << 8) | 0)); + colors.put("blanchedalmond", new Integer((255 << 16) | (235 << 8) | 205)); + colors.put("blue", new Integer((0 << 16) | (0 << 8) | 255)); + colors.put("blueviolet", new Integer((138 << 16) | (43 << 8) | 226)); + colors.put("brown", new Integer((165 << 16) | (42 << 8) | 42)); + colors.put("burlywood", new Integer((222 << 16) | (184 << 8) | 135)); + colors.put("cadetblue", new Integer((95 << 16) | (158 << 8) | 160)); + colors.put("chartreuse", new Integer((127 << 16) | (255 << 8) | 0)); + colors.put("chocolate", new Integer((210 << 16) | (105 << 8) | 30)); + colors.put("coral", new Integer((255 << 16) | (127 << 8) | 80)); + colors.put("cornflowerblue", new Integer((100 << 16) | (149 << 8) | 237)); + colors.put("cornsilk", new Integer((255 << 16) | (248 << 8) | 220)); + colors.put("crimson", new Integer((220 << 16) | (20 << 8) | 60)); + colors.put("cyan", new Integer((0 << 16) | (255 << 8) | 255)); + colors.put("darkblue", new Integer((0 << 16) | (0 << 8) | 139)); + colors.put("darkcyan", new Integer((0 << 16) | (139 << 8) | 139)); + colors.put("darkgoldenrod", new Integer((184 << 16) | (134 << 8) | 11)); + colors.put("darkgray", new Integer((169 << 16) | (169 << 8) | 169)); + colors.put("darkgreen", new Integer((0 << 16) | (100 << 8) | 0)); + colors.put("darkgrey", new Integer((169 << 16) | (169 << 8) | 169)); + colors.put("darkkhaki", new Integer((189 << 16) | (183 << 8) | 107)); + colors.put("darkmagenta", new Integer((139 << 16) | (0 << 8) | 139)); + colors.put("darkolivegreen", new Integer((85 << 16) | (107 << 8) | 47)); + colors.put("darkorange", new Integer((255 << 16) | (140 << 8) | 0)); + colors.put("darkorchid", new Integer((153 << 16) | (50 << 8) | 204)); + colors.put("darkred", new Integer((139 << 16) | (0 << 8) | 0)); + colors.put("darksalmon", new Integer((233 << 16) | (150 << 8) | 122)); + colors.put("darkseagreen", new Integer((143 << 16) | (188 << 8) | 143)); + colors.put("darkslateblue", new Integer((72 << 16) | (61 << 8) | 139)); + colors.put("darkslategray", new Integer((47 << 16) | (79 << 8) | 79)); + colors.put("darkslategrey", new Integer((47 << 16) | (79 << 8) | 79)); + colors.put("darkturquoise", new Integer((0 << 16) | (206 << 8) | 209)); + colors.put("darkviolet", new Integer((148 << 16) | (0 << 8) | 211)); + colors.put("deeppink", new Integer((255 << 16) | (20 << 8) | 147)); + colors.put("deepskyblue", new Integer((0 << 16) | (191 << 8) | 255)); + colors.put("dimgray", new Integer((105 << 16) | (105 << 8) | 105)); + colors.put("dimgrey", new Integer((105 << 16) | (105 << 8) | 105)); + colors.put("dodgerblue", new Integer((30 << 16) | (144 << 8) | 255)); + colors.put("firebrick", new Integer((178 << 16) | (34 << 8) | 34)); + colors.put("floralwhite", new Integer((255 << 16) | (250 << 8) | 240)); + colors.put("forestgreen", new Integer((34 << 16) | (139 << 8) | 34)); + colors.put("fuchsia", new Integer((255 << 16) | (0 << 8) | 255)); + colors.put("gainsboro", new Integer((220 << 16) | (220 << 8) | 220)); + colors.put("ghostwhite", new Integer((248 << 16) | (248 << 8) | 255)); + colors.put("gold", new Integer((255 << 16) | (215 << 8) | 0)); + colors.put("goldenrod", new Integer((218 << 16) | (165 << 8) | 32)); + colors.put("gray", new Integer((128 << 16) | (128 << 8) | 128)); + colors.put("grey", new Integer((128 << 16) | (128 << 8) | 128)); + colors.put("green", new Integer((0 << 16) | (128 << 8) | 0)); + colors.put("greenyellow", new Integer((173 << 16) | (255 << 8) | 47)); + colors.put("honeydew", new Integer((240 << 16) | (255 << 8) | 240)); + colors.put("hotpink", new Integer((255 << 16) | (105 << 8) | 180)); + colors.put("indianred", new Integer((205 << 16) | (92 << 8) | 92)); + colors.put("indigo", new Integer((75 << 16) | (0 << 8) | 130)); + colors.put("ivory", new Integer((255 << 16) | (255 << 8) | 240)); + colors.put("khaki", new Integer((240 << 16) | (230 << 8) | 140)); + colors.put("lavender", new Integer((230 << 16) | (230 << 8) | 250)); + colors.put("lavenderblush", new Integer((255 << 16) | (240 << 8) | 245)); + colors.put("lawngreen", new Integer((124 << 16) | (252 << 8) | 0)); + colors.put("lemonchiffon", new Integer((255 << 16) | (250 << 8) | 205)); + colors.put("lightblue", new Integer((173 << 16) | (216 << 8) | 230)); + colors.put("lightcoral", new Integer((240 << 16) | (128 << 8) | 128)); + colors.put("lightcyan", new Integer((224 << 16) | (255 << 8) | 255)); + colors.put("lightgoldenrodyellow", new Integer((250 << 16) | (250 << 8) | 210)); + colors.put("lightgray", new Integer((211 << 16) | (211 << 8) | 211)); + colors.put("lightgreen", new Integer((144 << 16) | (238 << 8) | 144)); + colors.put("lightgrey", new Integer((211 << 16) | (211 << 8) | 211)); + colors.put("lightpink", new Integer((255 << 16) | (182 << 8) | 193)); + colors.put("lightsalmon", new Integer((255 << 16) | (160 << 8) | 122)); + colors.put("lightseagreen", new Integer((32 << 16) | (178 << 8) | 170)); + colors.put("lightskyblue", new Integer((135 << 16) | (206 << 8) | 250)); + colors.put("lightslategray", new Integer((119 << 16) | (136 << 8) | 153)); + colors.put("lightslategrey", new Integer((119 << 16) | (136 << 8) | 153)); + colors.put("lightsteelblue", new Integer((176 << 16) | (196 << 8) | 222)); + colors.put("lightyellow", new Integer((255 << 16) | (255 << 8) | 224)); + colors.put("lime", new Integer((0 << 16) | (255 << 8) | 0)); + colors.put("limegreen", new Integer((50 << 16) | (205 << 8) | 50)); + colors.put("linen", new Integer((250 << 16) | (240 << 8) | 230)); + colors.put("magenta", new Integer((255 << 16) | (0 << 8) | 255)); + colors.put("maroon", new Integer((128 << 16) | (0 << 8) | 0)); + colors.put("mediumaquamarine", new Integer((102 << 16) | (205 << 8) | 170)); + colors.put("mediumblue", new Integer((0 << 16) | (0 << 8) | 205)); + colors.put("mediumorchid", new Integer((186 << 16) | (85 << 8) | 211)); + colors.put("mediumpurple", new Integer((147 << 16) | (112 << 8) | 219)); + colors.put("mediumseagreen", new Integer((60 << 16) | (179 << 8) | 113)); + colors.put("mediumslateblue", new Integer((123 << 16) | (104 << 8) | 238)); + colors.put("mediumspringgreen", new Integer((0 << 16) | (250 << 8) | 154)); + colors.put("mediumturquoise", new Integer((72 << 16) | (209 << 8) | 204)); + colors.put("mediumvioletred", new Integer((199 << 16) | (21 << 8) | 133)); + colors.put("midnightblue", new Integer((25 << 16) | (25 << 8) | 112)); + colors.put("mintcream", new Integer((245 << 16) | (255 << 8) | 250)); + colors.put("mistyrose", new Integer((255 << 16) | (228 << 8) | 225)); + colors.put("moccasin", new Integer((255 << 16) | (228 << 8) | 181)); + colors.put("navajowhite", new Integer((255 << 16) | (222 << 8) | 173)); + colors.put("navy", new Integer((0 << 16) | (0 << 8) | 128)); + colors.put("oldlace", new Integer((253 << 16) | (245 << 8) | 230)); + colors.put("olive", new Integer((128 << 16) | (128 << 8) | 0)); + colors.put("olivedrab", new Integer((107 << 16) | (142 << 8) | 35)); + colors.put("orange", new Integer((255 << 16) | (165 << 8) | 0)); + colors.put("orangered", new Integer((255 << 16) | (69 << 8) | 0)); + colors.put("orchid", new Integer((218 << 16) | (112 << 8) | 214)); + colors.put("palegoldenrod", new Integer((238 << 16) | (232 << 8) | 170)); + colors.put("palegreen", new Integer((152 << 16) | (251 << 8) | 152)); + colors.put("paleturquoise", new Integer((175 << 16) | (238 << 8) | 238)); + colors.put("palevioletred", new Integer((219 << 16) | (112 << 8) | 147)); + colors.put("papayawhip", new Integer((255 << 16) | (239 << 8) | 213)); + colors.put("peachpuff", new Integer((255 << 16) | (218 << 8) | 185)); + colors.put("peru", new Integer((205 << 16) | (133 << 8) | 63)); + colors.put("pink", new Integer((255 << 16) | (192 << 8) | 203)); + colors.put("plum", new Integer((221 << 16) | (160 << 8) | 221)); + colors.put("powderblue", new Integer((176 << 16) | (224 << 8) | 230)); + colors.put("purple", new Integer((128 << 16) | (0 << 8) | 128)); + colors.put("red", new Integer((255 << 16) | (0 << 8) | 0)); + colors.put("rosybrown", new Integer((188 << 16) | (143 << 8) | 143)); + colors.put("royalblue", new Integer((65 << 16) | (105 << 8) | 225)); + colors.put("saddlebrown", new Integer((139 << 16) | (69 << 8) | 19)); + colors.put("salmon", new Integer((250 << 16) | (128 << 8) | 114)); + colors.put("sandybrown", new Integer((244 << 16) | (164 << 8) | 96)); + colors.put("seagreen", new Integer((46 << 16) | (139 << 8) | 87)); + colors.put("seashell", new Integer((255 << 16) | (245 << 8) | 238)); + colors.put("sienna", new Integer((160 << 16) | (82 << 8) | 45)); + colors.put("silver", new Integer((192 << 16) | (192 << 8) | 192)); + colors.put("skyblue", new Integer((135 << 16) | (206 << 8) | 235)); + colors.put("slateblue", new Integer((106 << 16) | (90 << 8) | 205)); + colors.put("slategray", new Integer((112 << 16) | (128 << 8) | 144)); + colors.put("slategrey", new Integer((112 << 16) | (128 << 8) | 144)); + colors.put("snow", new Integer((255 << 16) | (250 << 8) | 250)); + colors.put("springgreen", new Integer((0 << 16) | (255 << 8) | 127)); + colors.put("steelblue", new Integer((70 << 16) | (130 << 8) | 180)); + colors.put("tan", new Integer((210 << 16) | (180 << 8) | 140)); + colors.put("teal", new Integer((0 << 16) | (128 << 8) | 128)); + colors.put("thistle", new Integer((216 << 16) | (191 << 8) | 216)); + colors.put("tomato", new Integer((255 << 16) | (99 << 8) | 71)); + colors.put("turquoise", new Integer((64 << 16) | (224 << 8) | 208)); + colors.put("violet", new Integer((238 << 16) | (130 << 8) | 238)); + colors.put("wheat", new Integer((245 << 16) | (222 << 8) | 179)); + colors.put("white", new Integer((255 << 16) | (255 << 8) | 255)); + colors.put("whitesmoke", new Integer((245 << 16) | (245 << 8) | 245)); + colors.put("yellow", new Integer((255 << 16) | (255 << 8) | 0)); + colors.put("yellowgreen", new Integer((154 << 16) | (205 << 8) | 50)); + } + +} diff --git a/src/org/ibex/translators/main.c b/src/org/ibex/translators/main.c index e69de29..4eca1e2 100644 --- a/src/org/ibex/translators/main.c +++ b/src/org/ibex/translators/main.c @@ -0,0 +1,12 @@ + +char *user_info[1024]; + +extern int mspack_main(); +extern int freetype_main(); + +int main(int argc, char **argv) { + if(argc < 1) return 1; + if(strcmp(argv[0],"mspack")==0) return mspack_main(); + if(strcmp(argv[0],"freetype")==0) return freetype_main(); + return 1; +}