// dclap/gr2pict.java
// write java graphics calls to outstream in PICT format (apple macintosh)
// d.gilbert, dec. 1996
// based on PSgr by E.J. Friedman-Hill
package dclap;
// pack edu.indiana.bio.dclap;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.lang.*;
import java.util.*;
//import dclap.util.PixelConsumer; // not yet used
//also uses dclap.QD; // dclap/quickdraw constants
/**
* Gr2PICT is a Graphics subclass that draws to PICT format.
* @version 1.0
* @author Don Gilbert
*/
public class Gr2PICT extends java.awt.Graphics
{
public final static int CLONE = 49;
protected static int PAGEHEIGHT = 792;
protected static int PAGEWIDTH = 612;
protected DataOutputStream os;
protected Color clr = Color.black;
protected Font font = new Font("Times",Font.PLAIN,12);
protected Rectangle clipr = new Rectangle(-30000,-30000,60000,60000);
protected Point origin = new Point(0,0);
protected boolean trouble = false;
protected Graphics g;
/**
* Constructs a new Gr2PICT Object. Unlike regular Graphics objects,
* Gr2PICT contexts can be created directly.
* @param o Output stream for PostScript output
* @see #create
*/
public Gr2PICT(OutputStream o, Graphics g) {
this(o, g, 0);
}
public Gr2PICT(OutputStream o, Graphics g, int what) {
this.g = g;
os = new DataOutputStream(o);
trouble = false;
Rectangle r= g.getClipRect();
if (r==null) r= new Rectangle(0,0,PAGEWIDTH,PAGEHEIGHT);
if (what != CLONE) emitHeader(r.width,r.height);
}
public static void setPagesize(int width, int height) {
PAGEWIDTH= width; PAGEHEIGHT= height;
}
private int fAlign= 0;
protected void emitbyte(int v) {
try { os.writeByte(v); fAlign++; }
catch (IOException ex) { trouble = true; }
}
protected void emitword(int v) {
try { os.writeShort(v); }
catch (IOException ex) { trouble = true; }
}
protected void emitint(int v) {
try { os.writeInt(v); }
catch (IOException ex) { trouble = true; }
}
protected void emitstring(String s) {
try {
os.writeBytes(s);
fAlign += s.length();
}
catch (IOException ex) { trouble = true; }
}
protected final void emitop(int op) {
if ((fAlign & 1) == 1) emitbyte(0); // pad to word size
emitword(op);
}
protected final void emitcolor(Color c) {
emitword(c.getRed() << 8);
emitword(c.getGreen() << 8);
emitword(c.getBlue() << 8);
}
protected final void emitrect(int x, int y, int width, int height) {
emitword(y);
emitword(x);
emitword(y+height);
emitword(x+width);
}
protected final void emitroundrect(int opcode,int x, int y,
int width, int height, int arcWidth, int arcHeight)
{
emitop(QD.oOvSize);
emitword(arcHeight);
emitword(arcWidth);
emitop(opcode);
emitrect(x,y,width,height);
}
protected void emitpolygon(Polygon p) {
int polysize= 2 + 8 + p.npoints * 4;
emitword(polysize);
Rectangle r= p.getBoundingBox();
emitrect(r.x,r.y,r.width,r.height);
for (int i=0; i
= 0) {
emitop(QD.oTxFont);
emitword(qdnum);
}
else {
emitop(QD.oFontName);
int len= fname.length() + 1 + 2 + 2; // length-byte + fontnum + #bytes total
emitword(len);
emitword(QD.fontnum++);
emitstring(fname);
}
int face= 0;
int style= font.getStyle();
if ((style & Font.BOLD) != 0) face |= QD.bold;
if ((style & Font.ITALIC) != 0) face |= QD.italic;
emitop(QD.oTxFace);
emitbyte(face);
emitop(QD.oTxSize);
emitword(font.getSize());
}
}
/**
* Gets the current font metrics.
* @see #getFont
*/
public FontMetrics getFontMetrics() {
return getFontMetrics(getFont());
}
/**
* Gets the current font metrics for the specified font.
* @param f the specified font
* @see #getFont
* @see #getFontMetrics
*/
public FontMetrics getFontMetrics(Font f) {
return g.getFontMetrics(f);
}
/**
* Returns the bounding rectangle of the current clipping area.
* @see #clipRect
*/
public Rectangle getClipRect() {
return clipr;
}
/**
* Clips to a rectangle. The resulting clipping area is the
* intersection of the current clipping area and the specified
* rectangle. Graphic operations have no effect outside of the
* clipping area.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #getClipRect
*/
public void clipRect(int x, int y, int width, int height) {
clipr = new Rectangle(x,y,width,height);
emitop(QD.oClip);
int rgnsize= 2 + 8; //size-word + sizeof(rect) + sizeof(region)??
emitword(rgnsize);
emitrect(x,y,width,height);
}
/**
* Copies an area of the screen.
* @param x the x-coordinate of the source
* @param y the y-coordinate of the source
* @param width the width
* @param height the height
* @param dx the horizontal distance
* @param dy the vertical distance
*/
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
//throw new RuntimeException("copyArea not supported");
}
/**
* Draws a line between the coordinates (x1,y1) and (x2,y2). The line is drawn
* below and to the left of the logical coordinates.
* @param x1 the first point's x coordinate
* @param y1 the first point's y coordinate
* @param x2 the second point's x coordinate
* @param y2 the second point's y coordinate
*/
public void drawLine(int x1, int y1, int x2, int y2) {
emitop(QD.oLine);
emitword(y1);
emitword(x1);
emitword(y2);
emitword(x2);
}
/**
* Fills the specified rectangle with the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #drawRect
* @see #clearRect
*/
public void fillRect(int x, int y, int width, int height) {
emitop(QD.opaintRect);
emitrect(x,y,width,height);
}
/**
* Draws the outline of the specified rectangle using the current color.
* Use drawRect(x, y, width-1, height-1) to draw the outline inside the specified
* rectangle.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #fillRect
* @see #clearRect
*/
public void drawRect(int x, int y, int width, int height) {
emitop(QD.oframeRect);
emitrect(x,y,width,height);
}
/**
* Clears the specified rectangle by filling it with the current background color
* of the current drawing surface.
* Which drawing surface it selects depends on how the graphics context
* was created.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #fillRect
* @see #drawRect
*/
public void clearRect(int x, int y, int width, int height) {
emitop(QD.oeraseRect);
emitrect(x,y,width,height);
}
/**
* Draws an outlined rounded corner rectangle using the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param arcWidth the diameter of the arc
* @param arcHeight the radius of the arc
* @see #fillRoundRect
*/
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
emitroundrect(QD.oframeRRect,x,y,width,height,arcWidth,arcHeight);
}
/**
* Draws a rounded rectangle filled in with the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param arcWidth the diameter of the arc
* @param arcHeight the radius of the arc
* @see #drawRoundRect
*/
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
emitroundrect(QD.opaintRRect,x,y,width,height,arcWidth,arcHeight);
}
/**
* Draws a highlighted 3-D rectangle.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param raised a boolean that states whether the rectangle is raised or not
*/
public void draw3DRect(int x, int y, int width, int height, boolean raised) {
Color c = getColor();
Color brighter = c.brighter();
Color darker = c.darker();
setColor(raised ? brighter : darker);
drawLine(x, y, x, y + height);
drawLine(x + 1, y, x + width - 1, y);
setColor(raised ? darker : brighter);
drawLine(x + 1, y + height, x + width, y + height);
drawLine(x + width, y, x + width, y + height);
setColor(c);
}
/**
* Paints a highlighted 3-D rectangle using the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param raised a boolean that states whether the rectangle is raised or not
*/
public void fill3DRect(int x, int y, int width, int height, boolean raised) {
Color c = getColor();
Color brighter = c.brighter();
Color darker = c.darker();
if (!raised) setColor(darker);
fillRect(x+1, y+1, width-2, height-2);
setColor(raised ? brighter : darker);
drawLine(x, y, x, y + height - 1);
drawLine(x + 1, y, x + width - 2, y);
setColor(raised ? darker : brighter);
drawLine(x + 1, y + height - 1, x + width - 1, y + height - 1);
drawLine(x + width - 1, y, x + width - 1, y + height - 1);
setColor(c);
}
/**
* Draws an oval inside the specified rectangle using the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #fillOval
*/
public void drawOval(int x, int y, int width, int height) {
emitop(QD.oframeOval);
emitrect(x,y,width,height);
}
/**
* Fills an oval inside the specified rectangle using the current color.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @see #drawOval
*/
public void fillOval(int x, int y, int width, int height) {
emitop(QD.opaintOval);
emitrect(x,y,width,height);
}
/**
* Draws an arc bounded by the specified rectangle from startAngle to
* endAngle. 0 degrees is at the 3-o'clock position.Positive arc
* angles indicate counter-clockwise rotations, negative arc angles are
* drawn clockwise.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param startAngle the beginning angle
* @param arcAngle the angle of the arc (relative to startAngle).
* @see #fillArc
*/
public void drawArc(int x, int y, int width, int height,
int startAngle, int arcAngle) {
emitop(QD.oframeArc);
emitrect(x,y,width,height);
emitword(startAngle);
emitword(arcAngle);
}
/**
* Fills an arc using the current color. This generates a pie shape.
*
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the arc
* @param height the height of the arc
* @param startAngle the beginning angle
* @param arcAngle the angle of the arc (relative to startAngle).
* @see #drawArc
*/
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
emitop(QD.opaintArc);
emitrect(x,y,width,height);
emitword(startAngle);
emitword(arcAngle);
}
/**
* Draws a polygon defined by an array of x points and y points.
* @param xPoints an array of x points
* @param yPoints an array of y points
* @param nPoints the total number of points
* @see #fillPolygon
*/
public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
drawPolygon(new Polygon(xPoints, yPoints, nPoints));
}
/**
* Draws a polygon defined by the specified point.
* @param p the specified polygon
* @see #fillPolygon
*/
public void drawPolygon(Polygon p) {
emitop(QD.oframePoly);
emitpolygon(p);
}
/**
* Fills a polygon with the current color.
* @param xPoints an array of x points
* @param yPoints an array of y points
* @param nPoints the total number of points
* @see #drawPolygon
*/
public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
fillPolygon(new Polygon(xPoints, yPoints, nPoints));
}
/**
* Fills the specified polygon with the current color.
* @param p the polygon
* @see #drawPolygon
*/
public void fillPolygon(Polygon p) {
emitop(QD.opaintPoly);
emitpolygon(p);
}
/**
* Draws the specified String using the current font and color.
* The x,y position is the starting point of the baseline of the String.
* @param str the String to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @see #drawChars
* @see #drawBytes
*/
public void drawString(String str, int x, int y) {
emitop(QD.oLongText);
emitword(y);
emitword(x);
emitbyte(str.length());
emitstring(str);
}
/**
* Draws the specified characters using the current font and color.
* @param data the array of characters to be drawn
* @param offset the start offset in the data
* @param length the number of characters to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @see #drawString
* @see #drawBytes
*/
public void drawChars(char data[], int offset, int length, int x, int y) {
drawString(new String(data, offset, length), x, y);
}
/**
* Draws the specified bytes using the current font and color.
* @param data the data to be drawn
* @param offset the start offset in the data
* @param length the number of bytes that are drawn
* @param x the x coordinate
* @param y the y coordinate
* @see #drawString
* @see #drawChars
*/
public void drawBytes(byte data[], int offset, int length, int x, int y) {
drawString(new String(data, 0, offset, length), x, y);
}
/******
// possible data for imaging
// hexadecimal digits
protected final static char hd[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
// number of chars in a full row of pixel data
protected final static int charsPerRow = 12*6;
*******/
public boolean doImage(Image img, int x, int y, int width, int height,
ImageObserver observer, Color bgcolor) {
/******
// This class fetches the pixels in its constructor.
PixelConsumer pc = new PixelConsumer(img);
y = transformY(y);
os.println("gsave");
os.println("% build a temporary dictionary");
os.println("20 dict begin");
emitColorImageProlog(pc.xdim);
os.println("% lower left corner");
os.print(x);
os.print(" ");
os.print(y);
os.println(" translate");
// compute image size. First of all, if width or height is 0, image is 1:1.
if (height == 0 || width == 0) {
height = pc.ydim;
width = pc.xdim;
}
os.println("% size of image");
os.print(width);
os.print(" ");
os.print(height);
os.println(" scale");
os.print(pc.xdim);
os.print(" ");
os.print(pc.ydim);
os.println(" 8");
os.print("[");
os.print(pc.xdim);
os.print(" 0 0 -");
os.print(pc.ydim);
os.print(" 0 ");
os.print(0);
os.println("]");
os.println("{currentfile pix readhexstring pop}");
os.println("false 3 colorimage");
os.println("");
int offset, sleepyet=0;;
// array to hold a line of pixel data
char[] sb = new char[charsPerRow + 1];
for (int i=0; i> 4];
sb[offset++] = hd[(n & 0xF) ];
sb[offset++] = hd[(n & 0xF000) >> 12];
sb[offset++] = hd[(n & 0xF00) >> 8];
sb[offset++] = hd[(n & 0xF00000) >> 20];
sb[offset++] = hd[(n & 0xF0000) >> 16];
if (offset >= charsPerRow) {
String s = String.copyValueOf(sb, 0, offset);
os.println(s);
if (sleepyet > 5) {
try {
// let the screen update occasionally!
Thread.sleep(15);
} catch (java.lang.InterruptedException ex) {
// yeah, so?
}
sleepyet = 0;
}
offset = 0;
}
}
} else {
os.println("%FalseColor"); // was System.out.println
// false color image.
for (int j=0; j= charsPerRow) {
String s = String.copyValueOf(sb, 0, offset);
os.println(s);
if (sleepyet > 5) {
try {
// let the screen update occasionally!
Thread.sleep(15);
} catch (java.lang.InterruptedException ex) {
// yeah, so?
}
sleepyet = 0;
}
offset = 0;
}
}
}
// print partial rows
if (offset != 0) {
String s = String.copyValueOf(sb, 0, offset);
os.println(s);
}
}
os.println("");
os.println("end");
os.println("grestore");
************/
return true;
}
/**
* Draws the specified image at the specified coordinate (x, y). If the image is
* incomplete the image observer will be notified later.
* @param img the specified image to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @param observer notifies if the image is complete or not
* @see Image
* @see ImageObserver
*/
public boolean drawImage(Image img, int x, int y,
ImageObserver observer) {
return doImage(img, x, y, 0, 0, observer, null);
}
/**
* Draws the specified image inside the specified rectangle. The image is
* scaled if necessary. If the image is incomplete the image observer will be
* notified later.
* @param img the specified image to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param observer notifies if the image is complete or not
* @see Image
* @see ImageObserver
*/
public boolean drawImage(Image img, int x, int y,
int width, int height,
ImageObserver observer) {
return doImage(img, x, y, width, height, observer, null);
}
/**
* Draws the specified image at the specified coordinate (x, y). If the image is
* incomplete the image observer will be notified later.
* @param img the specified image to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @param bgcolor the background color
* @param observer notifies if the image is complete or not
* @see Image
* @see ImageObserver
*/
public boolean drawImage(Image img, int x, int y, Color bgcolor,
ImageObserver observer) {
return doImage(img, x, y, 0, 0, observer, bgcolor);
}
/**
* Draws the specified image inside the specified rectangle. The image is
* scaled if necessary. If the image is incomplete the image observer will be
* notified later.
* @param img the specified image to be drawn
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the rectangle
* @param height the height of the rectangle
* @param bgcolor the background color
* @param observer notifies if the image is complete or not
* @see Image
* @see ImageObserver
* NOTE: Gr2PICT ignores the background color.
*/
public boolean drawImage(Image img, int x, int y,
int width, int height, Color bgcolor,
ImageObserver observer) {
return doImage(img, x, y, width, height, observer, bgcolor);
}
/**
* Disposes of this graphics context. The Graphics context cannot be used after
* being disposed of.
* @see #finalize
*/
public void dispose() {
endPicGroup();
emitop(QD.oopEndPic);
try { os.flush(); }
catch (IOException ex) { trouble = true; }
}
/**
* Disposes of this graphics context once it is no longer referenced.
* @see #dispose
*/
public void finalize() {
super.finalize();
dispose();
}
/**
* Returns a String object representing this Graphic's value.
*/
public String toString() {
return getClass().getName() + "[font=" + getFont() + ",color=" + getColor() + "]";
}
public boolean checkError() {
return trouble;
}
}