summaryrefslogtreecommitdiff
path: root/src/Speedo
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:40 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:40 +0000
commit153e8da44452905ae04a0e20ad0d85f40399b4ca (patch)
treeb4e614de58d4b596dab3dcc7fd4054ec96db592a /src/Speedo
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'src/Speedo')
-rw-r--r--src/Speedo/adobe-iso.h200
-rw-r--r--src/Speedo/bics-iso.h223
-rw-r--r--src/Speedo/do_char.c1022
-rw-r--r--src/Speedo/do_trns.c513
-rw-r--r--src/Speedo/keys.h56
-rw-r--r--src/Speedo/out_bl2d.c776
-rw-r--r--src/Speedo/out_blk.c708
-rw-r--r--src/Speedo/out_outl.c287
-rw-r--r--src/Speedo/out_scrn.c1091
-rw-r--r--src/Speedo/out_util.c337
-rw-r--r--src/Speedo/reset.c127
-rw-r--r--src/Speedo/set_spcs.c769
-rw-r--r--src/Speedo/set_trns.c1329
-rw-r--r--src/Speedo/spdo_prv.h425
-rw-r--r--src/Speedo/speedo.h1081
-rw-r--r--src/Speedo/spencode.c62
-rw-r--r--src/Speedo/sperr.c134
-rw-r--r--src/Speedo/spfile.c349
-rw-r--r--src/Speedo/spfont.c450
-rw-r--r--src/Speedo/spfuncs.c161
-rw-r--r--src/Speedo/spglyph.c403
-rw-r--r--src/Speedo/spinfo.c441
-rw-r--r--src/Speedo/spint.h172
-rw-r--r--src/Speedo/useropt.h41
24 files changed, 11157 insertions, 0 deletions
diff --git a/src/Speedo/adobe-iso.h b/src/Speedo/adobe-iso.h
new file mode 100644
index 0000000..e1eeef1
--- /dev/null
+++ b/src/Speedo/adobe-iso.h
@@ -0,0 +1,200 @@
+/* $Xorg: adobe-iso.h,v 1.3 2000/08/17 19:46:24 cpqbld Exp $ */
+
+/*
+ * Latin 1 format from masterset format 11 (ps)
+ * 0 implies no valid mapping
+ */
+
+int adobe_map[] = {
+ 32, 32,
+ 33, 33,
+ 34, 34,
+ 35, 35,
+ 36, 36,
+ 37, 37,
+ 38, 38,
+ 39, 169,
+ 40, 40,
+ 41, 41,
+ 42, 42,
+ 43, 43,
+ 44, 44,
+ 45, 45,
+ 46, 46,
+ 47, 47,
+ 48, 48,
+ 49, 49,
+ 50, 50,
+ 51, 51,
+ 52, 52,
+ 53, 53,
+ 54, 54,
+ 55, 55,
+ 56, 56,
+ 57, 57,
+ 58, 58,
+ 59, 59,
+ 60, 60,
+ 61, 61,
+ 62, 62,
+ 63, 63,
+ 64, 64,
+ 65, 65,
+ 66, 66,
+ 67, 67,
+ 68, 68,
+ 69, 69,
+ 70, 70,
+ 71, 71,
+ 72, 72,
+ 73, 73,
+ 74, 74,
+ 75, 75,
+ 76, 76,
+ 77, 77,
+ 78, 78,
+ 79, 79,
+ 80, 80,
+ 81, 81,
+ 82, 82,
+ 83, 83,
+ 84, 84,
+ 85, 85,
+ 86, 86,
+ 87, 87,
+ 88, 88,
+ 89, 89,
+ 90, 90,
+ 91, 91,
+ 92, 92,
+ 93, 93,
+ 94, 195,
+ 95, 95,
+ 96, 193,
+ 97, 97,
+ 98, 98,
+ 99, 99,
+ 100, 100,
+ 101, 101,
+ 102, 102,
+ 103, 103,
+ 104, 104,
+ 105, 105,
+ 106, 106,
+ 107, 107,
+ 108, 108,
+ 109, 109,
+ 110, 110,
+ 111, 111,
+ 112, 112,
+ 113, 113,
+ 114, 114,
+ 115, 115,
+ 116, 116,
+ 117, 117,
+ 118, 118,
+ 119, 119,
+ 120, 120,
+ 121, 121,
+ 122, 122,
+ 123, 123,
+ 124, 124,
+ 125, 125,
+ 126, 196, /* lc tilde */
+ 127, 0, /* */
+ 161, 161, /* invert exclamation */
+ 162, 162, /* cent */
+ 163, 163, /* pound sterling */
+ 164, 168, /* intl currency */
+ 165, 165, /* yen */
+ 166, 320, /* split vert bar */
+ 167, 167, /* section mark */
+ 168, 200, /* dierisis */
+ 169, 0, /* superior copyright */
+ 170, 0, /* feminine ordinal */
+ 171, 171, /* dbl left guillemot */
+ 172, 314, /* math not */
+ 173, 0, /* hyphen ? */
+ 174, 0, /* superior registered */
+ 175, 0, /* overscore */
+ 176, 321, /* degree */
+ 177, 329, /* math +- */
+ 178, 333, /* superior 2 */
+ 179, 332, /* superior 3 */
+ 180, 194, /* lc acute */
+ 181, 324, /* greek lc mu */
+ 182, 182, /* Paragraph */
+ 183, 180, /* center dot */
+ 184, 203, /* cedilla lc */
+ 185, 328, /* superior 1 */
+ 186, 0, /* masculine ordinal(using superior o) */
+ 187, 187, /* right dbl guillemot */
+ 188, 327, /* 1/4 */
+ 189, 326, /* 1/2 */
+ 190, 331, /* 3/4 */
+ 191, 191, /* invert question */
+ 192, 259, /* A grave */
+ 193, 256, /* A acute */
+ 194, 257, /* A circumflex */
+ 195, 261, /* A tilde */
+ 196, 258, /* A dierisis */
+ 197, 260, /* A angstrom */
+ 198, 225, /* AE ligature */
+ 199, 262, /* C cedilla */
+ 200, 266, /* E grave */
+ 201, 263, /* E acute */
+ 202, 264, /* E circumflex */
+ 203, 265, /* E dierisis */
+ 204, 270, /* I grave */
+ 205, 267, /* I acute */
+ 206, 268, /* I circumflex */
+ 207, 269, /* I dierisis */
+ 208, 317, /* D bar */
+ 209, 271, /* N tilde */
+ 210, 275, /* O grave */
+ 211, 272, /* O acute */
+ 212, 273, /* O circumflex */
+ 213, 276, /* O tilde */
+ 214, 274, /* O dierisis */
+ 215, 325, /* math multiply */
+ 216, 233, /* O bar */
+ 217, 281, /* U grave */
+ 218, 278, /* U acute */
+ 219, 279, /* U circumflex */
+ 220, 280, /* U dierisis */
+ 221, 319, /* Y acute */
+ 222, 318, /* icelandic thorn lc */
+ 223, 251, /* German dbl s */
+ 224, 287, /* a grave */
+ 225, 284, /* a acute */
+ 226, 285, /* a circumflex */
+ 227, 289, /* a tilde */
+ 228, 286, /* a dierisis */
+ 229, 288, /* a angstrom */
+ 230, 241, /* ae ligature */
+ 231, 290, /* c cedilla */
+ 232, 294, /* e grave */
+ 233, 291, /* e acute */
+ 234, 292, /* e circumflex */
+ 235, 293, /* e dierisis */
+ 236, 298, /* i grave */
+ 237, 295, /* i acute */
+ 238, 296, /* i circumflex */
+ 239, 297, /* i dierisis */
+ 240, 323, /* icelandic eth lc */
+ 241, 299, /* n tilde */
+ 242, 303, /* o grave */
+ 243, 300, /* o acute */
+ 244, 301, /* o circumflex */
+ 245, 304, /* o tilde */
+ 246, 302, /* o dierisis */
+ 247, 322, /* math divide */
+ 248, 249, /* o bar */
+ 249, 309, /* u grave */
+ 250, 306, /* u acute */
+ 251, 307, /* u circumflex */
+ 252, 308, /* u dierisis */
+ 253, 334, /* y acute */
+ 254, 330, /* icelandic thorn uc */
+ 255, 310, /* y dierisis */
+};
diff --git a/src/Speedo/bics-iso.h b/src/Speedo/bics-iso.h
new file mode 100644
index 0000000..f520562
--- /dev/null
+++ b/src/Speedo/bics-iso.h
@@ -0,0 +1,223 @@
+/* $Xorg: bics-iso.h,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+int sp_bics_map[] = {
+ 32, 0,
+ 33, 1,
+ 34, 2,
+ 35, 3,
+ 36, 4,
+ 37, 5,
+ 38, 6,
+ 39, 264,
+ 40, 8,
+ 41, 9,
+ 42, 10,
+ 43, 11,
+ 44, 12,
+ 45, 13,
+ 46, 14,
+ 47, 15,
+ 48, 16,
+ 49, 17,
+ 50, 18,
+ 51, 19,
+ 52, 20,
+ 53, 21,
+ 54, 22,
+ 55, 23,
+ 56, 24,
+ 57, 25,
+ 58, 26,
+ 59, 27,
+ 60, 28,
+ 61, 29,
+ 62, 30,
+ 63, 31,
+ 64, 32,
+ 65, 33,
+ 66, 34,
+ 67, 35,
+ 68, 36,
+ 69, 37,
+ 70, 38,
+ 71, 39,
+ 72, 40,
+ 73, 41,
+ 74, 42,
+ 75, 43,
+ 76, 44,
+ 77, 45,
+ 78, 46,
+ 79, 47,
+ 80, 48,
+ 81, 49,
+ 82, 50,
+ 83, 51,
+ 84, 52,
+ 85, 53,
+ 86, 54,
+ 87, 55,
+ 88, 56,
+ 89, 57,
+ 90, 58,
+ 91, 59,
+ 92, 60,
+ 93, 61,
+ 94, 133,
+ 95, 63,
+ 96, 131,
+ 97, 65,
+ 98, 66,
+ 99, 67,
+ 100, 68,
+ 101, 69,
+ 102, 70,
+ 103, 71,
+ 104, 72,
+ 105, 73,
+ 106, 74,
+ 107, 75,
+ 108, 76,
+ 109, 77,
+ 110, 78,
+ 111, 79,
+ 112, 80,
+ 113, 81,
+ 114, 82,
+ 115, 83,
+ 116, 84,
+ 117, 85,
+ 118, 86,
+ 119, 87,
+ 120, 88,
+ 121, 89,
+ 122, 90,
+ 123, 91,
+ 124, 92,
+ 125, 93,
+ 126, 137,
+ 127, 358,
+ 161, 128,
+ 162, 98,
+ 163, 97,
+ 164, 278,
+ 165, 274,
+ 166, 277,
+ 167, 110,
+ 168, 135,
+ 169, 503,
+ 170, 538,
+ 171, 125,
+ 172, 309,
+ 173, 191,
+ 174, 504,
+ 175, 230,
+ 176, 339,
+ 177, 286,
+ 178, 160,
+ 179, 161,
+ 180, 129,
+ 181, 325,
+ 182, 279,
+ 183, 102,
+ 184, 141,
+ 185, 159,
+ 186, 544,
+ 187, 126,
+ 188, 151,
+ 189, 153,
+ 190, 155,
+ 191, 127,
+ 192, 259,
+ 193, 261,
+ 194, 257,
+ 195, 253,
+ 196, 255,
+ 197, 113,
+ 198, 114,
+ 199, 148,
+ 200, 249,
+ 201, 251,
+ 202, 247,
+ 203, 245,
+ 204, 239,
+ 205, 241,
+ 206, 237,
+ 207, 235,
+ 208, 169,
+ 209, 196,
+ 210, 202,
+ 211, 200,
+ 212, 204,
+ 213, 208,
+ 214, 206,
+ 215, 284,
+ 216, 115,
+ 217, 212,
+ 218, 210,
+ 219, 214,
+ 220, 216,
+ 221, 224,
+ 222, 271,
+ 223, 121,
+ 224, 260,
+ 225, 262,
+ 226, 258,
+ 227, 254,
+ 228, 256,
+ 229, 117,
+ 230, 118,
+ 231, 149,
+ 232, 250,
+ 233, 252,
+ 234, 248,
+ 235, 246,
+ 236, 240,
+ 237, 242,
+ 238, 238,
+ 239, 236,
+ 240, 273,
+ 241, 195,
+ 242, 201,
+ 243, 199,
+ 244, 203,
+ 245, 207,
+ 246, 205,
+ 247, 285,
+ 248, 119,
+ 249, 211,
+ 250, 209,
+ 251, 213,
+ 252, 215,
+ 253, 223,
+ 254, 272,
+ 255, 221,
+};
+
diff --git a/src/Speedo/do_char.c b/src/Speedo/do_char.c
new file mode 100644
index 0000000..0ae416b
--- /dev/null
+++ b/src/Speedo/do_char.c
@@ -0,0 +1,1022 @@
+/* $Xorg: do_char.c,v 1.3 2000/08/17 19:46:24 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+/***************************** D O - C H A R . C *****************************
+ * *
+ * This is the top level module for processing one simple or composite *
+ * character.
+ * *
+ ****************************************************************************/
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static boolean sp_make_simp_char(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format);
+static boolean sp_make_comp_char(PROTO_DECL2 ufix8 FONTFAR *pointer);
+static ufix8 FONTFAR *sp_get_char_org(PROTO_DECL2 ufix16 char_index,boolean top_level);
+static fix15 sp_get_posn_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
+static fix15 sp_get_scale_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
+#else
+static boolean sp_make_simp_char(); /* Process simple character data */
+static boolean sp_make_comp_char(); /* Process compound character data */
+static ufix8 FONTFAR *sp_get_char_org(); /* Look up char in character directory */
+static fix15 sp_get_posn_arg(); /* Read Xpos Ypos args in DOCH instruction */
+static fix15 sp_get_scale_arg(); /* read Xscale Yscale args in DOCH instruction */
+#endif
+
+
+FUNCTION ufix16 get_char_id(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+/*
+ * Returns character id for specified character index in currently
+ * selected font.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 12 and returns 0 if character data not available.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return (ufix16)0; /* Return zero character id */
+ }
+
+pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return (ufix16)0; /* Return zero character id */
+ }
+
+return 0xffff & NEXT_WORD(pointer); /* Return character id */
+}
+
+
+#if INCL_METRICS
+FUNCTION fix31 get_char_width(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+/*
+ * Returns character set width for specified character index in currently
+ * selected font in units of 1/65536 em.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 12 and returns 0 if character data not available.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix31 set_width; /* Set width of character */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return (fix31)0; /* Return zero character width */
+ }
+
+pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return (fix31)0; /* Return zero character width */
+ }
+
+pointer += 2; /* Skip over character id */
+set_width = (fix31)NEXT_WORD(pointer); /* Read set width and Convert units */
+set_width = ((set_width << 16) + (sp_globals.metric_resolution >> 1)) / sp_globals.metric_resolution;
+return set_width; /* Return in 1/65536 em units */
+}
+#endif
+
+#if INCL_METRICS
+FUNCTION fix15 get_track_kern(track, point_size)
+GDECL
+fix15 track; /* Track required (0 - 3) */
+fix15 point_size; /* Point size (units of whole points) */
+/*
+ * Returns inter-character spacing adjustment in units of 1/256
+ * points for the specified kerning track and point size.
+ * If the specified point size is larger than the maximum point
+ * size for the specified track, the adjustment for the maximum
+ * point size is used.
+ * If the specified point size is smaller than the minimum point
+ * size for the specified track, the adjustment for the minimum
+ * point size is used.
+ * If the specified point size is between the minimum point size
+ * and the maximum point size for the specified track, the
+ * adjustment is interpolated linearly between the minimum and
+ * maximum adjustments.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 13 and returns 0 if track kerning data not in font.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix15 no_tracks; /* Number of kerning tracks in font */
+ufix8 format; /* Track kerning format byte */
+fix15 i; /* Track counter */
+fix15 min_pt_size; /* Minimum point size for track */
+fix15 max_pt_size; /* Maximum point size for track */
+fix15 min_adj; /* Adjustment for min point size */
+fix15 max_adj; /* Adjustment for max point size */
+fix31 delta_pt_size;/* Max point size - min point size */
+fix31 delta_adj; /* Min adjustment - max adjustment */
+fix15 adj = 0; /* Interpolated adjustment */
+
+if (track == 0) /* Track zero selected? */
+ {
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+no_tracks = sp_globals.kern.no_tracks; /* Number of kerning tracks */
+if (track > no_tracks) /* Required track not available? */
+ {
+ report_error(13); /* Report track kerning data not avail */
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+pointer = sp_globals.kern.tkorg; /* Point to start of track kern data */
+for (i = 0; i < track; i++) /* Read until track required is read */
+ {
+ format = NEXT_BYTE(pointer); /* Read track kerning format byte */
+ min_pt_size = (format & BIT0)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ min_adj = (format & BIT1)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ max_pt_size = (format & BIT2)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ max_adj = (format & BIT3)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ }
+
+if (point_size <= min_pt_size) /* Smaller than minimum point size? */
+ {
+ return min_adj; /* Return minimum adjustment (1/256 points) */
+ }
+
+if (point_size >= max_pt_size) /* Larger than maximum point size? */
+ {
+ return max_adj; /* Return maximum adjustment (1/256 points) */
+ }
+
+delta_pt_size = (fix31)(max_pt_size - min_pt_size);
+delta_adj = (fix31)(min_adj - max_adj);
+adj = (fix15)(min_adj -
+ (((fix31)(point_size - min_pt_size) * delta_adj +
+ (delta_pt_size >> 1)) / delta_pt_size));
+return adj; /* Return interpolated adjustment (1/256 points) */
+}
+#endif
+
+#if INCL_METRICS
+FUNCTION fix31 get_pair_kern(char_index1, char_index2)
+GDECL
+ufix16 char_index1; /* Index to first character in char directory */
+ufix16 char_index2; /* Index to second character in char directory */
+/*
+ * Returns inter-character spacing adjustment in units of 1/65536 em
+ * for the specified pair of characters.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 14 and returns 0 if pair kerning data not in font.
+ */
+{
+ufix8 FONTFAR *origin; /* Pointer to first kerning pair record */
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+ufix16 tmpufix16; /* Temporary workspace */
+fix15 no_pairs; /* Number of kerning pairs in font */
+ufix8 format; /* Track kerning format byte */
+boolean long_id; /* TRUE if 2-byte character ids */
+fix15 rec_size; /* Number of bytes in kern pair record */
+fix15 n; /* Number of remaining kern pairs */
+fix15 nn; /* Number of kern pairs in first partition */
+fix15 base; /* Index to first record in rem kern pairs */
+fix15 i; /* Index to kern pair being tested */
+fix31 adj = 0; /* Returned value of adjustment */
+fix15 adj_base; /* Adjustment base for relative adjustments */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return adj; /* Return zero pair kerning adjustment */
+ }
+
+no_pairs = sp_globals.kern.no_pairs; /* Number of kerning pairs */
+if (no_pairs == 0) /* Pair kerning data not available? */
+ {
+ report_error(14); /* Report pair kerning data not avail */
+ return adj; /* Return zero pair kerning adjustment */
+ }
+
+pointer = sp_globals.kern.pkorg; /* Point to start of pair kern data */
+format = NEXT_BYTE(pointer); /* Read pair kerning format byte */
+if (!(format & BIT0)) /* One-byte adjustment values? */
+ adj_base = NEXT_WORD(pointer); /* Read base adjustment */
+origin = pointer; /* First byte of kerning pair data */
+rec_size = format + 3; /* Compute kerning pair record size */
+long_id = format & BIT1; /* Set flag for 2-byte char index */
+
+n = no_pairs; /* Consider all kerning pairs */
+base = 0; /* Set base at first kern pair record */
+while (n != 0) /* While 1 or more kern pairs remain ... */
+ {
+ nn = n >> 1; /* Size of first partition */
+ i = base + nn; /* Index to record to be tested */
+ pointer = origin + (i * rec_size);
+ tmpufix16 = NEXT_CHNDX(pointer, long_id);
+ if (char_index1 < tmpufix16)
+ {
+ n = nn; /* Number remaining in first partition */
+ continue;
+ }
+ if (char_index1 > tmpufix16)
+ {
+ n -= nn + 1; /* Number remaining in second partition */
+ base = i + 1; /* Base index for second partition */
+ continue;
+ }
+ tmpufix16 = NEXT_CHNDX(pointer, long_id);
+ if (char_index2 < tmpufix16)
+ {
+ n = nn; /* Number remaining in first partition */
+ continue;
+ }
+ if (char_index2 > tmpufix16)
+ {
+ n -= nn + 1; /* Number remaining in second partition */
+ base = i + 1; /* Base index for second partition */
+ continue;
+ }
+ adj = (format & BIT0)?
+ (fix31)NEXT_WORD(pointer):
+ (fix31)(adj_base + (fix15)NEXT_BYTE(pointer));
+ adj = ((adj << 16) + (sp_globals.orus_per_em >> 1)) / sp_globals.orus_per_em; /* Convert units */
+ n = 0; /* No more to consider */
+ }
+return adj; /* Return pair kerning adjustment */
+}
+#endif
+
+
+#if INCL_METRICS
+#ifdef old
+FUNCTION boolean get_char_bbox(char_index, bbox)
+GDECL
+ufix16 char_index;
+bbox_t *bbox;
+{
+/*
+ * returns true if character exists, false if it doesn't
+ * provides transformed character bounding box in 1/65536 pixels
+ * in the provided bbox_t structure. Bounding box may be
+ * conservative in the event that the transformation is not
+ * normal or the character is compound.
+ */
+
+ufix8 FONTFAR *pointer;
+fix15 tmp;
+point_t Pmin, Pmax;
+
+#if REENTRANT_ALLOC
+plaid_t plaid;
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+tmp = NEXT_WORD(pointer); /* Read set width */
+
+tmp = NEXT_BYTE(pointer);
+if (tmp & BIT1) /* Optional data in header? */
+ {
+ tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmp; /* Skip optional data */
+ }
+
+pointer = plaid_tcb(pointer, tmp); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
+bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
+bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
+bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
+bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
+return TRUE;
+}
+
+#else /* new code, 4/25/91 */
+
+FUNCTION boolean get_char_bbox(char_index, bbox)
+GDECL
+ufix16 char_index;
+bbox_t *bbox;
+{
+/*
+ * returns true if character exists, false if it doesn't
+ * provides transformed character bounding box in 1/65536 pixels
+ * in the provided bbox_t structure. Bounding box may be
+ * conservative in the event that the transformation is not
+ * normal or the character is compound.
+ */
+
+ufix8 FONTFAR *pointer;
+fix15 tmp;
+fix15 format;
+ufix16 pix_adj;
+point_t Pmin, Pmax;
+
+#if REENTRANT_ALLOC
+plaid_t plaid;
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+tmp = NEXT_WORD(pointer); /* Read set width */
+
+format = NEXT_BYTE(pointer);
+if (format & BIT1) /* Optional data in header? */
+ {
+ tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmp; /* Skip optional data */
+ }
+
+if (format & BIT0)
+ {
+ pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
+ }
+else
+ {
+ pix_adj = 0;
+ }
+
+pointer = plaid_tcb(pointer, format); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
+
+Pmin.x -= pix_adj; /* ... of components of ... */
+Pmin.y -= pix_adj; /* ... compound ... */
+Pmax.x += pix_adj; /* ... character ... */
+Pmax.y += pix_adj; /* ... bounding box. */
+
+
+bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
+bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
+bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
+bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
+return TRUE;
+}
+#endif /* new code */
+
+#endif
+
+
+#if INCL_ISW
+FUNCTION boolean make_char_isw(char_index,imported_setwidth)
+GDECL
+ufix16 char_index;
+ufix32 imported_setwidth;
+{
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 xmax; /* Maximum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+ufix16 return_value;
+
+sp_globals.import_setwidth_act = TRUE;
+/* convert imported width to orus */
+sp_globals.imported_width = (sp_globals.metric_resolution *
+ imported_setwidth) >> 16;
+return_value = do_make_char(char_index);
+
+if (sp_globals.isw_modified_constants)
+ {
+ /* reset fixed point constants */
+ xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
+ ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
+ ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
+ sp_globals.constr.data_valid = FALSE;
+ xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
+ if (!setup_consts(xmin,xmax,ymin,ymax))
+ {
+ report_error(3); /* Requested specs out of range */
+ return FALSE;
+ }
+ }
+return (return_value);
+}
+
+FUNCTION boolean make_char(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+{
+sp_globals.import_setwidth_act = FALSE;
+return (do_make_char(char_index));
+}
+
+FUNCTION static boolean do_make_char(char_index)
+#else
+FUNCTION boolean make_char(char_index)
+#endif
+/*
+ * Outputs specified character using the currently selected font and
+ * scaling and output specifications.
+ * Reports Error 10 and returns FALSE if no font specifications
+ * previously set.
+ * Reports Error 12 and returns FALSE if character data not available.
+ */
+GDECL
+ufix16 char_index;
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix15 x_orus;
+fix15 tmpfix15;
+ufix8 format;
+
+#if INCL_ISW
+sp_globals.isw_modified_constants = FALSE;
+#endif
+
+#if REENTRANT_ALLOC
+
+plaid_t plaid;
+
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+intercepts_t intercepts;
+sp_globals.intercepts = &intercepts;
+#endif
+
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+#if INCL_MULTIDEV
+#if INCL_OUTLINE
+if (sp_globals.output_mode == MODE_OUTLINE && !sp_globals.outline_device_set)
+ {
+ report_error(2);
+ return FALSE;
+ }
+else
+#endif
+ if (!sp_globals.bitmap_device_set)
+ {
+ report_error(2);
+ return FALSE;
+ }
+#endif
+
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+SHOW(pointer);
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+x_orus = NEXT_WORD(pointer); /* Read set width */
+#if INCL_SQUEEZING || INCL_ISW
+sp_globals.setwidth_orus = x_orus;
+#endif
+
+#if INCL_ISW
+if (sp_globals.import_setwidth_act)
+ x_orus = sp_globals.imported_width;
+#endif
+sp_globals.Psw.x = (fix15)((fix31)
+ (((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+sp_globals.Psw.y = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+format = NEXT_BYTE(pointer);
+if (format & BIT1) /* Optional data in header? */
+ {
+ tmpfix15 = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmpfix15; /* Skip optional data */
+ }
+if (format & BIT0)
+ {
+ return sp_make_comp_char(pointer); /* Output compound character */
+ }
+else
+ {
+ return sp_make_simp_char(pointer, format); /* Output simple character */
+ }
+}
+
+FUNCTION static boolean sp_make_simp_char(pointer, format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Character format byte */
+/*
+ * Called by sp_make_char() to output a simple (non-compound) character.
+ * Returns TRUE on completion.
+ */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+#if INCL_SQUEEZING || INCL_ISW
+ufix8 FONTFAR *save_pointer;
+#endif
+#if INCL_ISW
+fix31 char_width;
+fix31 isw_scale;
+#endif
+
+#if INCL_SQUEEZING
+sp_globals.squeezing_compound = FALSE;
+if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_RIGHT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_TOP) ||
+ (sp_globals.pspecs->flags & SQUEEZE_BOTTOM) )
+ {
+ /* get the bounding box data before processing the character */
+ save_pointer = pointer;
+ preview_bounding_box (pointer, format);
+ pointer = save_pointer;
+ }
+#endif
+#if (INCL_ISW)
+if (sp_globals.import_setwidth_act)
+ {
+ save_pointer = pointer;
+ preview_bounding_box (pointer, format);
+ pointer = save_pointer;
+ /* make sure I'm not going to get fixed point overflow */
+ isw_scale = compute_isw_scale();
+ if (sp_globals.bbox_xmin_orus < 0)
+ char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus - sp_globals.bbox_xmin_orus), isw_scale);
+ else
+ char_width = SQUEEZE_MULT(sp_globals.bbox_xmax_orus, isw_scale);
+ if (char_width >= sp_globals.isw_xmax)
+ if (!reset_xmax(char_width))
+ return FALSE;
+ }
+#endif
+pointer = plaid_tcb(pointer, format); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
+if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character output */
+ {
+ do
+ {
+ proc_outl_data(pointer); /* Process outline data */
+ }
+ while (!fn_end_char()); /* Repeat if not done */
+ }
+return TRUE;
+}
+
+FUNCTION static boolean sp_make_comp_char(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+/*
+ * Called by sp_make_char() to output a compound character.
+ * Returns FALSE if data for any sub-character is not available.
+ * Returns TRUE if output completed with no error.
+ */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+point_t Pssw; /* Transformed escapement vector */
+ufix8 FONTFAR *pointer_sav; /* Saved pointer to compound character data */
+ufix8 FONTFAR *sub_pointer; /* Pointer to sub-character data */
+ufix8 format; /* Format of DOCH instruction */
+ufix16 sub_char_index; /* Index to sub-character in character directory */
+fix15 x_posn; /* X position of sub-character (outline res units) */
+fix15 y_posn; /* Y position of sub-character (outline res units) */
+fix15 x_scale; /* X scale factor of sub-character (scale units) */
+fix15 y_scale; /* Y scale factor of sub-character (scale units) */
+fix15 tmpfix15; /* Temporary workspace */
+fix15 x_orus; /* Set width in outline resolution units */
+fix15 pix_adj; /* Pixel adjustment to compound char bounding box */
+#if INCL_SQUEEZING
+fix31 x_factor, x_offset, top_scale, bottom_scale;
+boolean squeezed_x, squeezed_y;
+#endif
+#if INCL_SQUEEZING || INCL_ISW
+fix15 x_offset_pix;
+#endif
+#if INCL_ISW
+fix31 char_width;
+fix31 isw_scale;
+#endif
+
+
+#if INCL_SQUEEZING
+sp_globals.squeezing_compound = TRUE;
+#endif
+pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding box data */
+pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
+Pmin.x -= pix_adj; /* ... of components of ... */
+Pmin.y -= pix_adj; /* ... compound ... */
+Pmax.x += pix_adj; /* ... character ... */
+Pmax.y += pix_adj; /* ... bounding box. */
+
+#if INCL_SQUEEZING
+/* scale the bounding box if necessary before calling begin_char */
+squeezed_x = calculate_x_scale(&x_factor, &x_offset, 0);
+squeezed_y = calculate_y_scale(&top_scale, &bottom_scale,0,0);
+
+if (squeezed_x)
+ { /* scale the x coordinates of the bbox */
+ x_offset_pix = (fix15)(((x_offset >> 16) * sp_globals.tcb0.xppo)
+ >> sp_globals.mpshift);
+ if ((x_offset_pix >0) && (x_offset_pix < sp_globals.onepix))
+ x_offset_pix = sp_globals.onepix;
+ Pmin.x = SQUEEZE_MULT (x_factor, Pmin.x) + x_offset_pix - pix_adj;
+ Pmax.x = SQUEEZE_MULT (x_factor, Pmax.x) + x_offset_pix + pix_adj;
+ }
+if (squeezed_y)
+ { /* scale the y coordinates of the bbox */
+ if ((Pmin.y) < 0)
+ Pmin.y = SQUEEZE_MULT (bottom_scale, Pmin.y) - pix_adj;
+ else
+ Pmin.y = SQUEEZE_MULT (top_scale, Pmin.y) - pix_adj;
+ if ((Pmax.y) < 0)
+ Pmax.y = SQUEEZE_MULT (bottom_scale, Pmax.y) + pix_adj;
+ else
+ Pmax.y = SQUEEZE_MULT (top_scale, Pmax.y) + pix_adj;
+ }
+#endif
+#if (INCL_ISW)
+if (sp_globals.import_setwidth_act)
+ {
+ /* make sure I'm not going to get fixed point overflow */
+ isw_scale = ((fix31)sp_globals.imported_width << 16)/
+ (fix31)sp_globals.setwidth_orus;
+ char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus -
+ sp_globals.bbox_xmin_orus),
+isw_scale);
+ if (char_width >= sp_globals.isw_xmax)
+ if (!reset_xmax(char_width))
+ return FALSE;
+ }
+#endif
+
+if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character data */
+ {
+ pointer_sav = pointer;
+ do
+ {
+ pointer = pointer_sav; /* Point to next DOCH or END instruction */
+ while ((format = NEXT_BYTE(pointer))) /* DOCH instruction? */
+ {
+ init_tcb(); /* Initialize transformation control block */
+ x_posn = sp_get_posn_arg(&pointer, format);
+ y_posn = sp_get_posn_arg(&pointer, (ufix8)(format >> 2));
+ x_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT4));
+ y_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT5));
+ scale_tcb(&sp_globals.tcb, x_posn, y_posn, x_scale, y_scale); /* Scale for sub-char */
+ sub_char_index = (format & BIT6)? /* Read sub-char index */
+ 0xffff & NEXT_WORD(pointer):
+ 0xffff & NEXT_BYTE(pointer);
+ sub_pointer = sp_get_char_org(sub_char_index, FALSE); /* Point to start of sub-char */
+ if (sub_pointer == NULL) /* Character data not available? */
+ {
+ return FALSE; /* Abort character output */
+ }
+ sub_pointer += 2; /* Skip over character id */
+ x_orus = NEXT_WORD(sub_pointer); /* Read set_width of sub-character */
+
+ Pssw.x = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+ Pssw.y = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+ format = NEXT_BYTE(sub_pointer); /* Read sub-character format */
+ if (format & BIT1) /* Optional data in header? */
+ {
+ tmpfix15 = (ufix8)NEXT_BYTE(sub_pointer); /* Read size of optional data */
+ sub_pointer += tmpfix15; /* Skip optional data */
+ }
+ sub_pointer = plaid_tcb(sub_pointer, format); /* Process sub-character plaid data */
+ sub_pointer = read_bbox(sub_pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
+ fn_begin_sub_char(Pssw, Pmin, Pmax); /* Signal start of sub-character data */
+ proc_outl_data(sub_pointer); /* Process sub-character data */
+ fn_end_sub_char(); /* Signal end of sub-character data */
+ }
+ }
+ while (!fn_end_char()); /* Signal end of character; repeat if required */
+ }
+return TRUE;
+}
+
+#if INCL_LCD /* Dynamic load character data supported? */
+FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
+GDECL
+ufix16 char_index; /* Index of character to be accessed */
+boolean top_level; /* Not a compound character element */
+/*
+ * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
+ * sp_make_comp_char() to get a pointer to the start of the character data
+ * for the specified character index.
+ * Version for configuration supporting dynamic character data loading.
+ * Calls load_char_data() to load character data if not already loaded
+ * as part of the original font buffer.
+ * Returns NULL if character data not available
+ */
+{
+buff_t *pchar_data; /* Buffer descriptor requested */
+ufix8 FONTFAR *pointer; /* Pointer into character directory */
+ufix8 format; /* Character directory format byte */
+fix31 char_offset; /* Offset of char data from start of font file */
+fix31 next_char_offset; /* Offset of char data from start of font file */
+fix15 no_bytes; /* Number of bytes required for char data */
+
+if (top_level) /* Not element of compound char? */
+ {
+ if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
+ return NULL;
+ char_index -= sp_globals.first_char_idx;
+ if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
+ return NULL;
+ sp_globals.cb_offset = 0; /* Reset char buffer offset */
+ }
+
+pointer = sp_globals.pchar_dir;
+format = NEXT_BYTE(pointer); /* Read character directory format byte */
+pointer += char_index << 1; /* Point to indexed character entry */
+if (format) /* 3-byte entries in char directory? */
+ {
+ pointer += char_index; /* Adjust for 3-byte entries */
+ char_offset = read_long(pointer); /* Read file offset to char data */
+ next_char_offset = read_long(pointer + 3); /* Read offset to next char */
+ }
+else
+ {
+ char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
+ next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
+ }
+
+no_bytes = next_char_offset - char_offset;
+if (no_bytes == 0) /* Character not in directory? */
+ return NULL;
+
+if (next_char_offset <= sp_globals.font_buff_size)/* Character data already in font buffer? */
+ return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
+
+pchar_data = load_char_data(char_offset, no_bytes, sp_globals.cb_offset); /* Request char data load */
+if (pchar_data->no_bytes < no_bytes) /* Correct number of bytes loaded? */
+ return NULL;
+
+if (top_level) /* Not element of compound char? */
+ {
+ sp_globals.cb_offset = no_bytes;
+ }
+
+return pchar_data->org; /* Return pointer into character data buffer */
+}
+#endif
+
+#if INCL_LCD
+#else /* Dynamic load character data not supported? */
+FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
+GDECL
+ufix16 char_index; /* Index of character to be accessed */
+boolean top_level; /* Not a compound character element */
+/*
+ * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
+ * sp_make_comp_char() to get a pointer to the start of the character data
+ * for the specified character index.
+ * Version for configuration not supporting dynamic character data loading.
+ * Returns NULL if character data not available
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer into character directory */
+ufix8 format; /* Character directory format byte */
+fix31 char_offset; /* Offset of char data from start of font file */
+fix31 next_char_offset; /* Offset of char data from start of font file */
+fix15 no_bytes; /* Number of bytes required for char data */
+
+if (top_level) /* Not element of compound char? */
+ {
+ if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
+ return NULL;
+ char_index -= sp_globals.first_char_idx;
+ if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
+ return NULL;
+ }
+
+pointer = sp_globals.pchar_dir;
+format = NEXT_BYTE(pointer); /* Read character directory format byte */
+pointer += char_index << 1; /* Point to indexed character entry */
+if (format) /* 3-byte entries in char directory? */
+ {
+ pointer += char_index; /* Adjust for 3-byte entries */
+ char_offset = read_long(pointer); /* Read file offset to char data */
+ next_char_offset = read_long(pointer + 3); /* Read offset to next char */
+ }
+else
+ {
+ char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
+ next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
+ }
+
+no_bytes = next_char_offset - char_offset;
+if (no_bytes == 0) /* Character not in directory? */
+ return NULL;
+
+return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
+}
+#endif
+
+
+FUNCTION static fix15 sp_get_posn_arg(ppointer, format)
+GDECL
+ufix8 FONTFAR * STACKFAR *ppointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Format of DOCH arguments */
+/*
+ * Called by sp_make_comp_char() to read a position argument from the
+ * specified point in the font/char buffer.
+ * Updates pointer to byte following position argument.
+ * Returns value of position argument in outline resolution units
+ */
+{
+switch (format & 0x03)
+ {
+case 1:
+ return NEXT_WORD(*ppointer);
+
+case 2:
+ return (fix15)((fix7)NEXT_BYTE(*ppointer));
+
+default:
+ return (fix15)0;
+ }
+}
+
+FUNCTION static fix15 sp_get_scale_arg(ppointer, format)
+GDECL
+ufix8 FONTFAR *STACKFAR *ppointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Format of DOCH arguments */
+/*
+ * Called by sp_make_comp_char() to read a scale argument from the
+ * specified point in the font/char buffer.
+ * Updates pointer to byte following scale argument.
+ * Returns value of scale argument in scale units (normally 1/4096)
+ */
+{
+if (format)
+ return NEXT_WORD(*ppointer);
+else
+ return (fix15)ONE_SCALE;
+}
+#if INCL_ISW || INCL_SQUEEZING
+FUNCTION static void preview_bounding_box(pointer,format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Character format byte */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+
+ sp_globals.no_X_orus = (format & BIT2)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+ sp_globals.no_Y_orus = (format & BIT3)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+ pointer = read_oru_table(pointer);
+
+ /* Skip over control zone table */
+ pointer = skip_control_zone(pointer,format);
+
+ /* Skip over interpolation table */
+ pointer = skip_interpolation_table(pointer,format);
+ /* get_args has a pathological need for this value to be set */
+ sp_globals.Y_edge_org = sp_globals.no_X_orus;
+ pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding bo
+x */
+
+}
+#endif
+#if INCL_ISW
+FUNCTION static boolean reset_xmax(xmax)
+GDECL
+fix31 xmax;
+
+{
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+
+
+sp_globals.isw_modified_constants = TRUE;
+xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
+ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
+ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
+
+if (!setup_consts(xmin,xmax,ymin,ymax))
+ {
+ report_error(3); /* Requested specs out of range */
+ return FALSE;
+ }
+sp_globals.constr.data_valid = FALSE;
+/* recompute setwidth */
+sp_globals.Psw.x = (fix15)((fix31)(
+ ((fix31)sp_globals.imported_width * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)sp_globals.imported_width *
+ (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+sp_globals.Psw.y = (fix15)(
+ (fix31)(
+ ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+return TRUE;
+}
+#endif
diff --git a/src/Speedo/do_trns.c b/src/Speedo/do_trns.c
new file mode 100644
index 0000000..b003284
--- /dev/null
+++ b/src/Speedo/do_trns.c
@@ -0,0 +1,513 @@
+/* $Xorg: do_trns.c,v 1.3 2000/08/17 19:46:25 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+/**************************** D O _ T R N S . C ******************************
+ * *
+ * This module is responsible for executing all intelligent transformation *
+ * for bounding box and outline data *
+ * *
+ ****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static void sp_split_curve(PROTO_DECL2 point_t P1,point_t P2,point_t P3,fix15 depth);
+static ufix8 FONTFAR *sp_get_args(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format,point_t STACKFAR *pP);
+#else
+static void sp_split_curve(); /* Split Bezier curve into vectors */
+static ufix8 FONTFAR *sp_get_args(); /* Read X Y argument pair */
+#endif
+
+
+FUNCTION ufix8 FONTFAR *read_bbox(pointer, pPmin, pPmax, set_flag)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+point_t STACKFAR *pPmin; /* Lower left corner of bounding box */
+point_t STACKFAR *pPmax; /* Upper right corner of bounding box */
+boolean set_flag; /* flag to indicate whether global oru bbox should be saved */
+/*
+ * Called by make_simp_char() and make_comp_char() to read the
+ * bounding box data from the font.
+ * Sets Pmin and Pmax to the bottom left and top right corners
+ * of the bounding box after transformation into device space.
+ * The units of Pmin and Pmax are sub-pixels.
+ * Updates *ppointer to point to the byte following the
+ * bounding box data.
+ */
+{
+ufix8 format1;
+ufix8 format;
+fix15 i;
+point_t P;
+
+sp_globals.x_int = 0;
+sp_globals.y_int = sp_globals.Y_int_org;
+sp_globals.x_orus = sp_globals.y_orus = 0;
+format1 = NEXT_BYTE(pointer);
+pointer = sp_get_args(pointer, format1, pPmin);
+#if INCL_SQUEEZING || INCL_ISW
+if (set_flag)
+ {
+ sp_globals.bbox_xmin_orus = sp_globals.x_orus;
+ sp_globals.bbox_ymin_orus = sp_globals.y_orus;
+ }
+#endif
+*pPmax = *pPmin;
+for (i = 1; i < 4; i++)
+ {
+ switch(i)
+ {
+ case 1:
+ if (format1 & BIT6) /* Xmax requires X int zone 1? */
+ sp_globals.x_int++;
+ format = (format1 >> 4) | 0x0c;
+ break;
+
+ case 2:
+ if (format1 & BIT7) /* Ymax requires Y int zone 1? */
+ sp_globals.y_int++;
+ format = NEXT_BYTE(pointer);
+ break;
+
+ case 3:
+ sp_globals.x_int = 0;
+ format >>= 4;
+ break;
+
+ default:
+ break;
+ }
+
+ pointer = sp_get_args(pointer, format, &P);
+#if INCL_SQUEEZING || INCL_ISW
+ if (set_flag && (i==2))
+ {
+ sp_globals.bbox_xmax_orus = sp_globals.x_orus;
+ sp_globals.bbox_ymax_orus = sp_globals.y_orus;
+ }
+#endif
+ if ((i == 2) || (!sp_globals.normal))
+ {
+ if (P.x < pPmin->x)
+ pPmin->x = P.x;
+ if (P.y < pPmin->y)
+ pPmin->y = P.y;
+ if (P.x > pPmax->x)
+ pPmax->x = P.x;
+ if (P.y > pPmax->y)
+ pPmax->y = P.y;
+ }
+ }
+
+#if DEBUG
+printf("BBOX %6.1f(Xint 0), %6.1f(Yint 0), %6.1f(Xint %d), %6.1f(Yint %d)\n",
+ (real)pPmin->x / (real)sp_globals.onepix,
+ (real)pPmin->y / (real)sp_globals.onepix,
+ (real)pPmax->x / (real)sp_globals.onepix,
+ (format1 >> 6) & 0x01,
+ (real)pPmax->y / (real)sp_globals.onepix,
+ (format1 >> 7) & 0x01);
+
+#endif
+return pointer;
+}
+
+FUNCTION void proc_outl_data(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+/*
+ * Called by make_simp_char() and make_comp_char() to read the
+ * outline data from the font.
+ * The outline data is parsed, transformed into device coordinates
+ * and passed to an output module for further processing.
+ * Note that pointer is not updated to facilitate repeated
+ * processing of the outline data when banding mode is in effect.
+ */
+{
+ufix8 format1, format2;
+point_t P0, P1, P2, P3;
+fix15 depth;
+fix15 curve_count;
+
+sp_globals.x_int = 0;
+sp_globals.y_int = sp_globals.Y_int_org;
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+record_xint((fix15)sp_globals.x_int); /* Record xint data */
+record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
+#endif
+
+sp_globals.x_orus = sp_globals.y_orus = 0;
+curve_count = 0;
+while(TRUE)
+ {
+ format1 = NEXT_BYTE(pointer);
+ switch(format1 >> 4)
+ {
+ case 0: /* LINE */
+ pointer = sp_get_args(pointer, format1, &P1);
+#if DEBUG
+ printf("LINE %6.1f, %6.1f\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix);
+#endif
+ fn_line(P1);
+ sp_globals.P0 = P1;
+ continue;
+
+ case 1: /* Short XINT */
+ sp_globals.x_int = format1 & 0x0f;
+#if DEBUG
+ printf("XINT %d\n", sp_globals.x_int);
+#endif
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+record_xint((fix15)sp_globals.x_int); /* Record xint data */
+#endif
+ continue;
+
+ case 2: /* Short YINT */
+ sp_globals.y_int = sp_globals.Y_int_org + (format1 & 0x0f);
+#if DEBUG
+ printf("YINT %d\n", sp_globals.y_int - sp_globals.Y_int_org);
+#endif
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
+#endif
+ continue;
+
+ case 3: /* Miscellaneous */
+ switch(format1 & 0x0f)
+ {
+ case 0: /* END */
+ if (curve_count)
+ {
+ fn_end_contour();
+ }
+ return;
+
+ case 1: /* Long XINT */
+ sp_globals.x_int = NEXT_BYTE(pointer);
+#if DEBUG
+ printf("XINT %d\n", sp_globals.x_int);
+#endif
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+record_xint((fix15)sp_globals.x_int); /* Record xint data */
+#endif
+ continue;
+
+ case 2: /* Long YINT */
+ sp_globals.y_int = sp_globals.Y_int_org + NEXT_BYTE(pointer);
+#if DEBUG
+ printf("YINT %d\n", sp_globals.y_int - sp_globals.Y_int_org);
+#endif
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+record_yint((fix15)(sp_globals.y_int - sp_globals.Y_int_org)); /* Record yint data */
+#endif
+ continue;
+
+ default: /* Not used */
+ continue;
+ }
+
+ case 4: /* MOVE Inside */
+ case 5: /* MOVE Outside */
+ if (curve_count++)
+ {
+ fn_end_contour();
+ }
+
+ pointer = sp_get_args(pointer, format1, &P0);
+ sp_globals.P0 = P0;
+#if DEBUG
+ printf("MOVE %6.1f, %6.1f\n",
+ (real)sp_globals.P0.x / (real)sp_globals.onepix, (real)sp_globals.P0.y / (real)sp_globals.onepix);
+#endif
+ fn_begin_contour(sp_globals.P0, (boolean)(format1 & BIT4));
+ continue;
+
+ case 6: /* Undefined */
+#if DEBUG
+ printf("*** Undefined instruction (Hex %4x)\n", format1);
+#endif
+ continue;
+
+ case 7: /* Undefined */
+#if DEBUG
+ printf("*** Undefined instruction (Hex %4x)\n", format1);
+#endif
+ continue;
+
+ default: /* CRVE */
+ format2 = NEXT_BYTE(pointer);
+ pointer = sp_get_args(pointer, format1, &P1);
+ pointer = sp_get_args(pointer, format2, &P2);
+ pointer = sp_get_args(pointer, (ufix8)(format2 >> 4), &P3);
+ depth = (format1 >> 4) & 0x07;
+#if DEBUG
+ printf("CRVE %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %d\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
+ (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
+ (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix,
+ depth);
+#endif
+ depth += sp_globals.depth_adj;
+ if (sp_globals.curves_out)
+ {
+ fn_curve(P1, P2, P3, depth);
+ sp_globals.P0 = P3;
+ continue;
+ }
+ if (depth <= 0)
+ {
+ fn_line(P3);
+ sp_globals.P0 = P3;
+ continue;
+ }
+ sp_split_curve(P1, P2, P3, depth);
+ continue;
+ }
+ }
+}
+
+FUNCTION static void sp_split_curve(P1, P2, P3, depth)
+GDECL
+point_t P1; /* First control point of Bezier curve */
+point_t P2; /* Second control point of Bezier curve */
+point_t P3; /* End point of Bezier curve */
+fix15 depth; /* Levels of recursive subdivision required */
+/*
+ * Called by proc_outl_data() to subdivide Bezier curves into an
+ * appropriate number of vectors, whenever curves are not enabled
+ * for output to the currently selected output module.
+ * sp_split_curve() calls itself recursively to the depth specified
+ * at which point it calls line() to deliver each vector resulting
+ * from the spliting process.
+ */
+{
+fix31 X0 = (fix31)sp_globals.P0.x;
+fix31 Y0 = (fix31)sp_globals.P0.y;
+fix31 X1 = (fix31)P1.x;
+fix31 Y1 = (fix31)P1.y;
+fix31 X2 = (fix31)P2.x;
+fix31 Y2 = (fix31)P2.y;
+fix31 X3 = (fix31)P3.x;
+fix31 Y3 = (fix31)P3.y;
+point_t Pmid;
+point_t Pctrl1;
+point_t Pctrl2;
+
+#if DEBUG
+printf("CRVE(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f)\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
+ (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
+ (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix);
+#endif
+
+
+Pmid.x = (X0 + (X1 + X2) * 3 + X3 + 4) >> 3;
+Pmid.y = (Y0 + (Y1 + Y2) * 3 + Y3 + 4) >> 3;
+if ((--depth) <= 0)
+ {
+ fn_line(Pmid);
+ sp_globals.P0 = Pmid;
+ fn_line(P3);
+ sp_globals.P0 = P3;
+ }
+else
+ {
+ Pctrl1.x = (X0 + X1 + 1) >> 1;
+ Pctrl1.y = (Y0 + Y1 + 1) >> 1;
+ Pctrl2.x = (X0 + (X1 << 1) + X2 + 2) >> 2;
+ Pctrl2.y = (Y0 + (Y1 << 1) + Y2 + 2) >> 2;
+ sp_split_curve(Pctrl1, Pctrl2, Pmid, depth);
+ Pctrl1.x = (X1 + (X2 << 1) + X3 + 2) >> 2;
+ Pctrl1.y = (Y1 + (Y2 << 1) + Y3 + 2) >> 2;
+ Pctrl2.x = (X2 + X3 + 1) >> 1;
+ Pctrl2.y = (Y2 + Y3 + 1) >> 1;
+ sp_split_curve(Pctrl1, Pctrl2, P3, depth);
+ }
+}
+
+FUNCTION static ufix8 FONTFAR *sp_get_args(pointer, format, pP)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+ufix8 format; /* Format specifiaction of argument pair */
+point_t STACKFAR *pP; /* Resulting transformed point */
+/*
+ * Called by read_bbox() and proc_outl_data() to read an X Y argument
+ * pair from the font.
+ * The format is specified as follows:
+ * Bits 0-1: Type of X argument.
+ * Bits 2-3: Type of Y argument.
+ * where the 4 possible argument types are:
+ * Type 0: Controlled coordinate represented by one byte
+ * index into the X or Y controlled coordinate table.
+ * Type 1: Interpolated coordinate represented by a two-byte
+ * signed integer.
+ * Type 2: Interpolated coordinate represented by a one-byte
+ * signed increment/decrement relative to the
+ * proceding X or Y coordinate.
+ * Type 3: Repeat of preceding X or Y argument value and type.
+ * The units of P are sub-pixels.
+ * Updates *ppointer to point to the byte following the
+ * argument pair.
+ */
+{
+ufix8 edge;
+
+/* Read X argument */
+switch(format & 0x03)
+ {
+case 0: /* Index to controlled oru */
+ edge = NEXT_BYTE(pointer);
+ sp_globals.x_orus = sp_plaid.orus[edge];
+#if INCL_RULES
+ sp_globals.x_pix = sp_plaid.pix[edge];
+#endif
+ break;
+
+case 1: /* 2 byte interpolated oru value */
+ sp_globals.x_orus = NEXT_WORD(pointer);
+ goto L1;
+
+case 2: /* 1 byte signed oru increment */
+ sp_globals.x_orus += (fix15)((fix7)NEXT_BYTE(pointer));
+L1:
+#if INCL_RULES
+ 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);
+#endif
+ break;
+
+default: /* No change in X value */
+ break;
+ }
+
+/* Read Y argument */
+switch((format >> 2) & 0x03)
+ {
+case 0: /* Index to controlled oru */
+ edge = sp_globals.Y_edge_org + NEXT_BYTE(pointer);
+ sp_globals.y_orus = sp_plaid.orus[edge];
+#if INCL_RULES
+ sp_globals.y_pix = sp_plaid.pix[edge];
+#endif
+ break;
+
+case 1: /* 2 byte interpolated oru value */
+ sp_globals.y_orus = NEXT_WORD(pointer);
+ goto L2;
+
+case 2: /* 1 byte signed oru increment */
+ sp_globals.y_orus += (fix15)((fix7)NEXT_BYTE(pointer));
+L2:
+#if INCL_RULES
+ 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);
+#endif
+ break;
+
+default: /* No change in X value */
+ break;
+ }
+
+#if INCL_RULES
+switch(sp_globals.tcb.xmode)
+ {
+case 0: /* X mode 0 */
+ pP->x = sp_globals.x_pix;
+ break;
+
+case 1: /* X mode 1 */
+ pP->x = -sp_globals.x_pix;
+ break;
+
+case 2: /* X mode 2 */
+ pP->x = sp_globals.y_pix;
+ break;
+
+case 3: /* X mode 3 */
+ pP->x = -sp_globals.y_pix;
+ break;
+
+default: /* X mode 4 */
+#endif
+ pP->x = (MULT16(sp_globals.x_orus, sp_globals.tcb.xxmult) +
+ MULT16(sp_globals.y_orus, sp_globals.tcb.xymult) +
+ sp_globals.tcb.xoffset) >> sp_globals.mpshift;
+#if INCL_RULES
+ break;
+ }
+
+switch(sp_globals.tcb.ymode)
+ {
+case 0: /* Y mode 0 */
+ pP->y = sp_globals.y_pix;
+ break;
+
+case 1: /* Y mode 1 */
+ pP->y = -sp_globals.y_pix;
+ break;
+
+case 2: /* Y mode 2 */
+ pP->y = sp_globals.x_pix;
+ break;
+
+case 3: /* Y mode 3 */
+ pP->y = -sp_globals.x_pix;
+ break;
+
+default: /* Y mode 4 */
+#endif
+ pP->y = (MULT16(sp_globals.x_orus, sp_globals.tcb.yxmult) +
+ MULT16(sp_globals.y_orus, sp_globals.tcb.yymult) +
+ sp_globals.tcb.yoffset) >> sp_globals.mpshift;
+#if INCL_RULES
+ break;
+ }
+#endif
+
+return pointer;
+}
+
+
+
diff --git a/src/Speedo/keys.h b/src/Speedo/keys.h
new file mode 100644
index 0000000..dd9d0bf
--- /dev/null
+++ b/src/Speedo/keys.h
@@ -0,0 +1,56 @@
+/* $Xorg: keys.h,v 1.3 2000/08/17 19:46:25 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+/***** DECRYPTION KEY CONSTANTS (PC Platform) *****/
+
+#define CUS0 432 /* Customer number */
+
+#define KEY0 0 /* Decryption key 0 */
+#define KEY1 72 /* Decryption key 1 */
+#define KEY2 123 /* Decryption key 2 */
+#define KEY3 1 /* Decryption key 3 */
+#define KEY4 222 /* Decryption key 4 */
+#define KEY5 194 /* Decryption key 5 */
+#define KEY6 113 /* Decryption key 6 */
+#define KEY7 119 /* Decryption key 7 */
+#define KEY8 52 /* Decryption key 8 */
+
+/***** DECRYPTION KEY CONSTANTS (Sample) *****/
+
+#define XSAMPLEFONTS
+
+#define XCUS0 0 /* Customer number */
+
+#define XKEY0 0 /* Decryption key 0 */
+#define XKEY1 0 /* Decryption key 1 */
+#define XKEY2 0 /* Decryption key 2 */
+#define XKEY3 0 /* Decryption key 3 */
+#define XKEY4 0 /* Decryption key 4 */
+#define XKEY5 0 /* Decryption key 5 */
+#define XKEY6 0 /* Decryption key 6 */
+#define XKEY7 0 /* Decryption key 7 */
+#define XKEY8 0 /* Decryption key 8 */
+
+
diff --git a/src/Speedo/out_bl2d.c b/src/Speedo/out_bl2d.c
new file mode 100644
index 0000000..d14f8c3
--- /dev/null
+++ b/src/Speedo/out_bl2d.c
@@ -0,0 +1,776 @@
+/* $Xorg: out_bl2d.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+/*************************** O U T _ B L 2 D . C *****************************
+ * *
+ * This is an output module for screen writer using two dimensional scanning *
+ ****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for speedo */
+
+#define CLOCKWISE 1
+#define DEBUG 0
+#define ABS(X) ( (X < 0) ? -X : X)
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if INCL_2D
+#if PROTOS_AVAIL
+static void sp_draw_vector_to_2d(PROTO_DECL2 fix15 x0,fix15 y0,fix15 x1,fix15 y1,band_t GLOBALFAR *band);
+static void sp_add_intercept_2d(PROTO_DECL2 fix15 y,fix15 x);
+static void sp_proc_intercepts_2d(PROTO_DECL1);
+#else
+static void sp_add_intercept_2d();
+static void sp_proc_intercepts_2d();
+static void sp_draw_vector_to_2d();
+#endif
+#endif
+
+#if INCL_2D
+FUNCTION boolean init_2d(specsarg)
+GDECL
+specs_t GLOBALFAR *specsarg;
+/*
+ * init_out_2d() is called by sp_set_specs() to initialize the output module.
+ * Returns TRUE if output module can accept requested specifications.
+ * Returns FALSE otherwise.
+ */
+{
+
+if (specsarg->flags & CURVES_OUT)
+ return FALSE; /* Curves out, clipping not supported */
+
+#if DEBUG
+printf("INIT_OUT__2d()\n");
+#endif
+return TRUE;
+}
+#endif
+
+#if INCL_2D
+FUNCTION boolean begin_char_2d(Psw, Pmin, Pmax)
+GDECL
+point_t Psw;
+point_t Pmin;
+point_t Pmax;
+/* Called once at the start of the character generation process
+ * Initializes intercept table, either calculates pixel maxima or
+ * decides that they need to be collected
+ */
+{
+#if DEBUG
+printf("BEGIN_CHAR__2d(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
+ (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
+ (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
+#endif
+/* Convert PIX.FRAC to 16.16 form */
+sp_globals.x_scan_active = TRUE; /* Assume x-scanning from the start */
+
+init_char_out(Psw,Pmin,Pmax);
+return TRUE;
+}
+#endif
+
+
+#if INCL_2D
+FUNCTION void begin_contour_2d(P1, outside)
+GDECL
+point_t P1;
+boolean outside;
+/* Called at the start of each contour
+ */
+{
+
+#if DEBUG
+printf("BEGIN_CONTOUR__2d(%3.4f, %3.4f, %s)\n",
+ (real)P1.x / (real)sp_globals.onepix,
+ (real)P1.y / (real)sp_globals.onepix,
+ outside? "outside": "inside");
+#endif
+sp_globals.x0_spxl = P1.x;
+sp_globals.y0_spxl = P1.y;
+}
+#endif
+
+#if INCL_2D
+FUNCTION void line_2d(P1)
+GDECL
+point_t P1;
+/*
+ * Called for each vector in the transformed character
+ * "draws" vector into intercept table
+ */
+{
+
+#if DEBUG
+printf("LINE_0(%3.4f, %3.4f)\n",
+ (real)P1.x / (real)sp_globals.onepix,
+ (real)P1.y / (real)sp_globals.onepix);
+#endif
+
+if (sp_globals.extents_running)
+ {
+ if (sp_globals.x0_spxl > sp_globals.bmap_xmax)
+ sp_globals.bmap_xmax = sp_globals.x0_spxl;
+ if (sp_globals.x0_spxl < sp_globals.bmap_xmin)
+ sp_globals.bmap_xmin = sp_globals.x0_spxl;
+ if (sp_globals.y0_spxl > sp_globals.bmap_ymax)
+ sp_globals.bmap_ymax = sp_globals.y0_spxl;
+ if (sp_globals.y0_spxl < sp_globals.bmap_ymin)
+ sp_globals.bmap_ymin = sp_globals.y0_spxl;
+ }
+
+if (!sp_globals.intercept_oflo)
+ {
+ sp_draw_vector_to_2d(sp_globals.x0_spxl,
+ sp_globals.y0_spxl,
+ P1.x,
+ P1.y,
+ &sp_globals.y_band); /* y-scan */
+
+ if (sp_globals.x_scan_active)
+ sp_draw_vector_to_2d(sp_globals.y0_spxl,
+ sp_globals.x0_spxl,
+ P1.y,
+ P1.x,
+ &sp_globals.x_band); /* x-scan if selected */
+ }
+
+sp_globals.x0_spxl = P1.x;
+sp_globals.y0_spxl = P1.y; /* update endpoint */
+}
+
+FUNCTION static void sp_draw_vector_to_2d(x0, y0, x1, y1, band)
+GDECL
+fix15 x0; /* X coordinate */
+fix15 y0; /* Y coordinate */
+fix15 x1;
+fix15 y1;
+band_t GLOBALFAR *band;
+{
+register fix15 how_many_y; /* # of intercepts at y = n + 1/2 */
+register fix15 yc; /* Current scan-line */
+ fix15 temp1; /* various uses */
+ fix15 temp2; /* various uses */
+register fix31 dx_dy; /* slope of line in 16.16 form */
+register fix31 xc; /* high-precision (16.16) x coordinate */
+ fix15 y_pxl;
+
+yc = (y0 + sp_globals.pixrnd) >> sp_globals.pixshift; /* current scan line = end of last line */
+y_pxl = (y1 + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan line */
+
+if ((how_many_y = y_pxl - yc) == 0) return; /* Don't draw a null line */
+
+if (how_many_y < 0) yc--; /* Predecrment downward lines */
+
+if (yc > band->band_max) /* Is start point above band? */
+ {
+ if (y_pxl > band->band_max) return; /* line has to go down! */
+ how_many_y = y_pxl - (yc = band->band_max) - 1; /* Yes, limit it */
+ }
+
+if (yc < band->band_min) /* Is start point below band? */
+ {
+ if (y_pxl < band->band_min) return; /* line has to go up! */
+ how_many_y = y_pxl - (yc = band->band_min); /* Yes, limit it */
+ }
+
+xc = (fix31)(x0 + sp_globals.pixrnd) << 16; /* Original x coordinate with built in */
+ /* rounding. int.16 + pixshift form */
+
+if ( (temp1 = (x1 - x0)) == 0) /* check for vertical line */
+ {
+ dx_dy = 0L; /* Zero slope, leave xc alone */
+ goto skip_calc;
+ }
+
+/* calculate dx_dy at 16.16 fixed point */
+
+dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
+
+/* We have to check for a @#$%@# possible multiply overflow */
+/* by doing another @#$*& multiply. In assembly language, */
+/* the program could just check the OVerflow flag or whatever*/
+/* works on the particular processor. This C code is meant */
+/* to be processor independent. */
+
+temp1 = (yc << sp_globals.pixshift) - y0 + sp_globals.pixrnd;
+/* This sees if the sign bits start at bit 15 */
+/* if they do, no overflow has occurred */
+
+temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
+
+if ( (temp2 != (fix15)0xFFFF) &&
+ (temp2 != 0x0000) )
+ { /* Overflow. Pick point closest to yc + .5 */
+ if (ABS(temp1) < ABS((yc << sp_globals.pixshift) - y1 + sp_globals.pixrnd))
+ { /* use x1 instead of x0 */
+ xc = (fix31)(x1 + sp_globals.pixrnd) << (16 - sp_globals.pixshift);
+ }
+ goto skip_calc;
+ }
+/* calculate new xc at the center of the *current* scan line */
+/* due to banding, yc may be several lines away from y0 */
+/* xc += (yc + .5 - y0) * dx_dy */
+/* This multiply generates a subpixel delta. */
+/* So we leave it as an int.pixshift + 16 delta */
+
+xc += (fix31)temp1 * dx_dy;
+dx_dy <<= sp_globals.pixshift;
+skip_calc:
+
+yc -= band->band_array_offset; /* yc is now an offset relative to the band */
+
+if (how_many_y < 0)
+ { /* Vector down */
+ if ((how_many_y += yc + 1) < band->band_floor)
+ how_many_y = band->band_floor; /* can't go below floor */
+ while(yc >= how_many_y)
+ {
+ temp1 = (fix15)(xc >> 16);
+ sp_add_intercept_2d(yc--,temp1);
+ xc -= dx_dy;
+ }
+ }
+ else
+ { /* Vector up */
+ /* check to see that line doesn't extend beyond top of band */
+ if ((how_many_y += yc) > band->band_ceiling)
+ how_many_y = band->band_ceiling;
+ while(yc < how_many_y)
+ {
+ temp1 = (fix15)(xc >> 16);
+ sp_add_intercept_2d(yc++,temp1);
+ xc += dx_dy;
+ }
+ }
+}
+
+#endif
+
+#if INCL_2D
+FUNCTION boolean end_char_2d()
+GDECL
+/* Called when all character data has been output
+ * Return TRUE if output process is complete
+ * Return FALSE to repeat output of the transformed data beginning
+ * with the first contour
+ */
+{
+
+fix31 xorg;
+fix31 yorg;
+#if INCL_CLIPPING
+fix31 em_max, em_min, bmap_max, bmap_min;
+#endif
+
+#if DEBUG
+printf("END_CHAR__2d()\n");
+#endif
+
+if (sp_globals.first_pass)
+ {
+ if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
+ {
+ sp_globals.xmin = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.xmax = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.xmin = sp_globals.xmax = 0;
+ }
+ if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
+ {
+
+#if INCL_CLIPPING
+ switch(sp_globals.tcb0.xtype)
+ {
+ case 1: /* 180 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.clip_ymin = -1 * sp_globals.clip_ymin;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ sp_globals.clip_xmax = -sp_globals.xmin;
+ sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ case 2: /* 90 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize to x origin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_xmax)
+ sp_globals.xmax = bmap_max;
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+ sp_globals.clip_ymax = 0;
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ /* normalize to x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ break;
+ case 3: /* 270 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+
+ /* let the minimum be the larger of these two values */
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize the x value to new xorgin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+ /* let the max be the lesser of these two values */
+ if (bmap_max < sp_globals.clip_xmax)
+ {
+ sp_globals.xmax = bmap_max;
+ sp_globals.clip_xmax = bmap_max;
+ }
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+
+ /* normalize the x value to new x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ /* compute y clip values */
+ sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = 0;
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ break;
+ default: /* this is for zero degree rotation and arbitrary rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max > sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ sp_globals.clip_ymin = - sp_globals.clip_ymin;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ sp_globals.clip_xmin = -sp_globals.xmin;
+ sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ }
+if ( !(sp_globals.specs.flags & CLIP_TOP))
+#endif
+ sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+#if INCL_CLIPPING
+if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
+#endif
+ sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.ymin = sp_globals.ymax = 0;
+ }
+
+ /* add in the rounded out part (from xform.) of the left edge */
+ if (sp_globals.tcb.xmode == 0) /* for X pix is function of X orus only add the round */
+ xorg = (((fix31)sp_globals.xmin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.xmode == 1) /* for X pix is function of -X orus only, subtr. round */
+ xorg = (((fix31)sp_globals.xmin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift)) ;
+ else
+ xorg = (fix31)sp_globals.xmin << 16; /* for other cases don't use round on x */
+
+ if (sp_globals.tcb.ymode == 2) /* for Y pix is function of X orus only, add round error */
+ yorg = (((fix31)sp_globals.ymin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.ymode == 3) /* for Y pix is function of -X orus only, sub round */
+ yorg = (((fix31)sp_globals.ymin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift));
+ else /* all other cases have no round error on yorg */
+ yorg = (fix31)sp_globals.ymin << 16;
+
+ open_bitmap(sp_globals.set_width.x, sp_globals.set_width.y, xorg, yorg,
+ sp_globals.xmax - sp_globals.xmin, sp_globals.ymax - sp_globals.ymin);
+ if (sp_globals.intercept_oflo)
+ {
+ sp_globals.y_band.band_min = sp_globals.ymin;
+ sp_globals.y_band.band_max = sp_globals.ymax;
+ sp_globals.x_scan_active = FALSE;
+ sp_globals.no_x_lists = 0;
+ init_intercepts_out();
+ sp_globals.first_pass = FALSE;
+ sp_globals.extents_running = FALSE;
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_2d();
+ close_bitmap();
+ return TRUE;
+ }
+ }
+else
+ {
+ if (sp_globals.intercept_oflo)
+ {
+ reduce_band_size_out();
+ init_intercepts_out();
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_2d();
+ if (next_band_out())
+ {
+ init_intercepts_out();
+ return FALSE;
+ }
+ close_bitmap();
+ return TRUE;
+ }
+ }
+}
+#endif
+
+#if INCL_2D
+FUNCTION static void sp_add_intercept_2d(y, x)
+GDECL
+fix15 y; /* Y coordinate in relative pixel units */
+ /* (0 is lowest sample in band) */
+fix15 x; /* X coordinate of intercept in subpixel units */
+
+/* Called by line() to add an intercept to the intercept list structure
+ */
+
+{
+register fix15 from; /* Insertion pointers for the linked list sort */
+register fix15 to;
+
+#if DEBUG
+/* Bounds checking IS done in debug mode */
+if ((y >= MAX_INTERCEPTS) || (y < 0))
+ {
+ printf("Intercept out of table!!!!! (%d)\n",y);
+ return;
+ }
+
+if (y >= sp_globals.no_y_lists)
+ {
+ printf(" Add x intercept(%2d, %f)\n",
+ y + sp_globals.x_band.band_min - sp_globals.no_y_lists,
+ (real)x/(real)sp_globals.onepix);
+ if (y > (sp_globals.no_x_lists + sp_globals.no_y_lists))
+ {
+ printf(" Intercept too big for band!!!!!\007\n");
+ return;
+ }
+ }
+ else
+ {
+ printf(" Add y intercept(%2d, %f)\n", y + sp_globals.y_band.band_min,(real)x/(real)sp_globals.onepix);
+ }
+
+if (y < 0) /* Y value below bottom of current band? */
+ {
+ printf(" Intecerpt less than 0!!!\007\n");
+ return;
+ }
+#endif
+
+/* Store new values */
+
+sp_intercepts.car[sp_globals.next_offset] = x;
+
+/* Find slot to insert new element (between from and to) */
+
+from = y; /* Start at list head */
+
+while( (to = sp_intercepts.cdr[from]) >= sp_globals.first_offset) /* Until to == end of list */
+ {
+ if (x <= sp_intercepts.car[to]) /* If next item is larger than or same as this one... */
+ goto insert_element; /* ... drop out and insert here */
+ from = to; /* move forward in list */
+ }
+
+insert_element: /* insert element "next_offset" between elements "from" */
+ /* and "to" */
+
+sp_intercepts.cdr[from] = sp_globals.next_offset;
+sp_intercepts.cdr[sp_globals.next_offset] = to;
+
+if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
+ {
+ sp_globals.intercept_oflo = TRUE;
+/* There may be a few more calls to "add_intercept" from the current line */
+/* To avoid problems, we set next_offset to a safe value. We don't care */
+/* if the intercept table gets trashed at this point */
+ sp_globals.next_offset = sp_globals.first_offset;
+ }
+}
+
+#endif
+
+#if INCL_2D
+FUNCTION static void sp_proc_intercepts_2d()
+GDECL
+/* Called by sp_make_char to output accumulated intercept lists
+ * Clips output to xmin, xmax, sp_globals.ymin, ymax boundaries
+ */
+{
+register fix15 i;
+register fix15 from, to; /* Start and end of run in pixel units
+ relative to left extent of character */
+register fix15 y;
+register fix15 scan_line;
+ fix15 local_bmap_xmin;
+ fix15 local_bmap_xmax;
+ fix15 first_y, last_y;
+ fix15 j,k;
+
+#if INCL_CLIPPING
+if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
+ clipleft = TRUE;
+else
+ clipleft = FALSE;
+if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
+ clipright = TRUE;
+else
+ clipright = FALSE;
+if (clipleft || clipright)
+ {
+ xmax = sp_globals.clip_xmax << sp_globals.pixshift;
+ xmin = sp_globals.clip_xmin << sp_globals.pixshift;
+ }
+if (!clipright)
+ xmax = ((sp_globals.set_width.x+32768L) >> 16);
+#endif
+
+if (sp_globals.x_scan_active) /* If xscanning, we need to make sure we don't miss any important pixels */
+ {
+ first_y = sp_globals.x_band.band_floor; /* start of x lists */
+ last_y = sp_globals.x_band.band_ceiling; /* end of x lists */
+ for (y = first_y; y != last_y; y++) /* scan all xlists */
+ {
+ i = sp_intercepts.cdr[y]; /* Index head of intercept list */
+ while (i != 0) /* Link to next intercept if present */
+ {
+ from = sp_intercepts.car[i];
+ j = i;
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (i == 0) /* End of list? */
+ {
+#if DEBUG
+ printf("****** proc_intercepts: odd number of intercepts in x list\n");
+#endif
+ break;
+ }
+ to = sp_intercepts.car[i];
+ k = sp_intercepts.cdr[i];
+ if (((to >> sp_globals.pixshift) >= (from >> sp_globals.pixshift)) &&
+ ((to - from) < (sp_globals.onepix + 1)))
+ {
+ from = ((fix31)to + (fix31)from - (fix31)sp_globals.onepix) >> (sp_globals.pixshift + 1);
+ if (from > sp_globals.y_band.band_max)
+ from = sp_globals.y_band.band_max;
+ if ((from -= sp_globals.y_band.band_min) < 0)
+ from = 0;
+ to = ((y - sp_globals.x_band.band_floor + sp_globals.x_band.band_min)
+ << sp_globals.pixshift)
+ + sp_globals.pixrnd;
+ sp_intercepts.car[j] = to;
+ sp_intercepts.car[i] = to + sp_globals.onepix;
+ sp_intercepts.cdr[i] = sp_intercepts.cdr[from];
+ sp_intercepts.cdr[from] = j;
+ }
+ i = k;
+ }
+ }
+ }
+#if DEBUG
+printf("\nIntercept lists:\n");
+#endif
+
+if ((first_y = sp_globals.y_band.band_max) >= sp_globals.ymax)
+ first_y = sp_globals.ymax - 1; /* Clip to ymax boundary */
+
+if ((last_y = sp_globals.y_band.band_min) < sp_globals.ymin)
+ last_y = sp_globals.ymin; /* Clip to sp_globals.ymin boundary */
+
+last_y -= sp_globals.y_band.band_array_offset;
+
+local_bmap_xmin = sp_globals.xmin << sp_globals.pixshift;
+local_bmap_xmax = (sp_globals.xmax << sp_globals.pixshift) + sp_globals.pixrnd;
+
+#if DEBUG
+/* Print out all of the intercept info */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - local_bmap_xmin) < 0)
+ from = 0; /* Clip to xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (i == 0) /* End of list? */
+ {
+ printf("****** proc_intercepts: odd number of intercepts\n");
+ break;
+ }
+ if ((to = sp_intercepts.car[i]) > sp_globals.bmap_xmax)
+ to = sp_globals.bmap_xmax - local_bmap_xmin; /* Clip to xmax boundary */
+ else
+ to -= local_bmap_xmin;
+ printf(" Y = %2d (scanline %2d): %3.4f %3.4f:\n",
+ y + sp_globals.y_band.band_min,
+ scan_line,
+ (real)from / (real)sp_globals.onepix,
+ (real)to / (real)sp_globals.onepix);
+ }
+ }
+#endif
+
+/* Draw the image */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - local_bmap_xmin) < 0)
+ from = 0; /* Clip to xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+
+ if ((to = sp_intercepts.car[i]) > local_bmap_xmax)
+ to = sp_globals.bmap_xmax - local_bmap_xmin; /* Clip to xmax boundary */
+ else
+ to -= local_bmap_xmin;
+#if INCL_CLIPPING
+ if (clipleft)
+ {
+ if (to <= xmin)
+ continue;
+ if (from < xmin)
+ from = xmin;
+ }
+ if (clipright)
+ {
+ if (from >= xmax)
+ continue;
+ if (to > xmax)
+ to = xmax;
+ }
+#endif
+ if ( (to - from) <= sp_globals.onepix)
+ {
+ from = (to + from - sp_globals.onepix) >> (sp_globals.pixshift + 1);
+ set_bitmap_bits(scan_line, from, from + 1);
+ }
+ else
+ {
+ set_bitmap_bits(scan_line, from >> sp_globals.pixshift, to >> sp_globals.pixshift);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/Speedo/out_blk.c b/src/Speedo/out_blk.c
new file mode 100644
index 0000000..71e39af
--- /dev/null
+++ b/src/Speedo/out_blk.c
@@ -0,0 +1,708 @@
+/* $Xorg: out_blk.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+
+/*************************** O U T _ B L K . C *********************************
+ * *
+ * This is an output module for black-writer mode. *
+ * *
+ *****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+#define LOCAL static
+#define ABS(X) ( (X < 0) ? -X : X)
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if INCL_BLACK
+#if PROTOS_AVAIL
+static void sp_add_intercept_black(PROTO_DECL2 fix15 y, fix15 x);
+static void sp_proc_intercepts_black(PROTO_DECL1);
+#else
+static void sp_add_intercept_black();
+static void sp_proc_intercepts_black();
+#endif
+#endif
+
+
+#if INCL_BLACK
+FUNCTION boolean init_black(specsarg)
+GDECL
+specs_t GLOBALFAR *specsarg;
+/*
+ * init_out0() is called by sp_set_specs() to initialize the output module.
+ * Returns TRUE if output module can accept requested specifications.
+ * Returns FALSE otherwise.
+ */
+{
+#if DEBUG
+printf("INIT_BLK()\n");
+#endif
+if (specsarg->flags & CURVES_OUT)
+ return FALSE; /* Curves out not supported */
+return (TRUE);
+}
+#endif
+
+
+#if INCL_BLACK
+FUNCTION boolean begin_char_black(Psw, Pmin, Pmax)
+GDECL
+point_t Psw;
+point_t Pmin;
+point_t Pmax;
+/* Called once at the start of the character generation process
+ */
+{
+#if DEBUG
+printf("BEGIN_CHAR_BLACK(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
+ (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
+ (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
+#endif
+init_char_out(Psw,Pmin,Pmax);
+return TRUE;
+}
+#endif
+
+
+#if INCL_BLACK
+FUNCTION void begin_contour_black(P1, outside)
+GDECL
+point_t P1;
+boolean outside;
+/* Called at the start of each contour
+ */
+{
+
+#if DEBUG
+printf("BEGIN_CONTOUR_BLACK(%3.1f, %3.1f, %s)\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix, outside? "outside": "inside");
+#endif
+sp_globals.x0_spxl = P1.x;
+sp_globals.y0_spxl = P1.y;
+sp_globals.y_pxl = (sp_globals.y0_spxl + sp_globals.pixrnd) >> sp_globals.pixshift;
+}
+#endif
+
+#if INCL_BLACK
+FUNCTION void line_black(P1)
+GDECL
+point_t P1;
+/* Called for each vector in the transformed character
+ */
+{
+register fix15 how_many_y; /* # of intercepts at y = n + 1/2 */
+register fix15 yc, i; /* Current scan-line */
+ fix15 temp1; /* various uses */
+ fix15 temp2; /* various uses */
+register fix31 dx_dy; /* slope of line in 16.16 form */
+register fix31 xc; /* high-precision (16.16) x coordinate */
+ fix15 x0,y0,x1,y1; /* PIX.FRAC start and endpoints */
+
+x0 = sp_globals.x0_spxl; /* get start of line (== current point) */
+y0 = sp_globals.y0_spxl;
+sp_globals.x0_spxl = x1 = P1.x; /* end of line */
+sp_globals.y0_spxl = y1 = P1.y; /* (also update current point to end of line) */
+
+yc = sp_globals.y_pxl; /* current scan line = end of last line */
+sp_globals.y_pxl = (y1 + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan sp_globals.line */
+
+
+#if DEBUG
+printf("LINE_BLACK(%3.4f, %3.4f)\n",
+ (real)P1.x/(real)sp_globals.onepix,
+ (real)P1.y/(real)sp_globals.onepix);
+#endif
+
+if (sp_globals.extents_running)
+ {
+ if (sp_globals.x0_spxl > sp_globals.bmap_xmax)
+ sp_globals.bmap_xmax = sp_globals.x0_spxl;
+ if (sp_globals.x0_spxl < sp_globals.bmap_xmin)
+ sp_globals.bmap_xmin = sp_globals.x0_spxl;
+ if (sp_globals.y0_spxl > sp_globals.bmap_ymax)
+ sp_globals.bmap_ymax = sp_globals.y0_spxl;
+ if (sp_globals.y0_spxl < sp_globals.bmap_ymin)
+ sp_globals.bmap_ymin = sp_globals.y0_spxl;
+ }
+
+if (sp_globals.intercept_oflo) return;
+
+if ((how_many_y = sp_globals.y_pxl - yc) == 0) return; /* Don't draw a null line */
+
+if (how_many_y < 0) yc--; /* Predecrment downward lines */
+
+if (yc > sp_globals.y_band.band_max) /* Is start point above band? */
+ {
+ if (sp_globals.y_pxl > sp_globals.y_band.band_max) return; /* line has to go down! */
+ how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_max) - 1; /* Yes, limit it */
+ }
+
+if (yc < sp_globals.y_band.band_min) /* Is start point below band? */
+ {
+ if (sp_globals.y_pxl < sp_globals.y_band.band_min) return; /* line has to go up! */
+ how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_min); /* Yes, limit it */
+ }
+
+xc = (fix31)(x0 + sp_globals.pixrnd) << (16 - sp_globals.pixshift); /* Original x coordinate with built in */
+ /* rounding. 16.16 form */
+
+
+if ( (temp1 = (x1 - x0)) == 0) /* check for vertical line */
+ {
+ yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
+ temp1 = (fix15)(xc >> 16);
+ if (how_many_y < 0)
+ { /* Vector down */
+ if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
+ for (i = yc; i >= how_many_y; i--)
+ sp_add_intercept_black(i,temp1);
+ }
+ else
+ { /* Vector up */
+ /* check to see that line doesn't extend beyond top of band */
+ if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
+ for (i = yc; i != how_many_y; i++)
+ sp_add_intercept_black(i,temp1);
+ }
+ return;
+ }
+
+/* calculate dx_dy at 16.16 fixed point */
+
+dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
+
+/* We have to check for a @#$%@# possible multiply overflow */
+/* by doing another @#$*& multiply. In assembly language, */
+/* the program could just check the OVerflow flag or whatever*/
+/* works on the particular processor. This C code is meant */
+/* to be processor independant. */
+
+temp1 = (yc << sp_globals.pixshift) - y0 + sp_globals.pixrnd;
+/* This sees if the sign bits start at bit 15 */
+/* if they do, no overflow has occurred */
+
+temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
+
+if ( (temp2 != (fix15)0xFFFF) &&
+ (temp2 != 0x0000) &&
+ /* Overflow. Pick point closest to yc + .5 */
+ (ABS(temp1) < ABS((yc << sp_globals.pixshift) - y1 + sp_globals.pixrnd)) )
+ { /* use x1 instead of x0 */
+ xc = (fix31)(x1 + sp_globals.pixrnd) << (16 - sp_globals.pixshift);
+ }
+else
+ {
+/* calculate new xc at the center of the *current* scan line */
+/* due to banding, yc may be several lines away from y0 */
+/* xc += (yc + .5 - y0) * dx_dy */
+/* This multiply generates a subpixel delta. */
+/* So we shift it to be a 16.16 delta */
+
+ xc += ((fix31)temp1 * dx_dy) >> sp_globals.pixshift;
+ }
+
+yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
+
+if (how_many_y < 0)
+ { /* Vector down */
+ if (how_many_y == -1)
+ sp_add_intercept_black(yc, (fix15) (xc >> 16));
+ else
+ {
+ if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
+ for (i = yc; i >= how_many_y; i--)
+ {
+ temp1 = (fix15)(xc >> 16);
+ sp_add_intercept_black(i,temp1);
+ xc -= dx_dy;
+ }
+ }
+ }
+ else
+ { /* Vector up */
+ /* check to see that line doesn't extend beyond top of band */
+ if (how_many_y == 1)
+ sp_add_intercept_black(yc, (fix15) (xc >> 16));
+ else
+ {
+ if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
+ for (i = yc; i != how_many_y; i++)
+ {
+ temp1 = (fix15)(xc >> 16);
+ sp_add_intercept_black(i,temp1);
+ xc += dx_dy;
+ }
+ }
+ }
+}
+#endif
+#if INCL_BLACK
+FUNCTION boolean end_char_black()
+GDECL
+/* Called when all character data has been output
+ * Return TRUE if output process is complete
+ * Return FALSE to repeat output of the transformed data beginning
+ * with the first contour
+ */
+{
+
+fix31 xorg;
+fix31 yorg;
+#if INCL_CLIPPING
+fix31 bmap_max, bmap_min;
+#endif
+
+#if DEBUG
+printf("END_CHAR_BLACK()\n");
+#endif
+
+if (sp_globals.first_pass)
+ {
+ if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
+ {
+ sp_globals.xmin = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.xmax = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.xmin = sp_globals.xmax = 0;
+ }
+ if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
+ {
+
+#if INCL_CLIPPING
+ switch(sp_globals.tcb0.xtype)
+ {
+ case 1: /* 180 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.clip_ymin = -1 * sp_globals.clip_ymin;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ sp_globals.clip_xmax = -sp_globals.xmin;
+ sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ case 2: /* 90 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize to x origin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_xmax)
+ sp_globals.xmax = bmap_max;
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+ sp_globals.clip_ymax = 0;
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ /* normalize to x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ break;
+ case 3: /* 270 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+
+ /* let the minimum be the larger of these two values */
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize the x value to new xorgin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+ /* let the max be the lesser of these two values */
+ if (bmap_max < sp_globals.clip_xmax)
+ {
+ sp_globals.xmax = bmap_max;
+ sp_globals.clip_xmax = bmap_max;
+ }
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+
+ /* normalize the x value to new x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ /* compute y clip values */
+ sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = 0;
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ break;
+ default: /* this is for zero degree rotation and arbitrary rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max > sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ sp_globals.clip_ymin = - sp_globals.clip_ymin;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ sp_globals.clip_xmin = -sp_globals.xmin;
+ sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ }
+if ( !(sp_globals.specs.flags & CLIP_TOP))
+#endif
+ sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+#if INCL_CLIPPING
+if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
+#endif
+
+ sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.ymin = sp_globals.ymax = 0;
+ }
+
+ /* add in the rounded out part (from xform.) of the left edge */
+ if (sp_globals.tcb.xmode == 0) /* for X pix is function of X orus only add the round */
+ xorg = (((fix31)sp_globals.xmin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.xmode == 1) /* for X pix is function of -X orus only, subtr. round */
+ xorg = (((fix31)sp_globals.xmin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift)) ;
+ else
+ xorg = (fix31)sp_globals.xmin << 16; /* for other cases don't use round on x */
+
+ if (sp_globals.tcb.ymode == 2) /* for Y pix is function of X orus only, add round error */
+ yorg = (((fix31)sp_globals.ymin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.ymode == 3) /* for Y pix is function of -X orus only, sub round */
+ yorg = (((fix31)sp_globals.ymin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift));
+ else /* all other cases have no round error on yorg */
+ yorg = (fix31)sp_globals.ymin << 16;
+
+ open_bitmap(sp_globals.set_width.x, sp_globals.set_width.y, xorg, yorg,
+ sp_globals.xmax - sp_globals.xmin, sp_globals.ymax - sp_globals.ymin);
+ if (sp_globals.intercept_oflo)
+ {
+ sp_globals.y_band.band_min = sp_globals.ymin;
+ sp_globals.y_band.band_max = sp_globals.ymax;
+ init_intercepts_out();
+ sp_globals.first_pass = FALSE;
+ sp_globals.extents_running = FALSE;
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_black();
+ close_bitmap();
+ return TRUE;
+ }
+ }
+else
+ {
+ if (sp_globals.intercept_oflo)
+ {
+ reduce_band_size_out();
+ init_intercepts_out();
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_black();
+ if (next_band_out())
+ {
+ init_intercepts_out();
+ return FALSE;
+ }
+ close_bitmap();
+ return TRUE;
+ }
+ }
+}
+#endif
+
+#if INCL_BLACK
+FUNCTION LOCAL void sp_add_intercept_black(y, x)
+GDECL
+fix15 y; /* Y coordinate in relative pixel units */
+ /* (0 is lowest sample in band) */
+fix15 x; /* X coordinate of intercept in subpixel units */
+
+/* Called by line() to add an intercept to the intercept list structure
+ */
+
+{
+register fix15 from; /* Insertion pointers for the linked list sort */
+register fix15 to;
+
+#if DEBUG
+printf(" Add intercept(%2d, %d)\n", y + sp_globals.y_band.band_min,x);
+
+/* Bounds checking IS done in debug mode */
+if (y < 0) /* Y value below bottom of current band? */
+ {
+ printf(" Intecerpt less than 0!!!\007\n");
+ return;
+ }
+
+if (y > (sp_globals.no_y_lists - 1)) /* Y value above top of current band? */
+ {
+ printf(" Intercept too big for band!!!!!\007\n");
+ return;
+ }
+#endif
+
+/* Store new values */
+
+sp_intercepts.car[sp_globals.next_offset] = x;
+
+/* Find slot to insert new element (between from and to) */
+
+from = y; /* Start at list head */
+
+while( (to = sp_intercepts.cdr[from]) >= sp_globals.first_offset) /* Until to == end of list */
+ {
+ if (x <= sp_intercepts.car[to]) /* If next item is larger than or same as this one... */
+ goto insert_element; /* ... drop out and insert here */
+ from = to; /* move forward in list */
+ }
+
+insert_element: /* insert element "sp_globals.next_offset" between elements "from" */
+ /* and "to" */
+
+sp_intercepts.cdr[from] = sp_globals.next_offset;
+sp_intercepts.cdr[sp_globals.next_offset] = to;
+
+if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
+ {
+ sp_globals.intercept_oflo = TRUE;
+/* There may be a few more calls to "add_intercept" from the current line */
+/* To avoid problems, we set next_offset to a safe value. We don't care */
+/* if the intercept table gets trashed at this point */
+ sp_globals.next_offset = sp_globals.first_offset;
+ }
+}
+
+#endif
+
+#if INCL_BLACK
+FUNCTION LOCAL void sp_proc_intercepts_black()
+GDECL
+
+/* Called by sp_make_char to output accumulated intercept lists
+ * Clips output to sp_globals.xmin, sp_globals.xmax, sp_globals.ymin, sp_globals.ymax boundaries
+ */
+{
+register fix15 i;
+register fix15 from, to; /* Start and end of run in pixel units
+ relative to left extent of character */
+register fix15 y;
+register fix15 scan_line;
+ fix15 first_y, last_y;
+
+#if DEBUG
+printf("\nIntercept lists:\n");
+#endif
+
+#if INCL_CLIPPING
+if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
+ clipleft = TRUE;
+else
+ clipleft = FALSE;
+if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
+ clipright = TRUE;
+else
+ clipright = FALSE;
+if (clipleft || clipright)
+ {
+ xmax = sp_globals.clip_xmax;
+ xmin = sp_globals.clip_xmin;
+ }
+if (!clipright)
+ xmax = ((sp_globals.set_width.x+32768L) >> 16);
+#endif
+
+if ((first_y = sp_globals.y_band.band_max) >= sp_globals.ymax)
+ first_y = sp_globals.ymax - 1; /* Clip to sp_globals.ymax boundary */
+
+if ((last_y = sp_globals.y_band.band_min) < sp_globals.ymin)
+ last_y = sp_globals.ymin; /* Clip to sp_globals.ymin boundary */
+
+last_y -= sp_globals.y_band.band_min;
+#if DEBUG
+/* Print out all of the intercept info */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
+ from = 0; /* Clip to sp_globals.xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (i == 0) /* End of list? */
+ {
+ printf("****** proc_intercepts: odd number of intercepts\n");
+ break;
+ }
+ if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
+ to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
+ else
+ to -= sp_globals.xmin;
+ printf(" Y = %2d (scanline %2d): %d %d:\n",
+ y + sp_globals.y_band.band_min, scan_line, from, to);
+ }
+ }
+#endif
+
+/* Draw the image */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
+ from = 0; /* Clip to sp_globals.xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+
+ if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
+ to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
+ else
+ to -= sp_globals.xmin;
+ if (from >= to)
+ {
+ if (from >= sp_globals.xmax - sp_globals.xmin)
+ {
+ --from ;
+ }
+ to = from+1;
+ }
+#if INCL_CLIPPING
+ if (clipleft)
+ {
+ if (to <= xmin)
+ continue;
+ if (from < xmin)
+ from = xmin;
+ }
+ if (clipright)
+ {
+ if (from >= xmax)
+ continue;
+ if (to > xmax)
+ to = xmax;
+ }
+#endif
+ set_bitmap_bits(scan_line, from, to);
+ }
+ }
+}
+
+#endif
+
+
+
+
diff --git a/src/Speedo/out_outl.c b/src/Speedo/out_outl.c
new file mode 100644
index 0000000..bebc684
--- /dev/null
+++ b/src/Speedo/out_outl.c
@@ -0,0 +1,287 @@
+/* $Xorg: out_outl.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+/**************************** O U T _ 2 _ 1 . C ******************************
+ * *
+ * This is the standard output module for vector output mode. *
+ * *
+ ****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/* the following macro is used to limit points on the outline to the bounding box */
+
+#define RANGECHECK(value,min,max) (((value) >= (min) ? (value) : (min)) < (max) ? (value) : (max))
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+
+#if INCL_OUTLINE
+FUNCTION boolean init_outline(specsarg)
+GDECL
+specs_t GLOBALFAR *specsarg;
+/*
+ * init_out2() is called by sp_set_specs() to initialize the output module.
+ * Returns TRUE if output module can accept requested specifications.
+ * Returns FALSE otherwise.
+ */
+{
+#if DEBUG
+printf("INIT_OUT_2()\n");
+#endif
+if (specsarg->flags & (CLIP_LEFT + CLIP_RIGHT + CLIP_TOP + CLIP_BOTTOM))
+ return FALSE; /* Clipping not supported */
+return (TRUE);
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION boolean begin_char_outline(Psw, Pmin, Pmax)
+GDECL
+point_t Psw; /* End of escapement vector (sub-pixels) */
+point_t Pmin; /* Bottom left corner of bounding box */
+point_t Pmax; /* Top right corner of bounding box */
+/*
+ * If two or more output modules are included in the configuration, begin_char2()
+ * is called by begin_char() to signal the start of character output data.
+ * If only one output module is included in the configuration, begin_char() is
+ * called by make_simp_char() and make_comp_char().
+ */
+{
+fix31 set_width_x;
+fix31 set_width_y;
+fix31 xmin;
+fix31 xmax;
+fix31 ymin;
+fix31 ymax;
+
+#if DEBUG
+printf("BEGIN_CHAR_2(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)onepix, (real)Psw.y / (real)onepix,
+ (real)Pmin.x / (real)onepix, (real)Pmin.y / (real)onepix,
+ (real)Pmax.x / (real)onepix, (real)Pmax.y / (real)onepix);
+#endif
+sp_globals.poshift = 16 - sp_globals.pixshift;
+set_width_x = (fix31)Psw.x << sp_globals.poshift;
+set_width_y = (fix31)Psw.y << sp_globals.poshift;
+xmin = (fix31)Pmin.x << sp_globals.poshift;
+xmax = (fix31)Pmax.x << sp_globals.poshift;
+ymin = (fix31)Pmin.y << sp_globals.poshift;
+ymax = (fix31)Pmax.y << sp_globals.poshift;
+sp_globals.xmin = Pmin.x;
+sp_globals.xmax = Pmax.x;
+sp_globals.ymin = Pmin.y;
+sp_globals.ymax = Pmax.y;
+open_outline(set_width_x, set_width_y, xmin, xmax, ymin, ymax);
+return TRUE;
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION void begin_sub_char_outline(Psw, Pmin, Pmax)
+GDECL
+point_t Psw; /* End of sub-char escapement vector */
+point_t Pmin; /* Bottom left corner of sub-char bounding box */
+point_t Pmax; /* Top right corner of sub-char bounding box */
+/*
+ * If two or more output modules are included in the configuration, begin_sub_char2()
+ * is called by begin_sub_char() to signal the start of sub-character output data.
+ * If only one output module is included in the configuration, begin_sub_char() is
+ * called by make_comp_char().
+ */
+{
+#if DEBUG
+printf("BEGIN_SUB_CHAR_2(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)onepix, (real)Psw.y / (real)onepix,
+ (real)Pmin.x / (real)onepix, (real)Pmin.y / (real)onepix,
+ (real)Pmax.x / (real)onepix, (real)Pmax.y / (real)onepix);
+#endif
+start_new_char();
+}
+#endif
+
+
+#if INCL_OUTLINE
+FUNCTION void begin_contour_outline(P1, outside)
+GDECL
+point_t P1; /* Start point of contour */
+boolean outside; /* TRUE if outside (counter-clockwise) contour */
+/*
+ * If two or more output modules are included in the configuration, begin_contour2()
+ * is called by begin_contour() to define the start point of a new contour
+ * and to indicate whether it is an outside (counter-clockwise) contour
+ * or an inside (clockwise) contour.
+ * If only one output module is included in the configuration, begin_sub_char() is
+ * called by proc_outl_data().
+ */
+{
+fix15 x,y;
+#if DEBUG
+printf("BEGIN_CONTOUR_2(%3.1f, %3.1f, %s)\n",
+ (real)P1.x / (real)onepix, (real)P1.y / (real)onepix, outside? "outside": "inside");
+#endif
+x = RANGECHECK(P1.x,sp_globals.xmin,sp_globals.xmax);
+y = RANGECHECK(P1.y,sp_globals.ymin,sp_globals.ymax);
+
+start_contour((fix31)x << sp_globals.poshift, (fix31)y << sp_globals.poshift, outside);
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION void curve_outline(P1, P2, P3,depth)
+GDECL
+point_t P1; /* First control point of Bezier curve */
+point_t P2; /* Second control point of Bezier curve */
+point_t P3; /* End point of Bezier curve */
+fix15 depth;
+/*
+ * If two or more output modules are included in the configuration, curve2()
+ * is called by curve() to output one curve segment.
+ * If only one output module is included in the configuration, curve() is
+ * called by proc_outl_data().
+ * This function is only called when curve output is enabled.
+ */
+{
+fix15 x1,y1,x2,y2,x3,y3;
+#if DEBUG
+printf("CURVE_2(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f)\n",
+ (real)P1.x / (real)onepix, (real)P1.y / (real)onepix,
+ (real)P2.x / (real)onepix, (real)P2.y / (real)onepix,
+ (real)P3.x / (real)onepix, (real)P3.y / (real)onepix);
+#endif
+x1= RANGECHECK(P1.x,sp_globals.xmin,sp_globals.xmax);
+y1= RANGECHECK(P1.y,sp_globals.ymin,sp_globals.ymax);
+
+x2= RANGECHECK(P2.x,sp_globals.xmin,sp_globals.xmax);
+y2= RANGECHECK(P2.y,sp_globals.ymin,sp_globals.ymax);
+
+x3= RANGECHECK(P3.x,sp_globals.xmin,sp_globals.xmax);
+y3= RANGECHECK(P3.y,sp_globals.ymin,sp_globals.ymax);
+
+curve_to((fix31)x1 << sp_globals.poshift, (fix31)y1 << sp_globals.poshift,
+ (fix31)x2<< sp_globals.poshift, (fix31)y2 << sp_globals.poshift,
+ (fix31)x3 << sp_globals.poshift, (fix31)y3 << sp_globals.poshift);
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION void line_outline(P1)
+GDECL
+point_t P1; /* End point of vector */
+/*
+ * If two or more output modules are included in the configuration, line2()
+ * is called by line() to output one vector.
+ * If only one output module is included in the configuration, line() is
+ * called by proc_outl_data(). If curve output is enabled, line() is also
+ * called by split_curve().
+ */
+{
+fix15 x1,y1;
+#if DEBUG
+printf("LINE_2(%3.1f, %3.1f)\n", (real)P1.x / (real)onepix, (real)P1.y / (real)onepix);
+#endif
+x1= RANGECHECK(P1.x,sp_globals.xmin,sp_globals.xmax);
+y1= RANGECHECK(P1.y,sp_globals.ymin,sp_globals.ymax);
+
+line_to((fix31)x1 << sp_globals.poshift, (fix31)y1 << sp_globals.poshift);
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION void end_contour_outline()
+GDECL
+/*
+ * If two or more output modules are included in the configuration, end_contour2()
+ * is called by end_contour() to signal the end of a contour.
+ * If only one output module is included in the configuration, end_contour() is
+ * called by proc_outl_data().
+ */
+{
+#if DEBUG
+printf("END_CONTOUR_2()\n");
+#endif
+close_contour();
+}
+#endif
+
+
+#if INCL_OUTLINE
+FUNCTION void end_sub_char_outline()
+GDECL
+/*
+ * If two or more output modules are included in the configuration, end_sub_char2()
+ * is called by end_sub_char() to signal the end of sub-character data.
+ * If only one output module is included in the configuration, end_sub_char() is
+ * called by make_comp_char().
+ */
+{
+#if DEBUG
+printf("END_SUB_CHAR_2()\n");
+#endif
+}
+#endif
+
+
+#if INCL_OUTLINE
+FUNCTION boolean end_char_outline()
+GDECL
+/*
+ * If two or more output modules are included in the configuration, end_char2()
+ * is called by end_char() to signal the end of the character data.
+ * If only one output module is included in the configuration, end_char() is
+ * called by make_simp_char() and make_comp_char().
+ * Returns TRUE if output process is complete
+ * Returns FALSE to repeat output of the transformed data beginning
+ * with the first contour (of the first sub-char if compound).
+ */
+{
+#if DEBUG
+printf("END_CHAR_2()\n");
+#endif
+close_outline();
+return TRUE;
+}
+#endif
+
diff --git a/src/Speedo/out_scrn.c b/src/Speedo/out_scrn.c
new file mode 100644
index 0000000..3d04db6
--- /dev/null
+++ b/src/Speedo/out_scrn.c
@@ -0,0 +1,1091 @@
+/* $Xorg: out_scrn.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+/*************************** O U T _ S C R N . C *****************************
+ * *
+ * This is an output module for screen-writer mode. *
+ * *
+ *****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+#define LOCAL static
+#define ABS(X) ( (X < 0) ? -X : X)
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static void sp_add_intercept_screen(PROTO_DECL2 fix15 y,fix31 x);
+static void sp_proc_intercepts_screen(PROTO_DECL1);
+#else
+static void sp_add_intercept_screen();
+static void sp_proc_intercepts_screen();
+#endif
+
+
+#if INCL_SCREEN
+FUNCTION boolean init_screen(specsarg)
+GDECL
+specs_t FONTFAR *specsarg;
+/*
+ * init_out0() is called by sp_set_specs() to initialize the output module.
+ * Returns TRUE if output module can accept requested specifications.
+ * Returns FALSE otherwise.
+ */
+{
+#if DEBUG
+printf("INIT_SCREEN()\n");
+#endif
+return (TRUE);
+}
+#endif
+
+
+#if INCL_SCREEN
+FUNCTION boolean begin_char_screen(Psw, Pmin, Pmax)
+GDECL
+point_t Psw;
+point_t Pmin;
+point_t Pmax;
+/* Called once at the start of the character generation process
+ */
+{
+#if DEBUG
+printf("BEGIN_CHAR_SCREEN(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
+ (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
+ (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
+#endif
+if (sp_globals.pixshift > 8)
+ sp_intercepts.fracpix = sp_globals.onepix << (8 - sp_globals.pixshift);
+else
+ sp_intercepts.fracpix = sp_globals.onepix >> (sp_globals.pixshift - 8);
+
+init_char_out(Psw,Pmin,Pmax);
+
+return TRUE;
+}
+#endif
+
+
+#if INCL_SCREEN
+FUNCTION void begin_contour_screen(P1, outside)
+GDECL
+point_t P1;
+boolean outside;
+/* Called at the start of each contour
+ */
+{
+
+#if DEBUG
+printf("BEGIN_CONTOUR_SCREEN(%3.1f, %3.1f, %s)\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix, outside? "outside": "inside");
+#endif
+sp_globals.x0_spxl = P1.x;
+sp_globals.y0_spxl = P1.y;
+sp_globals.y_pxl = (sp_globals.y0_spxl + sp_globals.pixrnd) >> sp_globals.pixshift;
+}
+#endif
+
+#if INCL_SCREEN
+FUNCTION void curve_screen(P1, P2, P3, depth)
+GDECL
+point_t P1, P2, P3;
+fix15 depth;
+{
+fix31 X0;
+fix31 Y0;
+fix31 X1;
+fix31 Y1;
+fix31 X2;
+fix31 Y2;
+fix31 X3;
+fix31 Y3;
+#if DEBUG
+printf("CURVE_SCREEN(%6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f)\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
+ (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
+ (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix);
+#endif
+
+
+if (sp_globals.extents_running) /* Accumulate actual character extents if required */
+ {
+ if (P3.x > sp_globals.bmap_xmax)
+ sp_globals.bmap_xmax = P3.x;
+ if (P3.x < sp_globals.bmap_xmin)
+ sp_globals.bmap_xmin = P3.x;
+ if (P3.y > sp_globals.bmap_ymax)
+ sp_globals.bmap_ymax = P3.y;
+ if (P3.y < sp_globals.bmap_ymin)
+ sp_globals.bmap_ymin = P3.y;
+ }
+
+X0 = ((fix31)sp_globals.x0_spxl << sp_globals.poshift) + (fix31)32768;
+Y0 = ((fix31)sp_globals.y0_spxl << sp_globals.poshift) + (fix31)32768;
+X1 = ((fix31)P1.x << sp_globals.poshift) + (fix31)32768;
+Y1 = ((fix31)P1.y << sp_globals.poshift) + (fix31)32768;
+X2 = ((fix31)P2.x << sp_globals.poshift) + (fix31)32768;
+Y2 = ((fix31)P2.y << sp_globals.poshift) + (fix31)32768;
+X3 = ((fix31)P3.x << sp_globals.poshift) + (fix31)32768;
+Y3 = ((fix31)P3.y << sp_globals.poshift) + (fix31)32768;
+
+if (((Y0 - Y3) * sp_globals.tcb.mirror) > 0)
+ {
+ sp_intercepts.leftedge = LEFT_INT;
+ }
+else
+ {
+ sp_intercepts.leftedge = 0;
+ }
+
+scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3);
+sp_globals.x0_spxl = P3.x;
+sp_globals.y0_spxl = P3.y;
+sp_globals.y_pxl = (P3.y + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan sp_globals.line */
+}
+
+FUNCTION void scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3)
+GDECL
+fix31 X0,Y0,X1,Y1,X2,Y2,X3,Y3;
+/* Called for each curve in the transformed character if curves out enabled
+ */
+{
+fix31 Pmidx;
+fix31 Pmidy;
+fix31 Pctrl1x;
+fix31 Pctrl1y;
+fix31 Pctrl2x;
+fix31 Pctrl2y;
+
+#if DBGCRV
+printf("SCAN_CURVE_SCREEN(%6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f, %6.4f)\n",
+ (real)(X0-32768) / 65536.0, (real)(Y0-32768) / 65536.0,
+ (real)(X1-32768) / 65536.0, (real)(Y1-32768) / 65536.0,
+ (real)(X2-32768) / 65536.0, (real)(Y2-32768) / 65536.0,
+ (real)(X3-32768) / 65536.0, (real)(Y3-32768) / 65536.0);
+#endif
+
+if (((Y3 >> 16)) == (Y0 >> 16) || (Y3+1) == Y0 || Y3 == (Y0+1))
+ {
+ return;
+ }
+if ((X3 >> 16) == (X0 >> 16))
+ {
+ vert_line_screen(X3,(Y0>>16),(Y3>>16));
+ return;
+ }
+Pmidx = (X0 + (X1 + X2) * 3 + X3 + 4 ) >> 3;
+Pmidy = (Y0 + (Y1 + Y2) * 3 + Y3 + 4 ) >> 3;
+
+Pctrl1x = (X0 + X1 + 1 ) >> 1;
+Pctrl1y = (Y0 + Y1 + 1) >> 1;
+Pctrl2x = (X0 + (X1 << 1) + X2 + 2 ) >> 2;
+Pctrl2y = (Y0 + (Y1 << 1) + Y2 + 2 ) >> 2;
+scan_curve_screen(X0,Y0, Pctrl1x, Pctrl1y, Pctrl2x,Pctrl2y, Pmidx,Pmidy);
+
+Pctrl1x = (X1 + (X2 << 1) + X3 + 2 ) >> 2;
+Pctrl1y = (Y1 + (Y2 << 1) + Y3 + 2 ) >> 2;
+Pctrl2x = (X2 + X3 + 1 ) >> 1;
+Pctrl2y = (Y2 + Y3 + 1 ) >> 1;
+scan_curve_screen(Pmidx,Pmidy, Pctrl1x,Pctrl1y, Pctrl2x,Pctrl2y, X3,Y3);
+}
+
+FUNCTION void vert_line_screen(x,y1,y2)
+GDECL
+fix31 x;
+fix15 y1, y2;
+{
+
+#if DBGCRV
+printf("VERT_LINE_SCREEN(%6.4f, %6.4f, %6.4f)\n",
+ (real)(x - 32768) / 65536.0,
+ (real)(y1 - 32768) / 65536.0,
+ (real)(y2 - 32768) / 65536.0);
+#endif
+
+if (sp_globals.intercept_oflo)
+ return;
+
+if (y1 > y2) /* Line goes downwards ? */
+ {
+ if (y1 > (sp_globals.y_band.band_max + 1)) /* Start point above top of band? */
+ y1 = sp_globals.y_band.band_max + 1; /* Adjust start point to top of band */
+ if (y2 < sp_globals.y_band.band_min) /* End point below bottom of band? */
+ y2 = sp_globals.y_band.band_min; /* Adjust end point bottom of band */
+
+ y1 -= sp_globals.y_band.band_min; /* Translate start point to band origin */
+ y2 -= sp_globals.y_band.band_min; /* Translate end point to band origin */
+
+ while (y2 < y1) /* At least one intercept left? */
+ {
+ sp_add_intercept_screen(--y1, x); /* Add intercept */
+ }
+ }
+else if (y2 > y1) /* Line goes upwards ? */
+ {
+ if (y1 < sp_globals.y_band.band_min) /* Start point below bottom of band? */
+ y1 = sp_globals.y_band.band_min; /* Adjust start point to bottom of band */
+ if (y2 > (sp_globals.y_band.band_max + 1)) /* End point above top of band? */
+ y2 = sp_globals.y_band.band_max + 1; /* Adjust end point to top of band */
+
+ y1 -= sp_globals.y_band.band_min; /* Translate start point to band origin */
+ y2 -= sp_globals.y_band.band_min; /* Translate end point to band origin */
+
+ while (y1 < y2) /* At least one intercept left? */
+ {
+ sp_add_intercept_screen(y1++, x); /* Add intercept */
+ }
+ }
+
+
+}
+
+#endif
+
+
+#if INCL_SCREEN
+FUNCTION void line_screen(P1)
+GDECL
+point_t P1;
+/* Called for each vector in the transformed character
+ */
+{
+register fix15 how_many_y; /* # of intercepts at y = n + 1/2 */
+register fix15 yc; /* Current scan-line */
+ fix15 temp1; /* various uses */
+ fix15 temp2; /* various uses */
+register fix31 dx_dy; /* slope of line in 16.16 form */
+register fix31 xc; /* high-precision (16.16) x coordinate */
+ fix15 x0,y0,x1,y1; /* PIX.FRAC start and endpoints */
+
+x0 = sp_globals.x0_spxl; /* get start of line (== current point) */
+y0 = sp_globals.y0_spxl;
+sp_globals.x0_spxl = x1 = P1.x; /* end of line */
+sp_globals.y0_spxl = y1 = P1.y; /* (also update current point to end of line) */
+
+yc = sp_globals.y_pxl; /* current scan line = end of last line */
+sp_globals.y_pxl = (y1 + sp_globals.pixrnd) >> sp_globals.pixshift; /* calculate new end-scan sp_globals.line */
+
+
+#if DEBUG
+printf("LINE_SCREEN(%3.4f, %3.4f)\n",
+ (real)P1.x/(real)sp_globals.onepix,
+ (real)P1.y/(real)sp_globals.onepix);
+#endif
+
+if (sp_globals.extents_running)
+ {
+ if (sp_globals.x0_spxl > sp_globals.bmap_xmax)
+ sp_globals.bmap_xmax = sp_globals.x0_spxl;
+ if (sp_globals.x0_spxl < sp_globals.bmap_xmin)
+ sp_globals.bmap_xmin = sp_globals.x0_spxl;
+ if (sp_globals.y0_spxl > sp_globals.bmap_ymax)
+ sp_globals.bmap_ymax = sp_globals.y0_spxl;
+ if (sp_globals.y0_spxl < sp_globals.bmap_ymin)
+ sp_globals.bmap_ymin = sp_globals.y0_spxl;
+ }
+
+if (sp_globals.intercept_oflo) return;
+
+if ((how_many_y = sp_globals.y_pxl - yc) == 0) return; /* Don't draw a null line */
+
+xc = (fix31)(x0 + sp_globals.pixrnd) << (16 - sp_globals.pixshift); /* Original x coordinate with built in */
+ /* rounding. 16.16 form */
+
+if (how_many_y < 0)
+ {
+ yc--; /* Predecrment downward lines */
+ }
+
+if ((how_many_y * sp_globals.tcb.mirror) < 0)
+ {
+ sp_intercepts.leftedge = LEFT_INT;
+ }
+else
+ {
+ sp_intercepts.leftedge = 0;
+ }
+
+if (yc > sp_globals.y_band.band_max) /* Is start point above band? */
+ {
+ if (sp_globals.y_pxl > sp_globals.y_band.band_max) return; /* line has to go down! */
+ how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_max) - 1; /* Yes, limit it */
+ }
+
+if (yc < sp_globals.y_band.band_min) /* Is start point below band? */
+ {
+ if (sp_globals.y_pxl < sp_globals.y_band.band_min) return; /* line has to go up! */
+ how_many_y = sp_globals.y_pxl - (yc = sp_globals.y_band.band_min); /* Yes, limit it */
+ }
+
+if ( (temp1 = (x1 - x0)) == 0) /* check for vertical line */
+ {
+ dx_dy = 0L; /* Zero slope, leave xc alone */
+ goto skip_calc;
+ }
+
+/* calculate dx_dy at 16.16 fixed point */
+
+dx_dy = ( (fix31)temp1 << 16 )/(fix31)(y1 - y0);
+
+/* We have to check for a @#$%@# possible multiply overflow */
+/* by doing another @#$*& multiply. In assembly language, */
+/* the program could just check the OVerflow flag or whatever*/
+/* works on the particular processor. This C code is meant */
+/* to be processor independant. */
+
+temp1 = (yc << sp_globals.pixshift) - y0 + sp_globals.pixrnd;
+/* This sees if the sign bits start at bit 15 */
+/* if they do, no overflow has occurred */
+
+temp2 = (fix15)(MULT16(temp1,(fix15)(dx_dy >> 16)) >> 15);
+
+if ( (temp2 != (fix15)-1) &&
+ (temp2 != 0x0000) )
+ { /* Overflow. Pick point closest to yc + .5 */
+ if (ABS(temp1) < ABS((yc << sp_globals.pixshift) - y1 + sp_globals.pixrnd))
+ { /* use x1 instead of x0 */
+ xc = (fix31)(x1 + sp_globals.pixrnd) << (16 - sp_globals.pixshift);
+ }
+ goto skip_calc;
+ }
+/* calculate new xc at the center of the *current* scan line */
+/* due to banding, yc may be several lines away from y0 */
+/* xc += (yc + .5 - y0) * dx_dy */
+/* This multiply generates a subpixel delta. */
+/* So we shift it to be a 16.16 delta */
+
+xc += ((fix31)temp1 * dx_dy) >> sp_globals.pixshift;
+
+skip_calc:
+
+yc -= sp_globals.y_band.band_min; /* yc is now an offset relative to the band */
+
+if (how_many_y < 0)
+ { /* Vector down */
+ if ((how_many_y += yc + 1) < 0) how_many_y = 0; /* can't go below 0 */
+ while(yc >= how_many_y)
+ {
+ sp_add_intercept_screen(yc--,xc);
+ xc -= dx_dy;
+ }
+ }
+ else
+ { /* Vector up */
+ /* check to see that line doesn't extend beyond top of band */
+ if ((how_many_y += yc) > sp_globals.no_y_lists) how_many_y = sp_globals.no_y_lists;
+ while(yc != how_many_y)
+ {
+ sp_add_intercept_screen(yc++,xc);
+ xc += dx_dy;
+ }
+ }
+}
+#endif
+
+#if INCL_SCREEN
+FUNCTION void end_contour_screen()
+GDECL
+/* Called after the last vector in each contour
+ */
+{
+#if DEBUG
+printf("END_CONTOUR_SCREEN()\n");
+#endif
+sp_intercepts.inttype[sp_globals.next_offset-1] |= END_INT;
+}
+#endif
+
+
+
+#if INCL_SCREEN
+FUNCTION boolean end_char_screen()
+GDECL
+/* Called when all character data has been output
+ * Return TRUE if output process is complete
+ * Return FALSE to repeat output of the transformed data beginning
+ * with the first contour
+ */
+{
+
+fix31 xorg;
+fix31 yorg;
+
+#if INCL_CLIPPING
+fix31 em_max, em_min, bmap_max, bmap_min;
+#endif
+
+#if DEBUG
+printf("END_CHAR_SCREEN()\n");
+#endif
+
+if (sp_globals.first_pass)
+ {
+ if (sp_globals.bmap_xmax >= sp_globals.bmap_xmin)
+ {
+ sp_globals.xmin = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.xmax = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.xmin = sp_globals.xmax = 0;
+ }
+ if (sp_globals.bmap_ymax >= sp_globals.bmap_ymin)
+ {
+
+#if INCL_CLIPPING
+ switch(sp_globals.tcb0.xtype)
+ {
+ case 1: /* 180 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ sp_globals.clip_ymin = -1 * sp_globals.clip_ymin;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ sp_globals.clip_xmax = -sp_globals.xmin;
+ sp_globals.clip_xmin = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ case 2: /* 90 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize to x origin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max < sp_globals.clip_xmax)
+ sp_globals.xmax = bmap_max;
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+ sp_globals.clip_ymax = 0;
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ /* normalize to x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ break;
+ case 3: /* 270 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_xmin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmin = sp_globals.clip_xmin >> sp_globals.multshift;
+ sp_globals.clip_xmin = -1 * sp_globals.clip_xmin;
+ bmap_min = (sp_globals.bmap_xmin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+
+ /* let the minimum be the larger of these two values */
+ if (bmap_min > sp_globals.clip_xmin)
+ sp_globals.clip_xmin = bmap_min;
+
+ /* normalize the x value to new xorgin */
+ sp_globals.clip_xmin -= sp_globals.xmin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_xmax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_xmax = sp_globals.clip_xmax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_xmax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+ /* let the max be the lesser of these two values */
+ if (bmap_max < sp_globals.clip_xmax)
+ {
+ sp_globals.xmax = bmap_max;
+ sp_globals.clip_xmax = bmap_max;
+ }
+ else
+ sp_globals.xmax = sp_globals.clip_xmax;
+
+ /* normalize the x value to new x origin */
+ sp_globals.clip_xmax -= sp_globals.xmin;
+ }
+ /* compute y clip values */
+ sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = 0;
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ break;
+ default: /* this is for zero degree rotation and arbitrary rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ bmap_max = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+ if (bmap_max > sp_globals.clip_ymax)
+ sp_globals.ymax = bmap_max;
+ else
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ sp_globals.clip_ymin = - sp_globals.clip_ymin;
+ bmap_min = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ if (bmap_min < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ else
+ sp_globals.ymin = bmap_min;
+ }
+ sp_globals.clip_xmin = -sp_globals.xmin;
+ sp_globals.clip_xmax = ((sp_globals.set_width.x+32768L) >> 16) -
+ sp_globals.xmin;
+ break;
+ }
+if ( !(sp_globals.specs.flags & CLIP_TOP))
+#endif
+ sp_globals.ymax = (sp_globals.bmap_ymax + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+#if INCL_CLIPPING
+if ( !(sp_globals.specs.flags & CLIP_BOTTOM))
+#endif
+
+ sp_globals.ymin = (sp_globals.bmap_ymin + sp_globals.pixrnd + 1) >> sp_globals.pixshift;
+ }
+ else
+ {
+ sp_globals.ymin = sp_globals.ymax = 0;
+ }
+
+ /* add in the rounded out part (from xform.) of the left edge */
+ if (sp_globals.tcb.xmode == 0) /* for X pix is function of X orus only add the round */
+ xorg = (((fix31)sp_globals.xmin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.xmode == 1) /* for X pix is function of -X orus only, subtr. round */
+ xorg = (((fix31)sp_globals.xmin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift)) ;
+ else
+ xorg = (fix31)sp_globals.xmin << 16; /* for other cases don't use round on x */
+
+ if (sp_globals.tcb.ymode == 2) /* for Y pix is function of X orus only, add round error */
+ yorg = (((fix31)sp_globals.ymin << 16) + (sp_globals.rnd_xmin << sp_globals.poshift));
+ else
+ if (sp_globals.tcb.ymode == 3) /* for Y pix is function of -X orus only, sub round */
+ yorg = (((fix31)sp_globals.ymin << 16) - (sp_globals.rnd_xmin << sp_globals.poshift));
+ else /* all other cases have no round error on yorg */
+ yorg = (fix31)sp_globals.ymin << 16;
+
+ open_bitmap(sp_globals.set_width.x, sp_globals.set_width.y, xorg, yorg,
+ sp_globals.xmax - sp_globals.xmin, sp_globals.ymax - sp_globals.ymin);
+ if (sp_globals.intercept_oflo)
+ {
+ sp_globals.y_band.band_min = sp_globals.ymin;
+ sp_globals.y_band.band_max = sp_globals.ymax;
+ init_intercepts_out();
+ sp_globals.first_pass = FALSE;
+ sp_globals.extents_running = FALSE;
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_screen();
+ close_bitmap();
+ return TRUE;
+ }
+ }
+else
+ {
+ if (sp_globals.intercept_oflo)
+ {
+ reduce_band_size_out();
+ init_intercepts_out();
+ return FALSE;
+ }
+ else
+ {
+ sp_proc_intercepts_screen();
+ if (next_band_out())
+ {
+ init_intercepts_out();
+ return FALSE;
+ }
+ close_bitmap();
+ return TRUE;
+ }
+ }
+}
+#endif
+
+#if INCL_SCREEN
+FUNCTION LOCAL void sp_add_intercept_screen(y, x)
+GDECL
+fix15 y; /* Y coordinate in relative pixel units */
+ /* (0 is lowest sample in band) */
+fix31 x; /* X coordinate of intercept in subpixel units */
+
+/* Called by line() to add an intercept to the intercept list structure
+ */
+
+{
+register fix15 from; /* Insertion pointers for the linked list sort */
+register fix15 to;
+register fix15 xloc;
+register fix15 xfrac;
+
+#if DEBUG
+printf(" Add intercept(%2d, %x)\n", y + sp_globals.y_band.band_min, x);
+
+/* Bounds checking IS done in debug mode */
+if (y < 0) /* Y value below bottom of current band? */
+ {
+ printf(" Intecerpt less than 0!!!\007\n");
+ return;
+ }
+
+if (y > (sp_globals.no_y_lists - 1)) /* Y value above top of current band? */
+ {
+ printf(" Intercept too big for band!!!!!\007\n");
+ return;
+ }
+#endif
+
+/* Store new values */
+
+sp_intercepts.car[sp_globals.next_offset] = xloc = (fix15)(x >> 16);
+sp_intercepts.inttype[sp_globals.next_offset] = sp_intercepts.leftedge | (xfrac = ((x >> 8) & FRACTION));
+
+/* Find slot to insert new element (between from and to) */
+
+from = y; /* Start at list head */
+
+while( (to = sp_intercepts.cdr[from]) != 0) /* Until to == end of list */
+ {
+ if (xloc < sp_intercepts.car[to]) /* If next item is larger than or same as this one... */
+ goto insert_element; /* ... drop out and insert here */
+ else if (xloc == sp_intercepts.car[to] && xfrac < (sp_intercepts.inttype[to] & FRACTION))
+ goto insert_element; /* ... drop out and insert here */
+ from = to; /* move forward in list */
+ }
+
+insert_element: /* insert element "sp_globals.next_offset" between elements "from" */
+ /* and "to" */
+
+sp_intercepts.cdr[from] = sp_globals.next_offset;
+sp_intercepts.cdr[sp_globals.next_offset] = to;
+
+if (++sp_globals.next_offset >= MAX_INTERCEPTS) /* Intercept buffer full? */
+ {
+ sp_globals.intercept_oflo = TRUE;
+/* There may be a few more calls to "add_intercept" from the current line */
+/* To avoid problems, we set next_offset to a safe value. We don't care */
+/* if the intercept table gets trashed at this point */
+ sp_globals.next_offset = sp_globals.first_offset;
+ }
+}
+
+#endif
+
+#if INCL_SCREEN
+FUNCTION LOCAL void sp_proc_intercepts_screen()
+GDECL
+
+/* Called by sp_make_char to output accumulated intercept lists
+ * Clips output to sp_globals.xmin, sp_globals.xmax, sp_globals.ymin, sp_globals.ymax boundaries
+ */
+{
+register fix15 i,j, jplus1, iminus1;
+fix15 k,nextk, previ;
+register fix15 from, to; /* Start and end of run in pixel units
+ relative to left extent of character */
+register fix15 y;
+register fix15 scan_line;
+ fix15 first_y, last_y;
+ fix15 xsave;
+
+
+fix15 diff;
+
+#if DEBUG
+printf("\nPROC_INTERCEPTS_SCREEN: Intercept lists before:\n");
+#endif
+
+#if INCL_CLIPPING
+if ((sp_globals.specs.flags & CLIP_LEFT) != 0)
+ clipleft = TRUE;
+else
+ clipleft = FALSE;
+if ((sp_globals.specs.flags & CLIP_RIGHT) != 0)
+ clipright = TRUE;
+else
+ clipright = FALSE;
+if (clipleft || clipright)
+ {
+ xmax = sp_globals.clip_xmax + sp_globals.xmin;
+ xmin = sp_globals.clip_xmin + sp_globals.xmin;
+ }
+if (!clipright)
+ xmax = ((sp_globals.set_width.x+32768L) >> 16);
+#endif
+
+if ((first_y = sp_globals.y_band.band_max) >= sp_globals.ymax)
+ first_y = sp_globals.ymax - 1; /* Clip to sp_globals.ymax boundary */
+
+if ((last_y = sp_globals.y_band.band_min) < sp_globals.ymin)
+ last_y = sp_globals.ymin; /* Clip to sp_globals.ymin boundary */
+
+last_y -= sp_globals.y_band.band_min;
+
+#if DEBUG
+/* Print out all of the intercept info */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
+ from = 0; /* Clip to sp_globals.xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (i == 0) /* End of list? */
+ {
+ printf("****** proc_intercepts: odd number of intercepts\n");
+ break;
+ }
+ if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
+ to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
+ else
+ to -= sp_globals.xmin;
+ printf(" Y = %2d (scanline %2d): %d %d:\n",
+ y + sp_globals.y_band.band_min, scan_line, from, to);
+ }
+ }
+#endif
+
+/* CHECK INTERCEPT LIST FOR DROPOUT AND WINDING, FIX IF NECESSARY */
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--)
+ {
+ previ = y;
+ i = sp_intercepts.cdr[y]; /* Index head of intercept list */
+ while (i != 0) /* Link to next intercept if present */
+ {
+ j = i;
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (sp_intercepts.inttype[i] & LEFT_INT)
+ {
+ if (sp_intercepts.inttype[j] & LEFT_INT)
+ {
+ do { i = sp_intercepts.cdr[i]; } while (sp_intercepts.inttype[i] & LEFT_INT);
+ do { i = sp_intercepts.cdr[i]; } while (sp_intercepts.cdr[i] && !(sp_intercepts.inttype[sp_intercepts.cdr[i]] & LEFT_INT));
+ sp_intercepts.cdr[j] = i;
+ }
+ else
+ {
+ xsave = sp_intercepts.car[j];
+ sp_intercepts.car[j] = sp_intercepts.car[i];
+ sp_intercepts.car[i] = xsave;
+
+ xsave = sp_intercepts.inttype[j];
+ sp_intercepts.inttype[j] = sp_intercepts.inttype[i] & FRACTION;
+ sp_intercepts.inttype[i] = xsave | LEFT_INT;
+
+ sp_intercepts.cdr[previ] = i;
+ sp_intercepts.cdr[j] = sp_intercepts.cdr[i];
+ sp_intercepts.cdr[i] = j;
+ i = j;
+ j = sp_intercepts.cdr[previ];
+ }
+ }
+
+ if (sp_intercepts.car[j] < sp_globals.xmin)
+ sp_intercepts.car[j] = sp_globals.xmin; /* Clip to sp_globals.xmin boundary */
+
+ if (sp_intercepts.car[i] > sp_globals.xmax)
+ sp_intercepts.car[i] = sp_globals.xmax;
+
+ if (sp_intercepts.car[j] >= sp_intercepts.car[i])
+ {
+ if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i] & FRACTION) > sp_intercepts.fracpix)
+ ++sp_intercepts.car[i];
+ else
+ --sp_intercepts.car[j];
+ }
+ if (sp_globals.first_pass)
+ {
+ if (sp_intercepts.inttype[i-1] & END_INT)
+ {
+ for (iminus1 = i+1; !(sp_intercepts.inttype[iminus1] & END_INT); iminus1++)
+ ;
+ }
+ else
+ iminus1 = i-1;
+
+ if (sp_intercepts.inttype[j] & END_INT)
+ {
+ for (jplus1 = j-1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1--)
+ ;
+ jplus1++;
+ }
+ else
+ jplus1 = j+1;
+
+ if ((sp_intercepts.inttype[iminus1] & LEFT_INT))
+ {
+ if ( sp_intercepts.car[jplus1] > sp_intercepts.car[i])
+ {
+ diff = sp_intercepts.car[jplus1] - sp_intercepts.car[i];
+ sp_intercepts.car[i] += diff/2;
+ sp_intercepts.car[jplus1] -= diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[i] ++;
+ else
+ sp_intercepts.car[jplus1]--;
+ }
+ }
+ }
+ else if (!(sp_intercepts.inttype[jplus1] & LEFT_INT))
+ {
+ if (sp_intercepts.car[iminus1] < sp_intercepts.car[j])
+ {
+ diff = sp_intercepts.car[j] - sp_intercepts.car[iminus1];
+ sp_intercepts.car[j] -= diff/2;
+ sp_intercepts.car[iminus1] += diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) +
+ (ufix16)(sp_intercepts.inttype[iminus1] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[iminus1]++;
+ else
+ sp_intercepts.car[j]--;
+ }
+ }
+ }
+ if (sp_globals.tcb.mirror == -1)
+ {
+ if (sp_intercepts.inttype[j-1] & END_INT)
+ {
+ for (jplus1 = j+1; !(sp_intercepts.inttype[jplus1] & END_INT); jplus1++)
+ ;
+ }
+ else
+ {
+ jplus1 = j-1;
+ }
+ }
+
+ if (!(sp_intercepts.inttype[jplus1] & LEFT_INT) &&
+ sp_intercepts.car[j] > sp_intercepts.car[jplus1])
+ {
+ k = sp_intercepts.cdr[y - 1];
+ while (k > 0)
+ {
+ nextk = sp_intercepts.cdr[k];
+ if (!(sp_intercepts.inttype[k] & LEFT_INT) &&
+ (sp_intercepts.inttype[nextk] & LEFT_INT) &&
+ sp_intercepts.car[nextk] > sp_intercepts.car[jplus1])
+ {
+ if ((diff=sp_intercepts.car[j] - sp_intercepts.car[k]) > 0)
+ {
+ if (diff <= (sp_intercepts.car[nextk] - sp_intercepts.car[jplus1]))
+ {
+ sp_intercepts.car[j] -= diff/2;
+ sp_intercepts.car[k] += diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) +
+ (ufix16)(sp_intercepts.inttype[k] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[j]--;
+ else
+ sp_intercepts.car[k]++;
+ }
+ }
+ else
+ {
+ diff = sp_intercepts.car[nextk] - sp_intercepts.car[jplus1];
+ sp_intercepts.car[nextk] -= diff/2;
+ sp_intercepts.car[jplus1] += diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[jplus1] & FRACTION) +
+ (ufix16)(sp_intercepts.inttype[nextk] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[nextk]--;
+ else
+ sp_intercepts.car[jplus1]++;
+ }
+ }
+ }
+ break;
+ }
+ k = nextk;
+ }
+ }
+ if (j > 0 && sp_intercepts.car[j-1] > sp_intercepts.car[i] && !(sp_intercepts.inttype[j-1] & END_INT))
+ {
+ diff = sp_intercepts.car[j-1] - sp_intercepts.car[i];
+ sp_intercepts.car[i] += diff/2;
+ sp_intercepts.car[j-1] -= diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[i] & FRACTION) + (ufix16)(sp_intercepts.inttype[j-1] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[i]++;
+ else
+ sp_intercepts.car[j-1]--;
+ }
+ }
+ if (sp_intercepts.car[i+1] < sp_intercepts.car[j] && !(sp_intercepts.inttype[i] & END_INT))
+ {
+ diff = sp_intercepts.car[j] - sp_intercepts.car[i+1];
+ sp_intercepts.car[j] -= diff/2;
+ sp_intercepts.car[i+1] += diff/2;
+ if (diff & 1)
+ {
+ if ((ufix16)(sp_intercepts.inttype[j] & FRACTION) + (ufix16)(sp_intercepts.inttype[i+1] & FRACTION) > sp_intercepts.fracpix)
+ sp_intercepts.car[i+1]++;
+ else
+ sp_intercepts.car[j]--;
+ }
+
+ }
+ previ = i;
+ }
+ i = sp_intercepts.cdr[i];
+ }
+ }
+
+#if DEBUG
+printf("\nPROC_INTERCEPTS_SCREEN: Intercept lists after:\n");
+/* Print out all of the intercept info */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = y; /* Index head of intercept list */
+ while ((i = sp_intercepts.cdr[i]) != 0) /* Link to next intercept if present */
+ {
+ if ((from = sp_intercepts.car[i] - sp_globals.xmin) < 0)
+ from = 0; /* Clip to sp_globals.xmin boundary */
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ if (i == 0) /* End of list? */
+ {
+ printf("****** proc_intercepts: odd number of intercepts\n");
+ break;
+ }
+ if ((to = sp_intercepts.car[i]) > sp_globals.xmax)
+ to = sp_globals.xmax - sp_globals.xmin; /* Clip to sp_globals.xmax boundary */
+ else
+ to -= sp_globals.xmin;
+ printf(" Y = %2d (scanline %2d): %d %d:\n",
+ y + sp_globals.y_band.band_min, scan_line, from, to);
+ }
+ }
+#endif
+
+/* INTERCEPTS ALL PATCHED, NOW DRAW THE IMAGE */
+scan_line = sp_globals.ymax - first_y - 1;
+
+for (y = first_y - sp_globals.y_band.band_min; y >= last_y; y--, scan_line++)
+ {
+ i = sp_intercepts.cdr[y]; /* Index head of intercept list */
+ while (i != 0) /* Link to next intercept if present */
+ {
+ from = sp_intercepts.car[i];
+ i = sp_intercepts.cdr[i]; /* Link to next intercept */
+ to = sp_intercepts.car[i];
+#if INCL_CLIPPING
+ if (clipleft)
+ {
+ if (to <= xmin)
+ {
+ i = sp_intercepts.cdr[i];
+ continue;
+ }
+ if (from < xmin)
+ from = xmin;
+ }
+ if (clipright)
+ {
+ if (from >= xmax)
+ {
+ i = sp_intercepts.cdr[i];
+ continue;
+ }
+ if (to > xmax)
+ to = xmax;
+ }
+#endif
+ set_bitmap_bits(scan_line, from-sp_globals.xmin, to-sp_globals.xmin);
+ i = sp_intercepts.cdr[i];
+ }
+ }
+}
+
+#endif
diff --git a/src/Speedo/out_util.c b/src/Speedo/out_util.c
new file mode 100644
index 0000000..b3316a5
--- /dev/null
+++ b/src/Speedo/out_util.c
@@ -0,0 +1,337 @@
+/* $Xorg: out_util.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+#define DEBUG 0
+
+/*************************** O U T _ U T I L . C *****************************
+ * *
+ * This is a utility module share by all bitmap output modules *
+ * *
+ *****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+/* absolute value function */
+#define ABS(X) ( (X < 0) ? -X : X)
+#if INCL_BLACK || INCL_2D || INCL_SCREEN
+
+FUNCTION void init_char_out(Psw,Pmin,Pmax)
+GDECL
+point_t Psw, Pmin, Pmax;
+{
+sp_globals.set_width.x = (fix31)Psw.x << sp_globals.poshift;
+sp_globals.set_width.y = (fix31)Psw.y << sp_globals.poshift;
+set_first_band_out(Pmin, Pmax);
+init_intercepts_out();
+if (sp_globals.normal)
+ {
+ sp_globals.bmap_xmin = Pmin.x;
+ sp_globals.bmap_xmax = Pmax.x;
+ sp_globals.bmap_ymin = Pmin.y;
+ sp_globals.bmap_ymax = Pmax.y;
+ sp_globals.extents_running = FALSE;
+ }
+else
+ {
+ sp_globals.bmap_xmin = 32000;
+ sp_globals.bmap_xmax = -32000;
+ sp_globals.bmap_ymin = 32000;
+ sp_globals.bmap_ymax = -32000;
+ sp_globals.extents_running = TRUE;
+ }
+sp_globals.first_pass = TRUE;
+}
+
+FUNCTION void begin_sub_char_out(Psw, Pmin, Pmax)
+GDECL
+point_t Psw;
+point_t Pmin;
+point_t Pmax;
+/* Called at the start of each sub-character in a composite character
+ */
+{
+#if DEBUG
+printf("BEGIN_SUB_CHAR_out(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f\n",
+ (real)Psw.x / (real)sp_globals.onepix, (real)Psw.y / (real)sp_globals.onepix,
+ (real)Pmin.x / (real)sp_globals.onepix, (real)Pmin.y / (real)sp_globals.onepix,
+ (real)Pmax.x / (real)sp_globals.onepix, (real)Pmax.y / (real)sp_globals.onepix);
+#endif
+restart_intercepts_out();
+if (!sp_globals.extents_running)
+ {
+ sp_globals.bmap_xmin = 32000;
+ sp_globals.bmap_xmax = -32000;
+ sp_globals.bmap_ymin = 32000;
+ sp_globals.bmap_ymax = -32000;
+ sp_globals.extents_running = TRUE;
+ }
+}
+
+FUNCTION void curve_out(P1, P2, P3,depth)
+GDECL
+point_t P1, P2, P3;
+fix15 depth;
+/* Called for each curve in the transformed character if curves out enabled
+ */
+{
+#if DEBUG
+printf("CURVE_OUT(%3.1f, %3.1f, %3.1f, %3.1f, %3.1f, %3.1f)\n",
+ (real)P1.x / (real)sp_globals.onepix, (real)P1.y / (real)sp_globals.onepix,
+ (real)P2.x / (real)sp_globals.onepix, (real)P2.y / (real)sp_globals.onepix,
+ (real)P3.x / (real)sp_globals.onepix, (real)P3.y / (real)sp_globals.onepix);
+#endif
+}
+
+
+
+FUNCTION void end_contour_out()
+GDECL
+/* Called after the last vector in each contour
+ */
+{
+#if DEBUG
+printf("END_CONTOUR_OUT()\n");
+#endif
+}
+
+
+FUNCTION void end_sub_char_out()
+GDECL
+/* Called after the last contour in each sub-character in a compound character
+ */
+{
+#if DEBUG
+printf("END_SUB_CHAR_OUT()\n");
+#endif
+}
+
+
+FUNCTION void init_intercepts_out()
+GDECL
+/* Called to initialize intercept storage data structure
+ */
+
+{
+fix15 i;
+fix15 no_lists;
+
+#if DEBUG
+printf(" Init intercepts (Y band from %d to %d)\n", sp_globals.y_band.band_min, sp_globals.y_band.band_max);
+if (sp_globals.x_scan_active)
+ printf(" (X band from %d to %d)\n", sp_globals.x_band.band_min, sp_globals.x_band.band_max);
+#endif
+
+sp_globals.intercept_oflo = FALSE;
+
+sp_globals.no_y_lists = sp_globals.y_band.band_max - sp_globals.y_band.band_min + 1;
+#if INCL_2D
+if (sp_globals.output_mode == MODE_2D)
+ {
+ sp_globals.no_x_lists = sp_globals.x_scan_active ?
+ sp_globals.x_band.band_max - sp_globals.x_band.band_min + 1 : 0;
+ no_lists = sp_globals.no_y_lists + sp_globals.no_x_lists;
+ }
+else
+#endif
+ no_lists = sp_globals.no_y_lists;
+
+#if INCL_2D
+sp_globals.y_band.band_floor = 0;
+sp_globals.y_band.band_ceiling = sp_globals.no_y_lists;
+#endif
+
+if (no_lists >= MAX_INTERCEPTS) /* Not enough room for list table? */
+ {
+ no_lists = sp_globals.no_y_lists = MAX_INTERCEPTS;
+ sp_globals.intercept_oflo = TRUE;
+ sp_globals.y_band.band_min = sp_globals.y_band.band_max - sp_globals.no_y_lists + 1;
+#if INCL_2D
+ sp_globals.y_band.band_array_offset = sp_globals.y_band.band_min;
+ sp_globals.y_band.band_ceiling = sp_globals.no_y_lists;
+ sp_globals.no_x_lists = 0;
+ sp_globals.x_scan_active = FALSE;
+#endif
+ }
+
+for (i = 0; i < no_lists; i++) /* For each active value... */
+ {
+#if INCL_SCREEN
+ if (sp_globals.output_mode == MODE_SCREEN)
+ sp_intercepts.inttype[i]=0;
+#endif
+ sp_intercepts.cdr[i] = 0; /* Mark each intercept list empty */
+ }
+
+sp_globals.first_offset = sp_globals.next_offset = no_lists;
+
+#if INCL_2D
+sp_globals.y_band.band_array_offset = sp_globals.y_band.band_min;
+sp_globals.x_band.band_array_offset = sp_globals.x_band.band_min - sp_globals.no_y_lists;
+sp_globals.x_band.band_floor = sp_globals.no_y_lists;
+sp_globals.x_band.band_ceiling = no_lists;
+#endif
+#if INCL_SCREEN
+sp_intercepts.inttype[sp_globals.no_y_lists-1] = END_INT;
+#endif
+
+}
+
+
+FUNCTION void restart_intercepts_out()
+GDECL
+
+/* Called by sp_make_char when a new sub character is started
+ * Freezes current sorted lists
+ */
+
+{
+
+#if DEBUG
+printf(" Restart intercepts:\n");
+#endif
+sp_globals.first_offset = sp_globals.next_offset;
+}
+
+
+
+FUNCTION void set_first_band_out(Pmin, Pmax)
+GDECL
+point_t Pmin;
+point_t Pmax;
+{
+
+sp_globals.ymin = Pmin.y;
+sp_globals.ymax = Pmax.y;
+
+sp_globals.ymin = (sp_globals.ymin - sp_globals.onepix + 1) >> sp_globals.pixshift;
+sp_globals.ymax = (sp_globals.ymax + sp_globals.onepix - 1) >> sp_globals.pixshift;
+
+#if INCL_CLIPPING
+ switch(sp_globals.tcb0.xtype)
+ {
+ case 1: /* 180 degree rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ sp_globals.clip_ymin = -1* sp_globals.clip_ymin;
+ if (sp_globals.ymin < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ if (sp_globals.ymax > sp_globals.clip_ymax)
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ break;
+ case 2: /* 90 degree rotation */
+ sp_globals.clip_ymax = 0;
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ break;
+ case 3: /* 270 degree rotation */
+ sp_globals.clip_ymax = ((sp_globals.set_width.y+32768L) >> 16);
+ if ((sp_globals.specs.flags & CLIP_TOP) &&
+ (sp_globals.ymax > sp_globals.clip_ymax))
+ sp_globals.ymax = sp_globals.clip_ymax;
+ sp_globals.clip_ymin = 0;
+ if ((sp_globals.specs.flags & CLIP_BOTTOM) &&
+ (sp_globals.ymin < sp_globals.clip_ymin))
+ sp_globals.ymin = sp_globals.clip_ymin;
+ break;
+ default: /* this is for zero degree rotation and arbitrary rotation */
+ if (sp_globals.specs.flags & CLIP_TOP)
+ {
+ sp_globals.clip_ymax = (fix31)((fix31)EM_TOP * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymax = sp_globals.clip_ymax >> sp_globals.multshift;
+ if (sp_globals.ymax > sp_globals.clip_ymax)
+ sp_globals.ymax = sp_globals.clip_ymax;
+ }
+ if (sp_globals.specs.flags & CLIP_BOTTOM)
+ {
+ sp_globals.clip_ymin = (fix31)((fix31)(-1 * EM_BOT) * sp_globals.tcb0.yppo + ((1<<sp_globals.multshift)/2));
+ sp_globals.clip_ymin = sp_globals.clip_ymin >> sp_globals.multshift;
+ sp_globals.clip_ymin = - sp_globals.clip_ymin;
+ if (sp_globals.ymin < sp_globals.clip_ymin)
+ sp_globals.ymin = sp_globals.clip_ymin;
+ }
+ break;
+ }
+#endif
+sp_globals.y_band.band_min = sp_globals.ymin;
+sp_globals.y_band.band_max = sp_globals.ymax - 1;
+
+sp_globals.xmin = (Pmin.x + sp_globals.pixrnd) >> sp_globals.pixshift;
+sp_globals.xmax = (Pmax.x + sp_globals.pixrnd) >> sp_globals.pixshift;
+
+
+#if INCL_2D
+sp_globals.x_band.band_min = sp_globals.xmin - 1; /* subtract one pixel of "safety margin" */
+sp_globals.x_band.band_max = sp_globals.xmax /* - 1 + 1 */; /* Add one pixel of "safety margin" */
+#endif
+}
+
+
+
+
+
+
+
+FUNCTION void reduce_band_size_out()
+GDECL
+{
+sp_globals.y_band.band_min = sp_globals.y_band.band_max - ((sp_globals.y_band.band_max - sp_globals.y_band.band_min) >> 1);
+#if INCL_2D
+sp_globals.y_band.band_array_offset = sp_globals.y_band.band_min;
+#endif
+}
+
+
+FUNCTION boolean next_band_out()
+GDECL
+{
+fix15 tmpfix15;
+
+if (sp_globals.y_band.band_min <= sp_globals.ymin)
+ return FALSE;
+tmpfix15 = sp_globals.y_band.band_max - sp_globals.y_band.band_min;
+sp_globals.y_band.band_max = sp_globals.y_band.band_min - 1;
+sp_globals.y_band.band_min = sp_globals.y_band.band_max - tmpfix15;
+if (sp_globals.y_band.band_min < sp_globals.ymin)
+ sp_globals.y_band.band_min = sp_globals.ymin;
+#if INCL_2D
+sp_globals.y_band.band_array_offset = sp_globals.y_band.band_min;
+#endif
+return TRUE;
+}
+#endif
+
diff --git a/src/Speedo/reset.c b/src/Speedo/reset.c
new file mode 100644
index 0000000..786ec43
--- /dev/null
+++ b/src/Speedo/reset.c
@@ -0,0 +1,127 @@
+/* $Xorg: reset.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+
+/******************************* R E S E T . C *******************************
+ * *
+ * This module provides initialization functions. *
+ * *
+ ****************************************************************************/
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+#include "keys.h" /* Font decryption keys */
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+
+FUNCTION void reset()
+GDECL
+/*
+ * Called by the host software to intialize the Speedo mechanism
+ */
+{
+sp_globals.specs_valid = FALSE; /* Flag specs not valid */
+
+/* Reset decryption key */
+sp_globals.key32 = (KEY3 << 8) | KEY2;
+sp_globals.key4 = KEY4;
+sp_globals.key6 = KEY6;
+sp_globals.key7 = KEY7;
+sp_globals.key8 = KEY8;
+
+#if INCL_RULES
+sp_globals.constr.font_id_valid = FALSE;
+#endif
+
+#if INCL_MULTIDEV
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+sp_globals.bitmap_device_set = FALSE;
+#endif
+#if INCL_OUTLINE
+sp_globals.outline_device_set = FALSE;
+#endif
+#endif
+}
+
+#if INCL_KEYS
+FUNCTION void set_key(key)
+GDECL
+ufix8 key[]; /* Specified decryption key */
+/*
+ * Dynamically sets font decryption key.
+ */
+{
+sp_globals.key32 = ((ufix16)key[3] << 8) | key[2];
+sp_globals.key4 = key[4];
+sp_globals.key6 = key[6];
+sp_globals.key7 = key[7];
+sp_globals.key8 = key[8];
+}
+#endif
+
+
+
+FUNCTION ufix16 get_cust_no(font_buff)
+GDECL
+buff_t font_buff;
+/*
+ returns customer number from font
+*/
+{
+ufix8 FONTFAR *hdr2_org;
+ufix16 private_off;
+
+private_off = read_word_u(font_buff.org + FH_HEDSZ);
+if (private_off + FH_CUSNR > font_buff.no_bytes)
+ {
+ report_error(1); /* Insufficient font data loaded */
+ return FALSE;
+ }
+
+hdr2_org = font_buff.org + private_off;
+
+return (read_word_u(hdr2_org + FH_CUSNR));
+}
+
+
diff --git a/src/Speedo/set_spcs.c b/src/Speedo/set_spcs.c
new file mode 100644
index 0000000..d060a4b
--- /dev/null
+++ b/src/Speedo/set_spcs.c
@@ -0,0 +1,769 @@
+/* $Xorg: set_spcs.c,v 1.3 2000/08/17 19:46:26 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+/*************************** S E T _ S P C S . C *****************************
+ * *
+ * This module implements all sp_set_specs() functionality. *
+ * *
+ ****************************************************************************/
+#define SET_SPCS
+#include "spdo_prv.h" /* General definitions for Speedo */
+#include "keys.h"
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/****** EXTERNAL VARIABLES *****/
+
+/***** STATIC VARIABLES *****/
+
+
+/****** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static boolean sp_setup_consts(PROTO_DECL2 fix15 xmin, fix15 xmax,
+ fix15 ymin, fix15 ymax);
+static void sp_setup_tcb(PROTO_DECL2 tcb_t GLOBALFAR *ptcb);
+static fix15 sp_setup_mult(PROTO_DECL2 fix31 input_mult);
+static fix31 sp_setup_offset(PROTO_DECL2 fix31 input_offset);
+#else
+static void sp_setup_tcb(); /* Set up transformation control block */
+static fix15 sp_setup_mult(); /* Convert mult to internal form */
+static fix31 sp_setup_offset(); /* Convert offset to internal form */
+static boolean sp_setup_consts(); /* Set up scaling constants */
+#endif
+
+
+
+FUNCTION boolean set_specs(specsarg)
+GDECL
+specs_t STACKFAR *specsarg; /* Bundle of conversion specifications */
+/*
+ * Called by host software to set character generation specifications
+ */
+{
+fix31 offcd; /* Offset to start of character directory */
+fix31 ofcns; /* Offset to start of constraint data */
+fix31 cd_size; /* Size of character directory */
+fix31 no_bytes_min; /* Min number of bytes in font buffer */
+ufix16 font_id; /* Font ID */
+ufix16 private_off; /* offset to private header */
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 xmax; /* Maximum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+
+sp_globals.specs_valid = FALSE; /* Flag specs not valid */
+
+sp_globals.specs = *specsarg; /* copy specs structure into sp_globals */
+sp_globals.pspecs = &sp_globals.specs;
+sp_globals.font = *sp_globals.pspecs->pfont;
+sp_globals.pfont = &sp_globals.font;
+sp_globals.font_org = sp_globals.font.org;
+
+if (read_word_u(sp_globals.font_org + FH_FMVER + 4) != 0x0d0a)
+ {
+ report_error(4); /* Font format error */
+ return FALSE;
+ }
+if (read_word_u(sp_globals.font_org + FH_FMVER + 6) != 0x0000)
+ {
+ report_error(4); /* Font format error */
+ return FALSE;
+ }
+
+if (get_cust_no(*specsarg->pfont) == 0)
+ {
+ sp_globals.key32 = 0;
+ sp_globals.key4 = 0;
+ sp_globals.key6 = 0;
+ sp_globals.key7 = 0;
+ sp_globals.key8 = 0;
+ }
+else
+ {
+ sp_globals.key32 = (KEY3 << 8) | KEY2;
+ sp_globals.key4 = KEY4;
+ sp_globals.key6 = KEY6;
+ sp_globals.key7 = KEY7;
+ sp_globals.key8 = KEY8;
+ }
+
+
+sp_globals.no_chars_avail = read_word_u(sp_globals.font_org + FH_NCHRF);
+
+/* Read sp_globals.orus per em from font header */
+sp_globals.orus_per_em = read_word_u(sp_globals.font_org + FH_ORUPM);
+
+/* compute address of private header */
+private_off = read_word_u(sp_globals.font_org + FH_HEDSZ);
+sp_globals.hdr2_org = sp_globals.font_org + private_off;
+
+/* set metric resolution if specified, default to outline res otherwise */
+if (private_off > EXP_FH_METRES)
+ {
+ sp_globals.metric_resolution = read_word_u(sp_globals.font_org + EXP_FH_METRES);
+ }
+else
+ {
+ sp_globals.metric_resolution = sp_globals.orus_per_em;
+ }
+
+#if INCL_METRICS
+sp_globals.kern.tkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFTK);
+sp_globals.kern.pkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFPK);
+sp_globals.kern.no_tracks = read_word_u(sp_globals.font_org + FH_NKTKS);
+sp_globals.kern.no_pairs = read_word_u(sp_globals.font_org + FH_NKPRS);
+#endif
+
+offcd = read_long(sp_globals.hdr2_org + FH_OFFCD); /* Read offset to character directory */
+ofcns = read_long(sp_globals.hdr2_org + FH_OFCNS); /* Read offset to constraint data */
+cd_size = ofcns - offcd;
+if ((((sp_globals.no_chars_avail << 1) + 3) != cd_size) &&
+ (((sp_globals.no_chars_avail * 3) + 4) != cd_size))
+ {
+ report_error(4); /* Font format error */
+ return FALSE;
+ }
+
+#if INCL_LCD /* Dynamic character data load suppoorted? */
+#if INCL_METRICS
+no_bytes_min = read_long(sp_globals.hdr2_org + FH_OCHRD); /* Offset to character data */
+#else /* Dynamic character data load not supported? */
+no_bytes_min = read_long(sp_globals.hdr2_org + FH_OFFTK); /* Offset to track kerning data */
+#endif
+#else /* Dynamic character data load not supported? */
+no_bytes_min = read_long(sp_globals.hdr2_org + FH_NBYTE); /* Offset to EOF + 1 */
+#endif
+
+sp_globals.font_buff_size = sp_globals.pfont->no_bytes;
+if (sp_globals.font_buff_size < no_bytes_min) /* Minimum data not loaded? */
+ {
+ report_error(1); /* Insufficient font data loaded */
+ return FALSE;
+ }
+
+sp_globals.pchar_dir = sp_globals.font_org + offcd;
+sp_globals.first_char_idx = read_word_u(sp_globals.font_org + FH_FCHRF);
+
+/* Register font name with sp_globals.constraint mechanism */
+#if INCL_RULES
+font_id = read_word_u(sp_globals.font_org + FH_FNTID);
+if (!(sp_globals.constr.font_id_valid) || (sp_globals.constr.font_id != font_id))
+ {
+ sp_globals.constr.font_id = font_id;
+ sp_globals.constr.font_id_valid = TRUE;
+ sp_globals.constr.data_valid = FALSE;
+ }
+sp_globals.constr.org = sp_globals.font_org + ofcns;
+sp_globals.constr.active = ((sp_globals.pspecs->flags & CONSTR_OFF) == 0);
+#endif
+
+/* Set up sliding point constants */
+/* Set pixel shift to accomodate largest transformed pixel value */
+xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
+xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
+ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
+ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
+
+if (!sp_setup_consts(xmin,xmax,ymin,ymax))
+ {
+ report_error(3); /* Requested specs out of range */
+ return FALSE;
+ }
+#if INCL_ISW
+/* save the value of the max x oru that the fixed point constants are based on*/
+sp_globals.isw_xmax = xmax;
+#endif
+
+/* Setup transformation control block */
+sp_setup_tcb(&sp_globals.tcb0);
+
+
+/* Select output module */
+sp_globals.output_mode = sp_globals.pspecs->flags & 0x0007;
+
+#if INCL_USEROUT
+if (!init_userout(sp_globals.pspecs))
+#endif
+
+switch (sp_globals.output_mode)
+ {
+#if INCL_BLACK
+case MODE_BLACK: /* Output mode 0 (Black writer) */
+ sp_globals.init_out = sp_init_black;
+ sp_globals.begin_char = sp_begin_char_black;
+ sp_globals.begin_sub_char = sp_begin_sub_char_out;
+ sp_globals.begin_contour = sp_begin_contour_black;
+ sp_globals.curve = sp_curve_out;
+ sp_globals.line = sp_line_black;
+ sp_globals.end_contour = sp_end_contour_out;
+ sp_globals.end_sub_char = sp_end_sub_char_out;
+ sp_globals.end_char = sp_end_char_black;
+ break;
+#endif
+
+#if INCL_SCREEN
+case MODE_SCREEN: /* Output mode 1 (Screen writer) */
+ sp_globals.init_out = sp_init_screen;
+ sp_globals.begin_char = sp_begin_char_screen;
+ sp_globals.begin_sub_char = sp_begin_sub_char_out;
+ sp_globals.begin_contour = sp_begin_contour_screen;
+ sp_globals.curve = sp_curve_screen;
+ sp_globals.line = sp_line_screen;
+ sp_globals.end_contour = sp_end_contour_screen;
+ sp_globals.end_sub_char = sp_end_sub_char_out;
+ sp_globals.end_char = sp_end_char_screen;
+ break;
+#endif
+
+#if INCL_OUTLINE
+case MODE_OUTLINE: /* Output mode 2 (Vector) */
+ sp_globals.init_out = sp_init_outline;
+ sp_globals.begin_char = sp_begin_char_outline;
+ sp_globals.begin_sub_char = sp_begin_sub_char_outline;
+ sp_globals.begin_contour = sp_begin_contour_outline;
+ sp_globals.curve = sp_curve_outline;
+ sp_globals.line = sp_line_outline;
+ sp_globals.end_contour = sp_end_contour_outline;
+ sp_globals.end_sub_char = sp_end_sub_char_outline;
+ sp_globals.end_char = sp_end_char_outline;
+ break;
+#endif
+
+#if INCL_2D
+case MODE_2D: /* Output mode 3 */
+ sp_globals.init_out = sp_init_2d;
+ sp_globals.begin_char = sp_begin_char_2d;
+ sp_globals.begin_sub_char = sp_begin_sub_char_out;
+ sp_globals.begin_contour = sp_begin_contour_2d;
+ sp_globals.curve = sp_curve_out;
+ sp_globals.line = sp_line_2d;
+ sp_globals.end_contour = sp_end_contour_out;
+ sp_globals.end_sub_char = sp_end_sub_char_out;
+ sp_globals.end_char = sp_end_char_2d;
+ break;
+#endif
+
+default:
+ report_error(8); /* Unsupported mode requested */
+ return FALSE;
+ }
+
+ if (!fn_init_out(sp_globals.pspecs))
+ {
+ report_error(5);
+ return FALSE;
+ }
+
+
+sp_globals.curves_out = sp_globals.pspecs->flags & CURVES_OUT;
+
+if (sp_globals.pspecs->flags & BOGUS_MODE) /* Linear transformation requested? */
+ {
+ sp_globals.tcb0.xtype = sp_globals.tcb0.ytype = 4;
+ }
+else /* Intelligent transformation requested? */
+ {
+#if INCL_RULES
+#else
+ report_error(7); /* Rules requested; not supported */
+ return FALSE;
+#endif
+ }
+
+if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_RIGHT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_TOP) ||
+ (sp_globals.pspecs->flags & SQUEEZE_BOTTOM) )
+ {
+#if (INCL_SQUEEZING)
+#else
+ report_error(11);
+ return FALSE;
+#endif
+ }
+
+if ((sp_globals.pspecs->flags & CLIP_LEFT) ||
+ (sp_globals.pspecs->flags & CLIP_RIGHT) ||
+ (sp_globals.pspecs->flags & CLIP_TOP) ||
+ (sp_globals.pspecs->flags & CLIP_BOTTOM) )
+ {
+#if (INCL_CLIPPING)
+#else
+ report_error(11);
+ return FALSE;
+#endif
+ }
+
+sp_globals.specs_valid = TRUE;
+return TRUE;
+}
+
+
+
+#if INCL_MULTIDEV
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+FUNCTION boolean set_bitmap_device(bfuncs,size)
+GDECL
+bitmap_t *bfuncs;
+ufix16 size;
+{
+
+if (size != sizeof(sp_globals.bitmap_device))
+ return FALSE;
+
+sp_globals.bitmap_device = *bfuncs;
+sp_globals.bitmap_device_set = TRUE;
+}
+#endif
+
+#if INCL_OUTLINE
+FUNCTION boolean set_outline_device(ofuncs,size)
+GDECL
+outline_t *ofuncs;
+ufix16 size;
+{
+
+if (size != sizeof(sp_globals.outline_device))
+ return FALSE;
+
+sp_globals.outline_device = *ofuncs;
+sp_globals.outline_device_set = TRUE;
+}
+#endif
+#endif
+
+
+#ifdef old
+FUNCTION boolean sp_setup_consts(xmin, xmax, ymin, ymax)
+#else
+static FUNCTION boolean sp_setup_consts(xmin, xmax, ymin, ymax)
+#endif
+GDECL
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 xmax; /* Maximum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+/*
+ * Sets the following constants used for fixed point arithmetic:
+ * sp_globals.multshift multipliers and products; range is 14 to 8
+ * sp_globals.pixshift pixels: range is 0 to 8
+ * sp_globals.mpshift shift from product to sub-pixels (sp_globals.multshift - sp_globals.pixshift)
+ * sp_globals.multrnd rounding for products
+ * sp_globals.pixrnd rounding for pixels
+ * sp_globals.mprnd rounding for sub-pixels
+ * sp_globals.onepix 1 pixel in shifted pixel units
+ * sp_globals.pixfix mask to eliminate fractional bits of shifted pixels
+ * sp_globals.depth_adj curve splitting depth adjustment
+ * Returns FALSE if specs are out of range
+ */
+{
+fix31 mult; /* Successive multiplier values */
+ufix32 num; /* Numerator of largest multiplier value */
+ufix32 numcopy; /* Copy of numerator */
+ufix32 denom; /* Denominator of largest multiplier value */
+ufix32 denomcopy; /* Copy of denominator */
+ufix32 pix_max; /* Maximum pixel rounding error */
+fix31 xmult; /* Coefficient of X oru value in transformation */
+fix31 ymult; /* Coefficient of Y oru value in transformation */
+fix31 offset; /* Constant in transformation */
+fix15 i; /* Loop counter */
+fix15 x, y; /* Successive corners of bounding box in ORUs */
+fix31 pixval; /* Successive pixel values multiplied by orus per em */
+fix15 xx, yy; /* Bounding box corner that produces max pixel value */
+
+/* Determine numerator and denominator of largest multiplier value */
+mult = sp_globals.pspecs->xxmult >> 16;
+if (mult < 0)
+ mult = -mult;
+num = mult;
+
+mult = sp_globals.pspecs->xymult >> 16;
+if (mult < 0)
+ mult = -mult;
+if (mult > num)
+ num = mult;
+
+mult = sp_globals.pspecs->yxmult >> 16;
+if (mult < 0)
+ mult = -mult;
+if (mult > num)
+ num = mult;
+
+mult = sp_globals.pspecs->yymult >> 16;
+if (mult < 0)
+ mult = -mult;
+if (mult > num)
+ num = mult;
+num++; /* Max absolute pixels per em (rounded up) */
+denom = (ufix32)sp_globals.orus_per_em;
+
+/* Set curve splitting depth adjustment to accomodate largest multiplier value */
+sp_globals.depth_adj = 0; /* 0 = 0.5 pel, 1 = 0.13 pel, 2 = 0.04 pel accuracy */
+denomcopy = denom;
+/* The following two occurances of a strange method of shifting twice by 1
+ are intentional and should not be changed to a single shift by 2.
+ It prevents MicroSoft C 5.1 from generating functions calls to do the shift.
+ Worse, using the REENTRANT_ALLOC option in conjunction with the /AC compiler
+ option, the function appears to be called incorrectly, causing depth_adj to always
+ be set to -7, causing very angular characters. */
+
+while ((num > denomcopy) && (sp_globals.depth_adj < 5)) /* > 1, 4, 16, ... pixels per oru? */
+ {
+ denomcopy <<= 1;
+ denomcopy <<= 1;
+ sp_globals.depth_adj++; /* Add 1, 2, 3, ... to depth adjustment */
+ }
+numcopy = num << 2;
+while ((numcopy <= denom) && (sp_globals.depth_adj > -4)) /* <= 1/4, 1/16, 1/64 pix per oru? */
+ {
+ numcopy <<= 1;
+ numcopy <<= 1;
+ sp_globals.depth_adj--; /* Subtract 1, 2, 3, ... from depth adjustment */
+ }
+SHOW(sp_globals.depth_adj);
+
+/* Set multiplier shift to accomodate largest multiplier value */
+sp_globals.multshift = 14;
+numcopy = num;
+while (numcopy >= denom) /* More than 1, 2, 4, ... pix per oru? */
+ {
+ numcopy >>= 1;
+ sp_globals.multshift--; /* sp_globals.multshift is 13, 12, 11, ... */
+ }
+
+sp_globals.multrnd = ((fix31)1 << sp_globals.multshift) >> 1;
+SHOW(sp_globals.multshift);
+
+
+pix_max = (ufix32)( 0xffff & read_word_u(sp_globals.hdr2_org + FH_PIXMX));
+
+num = 0;
+xmult = ((sp_globals.pspecs->xxmult >> 16) + 1) >> 1;
+ymult = ((sp_globals.pspecs->xymult >> 16) + 1) >> 1;
+offset = ((sp_globals.pspecs->xoffset >> 16) + 1) >> 1;
+for (i = 0; i < 8; i++)
+ {
+ if (i == 4)
+ {
+ xmult = ((sp_globals.pspecs->yxmult >> 16) + 1) >> 1;
+ ymult = ((sp_globals.pspecs->yymult >> 16) + 1) >> 1;
+ offset = ((sp_globals.pspecs->yoffset >> 16) + 1) >> 1;
+ }
+ x = (i & BIT1)? xmin: xmax;
+ y = (i & BIT0)? ymin: ymax;
+ pixval = (fix31)x * xmult + (fix31)y * ymult + offset * denom;
+ if (pixval < 0)
+ pixval = -pixval;
+ if (pixval > num)
+ {
+ num = pixval;
+ xx = x;
+ yy = y;
+ }
+ }
+if (xx < 0)
+ xx = -xx;
+if (yy < 0)
+ yy = -yy;
+num += xx + yy + ((pix_max + 2) * denom);
+ /* Allow (with 2:1 safety margin) for 1 pixel rounding errors in */
+ /* xmult, ymult and offset values, pix_max pixel expansion */
+ /* due to intelligent scaling, and */
+ /* 1 pixel rounding of overall character position */
+denom = denom << 14; /* Note num is in units of half pixels times orus per em */
+
+sp_globals.pixshift = -1;
+while ((num <= denom) && (sp_globals.pixshift < 8)) /* Max pixels <= 32768, 16384, 8192, ... pixels? */
+ {
+ num <<= 1;
+ sp_globals.pixshift++; /* sp_globals.pixshift = 0, 1, 2, ... */
+ }
+if (sp_globals.pixshift < 0)
+ return FALSE;
+
+SHOW(sp_globals.pixshift);
+sp_globals.poshift = 16 - sp_globals.pixshift;
+
+sp_globals.onepix = (fix15)1 << sp_globals.pixshift;
+sp_globals.pixrnd = sp_globals.onepix >> 1;
+sp_globals.pixfix = ~0 << sp_globals.pixshift;
+
+sp_globals.mpshift = sp_globals.multshift - sp_globals.pixshift;
+if (sp_globals.mpshift < 0)
+ return FALSE;
+sp_globals.mprnd = ((fix31)1 << sp_globals.mpshift) >> 1;
+
+return TRUE;
+}
+
+#ifdef old
+FUNCTION void sp_setup_tcb(ptcb)
+#else
+static FUNCTION void sp_setup_tcb(ptcb)
+#endif
+GDECL
+tcb_t GLOBALFAR *ptcb; /* Pointer to transformation control bloxk */
+/*
+ * Convert transformation coeffs to internal form
+ */
+{
+
+ptcb->xxmult = sp_setup_mult(sp_globals.pspecs->xxmult);
+ptcb->xymult = sp_setup_mult(sp_globals.pspecs->xymult);
+ptcb->xoffset = sp_setup_offset(sp_globals.pspecs->xoffset);
+ptcb->yxmult = sp_setup_mult(sp_globals.pspecs->yxmult);
+ptcb->yymult = sp_setup_mult(sp_globals.pspecs->yymult);
+ptcb->yoffset = sp_setup_offset(sp_globals.pspecs->yoffset);
+
+SHOW(ptcb->xxmult);
+SHOW(ptcb->xymult);
+SHOW(ptcb->xoffset);
+SHOW(ptcb->yxmult);
+SHOW(ptcb->yymult);
+SHOW(ptcb->yoffset);
+
+type_tcb(ptcb); /* Classify transformation type */
+}
+
+FUNCTION static fix15 sp_setup_mult(input_mult)
+GDECL
+fix31 input_mult; /* Multiplier in input format */
+/*
+ * Called by sp_setup_tcb() to convert multiplier in transformation
+ * matrix from external to internal form.
+ */
+{
+fix15 imshift; /* Right shift to internal format */
+fix31 imdenom; /* Divisor to internal format */
+fix31 imrnd; /* Rounding for division operation */
+
+imshift = 15 - sp_globals.multshift;
+imdenom = (fix31)sp_globals.orus_per_em << imshift;
+imrnd = imdenom >> 1;
+
+input_mult >>= 1;
+if (input_mult >= 0)
+ return (fix15)((input_mult + imrnd) / imdenom);
+else
+ return -(fix15)((-input_mult + imrnd) / imdenom);
+}
+
+FUNCTION static fix31 sp_setup_offset(input_offset)
+GDECL
+fix31 input_offset; /* Multiplier in input format */
+/*
+ * Called by sp_setup_tcb() to convert offset in transformation
+ * matrix from external to internal form.
+ */
+{
+fix15 imshift; /* Right shift to internal format */
+fix31 imrnd; /* Rounding for right shift operation */
+
+imshift = 15 - sp_globals.multshift;
+imrnd = ((fix31)1 << imshift) >> 1;
+
+return (((input_offset >> 1) + imrnd) >> imshift) + sp_globals.mprnd;
+}
+
+FUNCTION void type_tcb(ptcb)
+GDECL
+tcb_t GLOBALFAR *ptcb; /* Pointer to transformation control bloxk */
+{
+fix15 x_trans_type;
+fix15 y_trans_type;
+fix15 xx_mult;
+fix15 xy_mult;
+fix15 yx_mult;
+fix15 yy_mult;
+fix15 h_pos;
+fix15 v_pos;
+fix15 x_ppo;
+fix15 y_ppo;
+fix15 x_pos;
+fix15 y_pos;
+
+/* check for mirror image transformations */
+xx_mult = ptcb->xxmult;
+xy_mult = ptcb->xymult;
+yx_mult = ptcb->yxmult;
+yy_mult = ptcb->yymult;
+
+ptcb->mirror = ((((fix31)xx_mult*(fix31)yy_mult)-
+ ((fix31)xy_mult*(fix31)yx_mult)) < 0) ? -1 : 1;
+
+if (sp_globals.pspecs->flags & BOGUS_MODE) /* Linear transformation requested? */
+ {
+ ptcb->xtype = 4;
+ ptcb->ytype = 4;
+
+ ptcb->xppo = 0;
+ ptcb->yppo = 0;
+ ptcb->xpos = 0;
+ ptcb->ypos = 0;
+ }
+else /* Intelligent tranformation requested? */
+ {
+ h_pos = ((ptcb->xoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+ v_pos = ((ptcb->yoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+
+ x_trans_type = 4;
+ x_ppo = 0;
+ x_pos = 0;
+
+ y_trans_type = 4;
+ y_ppo = 0;
+ y_pos = 0;
+
+ if (xy_mult == 0)
+ {
+ if (xx_mult >= 0)
+ {
+ x_trans_type = 0; /* X pix is function of X orus only */
+ x_ppo = xx_mult;
+ x_pos = h_pos;
+ }
+ else
+ {
+ x_trans_type = 1; /* X pix is function of -X orus only */
+ x_ppo = -xx_mult;
+ x_pos = -h_pos;
+ }
+ }
+
+ else if (xx_mult == 0)
+ {
+ if (xy_mult >= 0)
+ {
+ x_trans_type = 2; /* X pix is function of Y orus only */
+ y_ppo = xy_mult;
+ y_pos = h_pos;
+ }
+ else
+ {
+ x_trans_type = 3; /* X pix is function of -Y orus only */
+ y_ppo = -xy_mult;
+ y_pos = -h_pos;
+ }
+ }
+
+ if (yx_mult == 0)
+ {
+ if (yy_mult >= 0)
+ {
+ y_trans_type = 0; /* Y pix is function of Y orus only */
+ y_ppo = yy_mult;
+ y_pos = v_pos;
+ }
+ else
+ {
+ y_trans_type = 1; /* Y pix is function of -Y orus only */
+ y_ppo = -yy_mult;
+ y_pos = -v_pos;
+ }
+ }
+ else if (yy_mult == 0)
+ {
+ if (yx_mult >= 0)
+ {
+ y_trans_type = 2; /* Y pix is function of X orus only */
+ x_ppo = yx_mult;
+ x_pos = v_pos;
+ }
+ else
+ {
+ y_trans_type = 3; /* Y pix is function of -X orus only */
+ x_ppo = -yx_mult;
+ x_pos = -v_pos;
+ }
+ }
+
+ ptcb->xtype = x_trans_type;
+ ptcb->ytype = y_trans_type;
+
+ ptcb->xppo = x_ppo;
+ ptcb->yppo = y_ppo;
+ ptcb->xpos = x_pos;
+ ptcb->ypos = y_pos;
+ }
+
+sp_globals.normal = (ptcb->xtype != 4) && (ptcb->ytype != 4);
+
+ptcb->xmode = 4;
+ptcb->ymode = 4;
+
+SHOW(ptcb->xtype);
+SHOW(ptcb->ytype);
+SHOW(ptcb->xppo);
+SHOW(ptcb->yppo);
+SHOW(ptcb->xpos);
+SHOW(ptcb->ypos);
+}
+
+FUNCTION fix31 read_long(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of encrypted 3-byte integer */
+/*
+ * Reads a 3-byte encrypted integer from the byte string starting at
+ * the specified point.
+ * Returns the decrypted value read as a signed integer.
+ */
+{
+fix31 tmpfix31;
+
+tmpfix31 = (fix31)((*pointer++) ^ sp_globals.key4) << 8; /* Read middle byte */
+tmpfix31 += (fix31)(*pointer++) << 16; /* Read most significant byte */
+tmpfix31 += (fix31)((*pointer) ^ sp_globals.key6); /* Read least significant byte */
+return tmpfix31;
+}
+
+FUNCTION fix15 read_word_u(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of unencrypted 2-byte integer */
+/*
+ * Reads a 2-byte unencrypted integer from the byte string starting at
+ * the specified point.
+ * Returns the decrypted value read as a signed integer.
+ */
+{
+fix15 tmpfix15;
+
+tmpfix15 = (fix15)(*pointer++) << 8; /* Read most significant byte */
+tmpfix15 += (fix15)(*pointer); /* Add least significant byte */
+return tmpfix15;
+}
+
+
diff --git a/src/Speedo/set_trns.c b/src/Speedo/set_trns.c
new file mode 100644
index 0000000..8ef34ac
--- /dev/null
+++ b/src/Speedo/set_trns.c
@@ -0,0 +1,1329 @@
+/* $Xorg: set_trns.c,v 1.3 2000/08/17 19:46:27 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+
+/*************************** S E T _ T R N S . C *****************************
+ * *
+ * This module is called from do_char.c to set up the intelligent *
+ * transformation for one character (or sub-character of a composite *
+ * character.
+ * *
+ ****************************************************************************/
+
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+/***** LOCAL MACROS *****/
+
+#define SQUEEZE_X_ORU(A,B,C) ((((fix31)A * (fix31)B) + C) >> 16)
+#define ABS(A) ((A < 0)? -A:A) /* absolute value */
+#define IMPORT_FACTOR \
+ shift = 16;\
+ while (*x_factor > (0x7fffffffL / (isw_scale >> (16 - shift))))\
+ shift--;\
+ *x_factor = (*x_factor * (isw_scale>>(16-shift))) >> shift;
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static void sp_constr_update(PROTO_DECL1);
+static ufix8 FONTFAR *sp_setup_pix_table(PROTO_DECL2 ufix8 FONTFAR *pointer,boolean short_form,fix15 no_X_ctrl_zones,fix15 no_Y_ctrl_zones);
+static ufix8 FONTFAR *sp_setup_int_table(PROTO_DECL2 ufix8 FONTFAR *pointer,fix15 no_X_int_zones,fix15 no_Y_int_zones);
+#else
+static void sp_constr_update(); /* Update constraint table */
+static ufix8 FONTFAR *sp_setup_pix_table(); /* Read control zone table */
+static ufix8 FONTFAR *sp_setup_int_table(); /* Read interpolation zone table */
+#endif
+
+
+FUNCTION void init_tcb()
+GDECL
+/*
+ * Called by sp_make_char() and make_comp_char() to initialize the current
+ * transformation control block to the top level transformation.
+ */
+{
+sp_globals.tcb = sp_globals.tcb0;
+}
+
+FUNCTION void scale_tcb(ptcb, x_pos, y_pos, x_scale, y_scale)
+GDECL
+tcb_t GLOBALFAR *ptcb; /* Transformation control block */
+fix15 x_pos; /* X position (outline res units) */
+fix15 y_pos; /* Y position (outline res units) */
+fix15 x_scale; /* X scale factor * ONE_SCALE */
+fix15 y_scale; /* Y scale factor * ONE_SCALE */
+/*
+ * Called by make_comp_char() to apply position and scale for each of the
+ * components of a compound character.
+ */
+{
+fix15 xx_mult = ptcb->xxmult;
+fix15 xy_mult = ptcb->xymult;
+fix31 x_offset = ptcb->xoffset;
+fix15 yx_mult = ptcb->yxmult;
+fix15 yy_mult = ptcb->yymult;
+fix31 y_offset = ptcb->yoffset;
+
+ptcb->xxmult = TRANS(xx_mult, x_scale, (fix31)SCALE_RND, SCALE_SHIFT);
+ptcb->xymult = TRANS(xy_mult, y_scale, (fix31)SCALE_RND, SCALE_SHIFT);
+ptcb->xoffset = MULT16(xx_mult, x_pos) + MULT16(xy_mult, y_pos) + x_offset;
+ptcb->yxmult = TRANS(yx_mult, x_scale, (fix31)SCALE_RND, SCALE_SHIFT);
+ptcb->yymult = TRANS(yy_mult, y_scale, (fix31)SCALE_RND, SCALE_SHIFT);
+ptcb->yoffset = MULT16(yx_mult, x_pos) + MULT16(yy_mult, y_pos) + y_offset;
+
+type_tcb(ptcb); /* Reclassify transformation types */
+}
+
+FUNCTION ufix8 FONTFAR *skip_interpolation_table(pointer,format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+ufix8 format; /* Character format byte */
+{
+fix15 i,n;
+ufix8 intsize[9];
+
+intsize[0] = 1;
+intsize[1] = 2;
+intsize[2] = 3;
+intsize[3] = 1;
+intsize[4] = 2;
+intsize[5] = 1;
+intsize[6] = 2;
+intsize[7] = 0;
+intsize[8] = 0;
+
+n = ((format & BIT6)? (fix15)NEXT_BYTE(pointer): 0) +
+ ((format & BIT7)? (fix15)NEXT_BYTE(pointer): 0);
+for (i = 0; i < n; i++) /* For each entry in int table ... */
+ {
+ format = NEXT_BYTE(pointer); /* Read format byte */
+ if (format & BIT7) /* Short Start/End point spec? */
+ {
+ pointer++; /* Skip Start/End point byte */
+ }
+ else
+ {
+ pointer += intsize[format & 0x7]; /* Skip Start point spec */
+ pointer += intsize[(format >> 3) & 0x7]; /* Skip End point spec */
+ }
+ }
+return pointer;
+}
+FUNCTION ufix8 FONTFAR *skip_control_zone(pointer,format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+ufix8 format; /* Character format byte */
+{
+fix15 i,n;
+ufix16 tmpufix16;
+fix15 constr;
+
+n = sp_globals.no_X_orus + sp_globals.no_Y_orus - 2;
+for (i = 0; i < n; i++) /* For each entry in control table ... */
+ {
+ if (format & BIT4)
+ pointer++; /* Skip short form From/To fields */
+ else
+ pointer += 2; /* Skip FROM and TO fields */
+ /* skip constraints field */
+ constr = NEXT_BYTES (pointer, tmpufix16);
+
+ }
+return pointer;
+}
+
+#if INCL_RULES
+#else
+FUNCTION ufix8 FONTFAR *plaid_tcb(pointer, format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+ufix8 format; /* Character format byte */
+/*
+ * Called by make_simp_char() and make_comp_char() to set up the controlled
+ * coordinate table and skip all other intelligent scaling rules embedded
+ * in the character data.
+ * Updates pointer to first byte after plaid data.
+ * This is used only if intelligent scaling is not supported in the
+ * configuration definitions.
+ */
+{
+fix15 i, n;
+
+
+
+sp_globals.no_X_orus = (format & BIT2)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+sp_globals.no_Y_orus = (format & BIT3)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+pointer = read_oru_table(pointer); /* Updates no_X/Y/orus */
+sp_globals.Y_edge_org = sp_globals.no_X_orus;
+
+/* Skip over control zone table */
+pointer = skip_control_zone(pointer,format);
+
+/* Skip over interpolation table */
+pointer = skip_interpolation_table(pointer,format);
+return pointer;
+}
+#endif
+
+#if INCL_RULES
+FUNCTION ufix8 FONTFAR *plaid_tcb(pointer, format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to next byte in char data */
+ufix8 format; /* Character format byte */
+/*
+ * Called by make_simp_char() and make_comp_char() to set up the controlled
+ * coordinate table and process all intelligent scaling rules embedded
+ * in the character data.
+ * Updates pointer to first byte after plaid data.
+ * This is used only if intelligent scaling is enabled in the
+ * configuration definitions.
+ */
+{
+fix15 no_X_ctrl_zones;
+fix15 no_Y_ctrl_zones;
+fix15 no_X_int_zones;
+fix15 no_Y_int_zones;
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+begin_plaid_data();
+#endif
+
+sp_constr_update(); /* Update constraint table if required */
+
+sp_globals.no_X_orus = (format & BIT2)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+sp_globals.no_Y_orus = (format & BIT3)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+pointer = read_oru_table(pointer); /* Updates no_X/Y/orus to include zero values */
+sp_globals.Y_edge_org = sp_globals.no_X_orus;
+if (sp_globals.no_X_orus > 1) /* 2 or more controlled X coordinates? */
+ sp_globals.tcb.xmode = sp_globals.tcb.xtype; /* Enable intelligent scaling in X */
+
+if (sp_globals.no_Y_orus > 1) /* 2 or more controlled Y coordinates? */
+ sp_globals.tcb.ymode = sp_globals.tcb.ytype; /* Enable intelligent scaling in Y */
+
+no_X_ctrl_zones = sp_globals.no_X_orus - 1;
+no_Y_ctrl_zones = sp_globals.no_Y_orus - 1;
+pointer = sp_setup_pix_table(pointer, (boolean)(format & BIT4),
+ no_X_ctrl_zones, no_Y_ctrl_zones);
+
+no_X_int_zones = (format & BIT6)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+no_Y_int_zones = (format & BIT7)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+sp_globals.Y_int_org = no_X_int_zones;
+pointer = sp_setup_int_table(pointer, no_X_int_zones, no_Y_int_zones);
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+end_plaid_data();
+#endif
+
+return pointer;
+}
+#endif
+
+#if INCL_RULES
+FUNCTION static void sp_constr_update()
+GDECL
+/*
+ * Called by plaid_tcb() to update the constraint table for the current
+ * transformation.
+ * This is always carried out whenever a character is generated following
+ * a change of font or scale factor or after initialization.
+ */
+{
+fix31 ppo;
+fix15 xppo;
+fix15 yppo;
+ufix8 FONTFAR *pointer;
+fix15 no_X_constr;
+fix15 no_Y_constr;
+fix15 i, j, k, l, n;
+fix15 ppm;
+ufix8 format;
+ufix8 format1;
+fix15 limit;
+ufix16 constr_org;
+fix15 constr_nr;
+fix15 size;
+fix31 off;
+fix15 min;
+fix15 orus;
+fix15 pix;
+ufix16 tmpufix16; /* in extended mode, macro uses secnd term */
+
+if (sp_globals.constr.data_valid && /* Constr table already done and ... */
+ (sp_globals.tcb.xppo == sp_globals.constr.xppo) && /* ... X pix per oru unchanged and ... */
+ (sp_globals.tcb.yppo == sp_globals.constr.yppo)) /* ... Y pix per oru unchanged? */
+ {
+ return; /* No need to update constraint table */
+ }
+
+sp_globals.constr.xppo = xppo = sp_globals.tcb.xppo; /* Update X pixels per oru indicator */
+sp_globals.constr.yppo = yppo = sp_globals.tcb.yppo; /* Update Y pixels per oru indicator */
+sp_globals.constr.data_valid = TRUE; /* Mark constraint table valid */
+
+pointer = sp_globals.constr.org; /* Point to first byte of constraint data */
+no_X_constr = NEXT_BYTES(pointer, tmpufix16); /* Read nmbr of X constraints */
+no_Y_constr = NEXT_BYTES(pointer, tmpufix16); /* Read nmbr of Y constraints */
+
+i = 0;
+constr_org = 0;
+n = no_X_constr;
+ppo = xppo;
+for (j = 0; ; j++)
+ {
+ sp_globals.c_act[i] = FALSE; /* Flag constraint 0 not active */
+ sp_globals.c_pix[i++] = 0; /* Constraint 0 implies no minimum */
+ sp_globals.c_act[i] = FALSE; /* Flag constraint 1 not active */
+ sp_globals.c_pix[i++] = sp_globals.onepix; /* Constraint 1 implies min 1 pixel*/
+ ppm = (ppo * (fix31)sp_globals.orus_per_em) >> sp_globals.multshift;
+ for (k = 0; k < n; k++)
+ {
+ format = NEXT_BYTE(pointer); /* Read format byte */
+ limit = (fix15)NEXT_BYTE(pointer); /* Read limit field */
+ sp_globals.c_act[i] =
+ ((ppm < limit) || (limit == 255)) &&
+ sp_globals.constr.active;
+ if (sp_globals.c_act[i]) /* Constraint active? */
+ {
+ if ((format & BIT1) && /* Constraint specified and ... */
+ (constr_nr = constr_org +
+ ((format & BIT0)? /* Read unsigned constraint value */
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer)),
+ sp_globals.c_act[constr_nr])) /* ... and specified constraint active? */
+ {
+ pix = sp_globals.c_pix[constr_nr]; /* Use constrained pixel value */
+ format1 = format;
+ for (l = 2; l > 0; l--) /* Skip 2 arguments */
+ {
+ format1 >>= 2;
+ if ((size = format1 & 0x03))
+ pointer += size - 1;
+ }
+ }
+ else /* Constraint absent or inactive? */
+ {
+ orus = (format & BIT2)? /* Read unsigned oru value */
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+
+ if (format & BIT5) /* Specified offset value? */
+ {
+ off = (fix31)((format & BIT4)? /* Read offset value */
+ NEXT_WORD(pointer):
+ (fix7)NEXT_BYTE(pointer));
+ off = (off << (sp_globals.multshift - 6)) + sp_globals.multrnd;
+ }
+ else /* Unspecified (zero) offset value? */
+ {
+ off = sp_globals.multrnd;
+ }
+
+ pix = (fix15)(((fix31)orus * ppo + off) / (1 << sp_globals.mpshift)) & sp_globals.pixfix;
+ }
+ }
+ else /* Constraint inactive? */
+ {
+ format1 = format;
+ for (l = 3; l > 0; l--) /* Skip over 3 arguments */
+ {
+ if ((size = format1 & 0x03))
+ pointer += size - 1;
+ format1 >>= 2;
+ }
+ pix = 0;
+ }
+
+ if (format & 0xc0) /* Specified minimum value? */
+ {
+ min = (format & BIT7)? /* Read unsigned minimum value */
+ (fix15)NEXT_BYTE(pointer) << sp_globals.pixshift:
+ sp_globals.onepix;
+ }
+ else /* Unspecified (zero) minimum value? */
+ {
+ min = 0;
+ }
+
+ sp_globals.c_pix[i] = (pix < min)? min: pix;
+ i++;
+ }
+ if (j) break; /* Finished if second time around loop */
+ constr_org = sp_globals.Y_constr_org = i;
+ n = no_Y_constr;
+ ppo = yppo;
+ }
+
+#if DEBUG
+printf("\nCONSTRAINT TABLE\n");
+n = no_X_constr + 2;
+for (i = 0; i < n; i++)
+ {
+ printf("%3d ", i);
+ if (sp_globals.c_act[i])
+ {
+ printf("T ");
+ }
+ else
+ {
+ printf("F ");
+ }
+ printf("%5.1f\n", ((real)sp_globals.c_pix[i] / (real)sp_globals.onepix));
+ }
+printf("--------------\n");
+n = no_Y_constr + 2;
+for (i = 0; i < n; i++)
+ {
+ j = i + sp_globals.Y_constr_org;
+ printf("%3d ", i);
+ if (sp_globals.c_act[j])
+ {
+ printf("T ");
+ }
+ else
+ {
+ printf("F ");
+ }
+ printf("%5.1f\n", ((real)sp_globals.c_pix[j] / (real)sp_globals.onepix));
+ }
+#endif
+
+}
+#endif
+
+FUNCTION ufix8 FONTFAR *read_oru_table(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte in controlled coord table */
+/*
+ * Called by plaid_tcb() to read the controlled coordinate table from the
+ * character data in the font.
+ * Updates the pointer to the byte following the controlled coordinate
+ * data.
+ */
+{
+fix15 i, j, k, n;
+boolean zero_not_in;
+boolean zero_added;
+fix15 oru;
+
+#if INCL_RULES
+fix15 pos;
+#endif
+
+i = 0;
+n = sp_globals.no_X_orus;
+#if INCL_RULES
+pos = sp_globals.tcb.xpos;
+#endif
+for (j = 0; ; j++)
+ {
+ zero_not_in = TRUE;
+ zero_added = FALSE;
+ for (k = 0; k < n; k++)
+ {
+ oru = NEXT_WORD(pointer);
+ if (zero_not_in && (oru >= 0)) /* First positive oru value? */
+ {
+#if INCL_RULES
+ sp_plaid.pix[i] = pos; /* Insert position in pix array */
+#endif
+ if (oru != 0) /* Zero oru value omitted? */
+ {
+ sp_plaid.orus[i++] = 0; /* Insert zero value in oru array */
+ zero_added = TRUE; /* Remember to increment size of array */
+ }
+ zero_not_in = FALSE; /* Inhibit further testing for zero ins */
+ }
+ sp_plaid.orus[i++] = oru; /* Add specified oru value to array */
+ }
+ if (zero_not_in) /* All specified oru values negative? */
+ {
+#if INCL_RULES
+ sp_plaid.pix[i] = pos; /* Insert position in pix array */
+#endif
+ sp_plaid.orus[i++] = 0; /* Add zero oru value */
+ zero_added = TRUE; /* Remember to increment size of array */
+ }
+ if (j) /* Both X and Y orus read? */
+ break;
+ if (zero_added)
+ sp_globals.no_X_orus++; /* Increment X array size */
+ n = sp_globals.no_Y_orus; /* Prepare to read Y oru values */
+#if INCL_RULES
+ pos = sp_globals.tcb.ypos;
+#endif
+ }
+if (zero_added) /* Zero Y oru value added to array? */
+ sp_globals.no_Y_orus++; /* Increment Y array size */
+
+#if DEBUG
+printf("\nX ORUS\n");
+n = sp_globals.no_X_orus;
+for (i = 0; i < n; i++)
+ {
+ printf("%2d %4d\n", i, sp_plaid.orus[i]);
+ }
+printf("\nY ORUS\n");
+n = sp_globals.no_Y_orus;
+for (i = 0; i < n; i++)
+ {
+ printf("%2d %4d\n", i, sp_plaid.orus[i + sp_globals.no_X_orus]);
+ }
+#endif
+
+return pointer; /* Update pointer */
+}
+#if INCL_SQUEEZING || INCL_ISW
+FUNCTION static void calculate_x_pix(start_edge, end_edge, constr_nr,
+ x_scale, x_offset, ppo, setwidth_pix)
+GDECL
+ufix8 start_edge, end_edge;
+ufix16 constr_nr;
+fix31 x_scale;
+fix31 x_offset;
+fix31 ppo;
+fix15 setwidth_pix;
+/*
+ * Called by sp_setup_pix_table() when X squeezing is necessary
+ * to insert the correct edge in the global pix array
+ */
+{
+fix15 zone_pix;
+fix15 start_oru, end_oru;
+
+/* compute scaled oru coordinates */
+start_oru= (fix15)(SQUEEZE_X_ORU(sp_plaid.orus[start_edge], x_scale, x_offset));
+end_oru = (fix15)(SQUEEZE_X_ORU(sp_plaid.orus[end_edge], x_scale, x_offset));
+
+if (!sp_globals.c_act[constr_nr]) /* constraint inactive */
+ {
+ /* calculate zone width */
+ zone_pix = (fix15)(((((fix31)end_oru - (fix31)start_oru) * ppo) /
+ (1<<sp_globals.mpshift)) + sp_globals.pixrnd) & sp_globals.pixfix;
+ /* check for overflow */
+ if (((end_oru-start_oru) > 0) && (zone_pix < 0))
+ zone_pix = 0x7ffff;
+ /* check for minimum */
+ if ((ABS(zone_pix)) >= sp_globals.c_pix[constr_nr])
+ goto Lx;
+ }
+/* use the zone size from the constr table - scale it */
+zone_pix = (fix15)(((SQUEEZE_MULT(x_scale,sp_globals.c_pix[constr_nr]))
+ + sp_globals.pixrnd) & sp_globals.pixfix);
+
+/* look for overflow */
+if ((sp_globals.c_pix[constr_nr] > 0) && (zone_pix < 0))
+ zone_pix = 0x7fff;
+
+if (start_edge > end_edge)
+ {
+ zone_pix = -zone_pix;
+ }
+Lx:
+/* assign pixel value to global pix array */
+sp_plaid.pix[end_edge]=sp_plaid.pix[start_edge] + zone_pix;
+
+/* check for overflow */
+if (((sp_plaid.pix[start_edge] >0) && (zone_pix >0)) &&
+ (sp_plaid.pix[end_edge] < 0))
+ sp_plaid.pix[end_edge] = 0x7fff; /* set it to the max */
+
+/* be sure to be in the setwidth !*/
+#if INCL_ISW
+if (!sp_globals.import_setwidth_act) /* only check left edge if not isw only */
+#endif
+if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) && (sp_plaid.pix[end_edge] < 0))
+ sp_plaid.pix[end_edge] = 0;
+if ((sp_globals.pspecs->flags & SQUEEZE_RIGHT) &&
+ (sp_plaid.pix[end_edge] > setwidth_pix))
+ sp_plaid.pix[end_edge] = setwidth_pix;
+
+}
+#endif
+
+#if INCL_SQUEEZING
+FUNCTION static void calculate_y_pix(start_edge, end_edge,constr_nr,
+ top_scale, bottom_scale,ppo,em_top_pix, em_bot_pix)
+GDECL
+ufix8 start_edge, end_edge;
+ufix16 constr_nr;
+fix31 top_scale, bottom_scale;
+fix31 ppo;
+fix15 em_top_pix, em_bot_pix;
+
+/*
+ * Called by sp_setup_pix_table() when Y squeezing is necessary
+ * to insert the correct edge in the global pix array
+ */
+{
+fix15 zone_pix;
+fix15 start_oru, end_oru;
+fix31 zone_width, above_base, below_base;
+
+/* check whether edge is above or below the baseline */
+/* and apply appropriate scale factor to get scaled oru coordinates */
+if (sp_plaid.orus[start_edge] < 0)
+ start_oru =(fix15)(SQUEEZE_MULT(sp_plaid.orus[start_edge], bottom_scale));
+else
+ start_oru =(fix15)(SQUEEZE_MULT(sp_plaid.orus[start_edge], top_scale));
+
+if (sp_plaid.orus[end_edge] < 0)
+ end_oru =(fix15)(SQUEEZE_MULT(sp_plaid.orus[end_edge], bottom_scale));
+else
+ end_oru =(fix15)(SQUEEZE_MULT(sp_plaid.orus[end_edge], top_scale));
+
+if (!sp_globals.c_act[constr_nr]) /* Constraint inactive? */
+ {
+ /* calculate zone width */
+ zone_pix = (fix15)(((((fix31)end_oru - (fix31)start_oru) * ppo)
+ >> sp_globals.mpshift)+ sp_globals.pixrnd) & sp_globals.pixfix;
+ /* check minimum */
+ if ((ABS(zone_pix)) >= sp_globals.c_pix[constr_nr])
+ goto Ly;
+ }
+
+/* Use zone size from constr table */
+if ((end_oru >= 0) && (start_oru >=0))
+ /* all above baseline */
+ zone_pix = (fix15)(SQUEEZE_MULT(top_scale, sp_globals.c_pix[constr_nr]));
+else if ((end_oru <= 0) && (start_oru <=0))
+ /* all below baseline */
+ zone_pix = (fix15)(SQUEEZE_MULT(bottom_scale, sp_globals.c_pix[constr_nr]));
+else
+ {
+ /* mixture */
+ if (start_oru > 0)
+ {
+ zone_width = start_oru - end_oru;
+ /* get % above baseline in 16.16 fixed point */
+ above_base = (((fix31)start_oru) << 16) /
+ ((fix31)zone_width) ;
+ /* get % below baseline in 16.16 fixed point */
+ below_base = (((fix31)-end_oru) << 16) /
+ ((fix31)zone_width) ;
+ }
+ else
+ {
+ zone_width = end_oru - start_oru;
+ /* get % above baseline in 16.16 fixed point */
+ above_base = (((fix31)-start_oru) << 16) /
+ ((fix31)zone_width) ;
+ /* get % below baseline in 16.16 fixed point */
+ below_base = (((fix31)end_oru) << 16) /
+ ((fix31)zone_width) ;
+ }
+ /* % above baseline * total zone * top_scale + */
+ /* % below baseline * total zone * bottom_scale */
+ zone_pix = ((((above_base * (fix31)sp_globals.c_pix[constr_nr]) >> 16) *
+ top_scale) +
+ (((below_base * (fix31)sp_globals.c_pix[constr_nr]) >> 16) *
+ bottom_scale)) >> 16;
+ }
+
+/* make this zone pix fall on a pixel boundary */
+zone_pix = (zone_pix + sp_globals.pixrnd) & sp_globals.pixfix;
+
+/* if minimum is in effect make the zone one pixel */
+if ((sp_globals.c_pix[constr_nr] != 0) && (zone_pix < sp_globals.onepix))
+ zone_pix = sp_globals.onepix;
+
+if (start_edge > end_edge)
+ {
+ zone_pix = -zone_pix; /* Use negatve zone size */
+ }
+Ly:
+/* assign global pix value */
+sp_plaid.pix[end_edge] = sp_plaid.pix[start_edge] + zone_pix; /* Insert end pixels */
+
+/* make sure it is in the EM !*/
+if ((sp_globals.pspecs->flags & SQUEEZE_TOP) &&
+ (sp_plaid.pix[end_edge] > em_top_pix))
+ sp_plaid.pix[end_edge] = em_top_pix;
+if ((sp_globals.pspecs->flags & SQUEEZE_BOTTOM) &&
+ (sp_plaid.pix[end_edge] < em_bot_pix))
+ sp_plaid.pix[end_edge] = em_bot_pix;
+}
+
+FUNCTION boolean calculate_x_scale(x_factor, x_offset, no_X_ctrl_zones)
+GDECL
+fix31 *x_factor;
+fix31 *x_offset;
+fix15 no_X_ctrl_zones; /* Number of X control zones */
+/*
+ * Called by sp_setup_pix_table() when squeezing is included
+ * to determine whether X scaling is necessary. If it is, the
+ * scale factor and offset are computed. This function returns
+ * a boolean value TRUE = X squeezind is necessary, FALSE = no
+ * X squeezing is necessary.
+ */
+{
+boolean squeeze_left, squeeze_right;
+boolean out_on_right, out_on_left;
+fix15 bbox_width,set_width;
+fix15 bbox_xmin, bbox_xmax;
+fix15 x_offset_pix;
+fix15 i;
+#if INCL_ISW
+fix31 isw_scale;
+fix15 shift;
+#endif
+
+
+/* set up some flags and common calculations */
+squeeze_left = (sp_globals.pspecs->flags & SQUEEZE_LEFT)? TRUE:FALSE;
+squeeze_right = (sp_globals.pspecs->flags & SQUEEZE_RIGHT)? TRUE:FALSE;
+bbox_xmin = sp_globals.bbox_xmin_orus;
+bbox_xmax = sp_globals.bbox_xmax_orus;
+set_width = sp_globals.setwidth_orus;
+
+if (bbox_xmax > set_width)
+ out_on_right = TRUE;
+else
+ out_on_right = FALSE;
+if (bbox_xmin < 0)
+ out_on_left = TRUE;
+else
+ out_on_left = FALSE;
+bbox_width =bbox_xmax - bbox_xmin;
+
+/*
+ * don't need X squeezing if:
+ * - X squeezing not enabled
+ * - bbox doesn't violate on left or right
+ * - left squeezing only is enabled and char isn't out on left
+ * - right squeezing only is enabled and char isn't out on right
+ */
+
+if ((!squeeze_left && !squeeze_right) ||
+ (!out_on_right && !out_on_left) ||
+ (squeeze_left && !squeeze_right && !out_on_left) ||
+ (squeeze_right && !squeeze_left && !out_on_right))
+ return FALSE;
+
+#if INCL_ISW
+if (sp_globals.import_setwidth_act)
+ {
+ /* if both isw and squeezing is going on - let the imported */
+ /* setwidth factor be factored in with the squeeze */
+ isw_scale = compute_isw_scale();
+ /*sp_globals.setwidth_orus = sp_globals.imported_width;*/
+ }
+else
+ isw_scale = 0x10000L; /* 1 in 16.16 notation */
+#endif
+
+/* squeezing on left and right ? */
+if (squeeze_left && squeeze_right)
+ {
+ /* calculate scale factor */
+ if (bbox_width < set_width)
+ *x_factor = 0x10000L; /* 1 in 16.16 notation */
+ else
+ *x_factor = ((fix31)set_width<<16)/(fix31)bbox_width;
+#if INCL_ISW
+ IMPORT_FACTOR
+#endif
+ /* calculate offset */
+ if (out_on_left) /* fall out on left ? */
+ *x_offset = -(fix31)*x_factor * (fix31)bbox_xmin;
+ /* fall out on right and I am shifting only ? */
+ else if (out_on_right && (*x_factor == 0x10000L))
+ *x_offset = -(fix31)*x_factor * (fix31)(bbox_xmax - set_width);
+ else
+ *x_offset = 0x0L; /* 0 in 16.16 notation */
+ }
+/* squeezing on left only and violates left */
+else if (squeeze_left)
+ {
+ if (bbox_width < set_width) /* will it fit if I shift it ? */
+ *x_factor = 0x10000L; /* 1 in 16.16 notation */
+ else if (out_on_right)
+ *x_factor = ((fix31)set_width<<16)/(fix31)bbox_width;
+ else
+ *x_factor = ((fix31)set_width<<16)/
+ (fix31)(bbox_width - (bbox_xmax-set_width));
+#if INCL_ISW
+ IMPORT_FACTOR
+#endif
+ *x_offset = (fix31)-*x_factor * (fix31)bbox_xmin;
+ }
+
+/* I must be squeezing on right, and violates right */
+else
+ {
+ if (bbox_width < set_width) /* will it fit if I shift it ? */
+ { /* just shift it left - it will fit in the bbox */
+ *x_factor = 0x10000L; /* 1 in 16.16 notation */
+#if INCL_ISW
+ IMPORT_FACTOR
+#endif
+ *x_offset = (fix31)-*x_factor * (fix31)bbox_xmin;
+ }
+ else if (out_on_left)
+ {
+ *x_factor = ((fix31)set_width<<16)/(fix31)bbox_width;
+#if INCL_ISW
+ IMPORT_FACTOR
+#endif
+ *x_offset = 0x0L; /* 0 in 16.16 notation */
+ }
+ else
+ {
+ *x_factor = ((fix31)set_width<<16)/(fix31)bbox_xmax;
+#if INCL_ISW
+ IMPORT_FACTOR
+#endif
+ *x_offset = 0x0L; /* 0 in 16.16 notation */
+ }
+ }
+
+x_offset_pix = (fix15)(((*x_offset >> 16) * sp_globals.tcb0.xppo)
+ / (1<<sp_globals.mpshift));
+
+if ((x_offset_pix >0) && (x_offset_pix < sp_globals.onepix))
+ x_offset_pix = sp_globals.onepix;
+
+/* look for the first non-negative oru value, scale and add the offset */
+/* to the corresponding pixel value - note that the pixel value */
+/* is set in read_oru_table. */
+
+/* look at all the X edges */
+for (i=0; i < (no_X_ctrl_zones+1); i++)
+ if (sp_plaid.orus[i] >= 0)
+ {
+ sp_plaid.pix[i] = (SQUEEZE_MULT(sp_plaid.pix[i], *x_factor)
+ +sp_globals.pixrnd + x_offset_pix) & sp_globals.pixfix;
+ break;
+ }
+
+return TRUE;
+}
+
+FUNCTION boolean calculate_y_scale(top_scale, bottom_scale,
+ first_Y_zone, no_Y_ctrl_zones)
+GDECL
+fix31 *top_scale, *bottom_scale;
+fix15 first_Y_zone;
+fix15 no_Y_ctrl_zones;
+/*
+ * Called by sp_setup_pix_table() when squeezing is included
+ * to determine whether Y scaling is necessary. If it is,
+ * two scale factors are computed, one for above the baseline,
+ * and one for below the basline.
+ * This function returns a boolean value TRUE = Y squeezind is necessary,
+ * FALSE = no Y squeezing is necessary.
+ */
+{
+boolean squeeze_top, squeeze_bottom;
+boolean out_on_top, out_on_bottom;
+fix15 bbox_top, bbox_bottom;
+fix15 bbox_height;
+fix15 i;
+
+/* set up some flags and common calculations */
+squeeze_top = (sp_globals.pspecs->flags & SQUEEZE_TOP)? TRUE:FALSE;
+squeeze_bottom = (sp_globals.pspecs->flags & SQUEEZE_BOTTOM)? TRUE:FALSE;
+bbox_top = sp_globals.bbox_ymax_orus;
+bbox_bottom = sp_globals.bbox_ymin_orus;
+bbox_height = bbox_top - bbox_bottom;
+
+if (bbox_top > EM_TOP)
+ out_on_top = TRUE;
+else
+ out_on_top = FALSE;
+
+if (bbox_bottom < EM_BOT)
+ out_on_bottom = TRUE;
+else
+ out_on_bottom = FALSE;
+
+/*
+ * don't need Y squeezing if:
+ * - Y squeezing not enabled
+ * - bbox doesn't violate on top or bottom
+ * - top squeezing only is enabled and char isn't out on top
+ * - bottom squeezing only is enabled and char isn't out on bottom
+ */
+if ((!squeeze_top && !squeeze_bottom) ||
+ (!out_on_top && !out_on_bottom) ||
+ (squeeze_top && !squeeze_bottom && !out_on_top) ||
+ (squeeze_bottom && !squeeze_top && !out_on_bottom))
+ return FALSE;
+
+if (squeeze_top && (bbox_top > EM_TOP))
+ *top_scale = ((fix31)EM_TOP << 16)/(fix31)(bbox_top);
+else
+ *top_scale = 0x10000L; /* 1 in 16.16 fixed point */
+
+if (squeeze_bottom && (bbox_bottom < EM_BOT))
+ *bottom_scale = ((fix31)-(EM_BOT) << 16)/(fix31)-bbox_bottom;
+else
+ *bottom_scale = 0x10000L;
+
+if (sp_globals.squeezing_compound)
+ {
+ for (i=first_Y_zone; i < (first_Y_zone + no_Y_ctrl_zones + 1); i++)
+ {
+ if (sp_plaid.orus[i] >= 0)
+ sp_plaid.pix[i] = (SQUEEZE_MULT(sp_plaid.pix[i], *top_scale)
+ +sp_globals.pixrnd) & sp_globals.pixfix;
+ else
+ sp_plaid.pix[i] = (SQUEEZE_MULT(sp_plaid.pix[i], *bottom_scale)
+ +sp_globals.pixrnd) & sp_globals.pixfix;
+ }
+ }
+return TRUE;
+}
+#endif
+
+#if INCL_RULES
+FUNCTION static ufix8 FONTFAR *sp_setup_pix_table(
+ pointer, short_form, no_X_ctrl_zones, no_Y_ctrl_zones)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte in control zone table */
+boolean short_form; /* TRUE if 1 byte from/to specification */
+fix15 no_X_ctrl_zones; /* Number of X control zones */
+fix15 no_Y_ctrl_zones; /* Number of Y control zones */
+/*
+ * Called by plaid_tcb() to read the control zone table from the
+ * character data in the font.
+ * Sets up a table of pixel values for all controlled coordinates.
+ * Updates the pointer to the byte following the control zone
+ * data.
+ */
+{
+fix15 i, j, n;
+fix31 ppo;
+fix31 xppo0; /* top level pixels per oru */
+fix31 yppo0; /* top level pixels per oru */
+ufix8 edge_org;
+ufix8 edge;
+ufix8 start_edge;
+ufix8 end_edge;
+ufix16 constr_org;
+fix15 constr_nr;
+fix15 zone_pix;
+fix31 whole_zone; /* non-transformed value of the first X zone */
+ufix16 tmpufix16; /* in extended mode, macro uses secnd term */
+#if INCL_SQUEEZING
+fix31 x_scale;
+fix31 y_top_scale, y_bottom_scale;
+fix31 x_offset;
+boolean squeezed_y;
+fix15 setwidth_pix, em_top_pix, em_bot_pix;
+#endif
+
+#if INCL_ISW
+boolean imported_width;
+fix31 isw_scale;
+fix15 isw_setwidth_pix;
+#endif
+
+#if INCL_ISW || INCL_SQUEEZING
+boolean squeezed_x;
+#endif
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+begin_ctrl_zones(no_X_ctrl_zones, no_Y_ctrl_zones);
+#endif
+
+
+edge_org = 0;
+constr_org = 0;
+sp_globals.rnd_xmin = 0; /* initialize the error for chars with no zone */
+n = no_X_ctrl_zones;
+ppo = sp_globals.tcb.xppo;
+xppo0 = sp_globals.tcb0.xppo;
+yppo0 = sp_globals.tcb0.yppo;
+#if INCL_SQUEEZING || INCL_ISW
+squeezed_x = FALSE;
+#endif
+
+#if INCL_SQUEEZING
+squeezed_x = calculate_x_scale (&x_scale, &x_offset, no_X_ctrl_zones);
+squeezed_y = calculate_y_scale(&y_top_scale,&y_bottom_scale,(n+1),
+ no_Y_ctrl_zones);
+#if INCL_ISW
+if (sp_globals.import_setwidth_act == TRUE)
+setwidth_pix = ((fix15)(((fix31)sp_globals.imported_width * xppo0) >>
+ sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+
+else
+#endif
+setwidth_pix = ((fix15)(((fix31)sp_globals.setwidth_orus * xppo0) >>
+ sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+/* check for overflow */
+if (setwidth_pix < 0)
+ setwidth_pix = 0x7fff; /* set to maximum */
+em_bot_pix = ((fix15)(((fix31)EM_BOT * yppo0) >>
+ sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+em_top_pix = ((fix15)(((fix31)EM_TOP * yppo0) >>
+ sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+#endif
+
+#if INCL_ISW
+/* convert to pixels */
+isw_setwidth_pix = ((fix15)(((fix31)sp_globals.imported_width * xppo0) >>
+ sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
+/* check for overflow */
+if (isw_setwidth_pix < 0)
+ isw_setwidth_pix = 0x7fff; /* set to maximum */
+if (!squeezed_x && ((imported_width = sp_globals.import_setwidth_act) == TRUE))
+ {
+ isw_scale = compute_isw_scale();
+
+ /* look for the first non-negative oru value, scale and add the offset */
+ /* to the corresponding pixel value - note that the pixel value */
+ /* is set in read_oru_table. */
+
+ /* look at all the X edges */
+ for (i=0; i < (no_X_ctrl_zones+1); i++)
+ if (sp_plaid.orus[i] >= 0)
+ {
+ sp_plaid.pix[i] = (SQUEEZE_MULT(sp_plaid.pix[i], isw_scale)
+ +sp_globals.pixrnd) & sp_globals.pixfix;
+ break;
+ }
+
+ }
+#endif
+
+for (i = 0; ; i++) /* For X and Y control zones... */
+ {
+ for (j = 0; j < n; j++) /* For each zone in X or Y... */
+ {
+ if (short_form) /* 1 byte from/to specification? */
+ {
+ edge = NEXT_BYTE(pointer); /* Read packed from/to spec */
+ start_edge = edge_org + (edge & 0x0f); /* Extract start edge */
+ end_edge = edge_org + (edge >> 4); /* Extract end edge */
+ }
+ else /* 2 byte from/to specification? */
+ {
+ start_edge = edge_org + NEXT_BYTE(pointer); /* Read start edge */
+ end_edge = edge_org + NEXT_BYTE(pointer); /* read end edge */
+ }
+ constr_nr = constr_org +
+ NEXT_BYTES(pointer, tmpufix16); /* Read constraint number */
+#if INCL_SQUEEZING
+ if (i == 0 && squeezed_x)
+ calculate_x_pix(start_edge, end_edge, constr_nr,
+ x_scale, x_offset, ppo, setwidth_pix);
+ else if (i == 1 && squeezed_y)
+ calculate_y_pix(start_edge, end_edge,constr_nr,
+ y_top_scale, y_bottom_scale, ppo, em_top_pix, em_bot_pix);
+ else
+ {
+#endif
+#if INCL_ISW
+ if (i==0 && imported_width)
+ calculate_x_pix(start_edge, end_edge, constr_nr,
+ isw_scale, 0, ppo, isw_setwidth_pix);
+ else
+ {
+#endif
+ if (!sp_globals.c_act[constr_nr]) /* Constraint inactive? */
+ {
+ zone_pix = ((fix15)((((fix31)sp_plaid.orus[end_edge] -
+ (fix31)sp_plaid.orus[start_edge]) * ppo) /
+ (1<<sp_globals.mpshift)) + sp_globals.pixrnd) &
+ sp_globals.pixfix;
+ if ((ABS(zone_pix)) >= sp_globals.c_pix[constr_nr])
+ goto L1;
+ }
+ zone_pix = sp_globals.c_pix[constr_nr]; /* Use zone size from constr table */
+ if (start_edge > end_edge) /* sp_plaid.orus[start_edge] > sp_plaid.orus[end_edge]? */
+ {
+ zone_pix = -zone_pix; /* Use negatve zone size */
+ }
+ L1:
+ /* inter-character spacing fix */
+ if ((j == 0) && (i == 0)) /* if this is the 1st X zone, save rounding error */
+ { /* get the non-xformed - xformed zone, in right direction */
+ whole_zone = (((fix31)sp_plaid.orus[end_edge] -
+ (fix31)sp_plaid.orus[start_edge]) *
+ ppo) / (1<<sp_globals.mpshift);
+ sp_globals.rnd_xmin = whole_zone - zone_pix;
+ }
+ sp_plaid.pix[end_edge] = sp_plaid.pix[start_edge] + zone_pix; /* Insert end pixels */
+#if INCL_SQUEEZING
+ if (i == 0) /* in the x direction */
+ { /* brute force squeeze */
+ if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) &&
+ (sp_plaid.pix[end_edge] < 0))
+ sp_plaid.pix[end_edge] = 0;
+ if ((sp_globals.pspecs->flags & SQUEEZE_RIGHT) &&
+ (sp_plaid.pix[end_edge] > setwidth_pix))
+ sp_plaid.pix[end_edge] = setwidth_pix;
+ }
+ if (i == 1) /* in the y direction */
+ { /* brute force squeeze */
+ if ((sp_globals.pspecs->flags & SQUEEZE_TOP) &&
+ (sp_plaid.pix[end_edge] > em_top_pix))
+ sp_plaid.pix[end_edge] = em_top_pix;
+ if ((sp_globals.pspecs->flags & SQUEEZE_BOTTOM) &&
+ (sp_plaid.pix[end_edge] < em_bot_pix))
+ sp_plaid.pix[end_edge] = em_bot_pix;
+ }
+#endif
+#if INCL_SQUEEZING
+ }
+#endif
+#if INCL_ISW
+ }
+#endif
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+ record_ctrl_zone(
+ (fix31)sp_plaid.pix[start_edge] << (16 - sp_globals.pixshift),
+ (fix31)sp_plaid.pix[end_edge] << (16 - sp_globals.pixshift),
+ (fix15)(constr_nr - constr_org));
+#endif
+ }
+ if (i) /* Y pixels done? */
+ break;
+ edge_org = sp_globals.Y_edge_org; /* Prepare to process Y ctrl zones */
+ constr_org = sp_globals.Y_constr_org;
+ n = no_Y_ctrl_zones;
+ ppo = sp_globals.tcb.yppo;
+ }
+
+#if DEBUG
+printf("\nX PIX TABLE\n");
+n = no_X_ctrl_zones + 1;
+for (i = 0; i < n; i++)
+ printf("%2d %6.1f\n", i, (real)sp_plaid.pix[i] / (real)sp_globals.onepix);
+printf("\nY PIX TABLE\n");
+n = no_Y_ctrl_zones + 1;
+for (i = 0; i < n; i++)
+ {
+ j = i + no_X_ctrl_zones + 1;
+ printf("%2d %6.1f\n", i, (real)sp_plaid.pix[j] / (real)sp_globals.onepix);
+ }
+#endif
+
+return pointer;
+}
+#endif
+
+
+#if INCL_RULES
+FUNCTION static ufix8 FONTFAR *sp_setup_int_table(pointer, no_X_int_zones, no_Y_int_zones)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte in interpolation zone table */
+fix15 no_X_int_zones; /* Number of X interpolation zones */
+fix15 no_Y_int_zones; /* Number of X interpolation zones */
+/*
+ * Called by plaid_tcb() to read the interpolation zone table from the
+ * character data in the font.
+ * Sets up a table of interpolation coefficients with one entry for
+ * every X or Y interpolation zone.
+ * Updates the pointer to the byte following the interpolation zone
+ * data.
+ */
+{
+fix15 i, j, k, l, n;
+ufix8 format;
+ufix8 format_copy;
+ufix8 tmpufix8;
+fix15 start_orus;
+ufix8 edge_org;
+ufix8 edge;
+ufix16 adj_factor;
+fix15 adj_orus;
+fix15 end_orus;
+fix31 zone_orus;
+fix15 start_pix;
+fix15 end_pix;
+
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+begin_int_zones(no_X_int_zones, no_Y_int_zones);
+#endif
+
+i = 0;
+edge_org = 0;
+n = no_X_int_zones;
+for (j = 0; ; j++)
+ {
+ for (k = 0; k < n; k++)
+ {
+ format = NEXT_BYTE(pointer);
+ if (format & BIT7) /* Short start/end point spec? */
+ {
+ tmpufix8 = NEXT_BYTE(pointer);
+ edge = edge_org + (tmpufix8 & 0xf);
+ start_orus = sp_plaid.orus[edge];
+ start_pix = sp_plaid.pix[edge];
+ edge = edge_org + (tmpufix8 >> 4);
+ end_orus = sp_plaid.orus[edge];
+ end_pix = sp_plaid.pix[edge];
+ }
+ else /* Standard start and end point spec? */
+ {
+ format_copy = format;
+ for (l = 0; ; l++) /* Loop for start and end point */
+ {
+ switch (format_copy & 0x7) /* Decode start/end point format */
+ {
+
+ case 0: /* Index to control edge */
+ edge = edge_org + NEXT_BYTE(pointer);
+ end_orus = sp_plaid.orus[edge];
+ end_pix = sp_plaid.pix[edge];
+ break;
+
+ case 1: /* 1 byte fractional distance to next edge */
+ adj_factor = 0xffff & NEXT_BYTE(pointer) << 8;
+ goto L1;
+
+
+ case 2: /* 2 byte fractional distance to next edge */
+ adj_factor = 0xffff & NEXT_WORD(pointer);
+ L1: edge = edge_org + NEXT_BYTE(pointer);
+ end_orus = sp_plaid.orus[edge] +
+ ((((fix31)sp_plaid.orus[edge + 1] - (fix31)sp_plaid.orus[edge]) *
+ (ufix32)adj_factor + (fix31)32768) >> 16);
+ end_pix = sp_plaid.pix[edge] +
+ ((((fix31)sp_plaid.pix[edge + 1] - (fix31)sp_plaid.pix[edge]) *
+ (ufix32)adj_factor + (fix31)32768) >> 16);
+ break;
+
+ case 3: /* 1 byte delta orus before first edge */
+ adj_orus = -(fix15)NEXT_BYTE(pointer);
+ goto L2;
+
+ case 4: /* 2 byte delta orus before first edge */
+ adj_orus = -NEXT_WORD(pointer);
+ L2: edge = edge_org;
+ goto L4;
+
+ case 5: /* 1 byte delta orus after last edge */
+ adj_orus = (fix15)NEXT_BYTE(pointer);
+ goto L3;
+
+ case 6: /* 2 byte delta orus after last edge */
+ adj_orus = NEXT_WORD(pointer);
+ L3: edge = j? sp_globals.Y_edge_org + sp_globals.no_Y_orus - 1: sp_globals.no_X_orus - 1;
+ L4: end_orus = sp_plaid.orus[edge] + adj_orus;
+ end_pix = sp_plaid.pix[edge] +
+ (((fix31)adj_orus * (fix31)(j? sp_globals.tcb.yppo: sp_globals.tcb.xppo) +
+ sp_globals.mprnd) / (1<<sp_globals.mpshift));
+ break;
+
+ }
+
+ if (l) /* Second time round loop? */
+ break;
+ format_copy >>= 3; /* Adj format to decode end point format */
+ start_orus = end_orus; /* Save start point oru value */
+ start_pix = end_pix; /* Save start point pixel value */
+ }
+ }
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+ record_int_zone(
+ (fix31)start_pix << (16 - sp_globals.pixshift),
+ (fix31)end_pix << (16 - sp_globals.pixshift));
+#endif
+ zone_orus = (fix31)end_orus - (fix31)start_orus;
+ sp_plaid.mult[i] = ((((fix31)end_pix - (fix31)start_pix) << sp_globals.mpshift) +
+ (zone_orus / 2)) / zone_orus;
+ sp_plaid.offset[i] =
+ (((((fix31)start_pix + (fix31)end_pix) << sp_globals.mpshift) -
+ ((fix31)sp_plaid.mult[i] * ((fix31)start_orus + (fix31)end_orus))) / 2) +
+ sp_globals.mprnd;
+ i++;
+ }
+ if (j) /* Finished? */
+ break;
+ edge_org = sp_globals.Y_edge_org; /* Prepare to process Y ctrl zones */
+ n = no_Y_int_zones;
+ }
+
+#if DEBUG
+printf("\nX INT TABLE\n");
+n = no_X_int_zones;
+for (i = 0; i < n; i++)
+ {
+ printf("%2d %7.4f %7.4f\n", i,
+ (real)sp_plaid.mult[i] / (real)(1 << sp_globals.multshift),
+ (real)sp_plaid.offset[i] / (real)(1 << sp_globals.multshift));
+ }
+printf("\nY INT TABLE\n");
+n = no_Y_int_zones;
+for (i = 0; i < n; i++)
+ {
+ j = i + no_X_int_zones;
+ printf("%2d %7.4f %7.4f\n", i,
+ (real)sp_plaid.mult[j] / (real)(1 << sp_globals.multshift),
+ (real)sp_plaid.offset[j] / (real)(1 << sp_globals.multshift));
+ }
+#endif
+
+return pointer;
+}
+#endif
+#if INCL_ISW
+FUNCTION fix31 compute_isw_scale()
+GDECL
+{
+fix31 isw_scale;
+
+if (sp_globals.setwidth_orus == 0)
+ isw_scale = 0x00010000;
+else
+ isw_scale = ((fix31)sp_globals.imported_width << 16)/
+ (fix31)sp_globals.setwidth_orus;
+return isw_scale;
+}
+#endif
diff --git a/src/Speedo/spdo_prv.h b/src/Speedo/spdo_prv.h
new file mode 100644
index 0000000..47c5252
--- /dev/null
+++ b/src/Speedo/spdo_prv.h
@@ -0,0 +1,425 @@
+/* $Xorg: spdo_prv.h,v 1.3 2000/08/17 19:46:27 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+
+
+/***************************** S P D O _ P R V . H *******************************/
+
+#include "speedo.h" /* include public definitions */
+
+/***** CONFIGURATION DEFINITIONS *****/
+
+
+#ifndef INCL_PLAID_OUT
+#define INCL_PLAID_OUT 0 /* 1 to include plaid data monitoring */
+#endif /* 0 to omit plaid data monitoring */
+
+
+/***** PRIVATE FONT HEADER OFFSET CONSTANTS *****/
+#define FH_ORUMX 0 /* U Max ORU value 2 bytes */
+#define FH_PIXMX 2 /* U Max Pixel value 2 bytes */
+#define FH_CUSNR 4 /* U Customer Number 2 bytes */
+#define FH_OFFCD 6 /* E Offset to Char Directory 3 bytes */
+#define FH_OFCNS 9 /* E Offset to Constraint Data 3 bytes */
+#define FH_OFFTK 12 /* E Offset to Track Kerning 3 bytes */
+#define FH_OFFPK 15 /* E Offset to Pair Kerning 3 bytes */
+#define FH_OCHRD 18 /* E Offset to Character Data 3 bytes */
+#define FH_NBYTE 21 /* E Number of Bytes in File 3 bytes */
+
+
+/***** MODE FLAGS CONSTANTS *****/
+#define CURVES_OUT 0X0008 /* Output module accepts curves */
+#define BOGUS_MODE 0X0010 /* Linear scaling mode */
+#define CONSTR_OFF 0X0020 /* Inhibit constraint table */
+#define IMPORT_WIDTHS 0X0040 /* Imported width mode */
+#define SQUEEZE_LEFT 0X0100 /* Squeeze left mode */
+#define SQUEEZE_RIGHT 0X0200 /* Squeeze right mode */
+#define SQUEEZE_TOP 0X0400 /* Squeeze top mode */
+#define SQUEEZE_BOTTOM 0X0800 /* Squeeze bottom mode */
+#define CLIP_LEFT 0X1000 /* Clip left mode */
+#define CLIP_RIGHT 0X2000 /* Clip right mode */
+#define CLIP_TOP 0X4000 /* Clip top mode */
+#define CLIP_BOTTOM 0X8000 /* Clip bottom mode */
+
+
+/***** MACRO DEFINITIONS *****/
+
+#define SQUEEZE_MULT(A,B) (((fix31)A * (fix31)B) / (1 << 16))
+
+#define NEXT_BYTE(A) (*(A)++)
+
+#define NEXT_WORD(A) \
+ ((fix15)(sp_globals.key32 ^ ((A) += 2, \
+ ((fix15)((A)[-1]) << 8) | (fix15)((A)[-2]) | \
+ ((A)[-1] & 0x80? ~0xFFFF : 0))))
+
+#if INCL_EXT /* Extended fonts supported? */
+
+#define NEXT_BYTES(A, B) \
+ (((B = (ufix16)(*(A)++) ^ sp_globals.key7) >= 248)? \
+ ((ufix16)(B & 0x07) << 8) + ((*(A)++) ^ sp_globals.key8) + 248: \
+ B)
+
+#else /* Compact fonts only supported? */
+
+#define NEXT_BYTES(A, B) ((*(A)++) ^ sp_globals.key7)
+
+#endif
+
+
+#define NEXT_BYTE_U(A) (*(A)++)
+
+#define NEXT_WORD_U(A, B) \
+ (fix15)(B = (*(A)++) << 8, (fix15)(*(A)++) + B)
+
+#define NEXT_CHNDX(A, B) \
+ ((B)? (ufix16)NEXT_WORD(A): (ufix16)NEXT_BYTE(A))
+
+/* Multiply (fix15)X by (fix15)Y to produce (fix31)product */
+#define MULT16(X, Y) \
+ ((fix31)X * (fix31)Y)
+
+/* Multiply (fix15)X by (fix15)MULT, add (fix31)OFFSET,
+ * shift right SHIFT bits to produce (fix15)result */
+#define TRANS(X, MULT, OFFSET, SHIFT) \
+ ((fix15)((((fix31)X * (fix31)MULT) + OFFSET) / (1 << SHIFT)))
+
+/******************************************************************************
+ *
+ * the following block of definitions redefines every function
+ * reference to be prefixed with an "sp_". In addition, if this
+ * is a reentrant version, the parameter sp_globals will be added
+ * as the first parameter.
+ *
+ *****************************************************************************/
+
+#if STATIC_ALLOC || DYNAMIC_ALLOC
+
+#define GDECL
+
+#define get_char_id(char_index) sp_get_char_id(char_index)
+#define get_char_width(char_index) sp_get_char_width(char_index)
+#define get_track_kern(track,point_size) sp_get_track_kern(track,point_size)
+#define get_pair_kern(char_index1,char_index2) sp_get_pair_kern(char_index1,char_index2)
+#define get_char_bbox(char_index,bbox) sp_get_char_bbox(char_index,bbox)
+#define make_char(char_index) sp_make_char(char_index)
+#if INCL_ISW
+#define compute_isw_scale() sp_compute_isw_scale()
+#define do_make_char(char_index) sp_do_make_char(char_index)
+#define make_char_isw(char_index,imported_width) sp_make_char_isw(char_index,imported_width)
+#define reset_xmax(xmax) sp_reset_xmax(xmax)
+#endif
+#if INCL_ISW || INCL_SQUEEZING
+#define preview_bounding_box(pointer,format) sp_preview_bounding_box(pointer,format)
+#endif
+#define make_simp_char(pointer,format) sp_make_simp_char(pointer,format)
+#define make_comp_char(pointer) sp_make_comp_char(pointer)
+#define get_char_org(char_index,top_level) sp_get_char_org(char_index,top_level)
+#define get_posn_arg(ppointer,format) sp_get_posn_arg(ppointer,format)
+#define get_scale_arg(ppointer,format) sp_get_scale_arg(ppointer,format)
+#define read_bbox(ppointer,pPmin,pPmax,set_flag) sp_read_bbox(ppointer,pPmin,pPmax,set_flag)
+#define proc_outl_data(pointer) sp_proc_outl_data(pointer)
+#define split_curve(P1,P2,P3,depth) sp_split_curve(P1,P2,P3,depth)
+#define get_args(ppointer,format,pP) sp_get_args(ppointer,format,pP)
+
+#define init_black(specsarg) sp_init_black(specsarg)
+#define begin_char_black(Psw,Pmin,Pmax) sp_begin_char_black(Psw,Pmin,Pmax)
+#define begin_contour_black(P1,outside) sp_begin_contour_black(P1,outside)
+#define line_black(P1) sp_line_black(P1)
+#define end_char_black() sp_end_char_black()
+#define add_intercept_black(y,x) sp_add_intercept_black(y,x)
+#define proc_intercepts_black() sp_proc_intercepts_black()
+
+#define init_screen(specsarg) sp_init_screen(specsarg)
+#define begin_char_screen(Psw,Pmin,Pmax) sp_begin_char_screen(Psw,Pmin,Pmax)
+#define begin_contour_screen(P1,outside) sp_begin_contour_screen(P1,outside)
+#define curve_screen(P1,P2,P3,depth) sp_curve_screen(P1,P2,P3,depth)
+#define scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3) sp_scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3)
+#define vert_line_screen(x,y1,y2) sp_vert_line_screen(x,y1,y2)
+#define line_screen(P1) sp_line_screen(P1)
+#define end_contour_screen() sp_end_contour_screen()
+#define end_char_screen() sp_end_char_screen()
+#define add_intercept_screen(y,x) sp_add_intercept_screen(y,x)
+#define proc_intercepts_screen() sp_proc_intercepts_screen()
+
+#define init_outline(specsarg) sp_init_outline(specsarg)
+#define begin_char_outline(Psw,Pmin,Pmax) sp_begin_char_outline(Psw,Pmin,Pmax)
+#define begin_sub_char_outline(Psw,Pmin,Pmax) sp_begin_sub_char_outline(Psw,Pmin,Pmax)
+#define begin_contour_outline(P1,outside) sp_begin_contour_outline(P1,outside)
+#define curve_outline(P1,P2,P3,depth) sp_curve_outline(P1,P2,P3,depth)
+#define line_outline(P1) sp_line_outline(P1)
+#define end_contour_outline() sp_end_contour_outline()
+#define end_sub_char_outline() sp_end_sub_char_outline()
+#define end_char_outline() sp_end_char_outline()
+
+#define init_2d(specsarg) sp_init_2d(specsarg)
+#define begin_char_2d(Psw, Pmin, Pmax) sp_begin_char_2d(Psw, Pmin, Pmax)
+#define begin_contour_2d(P1, outside) sp_begin_contour_2d(P1, outside)
+#define line_2d(P1) sp_line_2d(P1)
+#define end_char_2d() sp_end_char_2d()
+#define add_intercept_2d(y, x) sp_add_intercept_2d(y, x)
+#define proc_intercepts_2d() sp_proc_intercepts_2d()
+#define draw_vector_to_2d(x0, y0, x1, y1, band) sp_draw_vector_to_2d(x0, y0, x1, y1, band)
+
+#define init_char_out(Psw,Pmin,Pmax) sp_init_char_out(Psw,Pmin,Pmax)
+#define begin_sub_char_out(Psw,Pmin,Pmax) sp_begin_sub_char_out(Psw,Pmin,Pmax)
+#define curve_out(P1,P2,P3,depth) sp_curve_out(P1,P2,P3,depth)
+#define end_contour_out() sp_end_contour_out()
+#define end_sub_char_out() sp_end_sub_char_out()
+#define init_intercepts_out() sp_init_intercepts_out()
+#define restart_intercepts_out() sp_restart_intercepts_out()
+#define set_first_band_out(Pmin,Pmax) sp_set_first_band_out(Pmin,Pmax)
+#define reduce_band_size_out() sp_reduce_band_size_out()
+#define next_band_out() sp_next_band_out()
+
+#define init_userout(specsarg) sp_init_userout(specsarg)
+
+#define reset() sp_reset()
+#define set_key(key) sp_set_key(key)
+#define get_cust_no(font_buff) sp_get_cust_no(font_buff)
+#define set_specs(specsarg) sp_set_specs(specsarg)
+#define setup_consts(xmin,xmax,ymin,ymax) sp_setup_consts(xmin,xmax,ymin,ymax)
+#define setup_tcb(ptcb) sp_setup_tcb(ptcb)
+#define setup_mult(input_mult) sp_setup_mult(input_mult)
+#define setup_offset(input_offset) sp_setup_offset(input_offset)
+#define type_tcb(ptcb) sp_type_tcb(ptcb)
+#define read_long(pointer) sp_read_long(pointer)
+#define read_word_u(pointer) sp_read_word_u(pointer)
+#define init_tcb() sp_init_tcb()
+#define scale_tcb(ptcb,x_pos,y_pos,x_scale,y_scale) sp_scale_tcb(ptcb,x_pos,y_pos,x_scale,y_scale)
+#define plaid_tcb(ppointer,format) sp_plaid_tcb(ppointer,format)
+#define skip_orus(ppointer,short_form,no_ctrl_zones) sp_skip_orus(ppointer,short_form,no_ctrl_zones)
+#define skip_interpolation_table(ppointer,format) sp_skip_interpolation_table(ppointer,format)
+#define skip_control_zone(ppointer,format) sp_skip_control_zone(ppointer,format)
+#define constr_update() sp_constr_update()
+#define read_oru_table(ppointer) sp_read_oru_table(ppointer)
+#define calculate_x_pix(start_edge,end_edge,constr_nr,x_scale,x_offset,ppo,setwidth_pix) sp_calculate_x_pix(start_edge,end_edge,constr_nr,x_scale,x_offset,ppo,setwidth_pix)
+#define calculate_y_pix(start_edge,end_edge,constr_nr,top_scale,bottom_scale,ppo,emtop_pix,embot_pix) sp_calculate_y_pix(start_edge,end_edge,constr_nr,top_scale,bottom_scale,ppo,emtop_pix,embot_pix)
+#define calculate_x_scale(x_factor,x_offset,no_x_ctrl_zones) sp_calculate_x_scale(x_factor,x_offset,no_x_ctrl_zones)
+#define calculate_y_scale(top_scale,bottom_scale,first_y_zone,no_Y_ctrl_zones) sp_calculate_y_scale(top_scale,bottom_scale,first_y_zone,no_Y_ctrl_zones)
+#define setup_pix_table(ppointer,short_form,no_X_ctrl_zones,no_Y_ctrl_zones) sp_setup_pix_table(ppointer,short_form,no_X_ctrl_zones,no_Y_ctrl_zones)
+#define setup_int_table(ppointer,no_X_int_zones, no_Y_int_zones) sp_setup_int_table(ppointer,no_X_int_zones, no_Y_int_zones)
+
+#define fn_init_out(specsarg) (*sp_globals.init_out)(specsarg)
+#define fn_begin_char(Psw,Pmin,Pmax) (*sp_globals.begin_char)(Psw,Pmin,Pmax)
+#define fn_begin_sub_char(Psw,Pmin,Pmax) (*sp_globals.begin_sub_char)(Psw,Pmin,Pmax)
+#define fn_end_sub_char() (*sp_globals.end_sub_char)()
+#define fn_end_char() (*sp_globals.end_char)()
+#define fn_line(P1) (*sp_globals.line)(P1)
+#define fn_end_contour() (*sp_globals.end_contour)()
+#define fn_begin_contour(P0,fmt) (*sp_globals.begin_contour)(P0,fmt)
+#define fn_curve(P1,P2,P3,depth) (*sp_globals.curve)(P1,P2,P3,depth)
+
+#define load_char_data(offset, no_bytes, buff_off) sp_load_char_data(offset, no_bytes, buff_off)
+#define report_error(n) sp_report_error(n)
+
+#if INCL_MULTIDEV
+
+#define set_bitmap_device(bfuncs,size) sp_set_bitmap_device(bfuncs,size)
+#define set_outline_device(ofuncs,size) sp_set_outline_device(ofuncs,size)
+
+#define open_bitmap(x_set_width, y_set_width, xmin, xmax, ymin, ymax) (*sp_globals.bitmap_device.p_open_bitmap)(x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define set_bitmap_bits(y, xbit1, xbit2) (*sp_globals.bitmap_device.p_set_bits)(y, xbit1, xbit2)
+#define close_bitmap() (*sp_globals.bitmap_device.p_close_bitmap)()
+
+#define open_outline(x_set_width, y_set_width, xmin, xmax, ymin, ymax) (*sp_globals.outline_device.p_open_outline)(x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define start_new_char() (*sp_globals.outline_device.p_start_char)()
+#define start_contour(x,y,outside) (*sp_globals.outline_device.p_start_contour)(x,y,outside)
+#define curve_to(x1,y1,x2,y2,x3,y3) (*sp_globals.outline_device.p_curve)(x1,y1,x2,y2,x3,y3)
+#define line_to(x,y) (*sp_globals.outline_device.p_line)(x,y)
+#define close_contour() (*sp_globals.outline_device.p_close_contour)()
+#define close_outline() (*sp_globals.outline_device.p_close_outline)()
+
+#else
+
+#define open_bitmap(x_set_width, y_set_width, xmin, xmax, ymin, ymax) sp_open_bitmap(x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define set_bitmap_bits(y, xbit1, xbit2) sp_set_bitmap_bits(y, xbit1, xbit2)
+#define close_bitmap() sp_close_bitmap()
+
+#define open_outline(x_set_width, y_set_width, xmin, xmax, ymin, ymax) sp_open_outline(x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define start_new_char() sp_start_new_char()
+#define start_contour(x,y,outside) sp_start_contour(x,y,outside)
+#define curve_to(x1,y1,x2,y2,x3,y3) sp_curve_to(x1,y1,x2,y2,x3,y3)
+#define line_to(x,y) sp_line_to(x,y)
+#define close_contour() sp_close_contour()
+#define close_outline() sp_close_outline()
+
+#endif
+
+#else
+
+#define GDECL SPEEDO_GLOBALS* sp_global_ptr;
+
+#define get_char_id(char_index) sp_get_char_id(sp_global_ptr,char_index)
+#define get_char_width(char_index) sp_get_char_width(sp_global_ptr,char_index)
+#define get_track_kern(track,point_size) sp_get_track_kern(sp_global_ptr,track,point_size)
+#define get_pair_kern(char_index1,char_index2) sp_get_pair_kern(sp_global_ptr,char_index1,char_index2)
+#define get_char_bbox(char_index,bbox) sp_get_char_bbox(sp_global_ptr,char_index,bbox)
+#define make_char(char_index) sp_make_char(sp_global_ptr,char_index)
+#if INCL_ISW
+#define compute_isw_scale() sp_compute_isw_scale(sp_global_ptr)
+#define do_make_char(char_index) sp_do_make_char(sp_global_ptr,char_index)
+#define make_char_isw(char_index,imported_width) sp_make_char_isw(sp_global_ptr,char_index,imported_width)
+#define reset_xmax(xmax) sp_reset_xmax(sp_global_ptr,xmax)
+#endif
+#if INCL_ISW || INCL_SQUEEZING
+#define preview_bounding_box(pointer,format) sp_preview_bounding_box(sp_global_ptr,pointer,format)
+#endif
+#define make_simp_char(pointer,format) sp_make_simp_char(sp_global_ptr,pointer,format)
+#define make_comp_char(pointer) sp_make_comp_char(sp_global_ptr,pointer)
+#define get_char_org(char_index,top_level) sp_get_char_org(sp_global_ptr,char_index,top_level)
+#define get_posn_arg(ppointer,format) sp_get_posn_arg(sp_global_ptr,ppointer,format)
+#define get_scale_arg(ppointer,format) sp_get_scale_arg(sp_global_ptr,ppointer,format)
+#define read_bbox(ppointer,pPmin,pPmax,set_flag) sp_read_bbox(sp_global_ptr,ppointer,pPmin,pPmax,set_flag)
+#define proc_outl_data(pointer) sp_proc_outl_data(sp_global_ptr,pointer)
+#define split_curve(P1,P2,P3,depth) sp_split_curve(sp_global_ptr,P1,P2,P3,depth)
+#define get_args(ppointer,format,pP) sp_get_args(sp_global_ptr,ppointer,format,pP)
+
+#define init_black(specsarg) sp_init_black(sp_global_ptr,specsarg)
+#define begin_char_black(Psw,Pmin,Pmax) sp_begin_char_black(sp_global_ptr,Psw,Pmin,Pmax)
+#define begin_contour_black(P1,outside) sp_begin_contour_black(sp_global_ptr,P1,outside)
+#define line_black(P1) sp_line_black(sp_global_ptr,P1)
+#define end_char_black() sp_end_char_black(sp_global_ptr)
+#define add_intercept_black(y,x) sp_add_intercept_black(sp_global_ptr,y,x)
+#define proc_intercepts_black() sp_proc_intercepts_black(sp_global_ptr)
+
+#define init_screen(specsarg) sp_init_screen(sp_global_ptr,specsarg)
+#define begin_char_screen(Psw,Pmin,Pmax) sp_begin_char_screen(sp_global_ptr,Psw,Pmin,Pmax)
+#define begin_contour_screen(P1,outside) sp_begin_contour_screen(sp_global_ptr,P1,outside)
+#define curve_screen(P1,P2,P3,depth) sp_curve_screen(sp_global_ptr,P1,P2,P3,depth)
+#define scan_curve_screen(X0,Y0,X1,Y1,X2,Y2,X3,Y3) sp_scan_curve_screen(sp_global_ptr,X0,Y0,X1,Y1,X2,Y2,X3,Y3)
+#define vert_line_screen(x,y1,y2) sp_vert_line_screen(sp_global_ptr,x,y1,y2)
+#define line_screen(P1) sp_line_screen(sp_global_ptr,P1)
+#define end_char_screen() sp_end_char_screen(sp_global_ptr)
+#define end_contour_screen() sp_end_contour_screen(sp_global_ptr)
+#define add_intercept_screen(y,x) sp_add_intercept_screen(sp_global_ptr,y,x)
+#define proc_intercepts_screen() sp_proc_intercepts_screen(sp_global_ptr)
+
+#define init_outline(specsarg) sp_init_outline(sp_global_ptr,specsarg)
+#define begin_char_outline(Psw,Pmin,Pmax) sp_begin_char_outline(sp_global_ptr,Psw,Pmin,Pmax)
+#define begin_sub_char_outline(Psw,Pmin,Pmax) sp_begin_sub_char_outline(sp_global_ptr,Psw,Pmin,Pmax)
+#define begin_contour_outline(P1,outside) sp_begin_contour_outline(sp_global_ptr,P1,outside)
+#define curve_outline(P1,P2,P3,depth) sp_curve_outline(sp_global_ptr,P1,P2,P3,depth)
+#define line_outline(P1) sp_line_outline(sp_global_ptr,P1)
+#define end_contour_outline() sp_end_contour_outline(sp_global_ptr)
+#define end_sub_char_outline() sp_end_sub_char_outline(sp_global_ptr)
+#define end_char_outline() sp_end_char_outline(sp_global_ptr)
+
+#define init_2d(specsarg) sp_init_2d(sp_global_ptr,specsarg)
+#define begin_char_2d(Psw, Pmin, Pmax) sp_begin_char_2d(sp_global_ptr,Psw, Pmin, Pmax)
+#define begin_contour_2d(P1, outside) sp_begin_contour_2d(sp_global_ptr,P1, outside)
+#define line_2d(P1) sp_line_2d(sp_global_ptr,P1)
+#define end_char_2d() sp_end_char_2d(sp_global_ptr)
+#define add_intercept_2d(y, x) sp_add_intercept_2d(sp_global_ptr,y, x)
+#define proc_intercepts_2d() sp_proc_intercepts_2d(sp_global_ptr)
+#define draw_vector_to_2d(x0, y0, x1, y1, band) sp_draw_vector_to_2d(sp_global_ptr,x0, y0, x1, y1, band)
+
+#define init_char_out(Psw,Pmin,Pmax) sp_init_char_out(sp_global_ptr,Psw,Pmin,Pmax)
+#define begin_sub_char_out(Psw,Pmin,Pmax) sp_begin_sub_char_out(sp_global_ptr,Psw,Pmin,Pmax)
+#define curve_out(P1,P2,P3,depth) sp_curve_out(sp_global_ptr,P1,P2,P3,depth)
+#define end_contour_out() sp_end_contour_out(sp_global_ptr)
+#define end_sub_char_out() sp_end_sub_char_out(sp_global_ptr)
+#define init_intercepts_out() sp_init_intercepts_out(sp_global_ptr)
+#define restart_intercepts_out() sp_restart_intercepts_out(sp_global_ptr)
+#define set_first_band_out(Pmin,Pmax) sp_set_first_band_out(sp_global_ptr,Pmin,Pmax)
+#define reduce_band_size_out() sp_reduce_band_size_out(sp_global_ptr)
+#define next_band_out() sp_next_band_out(sp_global_ptr)
+
+#define init_userout(specsarg) sp_init_userout(sp_global_ptr,specsarg)
+
+#define reset() sp_reset(sp_global_ptr)
+#define set_key(key) sp_set_key(sp_global_ptr,key)
+#define get_cust_no(font_buff) sp_get_cust_no(sp_global_ptr,font_buff)
+#define set_specs(specsarg) sp_set_specs(sp_global_ptr,specsarg)
+#define setup_consts(xmin,xmax,ymin,ymax) sp_setup_consts(sp_global_ptr,xmin,xmax,ymin,ymax)
+#define setup_tcb(ptcb) sp_setup_tcb(sp_global_ptr,ptcb)
+#define setup_mult(input_mult) sp_setup_mult(sp_global_ptr,input_mult)
+#define setup_offset(input_offset) sp_setup_offset(sp_global_ptr,input_offset)
+#define type_tcb(ptcb) sp_type_tcb(sp_global_ptr,ptcb)
+#define read_long(pointer) sp_read_long(sp_global_ptr,pointer)
+#define read_word_u(pointer) sp_read_word_u(sp_global_ptr,pointer)
+#define init_tcb() sp_init_tcb(sp_global_ptr)
+#define scale_tcb(ptcb,x_pos,y_pos,x_scale,y_scale) sp_scale_tcb(sp_global_ptr,ptcb,x_pos,y_pos,x_scale,y_scale)
+#define plaid_tcb(ppointer,format) sp_plaid_tcb(sp_global_ptr,ppointer,format)
+#define skip_orus(ppointer,short_form,no_ctrl_zones) sp_skip_orus(sp_global_ptr,ppointer,short_form,no_ctrl_zones)
+#define skip_interpolation_table(ppointer,format) sp_skip_interpolation_table(sp_global_ptr,ppointer,format)
+#define skip_control_zone(ppointer,format) sp_skip_control_zone(sp_global_ptr,ppointer,format)
+#define constr_update() sp_constr_update(sp_global_ptr)
+#define read_oru_table(ppointer) sp_read_oru_table(sp_global_ptr,ppointer)
+#define calculate_x_pix(start_edge,end_edge,constr_nr,x_scale,x_offset,ppo,setwidth_pix) sp_calculate_x_pix(sp_global_ptr,start_edge,end_edge,constr_nr,x_scale,x_offset,ppo,setwidth_pix)
+#define calculate_y_pix(start_edge,end_edge,constr_nr,top_scale,bottom_scale,ppo,emtop_pix,embot_pix) sp_calculate_y_pix(sp_global_ptr,start_edge,end_edge,constr_nr,top_scale,bottom_scale,ppo,emtop_pix,embot_pix)
+#define calculate_x_scale(x_factor,x_offset,no_x_ctrl_zones) sp_calculate_x_scale(sp_global_ptr,x_factor,x_offset,no_x_ctrl_zones)
+#define calculate_y_scale(top_scale,bottom_scale,first_y_zone,no_Y_ctrl_zones) sp_calculate_y_scale(sp_global_ptr,top_scale,bottom_scale,first_y_zone,no_Y_ctrl_zones)
+#define setup_pix_table(ppointer,short_form,no_X_ctrl_zones,no_Y_ctrl_zones) sp_setup_pix_table(sp_global_ptr,ppointer,short_form,no_X_ctrl_zones,no_Y_ctrl_zones)
+#define setup_int_table(ppointer,no_X_int_zones, no_Y_int_zones) sp_setup_int_table(sp_global_ptr,ppointer,no_X_int_zones, no_Y_int_zones)
+
+#define fn_init_out(specsarg) (*sp_globals.init_out)(sp_global_ptr,specsarg)
+#define fn_begin_char(Psw,Pmin,Pmax) (*sp_globals.begin_char)(sp_global_ptr,Psw,Pmin,Pmax)
+#define fn_begin_sub_char(Psw,Pmin,Pmax) (*sp_globals.begin_sub_char)(sp_global_ptr,Psw,Pmin,Pmax)
+#define fn_end_sub_char() (*sp_globals.end_sub_char)(sp_global_ptr)
+#define fn_end_char() (*sp_globals.end_char)(sp_global_ptr)
+#define fn_line(P1) (*sp_globals.line)(sp_global_ptr,P1)
+#define fn_end_contour() (*sp_globals.end_contour)(sp_global_ptr)
+#define fn_begin_contour(P0,fmt) (*sp_globals.begin_contour)(sp_global_ptr,P0,fmt)
+#define fn_curve(P1,P2,P3,depth) (*sp_globals.curve)(sp_global_ptr,P1,P2,P3,depth)
+
+
+#define load_char_data(offset, no_bytes, buff_off) sp_load_char_data(sp_global_ptr, offset, no_bytes, buff_off)
+#define report_error(n) sp_report_error(sp_global_ptr, n)
+
+#if INCL_MULTIDEV
+
+#define set_bitmap_device(bfuncs,size) sp_set_bitmap_device(sp_global_ptr,bfuncs,size)
+#define set_outline_device(ofuncs,size) sp_set_outline_device(sp_global_ptr,ofuncs,size)
+
+#define open_bitmap(x_set_width, y_set_width, xmin, xmax, ymin, ymax)(*sp_globals.bitmap_device.p_open_bitmap)(sp_global_ptr,x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define set_bitmap_bits(y, xbit1, xbit2)(*sp_globals.bitmap_device.p_set_bits)(sp_global_ptr,y, xbit1, xbit2)
+#define close_bitmap()(*sp_globals.bitmap_device.p_close_bitmap)(sp_global_ptr)
+
+#define open_outline(x_set_width, y_set_width, xmin, xmax, ymin, ymax)(*sp_globals.outline_device.p_open_outline)(sp_global_ptr,x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define start_new_char()(*sp_globals.outline_device.p_start_char)(sp_global_ptr)
+#define start_contour(x,y,outside)(*sp_globals.outline_device.p_start_contour)(sp_global_ptr,x,y,outside)
+#define curve_to(x1,y1,x2,y2,x3,y3)(*sp_globals.outline_device.p_curve)(sp_global_ptr,x1,y1,x2,y2,x3,y3)
+#define line_to(x,y)(*sp_globals.outline_device.p_line)(sp_global_ptr,x,y)
+#define close_contour()(*sp_globals.outline_device.p_close_contour)(sp_global_ptr)
+#define close_outline()(*sp_globals.outline_device.p_close_outline)(sp_global_ptr)
+
+#else
+
+#define open_bitmap(x_set_width, y_set_width, xmin, xmax, ymin, ymax) sp_open_bitmap(sp_global_ptr, x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define set_bitmap_bits(y, xbit1, xbit2) sp_set_bitmap_bits(sp_global_ptr, y, xbit1, xbit2)
+#define close_bitmap() sp_close_bitmap(sp_global_ptr)
+
+#define open_outline(x_set_width, y_set_width, xmin, xmax, ymin, ymax) sp_open_outline(sp_global_ptr, x_set_width, y_set_width, xmin, xmax, ymin, ymax)
+#define start_new_char() sp_start_new_char(sp_global_ptr )
+#define start_contour(x,y,outside) sp_start_contour(sp_global_ptr, x,y,outside)
+#define curve_to(x1,y1,x2,y2,x3,y3) sp_curve_to(sp_global_ptr, x1,y1,x2,y2,x3,y3)
+#define line_to(x,y) sp_line_to(sp_global_ptr, x,y)
+#define close_contour() sp_close_contour(sp_global_ptr)
+#define close_outline() sp_close_outline(sp_global_ptr)
+
+#endif
+#endif
+
+
diff --git a/src/Speedo/speedo.h b/src/Speedo/speedo.h
new file mode 100644
index 0000000..277c6a6
--- /dev/null
+++ b/src/Speedo/speedo.h
@@ -0,0 +1,1081 @@
+/* $Xorg: speedo.h,v 1.3 2000/08/17 19:46:27 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+#ifndef _SPEEDO_H_
+#define _SPEEDO_H_
+
+#include <X11/Xmd.h>
+
+/***************************** S P E E D O . H *******************************
+ ****************************************************************************/
+
+/***** USER OPTIONS OVERRIDE DEFAULTS ******/
+#include "useropt.h"
+
+/***** CONFIGURATION DEFINITIONS *****/
+
+#ifndef INCL_CLIPPING
+#define INCL_CLIPPING 0 /* 0 indicates CLIPPING code is not compiled in*/
+#endif
+
+#ifndef INCL_SQUEEZING
+#define INCL_SQUEEZING 0 /* 0 indicates SQUEEZE code is not compiled in*/
+#endif
+
+#ifndef INCL_EXT
+#define INCL_EXT 1 /* 1 to include extended font support */
+#endif /* 0 to omit extended font support */
+
+#ifndef INCL_RULES
+#define INCL_RULES 1 /* 1 to include intelligent scaling support */
+#endif /* 0 to omit intelligent scaling support */
+
+#ifndef INCL_BLACK
+#define INCL_BLACK 1 /* 1 to include blackwriter output support */
+#endif /* 0 to omit output mode 0 support */
+
+#ifndef INCL_SCREEN
+#define INCL_SCREEN 0 /* 1 to include screen writeroutput support */
+#endif /* 0 to omit support */
+
+#ifndef INCL_OUTLINE
+#define INCL_OUTLINE 0 /* 1 to include outline output support */
+#endif /* 0 to omit output mode 2 support */
+
+#ifndef INCL_2D
+#define INCL_2D 0 /* 1 to include 2d blackwriter output support */
+#endif /* 0 to omit output mode 3 support */
+
+#ifndef INCL_USEROUT
+#define INCL_USEROUT 0 /* 1 to include user defined output module support */
+#endif /* 0 to omit user defined output module support */
+
+#ifndef INCL_LCD
+#define INCL_LCD 1 /* 1 to include load char data support*/
+#endif /* 0 to omit load char data support */
+#ifndef INCL_ISW
+#define INCL_ISW 0 /* 1 to include imported width support */
+#endif /* 0 to omit imported width support */
+
+#ifndef INCL_METRICS
+#define INCL_METRICS 1 /* 1 to include metrics support */
+#endif /* 0 to omit metrics support */
+
+#ifndef INCL_KEYS
+#define INCL_KEYS 0 /* 1 to include multi key support */
+#endif /* 0 to omit multi key support */
+
+#ifndef INCL_MULTIDEV
+#define INCL_MULTIDEV 0 /* 1 to include multiple output device support */
+#endif /* 0 to omit multi device support */
+
+#ifndef SHORT_LISTS
+#define SHORT_LISTS 1 /* 1 to allocate small intercept lists */
+#endif
+
+#ifndef PROTOS_AVAIL /* 1 to use function prototyping */
+#define PROTOS_AVAIL 0 /* 0 to suppress it */
+#endif
+
+#ifndef FONTFAR /* if Intel mixed memory model implementation */
+#define FONTFAR /* pointer type modifier for font buffer */
+#endif
+
+#ifndef STACKFAR /* if Intel mixed memory model implementation */
+#define STACKFAR /* pointer type modifier for font buffer */
+#endif
+
+#ifndef GLOBALFAR
+#define GLOBALFAR
+#endif
+
+#define MODE_BLACK 0
+#define MODE_SCREEN MODE_BLACK + INCL_BLACK
+#define MODE_OUTLINE MODE_SCREEN + INCL_SCREEN
+#define MODE_2D MODE_OUTLINE + INCL_OUTLINE
+
+#ifdef DYNAMIC_ALLOC
+#if DYNAMIC_ALLOC
+#define STATIC_ALLOC 0
+#endif
+#endif
+
+#ifdef REENTRANT_ALLOC
+#if REENTRANT_ALLOC
+#define STATIC_ALLOC 0
+#endif
+#endif
+
+#ifndef STATIC_ALLOC
+#define STATIC_ALLOC 1
+#endif
+
+#ifndef DYNAMIC_ALLOC
+#define DYNAMIC_ALLOC 0
+#endif
+
+#ifndef REENTRANT_ALLOC
+#define REENTRANT_ALLOC 0
+#endif
+
+/***** TYPE DEFINITIONS *****/
+
+#ifndef STDEF
+#ifndef SPD_BMAP
+
+typedef INT8 fix7;
+
+typedef double real;
+
+typedef CARD8 ufix8;
+#ifndef VFONT
+typedef CARD8 boolean;
+#endif
+#endif
+
+typedef INT16 fix15;
+
+typedef CARD16 ufix16;
+
+typedef INT32 fix31;
+
+typedef CARD32 ufix32;
+#endif
+
+/***** GENERAL CONSTANTS *****/
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define FUNCTION
+
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+#if INCL_EXT /* Extended fonts supported? */
+
+#define MAX_CONSTR 750 /* Max constraints (incl 4 dummies) */
+#define MAX_CTRL_ZONES 256 /* Max number of controlled orus */
+#define MAX_INT_ZONES 256 /* Max number of interpolation zones */
+
+#else /* Compact fonts only supported */
+
+#define MAX_CONSTR 512 /* Max constraints (incl 4 dummies) */
+#define MAX_CTRL_ZONES 64 /* Max number of controlled orus */
+#define MAX_INT_ZONES 64 /* Max number of interpolation zones */
+
+#endif
+
+#define SCALE_SHIFT 12 /* Binary point positiion for scale values */
+#define SCALE_RND 2048 /* Rounding bit for scaling transformation */
+#define ONE_SCALE 4096 /* Unity scale value */
+
+#ifdef INCL_SCREEN /* constants used by Screenwriter module */
+#define LEFT_INT 1 /* left intercept */
+#define END_INT 2 /* last intercept */
+#define FRACTION 0xFC /* fractional portion of intercept type list */
+#endif
+
+#if INCL_SQUEEZING || INCL_CLIPPING /* constants used by SQUEEZEing code */
+#define EM_TOP 764
+#define EM_BOT -236
+#endif
+
+/***** STRUCTURE DEFINITIONS *****/
+#if PROTOS_AVAIL
+
+#if REENTRANT_ALLOC
+#define PROTO_DECL1 struct speedo_global_data GLOBALFAR *sp_global_ptr
+#define PROTO_DECL2 PROTO_DECL1 ,
+#else
+#define PROTO_DECL1 void
+#define PROTO_DECL2
+#endif
+#endif
+
+typedef
+struct buff_tag
+ {
+ ufix8 FONTFAR *org; /* Pointer to start of buffer */
+ ufix32 no_bytes; /* Size of buffer in bytes */
+ }
+buff_t; /* Buffer descriptor */
+
+typedef struct constr_tag
+ {
+ ufix8 FONTFAR *org; /* Pointer to first byte in constr data */
+ ufix16 font_id; /* Font id for calculated data */
+ fix15 xppo; /* X pixels per oru for calculated data */
+ fix15 yppo; /* Y pixels per oru for calculated data */
+ boolean font_id_valid; /* TRUE if font id valid */
+ boolean data_valid; /* TRUE if calculated data valid */
+ boolean active; /* TRUE if constraints enabled */
+ }
+constr_t; /* Constraint data state */
+
+typedef struct kern_tag
+ {
+ ufix8 FONTFAR *tkorg; /* First byte of track kerning data */
+ ufix8 FONTFAR *pkorg; /* First byte of pair kerning data */
+ fix15 no_tracks; /* Number of kerning tracks */
+ fix15 no_pairs; /* Number of kerning pairs */
+ }
+kern_t; /* Kerning control block */
+
+typedef struct specs_tag
+ {
+ buff_t STACKFAR *pfont; /* Pointer to font data */
+ fix31 xxmult; /* Coeff of X orus to compute X pix */
+ fix31 xymult; /* Coeff of Y orus to compute X pix */
+ fix31 xoffset; /* Constant to compute X pix */
+ fix31 yxmult; /* Coeff of X orus to compute Y pix */
+ fix31 yymult; /* Coeff of Y orus to compute Y pix */
+ fix31 yoffset; /* Constant to compute Y pix */
+ ufix32 flags; /* Mode flags: */
+ /* Bit 0 - 2: Output module selector: */
+ /* Bit 3: Send curves to output module*/
+ /* Bit 4: Use linear scaling if set */
+ /* Bit 5: Inhibit constraint table */
+ /* Bit 6: Import set width if set */
+ /* Bit 7: not used */
+ /* Bit 8: Squeeze left if set */
+ /* Bit 9: Squeeze right if set */
+ /* Bit 10: Squeeze top if set */
+ /* Bit 11: Squeeze bottom if set */
+ /* Bit 12: Clip left if set */
+ /* Bit 13: Clip right if set */
+ /* Bit 14: Clip top if set */
+ /* Bit 15: Clip bottom if set */
+ /* Bits 16-31 not used */
+#ifdef __STDC__
+ void *out_info; /* information for output module */
+#else
+ char *out_info;
+#endif
+ }
+specs_t; /* Specs structure for fw_set_specs */
+
+typedef struct tcb_tag
+ {
+ fix15 xxmult; /* Linear coeff of Xorus to compute Xpix */
+ fix15 xymult; /* Linear coeff of Yorus to compute Xpix */
+ fix31 xoffset; /* Linear constant to compute Xpix */
+ fix15 yxmult; /* Linear coeff of Xorus to compute Ypix */
+ fix15 yymult; /* Linear coeff of Yorus to compute Ypix */
+ fix31 yoffset; /* Linear constant to compute Ypix */
+ fix15 xppo; /* Pixels per oru in X dimension of char */
+ fix15 yppo; /* Pixels per oru in Y dimension of char */
+ fix15 xpos; /* Origin in X dimension of character */
+ fix15 ypos; /* Origin in Y dimension of character */
+ ufix16 xtype; /* Transformation type for X oru coords */
+ ufix16 ytype; /* Transformation type for Y oru coords */
+ ufix16 xmode; /* Transformation mode for X oru coords */
+ ufix16 ymode; /* Transformation mode for Y oru coords */
+ fix15 mirror; /* Transformation creates mirror image */
+ }
+tcb_t; /* Transformation control block */
+
+typedef struct point_tag
+ {
+ fix15 x; /* X coord of point (shifted pixels) */
+ fix15 y; /* Y coord of point (shifted pixels) */
+ }
+point_t; /* Point in device space */
+
+typedef struct band_tag
+ {
+ fix15 band_max;
+ fix15 band_min;
+ fix15 band_array_offset;
+ fix15 band_floor;
+ fix15 band_ceiling;
+ } band_t;
+
+typedef struct bbox_tag
+ {
+ fix31 xmin;
+ fix31 xmax;
+ fix31 ymin;
+ fix31 ymax;
+ } bbox_t;
+
+#if SHORT_LISTS
+#define MAX_INTERCEPTS 256 /* Max storage for intercepts */
+typedef ufix8 cdr_t; /* 8 bit links in intercept chains */
+#else
+#define MAX_INTERCEPTS 1000 /* Max storage for intercepts */
+typedef ufix16 cdr_t; /* 16 bit links in intercept chains */
+#endif
+
+#if REENTRANT_ALLOC
+
+typedef struct intercepts_tag
+ {
+ fix15 car[MAX_INTERCEPTS];
+ fix15 cdr[MAX_INTERCEPTS];
+#if INCL_SCREEN
+ ufix8 inttype[MAX_INTERCEPTS];
+ ufix8 leftedge;
+ ufix16 fracpix;
+#endif
+ } intercepts_t;
+
+typedef struct plaid_tag
+ {
+ fix15 orus[MAX_CTRL_ZONES]; /* Controlled coordinate table (orus) */
+#if INCL_RULES
+ fix15 pix[MAX_CTRL_ZONES]; /* Controlled coordinate table (sub-pixels) */
+ fix15 mult[MAX_INT_ZONES]; /* Interpolation multiplier table */
+ fix31 offset[MAX_INT_ZONES]; /* Interpolation offset table */
+#endif
+ } plaid_t;
+#endif
+
+#if INCL_MULTIDEV
+#if PROTOS_AVAIL
+typedef struct bitmap_tag
+ {
+ void (*p_open_bitmap)(PROTO_DECL2 fix31 x_set_width, fix31 y_set_width, fix31 xorg, fix31 yorg, fix15 xsize,fix15 ysize);
+ void (*p_set_bits)(PROTO_DECL2 fix15 y, fix15 xbit1, fix15 xbit2);
+ void (*p_close_bitmap)(PROTO_DECL1);
+ } bitmap_t;
+
+typedef struct outline_tag
+ {
+ void (*p_open_outline)(PROTO_DECL2 fix31 x_set_width, fix31 y_set_width, fix31 xmin, fix31 xmax, fix31 ymin,fix31 ymax);
+ void (*p_start_char)(PROTO_DECL1);
+ void (*p_start_contour)(PROTO_DECL2 fix31 x,fix31 y,boolean outside);
+ void (*p_curve)(PROTO_DECL2 fix31 x1, fix31 y1, fix31 x2, fix31 y2, fix31 x3, fix31 y3);
+ void (*p_line)(PROTO_DECL2 fix31 x, fix31 y);
+ void (*p_close_contour)(PROTO_DECL1);
+ void (*p_close_outline)(PROTO_DECL1);
+ } outline_t;
+#else
+typedef struct bitmap_tag
+ {
+ void (*p_open_bitmap)();
+ void (*p_set_bits)();
+ void (*p_close_bitmap)();
+ } bitmap_t;
+
+typedef struct outline_tag
+ {
+ void (*p_open_outline)();
+ void (*p_start_char)();
+ void (*p_start_contour)();
+ void (*p_curve)();
+ void (*p_line)();
+ void (*p_close_contour)();
+ void (*p_close_outline)();
+ } outline_t;
+#endif
+#endif
+
+/* ---------------------------------------------------*/
+/**** MAIN GLOBAL DATA STRUCTURE, SPEEDO_GLOBALS *****/
+
+typedef struct speedo_global_data
+ {
+/* do_char.c data definitions */
+#if INCL_METRICS /* Metrics functions supported? */
+ kern_t kern; /* Kerning control block */
+#endif /* endif incl_metrics */
+ point_t Psw; /* End of escapement vector (1/65536 pixel units) */
+
+#if INCL_LCD /* Dynamic load character data supported? */
+ fix15 cb_offset; /* Offset to sub-char data in char buffer */
+#endif /* endif incl_lcd */
+
+/* do_trns.c data definitions */
+ point_t P0; /* Current point (sub-pixels) */
+ fix15 x_orus; /* Current X argument (orus) */
+ fix15 y_orus; /* Current Y argument (orus) */
+ fix15 x_pix; /* Current X argument (sub-pixels) */
+ fix15 y_pix; /* Current Y argument (sub-pixels) */
+ ufix8 x_int; /* Current X interpolation zone */
+ ufix8 y_int; /* Current Y interpolation zone */
+
+#if INCL_MULTIDEV && INCL_OUTLINE
+ outline_t outline_device;
+ boolean outline_device_set;
+#endif
+
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+#if INCL_MULTIDEV
+ bitmap_t bitmap_device;
+ boolean bitmap_device_set;
+#endif
+ band_t y_band; /* Y current band(whole pixels) */
+
+ struct set_width_tag
+ {
+ fix31 x;
+ fix31 y;
+ } set_width; /* Character escapement vector */
+
+ boolean first_pass; /* TRUE during first pass thru outline data */
+ boolean extents_running; /* T if extent accumulation for each vector */
+ fix15 x0_spxl; /* X coord of current point (sub pixels) */
+ fix15 y0_spxl; /* Y coord of current point (sub pixels) */
+ fix15 y_pxl; /* Y coord of current point (whole pixels) */
+#if REENTRANT_ALLOC
+ intercepts_t STACKFAR *intercepts;
+#else /* else if not reentrant */
+ fix15 car[MAX_INTERCEPTS]; /* Data field of intercept storage */
+ cdr_t cdr[MAX_INTERCEPTS]; /* Link field of intercept storage */
+#if INCL_SCREEN
+ ufix8 inttype[MAX_INTERCEPTS];
+ ufix8 leftedge;
+ ufix16 fracpix;
+#endif /* endif incl_screen */
+#endif /* endif reentrant */
+ fix15 bmap_xmin; /* Min X value (sub-pixel units) */
+ fix15 bmap_xmax; /* Max X value (sub-pixel units) */
+ fix15 bmap_ymin; /* Min Y value (sub-pixel units) */
+ fix15 bmap_ymax; /* Max Y value (sub-pixel units) */
+ fix15 no_y_lists; /* Number of active intercept lists */
+ fix15 first_offset; /* Index of first active list cell */
+ fix15 next_offset; /* Index of next free list cell */
+ boolean intercept_oflo; /* TRUE if intercepts data lost */
+#endif /* endif incl_black, incl_screen, incl_2d */
+
+/* bounding box now used by all output modules, including outline */
+ fix15 xmin; /* Min X value in whole character */
+ fix15 xmax; /* Max X value in whole character */
+ fix15 ymin; /* Min Y value in whole character */
+ fix15 ymax; /* Max Y value in whole character */
+
+#if INCL_2D
+ fix15 no_x_lists; /* Number of active x intercept lists */
+ band_t x_band; /* X current band(whole pixels) */
+ boolean x_scan_active; /* X scan flag during scan conversion */
+#endif
+
+/* reset.c data definitions */
+ ufix16 key32; /* Decryption keys 3,2 combined */
+ ufix8 key4; /* Decryption key 4 */
+ ufix8 key6; /* Decryption key 6 */
+ ufix8 key7; /* Decryption key 7 */
+ ufix8 key8; /* Decryption key 8 */
+
+/* set_spcs.c data definitions */
+ buff_t font;
+ buff_t GLOBALFAR *pfont; /* Pointer to font buffer structure */
+ fix31 font_buff_size; /* Number of bytes loaded in font buffer */
+ ufix8 FONTFAR *pchar_dir; /* Pointer to character directory */
+ fix15 first_char_idx; /* Index to first character in font */
+ fix15 no_chars_avail; /* Total characters in font layout */
+ fix15 orus_per_em; /* Outline resolution */
+ fix15 metric_resolution; /* metric resolution for setwidths, kerning pairs
+ (defaults to orus_per_em) */
+ tcb_t tcb0; /* Top level transformation control block */
+
+ boolean specs_valid; /* TRUE if fw_set_specs() successful */
+
+ fix15 depth_adj; /* Curve splitting depth adjustment */
+ boolean curves_out; /* Allow curves to output module */
+ fix15 output_mode; /* Output module selector */
+ fix15 thresh; /* Scan conversion threshold (sub-pixels) */
+ boolean normal; /* TRUE if 0 obl and mult of 90 deg rot */
+
+ fix15 multshift; /* Fixed point shift for multipliers */
+ fix15 pixshift; /* Fixed point shift for sub-pixels */
+ fix15 poshift; /* Left shift from pixel to output format */
+ fix15 mpshift; /* Fixed point shift for mult to sub-pixels */
+ fix31 multrnd; /* 0.5 in multiplier units */
+ fix15 pixrnd; /* 0.5 in sub-pixel units */
+ fix31 mprnd; /* 0.5 sub-pixels in multiplier units */
+ fix15 pixfix; /* Mask to remove fractional pixels */
+ fix15 onepix; /* 1.0 pixels in sub-pixel units */
+
+#if PROTOS_AVAIL
+ boolean (*init_out)(PROTO_DECL2 specs_t GLOBALFAR *specsarg);
+ boolean (*begin_char)(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+ void (*begin_sub_char)(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+ void (*begin_contour)(PROTO_DECL2 point_t P1,boolean outside);
+ void (*curve)(PROTO_DECL2 point_t P1, point_t P2, point_t P3, fix15 depth);
+ void (*line)(PROTO_DECL2 point_t P1);
+ void (*end_contour)(PROTO_DECL1);
+ void (*end_sub_char)(PROTO_DECL1);
+ boolean (*end_char)(PROTO_DECL1);
+#else /* if not protos */
+ boolean (*init_out)();
+ boolean (*begin_char)();
+ void (*begin_sub_char)();
+ void (*begin_contour)();
+ void (*curve)();
+ void (*line)();
+ void (*end_contour)();
+ void (*end_sub_char)();
+ boolean (*end_char)();
+#endif /* end not protos */
+
+ specs_t GLOBALFAR *pspecs; /* Pointer to specifications bundle */
+ specs_t specs; /* copy specs onto stack */
+ ufix8 FONTFAR *font_org; /* Pointer to start of font data */
+ ufix8 FONTFAR *hdr2_org; /* Pointer to start of private header data */
+
+/* set_trns.c data definitions */
+ tcb_t tcb; /* Current transformation control block */
+ ufix8 Y_edge_org; /* Index to first Y controlled coordinate */
+ ufix8 Y_int_org; /* Index to first Y interpolation zone */
+ fix31 rnd_xmin; /* rounded out value of xmin for int-char spac. fix */
+
+#if REENTRANT_ALLOC
+ plaid_t STACKFAR *plaid;
+#else /* if not reentrant */
+ fix15 orus[MAX_CTRL_ZONES]; /* Controlled coordinate table (orus) */
+#if INCL_RULES
+ fix15 pix[MAX_CTRL_ZONES]; /* Controlled coordinate table (sub-pixels) */
+ fix15 mult[MAX_INT_ZONES]; /* Interpolation multiplier table */
+ fix31 offset[MAX_INT_ZONES]; /* Interpolation offset table */
+#endif /* endif incl_rules */
+#endif /* endif not reentrant */
+
+ fix15 no_X_orus; /* Number of X controlled coordinates */
+ fix15 no_Y_orus; /* Number of Y controlled coordinates */
+ ufix16 Y_constr_org; /* Origin of constraint table in font data */
+
+#if INCL_RULES
+ constr_t constr; /* Constraint data state */
+ boolean c_act[MAX_CONSTR]; /* TRUE if constraint currently active */
+ fix15 c_pix[MAX_CONSTR]; /* Size of constrained zone if active */
+#endif
+#if INCL_ISW
+ boolean import_setwidth_act; /* boolean to indicate imported setwidth */
+ boolean isw_modified_constants;
+ ufix32 imported_width; /* value of imported setwidth */
+ fix15 isw_xmax; /* maximum oru value for constants*/
+#endif
+#if INCL_SQUEEZING || INCL_ISW
+ fix15 setwidth_orus; /* setwidth value in orus */
+ /* bounding box in orus for squeezing */
+ fix15 bbox_xmin_orus; /* X minimum in orus */
+ fix15 bbox_xmax_orus; /* X maximum in orus */
+ fix15 bbox_ymin_orus; /* Y minimum in orus */
+ fix15 bbox_ymax_orus; /* Y maximum in orus */
+#endif
+#ifdef INCL_SQUEEZING
+ boolean squeezing_compound; /* flag to indicate a compound character*/
+#endif
+#ifdef INCL_CLIPPING
+ fix31 clip_xmax;
+ fix31 clip_ymax;
+ fix31 clip_xmin;
+ fix31 clip_ymin;
+#endif
+ } SPEEDO_GLOBALS;
+
+/***********************************************************************************
+ *
+ * Speedo global data structure allocation
+ *
+ ***********************************************************************************/
+
+#ifdef SET_SPCS
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+#if STATIC_ALLOC
+EXTERN SPEEDO_GLOBALS GLOBALFAR sp_globals;
+#define sp_intercepts sp_globals
+#define sp_plaid sp_globals
+#else
+#if DYNAMIC_ALLOC
+EXTERN SPEEDO_GLOBALS GLOBALFAR *sp_global_ptr;
+#define sp_globals (*sp_global_ptr)
+#define sp_intercepts (*sp_global_ptr)
+#define sp_plaid (*sp_global_ptr)
+#else
+#if REENTRANT_ALLOC
+#define sp_globals (*sp_global_ptr)
+#define sp_intercepts (*(*sp_global_ptr).intercepts)
+#define sp_plaid (*(*sp_global_ptr).plaid)
+#endif
+#endif
+#endif
+#ifdef EXTERN
+#undef EXTERN
+#endif
+
+
+/***** PUBLIC FONT HEADER OFFSET CONSTANTS *****/
+#define FH_FMVER 0 /* U D4.0 CR LF NULL NULL 8 bytes */
+#define FH_FNTSZ 8 /* U Font size (bytes) 4 bytes */
+#define FH_FBFSZ 12 /* U Min font buffer size (bytes) 4 bytes */
+#define FH_CBFSZ 16 /* U Min char buffer size (bytes) 2 bytes */
+#define FH_HEDSZ 18 /* U Header size (bytes) 2 bytes */
+#define FH_FNTID 20 /* U Source Font ID 2 bytes */
+#define FH_SFVNR 22 /* U Source Font Version Number 2 bytes */
+#define FH_FNTNM 24 /* U Source Font Name 70 bytes */
+#define FH_MDATE 94 /* U Manufacturing Date 10 bytes */
+#define FH_LAYNM 104 /* U Layout Name 70 bytes */
+#define FH_CPYRT 174 /* U Copyright Notice 78 bytes */
+#define FH_NCHRL 252 /* U Number of Chars in Layout 2 bytes */
+#define FH_NCHRF 254 /* U Total Number of Chars in Font 2 bytes */
+#define FH_FCHRF 256 /* U Index of first char in Font 2 bytes */
+#define FH_NKTKS 258 /* U Number of kerning tracks in font 2 bytes */
+#define FH_NKPRS 260 /* U Number of kerning pairs in font 2 bytes */
+#define FH_FLAGS 262 /* U Font flags 1 byte: */
+ /* Bit 0: Extended font */
+ /* Bit 1: not used */
+ /* Bit 2: not used */
+ /* Bit 3: not used */
+ /* Bit 4: not used */
+ /* Bit 5: not used */
+ /* Bit 6: not used */
+ /* Bit 7: not used */
+#define FH_CLFGS 263 /* U Classification flags 1 byte: */
+ /* Bit 0: Italic */
+ /* Bit 1: Monospace */
+ /* Bit 2: Serif */
+ /* Bit 3: Display */
+ /* Bit 4: not used */
+ /* Bit 5: not used */
+ /* Bit 6: not used */
+ /* Bit 7: not used */
+#define FH_FAMCL 264 /* U Family Classification 1 byte: */
+ /* 0: Don't care */
+ /* 1: Serif */
+ /* 2: Sans serif */
+ /* 3: Monospace */
+ /* 4: Script or calligraphic */
+ /* 5: Decorative */
+ /* 6-255: not used */
+#define FH_FRMCL 265 /* U Font form Classification 1 byte: */
+ /* Bits 0-3 (width type): */
+ /* 0-3: not used */
+ /* 4: Condensed */
+ /* 5: not used */
+ /* 6: Semi-condensed */
+ /* 7: not used */
+ /* 8: Normal */
+ /* 9: not used */
+ /* 10: Semi-expanded */
+ /* 11: not used */
+ /* 12: Expanded */
+ /* 13-15: not used */
+ /* Bits 4-7 (Weight): */
+ /* 0: not used */
+ /* 1: Thin */
+ /* 2: Ultralight */
+ /* 3: Extralight */
+ /* 4: Light */
+ /* 5: Book */
+ /* 6: Normal */
+ /* 7: Medium */
+ /* 8: Semibold */
+ /* 9: Demibold */
+ /* 10: Bold */
+ /* 11: Extrabold */
+ /* 12: Ultrabold */
+ /* 13: Heavy */
+ /* 14: Black */
+ /* 15-16: not used */
+#define FH_SFNTN 266 /* U Short Font Name 32 bytes */
+#define FH_SFACN 298 /* U Short Face Name 16 bytes */
+#define FH_FNTFM 314 /* U Font form 14 bytes */
+#define FH_ITANG 328 /* U Italic angle 2 bytes (1/256th deg) */
+#define FH_ORUPM 330 /* U Number of ORUs per em 2 bytes */
+#define FH_WDWTH 332 /* U Width of Wordspace 2 bytes */
+#define FH_EMWTH 334 /* U Width of Emspace 2 bytes */
+#define FH_ENWTH 336 /* U Width of Enspace 2 bytes */
+#define FH_TNWTH 338 /* U Width of Thinspace 2 bytes */
+#define FH_FGWTH 340 /* U Width of Figspace 2 bytes */
+#define FH_FXMIN 342 /* U Font-wide min X value 2 bytes */
+#define FH_FYMIN 344 /* U Font-wide min Y value 2 bytes */
+#define FH_FXMAX 346 /* U Font-wide max X value 2 bytes */
+#define FH_FYMAX 348 /* U Font-wide max Y value 2 bytes */
+#define FH_ULPOS 350 /* U Underline position 2 bytes */
+#define FH_ULTHK 352 /* U Underline thickness 2 bytes */
+#define FH_SMCTR 354 /* U Small caps transformation 6 bytes */
+#define FH_DPSTR 360 /* U Display sups transformation 6 bytes */
+#define FH_FNSTR 366 /* U Footnote sups transformation 6 bytes */
+#define FH_ALSTR 372 /* U Alpha sups transformation 6 bytes */
+#define FH_CMITR 378 /* U Chemical infs transformation 6 bytes */
+#define FH_SNMTR 384 /* U Small nums transformation 6 bytes */
+#define FH_SDNTR 390 /* U Small denoms transformation 6 bytes */
+#define FH_MNMTR 396 /* U Medium nums transformation 6 bytes */
+#define FH_MDNTR 402 /* U Medium denoms transformation 6 bytes */
+#define FH_LNMTR 408 /* U Large nums transformation 6 bytes */
+#define FH_LDNTR 414 /* U Large denoms transformation 6 bytes */
+ /* Transformation data format: */
+ /* Y position 2 bytes */
+ /* X scale 2 bytes (1/4096ths) */
+ /* Y scale 2 bytes (1/4096ths) */
+#define SIZE_FW FH_LDNTR + 6 /* size of nominal font header */
+#define EXP_FH_METRES SIZE_FW /* offset to expansion field metric resolution (optional) */
+
+
+
+/***** MODE FLAGS CONSTANTS *****/
+#define CURVES_OUT 0X0008 /* Output module accepts curves */
+#define BOGUS_MODE 0X0010 /* Linear scaling mode */
+#define CONSTR_OFF 0X0020 /* Inhibit constraint table */
+#define IMPORT_WIDTHS 0X0040 /* Imported width mode */
+#define SQUEEZE_LEFT 0X0100 /* Squeeze left mode */
+#define SQUEEZE_RIGHT 0X0200 /* Squeeze right mode */
+#define SQUEEZE_TOP 0X0400 /* Squeeze top mode */
+#define SQUEEZE_BOTTOM 0X0800 /* Squeeze bottom mode */
+#define CLIP_LEFT 0X1000 /* Clip left mode */
+#define CLIP_RIGHT 0X2000 /* Clip right mode */
+#define CLIP_TOP 0X4000 /* Clip top mode */
+#define CLIP_BOTTOM 0X8000 /* Clip bottom mode */
+
+/***********************************************************************************
+ *
+ * Speedo function declarations - use prototypes if available
+ *
+ ***********************************************************************************/
+
+#if PROTOS_AVAIL
+/* do_char.c functions */
+ufix16 sp_get_char_id(PROTO_DECL2 ufix16 char_index);
+boolean sp_make_char(PROTO_DECL2 ufix16 char_index);
+#if INCL_ISW
+fix31 sp_compute_isw_scale(PROTO_DECL2);
+static boolean sp_do_make_char(PROTO_DECL2 ufix16 char_index);
+boolean sp_make_char_isw(PROTO_DECL2 ufix16 char_index, ufix32 imported_width);
+static boolean sp_reset_xmax(PROTO_DECL2 fix31 xmax);
+#endif
+#if INCL_ISW || INCL_SQUEEZING
+static void sp_preview_bounding_box(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format);
+#endif
+
+#if INCL_METRICS /* Metrics functions supported? */
+fix31 sp_get_char_width(PROTO_DECL2 ufix16 char_index);
+fix15 sp_get_track_kern(PROTO_DECL2 fix15 track,fix15 point_size);
+fix31 sp_get_pair_kern(PROTO_DECL2 ufix16 char_index1,ufix16 char_index2);
+boolean sp_get_char_bbox(PROTO_DECL2 ufix16 char_index, bbox_t *bbox);
+#endif
+
+/* do_trns.c functions */
+ufix8 FONTFAR *sp_read_bbox(PROTO_DECL2 ufix8 FONTFAR *pointer,point_t STACKFAR *pPmin,point_t STACKFAR *pPmax,boolean set_flag);
+void sp_proc_outl_data(PROTO_DECL2 ufix8 FONTFAR *pointer);
+
+/* out_blk.c functions */
+#if INCL_BLACK
+boolean sp_init_black(PROTO_DECL2 specs_t GLOBALFAR *specsarg);
+boolean sp_begin_char_black(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+void sp_begin_contour_black(PROTO_DECL2 point_t P1,boolean outside);
+void sp_line_black(PROTO_DECL2 point_t P1);
+boolean sp_end_char_black(PROTO_DECL1);
+#endif
+
+/* out_scrn.c functions */
+#if INCL_SCREEN
+boolean sp_init_screen(PROTO_DECL2 specs_t GLOBALFAR *specsarg);
+boolean sp_begin_char_screen(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+void sp_begin_contour_screen(PROTO_DECL2 point_t P1,boolean outside);
+void sp_curve_screen(PROTO_DECL2 point_t P1,point_t P2,point_t P3, fix15 depth);
+void sp_scan_curve_screen(PROTO_DECL2 fix31 X0,fix31 Y0,fix31 X1,fix31 Y1,fix31 X2,fix31 Y2,fix31 X3,fix31 Y3);
+void sp_vert_line_screen(PROTO_DECL2 fix31 x, fix15 y1, fix15 y2);
+void sp_line_screen(PROTO_DECL2 point_t P1);
+void sp_end_contour_screen(PROTO_DECL1);
+boolean sp_end_char_screen(PROTO_DECL1);
+#endif
+
+/* out_outl.c functions */
+#if INCL_OUTLINE
+#if INCL_MULTIDEV
+boolean sp_set_outline_device(PROTO_DECL2 outline_t *ofuncs, ufix16 size);
+#endif
+
+
+boolean sp_init_outline(PROTO_DECL2 specs_t GLOBALFAR *specsarg);
+boolean sp_begin_char_outline(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+void sp_begin_sub_char_outline(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+void sp_begin_contour_outline(PROTO_DECL2 point_t P1,boolean outside);
+void sp_curve_outline(PROTO_DECL2 point_t P1,point_t P2,point_t P3, fix15 depth);
+void sp_line_outline(PROTO_DECL2 point_t P1);
+void sp_end_contour_outline(PROTO_DECL1);
+void sp_end_sub_char_outline(PROTO_DECL1);
+boolean sp_end_char_outline(PROTO_DECL1);
+#endif
+
+/* out_bl2d.c functions */
+#if INCL_2D
+boolean sp_init_2d(PROTO_DECL2 specs_t GLOBALFAR *specsarg);
+boolean sp_begin_char_2d(PROTO_DECL2 point_t Psw,point_t Pmin,point_t Pmax);
+void sp_begin_contour_2d(PROTO_DECL2 point_t P1,boolean outside);
+void sp_line_2d(PROTO_DECL2 point_t P1);
+boolean sp_end_char_2d(PROTO_DECL1);
+#endif
+
+/* out_util.c functions */
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+
+#if INCL_MULTIDEV
+boolean sp_set_bitmap_device(PROTO_DECL2 bitmap_t *bfuncs, ufix16 size);
+#endif
+
+void sp_init_char_out(PROTO_DECL2 point_t Psw, point_t Pmin, point_t Pmax);
+void sp_begin_sub_char_out(PROTO_DECL2 point_t Psw, point_t Pmin, point_t Pmax);
+void sp_curve_out(PROTO_DECL2 point_t P1, point_t P2, point_t P3, fix15 depth);
+void sp_end_contour_out(PROTO_DECL1);
+void sp_end_sub_char_out(PROTO_DECL1);
+void sp_init_intercepts_out(PROTO_DECL1);
+void sp_restart_intercepts_out(PROTO_DECL1);
+void sp_set_first_band_out(PROTO_DECL2 point_t Pmin, point_t Pmax);
+void sp_reduce_band_size_out(PROTO_DECL1);
+boolean sp_next_band_out(PROTO_DECL1);
+#endif
+
+#if INCL_USEROUT
+boolean sp_init_userout(specs_t *specsarg);
+#endif
+
+
+/* reset.c functions */
+void sp_reset(PROTO_DECL1);
+#if INCL_KEYS
+void sp_set_key(PROTO_DECL2 ufix8 key[]);
+#endif
+ufix16 sp_get_cust_no(PROTO_DECL2 buff_t font_buff);
+
+/* set_spcs.c functions */
+boolean sp_set_specs(PROTO_DECL2 specs_t STACKFAR *specsarg);
+void sp_type_tcb(PROTO_DECL2 tcb_t GLOBALFAR *ptcb);
+
+fix31 sp_read_long(PROTO_DECL2 ufix8 FONTFAR *pointer);
+fix15 sp_read_word_u(PROTO_DECL2 ufix8 FONTFAR *pointer);
+
+/* set_trns.c functions */
+void sp_init_tcb(PROTO_DECL1);
+void sp_scale_tcb(PROTO_DECL2 tcb_t GLOBALFAR *ptcb,fix15 x_pos,fix15 y_pos,fix15 x_scale,fix15 y_scale);
+ufix8 FONTFAR *sp_plaid_tcb(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format);
+ufix8 FONTFAR *sp_skip_interpolation_table(PROTO_DECL2 ufix8 FONTFAR *pointer, ufix8 format);
+ufix8 FONTFAR *sp_skip_control_zone(PROTO_DECL2 ufix8 FONTFAR *pointer, ufix8 format);
+
+ufix8 FONTFAR *sp_read_oru_table(PROTO_DECL2 ufix8 FONTFAR *pointer);
+#if INCL_SQUEEZING || INCL_ISW
+static void sp_calculate_x_pix(PROTO_DECL2 ufix8 start_edge,ufix8 end_edge,ufix16 constr_nr,fix31 x_scale,fix31 x_offset,fix31 ppo,fix15 setwidth_pix);
+#endif
+#if INCL_SQUEEZING
+static void sp_calculate_y_pix(PROTO_DECL2 ufix8 start_edge,ufix8 end_edge,ufix16 constr_nr,fix31 top_scale,fix31 bottom_scale,fix31 ppo,fix15 emtop_pix,fix15 embot_pix);
+boolean sp_calculate_x_scale(PROTO_DECL2 fix31 *x_factor,fix31 *x_offset,fix15 no_x_ctrl_zones);
+boolean sp_calculate_y_scale(PROTO_DECL2 fix31 *top_scale,fix31 *bottom_scale,fix15 first_y_zone, fix15 no_Y_ctrl_zones);
+#endif
+
+
+/* user defined functions */
+
+void sp_report_error(PROTO_DECL2 fix15 n);
+
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+void sp_open_bitmap(PROTO_DECL2 fix31 x_set_width, fix31 y_set_width, fix31 xorg, fix31 yorg, fix15 xsize,fix15 ysize);
+void sp_set_bitmap_bits(PROTO_DECL2 fix15 y, fix15 xbit1, fix15 xbit2);
+void sp_close_bitmap(PROTO_DECL1);
+#endif
+
+#if INCL_OUTLINE
+void sp_open_outline(PROTO_DECL2 fix31 x_set_width, fix31 y_set_width, fix31 xmin, fix31 xmax, fix31 ymin,fix31 ymax);
+void sp_start_new_char(PROTO_DECL1);
+void sp_start_contour(PROTO_DECL2 fix31 x,fix31 y,boolean outside);
+void sp_curve_to(PROTO_DECL2 fix31 x1, fix31 y1, fix31 x2, fix31 y2, fix31 x3, fix31 y3);
+void sp_line_to(PROTO_DECL2 fix31 x, fix31 y);
+void sp_close_contour(PROTO_DECL1);
+void sp_close_outline(PROTO_DECL1);
+#endif
+
+#if INCL_LCD /* Dynamic load character data supported? */
+buff_t *sp_load_char_data(PROTO_DECL2 fix31 file_offset,fix15 no_bytes,fix15 cb_offset); /* Load character data from font file */
+#endif
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+void sp_record_xint(PROTO_DECL2 fix15 int_num); /* Record xint data */
+void sp_record_yint(PROTO_DECL2 fix15 int_num); /* Record yint data */
+void sp_begin_plaid_data(PROTO_DECL1); /* Signal start of plaid data */
+void sp_begin_ctrl_zones(PROTO_DECL2 fix15, no_X_zones, fix15 no_Y_zones); /* Signal start of control zones */
+void sp_record_ctrl_zone(PROTO_DECL2 fix31 start, fix31 end, fix15 constr); /* Record control zone data */
+void sp_begin_int_zones(PROTO_DECL2 fix15 no_X_int_zones, fix15 no_Y_int_zones); /* Signal start of interpolation zones */
+void sp_record_int_zone(PROTO_DECL2 fix31 start, fix31 end); /* Record interpolation zone data */
+void sp_end_plaid_data(PROTO_DECL1); /* Signal end of plaid data */
+#endif
+
+#else /* NO PROTOTYPES AVAILABLE */
+
+
+
+/* do_char.c functions */
+boolean sp_make_char(); /* Make specified character */
+#if INCL_ISW
+fix31 sp_compute_isw_scale();
+static boolean sp_do_make_char();
+boolean sp_make_char_isw(); /* Make specified character with */
+ /* imported set widths.*/
+static boolean sp_reset_xmax();
+#endif
+#if INCL_ISW || INCL_SQUEEZING
+static void sp_preview_bounding_box();
+#endif
+ufix16 sp_get_char_id(); /* Get character id for specified char */
+
+#if INCL_METRICS /* Metrics functions supported? */
+fix31 sp_get_char_width(); /* Get character width for specified char */
+fix15 sp_get_track_kern(); /* Get track kerning for specified size */
+fix31 sp_get_pair_kern(); /* Get kerning for specified char pair */
+boolean sp_get_char_bbox();
+#endif
+
+/* do_trns.c functions */
+ufix8 FONTFAR *sp_read_bbox(); /* Read bounding box */
+void sp_proc_outl_data(); /* Process outline data */
+
+/* out_0c.c functions */
+boolean sp_init_black();
+boolean sp_begin_char_black();
+void sp_begin_contour_black();
+void sp_line_black();
+boolean sp_end_char_black();
+
+/* out_util.c functions */
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+
+void sp_init_char_out();
+void sp_begin_sub_char_out();
+void sp_curve_out();
+void sp_end_contour_out();
+void sp_end_sub_char_out();
+void sp_init_intercepts_out();
+void sp_restart_intercepts_out();
+void sp_set_first_band_out();
+void sp_reduce_band_size_out();
+boolean sp_next_band_out();
+#endif
+
+#if INCL_USEROUT
+boolean sp_init_userout();
+#endif
+
+/* reset.c functions */
+void sp_reset(); /* Initialize Fontware mechanism */
+
+#if INCL_KEYS
+void sp_set_key();
+#endif
+ufix16 sp_get_cust_no();
+
+/* set_spcs.c functions */
+boolean sp_set_specs(); /* Set specifications */
+void sp_type_tcb(); /* Update transformation class in tcb */
+
+fix31 sp_read_long(); /* Read long as 3 bytes encrypted */
+fix15 sp_read_word_u(); /* Read word as 2 bytes unencrypted */
+
+/* set_trns.c functions */
+void sp_init_tcb(); /* Initialize current trans control block */
+void sp_scale_tcb(); /* Transform trans control block */
+ufix8 FONTFAR *sp_plaid_tcb(); /* Enable intelligent transformation */
+ufix8 FONTFAR *sp_skip_interpolation_table();
+ufix8 FONTFAR *sp_skip_control_zone();
+
+ufix8 FONTFAR *sp_read_oru_table(); /* Read controlled coord table */
+#if INCL_SQUEEZING || INCL_ISW
+static void sp_calculate_x_pix();
+#endif
+#if INCL_SQUEEZING
+static void sp_calculate_y_pix();
+boolean sp_calculate_x_scale();
+boolean sp_calculate_y_scale() ;
+#endif
+
+/* user defined functions */
+
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+void sp_open_bitmap();
+void sp_set_bitmap_bits();
+void sp_close_bitmap();
+#endif
+
+#if INCL_OUTLINE
+void sp_open_outline();
+void sp_start_new_char();
+void sp_start_contour();
+void sp_curve_to();
+void sp_line_to();
+void sp_close_contour();
+void sp_close_outline();
+#endif
+
+#if INCL_LCD /* Dynamic load character data supported? */
+buff_t *sp_load_char_data(); /* Load character data from font file */
+#endif
+
+#if INCL_PLAID_OUT /* Plaid data monitoring included? */
+void sp_record_xint(); /* Record xint data */
+void sp_record_yint(); /* Record yint data */
+void sp_begin_plaid_data(); /* Signal start of plaid data */
+void sp_begin_ctrl_zones(); /* Signal start of control zones */
+void sp_record_ctrl_zone(); /* Record control zone data */
+void sp_begin_int_zones(); /* Signal start of interpolation zones */
+void sp_record_int_zone(); /* Record interpolation zone data */
+void sp_end_plaid_data(); /* Signal end of plaid data */
+#endif
+
+boolean sp_init_screen(); /* If only screen-writer mode supported */
+boolean sp_begin_char_screen(); /* If screenwriter mode supported */
+void sp_begin_contour_screen(); /* If screenwriter mode supported */
+void sp_line_screen(); /* If screenwriter mode supported */
+void sp_curve_screen(); /* If screenwriter mode supported */
+void sp_scan_curve_screen();
+void sp_vert_line_screen();
+void sp_end_contour_screen();
+boolean sp_end_char_screen(); /* If screenwriter mode supported */
+
+
+boolean sp_init_outline(); /* If only vector output mode supported */
+boolean sp_begin_char_outline(); /* If only vector output mode supported */
+void sp_begin_sub_char_outline(); /* If only vector output mode supported */
+void sp_begin_contour_outline(); /* If only vector output mode supported */
+void sp_curve_outline(); /* If only vector output mode supported */
+void sp_line_outline(); /* If only vector output mode supported */
+void sp_end_contour_outline(); /* If only vector output mode supported */
+void sp_end_sub_char_outline(); /* If only vector output mode supported */
+boolean sp_end_char_outline(); /* If only vector output mode supported */
+
+boolean sp_init_2d(); /* If screen-writer and other modes supported */
+boolean sp_begin_char_2d(); /* If screen-writer and other modes supported */
+void sp_begin_contour_2d(); /* If screen-writer and other modes supported */
+void sp_line_2d(); /* If screen-writer and other modes supported */
+boolean sp_end_char_2d(); /* If screen-writer and other modes supported */
+
+#endif
+
+
+
+#endif /* _SPEEDO_H_ */
diff --git a/src/Speedo/spencode.c b/src/Speedo/spencode.c
new file mode 100644
index 0000000..b74e71d
--- /dev/null
+++ b/src/Speedo/spencode.c
@@ -0,0 +1,62 @@
+/* $Xorg: spencode.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#include "spint.h"
+
+#include "bics-iso.h"
+
+int sp_bics_map_size = (sizeof(sp_bics_map) / (sizeof(int) * 2));
+
+#ifdef EXTRAFONTS
+#include "adobe-iso.h"
+
+int adobe_map_size = (sizeof(adobe_map) / (sizeof(int) * 2));
+
+#endif /* EXTRAFONTS */
diff --git a/src/Speedo/sperr.c b/src/Speedo/sperr.c
new file mode 100644
index 0000000..8d94d85
--- /dev/null
+++ b/src/Speedo/sperr.c
@@ -0,0 +1,134 @@
+/* $Xorg: sperr.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of M.I.T., Network Computing Devices,
+ * or Digital not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. Network Computing Devices, or Digital
+ * make no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES, DIGITAL AND MIT DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, DIGITAL OR MIT BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+
+Copyright 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+#include "spint.h"
+
+#if NeedVarargsPrototypes
+#include <stdarg.h>
+
+void
+SpeedoErr(char *str, ...)
+{
+ va_list v;
+ int a1;
+
+ va_start(v, str);
+ ErrorF("Speedo: ");
+ a1 = va_arg(v, int);
+ ErrorF(str, a1);
+ va_end(v);
+}
+
+#else
+
+/* VARARGS1 */
+void
+SpeedoErr(str, a1)
+ char *str;
+ char *a1;
+{
+ ErrorF("Speedo: ");
+ ErrorF(str, a1);
+}
+#endif /* NeedVarargsPrototypes else */
+
+
+/*
+ * Called by Speedo character generator to report an error.
+ *
+ * Since character data not available is one of those errors
+ * that happens many times, don't report it to user
+ */
+void
+sp_report_error(n)
+ fix15 n;
+{
+ switch (n) {
+ case 1:
+ SpeedoErr("Insufficient font data loaded\n");
+ break;
+ case 3:
+ SpeedoErr("Transformation matrix out of range\n");
+ break;
+ case 4:
+ SpeedoErr("Font format error\n");
+ break;
+ case 5:
+ SpeedoErr("Requested specs not compatible with output module\n");
+ break;
+ case 7:
+ SpeedoErr("Intelligent transformation requested but not supported\n");
+ break;
+ case 8:
+ SpeedoErr("Unsupported output mode requested\n");
+ break;
+ case 9:
+ SpeedoErr("Extended font loaded but only compact fonts supported\n");
+ break;
+ case 10:
+ SpeedoErr("Font specs not set prior to use of font\n");
+ break;
+ case 12:
+ break;
+ case 13:
+ SpeedoErr("Track kerning data not available()\n");
+ break;
+ case 14:
+ SpeedoErr("Pair kerning data not available()\n");
+ break;
+ default:
+ SpeedoErr("report_error(%d)\n", n);
+ break;
+ }
+}
diff --git a/src/Speedo/spfile.c b/src/Speedo/spfile.c
new file mode 100644
index 0000000..2eac82e
--- /dev/null
+++ b/src/Speedo/spfile.c
@@ -0,0 +1,349 @@
+/* $Xorg: spfile.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices Inc
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#include <stdio.h>
+#include "fntfilst.h"
+
+#include "spint.h"
+
+SpeedoFontPtr sp_fp_cur = (SpeedoFontPtr) 0;
+
+#ifdef EXTRAFONTS
+#include "ncdkeys.h"
+#endif
+
+#include "keys.h"
+
+#ifdef EXTRAFONTS
+static ufix8 skey[] =
+{
+ SKEY0,
+ SKEY1,
+ SKEY2,
+ SKEY3,
+ SKEY4,
+ SKEY5,
+ SKEY6,
+ SKEY7,
+ SKEY8
+}; /* Sample Font decryption key */
+
+static ufix8 rkey[] =
+{
+ RKEY0,
+ RKEY1,
+ RKEY2,
+ RKEY3,
+ RKEY4,
+ RKEY5,
+ RKEY6,
+ RKEY7,
+ RKEY8
+}; /* Retail Font decryption key */
+
+#endif /* EXTRAFONTS */
+
+#ifdef XSAMPLEFONTS
+static ufix8 xkey[] =
+{
+ XKEY0,
+ XKEY1,
+ XKEY2,
+ XKEY3,
+ XKEY4,
+ XKEY5,
+ XKEY6,
+ XKEY7,
+ XKEY8
+}; /* Sample Font decryption key */
+#endif
+
+static ufix8 mkey[] =
+{
+ KEY0,
+ KEY1,
+ KEY2,
+ KEY3,
+ KEY4,
+ KEY5,
+ KEY6,
+ KEY7,
+ KEY8
+}; /* Font decryption key */
+
+
+static fix15
+read_2b(ptr)
+ ufix8 *ptr;
+{
+ fix15 tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) + *ptr;
+ return tmp;
+}
+
+static fix31
+read_4b(ptr)
+ ufix8 *ptr;
+{
+ fix31 tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) + *ptr++;
+ tmp = (tmp << 8) + *ptr++;
+ tmp = (tmp << 8) + *ptr;
+ return tmp;
+}
+
+/*
+ * loads the specified char's data
+ */
+buff_t *
+sp_load_char_data(file_offset, num, cb_offset)
+ fix31 file_offset;
+ fix15 num;
+ fix15 cb_offset;
+{
+ SpeedoMasterFontPtr master = sp_fp_cur->master;
+
+ if (fseek(master->fp, (long) file_offset, (int) 0)) {
+ SpeedoErr("can't seek to char\n");
+ }
+ if ((num + cb_offset) > master->mincharsize) {
+ SpeedoErr("char buf overflow\n");
+ }
+ if (fread((master->c_buffer + cb_offset), sizeof(ufix8), num,
+ master->fp) != num) {
+ SpeedoErr("can't get char data\n");
+ }
+ master->char_data.org = (ufix8 *) master->c_buffer + cb_offset;
+ master->char_data.no_bytes = num;
+
+ return &master->char_data;
+}
+
+int
+sp_open_master(filename, master)
+ char *filename;
+ SpeedoMasterFontPtr *master;
+{
+ SpeedoMasterFontPtr spmf;
+ ufix8 tmp[16];
+ ufix16 cust_no;
+ FILE *fp;
+ ufix32 minbufsize;
+ ufix16 mincharsize;
+ ufix8 *f_buffer;
+ ufix8 *c_buffer;
+ int ret;
+ ufix8 *key;
+
+ spmf = (SpeedoMasterFontPtr) xalloc(sizeof(SpeedoMasterFontRec));
+ if (!spmf)
+ return AllocError;
+ bzero(spmf, sizeof(SpeedoMasterFontRec));
+ spmf->entry = NULL;
+ spmf->f_buffer = NULL;
+ spmf->c_buffer = NULL;
+
+ /* open font */
+ spmf->fname = (char *) xalloc(strlen(filename) + 1);
+ if (!spmf->fname)
+ return AllocError;
+ fp = fopen(filename, "r");
+ if (!fp) {
+ ret = BadFontName;
+ goto cleanup;
+ }
+ strcpy(spmf->fname, filename);
+ spmf->fp = fp;
+ spmf->state |= MasterFileOpen;
+
+ if (fread(tmp, sizeof(ufix8), 16, fp) != 16) {
+ ret = BadFontName;
+ goto cleanup;
+ }
+ minbufsize = (ufix32) read_4b(tmp + FH_FBFSZ);
+ f_buffer = (ufix8 *) xalloc(minbufsize);
+ if (!f_buffer) {
+ ret = AllocError;
+ goto cleanup;
+ }
+ spmf->f_buffer = f_buffer;
+
+ fseek(fp, (ufix32) 0, 0);
+
+ /* read in the font */
+ if (fread(f_buffer, sizeof(ufix8), (ufix16) minbufsize, fp) != minbufsize) {
+ ret = BadFontName;
+ goto cleanup;
+ }
+ spmf->copyright = (char *) (f_buffer + FH_CPYRT);
+ spmf->mincharsize = mincharsize = read_2b(f_buffer + FH_CBFSZ);
+
+ c_buffer = (ufix8 *) xalloc(mincharsize);
+ if (!c_buffer) {
+ ret = AllocError;
+ goto cleanup;
+ }
+ spmf->c_buffer = c_buffer;
+
+ spmf->font.org = spmf->f_buffer;
+ spmf->font.no_bytes = minbufsize;
+
+ cust_no = sp_get_cust_no(spmf->font);
+
+ /* XXX add custom encryption stuff here */
+
+#ifdef EXTRAFONTS
+ if (cust_no == SCUS0) {
+ key = skey;
+ } else if (cust_no == RCUS0) {
+ key = rkey;
+ } else
+#endif
+
+#ifdef XSAMPLEFONTS
+ if (cust_no == XCUS0) {
+ key = xkey;
+ } else
+#endif
+
+ if (cust_no == CUS0) {
+ key = mkey;
+ } else {
+ SpeedoErr("Non - standard encryption for \"%s\"\n", filename);
+ ret = BadFontName;
+ goto cleanup;
+ }
+ spmf->key = key;
+ sp_set_key(key);
+
+ spmf->first_char_id = read_2b(f_buffer + FH_FCHRF);
+ spmf->num_chars = read_2b(f_buffer + FH_NCHRL);
+
+
+ spmf->enc = sp_bics_map;
+ spmf->enc_size = sp_bics_map_size;
+
+#ifdef EXTRAFONTS
+ { /* choose the proper encoding */
+ char *f;
+
+ f = strrchr(filename, '/');
+ if (f) {
+ f++;
+ if (strncmp(f, "bx113", 5) == 0) {
+ spmf->enc = adobe_map;
+ spmf->enc_size = adobe_map_size;
+ }
+ }
+ }
+#endif
+
+ /* XXX slam back to ISO Latin1 */
+ spmf->first_char_id = spmf->enc[0];
+ /* size of extents array */
+ spmf->max_id = spmf->enc[(spmf->enc_size - 1) * 2];
+ spmf->num_chars = spmf->enc_size;
+
+ *master = spmf;
+
+ return Successful;
+
+cleanup:
+ *master = (SpeedoMasterFontPtr) 0;
+ sp_close_master_font(spmf);
+ return ret;
+}
+
+void
+sp_close_master_font(spmf)
+ SpeedoMasterFontPtr spmf;
+{
+ if (!spmf)
+ return;
+ if (spmf->state & MasterFileOpen)
+ fclose(spmf->fp);
+ if (spmf->entry)
+ spmf->entry->u.scalable.extra->private = NULL;
+ xfree(spmf->fname);
+ xfree(spmf->f_buffer);
+ xfree(spmf->c_buffer);
+ xfree(spmf);
+}
+
+void
+sp_close_master_file(spmf)
+ SpeedoMasterFontPtr spmf;
+{
+ (void) fclose(spmf->fp);
+ spmf->state &= ~MasterFileOpen;
+}
+
+
+/*
+ * reset the encryption key, and make sure the file is opened
+ */
+void
+sp_reset_master(spmf)
+ SpeedoMasterFontPtr spmf;
+{
+ sp_set_key(spmf->key);
+ if (!(spmf->state & MasterFileOpen)) {
+ spmf->fp = fopen(spmf->fname, "r");
+ /* XXX -- what to do if we can't open the file? */
+ spmf->state |= MasterFileOpen;
+ }
+ fseek(spmf->fp, 0, 0);
+}
diff --git a/src/Speedo/spfont.c b/src/Speedo/spfont.c
new file mode 100644
index 0000000..ebfc526
--- /dev/null
+++ b/src/Speedo/spfont.c
@@ -0,0 +1,450 @@
+/* $Xorg: spfont.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices Inc
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Speedo font loading
+ */
+
+#include "FSproto.h"
+#include "spint.h"
+#include <servermd.h>
+#ifdef _XOPEN_SOURCE
+#include <math.h>
+#else
+#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */
+#include <math.h>
+#undef _XOPEN_SOURCE
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159
+#endif /* M_PI */
+#ifndef DEFAULT_BIT_ORDER
+
+#ifdef BITMAP_BIT_ORDER
+#define DEFAULT_BIT_ORDER BITMAP_BIT_ORDER
+#else
+#define DEFAULT_BIT_ORDER UNKNOWN_BIT_ORDER
+#endif
+
+#endif
+
+extern void SpeedoCloseFont();
+static int sp_get_glyphs();
+static int sp_get_metrics();
+static int sp_load_font();
+
+static int
+sp_get_glyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register unsigned char *chars;
+ FontEncoding charEncoding;
+ unsigned long *glyphCount; /* RETURN */
+ CharInfoPtr *glyphs; /* RETURN */
+{
+ SpeedoFontPtr spf;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ CharInfoPtr *glyphsBase;
+ register unsigned int c;
+ register CharInfoPtr pci;
+ unsigned int r;
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+ int itemSize;
+ int err = Successful;
+
+ spf = (SpeedoFontPtr) pFont->fontPrivate;
+ encoding = spf->encoding;
+ pDefault = spf->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+
+ /* XXX - this should be much smarter */
+ /* make sure the glyphs are there */
+ if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
+ itemSize = 1;
+ else
+ itemSize = 2;
+
+#ifdef notyet
+ if (!fsd->complete)
+ err = fs_load_glyphs(NULL, pFont, count, itemSize, chars);
+#endif
+
+ if (err != Successful)
+ return err;
+
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = &encoding[c];
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols && (pci = &encoding[c])->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = &encoding[c];
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols && (pci = &encoding[c])->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols &&
+ (pci = &encoding[r * numCols + c])->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return Successful;
+}
+
+static CharInfoRec nonExistantChar;
+
+static int
+sp_get_metrics(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register unsigned char *chars;
+ FontEncoding charEncoding;
+ unsigned long *glyphCount; /* RETURN */
+ xCharInfo **glyphs; /* RETURN */
+{
+ int ret;
+ SpeedoFontPtr spf;
+ CharInfoPtr oldDefault;
+
+ spf = (SpeedoFontPtr) pFont->fontPrivate;
+ oldDefault = spf->pDefault;
+ spf->pDefault = &nonExistantChar;
+ ret = sp_get_glyphs(pFont, count, chars, charEncoding,
+ glyphCount, (CharInfoPtr *) glyphs);
+
+ spf->pDefault = oldDefault;
+ return ret;
+}
+
+int
+sp_open_font(fontname, filename, entry, vals, format, fmask, flags, spfont)
+ char *fontname,
+ *filename;
+ FontEntryPtr entry;
+ FontScalablePtr vals;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ Mask flags;
+ SpeedoFontPtr *spfont;
+{
+ SpeedoFontPtr spf;
+ SpeedoMasterFontPtr spmf;
+ int ret;
+ specs_t specs;
+ int xx8, xy8, yx8, yy8;
+
+ /* find a master (create it if necessary) */
+ spmf = (SpeedoMasterFontPtr) entry->u.scalable.extra->private;
+ if (!spmf)
+ {
+ ret = sp_open_master(filename, &spmf);
+ if (ret != Successful)
+ return ret;
+ entry->u.scalable.extra->private = (pointer) spmf;
+ spmf->entry = entry;
+ }
+
+ spf = (SpeedoFontPtr) xalloc(sizeof(SpeedoFontRec));
+ if (!spf)
+ return AllocError;
+ bzero((char *) spf, sizeof(SpeedoFontRec));
+
+ *spfont = spf;
+
+ /* clobber everything -- this may be leaking, but other wise evil
+ * stuff is left behind -- succesive transformed fonts get mangled */
+ bzero((char *)&sp_globals, sizeof(sp_globals));
+
+ spf->master = spmf;
+ spf->entry = entry;
+ spmf->refcount++;
+ sp_reset_master(spmf);
+ /* now we've done enough that if we bail out we must call sp_close_font */
+
+ spf->vals = *vals;
+
+ /* set up specs */
+
+ specs.pfont = &spmf->font;
+
+ specs.xxmult = (int)(vals->pixel_matrix[0] * (double)(1L << 16));
+ specs.xymult = (int)(vals->pixel_matrix[2] * (double)(1L << 16));
+ specs.yxmult = (int)(vals->pixel_matrix[1] * (double)(1L << 16));
+ specs.yymult = (int)(vals->pixel_matrix[3] * (double)(1L << 16));
+
+ specs.xoffset = 0L << 16; /* XXX tweak? */
+ specs.yoffset = 0L << 16; /* XXX tweak? */
+
+ specs.flags = MODE_SCREEN;
+ specs.out_info = NULL;
+
+ /* When Speedo tries to generate a very small font bitmap, it
+ often crashes or goes into an infinite loop.
+ Don't know why this is so, but until we can fix it properly,
+ return BadFontName for anything smaller than 4 pixels.
+ */
+#define TINY_FACTOR (16 << 16)
+ xx8 = specs.xxmult >> 8;
+ xy8 = specs.xymult >> 8;
+ yx8 = specs.yxmult >> 8;
+ yy8 = specs.yymult >> 8;
+ if (xx8 * xx8 + xy8 * xy8 < TINY_FACTOR ||
+ yx8 * yx8 + yy8 * yy8 < TINY_FACTOR)
+ {
+ sp_close_font(spf);
+ return BadFontName;
+ }
+
+ /* clobber global state to avoid wrecking future transformed fonts */
+ bzero ((char *) &sp_globals, sizeof(sp_globals));
+
+ if (!sp_set_specs(&specs))
+ {
+ sp_close_font(spf);
+ return BadFontName;
+ }
+
+ spf->specs = specs;
+ spf->master = spmf;
+
+ *spfont = spf;
+ return Successful;
+}
+
+static int
+sp_load_font(fontname, filename, entry, vals, format, fmask, pfont, flags)
+ char *fontname,
+ *filename;
+ FontEntryPtr entry;
+ FontScalablePtr vals;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ FontPtr pfont;
+ Mask flags;
+{
+ SpeedoFontPtr spf;
+ SpeedoMasterFontPtr spmf;
+ int esize;
+ int ret;
+ long sWidth;
+
+ ret = sp_open_font(fontname, filename, entry, vals, format, fmask,
+ flags, &spf);
+
+ if (ret != Successful)
+ return ret;
+
+ spmf = spf->master;
+ sp_reset_master(spmf);
+ esize = sizeof(CharInfoRec) * (spmf->max_id - spmf->first_char_id + 1);
+
+ spf->encoding = (CharInfoPtr) xalloc(esize);
+ if (!spf->encoding) {
+ sp_close_font(spf);
+ return AllocError;
+ }
+ bzero((char *) spf->encoding, esize);
+
+ sp_fp_cur = spf;
+
+ sp_make_header(spf, &pfont->info);
+
+ sp_compute_bounds(spf, &pfont->info, SaveMetrics, &sWidth);
+
+ sp_compute_props(spf, fontname, &pfont->info, sWidth);
+
+ pfont->fontPrivate = (pointer) spf;
+
+/* XXX */
+ flags |= FontLoadBitmaps;
+
+ if (flags & FontLoadBitmaps) {
+ sp_fp_cur = spf;
+ ret = sp_build_all_bitmaps(pfont, format, fmask);
+ }
+ if (ret != Successful)
+ return ret;
+
+ /* compute remaining accelerators */
+ FontComputeInfoAccelerators(&pfont->info);
+
+ pfont->format = format;
+
+ pfont->get_metrics = sp_get_metrics;
+ pfont->get_glyphs = sp_get_glyphs;
+ pfont->unload_font = SpeedoCloseFont;
+ pfont->unload_glyphs = NULL;
+ pfont->refcnt = 0;
+ pfont->maxPrivate = -1;
+ pfont->devPrivates = (pointer *) 0;
+
+ /* have to hold on to master for min/max id */
+ sp_close_master_file(spmf);
+
+ return ret;
+}
+
+int
+SpeedoFontLoad(ppfont, fontname, filename, entry, vals, format, fmask, flags)
+ FontPtr *ppfont;
+ char *fontname;
+ char *filename;
+ FontEntryPtr entry;
+ FontScalablePtr vals;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ Mask flags;
+{
+ FontPtr pfont;
+ int ret;
+
+ /* Reject ridiculously small sizes that will blow up the math */
+ if (hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]) < 1.0 ||
+ hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]) < 1.0)
+ return BadFontName;
+
+ pfont = (FontPtr) xalloc(sizeof(FontRec));
+ if (!pfont) {
+ return AllocError;
+ }
+ ret = sp_load_font(fontname, filename, entry, vals, format, fmask,
+ pfont, flags);
+
+ if (ret == Successful)
+ *ppfont = pfont;
+ else
+ xfree (pfont);
+
+ return ret;
+}
+
+void
+sp_close_font(spf)
+ SpeedoFontPtr spf;
+{
+ SpeedoMasterFontPtr spmf;
+
+ spmf = spf->master;
+ --spmf->refcount;
+ if (spmf->refcount == 0)
+ sp_close_master_font (spmf);
+ xfree(spf->encoding);
+ xfree(spf->bitmaps);
+ xfree(spf);
+}
+
+void
+SpeedoCloseFont(pfont)
+ FontPtr pfont;
+{
+ SpeedoFontPtr spf;
+
+ spf = (SpeedoFontPtr) pfont->fontPrivate;
+ sp_close_font(spf);
+ xfree(pfont->info.isStringProp);
+ xfree(pfont->info.props);
+ xfree(pfont->devPrivates);
+ xfree(pfont);
+}
diff --git a/src/Speedo/spfuncs.c b/src/Speedo/spfuncs.c
new file mode 100644
index 0000000..0cd09ee
--- /dev/null
+++ b/src/Speedo/spfuncs.c
@@ -0,0 +1,161 @@
+/* $Xorg: spfuncs.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#include <X11/Xos.h>
+#include "fntfilst.h"
+#include "spint.h"
+
+/* ARGSUSED */
+int
+SpeedoOpenScalable (fpe, pFont, flags, entry, fileName, vals, format, fmask,
+ non_cachable_font)
+ FontPathElementPtr fpe;
+ FontPtr *pFont;
+ int flags;
+ FontEntryPtr entry;
+ char *fileName;
+ FontScalablePtr vals;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ FontPtr non_cachable_font; /* We don't do licensing */
+{
+ char fullName[MAXFONTNAMELEN];
+
+ strcpy (fullName, entry->name.name);
+ return SpeedoFontLoad (pFont, fullName, fileName, entry, vals,
+ format, fmask, flags);
+}
+
+/*
+ * XXX
+ *
+ * this does a lot more then i'd like, but it has to get the bitmaps
+ * in order to get accurate metrics (which it *must* have).
+ *
+ * a possible optimization is to avoid allocating the glyph memory
+ * and to simply save the values without doing the work.
+ */
+static int
+get_font_info(pinfo, fontname, filename, entry, vals, spfont)
+ FontInfoPtr pinfo;
+ char *fontname;
+ char *filename;
+ FontEntryPtr entry;
+ FontScalablePtr vals;
+ SpeedoFontPtr *spfont;
+{
+ SpeedoFontPtr spf;
+ int err;
+ long sWidth;
+
+ err = sp_open_font(fontname, filename, entry, vals,
+ (fsBitmapFormat) 0, (fsBitmapFormatMask) 0, (unsigned long) 0,
+ &spf);
+
+ if (err != Successful)
+ return err;
+
+ sp_fp_cur = spf;
+ sp_reset_master(spf->master);
+
+ sp_make_header(spf, pinfo);
+
+ sp_compute_bounds(spf, pinfo, (unsigned long) 0, &sWidth);
+
+ sp_compute_props(spf, fontname, pinfo, sWidth);
+
+ /* compute remaining accelerators */
+ FontComputeInfoAccelerators (pinfo);
+
+ *spfont = spf;
+
+ return Successful;
+}
+
+/* ARGSUSED */
+int
+SpeedoGetInfoScaleable(fpe, pFontInfo, entry, fontName, fileName, vals)
+ FontPathElementPtr fpe;
+ FontInfoPtr pFontInfo;
+ FontEntryPtr entry;
+ FontNamePtr fontName;
+ char *fileName;
+ FontScalablePtr vals;
+{
+ SpeedoFontPtr spf = NULL;
+ char fullName[MAXFONTNAMELEN];
+ int err;
+
+ strcpy(fullName, entry->name.name);
+ FontParseXLFDName(fullName, vals, FONT_XLFD_REPLACE_VALUE);
+
+ err = get_font_info(pFontInfo, fullName, fileName, entry, vals, &spf);
+
+ if (spf)
+ sp_close_font(spf);
+
+ return err;
+}
+
+static FontRendererRec renderer = {
+ ".spd", 4, (int (*)()) 0, SpeedoOpenScalable,
+ (int (*)()) 0, SpeedoGetInfoScaleable, 0
+ , CAP_MATRIX | CAP_CHARSUBSETTING
+};
+
+void
+SpeedoRegisterFontFileFunctions()
+{
+ sp_make_standard_props();
+ sp_reset();
+ FontFileRegisterRenderer(&renderer);
+}
diff --git a/src/Speedo/spglyph.c b/src/Speedo/spglyph.c
new file mode 100644
index 0000000..ff0f370
--- /dev/null
+++ b/src/Speedo/spglyph.c
@@ -0,0 +1,403 @@
+/* $Xorg: spglyph.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices Inc
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#include <X11/X.h> /* for bit order #defines */
+#include "spint.h"
+
+#undef CLIP_BBOX_NOISE
+
+static CurrentFontValuesRec current_font_values;
+static CurrentFontValuesPtr cfv = &current_font_values;
+static int bit_order,
+ byte_order,
+ scan;
+
+unsigned long
+sp_compute_data_size(pfont, mappad, scanlinepad, start, end)
+ FontPtr pfont;
+ int mappad,
+ scanlinepad;
+ unsigned long start,
+ end;
+{
+ unsigned long ch;
+ unsigned long size = 0;
+ int bpr;
+ SpeedoFontPtr spf = (SpeedoFontPtr) pfont->fontPrivate;
+ FontInfoPtr pinfo = &pfont->info;
+ int firstChar;
+
+ firstChar = spf->master->first_char_id;
+
+ /* allocate the space */
+ switch (mappad) {
+ int charsize;
+ CharInfoPtr ci;
+ xCharInfo *cim;
+
+ case BitmapFormatImageRectMin:
+ cfv->bpr = 0;
+ for (ch = start; ch <= end; ch++) {
+ ci = &spf->encoding[ch - firstChar];
+ if (!ci)
+ ci = spf->pDefault;
+ cim = &ci->metrics;
+ charsize = GLYPH_SIZE(ci, scanlinepad);
+ charsize *= cim->ascent + cim->descent;
+ size += charsize;
+ }
+ break;
+ case BitmapFormatImageRectMaxWidth:
+ bpr = GLWIDTHBYTESPADDED(FONT_MAX_WIDTH(pinfo), scanlinepad);
+ cfv->bpr = bpr;
+ for (ch = start; ch <= end; ch++) {
+ ci = &spf->encoding[ch - firstChar];
+ if (!ci)
+ ci = spf->pDefault;
+ cim = &ci->metrics;
+ charsize = bpr * (cim->ascent + cim->descent);
+ size += charsize;
+ }
+ break;
+ case BitmapFormatImageRectMax:
+ bpr = GLWIDTHBYTESPADDED(FONT_MAX_WIDTH(pinfo), scanlinepad);
+ cfv->bpr = bpr;
+ size = (end - start + 1) * bpr * FONT_MAX_HEIGHT(pinfo);
+ break;
+ default:
+ assert(0);
+ }
+
+ return size;
+}
+
+static void
+finish_line(spf)
+ SpeedoFontPtr spf;
+{
+ int bpr = cfv->bpr;
+ CharInfoPtr ci = &spf->encoding[cfv->char_id - spf->master->first_char_id];
+
+ if (bpr == 0) {
+ bpr = GLYPH_SIZE(ci, cfv->scanpad);
+ }
+ if (bpr) { /* char may not have any metrics... */
+ cfv->bp += bpr;
+ }
+ assert(cfv->bp - sp_fp_cur->bitmaps <= sp_fp_cur->bitmap_size);
+}
+
+
+void
+sp_set_bitmap_bits(y, xbit1, xbit2)
+ fix15 y;
+ fix15 xbit1,
+ xbit2;
+{
+ int nmiddle;
+ CARD8 startmask,
+ endmask;
+ CARD8 *dst;
+
+ if (xbit1 > cfv->bit_width) {
+
+#ifdef CLIP_BBOX_NOISE
+ SpeedoErr("Run wider than bitmap width -- truncated\n");
+#endif
+
+ xbit1 = cfv->bit_width;
+ }
+ if (xbit2 > cfv->bit_width) {
+
+#ifdef CLIP_BBOX_NOISE
+ SpeedoErr("Run wider than bitmap width -- truncated\n");
+#endif
+
+ xbit2 = cfv->bit_width;
+ }
+
+ if (xbit2 < xbit1) {
+ xbit2 = xbit1;
+ }
+
+ while (cfv->cur_y != y) {
+ finish_line(sp_fp_cur);
+ cfv->cur_y++;
+ }
+
+ cfv->last_y = y;
+ if (y >= cfv->bit_height) {
+
+#ifdef CLIP_BBOX_NOISE
+ SpeedoErr("Y larger than bitmap height -- truncated\n");
+#endif
+
+ cfv->trunc = 1;
+ return;
+ }
+ if (xbit1 < 0) /* XXX this is more than a little bit rude... */
+ xbit1 = 0;
+
+ nmiddle = (xbit1 >> 3);
+ dst = (CARD8 *) (cfv->bp + nmiddle);
+ xbit2 -= (xbit1 & ~7);
+ nmiddle = (xbit2 >> 3);
+ xbit1 &= 7;
+ xbit2 &= 7;
+ if (bit_order == MSBFirst) {
+ startmask = ((CARD8) ~0) >> xbit1;
+ endmask = ~(((CARD8) ~0) >> xbit2);
+ } else {
+ startmask = ((CARD8) ~0) << xbit1;
+ endmask = ~(((CARD8) ~0) << xbit2);
+ }
+ if (nmiddle == 0)
+ *dst |= endmask & startmask;
+ else {
+ *dst++ |= startmask;
+ while (--nmiddle)
+ *dst++ = (CARD8)~0;
+ *dst |= endmask;
+ }
+}
+
+/* ARGSUSED */
+void
+sp_open_bitmap(x_set_width, y_set_width, xorg, yorg, xsize, ysize)
+ fix31 x_set_width;
+ fix31 y_set_width;
+ fix31 xorg;
+ fix31 yorg;
+ fix15 xsize;
+ fix15 ysize;
+{
+ CharInfoPtr ci = &sp_fp_cur->encoding[cfv->char_id - sp_fp_cur->master->first_char_id];
+
+/*-
+ * this is set to provide better quality bitmaps. since the Speedo
+ * sp_get_bbox() function returns an approximate (but guarenteed to contain)
+ * set of metrics, some of the bitmaps can be place poorly inside and
+ * look bad.
+ *
+ * with this set, the actual bitmap values are used instead of the bboxes.
+ * it makes things look better, but causes two possible problems:
+ *
+ * 1 - the reported min & max bounds may not correspond to the extents
+ * reported
+ * 2 - if the extents are reported before the character is generated,
+ * a client could see them change. this currently never happens,
+ * but will when a desired enhancement (don't reneder till needed)
+ * is made.
+ */
+
+#define BBOX_FIXUP 1
+
+#ifdef BBOX_FIXUP
+ int off_horz;
+ int off_vert;
+
+ if (xorg < 0)
+ off_horz = (fix15) ((xorg - 32768L) / 65536);
+ else
+ off_horz = (fix15) ((xorg + 32768L) / 65536);
+ if (yorg < 0)
+ off_vert = (fix15) ((yorg - 32768L) / 65536);
+ else
+ off_vert = (fix15) ((yorg + 32768L) / 65536);
+ if (xsize != 0 || ysize != 0 || ci->metrics.characterWidth)
+ {
+ ci->metrics.leftSideBearing = off_horz;
+ ci->metrics.descent = -off_vert;
+ ci->metrics.rightSideBearing = xsize + off_horz;
+ ci->metrics.ascent = ysize + off_vert;
+ }
+ else
+ {
+ /* If setting the proper size would cause the character to appear to
+ be non-existent, fudge things by giving it a pixel to occupy. */
+ xsize = ysize = 1;
+ ci->metrics.leftSideBearing = ci->metrics.descent = 0;
+ ci->metrics.rightSideBearing = ci->metrics.ascent = 1;
+ }
+
+ cfv->bit_width = xsize;
+ cfv->bit_height = ysize;
+#else
+ cfv->bit_width = ci->metrics.rightSideBearing -
+ ci->metrics.leftSideBearing;
+ cfv->bit_height = ci->metrics.ascent + ci->metrics.descent;
+#endif
+
+ assert(cfv->bp - sp_fp_cur->bitmaps <= sp_fp_cur->bitmap_size);
+ ci->bits = (char *) cfv->bp;
+
+ cfv->cur_y = 0;
+}
+
+void
+sp_close_bitmap()
+{
+ CharInfoPtr ci = &sp_fp_cur->encoding[cfv->char_id - sp_fp_cur->master->first_char_id];
+ int bpr = cfv->bpr;
+
+ if (bpr == 0)
+ bpr = GLYPH_SIZE(ci, cfv->scanpad);
+ if (!cfv->trunc)
+ finish_line(sp_fp_cur);
+ cfv->trunc = 0;
+ cfv->last_y++;
+ while (cfv->last_y < cfv->bit_height) {
+ finish_line(sp_fp_cur);
+ cfv->last_y++;
+ }
+ if (byte_order != bit_order) {
+ switch (scan) {
+ case 1:
+ break;
+ case 2:
+ TwoByteSwap(cfv->bp, bpr * cfv->bit_height);
+ break;
+ case 4:
+ FourByteSwap(cfv->bp, bpr * cfv->bit_height);
+ break;
+ }
+ }
+}
+
+int
+sp_build_all_bitmaps(pfont, format, fmask)
+ FontPtr pfont;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+{
+ int ret,
+ glyph = 1,
+ image = BitmapFormatImageRectMin;
+ unsigned long glyph_size;
+ SpeedoFontPtr spf = (SpeedoFontPtr) pfont->fontPrivate;
+ SpeedoMasterFontPtr spmf = spf->master;
+ pointer bitmaps;
+ int start,
+ end,
+ i;
+
+ scan = 1;
+ ret = CheckFSFormat(format, fmask,
+ &bit_order, &byte_order, &scan, &glyph, &image);
+
+ pfont->bit = bit_order;
+ pfont->byte = byte_order;
+ pfont->glyph = glyph;
+ pfont->scan = scan;
+ if (ret != Successful)
+ return BadFontFormat;
+
+ start = spmf->first_char_id;
+ end = spmf->max_id;
+ glyph_size = sp_compute_data_size(pfont, image, glyph, start, end);
+
+ /* XXX -- MONDO KLUDGE -- add some slop */
+ /*
+ * not sure why this is wanted, but it keeps the packer from going off the
+ * end and toasting us down the line
+ */
+ glyph_size += 20;
+
+#ifdef DEBUG
+ spf->bitmap_size = glyph_size;
+#endif
+
+ bitmaps = (pointer) xalloc(glyph_size);
+ if (!bitmaps)
+ return AllocError;
+ bzero((char *) bitmaps, glyph_size);
+
+ /* set up some state */
+ sp_fp_cur = spf;
+ spf->bitmaps = bitmaps;
+ cfv->format = format;
+ cfv->scanpad = glyph;
+ cfv->bp = bitmaps;
+
+ for (i = 0; i < spmf->num_chars; i++) {
+ int j;
+ cfv->char_index = spmf->enc[i * 2 + 1];
+ cfv->char_id = spmf->enc[i * 2];
+#if DEBUG
+fprintf(stderr, "build_all_sp_bitmaps:i = %d, Char ID = %d\n", i, cfv->char_id);
+#endif
+ if (!cfv->char_id)
+ continue;
+
+ /*
+ * See if this character is in the list of ranges specified in the
+ * XLFD name
+ */
+ for (j = 0; j < spf->vals.nranges; j++)
+ if (cfv->char_id >= mincharno(spf->vals.ranges[j]) &&
+ cfv->char_id <= maxcharno(spf->vals.ranges[j]))
+ break;
+
+ /* If not, don't realize it. */
+ if (spf->vals.nranges && j == spf->vals.nranges)
+ continue;
+
+ if (!sp_make_char(cfv->char_index)) {
+
+#ifdef DEBUG /* can be very common with some encodings */
+ SpeedoErr("Can't make char %d\n", cfv->char_index);
+#endif
+ }
+ }
+
+ return Successful;
+}
diff --git a/src/Speedo/spinfo.c b/src/Speedo/spinfo.c
new file mode 100644
index 0000000..05d3f24
--- /dev/null
+++ b/src/Speedo/spinfo.c
@@ -0,0 +1,441 @@
+/* $Xorg: spinfo.c,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#include "fntfilst.h"
+#include "spint.h"
+#include <math.h>
+
+/* percentage of pointsize used to specify ascent & descent */
+#define STRETCH_FACTOR 120
+
+enum scaleType {
+ atom, truncate_atom, pixel_size, point_size, resolution_x,
+ resolution_y, average_width
+};
+
+typedef struct _fontProp {
+ char *name;
+ long atom;
+ enum scaleType type;
+} fontProp;
+
+static fontProp fontNamePropTable[] = {
+ { "FOUNDRY", 0, atom },
+ { "FAMILY_NAME", 0, atom },
+ { "WEIGHT_NAME", 0, atom },
+ { "SLANT", 0, atom },
+ { "SETWIDTH_NAME", 0, atom },
+ { "ADD_STYLE_NAME", 0, atom },
+ { "PIXEL_SIZE", 0, pixel_size },
+ { "POINT_SIZE", 0, point_size },
+ { "RESOLUTION_X", 0, resolution_x },
+ { "RESOLUTION_Y", 0, resolution_y },
+ { "SPACING", 0, atom },
+ { "AVERAGE_WIDTH", 0, average_width },
+ { "CHARSET_REGISTRY", 0, atom },
+ { "CHARSET_ENCODING", 0, truncate_atom }
+};
+
+/* Warning: following array is closely related to the sequence of
+ defines after it. */
+
+static fontProp extraProps[] = {
+ { "FONT", 0, },
+ { "COPYRIGHT", 0, },
+ { "RAW_PIXEL_SIZE", 0, },
+ { "RAW_POINT_SIZE", 0, },
+ { "RAW_ASCENT", 0, },
+ { "RAW_DESCENT", 0, },
+ { "RAW_AVERAGE_WIDTH", 0, }
+};
+
+/* this is a bit kludgy */
+#define FONTPROP 0
+#define COPYRIGHTPROP 1
+#define RAWPIXELPROP 2
+#define RAWPOINTPROP 3
+#define RAWASCENTPROP 4
+#define RAWDESCENTPROP 5
+#define RAWWIDTHPROP 6
+
+
+#define NNAMEPROPS (sizeof(fontNamePropTable) / sizeof(fontProp))
+#define NEXTRAPROPS (sizeof(extraProps) / sizeof(fontProp))
+
+#define NPROPS (NNAMEPROPS + NEXTRAPROPS)
+
+extern Atom MakeAtom();
+
+void
+sp_make_standard_props()
+{
+ int i;
+ fontProp *t;
+
+ i = sizeof(fontNamePropTable) / sizeof(fontProp);
+ for (t = fontNamePropTable; i; i--, t++)
+ t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
+ i = sizeof(extraProps) / sizeof(fontProp);
+ for (t = extraProps; i; i--, t++)
+ t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
+}
+
+void
+sp_make_header(spf, pinfo)
+ SpeedoFontPtr spf;
+ FontInfoPtr pinfo;
+{
+ int pixel_size;
+ SpeedoMasterFontPtr spmf = spf->master;
+
+ pinfo->firstCol = spmf->first_char_id & 0xff;
+ pinfo->firstRow = spmf->first_char_id >> 8;
+ pinfo->lastCol = spmf->max_id & 0xff;
+ pinfo->lastRow = spmf->max_id >> 8;
+
+ /* XXX -- hackery here */
+ pinfo->defaultCh = 0;
+/* computed by FontComputeInfoAccelerators:
+ * noOverlap
+ * constantMetrics
+ * terminalFont
+ * constantWidth
+ * inkInside
+ */
+ pinfo->inkMetrics = 0;
+ pinfo->allExist = 0;
+ pinfo->drawDirection = LeftToRight;
+ pinfo->cachable = 1;
+ if (spf->specs.xxmult != spf->specs.yymult)
+ pinfo->anamorphic = TRUE;
+ else
+ pinfo->anamorphic = FALSE;
+/* computed by sp_compute_bounds:
+ * maxOverlap
+ * maxbounds
+ * minbounds
+ * ink_maxbounds
+ * ink_minbounds
+ */
+ pixel_size = spf->vals.pixel_matrix[3] * STRETCH_FACTOR / 100;
+ pinfo->fontAscent = pixel_size * 764 / 1000; /* 764 == EM_TOP */
+ pinfo->fontDescent = pixel_size - pinfo->fontAscent;
+}
+
+static void
+adjust_min_max(minc, maxc, tmp)
+ xCharInfo *minc,
+ *maxc,
+ *tmp;
+{
+#define MINMAX(field,ci) \
+ if (minc->field > (ci)->field) \
+ minc->field = (ci)->field; \
+ if (maxc->field < (ci)->field) \
+ maxc->field = (ci)->field;
+
+ MINMAX(ascent, tmp);
+ MINMAX(descent, tmp);
+ MINMAX(leftSideBearing, tmp);
+ MINMAX(rightSideBearing, tmp);
+ MINMAX(characterWidth, tmp);
+
+ if ((INT16)minc->attributes > (INT16)tmp->attributes)
+ minc->attributes = tmp->attributes;
+ if ((INT16)maxc->attributes < (INT16)tmp->attributes)
+ maxc->attributes = tmp->attributes;
+
+#undef MINMAX
+}
+
+
+void
+sp_compute_bounds(spf, pinfo, flags, sWidth)
+ SpeedoFontPtr spf;
+ FontInfoPtr pinfo;
+ unsigned long flags;
+ long *sWidth;
+{
+ int i,
+ id,
+ index,
+ maxOverlap,
+ overlap,
+ total_width = 0;
+ xCharInfo minchar,
+ maxchar,
+ tmpchar;
+ bbox_t bbox;
+ fix31 width;
+ double pix_width;
+ SpeedoMasterFontPtr spmf = spf->master;
+ int firstChar;
+ int num_chars = 0;
+
+ firstChar = spmf->first_char_id;
+ minchar.ascent = minchar.descent =
+ minchar.leftSideBearing = minchar.rightSideBearing =
+ minchar.characterWidth = minchar.attributes = 32767;
+ maxchar.ascent = maxchar.descent =
+ maxchar.leftSideBearing = maxchar.rightSideBearing =
+ maxchar.characterWidth = maxchar.attributes = -32767;
+ maxOverlap = -32767;
+ *sWidth = 0;
+ for (i = 0; i < spmf->num_chars; i++) {
+ int j;
+ int char_id;
+
+ index = spmf->enc[i * 2 + 1];
+ char_id = spmf->enc[i * 2];
+ /*
+ * See if this character is in the list of ranges specified in the
+ * XLFD name
+ */
+ for (j = 0; j < spf->vals.nranges; j++)
+ if (char_id >= mincharno(spf->vals.ranges[j]) &&
+ char_id <= maxcharno(spf->vals.ranges[j]))
+ break;
+ if (spf->vals.nranges && j == spf->vals.nranges)
+ continue;
+ num_chars++;
+
+ if (!(flags & ComputeBoundsOnly)) {
+
+ width = sp_get_char_width(index);
+
+ /* convert to pixel coords */
+ pix_width = (int)width * (spf->specs.xxmult / 65536L) +
+ ((int) width * (spf->specs.xxmult % 65536L))
+ / 65536L;
+ pix_width /= 65536L;
+
+ (void) sp_get_char_bbox(index, &bbox);
+ bbox.ymax = (bbox.ymax + 32768L) >> 16;
+ bbox.ymin = (bbox.ymin + 32768L) >> 16;
+ bbox.xmin = (bbox.xmin + 32768L) >> 16;
+ bbox.xmax = (bbox.xmax + 32768L) >> 16;
+ tmpchar.ascent = bbox.ymax;
+ tmpchar.descent = -bbox.ymin;
+ tmpchar.characterWidth = (int)(pix_width + /* round */
+ (pix_width > 0 ? 0.5 : -0.5));
+ tmpchar.rightSideBearing = bbox.xmax;
+ tmpchar.leftSideBearing = bbox.xmin;
+
+ if (!tmpchar.characterWidth &&
+ tmpchar.ascent == -tmpchar.descent &&
+ tmpchar.rightSideBearing == tmpchar.leftSideBearing)
+ {
+ /* Character appears non-existent, probably as a result
+ of the transformation. Let's give it one pixel in
+ the universe so it's not mistaken for non-existent. */
+ tmpchar.leftSideBearing = tmpchar.descent = 0;
+ tmpchar.rightSideBearing = tmpchar.ascent = 1;
+ }
+
+ tmpchar.attributes = (int)((double)(int)width / 65.536 + .5);
+ }
+ else
+ tmpchar = spf->encoding[char_id - firstChar].metrics;
+
+ adjust_min_max(&minchar, &maxchar, &tmpchar);
+ overlap = tmpchar.rightSideBearing - tmpchar.characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+
+ total_width += ((int)(INT16)tmpchar.attributes);
+ *sWidth += abs((int)(INT16)tmpchar.attributes);
+
+ if (flags & SaveMetrics) {
+ id = spmf->enc[i * 2] - firstChar;
+ assert(id <= spmf->max_id - firstChar);
+ spf->encoding[id].metrics = tmpchar;
+ }
+ }
+
+
+ if (num_chars > 0)
+ {
+ *sWidth = (int)(((double)*sWidth * 10.0 + (double)num_chars / 2.0) /
+ num_chars);
+ if (total_width < 0)
+ {
+ /* Predominant direction is R->L */
+ *sWidth = -*sWidth;
+ }
+ spf->vals.width = (int)((double)*sWidth * spf->vals.pixel_matrix[0] /
+ 1000.0 +
+ (spf->vals.pixel_matrix[0] > 0 ? .5 : -.5));
+ }
+ else
+ {
+ spf->vals.width = 0;
+ }
+ pinfo->maxbounds = maxchar;
+ pinfo->minbounds = minchar;
+ pinfo->ink_maxbounds = maxchar;
+ pinfo->ink_minbounds = minchar;
+ pinfo->maxOverlap = maxOverlap;
+}
+
+void
+sp_compute_props(spf, fontname, pinfo, sWidth)
+ SpeedoFontPtr spf;
+ char *fontname;
+ FontInfoPtr pinfo;
+ long sWidth;
+{
+ FontPropPtr pp;
+ int i,
+ nprops;
+ fontProp *fpt;
+ char *is_str;
+ char *ptr1,
+ *ptr2;
+ char *ptr3;
+ char tmpname[1024];
+ FontScalableRec tmpvals;
+
+ nprops = pinfo->nprops = NPROPS;
+ pinfo->isStringProp = (char *) xalloc(sizeof(char) * nprops);
+ pinfo->props = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops);
+ if (!pinfo->isStringProp || !pinfo->props) {
+ xfree(pinfo->isStringProp);
+ pinfo->isStringProp = (char *) 0;
+ xfree(pinfo->props);
+ pinfo->props = (FontPropPtr) 0;
+ return;
+ }
+ bzero(pinfo->isStringProp, (sizeof(char) * nprops));
+
+ ptr2 = fontname;
+ for (i = NNAMEPROPS, pp = pinfo->props, fpt = fontNamePropTable,
+ is_str = pinfo->isStringProp;
+ i;
+ i--, pp++, fpt++, is_str++) {
+
+ if (*ptr2)
+ {
+ ptr1 = ptr2 + 1;
+ if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
+ }
+
+ pp->name = fpt->atom;
+ switch (fpt->type) {
+ case atom:
+ *is_str = TRUE;
+ pp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
+ break;
+ case truncate_atom:
+ *is_str = TRUE;
+ for (ptr3 = ptr1; *ptr3; ptr3++)
+ if (*ptr3 == '[')
+ break;
+ pp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE);
+ break;
+ case pixel_size:
+ pp->value = (int)(spf->vals.pixel_matrix[3] +
+ (spf->vals.pixel_matrix[3] > 0 ? .5 : -.5));
+ break;
+ case point_size:
+ pp->value = (int)(spf->vals.point_matrix[3] * 10.0 +
+ (spf->vals.point_matrix[3] > 0 ? .5 : -.5));
+ break;
+ case resolution_x:
+ pp->value = spf->vals.x;
+ break;
+ case resolution_y:
+ pp->value = spf->vals.y;
+ break;
+ case average_width:
+ pp->value = spf->vals.width;
+ break;
+ }
+ }
+
+ for (i = 0, fpt = extraProps; i < NEXTRAPROPS; i++, is_str++, pp++, fpt++) {
+ pp->name = fpt->atom;
+ switch (i) {
+ case FONTPROP:
+ *is_str = TRUE;
+ strcpy(tmpname, fontname);
+ FontParseXLFDName(tmpname, &tmpvals, FONT_XLFD_REPLACE_ZERO);
+ FontParseXLFDName(tmpname, &spf->vals, FONT_XLFD_REPLACE_VALUE);
+ pp->value = MakeAtom(tmpname, strlen(tmpname), TRUE);
+ break;
+ case COPYRIGHTPROP:
+ *is_str = TRUE;
+ pp->value = MakeAtom(spf->master->copyright,
+ strlen(spf->master->copyright), TRUE);
+ break;
+ case RAWPIXELPROP:
+ *is_str = FALSE;
+ pp->value = 1000;
+ break;
+ case RAWPOINTPROP:
+ *is_str = FALSE;
+ pp->value = (long)(72270.0 / (double)spf->vals.y + .5);
+ break;
+ case RAWASCENTPROP:
+ *is_str = FALSE;
+ pp->value = STRETCH_FACTOR * 764 / 100;
+ break;
+ case RAWDESCENTPROP:
+ *is_str = FALSE;
+ pp->value = STRETCH_FACTOR * 236 / 100;
+ break;
+ case RAWWIDTHPROP:
+ *is_str = FALSE;
+ pp->value = sWidth;
+ break;
+ }
+ }
+}
diff --git a/src/Speedo/spint.h b/src/Speedo/spint.h
new file mode 100644
index 0000000..d915238
--- /dev/null
+++ b/src/Speedo/spint.h
@@ -0,0 +1,172 @@
+/* $Xorg: spint.h,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#ifndef _SPINT_H_
+#define _SPINT_H_
+
+#include <stdio.h>
+#include "fntfilst.h"
+#include <X11/Xfuncproto.h>
+#include "speedo.h"
+
+#define SaveMetrics 0x1
+#define ComputeBoundsOnly 0x2
+
+#define GLWIDTHBYTESPADDED(bits,nbytes) \
+ ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
+ :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
+ :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
+ :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
+ : 0)
+
+#define GLYPH_SIZE(ch, nbytes) \
+ GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
+ (ch)->metrics.leftSideBearing, (nbytes))
+
+#define mincharno(p) ((p).min_char_low + ((p).min_char_high << 8))
+#define maxcharno(p) ((p).max_char_low + ((p).max_char_high << 8))
+
+#define MasterFileOpen 0x1
+
+typedef struct _sp_master {
+ FontEntryPtr entry; /* back pointer */
+ FILE *fp;
+ char *fname;
+ ufix8 *f_buffer;
+ ufix8 *c_buffer;
+ char *copyright;
+ ufix8 *key;
+ buff_t font;
+ buff_t char_data;
+ ufix16 mincharsize;
+ int first_char_id;
+ int num_chars;
+ int max_id;
+ int state; /* open, closed */
+ int refcount; /* number of instances */
+ int *enc;
+ int enc_size;
+} SpeedoMasterFontRec, *SpeedoMasterFontPtr;
+
+typedef struct _cur_font_stats {
+ fsBitmapFormat format;
+ /* current glyph info */
+ ufix16 char_index;
+ ufix16 char_id;
+
+ fix15 bit_width,
+ bit_height;
+ fix15 cur_y;
+ int bpr;
+
+ /*
+ * since Speedo returns extents that are not identical to what it feeds to
+ * the bitmap builder, and we want to be able to use the extents for
+ * preformance reasons, some of the bitmaps require padding out. the next
+ * two flags keep track of this.
+ */
+ fix15 last_y;
+ int trunc;
+
+ pointer bp;
+ int scanpad;
+} CurrentFontValuesRec, *CurrentFontValuesPtr;
+
+
+typedef struct _sp_font {
+ struct _sp_master *master;
+ specs_t specs;
+
+ FontEntryPtr entry;
+
+ FontScalableRec vals;
+
+ /* char & metric data */
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+ pointer bitmaps;
+
+#ifdef DEBUG
+ unsigned long bitmap_size;
+#endif
+
+} SpeedoFontRec, *SpeedoFontPtr;
+
+extern SpeedoFontPtr sp_fp_cur;
+
+extern int sp_open_font();
+extern int sp_open_master();
+extern void sp_close_font();
+extern void sp_close_master_font();
+extern void sp_close_master_file();
+extern void sp_reset_master();
+#if NeedVarargsPrototypes
+extern void SpeedoErr(char *fmt, ...);
+#else
+extern void SpeedoErr();
+#endif
+
+extern void sp_make_standard_props();
+extern void sp_make_header();
+extern void sp_compute_bounds();
+extern void sp_compute_props();
+extern int sp_build_all_bitmaps();
+extern unsigned long sp_compute_data_size();
+
+extern int sp_bics_map[];
+extern int sp_bics_map_size;
+
+#ifdef EXTRAFONTS
+extern int adobe_map[];
+extern int adobe_map_size;
+
+#endif
+
+#endif /* _SPINT_H_ */
diff --git a/src/Speedo/useropt.h b/src/Speedo/useropt.h
new file mode 100644
index 0000000..e879aae
--- /dev/null
+++ b/src/Speedo/useropt.h
@@ -0,0 +1,41 @@
+/* $Xorg: useropt.h,v 1.4 2001/02/09 02:04:00 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#define INCL_LCD 1
+#define STATIC_ALLOC 1
+
+#define INCL_BLACK 1
+#define INCL_SCREEN 1
+#define INCL_2D 1
+#define SHORT_LISTS 0
+
+#define INCL_RULES 1
+#define INCL_METRICS 1
+
+#define INCL_KEYS 1