Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/port80/eclipse/util/XPMFile.java


1   package com.port80.eclipse.util;
2   
3   import java.io.BufferedReader;
4   import java.io.FileInputStream;
5   import java.io.IOException;
6   import java.io.InputStreamReader;
7   import java.net.URL;
8   import java.util.StringTokenizer;
9   
10  import com.port80.util.Msg;
11  import com.port80.util.struct.IntValueHashMap;
12  import com.port80.util.text.TextUtil;
13  
14  /**
15   * Straightforward XPM file parser, which is unusually strict, but
16   * serves its purpose for most XPM files.
17   * 
18   * HISTORY:
19   * . Switch back to use transparentPixel.  
20   *   alphaData is 10 times slower than maskData in SWT GC.drawImage() !
21   */
22  public class XPMFile {
23  
24    ////////////////////////////////////////////////////////////////////////
25  
26    private static final String NAME = "XPMFile";
27    private static final boolean DEBUG = false;
28  
29    ////////////////////////////////////////////////////////////////////////
30  
31    private String fFilename;
32    private BufferedReader fReader;
33    private int fRows, fColumns, fColors, fColorChars;
34  
35    private IntValueHashMap fColorTable;
36    private String fTransparentSymbol;
37    private int fTransparent;
38    private int[] fData;
39    // private byte[] fAlphas;
40  
41    ////////////////////////////////////////////////////////////////////////
42  
43    public XPMFile(String filename) {
44      fColorTable = new IntValueHashMap(17);
45      fFilename = filename;
46      loadFile(filename);
47    }
48  
49    public XPMFile(URL url) {
50      fColorTable = new IntValueHashMap(17);
51      fFilename = url.toString();
52      loadFile(url);
53    }
54  
55    ////////////////////////////////////////////////////////////////////////
56  
57    public String getFilename() {
58      return fFilename;
59    }
60  
61    public int[] getData() {
62      return fData;
63    }
64  
65    public int getRowCount() {
66      return fRows;
67    }
68  
69    public int getColumnCount() {
70      return fColumns;
71    }
72  
73    public int getTransparentColor() {
74      return fTransparent;
75    }
76  
77    ////////////////////////////////////////////////////////////////////////
78  
79    private void openFile(String filename) {
80      try {
81        fFilename = filename;
82        fReader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
83      } catch (IOException ex) {
84        Msg.err("filename=" + filename, ex);
85      }
86    }
87  
88    private boolean loadFile(URL url) {
89      try {
90        fColorTable.clear();
91        fReader = new BufferedReader(new InputStreamReader(url.openStream()));
92        parseFile();
93      } catch (IOException ioe) {
94        return false;
95      }
96      return true;
97    }
98  
99    private boolean loadFile(String filename) {
100     try {
101       fColorTable.clear();
102       openFile(filename);
103       parseFile();
104       return true;
105     } catch (IOException ioe) {
106       return false;
107     }
108   }
109 
110   private void parseFile() throws IOException {
111     String line;
112     do {
113       line = fReader.readLine();
114     } while (line != null && (line.length() == 0 || line.charAt(0) != '"'));
115     readMetaData(line.substring(1, line.length() - 2));
116     //
117     for (int i = 0; i < fColors; i++) {
118       readColor();
119     }
120     //
121     fData = new int[fRows * fColumns];
122     for (int i = 0; i < fRows; i++) {
123       readImageRow(i);
124     }
125     fTransparent = -1;
126     if (fTransparentSymbol != null) {
127       // FIXME: 
128       // . As of Eclipse 2.1.0 GTK, eclipse (Label and Button) do not handle transparent
129       //   icons correctly unless the transparentPixel==0.  This hack move any color==0
130       //   to 1 and always return fTransparent==0. 
131       fTransparent = 0;
132       //      // Look for first unused color. In most case, all these would do is just set fTransparent=0.
133       //      int[] values = fColorTable.values();
134       //      Arrays.sort(values);
135       //      if (DEBUG)
136       //        System.err.println(Sprint.array("values=", "%08x  ", values));
137       //      int last = -1;
138       //      for (int i = 0; i < values.length; ++i) {
139       //        // Unless color 0x000000 is used, otherwise fTransparent should be 0
140       //        // since the first color is always -1.
141       //        if (values[i] - last > 1) {
142       //          fTransparent = last + 1;
143       //          break;
144       //        }
145       //        last = values[i];
146       //      }
147       //      if (fTransparent < 0) {
148       //        Msg.err(
149       //          NAME
150       //            + ".parseFile(): Can't find unused color: transparent symbol="
151       //            + fTransparentSymbol);
152       //        fTransparent = 0;
153       //      }
154       //      // Init. transparent mask data.
155       //      for (int i = 0; i < fData.length; ++i) {
156       //        if (fData[i] < 0) {
157       //          fData[i] = fTransparent;
158       //        }
159       //      }
160     }
161   }
162 
163   private void readMetaData(String line) throws IOException {
164     if (line == null) {
165       throw new IllegalStateException("File " + fFilename + " contains no data");
166     }
167     StringTokenizer t = new StringTokenizer(line, " \t");
168     try {
169       fColumns = Integer.parseInt(t.nextToken());
170       fRows = Integer.parseInt(t.nextToken());
171       fColors = Integer.parseInt(t.nextToken());
172       fColorChars = Integer.parseInt(t.nextToken());
173     } catch (Exception e) {
174       throw new IllegalStateException("Malformed meta data line: " + line);
175     }
176   }
177 
178   /**
179    * Read a color row and remember it in the color table.
180    */
181   private void readColor() throws IOException {
182     String line;
183     do {
184       line = fReader.readLine();
185     } while (line != null && (line.length() == 0 || line.charAt(0) != '"'));
186     // Sanity check, min. length "s c #x"
187     if (line == null || line.length() < 8) {
188       throw new IllegalStateException("File " + fFilename + " ended prematurely");
189     }
190     int start = 1 + fColorChars;
191     int end = line.length() - 2;
192     String symbol = line.substring(1, start);
193     String hexval = null;
194     String s;
195     char c;
196     int index;
197     do {
198       start = TextUtil.skipSpaces(line, start, end);
199       while(start<end && !Character.isWhitespace(line.charAt(start))) ++start;
200       start = TextUtil.skipSpaces(line, start, end);
201       for (index = start; index < end; ++index) {
202         c = line.charAt(index);
203         if (c == ' ' || c == '\t' || c == 0xa0)
204           break;
205       }
206       s= line.substring(start, index);
207       c=line.charAt(start);
208       if(c=='#' || s.equalsIgnoreCase("none")) {
209         hexval = s;
210         break;
211       } else if(c=='"')
212         break;
213       
214       start = index;
215     } while (start < end);
216     if (hexval == null) {
217       throw new IllegalStateException("File " + fFilename + " invalid color value: " + line);
218     }
219     // Deal with the transparent color
220     // FIXME: 
221     // . As of Eclipse 2.1.0 GTK, eclipse (Label and Button) do not handle transparent
222     //   icons correctly unless the transparentPixel==0.  This hack move any color==0
223     //   to 1 and always return fTransparent==0. 
224     if (hexval.equalsIgnoreCase("none")) {
225       fTransparentSymbol = symbol;
226       //      fColorTable.put(symbol, -1);
227       fColorTable.put(symbol, 0);
228     } else {
229       int color = convertColorString(hexval);
230       if (color == 0)
231         color = 1;
232       fColorTable.put(symbol, color);
233     }
234   }
235 
236   private void readImageRow(int row) throws IOException {
237     String line;
238     do {
239       line = fReader.readLine();
240     } while (line != null && (line.length() == 0 || line.charAt(0) != '"'));
241     if (line == null) {
242       throw new IllegalStateException("Premature end of file " + fFilename);
243     }
244     line = line.substring(1, 1 + fColumns * fColorChars);
245     int offset = row * fColumns;
246     for (int i = 0; i < fColumns; i++) {
247       int start = i * fColorChars;
248       String c = line.substring(start, start + fColorChars);
249       fData[offset + i] = fColorTable.get(c);
250     }
251   }
252 
253   private int convertColorString(String colString) {
254     return Integer.parseInt(colString.substring(1), 16);
255   }
256 
257   ////////////////////////////////////////////////////////////////////////
258 
259   public static void main(String[] args) throws IOException {
260     System.err.println("dir=" + System.getProperty("user.dir"));
261     XPMFile xpm = new XPMFile(args[0]);
262     System.err.println("Transparent=" + xpm.getTransparentColor());
263     ImageFactory.getDefault().create(xpm, "test");
264   }
265 
266   ////////////////////////////////////////////////////////////////////////
267 }