home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / desvs7nu / src / xpmparser.java < prev   
Encoding:
Java Source  |  1996-08-14  |  7.7 KB  |  323 lines

  1.  
  2. import java.io.*;
  3. import java.util.*;
  4. import java.awt.Color;
  5.  
  6. /**
  7.  * X11 bitmap (xpm) parser
  8.  *
  9.  * Parse files of the form:
  10.  * <pre>
  11.  *  static char * fee_m_pm[] = {
  12.  *  "8 8 2 1 -1 -1",
  13.  *  "       s iconColor5    m black c blue",
  14.  *  ".      s none  m none  c none",
  15.  *  "      ..",
  16.  *  "    ....",
  17.  *  "    ....",
  18.  *  "     ...",
  19.  *  " ..   ..",
  20.  *  " ...   .",
  21.  *  ".....   ",
  22.  *  "......  "};
  23.  * </pre>
  24.  *
  25.  * @version    1.2 96/02/20
  26.  * @author     Jan Andersson, Torpa Konsult AB. (janne@torpa.se)
  27.  */
  28. public class XpmParser {
  29.    private DataInputStream input;
  30.    private int lineNo = 0;
  31.    private int width = 0;
  32.    private int height = 0;
  33.    private int nColors = 0;
  34.    private int charsPerPixel = 0;
  35.    private int colors[] = null;    
  36.    private Color[] colorTable;
  37.    private byte[] pixmap = null;
  38.    private String line;
  39.    
  40.    /**
  41.     * Construct and XpmParser from an InputStream
  42.     * @param is the imput stream to parse
  43.     */
  44.    public XpmParser(InputStream is) {
  45.       input = new DataInputStream(is);
  46.    }
  47.  
  48.    /**
  49.     * Parse input stream.
  50.     * @return true on success.
  51.     */
  52.    public boolean parse() {
  53.       try {
  54.      parseInput();
  55.      return true;
  56.       }
  57.       catch (Exception e) {
  58.      System.err.println("XpmParser: " + e.getMessage());
  59.      e.printStackTrace();
  60.      return false;
  61.       }
  62.    }
  63.  
  64.    /**
  65.     * Get image width.
  66.     * @return width in pixels.
  67.     */
  68.    public int getWidth() {
  69.       return width;
  70.    }
  71.    
  72.    /**
  73.     * Get image height.
  74.     * @return height in pixels.
  75.     */
  76.    public int getHeight() {
  77.       return height;
  78.    }
  79.    
  80.    /**
  81.     * Get pixmap.
  82.     * @return pixmap array.
  83.     */
  84.    public byte[] getPixmap() {
  85.       return pixmap;
  86.    }
  87.  
  88.    /**
  89.     * Get color table.
  90.     * @return array of used colors.
  91.     */
  92.    public Color[] getColorTable() {
  93.       return colorTable;
  94.    }
  95.    
  96.    /**
  97.     * Parse input stream.
  98.     * @exception Exception on input errors.
  99.     */
  100.    private void parseInput() throws Exception {
  101.       checkForHeader();
  102.       skipLineStartingWith("static char");
  103.       readHintsLine();
  104.       // allocate color relates tables
  105.       colors = new int[charsPerPixel * 256];
  106.       colorTable = new Color[nColors];
  107.       readColorTable();
  108.       readPixels();
  109.    }
  110.  
  111.    /**
  112.     * Read and check XPM header comment
  113.     */
  114.    private void checkForHeader() throws Exception {
  115.       readLine();
  116.       if (line != null && line.startsWith("/*") && line.endsWith("*/")) {
  117.      String tmp = line.substring(2);
  118.      tmp = tmp.trim();
  119.      if (!tmp.substring(0, 3).equals("XPM"))
  120.         System.err.println("XpmParser: warning: Not Xpm version 3.");
  121.      // read next line
  122.      readLine();
  123.       }
  124.    }
  125.    
  126.    /**
  127.     * Skip line starting with specified string.
  128.     */
  129.    private void skipLineStartingWith(String skip) throws Exception {
  130.       if (line == null)
  131.      throw(new Exception("Invalid Xpm format, line: " + lineNo));
  132.       if (line.startsWith(skip)) {
  133.      // ignore this line; read next
  134.      readLine();
  135.       }
  136.    }
  137.  
  138.    /**
  139.     * Read XPM hints line. I.e width, height, number of colors and
  140.     * chars per pixel.
  141.     */
  142.    private void readHintsLine() throws Exception {
  143.       // skip comment line
  144.       if (line != null && line.startsWith("/*") && line.endsWith("*/"))
  145.      readLine();
  146.       if (line == null)
  147.      throw(new Exception("Invalid Xpm format: unexpected EOF, line: " +
  148.                  lineNo));
  149.       int start = line.indexOf('"');
  150.       int end = line.lastIndexOf('"');
  151.       if (start < 0 || end < 0 || end <= start)
  152.      throw(new Exception("Invalid Xpm format: hints line: " + lineNo));
  153.       String tmp = line.substring(start+1, end);
  154.       StringTokenizer st = new StringTokenizer(tmp);
  155.       if (st.countTokens() < 4)
  156.      throw(new Exception("Invalid Xpm format: hints line: " + lineNo));
  157.       try {
  158.      width = Integer.parseInt(st.nextToken());
  159.      height = Integer.parseInt(st.nextToken());
  160.      nColors = Integer.parseInt(st.nextToken());
  161.      charsPerPixel = Integer.parseInt(st.nextToken());
  162.       }
  163.       catch (Exception e) {
  164.      throw(new Exception("Invalid Xpm format: hints line: " + lineNo));
  165.       }
  166.       if (charsPerPixel > 2) {
  167.      throw(new Exception("Invalid Xpm format: "+
  168.                 "Can only handle up to 2 chars per pixels"));
  169.       }
  170.       
  171.    }
  172.  
  173.    /**
  174.     * Read XPM color table.
  175.     */
  176.    private void readColorTable() throws Exception {
  177.       for (int i=0; i<nColors; i++) {
  178.      readLine();
  179.      // skip comment line
  180.      if (line != null && line.startsWith("/*") && line.endsWith("*/"))
  181.         readLine();
  182.      if (line == null)
  183.         throw(new Exception("Invalid Xpm format: unexpected EOF, line: " +
  184.                 lineNo));
  185.      // read the chars
  186.      int pos = line.indexOf('"');
  187.      if (pos < 0)
  188.         throw(new Exception("Invalid Xpm format: color table, line: "
  189.                    + lineNo));
  190.      String tmp = line.substring(pos+1);
  191.      int colorIndex = 0;
  192.      for (int j=0; j<charsPerPixel; ++j)
  193.         colorIndex = (colorIndex << 8) + tmp.charAt(j);
  194.      
  195.      tmp = line.substring(pos+1+charsPerPixel);
  196.      StringTokenizer st = new StringTokenizer(tmp, " \"\t\n\r");
  197.      int state = 0;
  198.      boolean gotC = false;
  199.      while (st.hasMoreTokens() && state < 2) {
  200.         // look for 'c'
  201.         String token = st.nextToken();
  202.         switch (state) {
  203.            case 0:
  204.           // looking for 'c'
  205.           if (token.equals("c"))
  206.              state++;
  207.           break;
  208.            case 1:
  209.           // parse color
  210.           colorTable[i] = parseColor(token);
  211.           colors[colorIndex] = i;
  212.           state++;
  213.           break;
  214.         }
  215.      }
  216.       }
  217.    }
  218.  
  219.    /**
  220.     * Read the XPM pixels.
  221.     */
  222.    private void readPixels() throws Exception {
  223.       readLine();
  224.       // skip comment line
  225.       if (line != null && line.startsWith("/*") && line.endsWith("*/"))
  226.      readLine();
  227.       if (line == null)
  228.      throw(new Exception("Invalid Xpm format: "+
  229.                 "EOF at line: " + lineNo));
  230.  
  231.       int datasize = width * height;
  232.       pixmap = new byte[datasize];
  233.       int index = 0;
  234.       
  235.       while (line != null) {
  236.      int start = line.indexOf('"');
  237.      int end = line.lastIndexOf('"');
  238.      if (start < 0 || end < 0 || end <= start)
  239.         throw(new Exception("Invalid Xpm format: line: " + lineNo));
  240.      String tmp = line.substring(start+1, end);
  241.      int i = 0;
  242.      while (i < tmp.length()) {
  243.         int colorIndex = 0;
  244.         for (int j=0; j<charsPerPixel; ++j) 
  245.            colorIndex = (colorIndex << 8) + tmp.charAt(i++);
  246.         pixmap[index++] = (byte) colors[colorIndex];
  247.      }
  248.      
  249.      if (index >= datasize)
  250.         return;
  251.      readLine();
  252.       }
  253.    }
  254.    
  255.    /**
  256.     * Read a line from input stream.
  257.     */
  258.    private void readLine() {
  259.       line = null;
  260.       try {
  261.      line = input.readLine();
  262.       }
  263.       catch (IOException e) {
  264.      line = null;
  265.       }
  266.       if (line != null)
  267.      line = line.trim();
  268.       lineNo++;
  269.    }
  270.  
  271.    /**
  272.     * Parse color string
  273.     */
  274.    private Color parseColor(String aColor) {
  275.       Color c = null;
  276.       if (aColor.charAt(0) == '#') {
  277.      // hexadecimal value
  278.      switch (aColor.length()) {
  279.         case 4:
  280.            // NYI
  281.            break;
  282.         case 7:
  283.            //Integer rgbValue = new Integer(0);
  284.            Integer rgbValue = Integer.valueOf(aColor.substring(1), 16);
  285.            c = new Color(rgbValue.intValue());
  286.            break;
  287.         case 13:
  288.            Integer rValue = Integer.valueOf(aColor.substring(1,3), 16);
  289.            Integer gValue = Integer.valueOf(aColor.substring(5,7), 16);
  290.            Integer bValue = Integer.valueOf(aColor.substring(9,11), 16);
  291.            c = new Color(rValue.intValue(), gValue.intValue(),
  292.                  bValue.intValue());
  293.            break;
  294.      }
  295.      if (c == null) {
  296.         // unknown color; use black :-(
  297.         c = Color.black;
  298.      }
  299.       }
  300.       else {
  301.      // assume symbolic color name
  302.      if (aColor.equalsIgnoreCase("none")) {
  303.         // Use null to indicate transparent color
  304.         c = null;
  305.      }
  306.      else {
  307.         // look up color RGB value among known X11 colornames
  308.         int rgb = XColorNames.getRgb(aColor);
  309.         if (rgb != XColorNames.NOT_FOUND) 
  310.            c = new Color(rgb);
  311.         if (c == null) {
  312.            // unknown color; use black :-(
  313.            c = Color.black;
  314.         }
  315.      }
  316.       }
  317.       
  318.       return c;
  319.    }
  320. }
  321.  
  322.    
  323.