1 /*
2  * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*-
27  *      Reads xbitmap format images into a DIBitmap structure.
28  */
29 package sun.awt.image;
30 
31 import java.io.*;
32 import java.awt.image.*;
33 
34 /**
35  * Parse files of the form:
36  *
37  * #define foo_width w
38  * #define foo_height h
39  * static char foo_bits[] = {
40  * 0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,
41  * 0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,0xnn,
42  * 0xnn,0xnn,0xnn,0xnn};
43  *
44  * @author James Gosling
45  */
46 public class XbmImageDecoder extends ImageDecoder {
47     private static byte[] XbmColormap = {(byte) 255, (byte) 255, (byte) 255,
48                                          0, 0, 0};
49     private static int XbmHints = (ImageConsumer.TOPDOWNLEFTRIGHT |
50                                    ImageConsumer.COMPLETESCANLINES |
51                                    ImageConsumer.SINGLEPASS |
52                                    ImageConsumer.SINGLEFRAME);
53 
XbmImageDecoder(InputStreamImageSource src, InputStream is)54     public XbmImageDecoder(InputStreamImageSource src, InputStream is) {
55         super(src, is);
56         if (!(input instanceof BufferedInputStream)) {
57             // If the topmost stream is a metered stream,
58             // we take forever to decode the image...
59             input = new BufferedInputStream(input, 80);
60         }
61     }
62 
63 
64     /**
65      * An error has occurred. Throw an exception.
66      */
error(String s1)67     private static void error(String s1) throws ImageFormatException {
68         throw new ImageFormatException(s1);
69     }
70 
71     /**
72      * produce an image from the stream.
73      */
produceImage()74     public void produceImage() throws IOException, ImageFormatException {
75         char[] nm = new char[80];
76         int c;
77         int i = 0;
78         int state = 0;
79         int H = 0;
80         int W = 0;
81         int x = 0;
82         int y = 0;
83         boolean start = true;
84         byte[] raster = null;
85         IndexColorModel model = null;
86         while (!aborted && (c = input.read()) != -1) {
87             if ('a' <= c && c <= 'z' ||
88                     'A' <= c && c <= 'Z' ||
89                     '0' <= c && c <= '9' || c == '#' || c == '_') {
90                 if (i < 78)
91                     nm[i++] = (char) c;
92             } else if (i > 0) {
93                 int nc = i;
94                 i = 0;
95                 if (start) {
96                     if (nc != 7 ||
97                         nm[0] != '#' ||
98                         nm[1] != 'd' ||
99                         nm[2] != 'e' ||
100                         nm[3] != 'f' ||
101                         nm[4] != 'i' ||
102                         nm[5] != 'n' ||
103                         nm[6] != 'e')
104                     {
105                         error("Not an XBM file");
106                     }
107                     start = false;
108                 }
109                 if (nm[nc - 1] == 'h')
110                     state = 1;  /* expecting width */
111                 else if (nm[nc - 1] == 't' && nc > 1 && nm[nc - 2] == 'h')
112                     state = 2;  /* expecting height */
113                 else if (nc > 2 && state < 0 && nm[0] == '0' && nm[1] == 'x') {
114                     int n = 0;
115                     for (int p = 2; p < nc; p++) {
116                         c = nm[p];
117                         if ('0' <= c && c <= '9')
118                             c = c - '0';
119                         else if ('A' <= c && c <= 'Z')
120                             c = c - 'A' + 10;
121                         else if ('a' <= c && c <= 'z')
122                             c = c - 'a' + 10;
123                         else
124                             c = 0;
125                         n = n * 16 + c;
126                     }
127                     for (int mask = 1; mask <= 0x80; mask <<= 1) {
128                         if (x < W) {
129                             if ((n & mask) != 0)
130                                 raster[x] = 1;
131                             else
132                                 raster[x] = 0;
133                         }
134                         x++;
135                     }
136                     if (x >= W) {
137                         if (setPixels(0, y, W, 1, model, raster, 0, W) <= 0) {
138                             return;
139                         }
140                         x = 0;
141                         if (y++ >= H) {
142                             break;
143                         }
144                     }
145                 } else {
146                     int n = 0;
147                     for (int p = 0; p < nc; p++)
148                         if ('0' <= (c = nm[p]) && c <= '9')
149                             n = n * 10 + c - '0';
150                         else {
151                             n = -1;
152                             break;
153                         }
154                     if (n > 0 && state > 0) {
155                         if (state == 1)
156                             W = n;
157                         else
158                             H = n;
159                         if (W == 0 || H == 0)
160                             state = 0;
161                         else {
162                             model = new IndexColorModel(8, 2, XbmColormap,
163                                                         0, false, 0);
164                             setDimensions(W, H);
165                             setColorModel(model);
166                             setHints(XbmHints);
167                             headerComplete();
168                             raster = new byte[W];
169                             state = -1;
170                         }
171                     }
172                 }
173             }
174         }
175         input.close();
176         imageComplete(ImageConsumer.STATICIMAGEDONE, true);
177     }
178 }
179