qd.pl
上传用户:qdrechuli
上传日期:2022-08-01
资源大小:917k
文件大小:32k
- #!/usr/local/bin/perl
- # $Id: qd.pl,v 1.2 1994/09/29 01:24:24 lstein Exp $
- # This is a package of routines that let you create Macintosh
- # PICT files from within perl. It implements a subset of Quickdraw
- # drawing commands, primarily those related to line drawing, rectangles,
- # ovals, polygons, and text. Flagrantly absent are: regions and the
- # snazzy color transfer modes. Regions are absent because they were
- # more trouble than I had time for, and the transfer modes because I
- # never use them. (The latter shouldn't be too hard to add.) Also
- # missing are the pixmap commands. If you want to do pixmaps, you
- # should be using the ppm utilities.
- # A QUICK TUTORIAL ON QUICKDRAW
- #
- # Quickdraw is not Postscript. You cannot write routines in it or get
- # (any useful) information out of it. Quickdraw pictures are a series of
- # drawing commands, concatenated together in a binary format.
- #
- # A Macintosh picture consists of a header describing the size of the
- # picture and its bounding rectangle, followed by a series of drawing
- # commands, followed by a termination code. This perl library is
- # modeled closely on the way that you would draw a picture on the Mac.
- # First you open the picture with the &qd'OpenPicture() command. This
- # initializes some data structures. Then you call a series of drawing
- # subroutines, such as &qd'TextFont(), &qd'MoveTo(), &qd'DrawString().
- # These routines append their data to the growing (but still private)
- # picture. You then close the picture with &qd'ClosePicture. This
- # returns a scalar variable containing the binary picture data.
- # RECTANGLES
- #
- # To open a picture you need to define a rectangle that will serve as
- # its frame and will define its drawing area. The rectangle is (of
- # course) a binary structure. The following utilities allow you to
- # create and manipulate rectangles:
- #
- # &qd'SetRect(*myRect,left,top,right,bottom); # Set the sides of $myRect
- # &qd'OffsetRect(*myRect,deltaH,deltaV); # Shift the rectangle as indicated
- # &qd'InsetRect(*myRect,deltaH,deltaV); # Shrink rectangle by size indicated
- # OPENING A PICTURE
- #
- # Pass a previously-defined rectangle to the routine OpenPicture. Only one picture
- # may be open at a time. The rectangle defines the drawing area in pixels.
- # A printer page is 8.5 x 11 inches, at 72 pixels per inch = 612 x 792 pixels.
- #
- # &qd'OpenPicture($myRect);
- #
- # You will next very likely want to set the clipping rectangle to the same rectangle
- # you used to open the picture with. Clipping rectangles limit quickdraw's drawing
- # to the area within the rectangle. Even if you don't use clipping, however, it's a
- # good idea to define the rectangle because some drawing programs behave eratically
- # when displaying unclipped pictures.
- #
- # You then issue drawing commands. When you're done you can get the picture data with
- # something like $pictData = &qd'ClosePicture;
- #
- # SETTING THE FOREGROUND AND BACKGROUND COLORS
- #
- # The foreground color is the color of the ink when a "frame" or "paint" command
- # is given. The background color is the color of the erased area when an "erase"
- # command is given. The defaults are black and white. The colors can be changed
- # in either of two ways:
- #
- # 1. The "old" 8-color system: black, white, red, green, blue, cyan, magenta, yellow
- # Call the routines &qd'FgColor() and &qd'BgColor() with one of the constants
- # $qd'REDCOLOR,$qd'GREENCOLOR, etc. This gives you a limited number of highly
- # satured colors.
- #
- # 2. The new 24-bit color system. Call the routines &qd'RGBForeColor() and
- # &qd'RGBBackColor(), passing the routines the red, green and blue components
- # of the color. These components are two-byte unsigned integers, so you can choose
- # any value between 0x000 and 0xFFFF. Higher is darker, so:
- # (0x0000,0x0000,0x0000) = BLACK
- # (0xFFFFF,0xFFFF,0xFFFF) = WHITE
- # (0xFFFFF,0x0000,0x0000) = PURE RED
- # etc.
- # SETTING THE PATTERN
- #
- # Like colors, the drawing commands use the current pattern, a 32 row x 32 column
- # bit array that defines the pattern of the "ink".
- # The default pattern is $qd'BLACK, which is solid black. The only
- # other pattern I've defined is $qd'GRAY, which is a 50% checkerboard. You
- # might want to define others.
- #
- # The current pattern is set using &qd'PenPat($myPattern).
- # LINE DRAWING
- #
- # Quickdraw has the concept of the "current point" of the pen. Generally
- # you move the pen to a point and then start drawing. The next time you draw,
- # the pen will be wherever the last drawing command left it. In addition, the
- # pen has a width, a pattern and a color. In the below descriptions,
- # h=horizontal, v=vertical
- #
- # &qd'MoveTo(h,v) # Move to indicated coordinates (0,0 is upper left of picture)
- # &qd'LineTo(h,v) # Draw from current position to indicated position
- # &qd'Line(dh,dv) # Draw a line dh pixels horizontally, dv pixels vertically,
- # starting at current position
- # &qd'PenSize(h,v) # Set the size of the pen to h pixels wide, v pixels high
- # PEN SCALING
- #
- # The original quickdraw was incapable of drawing at higher than the screen resolution,
- # so even if the PenSize is set to (1,1) the lines will appear chunky when printed out
- # on the laserwriter (which has four times the resolution of the screen). Call
- # &qd'Scale(1,4) to fix this problem by shrinking the pen down to a quarter of its
- # (1,1) size.
- #
- # &qd'Scale(numerator,denominator) # Scale the pen by the fraction numerator/denominator
- # TEXT
- #
- # &qd'TextFont(fontCode) # Set the current font to indicated code. Currently
- # defined fonts are $qd'TIMES, $qd'NEWCENTURYSCHOOLBK,
- # $qd'SYMBOL, $qd'HELVETICA, and $qd'COURIER.
- #
- # &qd'TextSize(size) # Set the current font size (in points). 12 point is typical
- #
- # &qd'TextFace(attributes) # Set one or more font style attributes. Currently defined
- # are $qd'PLAIN, $qd'BOLD, $qd'ITALIC, $qd'UNDERLINE, and
- # can be used in combination:
- # &qd'TextFace($qd'BOLD + $qd'ITALIC);
- #
- # &qd'DrawString(string) # Draw the indicated text. It will be drawn from the
- # current pen location. Word wrap is NOT supported.
- # Rotated text is NOT supported.
- #
- # &qd'TextWidth(string) # This will return an approximate width for the string
- # when it is printed in the current size, font and face.
- # Unfortunately, since perl has no access to the Macintosh
- # font description tables, the number returned by this
- # routine will be wildly inaccurate at best.
- # However, if you have X11R5 bdf fonts installed, we look
- # in the directory $qd'X11FONTS in order to find a bdf metrics
- # font to use. This will give you extremely accurate measurements.
- # Please set this variable to whatever is correct for your local
- # system. To add more fonts, put them in your bdf font directory
- # and update the %qd'font_metric_files array at the bottom of this
- # file. It maps a key consisting of the Quickdraw font number,
- # font size, and font style (0 for plain, 1 for italic, 2 for bold,
- # 3 for both) to the appropriate bdf file.
- # RECTANGLES
- #
- # Draw rectangles using the routines:
- # &qd'FrameRect($myRect); # Draw wire-frame rectangle
- # &qd'PaintRect($myRect); # Fill rectangle with current foreground
- # color and pattern
- # &qd'EraseRect($myRect); # Erase the rectangle (fill with bg color)
- # &qd'InvertRect($myRect); # Invert black and white in rectangle
- # OVALS
- #
- # Draw ovals using the routines:
- # &qd'FrameOval($myRect); # Draw wire-frame oval
- # &qd'PaintOval($myRect); # Fill oval with current foreground
- # color and pattern
- # &qd'EraseOval($myRect); # Erase the oval (fill with bg color)
- # &qd'InvertOval($myRect); # Invert black and white in oval
- # &qd'FillOval($myRect,$pat); # Fill with specified pattern
- #
- # ROUND RECTANGLES
- #
- # Draw round-cornered rectangles with these routines. They each take an oval radius
- # to determine the amount of curvature. Values of 10-20 are typical.
- # &qd'FrameRoundRect($myRect,$ovalWidth,$ovalHeight); # wire-frame outline
- # &qd'PaintRoundRect($myRect,$ovalWidth,$ovalHeight); # fill with current foreground
- # &qd'EraseRoundRect($myRect,$ovalWidth,$ovalHeight); # erase
- # &qd'InvertRoundRect($myRect,$ovalWidth,$ovalHeight);# invert
- # &qd'FillRoundRect($myRect,$ovalWidth,$ovalHeight,$pat); # fill with specified pattern
- # ARCS
- # Draw an arc subtending the specified rectangle. Angles are in degrees and
- # start pointing northward and get larger clockwise:
- # e.g. PaintArc($r,45,90) gives you a pie wedge from 2 o'clock to 5 o'clock
- # &qd'FrameArc($rect,$startAngle,$arcAngle); # wire-frame the arc
- # &qd'PaintArc($rect,$startAngle,$arcAngle); # fill with current foreground
- # &qd'EraseArc($rect,$startAngle,$arcAngle); # erase arc
- # &qd'InvertArc($rect,$startAngle,$arcAngle); # flip white and black
- # &qd'FillArc($rect,,$startAngle,$arcAngle,$pat); # fill with specified pattern
- # POLYGONS
- # Calling OpenPoly returns the name of a variable in which a growing
- # polygon structure will be stored. Once a polygon is opened, all drawing
- # commands cease to have an effect on the picture. Instead, all MoveTo,
- # LineTo and Line commands accumulate polygon vertices into the data structure.
- # Call ClosePoly to stop recording drawing commands. The polygon can now
- # be moved, scaled, drawn, filled and erased as many times as wished. Call
- # KillPoly to release the memory taken up by the polygon
- # $polygon = &qd'OpenPoly; # begin recording drawing commands
- # &qd'ClosePoly($polygon); # stop recording drawing commands
- # &qd'FramePoly($polygon); # wire-frame the polygon
- # &qd'PaintPoly($polygon); # fill with current foreground
- # &qd'ErasePoly($polygon); # erase polygon
- # &qd'FillPoly($polygon,$pat); # fill polygon with pattern
- # &qd'OffsetPoly($polygon,$dh,$dv); # translate poly by dh horizontally, dv vertically
- # &qd'MapPoly($polygon,$srcRect,$destRect); # map polygon from coordinate system defined by
- # source rectangle to that defined by destination
- # rectangle (moving or resizing it as needed)
- # PRINTING OUT THE PICTURE IN A FORM THAT THE MACINTOSH CAN READ
- #
- # The Mac expects its picture files to begin with 512 bytes of "application specific"
- # data. By default the picture data that you get will be proceeded by 512 bytes of
- # 0's. If you want something else, or if you just want the picture data, set the
- # package variable $qd'PICTHEADER to whatever you desire before calling ClosePicture.
- # In order for the picture data to be readable on the Macintosh, the file type must
- # be set to 'PICT'. A number of UNIX utilities, including mcvert and BinHex allow
- # you to do this. Or you can use the picttoppm utility (part of the netppm suite of
- # graphics tools) to translate the file into any format you desire.
- # A WORKING EXAMPLE
- # require "qd.pl";
- # &qd'SetRect(*myRect,0,0,500,500); # Define a 500 pixel square
- # &qd'OpenPicture($myRect); # Begin defining the picture
- # &qd'ClipRect($myRect); # Always a good idea
- # &qd'MoveTo(5,5); # Move the pen to a starting point
- # &qd'LineTo(400,400); # A diagonal line
- # &qd'TextFont($qd'COURIER); # Set the font
- # &qd'MoveTo(50,20); # Move the pen to a new starting point
- # &qd'DrawString("Hello there!"); # Friendly greeting
- # &qd'SetRect(*myRect,80,80,250,250); # New rectangle
- # &qd'RGBForeColor(0x0000,0x0000,0xFFFF); # Set the color to blue
- # &qd'PaintRect($myRect); # Fill rectangle with that color
- # $data = &qd'ClosePicture; # Close picture and retrieve data
- # # Pipe through binhex, setting the creator type to JVWR for JPEG Viewer
- # # Note: BinHex is available at <ftp://genome.wi.mit.edu/software/util/BinHex>
- # open (BINHEX "| BinHex -t PICT -c JVWR -n 'An Example'");
- # print BINHEX $data;
- # close BINHEX;
- # # Turn it into a GIF file, using the ppm utilities
- # open (GIF, "| picttoppm | ppmtogif -transparent white");
- # print GIF $data;
- # close GIF;
- # MISCELLANEOUS NOTES
- # NOTE: For some reason the various FILL routines don't work as
- # advertised. They are simulated by a PnPat followed by a paint
- # --------------------------------------------------------------------
- # Quickdraw-like functions -- now using PICT2
- # --------------------------------------------------------------------
- {
- package qd;
- # Directory to look in to find font metric definitions -- change this
- # for your installation
- $X11FONTS = '/usr/local/X11R5/X11/fonts/bdf';
- # Apple quickdraw constants
- $TIMES = 20;
- $HELVETICA = 21;
- $COURIER = 22;
- $SYMBOL = 23;
- $NEWCENTURYSCHOOLBK = 34;
- $PLAIN = 0;
- $BOLD = 1;
- $ITALIC = 2;
- $UNDERLINE = 4;
- # Some minimal patterns -- define your own if you like
- $GRAY = pack ('n4',0xAA55,0xAA55,0xAA55,0xAA55);
- $DKGRAY = pack ('n4',0xDD77,0xDD77,0xDD77,0xDD77);
- $LTGRAY = pack ('n4',0x8822,0x8822,0x8822,0x8822);
- $WHITE = pack('n4',0x0000,0x0000,0x0000,0x0000);
- $BLACK = pack ('n4',0xFFFF,0xFFFF,0xFFFF,0xFFFF);
- # absolute colors to be used with FgColor/BgColor
- # (for better control, use RGBFgColor/RGBBgColor)
- $BLACKCOLOR = 33;
- $WHITECOLOR = 30;
- $REDCOLOR = 209;
- $GREENCOLOR = 329;
- $BLUECOLOR = 389;
- $CYANCOLOR = 269;
- $MAGENTACOLOR = 149;
- $YELLOWCOLOR = 89;
- # This defines the header used at the beginning of PICT files:
- $PICTHEADER = "