/Users/lyon/j4p/src/graphics/dclap/Gr2PICT.java

1    // graphics.dclap/gr2pict.java 
2    // write java ip.graphics calls to outstream in PICT format (apple macintosh) 
3    // d.gilbert, dec. 1996 
4    // based on PSgr by E.J. Friedman-Hill 
5     
6     
7    package graphics.dclap; 
8     
9    // pack edu.indiana.bio.graphics.dclap; 
10    
11   import java.awt.*; 
12   import java.awt.image.ImageObserver; 
13   import java.io.DataOutputStream; 
14   import java.io.IOException; 
15   import java.io.OutputStream; 
16    
17   /** 
18    * Gr2PICT is a Graphics subclass that draws to PICT format. 
19    * @version 1.0 
20    * @author Don Gilbert 
21    */ 
22    
23    
24   public class Gr2PICT extends java.awt.Graphics { 
25   //uncomment for jdk 1.2 
26       public void drawString(java.text.AttributedCharacterIterator aci, int a, int b) { 
27       }; 
28    
29       public final static int CLONE = 49; 
30       protected final static int PAGEHEIGHT = 792; 
31       protected final static int PAGEWIDTH = 612; 
32    
33       protected DataOutputStream os; 
34       protected Color clr = Color.black; 
35       protected Font font = new 
36               Font("Times", Font.PLAIN, 12); 
37       protected Rectangle clipr = new Rectangle(-30000, -30000, 60000, 60000); 
38       protected Point origin = new Point(0, 0); 
39       protected boolean trouble = false; 
40       protected Graphics g; 
41    
42    
43       public Rectangle getClipBounds() { 
44           Rectangle r = new Rectangle(); 
45           return r; 
46       } 
47    
48       public void setClip(int a, int b, int c, int d) { 
49           return; 
50       } 
51    
52       public void setClip(java.awt.Shape a) { 
53           return; 
54       } 
55    
56       public java.awt.Shape getClip() { 
57           Rectangle s = new Rectangle(); 
58           return s; 
59       } 
60    
61       public void drawPolyline(int[] a, int[] b, int c) { 
62           return; 
63       } 
64    
65       public boolean drawImage(Image i, int a, int b, int c, int d, int e, int f, int g, int h, ImageObserver o) { 
66           return true; 
67       } 
68    
69       public boolean drawImage(Image i, int a, int b, int c, int d, int e, int f, int g, int h, Color cl, ImageObserver o) { 
70           return true; 
71       } 
72    
73       /** 
74        * Constructs a new Gr2PICT Object. Unlike regular Graphics objects, 
75        * Gr2PICT contexts can be created directly. 
76        * @param o Output stream for PostScript output 
77        * @see #create 
78        */ 
79    
80    
81       public Gr2PICT(OutputStream o, Graphics g) { 
82           os = new DataOutputStream(o); 
83           trouble = false; 
84           this.g = g; 
85           Rectangle r = g.getClipBounds(); 
86           if (r == null) 
87               r = new 
88                       Rectangle(0, 0, PAGEWIDTH, PAGEHEIGHT); 
89           emitHeader(r.width, r.height); 
90       } 
91    
92       public Gr2PICT(OutputStream o, 
93                      Graphics g, int what) { 
94           os = new DataOutputStream(o); 
95           trouble = false; 
96           this.g = g; 
97           Rectangle r = g.getClipBounds(); 
98           if (r == null) 
99               r = new 
100                      Rectangle(0, 0, PAGEWIDTH, PAGEHEIGHT); 
101          if (what != CLONE) 
102              emitHeader(r.width, r.height); 
103      } 
104   
105      private int fAlign = 0; 
106   
107      protected void emitbyte(int v) { 
108          try { 
109              os.writeByte(v); 
110              fAlign++; 
111          } catch (IOException ex) { 
112              trouble = true; 
113          } 
114      } 
115   
116      protected void emitword(int v, DataOutputStream dos) { 
117          try { 
118              dos.writeShort(v); 
119          } catch (IOException ex) { 
120              trouble = true; 
121          } 
122      } 
123   
124      protected void emitint(int v) { 
125          try { 
126              os.writeInt(v); 
127          } catch (IOException ex) { 
128              trouble = true; 
129          } 
130      } 
131   
132      protected void emitstring(String s) { 
133          try { 
134              os.writeBytes(s); 
135              fAlign += s.length(); 
136          } catch (IOException ex) { 
137              trouble = true; 
138          } 
139      } 
140   
141      protected final void emitop(int op) { 
142          if ((fAlign & 1) == 1) emitbyte(0); // pad to word size 
143          emitword(op, os); 
144      } 
145   
146      protected final void emitcolor(Color c) { 
147          emitword(c.getRed() << 8, os); 
148          emitword(c.getGreen() << 8, os); 
149          emitword(c.getBlue() << 8, os); 
150      } 
151   
152      protected final void emitrect(int x, int y, int width, int height) { 
153          emitword(y, os); 
154          emitword(x, os); 
155          emitword(y + height, os); 
156          emitword(x + width, os); 
157      } 
158   
159      protected final void emitroundrect( 
160              int opcode, int x, int y, 
161              int width, int height, int arcWidth, 
162              int arcHeight) { 
163          emitop(QD.oOvSize); 
164          emitword(arcHeight, os); 
165          emitword(arcWidth, os); 
166          emitop(opcode); 
167          emitrect(x, y, width, height); 
168      } 
169   
170      protected void emitpolygon(Polygon p) { 
171          int polysize = 2 + 8 + p.npoints * 4; 
172          emitword(polysize, os); 
173          Rectangle r = p.getBounds(); 
174          emitrect(r.x, r.y, r.width, r.height); 
175          for (int i = 0; i < p.npoints; i++) { 
176              emitword(p.ypoints[i], os); 
177              emitword(p.xpoints[i], os); 
178          } 
179      } 
180   
181      protected void emitcomment(int kind, int datasize, String data) { 
182          if (datasize == 0) { 
183              emitop(QD.oShortComment); 
184              emitword(kind, os); 
185          } else { 
186              emitop(QD.oLongComment); 
187              emitword(kind, os); 
188              emitword(data.length(), os); 
189              emitstring(data); 
190          } 
191      } 
192   
193      public final void beginPicGroup() { 
194          emitcomment(QD.picGrpBeg, 0, null); 
195      } 
196   
197      public final void endPicGroup() { 
198          emitcomment(QD.picGrpEnd, 0, null); 
199      } 
200   
201      public void laserLine(int num, int denom) { 
202          // set laserwriter line width 
203          // use num=1, denom=4 for 1/300 dpi line 
204          //emitcomment( QD.setLineWidth, sizeof(lineSize), lineSize); 
205          emitop(QD.oLongComment); 
206          emitword(QD.setLineWidth, os); 
207          emitword(4, os); 
208          emitword(num, os); 
209          emitword(denom, os); 
210      } 
211   
212   
213      /** 
214       Top of every PICT file 
215       */ 
216   
217      protected void emitHeader(int picwidth, int picheight) { 
218          // 512 byte writeHeader 
219          try { 
220              int buflen = 512; 
221              byte[] buf = new byte[buflen]; // java zeros buf !? 
222              os.write(buf, 0, buflen); 
223          } catch (IOException ex) { 
224              trouble = true; 
225          } 
226   
227          int picbytes = 0;  // will zero here suffice !? seems to be working... 
228          emitword(picbytes, os); 
229          emitrect(0, 0, picwidth, picheight); 
230          emitop(QD.oVersion); 
231          emitword(QD.version2, os); 
232   
233          // writeHeader from clarisdraw 
234          // C00   0x10 0xc00           :  (skip 24) FF FF FF FF FF FF  0  0 FF FF 
235   
236          emitop(QD.oHeaderOp); // reserved writeHeader opcode, followed by 24 byte writeHeader 
237          emitint(-1); // total size in bytes or -1 
238          for (int i = 0; i < 4; i++) { 
239              emitword(-1, os); 
240              emitword(0, os); 
241          } // fixedpt bound box or -1 
242          emitint(-1); // reserved or -1 
243   
244          //oDefHilite & clipRect of pict size as 1st op is usual but not required !? 
245          emitop(QD.oDefHilite); 
246          clipRect(clipr.x, clipr.y, clipr.width, clipr.height); 
247          beginPicGroup(); 
248      } 
249   
250   
251   
252      ///////////// Graphics Public Interface //////////// 
253   
254   
255   
256      /** 
257       * Creates a new Gr2PICT Object that is a copy of the original Gr2PICT Object. 
258       */ 
259      public Graphics create() { 
260          Gr2PICT grpict = new Gr2PICT(os, g, CLONE); 
261          grpict.font = font; 
262          grpict.clipr = clipr; 
263          grpict.clr = clr; 
264          return grpict; 
265      } 
266   
267      /** 
268       * Creates a new Graphics Object with the specified parameters, 
269       * based on the original 
270       * Graphics Object. 
271       * This method translates the specified parameters, x and y, to 
272       * the proper origin coordinates and then clips the Graphics Object to the 
273       * area. 
274       * @param x the x coordinate 
275       * @param y the y coordinate 
276       * @param width the width of the area 
277       * @param height the height of the area 
278       * @see #translate 
279       */ 
280      public Graphics create(int x, int y, int width, int height) { 
281          Graphics g = create(); 
282          g.translate(x, y); 
283          g.clipRect(0, 0, width, height); 
284          return g; 
285      } 
286   
287      /** 
288       * Translates the specified parameters into the origin of 
289       * the ip.graphics context. All subsequent 
290       * operations on this ip.graphics context will be relative to this origin. 
291       * @param x the x coordinate 
292       * @param y the y coordinate 
293       * @see #scale 
294       */ 
295   
296      public void translate(int x, int y) { 
297          // ? do this internally, adjusting each emitted x,y? 
298          origin.x = x; 
299          origin.y = y; 
300          // or as emitted opcode ?? 
301          emitop(QD.oOrigin); 
302          emitword(-x, os); 
303          emitword(-y, os); 
304      } 
305   
306   
307      /** 
308       * Gets the current color. 
309       * @see #setColor 
310       */ 
311      public Color getColor() { 
312          return clr; 
313      } 
314   
315   
316      /** 
317       * Sets the current color to the specified color. All subsequent ip.graphics operations 
318       * will use this specified color. 
319       * @param c the color to be set 
320       * @see Color 
321       * @see #getColor 
322       */ 
323   
324      public void setColor(Color c) { 
325          if (c != null) clr = c; 
326          emitop(QD.oRGBFgCol); 
327          emitcolor(clr); 
328      } 
329   
330   
331      /** 
332       * Sets the default paint mode to overwrite the destination with the 
333       * current color. 
334       */ 
335      public void setPaintMode() { 
336          emitop(QD.oPnMode); 
337          emitword(QD.patCopy, os); // or QD.patOr 
338      } 
339   
340      /** 
341       * Sets the paint mode to alternate between the current color 
342       * and the new specified color. 
343       * @param c1 the second color 
344       */ 
345      public void setXORMode(Color c1) { 
346          emitop(QD.oPnMode); 
347          emitword(QD.patXor, os); 
348          if (c1 != null) { 
349              // set c1 as PICT HiliteColor & set HiliteMode !? 
350              emitop(QD.oHiliteMode); 
351              emitop(QD.oHiliteColor); 
352              emitcolor(c1); 
353          } 
354      } 
355   
356      /** 
357       * Gets the current font. 
358       * @see #setFont 
359       */ 
360      public Font getFont() { 
361          return font; 
362      } 
363   
364      /** 
365       * Sets the font for all subsequent text-drawing operations. 
366       * @param font the specified font 
367       * @see Font 
368       * @see #getFont 
369       * @see #drawString 
370       * @see #drawBytes 
371       * @see #drawChars 
372       */ 
373      public void setFont(Font f) { 
374          if (f != null) { 
375              this.font = f; 
376   
377              // count # bytes in name + number + 
378              String fname = font.getName(); 
379              fname = "Times"; // HACK! 
380              // Make sure the font is really 
381              // Times, for the purpose of printing!! 
382              int qdnum = QD.getQuickDrawFontNum(fname); 
383              if (qdnum >= 0) { 
384                  emitop(QD.oTxFont); 
385                  emitword(qdnum, os); 
386              } else { 
387                  emitop(QD.oFontName); 
388                  int len = fname.length() + 1 + 2 + 2; // length-byte + fontnum + #bytes total 
389                  emitword(len, os); 
390                  emitword(QD.fontnum++, os); 
391                  emitstring(fname); 
392              } 
393   
394              int face = 0; 
395              int style = font.getStyle(); 
396              if ((style & Font.BOLD) != 0) face |= QD.bold; 
397              if ((style & Font.ITALIC) != 0) face |= QD.italic; 
398              emitop(QD.oTxFace); 
399              emitbyte(face); 
400   
401              emitop(QD.oTxSize); 
402              emitword(font.getSize(), os); 
403          } 
404      } 
405   
406   
407      /** 
408       * Gets the current font metrics. 
409       * @see #getFont 
410       */ 
411      public FontMetrics getFontMetrics() { 
412          return getFontMetrics(getFont()); 
413      } 
414   
415      /** 
416       * Gets the current font metrics for the specified font. 
417       * @param f the specified font 
418       * @see #getFont 
419       * @see #getFontMetrics 
420       */ 
421      public FontMetrics getFontMetrics(Font f) { 
422          return g.getFontMetrics(f); 
423      } 
424   
425   
426      /** 
427       * Returns the bounding rectangle of the current clipping area. 
428       * @see #clipRect 
429       */ 
430      public Rectangle getBounds() { 
431          return clipr; 
432      } 
433   
434      /** 
435       * Clips to a rectangle. The resulting clipping area is the 
436       * intersection of the current clipping area and the specified 
437       * rectangle. Graphic operations have no effect outside of the 
438       * clipping area. 
439       * @param x the x coordinate 
440       * @param y the y coordinate 
441       * @param width the width of the rectangle 
442       * @param height the height of the rectangle 
443       * @see #getClipRect 
444       */ 
445      public void clipRect(int x, int y, int width, int height) { 
446          clipr = new Rectangle(x, y, width, height); 
447          emitop(QD.oClip); 
448          int rgnsize = 2 + 8; //size-word + sizeof(rect) + sizeof(region)?? 
449          emitword(rgnsize, os); 
450          emitrect(x, y, width, height); 
451      } 
452   
453      /** 
454       * Copies an area of the screen. 
455       * @param x the x-coordinate of the source 
456       * @param y the y-coordinate of the source 
457       * @param width the width 
458       * @param height the height 
459       * @param dx the horizontal distance 
460       * @param dy the vertical distance 
461       */ 
462      public void copyArea(int x, int y, int width, int height, int dx, int dy) { 
463          //throw new RuntimeException("copyArea not supported"); 
464      } 
465   
466      /** 
467       * Draws a line between the coordinates (x1,y1) and (x2,y2). The line is drawn 
468       * below and to the left of the logical coordinates. 
469       * @param x1 the first point's x coordinate 
470       * @param y1 the first point's y coordinate 
471       * @param x2 the second point's x coordinate 
472       * @param y2 the second point's y coordinate 
473       */ 
474   
475      public void drawLine(int x1, int y1, int x2, int y2) { 
476          emitop(QD.oLine); 
477          emitword(y1, os); 
478          emitword(x1, os); 
479          emitword(y2, os); 
480          emitword(x2, os); 
481      } 
482   
483      /** 
484       * Fills the specified rectangle with the current color. 
485       * @param x the x coordinate 
486       * @param y the y coordinate 
487       * @param width the width of the rectangle 
488       * @param height the height of the rectangle 
489       * @see #drawRect 
490       * @see #clearRect 
491       */ 
492      public void fillRect(int x, int y, int width, int height) { 
493          emitop(QD.opaintRect); 
494          emitrect(x, y, width, height); 
495      } 
496   
497      /** 
498       * Draws the outline of the specified rectangle using the current color. 
499       * Use drawRect(x, y, width-1, height-1) to draw the outline inside the specified 
500       * rectangle. 
501       * @param x the x coordinate 
502       * @param y the y coordinate 
503       * @param width the width of the rectangle 
504       * @param height the height of the rectangle 
505       * @see #fillRect 
506       * @see #clearRect 
507       */ 
508      public void drawRect(int x, int y, int width, int height) { 
509          emitop(QD.oframeRect); 
510          emitrect(x, y, width, height); 
511      } 
512   
513      /** 
514       * Clears the specified rectangle by filling it with the current background color 
515       * of the current drawing surface. 
516       * Which drawing surface it selects depends on how the ip.graphics context 
517       * was created. 
518       * @param x the x coordinate 
519       * @param y the y coordinate 
520       * @param width the width of the rectangle 
521       * @param height the height of the rectangle 
522       * @see #fillRect 
523       * @see #drawRect 
524       */ 
525      public void clearRect(int x, int y, int width, int height) { 
526          emitop(QD.oeraseRect); 
527          emitrect(x, y, width, height); 
528      } 
529   
530   
531      /** 
532       * Draws an outlined rounded corner rectangle using the current color. 
533       * @param x the x coordinate 
534       * @param y the y coordinate 
535       * @param width the width of the rectangle 
536       * @param height the height of the rectangle 
537       * @param arcWidth the diameter of the arc 
538       * @param arcHeight the radius of the arc 
539       * @see #fillRoundRect 
540       */ 
541      public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { 
542          emitroundrect(QD.oframeRRect, x, y, width, height, arcWidth, arcHeight); 
543      } 
544   
545      /** 
546       * Draws a rounded rectangle filled in with the current color. 
547       * @param x the x coordinate 
548       * @param y the y coordinate 
549       * @param width the width of the rectangle 
550       * @param height the height of the rectangle 
551       * @param arcWidth the diameter of the arc 
552       * @param arcHeight the radius of the arc 
553       * @see #drawRoundRect 
554       */ 
555      public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { 
556          emitroundrect(QD.opaintRRect, x, y, width, height, arcWidth, arcHeight); 
557      } 
558   
559      /** 
560       * Draws a highlighted 3-D rectangle. 
561       * @param x the x coordinate 
562       * @param y the y coordinate 
563       * @param width the width of the rectangle 
564       * @param height the height of the rectangle 
565       * @param raised a boolean that states whether the rectangle is raised or not 
566       */ 
567      public void draw3DRect(int x, int y, int width, int height, boolean raised) { 
568          Color c = getColor(); 
569          Color brighter = c.brighter(); 
570          Color darker = c.darker(); 
571   
572          setColor(raised ? brighter : darker); 
573          drawLine(x, y, x, y + height); 
574          drawLine(x + 1, y, x + width - 1, y); 
575          setColor(raised ? darker : brighter); 
576          drawLine(x + 1, y + height, x + width, y + height); 
577          drawLine(x + width, y, x + width, y + height); 
578          setColor(c); 
579      } 
580   
581      /** 
582       * Paints a highlighted 3-D rectangle using the current color. 
583       * @param x the x coordinate 
584       * @param y the y coordinate 
585       * @param width the width of the rectangle 
586       * @param height the height of the rectangle 
587       * @param raised a boolean that states whether the rectangle is raised or not 
588       */ 
589      public void fill3DRect(int x, int y, int width, int height, boolean raised) { 
590          Color c = getColor(); 
591          Color brighter = c.brighter(); 
592          Color darker = c.darker(); 
593   
594          if (!raised) setColor(darker); 
595          fillRect(x + 1, y + 1, width - 2, height - 2); 
596          setColor(raised ? brighter : darker); 
597          drawLine(x, y, x, y + height - 1); 
598          drawLine(x + 1, y, x + width - 2, y); 
599          setColor(raised ? darker : brighter); 
600          drawLine(x + 1, y + height - 1, x + width - 1, y + height - 1); 
601          drawLine(x + width - 1, y, x + width - 1, y + height - 1); 
602          setColor(c); 
603      } 
604   
605      /** 
606       * Draws an oval inside the specified rectangle using the current color. 
607       * @param x the x coordinate 
608       * @param y the y coordinate 
609       * @param width the width of the rectangle 
610       * @param height the height of the rectangle 
611       * @see #fillOval 
612       */ 
613      public void drawOval(int x, int y, int width, int height) { 
614          emitop(QD.oframeOval); 
615          emitrect(x, y, width, height); 
616      } 
617   
618      /** 
619       * Fills an oval inside the specified rectangle using the current color. 
620       * @param x the x coordinate 
621       * @param y the y coordinate 
622       * @param width the width of the rectangle 
623       * @param height the height of the rectangle 
624       * @see #drawOval 
625       */ 
626      public void fillOval(int x, int y, int width, int height) { 
627          emitop(QD.opaintOval); 
628          emitrect(x, y, width, height); 
629      } 
630   
631   
632      /** 
633       * Draws an arc bounded by the specified rectangle from startAngle to 
634       * endAngle. 0 degrees is at the 3-o'clock position.Positive arc 
635       * angles indicate counter-clockwise rotations, negative arc angles are 
636       * drawn clockwise. 
637       * @param x the x coordinate 
638       * @param y the y coordinate 
639       * @param width the width of the rectangle 
640       * @param height the height of the rectangle 
641       * @param startAngle the beginning angle 
642       * @param arcAngle the angle of the arc (relative to startAngle). 
643       * @see #fillArc 
644       */ 
645      public void drawArc(int x, int y, int width, int height, 
646                          int startAngle, int arcAngle) { 
647          emitop(QD.oframeArc); 
648          emitrect(x, y, width, height); 
649          emitword(startAngle + 90, os); 
650          emitword(arcAngle, os); 
651      } 
652   
653      /** 
654       * Fills an arc using the current color. This generates a pie shape. 
655       * 
656       * @param x the x coordinate 
657       * @param y the y coordinate 
658       * @param width the width of the arc 
659       * @param height the height of the arc 
660       * @param startAngle the beginning angle 
661       * @param arcAngle the angle of the arc (relative to startAngle). 
662       * @see #drawArc 
663       */ 
664      public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { 
665          emitop(QD.opaintArc); 
666          emitrect(x, y, width, height); 
667          emitword(startAngle, os); 
668          emitword(arcAngle, os); 
669      } 
670   
671   
672      /** 
673       * Draws a polygon defined by an array of x points and y points. 
674       * @param xPoints an array of x points 
675       * @param yPoints an array of y points 
676       * @param nPoints the total number of points 
677       * @see #fillPolygon 
678       */ 
679      public void drawPolygon(int xPoints[], int yPoints[], int nPoints) { 
680          drawPolygon(new Polygon(xPoints, yPoints, nPoints)); 
681      } 
682   
683      /** 
684       * Draws a polygon defined by the specified point. 
685       * @param p the specified polygon 
686       * @see #fillPolygon 
687       */ 
688      public void drawPolygon(Polygon p) { 
689          emitop(QD.oframePoly); 
690          emitpolygon(p); 
691      } 
692   
693      /** 
694       * Fills a polygon with the current color. 
695       * @param xPoints an array of x points 
696       * @param yPoints an array of y points 
697       * @param nPoints the total number of points 
698       * @see #drawPolygon 
699       */ 
700      public void fillPolygon(int xPoints[], int yPoints[], int nPoints) { 
701          fillPolygon(new Polygon(xPoints, yPoints, nPoints)); 
702      } 
703   
704      /** 
705       * Fills the specified polygon with the current color. 
706       * @param p the polygon 
707       * @see #drawPolygon 
708       */ 
709      public void fillPolygon(Polygon p) { 
710          emitop(QD.opaintPoly); 
711          emitpolygon(p); 
712      } 
713   
714      /** 
715       * Draws the specified String using the current font and color. 
716       * The x,y position is the starting point of the baseline of the String. 
717       * @param str the String to be drawn 
718       * @param x the x coordinate 
719       * @param y the y coordinate 
720       * @see #drawChars 
721       * @see #drawBytes 
722       */ 
723      public void drawString(String str, int x, int y) { 
724          emitop(QD.oLongText); 
725          emitword(y, os); 
726          emitword(x, os); 
727          emitbyte(str.length()); 
728          emitstring(str); 
729      } 
730   
731      /** 
732       * Draws the specified characters using the current font and color. 
733       * @param data the array of characters to be drawn 
734       * @param offset the start offset in the data 
735       * @param length the number of characters to be drawn 
736       * @param x the x coordinate 
737       * @param y the y coordinate 
738       * @see #drawString 
739       * @see #drawBytes 
740       */ 
741      public void drawChars(char data[], int offset, int length, int x, int y) { 
742          drawString(new String(data, offset, length), x, y); 
743      } 
744   
745      /** 
746       * Draws the specified bytes using the current font and color. 
747       * @param data the data to be drawn 
748       * @param offset the start offset in the data 
749       * @param length the number of bytes that are drawn 
750       * @param x the x coordinate 
751       * @param y the y coordinate 
752       * @see #drawString 
753       * @see #drawChars 
754       */ 
755      public void drawBytes(byte data[], int offset, int length, int x, int y) { 
756          // deprecated: 
757          //drawString(new String(data, 0, offset, length), x, y); 
758          drawString(new String(data, offset, length), x, y); 
759      } 
760   
761   
762      /****** 
763       // possible data for imaging 
764       // hexadecimal digits 
765       protected final static char hd[] = {'0', '1', '2', '3', '4', '5', '6', '7', 
766       '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 
767       // number of chars in a full row of pixel data 
768       protected final static int charsPerRow = 12*6; 
769       *******/ 
770   
771   
772      public boolean doImage(Image img, int x, int y, int width, int height, 
773                             ImageObserver observer, Color bgcolor) { 
774          /****** 
775   
776           // This class fetches the pixels in its constructor. 
777           PixelConsumer pc = new PixelConsumer(img); 
778   
779           y = transformY(y); 
780           os.println("gsave"); 
781   
782           os.println("% build a temporary dictionary"); 
783           os.println("20 dict begin"); 
784           emitColorImageProlog(pc.xdim); 
785   
786           os.println("% lower left corner"); 
787           os.print(x); 
788           os.print(" "); 
789           os.print(y); 
790           os.println(" translate"); 
791   
792           // compute image size. First of all, if width or height is 0, image is 1:1. 
793           if (height == 0 || width == 0) { 
794           height = pc.ydim; 
795           width = pc.xdim; 
796           } 
797   
798           os.println("% size of image"); 
799           os.print(width); 
800           os.print(" "); 
801           os.print(height); 
802           os.println(" scale"); 
803   
804           os.print(pc.xdim); 
805           os.print(" "); 
806           os.print(pc.ydim); 
807           os.println(" 8"); 
808   
809           os.print("["); 
810           os.print(pc.xdim); 
811           os.print(" 0 0 -"); 
812           os.print(pc.ydim); 
813           os.print(" 0 "); 
814           os.print(0); 
815           os.println("]"); 
816   
817           os.println("{currentfile pix readhexstring pop}"); 
818           os.println("false 3 colorimage"); 
819           os.println(""); 
820   
821   
822           int offset, sleepyet=0;; 
823           // array to hold a line of pixel data 
824           char[] sb = new char[charsPerRow + 1]; 
825   
826           for (int i=0; i<pc.ydim; i++) { 
827           offset = 0; 
828           ++sleepyet; 
829           if (bgcolor == null) { 
830           // real color image. We're deliberately duplicating code here 
831           // in the interest of speed - we don't want to check bgcolor 
832           // on every iteration. 
833           for (int j=0; j<pc.xdim; j++) { 
834           int n = pc.pix[j][i]; 
835   
836           // put hex chars into string 
837           // flip red for blue, to make postscript happy. 
838   
839           sb[offset++] = hd[(n & 0xF0)     >>  4]; 
840           sb[offset++] = hd[(n & 0xF)           ]; 
841           sb[offset++] = hd[(n & 0xF000)   >> 12]; 
842           sb[offset++] = hd[(n & 0xF00)    >>  8]; 
843           sb[offset++] = hd[(n & 0xF00000) >> 20]; 
844           sb[offset++] = hd[(n & 0xF0000)  >> 16]; 
845   
846           if (offset >= charsPerRow) { 
847           String s = String.copyValueOf(sb, 0, offset); 
848           os.println(s); 
849           if (sleepyet > 5) { 
850           try { 
851           // let the screen update occasionally! 
852           Thread.sleep(15); 
853           } catch (java.lang.InterruptedException ex) { 
854           // yeah, so? 
855           } 
856           sleepyet = 0; 
857           } 
858           offset = 0; 
859           } 
860           } 
861           } else { 
862           os.println("%FalseColor"); // was System.out.println 
863           // false color image. 
864           for (int j=0; j<pc.xdim; j++) { 
865           int bg = 
866           bgcolor.getGreen() << 16 + bgcolor.getBlue() << 8 + bgcolor.getRed(); 
867           int fg = 
868           clr.getGreen() << 16 + clr.getBlue() << 8 + clr.getRed(); 
869   
870           int n = (pc.pix[j][i] == 1 ? fg : bg); 
871   
872           // put hex chars into string 
873   
874           sb[offset++] = hd[(n & 0xF0)     ]; 
875           sb[offset++] = hd[(n & 0xF)     ]; 
876           sb[offset++] = hd[(n & 0xF000)  ]; 
877           sb[offset++] = hd[(n & 0xF00)   ]; 
878           sb[offset++] = hd[(n & 0xF00000)]; 
879           sb[offset++] = hd[(n & 0xF0000) ]; 
880   
881           if (offset >= charsPerRow) { 
882           String s = String.copyValueOf(sb, 0, offset); 
883           os.println(s); 
884           if (sleepyet > 5) { 
885           try { 
886           // let the screen update occasionally! 
887           Thread.sleep(15); 
888           } catch (java.lang.InterruptedException ex) { 
889           // yeah, so? 
890           } 
891           sleepyet = 0; 
892           } 
893           offset = 0; 
894           } 
895           } 
896           } 
897           // print partial rows 
898           if (offset != 0) { 
899           String s = String.copyValueOf(sb, 0, offset); 
900           os.println(s); 
901           } 
902           } 
903   
904           os.println(""); 
905           os.println("end"); 
906           os.println("grestore"); 
907           ************/ 
908          return true; 
909      } 
910   
911      /** 
912       * Draws the specified image at the specified coordinate (x, y). If the image is 
913       * incomplete the image observer will be notified later. 
914       * @param img the specified image to be drawn 
915       * @param x the x coordinate 
916       * @param y the y coordinate 
917       * @param observer notifies if the image is complete or not 
918       * @see Image 
919       * @see ImageObserver 
920       */ 
921   
922      public boolean drawImage(Image img, int x, int y, 
923                               ImageObserver observer) { 
924          return doImage(img, x, y, 0, 0, observer, null); 
925      } 
926   
927      /** 
928       * Draws the specified image inside the specified rectangle. The image is 
929       * scaled if necessary. If the image is incomplete the image observer will be 
930       * notified later. 
931       * @param img the specified image to be drawn 
932       * @param x the x coordinate 
933       * @param y the y coordinate 
934       * @param width the width of the rectangle 
935       * @param height the height of the rectangle 
936       * @param observer notifies if the image is complete or not 
937       * @see Image 
938       * @see ImageObserver 
939       */ 
940      public boolean drawImage(Image img, int x, int y, 
941                               int width, int height, 
942                               ImageObserver observer) { 
943          return doImage(img, x, y, width, height, observer, null); 
944      } 
945   
946      /** 
947       * Draws the specified image at the specified coordinate (x, y). If the image is 
948       * incomplete the image observer will be notified later. 
949       * @param img the specified image to be drawn 
950       * @param x the x coordinate 
951       * @param y the y coordinate 
952       * @param bgcolor the background color 
953       * @param observer notifies if the image is complete or not 
954       * @see Image 
955       * @see ImageObserver 
956       */ 
957   
958      public boolean drawImage(Image img, int x, int y, Color bgcolor, 
959                               ImageObserver observer) { 
960          return doImage(img, x, y, 0, 0, observer, bgcolor); 
961      } 
962   
963      /** 
964       * Draws the specified image inside the specified rectangle. The image is 
965       * scaled if necessary. If the image is incomplete the image observer will be 
966       * notified later. 
967       * @param img the specified image to be drawn 
968       * @param x the x coordinate 
969       * @param y the y coordinate 
970       * @param width the width of the rectangle 
971       * @param height the height of the rectangle 
972       * @param bgcolor the background color 
973       * @param observer notifies if the image is complete or not 
974       * @see Image 
975       * @see ImageObserver 
976       * 
977       */ 
978      public boolean drawImage(Image img, int x, int y, 
979                               int width, int height, Color bgcolor, 
980                               ImageObserver observer) { 
981          return doImage(img, x, y, width, height, observer, bgcolor); 
982      } 
983   
984      /** 
985       * Disposes of this ip.graphics context.  The Graphics context cannot be used after 
986       * being disposed of. 
987       * @see #finalize 
988       */ 
989      public void dispose() { 
990          endPicGroup(); 
991          emitop(QD.oopEndPic); 
992          try { 
993              os.flush(); 
994          } catch (IOException ex) { 
995              trouble = true; 
996          } 
997      } 
998   
999      /** 
1000      * Disposes of this ip.graphics context once it is no longer referenced. 
1001      * @see #dispose 
1002      */ 
1003     public void finalize() { 
1004         super.finalize(); 
1005         dispose(); 
1006     } 
1007  
1008     /** 
1009      * Returns a String object representing this Graphic's value. 
1010      */ 
1011     public String toString() { 
1012         return getClass().getName() + "[font=" + getFont() + ",color=" + getColor() + "]"; 
1013     } 
1014  
1015     public boolean checkError() { 
1016         return trouble; 
1017     } 
1018  
1019 } 
1020  
1021  
1022