[cairo] text widget to postscript output.

Carl Worth cworth at cworth.org
Thu Oct 20 09:05:57 PDT 2005


On Thu, 20 Oct 2005 11:04:47 +0000 (UTC), V.Krishnakumar wrote:
> I'm trying to print from a text widget through the postscript backend. I have
> trouble getting the conversion from pixels to points right. Are there examples
> of postscript printing from cairo ?

1 point is 1/72.0 inch, while the size of a pixel depends on the size
and resolution of your display, (and the actual size of the pixel
probably doesn't matter much at all here). What is much more
significant to the conversion you need is the real-world size you
actually want your PostScript output to be.

Let's assume you want your PostScript output to have an actual size in
millimeters of:

	WIDTH_IN_MM x HEIGHT_IN_MM

To construct a correctly-sized PostScript surface, all you need to do
is convert the millimeters to points:

	#define INCHES_PER_MM   (1.0/25.4)
	#define POINTS_PER_INCH 72.0
	
	double width_in_points, height_in_points;
	width_in_points  =  WIDTH_IN_MM * INCHES_PER_MM * POINTS_PER_INCH;
	height_in_points = HEIGHT_IN_MM * INCHES_PER_MM * POINTS_PER_INCH;
	
	surface = cairo_ps_surface_create (filename,
					   width_in_points, height_in_points);

Now, you're almost ready to call your existing drawing code. In fact,
if your drawing code adapts automatically to a provided size, then you
can just call it with the size you've computed:

	cr = cairo_create (surface);

	call_drawing_code (cr, width_in_points, height_in_points);

If, however, your drawing code is making assumptions about the surface
size then you will need to scale user space to match those
assumptions. Let's assume the drawing code assumes a surface size of:

	WIDTH_IN_USER_SPACE_UNITS x HEIGHT_IN_USER_SPACE_UNITS.

(It might be easier to think of this as a size in "pixels" but calling
it a size in "user-space units" is much more accurate.)

Scaling user space to match is actually quite simple:

	cairo_scale (cr, width_in_points / WIDTH_IN_USER_SPACE_UNITS,
			 height_in_points / HEIGHT_IN_USER_SPACE_UNITS);

	call_drawing_code (cr);

Note: I've assumed here that the ratio of the width/height in
user-space units is equal to the width/height in points of the
PostScript surface size. If that's not the case, then the code above
will distort the aspect ratio of the result. To avoid this, you could
do consistent scaling based on the smaller scale factor from one
dimension and perhaps also re-center in the other dimension:

	double scale, tx, ty;

	scale = MIN (width_in_points / WIDTH_IN_USER_SPACE_UNITS,
		     height_in_points / HEIGHT_IN_USER_SPACE_UNITS);

	tx = (width_in_points - scale * WIDTH_IN_USER_SPACE_UNITS) / 2.0;
	ty = (height_in_points - scale * HEIGHT_IN_USER_SPACE_UNITS) / 2.0;

	cairo_translate (cr, tx, ty);
	cairo_scale (cr, scale, scale);

	call_drawing_code (cr);

Note: When targeting display devices using conversions such as the
above, it's often helpful to force the scale, tx, and ty values to be
integers so that pixel-alignment properties are maintained.

Phew! That's a longer answer than I thought it would be, but I hope
something in there is useful for you.

-Carl

PS. I've typed the code only into this email, and not tested any of
it. So there are likely syntax and logic errors in there. Do let me
know if you get stuck trying to fix any of those. :-}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20051020/734fbb2d/attachment.pgp


More information about the cairo mailing list