1 /* $XConsortium: do_trns.c,v 1.4 94/04/17 20:17:43 gildea Exp $ */
5 Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
6 You are hereby granted permission under all Bitstream propriety rights to
7 use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
8 software and the Bitstream Charter outline font for any purpose and without
9 restrictions; provided, that this notice is left intact on all copies of such
10 software or font and that Bitstream's trademark is acknowledged as shown below
11 on all unmodified copies of such font.
13 BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
16 BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
17 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
19 DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
20 INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
21 WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
25 /**************************** D O _ T R N S . C ******************************
27 * This module is responsible for executing all intelligent transformation *
28 * for bounding box and outline data *
30 ****************************************************************************/
33 #include "spdo_prv.h" /* General definitions for Speedo */
39 #define SHOW(X) printf("X = %d\n", X)
44 /***** GLOBAL VARIABLES *****/
46 /***** GLOBAL FUNCTIONS *****/
48 /***** EXTERNAL VARIABLES *****/
50 /***** EXTERNAL FUNCTIONS *****/
52 /***** STATIC VARIABLES *****/
54 /***** STATIC FUNCTIONS *****/
57 static void sp_split_curve(PROTO_DECL2 point_t P1,point_t P2,point_t P3,fix15 depth);
58 static ufix8 FONTFAR *sp_get_args(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format,point_t STACKFAR *pP);
60 static void sp_split_curve(); /* Split Bezier curve into vectors */
61 static ufix8 FONTFAR *sp_get_args(); /* Read X Y argument pair */
65 FUNCTION ufix8 FONTFAR *read_bbox(pointer, pPmin, pPmax, set_flag)
67 ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
68 point_t STACKFAR *pPmin; /* Lower left corner of bounding box */
69 point_t STACKFAR *pPmax; /* Upper right corner of bounding box */
70 boolean set_flag; /* flag to indicate whether global oru bbox should be saved */
72 * Called by make_simp_char() and make_comp_char() to read the
73 * bounding box data from the font.
74 * Sets Pmin and Pmax to the bottom left and top right corners
75 * of the bounding box after transformation into device space.
76 * The units of Pmin and Pmax are sub-pixels.
77 * Updates *ppointer to point to the byte following the
87 sp_globals.y_int = sp_globals.Y_int_org;
88 sp_globals.x_orus = sp_globals.y_orus = 0;
89 format1 = NEXT_BYTE(pointer);
90 pointer = sp_get_args(pointer, format1, pPmin);
91 #if INCL_SQUEEZING || INCL_ISW
94 sp_globals.bbox_xmin_orus = sp_globals.x_orus;
95 sp_globals.bbox_ymin_orus = sp_globals.y_orus;
99 for (i = 1; i < 4; i++)
104 if (format1 & BIT6) /* Xmax requires X int zone 1? */
106 format = (format1 >> 4) | 0x0c;
110 if (format1 & BIT7) /* Ymax requires Y int zone 1? */
112 format = NEXT_BYTE(pointer);
116 sp_globals.x_int = 0;
124 pointer = sp_get_args(pointer, format, &P);
125 #if INCL_SQUEEZING || INCL_ISW
126 if (set_flag && (i==2))
128 sp_globals.bbox_xmax_orus = sp_globals.x_orus;
129 sp_globals.bbox_ymax_orus = sp_globals.y_orus;
132 if ((i == 2) || (!sp_globals.normal))
146 printf("BBOX %6.1f(Xint 0), %6.1f(Yint 0), %6.1f(Xint %d), %6.1f(Yint %d)\n",
147 (real)pPmin->x / (real)sp_globals.onepix,
148 (real)pPmin->y / (real)sp_globals.onepix,
149 (real)pPmax->x / (real)sp_globals.onepix,
150 (format1 >> 6) & 0x01,
151 (real)pPmax->y / (real)sp_globals.onepix,
152 (format1 >> 7) & 0x01);
158 FUNCTION void proc_outl_data(pointer)
160 ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
162 * Called by make_simp_char() and make_comp_char() to read the
163 * outline data from the font.
164 * The outline data is parsed, transformed into device coordinates
165 * and passed to an output module for further processing.
166 * Note that pointer is not updated to facilitate repeated
167 * processing of the outline data when banding mode is in effect.
170 ufix8 format1, format2;
171 point_t P0, P1, P2, P3;
175 sp_globals.x_int = 0;
176 sp_globals.y_int = sp_globals.Y_int_org;
177 #if INCL_PLAID_OUT /* Plaid data monitoring included? */
178 record_xint((fix15)sp_globals.x_int); /* Record xint data */
179 record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
182 sp_globals.x_orus = sp_globals.y_orus = 0;
186 format1 = NEXT_BYTE(pointer);
190 pointer = sp_get_args(pointer, format1, &P1);
192 printf("LINE %6.1f, %6.1f\n",
193 (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix);
199 case 1: /* Short XINT */
200 sp_globals.x_int = format1 & 0x0f;
202 printf("XINT %d\n", sp_globals.x_int);
204 #if INCL_PLAID_OUT /* Plaid data monitoring included? */
205 record_xint((fix15)sp_globals.x_int); /* Record xint data */
209 case 2: /* Short YINT */
210 sp_globals.y_int = sp_globals.Y_int_org + (format1 & 0x0f);
212 printf("YINT %d\n", sp_globals.y_int - sp_globals.Y_int_org);
214 #if INCL_PLAID_OUT /* Plaid data monitoring included? */
215 record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
219 case 3: /* Miscellaneous */
220 switch(format1 & 0x0f)
229 case 1: /* Long XINT */
230 sp_globals.x_int = NEXT_BYTE(pointer);
232 printf("XINT %d\n", sp_globals.x_int);
234 #if INCL_PLAID_OUT /* Plaid data monitoring included? */
235 record_xint((fix15)sp_globals.x_int); /* Record xint data */
239 case 2: /* Long YINT */
240 sp_globals.y_int = sp_globals.Y_int_org + NEXT_BYTE(pointer);
242 printf("YINT %d\n", sp_globals.y_int - sp_globals.Y_int_org);
244 #if INCL_PLAID_OUT /* Plaid data monitoring included? */
245 record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
249 default: /* Not used */
253 case 4: /* MOVE Inside */
254 case 5: /* MOVE Outside */
260 pointer = sp_get_args(pointer, format1, &P0);
263 printf("MOVE %6.1f, %6.1f\n",
264 (real)sp_globals.P0.x / (real)sp_globals.onepix, (real)sp_globals.P0.y / (real)sp_globals.onepix);
266 fn_begin_contour(sp_globals.P0, (boolean)(format1 & BIT4));
269 case 6: /* Undefined */
271 printf("*** Undefined instruction (Hex %4x)\n", format1);
275 case 7: /* Undefined */
277 printf("*** Undefined instruction (Hex %4x)\n", format1);
282 format2 = NEXT_BYTE(pointer);
283 pointer = sp_get_args(pointer, format1, &P1);
284 pointer = sp_get_args(pointer, format2, &P2);
285 pointer = sp_get_args(pointer, (ufix8)(format2 >> 4), &P3);
286 depth = (format1 >> 4) & 0x07;
288 printf("CRVE %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %d\n",
289 (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
290 (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
291 (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix,
294 depth += sp_globals.depth_adj;
295 if (sp_globals.curves_out)
297 fn_curve(P1, P2, P3, depth);
307 sp_split_curve(P1, P2, P3, depth);
313 FUNCTION static void sp_split_curve(P1, P2, P3, depth)
315 point_t P1; /* First control point of Bezier curve */
316 point_t P2; /* Second control point of Bezier curve */
317 point_t P3; /* End point of Bezier curve */
318 fix15 depth; /* Levels of recursive subdivision required */
320 * Called by proc_outl_data() to subdivide Bezier curves into an
321 * appropriate number of vectors, whenever curves are not enabled
322 * for output to the currently selected output module.
323 * sp_split_curve() calls itself recursively to the depth specified
324 * at which point it calls line() to deliver each vector resulting
325 * from the spliting process.
328 fix31 X0 = (fix31)sp_globals.P0.x;
329 fix31 Y0 = (fix31)sp_globals.P0.y;
330 fix31 X1 = (fix31)P1.x;
331 fix31 Y1 = (fix31)P1.y;
332 fix31 X2 = (fix31)P2.x;
333 fix31 Y2 = (fix31)P2.y;
334 fix31 X3 = (fix31)P3.x;
335 fix31 Y3 = (fix31)P3.y;
341 printf("CRVE(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f)\n",
342 (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
343 (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
344 (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix);
348 Pmid.x = (X0 + (X1 + X2) * 3 + X3 + 4) >> 3;
349 Pmid.y = (Y0 + (Y1 + Y2) * 3 + Y3 + 4) >> 3;
353 sp_globals.P0 = Pmid;
359 Pctrl1.x = (X0 + X1 + 1) >> 1;
360 Pctrl1.y = (Y0 + Y1 + 1) >> 1;
361 Pctrl2.x = (X0 + (X1 << 1) + X2 + 2) >> 2;
362 Pctrl2.y = (Y0 + (Y1 << 1) + Y2 + 2) >> 2;
363 sp_split_curve(Pctrl1, Pctrl2, Pmid, depth);
364 Pctrl1.x = (X1 + (X2 << 1) + X3 + 2) >> 2;
365 Pctrl1.y = (Y1 + (Y2 << 1) + Y3 + 2) >> 2;
366 Pctrl2.x = (X2 + X3 + 1) >> 1;
367 Pctrl2.y = (Y2 + Y3 + 1) >> 1;
368 sp_split_curve(Pctrl1, Pctrl2, P3, depth);
372 FUNCTION static ufix8 FONTFAR *sp_get_args(pointer, format, pP)
374 ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
375 ufix8 format; /* Format specifiaction of argument pair */
376 point_t STACKFAR *pP; /* Resulting transformed point */
378 * Called by read_bbox() and proc_outl_data() to read an X Y argument
379 * pair from the font.
380 * The format is specified as follows:
381 * Bits 0-1: Type of X argument.
382 * Bits 2-3: Type of Y argument.
383 * where the 4 possible argument types are:
384 * Type 0: Controlled coordinate represented by one byte
385 * index into the X or Y controlled coordinate table.
386 * Type 1: Interpolated coordinate represented by a two-byte
388 * Type 2: Interpolated coordinate represented by a one-byte
389 * signed increment/decrement relative to the
390 * proceding X or Y coordinate.
391 * Type 3: Repeat of preceding X or Y argument value and type.
392 * The units of P are sub-pixels.
393 * Updates *ppointer to point to the byte following the
399 /* Read X argument */
400 switch(format & 0x03)
402 case 0: /* Index to controlled oru */
403 edge = NEXT_BYTE(pointer);
404 sp_globals.x_orus = sp_plaid.orus[edge];
406 sp_globals.x_pix = sp_plaid.pix[edge];
410 case 1: /* 2 byte interpolated oru value */
411 sp_globals.x_orus = NEXT_WORD(pointer);
414 case 2: /* 1 byte signed oru increment */
415 sp_globals.x_orus += (fix15)((fix7)NEXT_BYTE(pointer));
418 sp_globals.x_pix = TRANS(sp_globals.x_orus, sp_plaid.mult[sp_globals.x_int], sp_plaid.offset[sp_globals.x_int], sp_globals.mpshift);
422 default: /* No change in X value */
426 /* Read Y argument */
427 switch((format >> 2) & 0x03)
429 case 0: /* Index to controlled oru */
430 edge = sp_globals.Y_edge_org + NEXT_BYTE(pointer);
431 sp_globals.y_orus = sp_plaid.orus[edge];
433 sp_globals.y_pix = sp_plaid.pix[edge];
437 case 1: /* 2 byte interpolated oru value */
438 sp_globals.y_orus = NEXT_WORD(pointer);
441 case 2: /* 1 byte signed oru increment */
442 sp_globals.y_orus += (fix15)((fix7)NEXT_BYTE(pointer));
445 sp_globals.y_pix = TRANS(sp_globals.y_orus, sp_plaid.mult[sp_globals.y_int], sp_plaid.offset[sp_globals.y_int], sp_globals.mpshift);
449 default: /* No change in X value */
454 switch(sp_globals.tcb.xmode)
456 case 0: /* X mode 0 */
457 pP->x = sp_globals.x_pix;
460 case 1: /* X mode 1 */
461 pP->x = -sp_globals.x_pix;
464 case 2: /* X mode 2 */
465 pP->x = sp_globals.y_pix;
468 case 3: /* X mode 3 */
469 pP->x = -sp_globals.y_pix;
472 default: /* X mode 4 */
474 pP->x = (MULT16(sp_globals.x_orus, sp_globals.tcb.xxmult) +
475 MULT16(sp_globals.y_orus, sp_globals.tcb.xymult) +
476 sp_globals.tcb.xoffset) >> sp_globals.mpshift;
481 switch(sp_globals.tcb.ymode)
483 case 0: /* Y mode 0 */
484 pP->y = sp_globals.y_pix;
487 case 1: /* Y mode 1 */
488 pP->y = -sp_globals.y_pix;
491 case 2: /* Y mode 2 */
492 pP->y = sp_globals.x_pix;
495 case 3: /* Y mode 3 */
496 pP->y = -sp_globals.x_pix;
499 default: /* Y mode 4 */
501 pP->y = (MULT16(sp_globals.x_orus, sp_globals.tcb.yxmult) +
502 MULT16(sp_globals.y_orus, sp_globals.tcb.yymult) +
503 sp_globals.tcb.yoffset) >> sp_globals.mpshift;