ML-PostScript
A PostScript engine for OCaml

This library is obsolete. Do not use it. Use Cairo instead.

This is a library to produce PostScript documents using the OCaml. It is distributed under the terms of the GNU Lesser General Public Licence. You can download it here: postscript.ml.

Types

type orientation = [ `Portrait | `Landscape ]

Orientations for the page.

type alignment = [ `Left | `Right | `Center ]

Text alignment

type end_point = [ `Square | `Round | `Projected ]

End point style for lines. With `Square, lines are ended with with a straight stop; with `Round they are ended with a circle; and with `Projected, they are ended bu a square.

type line_join = [ `Square | `Round | `Bevel ]

Join style for lines. With Square, they make an angle; with Round, they are joint by a curve line; and with Bevel, they are joint by une segment.

and color =
  [ `RGB of float * float * float
  | `HSB of float * float * float
  | `Gray of float ]

Color specification, either red/green/blue, hue/saturation/brightness or gray level. All values are between 0.0 and 1.0 except hue, which is between 0.0 and 360.0.

type fill_type = [ `None | `Current | `Color of color ]

Fill styles for closed figures.

type document_state = Pre_init | Post_exit | Dumb | Prolog | Page

Possible states for the PostScript structure generator. You don't need to use that!

type structure_severity = [ `Fatal | `Verbose | `Quiet ]

Severity level in case of structural error. `Fatal raises an exception, `Verbose prints a warning on stderr and `Quiet does nothing.

type font = { ft_name: string }

The (opaque) structure returned by font creation methods.


Matrix module

module Matrix :
  sig

This module handles affine transformations.

type t = (float * float) * (float * float) * (float * float)
val id : t

The identity transform.

val translation : float -> float -> t
translation x y

The translation of vector (x, y).

val rotation : ?center:float * float -> float -> t
rotation center:(x, y) angle

The rotation of center (x, y) and angle angle. The center defaults to (0, 0).

val homotetie : ?center:float * float -> float -> t
homotetie center:(x, y) ratio

The homotetie of center (x, y) and ratio ratio. The center defaults to (0, 0).

val shear_x : float -> t

The shearing along the x axis:

 ______       _______
|      |     /      /
|______| -> /______/
val shear_y : float -> t

The shearing along the y axis.

val apply : t -> float * float -> float * float
apply matrix vector

Calculates the image of vector by matrix.

val compose : t -> t -> t
compose matr1 matr2

Returns the composed matrix matr1 o matr2.

val dump : t -> string

Dumps a matrix in PostScript syntax.

val dump_up : t -> string

Dumps a matrix in PostScript syntax, using the NICOMP function to take care of vertical inversion. Useful when handling font transforms.


Useful functions

val may : ('a -> 'b) -> 'b -> 'a option -> 'b
may function default option

An useful function to handle option values: if option is None, default is returned, and if it is Some x, function x is evalued.

val split : string -> string list

Splits a string into words.

val ascii85encode : char Stream.t -> (char -> unit) -> unit
ascii85encode input_stream output_function

Encodes input_stream in ASCII-85, and output it using output_function.

val uniq_name : string -> unit -> string
let u = uniq_name "prefix"
u (); u ()

Makes functions that generates uniques names starting with prefix.

val state_name : document_state -> string

Converts document_state value in a readable form.

val latin1_encoding : string list

The names of the gliphs in the iso-8859-1 (latin-1) encoding.

val default_charset : string * string list
("latin1", latin1_encoding)

The default charset of the PostScript engine, latin-1.

val procset : string

The procedures set used by the engine.

val quote_string : string -> string

Quotes a string using the convention: characters (, ) and \ are prefixed with a \.


Font_metrics module

module Font_metrics :
  sig

This module enables to parse .afm font metrics files. It is very simple.

type character = {
  name : string;
  wx : int;
  xmin : int;
  ymin : int;
  xmax : int;
  ymax : int;
}

Information of a character in a font. wx is the horizontal offset.

type t = { chars : character array; } 

Metric information about a font.

val read : ?encoding:string list -> string -> t

Read and parse the given .afm font metrics. Very strict about the format.

val string : t -> ?size:float -> string -> float * float * float
let (width, max, min) = string font_metrics "string"

Computes the extents of the given string, max and min define the vertical extents, relative to the current point.


The PostScript object

class postscript :
  ?end_fun:(unit -> unit) ->
  out_channel ->
  object
let engine = new postscript end_fun:function output

The PostScript engine object. I use an object because it's possible t want to output several PostScripts at the same time, and because there are side effects. output is the output stream for the PostScript. end_fun will be called when the object is exited. It can be used to automatically close output.

Dumb documents handling

method init :
  ?unit:float ->
  ?orientation:orientation ->
  ?inverted:bool ->
  ?hmargin:float -> ?vmargin:float -> float -> float -> unit
engine#init width height

Initializes the postScript engine with a page size of width×height. unit is the unit used for all dimensions, in dots; it defaults to 1 dot. If inverted is true, the y coordinates grows downward; if it's false (the default), it grows upwads. hmargin and vmargin are respectivly the left and bottom (or tom, if inverted is true) margins; they default to 0.

method exit : unit -> unit

Flushes the PostScript engine and end the session.

method new_page : unit -> unit

Begin a new page. All drawing properties are reset.

Structured document handling

You can use this PostScript engine to produce structured documents, with page information. The resulting documents can be best viewed with softwares like GhostView (at this time, it doesn't conform strictly to Adobe's DSC, but GhostView accepts it). But If you do that, you must take care to define all used resources in the prolog, before starting the first page.

method begin_document :
  ?unit:float ->
  ?orientation:orientation ->
  ?inverted:bool ->
  ?pages:int ->
  ?hmargin:float -> ?vmargin:float -> float -> float -> unit

Initialize the PostScript engine, but with document structure information. pages is the total number of pages of the document. For the others arguments, see init.

method end_document : unit -> unit

Ends the document.

method begin_page : string -> unit
engine#begin_page label

Begin a new page, labeled with label (which is usually a number, but that's not necessary).

Drawing style

Warning: all these styles are reset when you start a new page.

method set_color : color -> unit

Sets the color.

method set_line_width : float -> unit

Sets the line width. 0 is the device thinest line.

method set_dash : black:float -> white:float -> unit

Sets the lines to be dashed. black is the length of drawn segments, white is the length of not drawn segments.

method set_dash_full : ofs:float -> len:float list -> unit

Sets the lines to be dashed, in a richer form. ofs is the space before the first dash, len is the length of the dashes.

method set_no_dash : unit -> unit

Sets the lines to be plain.

method set_line_cap : end_point -> unit

Sets the line cap. See the end_point type for more.

method set_line_join : line_join -> unit

Sets the line join. See the line_join type for more.

Drawing primitives

method line : float -> float -> float -> float -> unit
engine#line x1 y1 x2 y2

Draws a line from (x1, y1) to (x2, y2).

method lines : (float * float) list -> unit

Draws lines between the points whose coordinates are given.

method rectangle :
  ?fill:fill_type -> float -> float -> w:float -> h:float -> unit
engine#rectangle x y w:width h:height

Draws a rectangle with the lower-left (I supose you don't use an inverted coordinates system) corner at (x, y) whose size is width×height. The rectangle can be filled. See the fill_typetype for more information. I won't speak again of filling.

method circle : ?fill:fill_type -> float -> float -> rad:float -> unit
engine#circle x y radius

Draws a circle. Ellipses are currently unsupported. Sorry.

method polygon : ?fill:fill_type -> (float * float) list -> unit

Draws a polygon. The difference with lines is that the polygon is closed and can be filled.

method arc : float -> float -> rad:float -> a1:float -> a2:float -> unit
engine#arc x y rad:radius a1:start_angle a2:end_angle

Draws a circle arc. Anlges are given in degrees, starting along the x axis.

method angle :
  ?fill:fill_type ->
  float -> float -> rad:float -> a1:float -> a2:float -> unit

Draws a circle angle. Unlike arc, this function draws the radius. As it's a closed path, you can fill it.

method curve :
  s:float * float ->
  e:float * float -> ts:float * float -> te:float * float -> unit

Draws a Béziers curve between from with tangent vector tfrom to to with tangent vector tto.

method curves : ((float * float) * (float * float)) list -> unit

Like lines but for Béziers curves.

method poly_curve :
  ?fill:fill_type -> ((float * float) * (float * float)) list -> unit

Like polygon but for Béziers curves.

Text and fonts

method create_font :
  ?charset:string * string list -> string -> float -> font
let font = engine#create_font font_name size

Create a new font.

method create_font_matrix :
  ?charset:string * string list -> string -> Matrix.t -> font
let font = engine#create_font_matrix font_name matrix

Create a new font, using a transform matrix instead of a sinple size. create_font is equivalent to create_font_matrix with matrix equals to Matrix.homotetie size.

method print : ?align:alignment -> float -> float -> str:string -> unit
engine#print x y string

Prints a string, using the current font.

method set_font : font -> unit

Sets the current font.

method add_charset : string -> string list -> unit

Defines a new character encoding. I think you don't want to use that, consider it's private.

method recode_font : ?charset:string * string list -> string -> string

Changes the character encoding of a font.

Coordinates systems

method clip : ?reset:bool -> float -> float -> w:float -> h:float -> unit
engine#clip x y w:width h:height

Sets the clipping rectangle. If reset is false, it's intersected with the previous; reset defaults to true.

method change_coordinates : ?definitive:bool -> Matrix.t -> unit

Change the coordinates system, acording to the given matrix. If definitive is true, the old coordinates system can't be restored (but it's always reset on a new page); it defaults to false.

method restore_coordinates : unit -> unit

Restores the previous coordinates system.

Bitmap images

method private image_matrix :
  float -> float -> float -> float -> int -> int -> unit

Outputs the transform matrix, given the image size, position and resolution.

method color_image_from_function :
  size:float * float ->
  pos:float * float ->
  res:int * int -> f:(int -> int -> int * int * int) -> unit

Plots a color bitmap image. pos is coordinates of the lower-left corner of the image. size is the size of the resulting image. res is the number of pixel in each direction. fun is a function that takes the coordinates of the pixel and returns the color (in three RGB 0-255 integers).

method color_image_from_strings :
  size:float * float ->
  pos:float * float -> res:int * int -> data:string array -> unit

Plots a color bitmap image. Here, the bitmap data is held by a string array: one string per row, three characters per pixel.

method gray_image_from_function :
  size:float * float ->
  pos:float * float -> res:int * int -> f:(int -> int -> int) -> unit

Exactly like above, but for gray-level images.

method gray_image_from_strings :
  size:float * float ->
  pos:float * float -> res:int * int -> data:string array -> unit

Exactly like above, but for gray-level images.

method color_image :
  float ->
  float -> float -> float -> int -> int -> (unit -> unit) -> unit

The low-level function to plot a color color image.

method gray_image :
  float ->
  float -> float -> float -> int -> int -> (unit -> unit) -> unit

The low-level function to plot a gray gray image.

JPEG bitmap images

These two functions enables to include JPEG bitmaps in the document in a quite compact form.

method jpeg_image :
  ?color:bool ->
  size:float * float ->
  pos:float * float -> res:int * int -> char Stream.t -> unit

Draws a JPEG bitmap given as a char stream. You have to provide yourself the information on the resolution of the JPEG and wether it is a color or grayscale image. If the y coordinates grows upwards, the image will be vertically inverted, unless you give a nigative vertical size.

method jpeg_image_from_file :
  ?color:bool ->
  size:float * float ->
  pos:float * float -> res:int * int -> string -> unit

As above, but reads in a file.

Low level drawing primitives

These functions enables to do more things, but are a bit more difficile to use. Maybe you should have a look at the PostScript internal system.

method ll_newpath : unit -> unit

Begins a new path.

method ll_moveto : ?relative:bool -> float -> float -> unit

Moves the current point.

method ll_lineto : ?relative:bool -> float -> float -> unit

Appends a line between the current point and the given point to the current path.

method ll_arc :
  ?clockwise:bool -> float * float -> float -> float -> float -> unit
engine#ll_arc (x, y) radius start_angle end_angle

Appends an arc to the current path.

method ll_curveto :
  ?relative:bool ->
  float * float -> float * float -> float * float -> unit
engine#curveto first_handle second_handle end_point

Appends a Béziers curve to the current path. Warning: the handle points are not vectors.

method ll_stroke : unit -> unit

Draws the current path.

method ll_clip : unit -> unit

Sets the interior of the current path to be the clipping area.

method ll_closepath : unit -> unit

Closes the current path with a straight line.

method ll_reversepath : unit -> unit

Reverses the current path.

method ll_strokepath : unit -> unit

Replaces the current path by its outline.

Hacking functions

method set_severity : structure_severity -> unit

Sets the severity level of the engine, about mistakes in the document structure.

method dirty_write : string -> unit

Write string directly to the PostScript file.


val new_postscript_to_file : string -> postscript

Creates a new PostScript engine, outputing to a file, and automaticaly closing the channel.


[http://www.eleves.ens.fr:8080/home/george/info/prg/postscript.html] [nicolas.george@ens.fr] [plan du site]

Mise à jour: 14 décembre 2000
© Nicolas GEORGE - Les copies totales ou partielles de cette page sont autorisées à condition de ne pas en dénaturer le sens et d'indiquer la source