OSDN Git Service

5130d8d98fcd0cc95247bc4105dc18a35aa9690e
[nxt-jsp/lejos_nxj.git] / nxtOSEK / lejos_nxj / src / java / classes / javax / microedition / lcdui / Graphics.java
1 package javax.microedition.lcdui;\r
2 \r
3 import lejos.nxt.LCD;\r
4 \r
5 \r
6 /**\r
7  * Preliminary Graphics class for LCD Screen\r
8  * @author Brian Bagnall\r
9  *\r
10  */\r
11 public class Graphics {\r
12         /** drawArc and fillArc accuracy parameter */\r
13         private static final int ARC_ACC = 5;\r
14 \r
15         /* Public color definitions */\r
16         public static final int BLACK = 1;\r
17         public static final int WHITE = 0;\r
18 \r
19         /* Public line stroke definitions */\r
20         public static final int SOLID   = 0;\r
21         public static final int DOTTED  = 2;\r
22 \r
23         private int rgbColor = BLACK;\r
24         private int strokeStyle = SOLID;\r
25 \r
26         public Graphics() {}\r
27         \r
28         public int getWidth() {\r
29                 return LCD.DISPLAY_WIDTH;\r
30         }\r
31         \r
32         public int getHeight() {\r
33                 return 2 * LCD.DISPLAY_DEPTH;\r
34         }\r
35         \r
36         public int getCenteredX(String str) {\r
37                 return (LCD.DISPLAY_CHAR_WIDTH - str.length()) / 2;\r
38         }\r
39                 \r
40         /**\r
41         * Using rgbColor as argument even though global, because when this\r
42         * setPixel() method is used later it will need color argument\r
43         */\r
44         public void setPixel(int rgbColor, int x, int y) {\r
45                 LCD.setPixel(rgbColor, x, y);\r
46         }\r
47 \r
48         public void drawLine(int x0, int y0, int x1, int y1) {\r
49                 drawLine(x0, y0, x1, y1, strokeStyle);\r
50         }\r
51         \r
52         private void drawLine(int x0, int y0, int x1, int y1, int style) {\r
53                 // Uses Bresenham's line algorithm\r
54                 int dy = y1 - y0;\r
55                 int dx = x1 - x0;\r
56                 int stepx, stepy;\r
57                 boolean skip = false;\r
58 \r
59                 if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }\r
60                 if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }\r
61                 dy <<= 1; // dy is now 2*dy\r
62                 dx <<= 1; // dx is now 2*dx\r
63 \r
64                 setPixel(rgbColor,x0, y0);\r
65                 if (dx > dy) {\r
66                         int fraction = dy - (dx >> 1);  // same as 2*dy - dx\r
67                         while (x0 != x1) {\r
68                                 if (fraction >= 0) {\r
69                                         y0 += stepy;\r
70                                         fraction -= dx; // same as fraction -= 2*dx\r
71                                 }\r
72                                 x0 += stepx;\r
73                                 fraction += dy; // same as fraction -= 2*dy\r
74                                 if ((style == SOLID) || !skip)\r
75                                         setPixel(rgbColor, x0, y0);\r
76                                 skip = !skip;\r
77                         }\r
78         } else {\r
79                         int fraction = dx - (dy >> 1);\r
80                         while (y0 != y1) {\r
81                                 if (fraction >= 0) {\r
82                                         x0 += stepx;\r
83                                         fraction -= dy;\r
84                                 }\r
85                                 y0 += stepy;\r
86                                 fraction += dx;\r
87                                 if ((style == SOLID) || !skip)\r
88                                         setPixel(rgbColor, x0, y0);\r
89                                 skip = !skip;\r
90                         }\r
91                 }\r
92         }\r
93 \r
94         public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {\r
95                 drawArc(x, y, width, height, startAngle, arcAngle, strokeStyle, false);\r
96         }\r
97         \r
98         public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {\r
99                 // drawArc is for now only SOLID \r
100                 drawArc(x, y, width, height, startAngle, arcAngle, SOLID, true);\r
101         }\r
102 \r
103         private void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle, \r
104                         int style, boolean fill) {\r
105                 // Scale up width and height to create more accurate ellipse form\r
106                 int xscale = (width < height) ? ARC_ACC : ((ARC_ACC * width + (width >> 1)) / height);\r
107                 int yscale = (width < height) ? ((ARC_ACC * height + (height >> 1)) / width) : ARC_ACC;\r
108                 \r
109                 // Calculate x, y center and radius from upper left corner\r
110                 int x0 = x + (width >> 1);\r
111                 int y0 = y + (height >> 1);\r
112                 int radius = (width < height) ? (width >> 1) : (height >> 1);\r
113                 \r
114                 // Check and set start and end angle\r
115                 int endAngle = startAngle + arcAngle;\r
116                 while (endAngle < 0) endAngle = endAngle + 360;\r
117                 while (endAngle > 360) endAngle = endAngle - 360;\r
118                 if(arcAngle < 0) { // Switches start and end\r
119                         int temp = startAngle;\r
120                         startAngle = endAngle;\r
121                         endAngle = (temp > 0) ? temp : 360;\r
122                 }\r
123                 \r
124                 // Initialize scaled up Bresenham's circle algorithm\r
125                 int f = (1 - ARC_ACC * radius);\r
126                 int ddF_x = 0;\r
127                 int ddF_y = -2 * ARC_ACC * radius;\r
128                 int xc = 0;\r
129                 int yc = ARC_ACC * radius;\r
130                 int dotskip = 0;\r
131                 while (xc < yc) {\r
132                         if (f >= 0) { \r
133                                 yc--;\r
134                                 ddF_y += 2;\r
135                                 f += ddF_y;\r
136                         }\r
137                     \r
138                         xc++;\r
139                     ddF_x += 2;\r
140                     f += ddF_x + 1;\r
141                     \r
142                     // Skip points for dotted version\r
143                     dotskip = (dotskip + 1) % (2 * ARC_ACC);\r
144                     if ((style == DOTTED) && !fill && (dotskip < ((2 * ARC_ACC) - 1))) continue;\r
145 \r
146                     // Scale down again\r
147                     int xxp = (xc * xscale + (xscale >> 1)) / (ARC_ACC * ARC_ACC);\r
148                     int xyp = (xc * yscale + (yscale >> 1)) / (ARC_ACC * ARC_ACC);\r
149                     int yyp = (yc * yscale + (yscale >> 1)) / (ARC_ACC * ARC_ACC);\r
150                     int yxp = (yc * xscale + (xscale >> 1)) / (ARC_ACC * ARC_ACC);\r
151                     \r
152                     // Calculate angle for partly circles / ellipses\r
153                     // NOTE: Below, (float) should not be needed. Not sure why Math.round() only accepts float.\r
154                     int tp = (int) Math.round((float) Math.toDegrees(Math.atan2(yc, xc)));\r
155                     if (fill) {\r
156                         /* TODO: Optimize more by drawing horizontal lines */\r
157                         if (((90 - tp) >= startAngle) && ((90 - tp) <= endAngle))\r
158                                 drawLine(x0, y0, x0 + yxp, y0 - xyp, style); // 0   - 45 degrees\r
159                         if ((tp >= startAngle) && (tp <= endAngle))\r
160                                 drawLine(x0, y0, x0 + xxp, y0 - yyp, style); // 45  - 90 degrees\r
161                         if (((180 - tp) >= startAngle) && ((180 - tp) <= endAngle))\r
162                                 drawLine(x0, y0, x0 - xxp, y0 - yyp, style); // 90  - 135 degrees\r
163                         if (((180 - (90 - tp)) >= startAngle) && ((180 - (90 - tp)) <= endAngle))\r
164                                 drawLine(x0, y0, x0 - yxp, y0 - xyp, style); // 135 - 180 degrees\r
165                         if (((270 - tp) >= startAngle) && ((270 - tp) <= endAngle))\r
166                                 drawLine(x0, y0, x0 - yxp, y0 + xyp, style); // 180 - 225 degrees\r
167                         if (((270 - (90 - tp)) >= startAngle) && ((270 - (90 - tp)) <= endAngle))\r
168                                 drawLine(x0, y0, x0 - xxp, y0 + yyp, style); // 225 - 270 degrees\r
169                         if (((360 - tp) >= startAngle) && ((360 - tp) <= endAngle))\r
170                                 drawLine(x0, y0, x0 + xxp, y0 + yyp, style); // 270 - 315 degrees\r
171                         if (((360 - (90 - tp)) >= startAngle) && ((360 - (90 - tp)) <= endAngle))\r
172                                 drawLine(x0, y0, x0 + yxp, y0 + xyp, style); // 315 - 360 degrees\r
173                     } else {\r
174                         if (((90 - tp) >= startAngle) && ((90 - tp) <= endAngle))\r
175                                 setPixel(rgbColor, x0 + yxp, y0 - xyp); // 0   - 45 degrees\r
176                         if ((tp >= startAngle) && (tp <= endAngle))\r
177                                 setPixel(rgbColor, x0 + xxp, y0 - yyp); // 45  - 90 degrees\r
178                         if (((180 - tp) >= startAngle) && ((180 - tp) <= endAngle))\r
179                                 setPixel(rgbColor, x0 - xxp, y0 - yyp); // 90  - 135 degrees\r
180                         if (((180 - (90 - tp)) >= startAngle) && ((180 - (90 - tp)) <= endAngle))\r
181                                 setPixel(rgbColor, x0 - yxp, y0 - xyp); // 135 - 180 degrees\r
182                         if (((270 - tp) >= startAngle) && ((270 - tp) <= endAngle))\r
183                                 setPixel(rgbColor, x0 - yxp, y0 + xyp); // 180 - 225 degrees\r
184                         if (((270 - (90 - tp)) >= startAngle) && ((270 - (90 - tp)) <= endAngle))\r
185                                 setPixel(rgbColor, x0 - xxp, y0 + yyp); // 225 - 270 degrees\r
186                         if (((360 - tp) >= startAngle) && ((360 - tp) <= endAngle))\r
187                                 setPixel(rgbColor, x0 + xxp, y0 + yyp); // 270 - 315 degrees\r
188                         if (((360 - (90 - tp)) >= startAngle) && ((360 - (90 - tp)) <= endAngle))\r
189                                 setPixel(rgbColor, x0 + yxp, y0 + xyp); // 315 - 360 degrees\r
190                     }\r
191                 }\r
192         }\r
193 \r
194         public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {\r
195 \r
196                 int xc = x + (width/2);\r
197                 int yc = y + (height/2);\r
198                 int a = arcWidth/2;\r
199                 int b = arcHeight/2;\r
200 \r
201                 int translateX = (width/2) - (arcWidth/2);\r
202                 int translateY = (height/2) - (arcHeight/2);\r
203 \r
204                 // Draw 4 sides:\r
205                 int xDiff = arcWidth/2;\r
206                 int yDiff = arcHeight/2;\r
207                 drawLine(x, y+yDiff, x, height-yDiff);\r
208                 drawLine(width, y+yDiff, width, height-yDiff);\r
209                 drawLine(x+xDiff, y, width-xDiff, y);\r
210                 drawLine(x+xDiff, height, width-xDiff, height);\r
211 \r
212 \r
213                 /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */\r
214                 int xxx = 0, yyy = b;\r
215                 int a2 = a*a, b2 = b*b;\r
216                 int crit1 = -(a2/4 + a%2 + b2);\r
217                 int crit2 = -(b2/4 + b%2 + a2);\r
218                 int crit3 = -(b2/4 + b%2);\r
219                 int t = -a2*yyy; /* e(xxx+1/2,y-1/2) - (a^2+b^2)/4 */\r
220                 int dxt = 2*b2*xxx, dyt = -2*a2*yyy;\r
221                 int d2xt = 2*b2, d2yt = 2*a2;\r
222 \r
223                 while (yyy>=0 && xxx<=a) {\r
224                         setPixel(BLACK, xc+xxx + translateX, yc+yyy + translateY); // Q4\r
225                         if (xxx!=0 || yyy!=0)\r
226                                 setPixel(BLACK, xc-xxx - translateX, yc-yyy - translateY); // Q2\r
227                         if (xxx!=0 && yyy!=0) {\r
228                                 setPixel(BLACK, xc+xxx + translateX, yc-yyy - translateY); // Q1\r
229                                 setPixel(BLACK, xc-xxx - translateX, yc+yyy + translateY); // Q3\r
230                         }\r
231                         if (t + b2*xxx <= crit1 ||   /* e(xxx+1,y-1/2) <= 0 */\r
232                             t + a2*yyy <= crit3)      /* e(xxx+1/2,y) <= 0 */\r
233                                 {xxx++; dxt += d2xt; t += dxt;} // incx()\r
234                          else if (t - a2*yyy > crit2) /* e(xxx+1/2,y-1) > 0 */\r
235                                 {yyy--; dyt += d2yt; t += dyt;}\r
236                         else {\r
237                                 {xxx++; dxt += d2xt; t += dxt;} // incx()\r
238                                 {yyy--; dyt += d2yt; t += dyt;}\r
239                         }\r
240                 }\r
241         }\r
242 \r
243         \r
244         public void drawRect(int x, int y, int width, int height) {\r
245                 if ((width < 0) || (height < 0))\r
246                         return;\r
247 \r
248                 if (height == 0 || width == 0) {\r
249                         drawLine(x, y, x + width, y + height);\r
250                 } else {\r
251                 drawLine(x, y, x + width - 1, y);\r
252                         drawLine(x + width, y, x + width, y + height - 1);\r
253                         drawLine(x + width, y + height, x + 1, y + height);\r
254                         drawLine(x, y + height, x, y + 1);\r
255                 }\r
256     }\r
257          \r
258         public void fillRect(int x, int y, int width, int height) {\r
259                 if ((width < 0) || (height < 0))\r
260                         return;\r
261 \r
262                 for(int i=y;i<y + height;i++) \r
263                         drawLine(x, i, x + width, i);\r
264                         //for(int j=x; j<x+width;j++) // Barely faster than using lines.\r
265                                 //setPixel(rgbColor, j, i);\r
266         }\r
267 \r
268         public void drawString(String str, int x, int y) {\r
269                 drawString(str, x, y, false);\r
270         }\r
271         \r
272         public void drawString(String str, int x, int y, boolean invert) {\r
273                 LCD.drawString(str, x, y, invert);\r
274         }\r
275         \r
276         public void drawChar(char c, int x, int y, boolean invert) {\r
277                 LCD.drawChar(c, x, y, invert);\r
278         }\r
279         \r
280         public void drawImage(Image img, int x, int y, boolean invert) {\r
281                 if (img == null) {\r
282                         return;\r
283                 }\r
284                 \r
285                 byte[] imgData = img.getData();\r
286                 for (int iy = y; iy < (y + img.getHeight()); iy += 8) {\r
287                         int yOffset = ((iy - y) / 8) * img.getWidth();\r
288                         for (int ix = x; ix < (x + img.getWidth()); ix++) {\r
289                                 LCD.drawPixels(imgData[yOffset + (ix - x)], ix, iy, invert);\r
290                         }\r
291                 }\r
292         }\r
293 \r
294         public int getStrokeStyle() {\r
295                 return strokeStyle;\r
296         }\r
297 \r
298         public void setStrokeStyle(int style) {\r
299                 if (style != SOLID && style != DOTTED) {\r
300                         throw new IllegalArgumentException();\r
301                 }\r
302                 strokeStyle = style;\r
303         }\r
304 \r
305         // Temp for testing purposes until Canvas made.\r
306         public void refresh() {\r
307                 LCD.setDisplay();\r
308                 LCD.refresh();\r
309         }\r
310         \r
311         // Temp method for testing. Clears out graphics buffer\r
312         // and refreshes screen.\r
313         public void clear() {\r
314                 LCD.clearDisplay();\r
315         }\r
316 }\r
317 \r
318 /*\r
319 class LCD extends JPanel {\r
320         public static final int SCREEN_WIDTH = 100;\r
321         public static final int SCREEN_HEIGHT = 64;\r
322         public static final int SCREEN_SCALE = 4;\r
323 \r
324         public static int [] screenBuf;\r
325         public Graphics nxjGraphics;\r
326         \r
327         // drawArc and fillArc parameters\r
328         int x = 10;\r
329         int y = 10;\r
330         int width = 80;\r
331         int height = 50;\r
332         int start = 0;\r
333         int angle = -135;\r
334         \r
335         public LCD() {\r
336                 setBackground(Color.WHITE);\r
337                 setPreferredSize(new Dimension(SCREEN_SCALE * SCREEN_WIDTH, \r
338                                 SCREEN_SCALE * SCREEN_HEIGHT));\r
339 \r
340                 nxjGraphics = new Graphics();\r
341                 nxjGraphics.setStrokeStyle(Graphics.DOTTED);\r
342                 nxjGraphics.drawLine(0, 0, 100, 64);\r
343                 nxjGraphics.fillArc(x, y, width, height, start, angle);\r
344                 nxjGraphics.drawArc(10, 10, 20, 40, 0, 360);\r
345 //              nxjGraphics.drawRoundRect(75, 5, 20, 10, 45, 45);\r
346                 nxjGraphics.refresh();\r
347                 repaint();\r
348         }\r
349 \r
350         public static void drawString(String str, int x, int y) {}\r
351         public static void setDisplay(int [] buff) {\r
352                 screenBuf = buff;\r
353         }\r
354         public static void refresh() {}\r
355         \r
356     public synchronized void paint(java.awt.Graphics g) {\r
357         int w = getSize().width;\r
358         int h = getSize().height;\r
359 \r
360         java.awt.Graphics2D g2 = (java.awt.Graphics2D) g;\r
361         g2.setBackground(getBackground());\r
362         g2.clearRect(0, 0, w, h); \r
363         \r
364         // Draw example image for verification\r
365         g2.setColor(Color.RED);\r
366         g2.fillArc(SCREEN_SCALE * x, SCREEN_SCALE * y, SCREEN_SCALE * width, \r
367                         SCREEN_SCALE * height, start, angle);\r
368         g2.drawRect(300, 20, 80, 40);\r
369         g2.drawRoundRect(300, 20, 80, 40, 45, 30);\r
370 \r
371         // Draw NXJ image\r
372         g2.setColor(Color.BLACK);\r
373         for (int xp = 0; xp < 100; xp++) {\r
374                 for (int yp = 0; yp < 64; yp++) {\r
375                         if (xp < 0 || xp >= 100 || yp < 0 || yp >= 64) continue;\r
376                         int xChar = xp / 4;\r
377                         int yChar = yp / 8;\r
378                         int index = yChar * 25 + xChar;\r
379                         int specificBit = (yp % 8) + ((xp % 4) * 8);\r
380                         if ((screenBuf[index] & (1 << specificBit)) != 0) {\r
381                                 g2.drawRect(SCREEN_SCALE * xp, SCREEN_SCALE * yp, \r
382                                                 SCREEN_SCALE, SCREEN_SCALE);\r
383                         }\r
384                 }\r
385         }        \r
386     }\r
387 }\r
388 \r
389 class TestApp extends JFrame {\r
390         public TestApp() {\r
391                 // End application when window is closed\r
392         addWindowListener(new WindowAdapter() {\r
393             public void windowClosing(WindowEvent e) {\r
394                 System.exit(0);\r
395             }\r
396         });\r
397 \r
398         setTitle("NXJ Grapics test app");\r
399                 getContentPane().add(new LCD());\r
400             pack();\r
401             show();\r
402         }\r
403 \r
404         public static void main(String[] args) {\r
405                 new TestApp();\r
406         }\r
407 }\r
408 \r
409 */