Annotation of researchv10no/cmd/bcp/bcp.cpio, revision 1.1.1.1
1.1 root 1: 0707070035351137021006640007620000050000010260220476773366500001100000001573Bfeats.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
3: /* The copyright notice does not imply actual or intended publication. */
4: /* AUTHORS: */
5: /* H. S. Baird - ATT-BL MH - first versions */
6:
7: /* Bfeats.h - typedef, constants, and function declarations for Bfeats.
8: INCLUDES
9: Requires prior #include "BMask.h"
10: */
11:
12: typedef struct Bfeats {
13: BMask bm; /* bitmask (1 for each feature) */
14: unsigned short mny; /* number of feature indices in fa[] */
15: unsigned short *fa; /* fa[mny] of feature (ss) nos, no dups (malloc) */
16: } Bfeats;
17:
18: #define Init_Bfeats {Init_BMask,0,NULL}
19: #if MAIN
20: Bfeats empty_Bfeats = Init_Bfeats;
21: #else
22: extern Bfeats empty_Bfeats;
23: #endif
24:
25: Bfeats *alloc_bfeats();
26: free_bfeats();
27: char *bfeats_toa();
28: Bfeats *dup_bfeats();
29: 0707070035351137031006640007620000050000010260240476773366500001100000470007Bitmap.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
30: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
31: /* The copyright notice does not imply actual or intended publication. */
32: /* AUTHORS: */
33: /* H. S. Baird - ATT-BL MH - first versions */
34: /* Bitmap.h: 2-D fixed-sized bitmaps */
35:
36: /* BITMAP TEMPLATES: potentially MACHINE-DEPENDENT bit-packing */
37: #define Bm_h 54 /* height (no. bits) */
38: #define Bm_il 3 /* width (no. ints) */
39: #define Bm_ex_h 5 /* extra pixels allowed, top/bottom */
40: #define Bm_ex_w 16 /* extra pixels allowed, left/right */
41:
42: #define Bm_wi ((int)(8*sizeof(int))) /* width of an int in bits; sizeof() is
43: unsigned: must coerce to signed so can
44: compare correctly with negative ints */
45: typedef unsigned int Bm_l[Bm_il]; /* bitmap line */
46: #define Bm_w (Bm_wi*Bm_il) /* width of bitmap (<= # bits in a Bm_l) */
47: #define Bm_w_ok (Bm_w+2*Bm_ex_w) /* OK width (sides truncated to fit) */
48: #define Bm_h_ok (Bm_h+2*Bm_ex_h) /* OK height (top/bot truncated to fit) */
49: #define Bm_area (Bm_w*Bm_h) /* area of bitmap */
50: #define Bm_ni (Bm_il*Bm_h) /* no. ints in bitmap area */
51: #define Bm_ns (2*Bm_ni) /* no. of shorts in bitmap area */
52:
53: typedef union Bm { /* the rectangular array of bits */
54: Bm_l l[Bm_h];
55: int unsigned i[Bm_ni];
56: short unsigned s[Bm_ns];
57: } Bm;
58:
59: typedef struct Bm_consts {
60: unsigned int mask_all; /* all bitmap bits set */
61: unsigned int mask[Bm_wi]; /* constant mask bits (in int) */
62: unsigned char Rbits[256]; /* Bytes with bits reversed */
63: unsigned char Nbits[65536]; /* Nbits[i] = no. bits set in
64: (unsigned short) i */
65: } Bm_consts;
66:
67: /* The following 2076 lines are a static initialization for Bm_consts;
68: it is written by program `mkbmc' which runs function `fwra_bm_consts' */
69: #if MAIN
70: Bm_consts bm_consts = {
71: 0xffffffff,
72: { 0x1,0x2,0x4,0x8,
73: 0x10,0x20,0x40,0x80,
74: 0x100,0x200,0x400,0x800,
75: 0x1000,0x2000,0x4000,0x8000,
76: 0x10000,0x20000,0x40000,0x80000,
77: 0x100000,0x200000,0x400000,0x800000,
78: 0x1000000,0x2000000,0x4000000,0x8000000,
79: 0x10000000,0x20000000,0x40000000,0x80000000 },
80: { 00,0200,0100,0300,040,0240,0140,0340,020,0220,0120,0320,060,0260,0160,0360,
81: 010,0210,0110,0310,050,0250,0150,0350,030,0230,0130,0330,070,0270,0170,0370,
82: 04,0204,0104,0304,044,0244,0144,0344,024,0224,0124,0324,064,0264,0164,0364,
83: 014,0214,0114,0314,054,0254,0154,0354,034,0234,0134,0334,074,0274,0174,0374,
84: 02,0202,0102,0302,042,0242,0142,0342,022,0222,0122,0322,062,0262,0162,0362,
85: 012,0212,0112,0312,052,0252,0152,0352,032,0232,0132,0332,072,0272,0172,0372,
86: 06,0206,0106,0306,046,0246,0146,0346,026,0226,0126,0326,066,0266,0166,0366,
87: 016,0216,0116,0316,056,0256,0156,0356,036,0236,0136,0336,076,0276,0176,0376,
88: 01,0201,0101,0301,041,0241,0141,0341,021,0221,0121,0321,061,0261,0161,0361,
89: 011,0211,0111,0311,051,0251,0151,0351,031,0231,0131,0331,071,0271,0171,0371,
90: 05,0205,0105,0305,045,0245,0145,0345,025,0225,0125,0325,065,0265,0165,0365,
91: 015,0215,0115,0315,055,0255,0155,0355,035,0235,0135,0335,075,0275,0175,0375,
92: 03,0203,0103,0303,043,0243,0143,0343,023,0223,0123,0323,063,0263,0163,0363,
93: 013,0213,0113,0313,053,0253,0153,0353,033,0233,0133,0333,073,0273,0173,0373,
94: 07,0207,0107,0307,047,0247,0147,0347,027,0227,0127,0327,067,0267,0167,0367,
95: 017,0217,0117,0317,057,0257,0157,0357,037,0237,0137,0337,077,0277,0177,0377 },
96: { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
97: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
98: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
99: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
100: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
101: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
102: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
103: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
104: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
105: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
106: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
107: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
108: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
109: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
110: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
111: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
112: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
113: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
114: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
115: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
116: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
117: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
118: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
119: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
120: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
121: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
122: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
123: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
124: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
125: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
126: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
127: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
128: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
129: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
130: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
131: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
132: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
133: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
134: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
135: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
136: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
137: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
138: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
139: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
140: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
141: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
142: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
143: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
144: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
145: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
146: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
147: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
148: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
149: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
150: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
151: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
152: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
153: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
154: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
155: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
156: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
157: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
158: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
159: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
160: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
161: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
162: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
163: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
164: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
165: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
166: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
167: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
168: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
169: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
170: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
171: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
172: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
173: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
174: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
175: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
176: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
177: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
178: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
179: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
180: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
181: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
182: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
183: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
184: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
185: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
186: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
187: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
188: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
189: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
190: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
191: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
192: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
193: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
194: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
195: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
196: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
197: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
198: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
199: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
200: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
201: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
202: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
203: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
204: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
205: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
206: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
207: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
208: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
209: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
210: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
211: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
212: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
213: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
214: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
215: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
216: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
217: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
218: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
219: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
220: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
221: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
222: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
223: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
224: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
225: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
226: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
227: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
228: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
229: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
230: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
231: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
232: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
233: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
234: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
235: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
236: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
237: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
238: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
239: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
240: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
241: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
242: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
243: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
244: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
245: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
246: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
247: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
248: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
249: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
250: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
251: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
252: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
253: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
254: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
255: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
256: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
257: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
258: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
259: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
260: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
261: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
262: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
263: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
264: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
265: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
266: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
267: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
268: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
269: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
270: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
271: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
272: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
273: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
274: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
275: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
276: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
277: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
278: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
279: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
280: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
281: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
282: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
283: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
284: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
285: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
286: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
287: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
288: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
289: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
290: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
291: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
292: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
293: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
294: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
295: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
296: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
297: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
298: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
299: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
300: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
301: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
302: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
303: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
304: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
305: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
306: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
307: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
308: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
309: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
310: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
311: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
312: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
313: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
314: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
315: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
316: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
317: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
318: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
319: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
320: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
321: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
322: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
323: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
324: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
325: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
326: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
327: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
328: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
329: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
330: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
331: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
332: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
333: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
334: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
335: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
336: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
337: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
338: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
339: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
340: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
341: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
342: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
343: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
344: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
345: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
346: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
347: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
348: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
349: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
350: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
351: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
352: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
353: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
354: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
355: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
356: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
357: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
358: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
359: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
360: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
361: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
362: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
363: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
364: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
365: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
366: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
367: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
368: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
369: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
370: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
371: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
372: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
373: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
374: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
375: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
376: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
377: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
378: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
379: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
380: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
381: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
382: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
383: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
384: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
385: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
386: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
387: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
388: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
389: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
390: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
391: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
392: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
393: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
394: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
395: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
396: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
397: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
398: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
399: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
400: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
401: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
402: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
403: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
404: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
405: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
406: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
407: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
408: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
409: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
410: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
411: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
412: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
413: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
414: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
415: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
416: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
417: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
418: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
419: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
420: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
421: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
422: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
423: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
424: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
425: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
426: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
427: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
428: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
429: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
430: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
431: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
432: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
433: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
434: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
435: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
436: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
437: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
438: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
439: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
440: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
441: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
442: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
443: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
444: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
445: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
446: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
447: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
448: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
449: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
450: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
451: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
452: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
453: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
454: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
455: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
456: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
457: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
458: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
459: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
460: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
461: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
462: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
463: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
464: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
465: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
466: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
467: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
468: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
469: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
470: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
471: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
472: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
473: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
474: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
475: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
476: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
477: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
478: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
479: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
480: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
481: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
482: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
483: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
484: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
485: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
486: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
487: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
488: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
489: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
490: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
491: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
492: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
493: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
494: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
495: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
496: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
497: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
498: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
499: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
500: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
501: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
502: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
503: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
504: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
505: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
506: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
507: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
508: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
509: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
510: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
511: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
512: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
513: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
514: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
515: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
516: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
517: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
518: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
519: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
520: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
521: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
522: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
523: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
524: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
525: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
526: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
527: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
528: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
529: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
530: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
531: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
532: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
533: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
534: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
535: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
536: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
537: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
538: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
539: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
540: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
541: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
542: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
543: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
544: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
545: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
546: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
547: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
548: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
549: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
550: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
551: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
552: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
553: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
554: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
555: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
556: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
557: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
558: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
559: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
560: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
561: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
562: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
563: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
564: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
565: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
566: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
567: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
568: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
569: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
570: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
571: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
572: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
573: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
574: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
575: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
576: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
577: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
578: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
579: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
580: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
581: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
582: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
583: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
584: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
585: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
586: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
587: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
588: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
589: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
590: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
591: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
592: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
593: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
594: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
595: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
596: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
597: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
598: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
599: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
600: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
601: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
602: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
603: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
604: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
605: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
606: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
607: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
608: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
609: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
610: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
611: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
612: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
613: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
614: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
615: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
616: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
617: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
618: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
619: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
620: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
621: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
622: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
623: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
624: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
625: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
626: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
627: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
628: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
629: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
630: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
631: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
632: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
633: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
634: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
635: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
636: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
637: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
638: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
639: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
640: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
641: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
642: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
643: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
644: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
645: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
646: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
647: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
648: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
649: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
650: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
651: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
652: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
653: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
654: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
655: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
656: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
657: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
658: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
659: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
660: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
661: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
662: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
663: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
664: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
665: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
666: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
667: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
668: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
669: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
670: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
671: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
672: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
673: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
674: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
675: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
676: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
677: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
678: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
679: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
680: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
681: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
682: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
683: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
684: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
685: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
686: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
687: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
688: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
689: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
690: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
691: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
692: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
693: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
694: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
695: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
696: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
697: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
698: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
699: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
700: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
701: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
702: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
703: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
704: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
705: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
706: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
707: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
708: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
709: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
710: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
711: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
712: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
713: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
714: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
715: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
716: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
717: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
718: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
719: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
720: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
721: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
722: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
723: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
724: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
725: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
726: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
727: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
728: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
729: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
730: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
731: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
732: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
733: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
734: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
735: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
736: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
737: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
738: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
739: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
740: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
741: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
742: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
743: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
744: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
745: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
746: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
747: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
748: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
749: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
750: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
751: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
752: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
753: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
754: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
755: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
756: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
757: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
758: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
759: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
760: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
761: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
762: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
763: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
764: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
765: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
766: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
767: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
768: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
769: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
770: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
771: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
772: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
773: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
774: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
775: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
776: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
777: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
778: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
779: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
780: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
781: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
782: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
783: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
784: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
785: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
786: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
787: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
788: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
789: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
790: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
791: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
792: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
793: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
794: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
795: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
796: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
797: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
798: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
799: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
800: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
801: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
802: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
803: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
804: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
805: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
806: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
807: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
808: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
809: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
810: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
811: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
812: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
813: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
814: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
815: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
816: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
817: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
818: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
819: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
820: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
821: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
822: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
823: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
824: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
825: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
826: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
827: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
828: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
829: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
830: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
831: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
832: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
833: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
834: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
835: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
836: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
837: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
838: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
839: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
840: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
841: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
842: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
843: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
844: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
845: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
846: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
847: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
848: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
849: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
850: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
851: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
852: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
853: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
854: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
855: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
856: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
857: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
858: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
859: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
860: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
861: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
862: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
863: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
864: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
865: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
866: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
867: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
868: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
869: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
870: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
871: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
872: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
873: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
874: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
875: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
876: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
877: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
878: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
879: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
880: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
881: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
882: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
883: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
884: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
885: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
886: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
887: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
888: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
889: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
890: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
891: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
892: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
893: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
894: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
895: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
896: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
897: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
898: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
899: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
900: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
901: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
902: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
903: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
904: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
905: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
906: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
907: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
908: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
909: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
910: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
911: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
912: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
913: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
914: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
915: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
916: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
917: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
918: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
919: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
920: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
921: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
922: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
923: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
924: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
925: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
926: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
927: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
928: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
929: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
930: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
931: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
932: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
933: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
934: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
935: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
936: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
937: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
938: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
939: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
940: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
941: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
942: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
943: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
944: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
945: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
946: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
947: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
948: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
949: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
950: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
951: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
952: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
953: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
954: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
955: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
956: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
957: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
958: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
959: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
960: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
961: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
962: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
963: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
964: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
965: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
966: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
967: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
968: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
969: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
970: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
971: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
972: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
973: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
974: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
975: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
976: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
977: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
978: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
979: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
980: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
981: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
982: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
983: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
984: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
985: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
986: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
987: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
988: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
989: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
990: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
991: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
992: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
993: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
994: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
995: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
996: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
997: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
998: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
999: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1000: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1001: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1002: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1003: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1004: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1005: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1006: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1007: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1008: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1009: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1010: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1011: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1012: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1013: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1014: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1015: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1016: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1017: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1018: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1019: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1020: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1021: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1022: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1023: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1024: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1025: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1026: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1027: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1028: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1029: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1030: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1031: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1032: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1033: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1034: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1035: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1036: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1037: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1038: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1039: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1040: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1041: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1042: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1043: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1044: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1045: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1046: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1047: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1048: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1049: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1050: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1051: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1052: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1053: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1054: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1055: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1056: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1057: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1058: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1059: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1060: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1061: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1062: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1063: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1064: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1065: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1066: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1067: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1068: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1069: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1070: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1071: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1072: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1073: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1074: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1075: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1076: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1077: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1078: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1079: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1080: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1081: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1082: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1083: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1084: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1085: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1086: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1087: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1088: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1089: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1090: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1091: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1092: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1093: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1094: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1095: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1096: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1097: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1098: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1099: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1100: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1101: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1102: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1103: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1104: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1105: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1106: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1107: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1108: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1109: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1110: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1111: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1112: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1113: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1114: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1115: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1116: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1117: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1118: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1119: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
1120: 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
1121: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1122: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1123: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1124: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1125: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1126: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1127: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1128: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1129: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1130: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1131: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1132: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1133: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1134: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1135: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1136: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1137: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1138: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1139: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1140: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1141: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1142: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1143: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1144: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1145: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1146: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1147: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1148: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1149: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1150: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1151: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1152: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1153: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1154: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1155: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1156: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1157: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1158: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1159: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1160: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1161: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1162: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1163: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1164: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1165: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1166: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1167: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1168: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1169: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1170: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1171: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1172: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1173: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1174: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1175: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1176: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1177: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1178: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1179: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1180: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1181: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1182: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1183: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1184: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1185: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1186: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1187: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1188: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1189: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1190: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1191: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1192: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1193: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1194: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1195: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1196: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1197: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1198: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1199: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1200: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1201: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1202: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1203: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1204: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1205: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1206: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1207: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1208: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1209: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1210: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1211: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1212: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1213: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1214: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1215: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1216: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1217: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1218: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1219: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1220: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1221: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1222: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1223: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1224: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1225: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1226: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1227: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1228: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1229: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1230: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1231: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1232: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1233: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1234: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1235: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1236: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1237: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1238: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1239: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1240: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1241: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1242: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1243: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1244: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1245: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1246: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1247: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1248: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1249: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1250: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1251: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1252: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1253: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1254: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1255: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1256: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1257: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1258: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1259: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1260: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1261: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1262: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1263: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1264: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1265: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1266: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1267: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1268: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1269: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1270: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1271: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1272: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1273: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1274: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1275: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1276: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1277: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1278: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1279: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1280: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1281: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1282: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1283: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1284: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1285: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1286: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1287: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1288: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1289: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1290: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1291: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1292: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1293: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1294: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1295: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1296: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1297: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1298: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1299: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1300: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1301: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1302: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1303: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1304: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1305: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1306: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1307: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1308: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1309: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1310: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1311: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1312: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1313: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1314: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1315: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1316: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1317: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1318: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1319: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1320: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1321: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1322: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1323: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1324: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1325: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1326: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1327: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1328: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1329: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1330: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1331: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1332: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1333: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1334: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1335: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1336: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1337: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1338: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1339: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1340: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1341: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1342: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1343: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1344: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1345: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1346: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1347: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1348: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1349: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1350: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1351: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1352: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1353: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1354: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1355: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1356: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1357: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1358: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1359: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1360: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1361: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1362: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1363: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1364: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1365: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1366: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1367: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1368: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1369: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1370: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1371: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1372: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1373: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1374: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1375: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1376: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1377: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1378: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1379: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1380: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1381: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1382: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1383: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1384: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1385: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1386: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1387: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1388: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1389: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1390: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1391: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1392: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1393: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1394: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1395: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1396: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1397: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1398: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1399: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1400: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1401: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1402: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1403: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1404: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1405: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1406: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1407: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1408: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1409: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1410: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1411: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1412: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1413: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1414: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1415: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1416: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1417: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1418: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1419: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1420: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1421: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1422: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1423: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1424: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1425: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1426: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1427: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1428: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1429: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1430: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1431: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1432: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1433: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1434: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1435: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1436: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1437: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1438: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1439: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1440: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1441: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1442: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1443: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1444: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1445: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1446: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1447: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1448: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1449: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1450: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1451: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1452: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1453: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1454: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1455: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1456: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1457: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1458: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1459: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1460: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1461: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1462: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1463: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1464: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1465: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1466: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1467: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1468: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1469: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1470: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1471: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1472: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1473: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1474: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1475: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1476: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1477: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1478: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1479: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1480: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1481: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1482: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1483: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1484: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1485: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1486: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1487: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1488: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1489: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1490: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1491: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1492: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1493: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1494: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1495: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1496: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1497: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1498: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1499: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1500: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1501: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1502: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1503: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1504: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1505: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1506: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1507: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1508: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1509: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1510: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1511: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1512: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1513: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1514: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1515: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1516: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1517: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1518: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1519: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1520: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1521: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1522: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1523: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1524: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1525: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1526: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1527: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1528: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1529: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1530: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1531: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1532: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1533: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1534: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1535: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1536: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1537: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1538: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1539: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1540: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1541: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1542: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1543: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1544: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1545: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1546: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1547: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1548: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1549: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1550: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1551: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1552: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1553: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1554: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1555: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1556: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1557: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1558: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1559: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1560: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1561: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1562: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1563: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1564: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1565: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1566: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1567: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1568: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1569: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1570: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1571: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1572: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1573: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1574: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1575: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1576: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1577: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1578: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1579: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1580: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1581: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1582: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1583: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1584: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1585: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1586: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1587: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1588: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1589: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1590: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1591: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1592: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1593: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1594: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1595: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1596: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1597: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1598: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1599: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1600: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1601: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1602: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1603: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1604: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1605: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1606: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1607: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1608: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1609: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1610: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1611: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1612: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1613: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1614: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1615: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1616: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1617: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1618: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1619: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1620: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1621: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1622: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1623: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1624: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1625: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1626: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1627: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1628: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1629: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1630: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1631: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
1632: 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1633: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1634: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1635: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1636: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1637: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1638: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1639: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1640: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1641: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1642: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1643: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1644: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1645: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1646: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1647: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1648: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1649: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1650: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1651: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1652: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1653: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1654: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1655: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1656: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1657: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1658: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1659: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1660: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1661: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1662: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1663: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1664: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1665: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1666: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1667: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1668: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1669: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1670: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1671: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1672: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1673: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1674: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1675: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1676: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1677: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1678: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1679: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1680: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1681: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1682: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1683: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1684: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1685: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1686: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1687: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1688: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1689: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1690: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1691: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1692: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1693: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1694: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1695: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1696: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1697: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1698: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1699: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1700: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1701: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1702: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1703: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1704: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1705: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1706: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1707: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1708: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1709: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1710: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1711: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1712: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1713: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1714: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1715: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1716: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1717: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1718: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1719: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1720: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1721: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1722: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1723: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1724: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1725: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1726: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1727: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1728: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1729: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1730: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1731: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1732: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1733: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1734: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1735: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1736: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1737: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1738: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1739: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1740: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1741: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1742: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1743: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1744: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1745: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1746: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1747: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1748: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1749: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1750: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1751: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1752: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1753: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1754: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1755: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1756: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1757: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1758: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1759: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1760: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1761: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1762: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1763: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1764: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1765: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1766: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1767: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1768: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1769: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1770: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1771: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1772: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1773: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1774: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1775: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1776: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1777: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1778: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1779: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1780: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1781: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1782: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1783: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1784: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1785: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1786: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1787: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1788: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1789: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1790: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1791: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1792: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1793: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1794: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1795: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1796: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1797: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1798: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1799: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1800: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1801: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1802: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1803: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1804: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1805: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1806: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1807: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1808: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1809: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1810: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1811: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1812: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1813: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1814: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1815: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1816: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1817: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1818: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1819: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1820: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1821: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1822: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1823: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1824: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1825: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1826: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1827: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1828: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1829: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1830: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1831: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1832: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1833: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1834: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1835: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1836: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1837: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1838: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1839: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1840: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1841: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1842: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1843: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1844: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1845: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1846: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1847: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1848: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1849: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1850: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1851: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1852: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1853: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1854: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1855: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1856: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1857: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1858: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1859: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1860: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1861: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1862: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1863: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1864: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1865: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1866: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1867: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1868: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1869: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1870: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1871: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1872: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1873: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1874: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1875: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1876: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1877: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1878: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1879: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1880: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1881: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1882: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1883: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1884: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1885: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1886: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1887: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
1888: 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
1889: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1890: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1891: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1892: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1893: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1894: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1895: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1896: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1897: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1898: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1899: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1900: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1901: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1902: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1903: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1904: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1905: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1906: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1907: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1908: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1909: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1910: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1911: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1912: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1913: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1914: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1915: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1916: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1917: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1918: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1919: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1920: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1921: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1922: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1923: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1924: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1925: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1926: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1927: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1928: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1929: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1930: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1931: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1932: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1933: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1934: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1935: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1936: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1937: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1938: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1939: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1940: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1941: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1942: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1943: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1944: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1945: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1946: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1947: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1948: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1949: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1950: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1951: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1952: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
1953: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1954: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1955: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1956: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1957: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1958: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1959: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1960: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1961: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1962: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1963: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1964: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1965: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1966: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1967: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1968: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1969: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1970: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1971: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1972: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1973: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1974: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1975: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1976: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1977: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1978: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1979: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1980: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1981: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1982: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1983: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
1984: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
1985: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1986: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1987: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1988: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1989: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1990: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1991: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1992: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
1993: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1994: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1995: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1996: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
1997: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1998: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
1999: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2000: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2001: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2002: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2003: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2004: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2005: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2006: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2007: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2008: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2009: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2010: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2011: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2012: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2013: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2014: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2015: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2016: 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,
2017: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2018: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2019: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2020: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2021: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2022: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2023: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2024: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2025: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2026: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2027: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2028: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2029: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2030: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2031: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2032: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2033: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2034: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2035: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2036: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2037: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2038: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2039: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2040: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2041: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2042: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2043: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2044: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2045: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2046: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2047: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2048: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2049: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2050: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2051: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2052: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2053: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2054: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2055: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2056: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2057: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2058: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2059: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2060: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2061: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2062: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2063: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2064: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2065: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2066: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2067: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2068: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2069: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2070: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2071: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2072: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2073: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2074: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2075: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2076: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2077: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2078: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2079: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2080: 5,6,6,7,6,7,7,8,6,7,7,8,7,8,8,9,6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,
2081: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2082: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2083: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2084: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2085: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2086: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2087: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2088: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2089: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2090: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2091: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2092: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2093: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2094: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2095: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2096: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2097: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2098: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2099: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2100: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2101: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2102: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2103: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2104: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2105: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2106: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2107: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2108: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2109: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2110: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2111: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2112: 6,7,7,8,7,8,8,9,7,8,8,9,8,9,9,10,7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,
2113: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2114: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2115: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2116: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2117: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2118: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2119: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2120: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2121: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2122: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2123: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2124: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2125: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2126: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2127: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2128: 7,8,8,9,8,9,9,10,8,9,9,10,9,10,10,11,8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,
2129: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2130: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2131: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2132: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2133: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2134: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2135: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2136: 8,9,9,10,9,10,10,11,9,10,10,11,10,11,11,12,9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,
2137: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2138: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2139: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2140: 9,10,10,11,10,11,11,12,10,11,11,12,11,12,12,13,10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,
2141: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2142: 10,11,11,12,11,12,12,13,11,12,12,13,12,13,13,14,11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,
2143: 11,12,12,13,12,13,13,14,12,13,13,14,13,14,14,15,12,13,13,14,13,14,14,15,13,14,14,15,14,15,15,16 }
2144: };
2145:
2146: #else
2147: extern Bm_consts bm_consts;
2148: #endif
2149:
2150: double Bm_match();
2151: char *BM_toa();
2152: 0707070035351137041006640007620000050000010260520476773366600001000000207047CCITT.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
2153: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
2154: /* The copyright notice does not imply actual or intended publication. */
2155: /* AUTHORS: */
2156: /* H. S. Baird - ATT-BL MH - first versions */
2157:
2158: /* CCITT.c - functions for CCITT compression/decompression of binary images.
2159: The following discussion is a summary of CCITT Recommendations T.4 and T.6
2160: on facsimile coding schemes and coding control functions for Group 3 and Group
2161: 4 facsimile apparatus (drafted at Malaga-Torremolinos, 1984). They describe
2162: algorithms for invertible (lossless) compression and decompression of bilevel
2163: (black-and-white, not grey) 2D rectangular images of arbitrary height and
2164: width. By convention the images are processed top-down, one horizontal scan
2165: line at a time. It is not strictly necessary to know the height of an image
2166: before starting compression or decompression. Width, however, must be known
2167: in advance in some cases (discussed below), and must remain constant for the
2168: whole image in all cases. There are three distinct but intimately related
2169: standards: Group 3 1-dimensional, Group 3 2-dimensional, and Group 4.
2170: VLSI hardware implementations always include all three. The Group 3 encodings
2171: are used in the vast installed base of FAX machines. Group 4 is not used
2172: in today's FAX machines, but seems to be the default standard in document image
2173: archiving applications.
2174: The CCITT Group 3 FAX standard permits either 1-D or 2-D encoding.
2175: It is not easy to tell from an encoding which was used. Both 1-D and 2-D
2176: assume fixed scanline length (in pixels), which must be known at encoding time.
2177: Group 3 1-D (g31) code uses fixed ``modified Huffman'' codes for
2178: run-lengths, with two different code tables for black and white runs. Each
2179: line is assumed to begin with a (possibly 0-length) white run. Of course,
2180: the colors strictly alternate. An empty (all-white) line is supposed to be
2181: spelled out with a full pixel count, although some decoders won't complain
2182: if just a 0-length count is used. There are provisions for fill bits at the
2183: end of lines to allow slow receiving equipment to keep up. Each line ends with
2184: an EOL code on which it may be possible to synchronize after transmission error.
2185: Group 3 2-D (g32) encoding tries to exploit the slowly-changing nature
2186: of artwork from line to line. It is a mixture of 1-D-coded lines and
2187: ``2-D''-coded lines describing small local changes relative to the immediately
2188: prior ``reference'' line. 1-D coding recurs every few (`k') lines, so that
2189: resynchronization is frequently possible. K is usually 2 or 4, but the
2190: standard permits any number, even infinity, since the coding method used on
2191: a line is specified by which of two special EOLx codes is used to end the
2192: prior line.
2193: CCITT Group 4 (g4) is like Group 3 2-D, but optimized to take advantage
2194: of a lossless communications channel or reliable storage medium (such as computer
2195: memory), where resynchronization is unnecessary. Thus the first line is 2-D
2196: encoded referenced to an imaginary initial blank line, k is always infinity,
2197: and EOL's are not used at all. It essential that the line-length be known in
2198: advance of both encoding and decoding, so that line-breaks can be triggered when
2199: that length is exceeded. End of FAX buffer (end of page) is signaled by a
2200: special EOFB code.
2201: On images of printed text and sparse line-graphics, g4-compressed files
2202: are often 15-40X smaller than bitmap (packed bits), 5X than bitfile(9.5),
2203: 2X than g31, and 2X than rle | pack.
2204: PERFORMANCE
2205: On 10 printed A4 pages (business letters, technical reports, etc),
2206: at a resolution of 400 dpi:
2207: binary: 2020 Kbytes CPU secs (to compress binary)
2208: pack: 200 - 380 17
2209: bitfile(9.5): 150 - 360 ?
2210: rle: 100 - 230 7.5
2211: compress: 90 - 155 14
2212: g31: 85 - 190 13
2213: g32: 55 - 110 13
2214: g4: 30 - 70 13
2215: G4-compressed files are 15-40X smaller than binary, 5X than bitfile(9.5),
2216: 3.5X than rle, 2X than g31, and 2X than rle | pack.
2217: */
2218:
2219: #include <stdio.h>
2220: #include <string.h>
2221: #include <ctype.h>
2222: #include "CPU.h"
2223: #include "stdocr.h"
2224: #include "rle.h"
2225: #include "bitio.h"
2226: #include "CCITT.h"
2227:
2228: #define DEBUG 0 /* 0 disables compilation of all debugging code;
2229: 1 compiles, but must enable particular parts below */
2230: #define NEW_TRAIL 1 /* enable new trailing-0 counts (has passed early tests) */
2231: #define dbg_trail 0
2232:
2233: DST_table *ccitt_table()
2234: { DST_context cx;
2235: if((cx.t = (DST_table *)malloc(sizeof(DST_table)))==NULL)
2236: abort("CCITT.c: build_tbl: can't alloc cx.t");
2237: /* All tables have e[DST_white], e[DST_black], & e[DST_2d] entries */
2238: cx.t->mny=3;
2239: if((cx.t->e=(DST_entry *)malloc(cx.t->mny*sizeof(DST_entry)))==NULL)
2240: abort("CCITT.c: build_tbl: can't alloc cx.t->e[%d]",cx.t->mny);
2241:
2242: cx.s = cx.c = DST_white;
2243: cx.l = 0;
2244: cx.t->e[cx.s].p[0] = '\0';
2245: cx.t->e[cx.s].l = 0;
2246: cx.t->e[cx.s].z = 0;
2247: build_transits(cx);
2248:
2249: cx.s = cx.c = DST_black;
2250: cx.l = 0;
2251: cx.t->e[cx.s].p[0] = '\0';
2252: cx.t->e[cx.s].l = 0;
2253: cx.t->e[cx.s].z = 0;
2254: build_transits(cx);
2255:
2256: cx.s = cx.c = DST_2d;
2257: cx.l = 0;
2258: cx.t->e[cx.s].p[0] = '\0';
2259: cx.t->e[cx.s].l = 0;
2260: cx.t->e[cx.s].z = 0;
2261: build_transits(cx);
2262:
2263: #if DEBUG
2264: if(F) ccitt_err_tbl(cx.t);
2265: #endif
2266: return(cx.t);
2267: }
2268:
2269: DST_state new_state(t)
2270: DST_table *t;
2271: { t->mny++;
2272: if((t->e=(DST_entry *)realloc(t->e,t->mny*sizeof(DST_entry)))==NULL)
2273: abort("can't realloc t->[%d]",t->mny);
2274: return(t->mny-1);
2275: }
2276:
2277: /* The entry described by `cx' exists in the table, and its prefix `p' is
2278: setup; create its transitions, and their next entries, recursively. */
2279: build_transits(cx)
2280: DST_context cx;
2281: #define entry cx.t->e[cx.s]
2282: #define transit entry.t[col]
2283: { DST_color col;
2284: DST_entry ne; /* next entry */
2285: DST_context ncx; /* next Context */
2286: char **s,**ss; /* for searching code */
2287: short *c,*cs;
2288: int si,matching,longer;
2289: char svch,col_str[2];
2290: switch(cx.c) {
2291: case DST_white:
2292: ss=codewht;
2293: cs=bitcwht;
2294: break;
2295: case DST_black:
2296: ss=codeblk;
2297: cs=bitcblk;
2298: break;
2299: case DST_2d:
2300: ss=code2d;
2301: cs=bitc2d;
2302: break;
2303: };
2304: for(col=0;col<=1;col++) {
2305: sprintf(col_str,"%1d",col);
2306: ncx = cx; ncx.l++;
2307: /* build a transition */
2308: strcpy(ne.p,entry.p); strcat(ne.p,col_str);
2309: ne.l = ncx.l;
2310: if(col==0) ne.z = entry.z+1; else ne.z = 0;
2311: /* count those that match new prefix */
2312: longer=matching=0;
2313: for(s=ss,c=cs,si=0; (*s)!=NULL; s++,c++,si++) {
2314: if(*c==ncx.l) {
2315: if(strcmp(*s,ne.p)==0) {
2316: matching++;
2317: switch(cx.c) {
2318: case DST_white:
2319: case DST_black:
2320: transit.a = itor(si);
2321: break;
2322: case DST_2d:
2323: transit.a = si;
2324: break;
2325: };
2326: };
2327: }
2328: else if(*c>ncx.l) {
2329: svch=(*s)[ncx.l]; (*s)[ncx.l] = '\0';
2330: if(strcmp(*s,ne.p)==0) {
2331: longer++;
2332: };
2333: (*s)[ncx.l]=svch;
2334: };
2335: };
2336: /* analyze results */
2337: if(matching==0&&longer>0) {
2338: /* no match yet; go deeper */
2339: transit.a = DST_action_NULL;
2340: ncx.s = transit.s = new_state(cx.t);
2341: strcpy(cx.t->e[ncx.s].p,ne.p);
2342: cx.t->e[ncx.s].l = ne.l;
2343: cx.t->e[ncx.s].z = ne.z;
2344: build_transits(ncx);
2345: }
2346: else if(matching==1&&longer==0) {
2347: /* unique leaf: good */
2348: /* picked up action earlier */
2349: switch(cx.c) {
2350: case DST_white:
2351: case DST_black:
2352: if(transit.a<=63) /* termination code */
2353: transit.s = flip_color(cx.c);
2354: else /* makeup code */
2355: transit.s = cx.c;
2356: break;
2357: case DST_2d:
2358: /* legal end of code */
2359: transit.s = DST_state_NULL;
2360: break;
2361: };
2362: }
2363: else { /* illegal transition */
2364: transit.a = DST_action_ERROR;
2365: transit.s = DST_state_NULL;
2366: };
2367: };
2368: }
2369:
2370: ccitt_err_tbl(t)
2371: DST_table *t;
2372: { int d;
2373: ccitt_err_state(DST_white,t);
2374: ccitt_err_state(DST_black,t);
2375: ccitt_err_state(DST_2d,t);
2376: }
2377:
2378: ccitt_err_state(s,t)
2379: DST_state s;
2380: DST_table *t;
2381: { err("%03d %s %2d %2d%*s %d %03d,%-4d %d %03d,%-4d",
2382: s,t->e[s].p,t->e[s].l,t->e[s].z,14-strlen(t->e[s].p)," ",
2383: 0,t->e[s].t[0].s,t->e[s].t[0].a,
2384: 1,t->e[s].t[1].s,t->e[s].t[1].a
2385: );
2386: if(t->e[s].t[0].s>1) ccitt_err_state(t->e[s].t[0].s,t);
2387: if(t->e[s].t[1].s>1) ccitt_err_state(t->e[s].t[1].s,t);
2388: }
2389:
2390: /* Translate a stream of bits in CCITT FAX Group 3 (1-D) compression format
2391: into a sequence of RLE_Lines. Returns one (RLE_Line *) on each call (or NULL
2392: if EOF or error). The first pixel (black or white) in each g31 line is
2393: assigned run index 0. */
2394: RLE_Line *g31_to_rlel(t,f,bof)
2395: DST_table *t;
2396: BITFILE *f;
2397: boolean bof; /* beginning of file */
2398: #define dbg_g31r_r (0) /* trace each run/EOL/ERR_SYN */
2399: #define dbg_g31r_c (0) /* trace each Huffman code (or, fill+EOL)*/
2400: #define dbg_g31r_t (0) /* trace each state-transition */
2401: { static DST_context cx;
2402: static RLE_Line rl;
2403: static RLE_Run *r; /* prior, current runs */
2404: int run,biti,sync,si,bitv;
2405: boolean fill;
2406: /* color of 1st run in each line */
2407: #define g31_first_color DST_white
2408: /* reverse Black/White in output image */
2409: #define g31_negative 0
2410: if(bof){if(T) { /* sync by skipping initial FILL & EOL code */
2411: sync=0; while((bitv=getb(f))==0) sync++;
2412: if(bitv!=1||sync<11) {
2413: #if DEBUG
2414: if(dbg_g31r_c) {
2415: fprintf(stderr,"BOF_ERR ");
2416: for(si=0;si<sync;si++) fprintf(stderr,"0");
2417: if(bitv==1) fprintf(stderr,"1\n");
2418: else fprintf(stderr,"?\n");
2419: };
2420: #endif
2421: return(NULL);
2422: }
2423: #if DEBUG
2424: else if(dbg_g31r_c){
2425: fprintf(stderr,"BOF_EOL ");
2426: for(si=0;si<sync;si++) fprintf(stderr,"0");
2427: fprintf(stderr,"1\n");
2428: };
2429: #endif
2430: };
2431: /* start file expecting a run-code of a fixed color */
2432: cx.s = cx.c = g31_first_color;
2433: rl.y = -1; /* assume first line is y==0 */
2434: };
2435: rl.y++; rl.runs=0; r = rl.r; biti=run=0;
2436: while(T) switch(getb(f)) {
2437: case 0 : /* next bit is 0 */
2438: switch(t->e[cx.s].t[0].a) {
2439: case DST_action_ERROR:
2440: /* bad code: try to resynchronize */
2441: #if DEBUG
2442: if(dbg_g31r_t){
2443: fprintf(stderr,"%s %04d %s0?...\n",
2444: (cx.c==DST_white)? "W": "B",
2445: t->e[cx.s].t[0].s,
2446: t->e[cx.s].p);
2447: };
2448: #endif
2449: /* count trailing 0's so far (should be in table) */
2450: #if !NEW_TRAIL
2451: sync=1;
2452: si=strlen(t->e[cx.s].p)-1;
2453: while(si>=0&&t->e[cx.s].p[si]=='0') {sync++; si--;};
2454: fill = (si<0); /* all 0's: may be fill bits */
2455: #else
2456: sync=t->e[cx.s].z+1;
2457: fill = (sync>t->e[cx.s].l); /* all 0's: maybe fill bits */
2458: #endif
2459: #if DEBUG
2460: if(dbg_trail) err("sync %d fill %d",sync,fill);
2461: if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s0?",t->e[cx.s].p);
2462: #endif
2463: while(sync<11) {
2464: switch(bitv=getb(f)) {
2465: case 0: sync++;
2466: #if DEBUG
2467: if(dbg_g31r_c) fprintf(stderr,"0");
2468: #endif
2469: break;
2470: case 1: sync=0; fill=F;
2471: #if DEBUG
2472: if(dbg_g31r_c) fprintf(stderr,"1");
2473: #endif
2474: break;
2475: case EOF:
2476: #if DEBUG
2477: if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
2478: #endif
2479: return(NULL); break;
2480: };
2481: };
2482: /* next `1' will synchronize */
2483: do { switch(bitv=getb(f)) {
2484: case 0:
2485: #if DEBUG
2486: if(dbg_g31r_c) fprintf(stderr,"0");
2487: #endif
2488: break;
2489: case 1:
2490: #if DEBUG
2491: if(dbg_g31r_c) fprintf(stderr,"1");
2492: #endif
2493: break;
2494: case EOF:
2495: #if DEBUG
2496: if(dbg_g31r_c) fprintf(stderr,"<EOF>\n");
2497: #endif
2498: return(NULL); break;
2499: };
2500: }
2501: while(bitv!=1);
2502: #if DEBUG
2503: if(dbg_g31r_c) fprintf(stderr,"\n");
2504: if(dbg_g31r_r) {
2505: if(fill) fprintf(stderr,"FILL_EOL\n");
2506: else fprintf(stderr,"ERR_SYN_EOL\n");
2507: };
2508: #endif
2509: /* start next line expecting a run-code of a fixed color */
2510: cx.s = cx.c = g31_first_color;
2511: return(&rl);
2512: break;
2513: case DST_action_NULL:
2514: #if DEBUG
2515: if(dbg_g31r_t)fprintf(stderr,"%s %04d %s0\n",
2516: (cx.c==DST_white)? "W": "B",
2517: t->e[cx.s].t[0].s,
2518: t->e[cx.s].p);
2519: #endif
2520: cx.s = t->e[cx.s].t[0].s;
2521: break;
2522: case DST_EOL:
2523: #if DEBUG
2524: if(dbg_g31r_c)fprintf(stderr,"EOL %s0\n",
2525: t->e[cx.s].p);
2526: if(dbg_g31r_r)fprintf(stderr,"EOL\n");
2527: #endif
2528: /* start next line expecting a run-code of a fixed color */
2529: cx.s = cx.c = g31_first_color;
2530: return(&rl);
2531: break;
2532: default:
2533: #if DEBUG
2534: if(dbg_g31r_c)fprintf(stderr,"%s%6d %s0\n",
2535: (cx.c==DST_white)? "W": "B",
2536: t->e[cx.s].t[0].a,
2537: t->e[cx.s].p);
2538: #endif
2539: if(t->e[cx.s].t[0].a<=63) {
2540: run += t->e[cx.s].t[0].a;
2541: #if DEBUG
2542: if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
2543: (cx.c==DST_white)? "W": "B",
2544: run);
2545: #endif
2546: biti += run;
2547: if(cx.c==DST_black^g31_negative) {
2548: /* end of black run */
2549: r->xe = biti-1;
2550: r++; rl.runs++;
2551: }
2552: else { /* end of white run */
2553: r->xs = biti;
2554: };
2555: cx.c = flip_color(cx.c);
2556: run = 0;
2557: }
2558: else run += t->e[cx.s].t[0].a;
2559: cx.s = t->e[cx.s].t[0].s;
2560: break;
2561: };
2562: break;
2563: case 1: /* next bit is 1 */
2564: switch(t->e[cx.s].t[1].a) {
2565: case DST_action_ERROR:
2566: /* bad code: try to resynchronize */
2567: #if DEBUG
2568: if(dbg_g31r_t){
2569: fprintf(stderr,"%s %04d %s1?...\n",
2570: (cx.c==DST_white)? "W": "B",
2571: t->e[cx.s].t[1].s,
2572: t->e[cx.s].p);
2573: };
2574: if(dbg_g31r_c)fprintf(stderr,"ERR_SYN %s1?",t->e[cx.s].p);
2575: #endif
2576: /* no trailing 0's; can't be fill bits */
2577: sync=0;
2578: while(sync<11) {
2579: switch(bitv=getb(f)) {
2580: case 0: sync++;
2581: #if DEBUG
2582: if(dbg_g31r_c) fprintf(stderr,"0");
2583: #endif
2584: break;
2585: case 1: sync=0;
2586: #if DEBUG
2587: if(dbg_g31r_c) fprintf(stderr,"1");
2588: #endif
2589: break;
2590: case EOF:
2591: #if DEBUG
2592: if(dbg_g31r_c)
2593: fprintf(stderr,"<EOF>\n");
2594: #endif
2595: return(NULL); break;
2596: };
2597: };
2598: /* next `1' will synchronize */
2599: do { switch(bitv=getb(f)) {
2600: case 0:
2601: #if DEBUG
2602: if(dbg_g31r_c) fprintf(stderr,"0");
2603: #endif
2604: break;
2605: case 1:
2606: #if DEBUG
2607: if(dbg_g31r_c) fprintf(stderr,"1");
2608: #endif
2609: break;
2610: case EOF:
2611: #if DEBUG
2612: if(dbg_g31r_c)
2613: fprintf(stderr,"<EOF>\n");
2614: #endif
2615: return(NULL); break;
2616: };
2617: }
2618: while(bitv!=1);
2619: #if DEBUG
2620: if(dbg_g31r_c) fprintf(stderr,"\n");
2621: if(dbg_g31r_r) fprintf(stderr,"ERR_SYN_EOL\n");
2622: #endif
2623: /* start next line expecting a run-code of a fixed color */
2624: cx.s = cx.c = g31_first_color;
2625: return(&rl);
2626: break;
2627: case DST_action_NULL:
2628: #if DEBUG
2629: if(dbg_g31r_t)fprintf(stderr,"%s %04d %s1\n",
2630: (cx.c==DST_white)? "W": "B",
2631: t->e[cx.s].t[1].s,
2632: t->e[cx.s].p);
2633: #endif
2634: cx.s = t->e[cx.s].t[1].s;
2635: break;
2636: case DST_EOL:
2637: #if DEBUG
2638: if(dbg_g31r_c)fprintf(stderr,"EOL %s1\n",
2639: t->e[cx.s].p);
2640: if(dbg_g31r_r)fprintf(stderr,"EOL\n");
2641: #endif
2642: /* start next line expecting a run-code of a fixed color */
2643: cx.s = cx.c = g31_first_color;
2644: return(&rl);
2645: break;
2646: default:
2647: #if DEBUG
2648: if(dbg_g31r_c)fprintf(stderr,"%s%6d %s1\n",
2649: (cx.c==DST_white)? "W": "B",
2650: t->e[cx.s].t[1].a,
2651: t->e[cx.s].p);
2652: #endif
2653: if(t->e[cx.s].t[1].a<=63) {
2654: run += t->e[cx.s].t[1].a;
2655: #if DEBUG
2656: if(dbg_g31r_r)fprintf(stderr,"%s%6d\n",
2657: (cx.c==DST_white)? "W": "B",
2658: run);
2659: #endif
2660: biti += run;
2661: if(cx.c==DST_black^g31_negative) {
2662: /* end of black run */
2663: r->xe = biti-1;
2664: r++; rl.runs++;
2665: }
2666: else { /* end of white run */
2667: r->xs = biti;
2668: };
2669: cx.c = flip_color(cx.c);
2670: run = 0;
2671: }
2672: else run += t->e[cx.s].t[1].a;
2673: cx.s = t->e[cx.s].t[1].s;
2674: break;
2675: };
2676: break;
2677: case EOF:
2678: return(NULL);
2679: break;
2680: default:
2681: return(NULL);
2682: break;
2683: };
2684: /* never come here: return() variously from cases above */
2685: }
2686:
2687: /* Translate a sequence of RLE_Line's (describing a binary image)
2688: into a file (a stream of bits) in CCITT FAX Group 3 (1-D) compression format.
2689: BOF_to_g31() must be called first; then call rlel_to_g31() for each line
2690: (including blank lines); finally, EOF_to_g31() must be called. Each line's
2691: EOL and the RTC's first EOL are padded so they end on a byte boundary.
2692: */
2693: /* debugging flags: trace to stderr */
2694: #define dbg_rg31_e (0) /* entry */
2695: #define dbg_rg31_r (0) /* runs */
2696: #define dbg_rg31_s (0) /* bitstrings */
2697:
2698: #if DEBUG
2699: #define bits_g31(bits) { \
2700: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
2701: if(dbg_rg31_s) fprintf(stderr,"%s",(bits)); \
2702: if(dbg_rg31_r) fprintf(stderr," "); \
2703: }
2704: #define EOL_g31 { \
2705: if(dbg_rg31_r) fprintf(stderr,"EOL "); \
2706: bits_g31(EOLSTRING); \
2707: if(dbg_rg31_r) fprintf(stderr,"\n"); \
2708: }
2709: #else
2710: #define bits_g31(bits) { \
2711: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
2712: }
2713: #define EOL_g31 { \
2714: bits_g31(EOLSTRING); \
2715: }
2716: #endif
2717:
2718: BOF_to_g31(f)
2719: BITFILE *f; /* state of output bitfile */
2720: { char *cs;
2721: EOL_g31;
2722: }
2723:
2724: rlel_to_g31(rl,wid,f)
2725: RLE_Line *rl; /* line of runs: if NULL, then blank */
2726: int wid; /* width of an output line in pixels */
2727: BITFILE *f; /* state of output bitfile */
2728: { int pi; /* input pixel index on line */
2729: RLE_Run *rp,*pp,*sp;
2730: int runl,codi;
2731: char *cs,*p01;
2732: #if DEBUG
2733: #define Wrun_g31(rn) { \
2734: runl=(rn); \
2735: if(dbg_rg31_r) fprintf(stderr,"W %5d ",runl); \
2736: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
2737: p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
2738: if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
2739: if(dbg_rg31_r) fprintf(stderr,"\n"); \
2740: }
2741: #else
2742: #define Wrun_g31(rn) { \
2743: runl=(rn); \
2744: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
2745: p01=codewht[codi=rtoi(runl)]; bits_g31(p01); \
2746: if(codi>=64) {p01=codewht[runl%64]; bits_g31(p01);}; \
2747: }
2748: #endif
2749: #if DEBUG
2750: #define Brun_g31(rn) { \
2751: runl=(rn); \
2752: if(dbg_rg31_r) fprintf(stderr,"B %5d ",runl); \
2753: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
2754: p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
2755: if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
2756: if(dbg_rg31_r) fprintf(stderr,"\n"); \
2757: }
2758:
2759: #else
2760: #define Brun_g31(rn) { \
2761: runl=(rn); \
2762: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g31(p01); runl-=2560;}; \
2763: p01=codeblk[codi=rtoi(runl)]; bits_g31(p01); \
2764: if(codi>=64) {p01=codeblk[runl%64]; bits_g31(p01);}; \
2765: }
2766: #endif
2767: #if DEBUG
2768: if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
2769: #endif
2770: if(rl!=NULL&&rl->runs>0) {
2771: pi=0; /* bit to write next */
2772: #if DEBUG
2773: if(dbg_rg31_e) err("rlel_to_g31(rl[y%d,r%d])",rl->y,rl->runs);
2774: #endif
2775: for(sp=(rp=rl->r)+rl->runs; rp<sp; rp++) {
2776: Wrun_g31(rp->xs-pi); pi=rp->xs;
2777: Brun_g31(rp->xe-pi+1); pi=rp->xe+1;
2778: };
2779: if((--rp)->xe+1<wid) Wrun_g31(wid-rp->xe-1);
2780: }
2781: else {
2782: #if DEBUG
2783: if(dbg_rg31_e) err("rlel_to_g31(rl[y?,r0])");
2784: #endif
2785: Wrun_g31(wid); /* blank (all-white) scanline */
2786: };
2787: /* fill so that EOL ends on byte boundary */
2788: padb(f,0,8,EOLLENGTH);
2789: #if DEBUG
2790: if(dbg_rg31_s) fprintf(stderr,"+0?");
2791: #endif
2792: EOL_g31;
2793: }
2794:
2795: EOF_to_g31(f)
2796: BITFILE *f;
2797: { char *cs;
2798: /* fill so that EOL ends on byte boundary */
2799: padb(f,0,8,EOLLENGTH);
2800: #if DEBUG
2801: if(dbg_rg31_s) fprintf(stderr,"+0?");
2802: #endif
2803: /* write RTC */
2804: EOL_g31;
2805: EOL_g31;
2806: EOL_g31;
2807: EOL_g31;
2808: EOL_g31;
2809: EOL_g31;
2810: }
2811:
2812: /* Macro for use within g32_to_rlel, to read one 1-D Modified Huffman coded
2813: run-length of a given color, placing the result in a given variable.
2814: Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
2815: */
2816: #if DEBUG
2817: #define g32_1d_run(C,V) { \
2818: run = 0; \
2819: do { cx.tr.s = (C); \
2820: do { px = cx; \
2821: switch(bitv=getb(f)) { \
2822: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
2823: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
2824: case EOF : goto trap_eof; break; \
2825: }; \
2826: } \
2827: while(cx.tr.a==DST_action_NULL); \
2828: switch(cx.tr.a) { \
2829: case DST_EOL : \
2830: if(dbg_g32r_c)fprintf(stderr,"EOL %s\n",EOLSTRING); \
2831: goto trap_eol; \
2832: break; \
2833: case DST_action_ERROR : goto trap_code_err; break; \
2834: default : \
2835: if(dbg_g32r_c)fprintf(stderr,"%s%6d %s%d\n", \
2836: ((C)==DST_white)? "W": "B", \
2837: cx.tr.a, \
2838: t->e[px.tr.s].p, \
2839: bitv); \
2840: run += cx.tr.a; \
2841: break; \
2842: }; \
2843: } \
2844: while(cx.tr.a>63); \
2845: (V) = run; \
2846: }
2847: #else
2848: #define g32_1d_run(C,V) { \
2849: run = 0; \
2850: do { cx.tr.s = (C); \
2851: do { px = cx; \
2852: switch(bitv=getb(f)) { \
2853: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
2854: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
2855: case EOF : goto trap_eof; break; \
2856: }; \
2857: } \
2858: while(cx.tr.a==DST_action_NULL); \
2859: switch(cx.tr.a) { \
2860: case DST_EOL : \
2861: goto trap_eol; \
2862: break; \
2863: case DST_action_ERROR : goto trap_code_err; break; \
2864: default : \
2865: run += cx.tr.a; \
2866: break; \
2867: }; \
2868: } \
2869: while(cx.tr.a>63); \
2870: (V) = run; \
2871: }
2872: #endif
2873:
2874: /* Translate a stream of bits in CCITT FAX Group 3 (2-D) compression format
2875: into a sequence of RLE_Lines. Returns one (RLE_Line *) on each call (or NULL
2876: if EOF or error). The first pixel (black or white) in each g32 line is
2877: assigned run index 0. */
2878: RLE_Line *g32_to_rlel(t,f,bof)
2879: DST_table *t;
2880: BITFILE *f;
2881: boolean bof; /* beginning of file */
2882: #define dbg_g32r_e (0) /* entry/exit */
2883: #define dbg_g32r_r (0) /* trace each run/EOL/ERR_SYN */
2884: #define dbg_g32r_c (0) /* trace each Huffman code (or, fill+EOL)*/
2885: #define dbg_g32r_t (0) /* trace each state-transition */
2886: #define g32r_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
2887: { static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
2888: RLE_Line *swrl;
2889: int bitv; /* the last-read bit value */
2890: DST_context cx,px; /* the current/prior decoding context */
2891: RLE_Run *cr,*pr,*pre; /* into current/prior rle lines */
2892: RLE_Run *pra0; /* rightmost in prior line with xe<=a0 (if none: prl->r) */
2893: int run,sync,si,rtc_eols;
2894: boolean fill;
2895: /* pixel indices (0,1,...): current-line a*; prior-line b*.
2896: a0 is the index of the most recently completely encoded bit */
2897: int a0,a1,a2,b1,b2;
2898: DST_color a0_color; /* a0's color: same as a2 & b2, opposite of a1 & b1 */
2899: int a01,a12; /* lengths of runs a0-a1 & a1-a2 */
2900: #define g32_first_color DST_white /* color of 1st run in each line */
2901: #define g32_negative (0) /* if 1, invert Black/White on output */
2902: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
2903: /* detect b1 & b2: sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
2904: #define g32r_find_Bb1Wb2 { \
2905: /* find 1st black changing pel>a0 */ \
2906: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
2907: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
2908: /* look beyond pra0 */ \
2909: pr=pra0; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
2910: /* move b2 to 1st changing white pel > b1 */ \
2911: if(pr<pre) b2=pr->xe+1; \
2912: else b1=b2=prl->len; \
2913: }
2914: #define g32r_find_Wb1Bb2 { \
2915: /* find 1st white changing pel>a0 */ \
2916: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
2917: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
2918: /* look beyond pra0 */ \
2919: pr=pra0; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
2920: /* move b2 to 1st changing black pel > b1 */ \
2921: if(pr<pre) { \
2922: if((pr+1)<pre) b2=(pr+1)->xs; \
2923: else b2=prl->len; \
2924: } \
2925: else b1=b2=prl->len; \
2926: }
2927: #define g32r_find_b1b2 {if(a0_color==DST_white) g32r_find_Bb1Wb2 else g32r_find_Wb1Bb2;}
2928:
2929: #if DEBUG
2930: if(dbg_g32r_e) fprintf(stderr,"g32_to_rlel(t,bf,bof%d)\n",bof);
2931: #endif
2932: if(bof){crl= &rl0; crl->y= -1; crl->len=0; crl->runs=0;
2933: prl= &rl1; prl->y= -1; prl->len=0; prl->runs=0;
2934: /* sync by skipping initial FILL & EOL code */
2935: sync=0; while((bitv=getb(f))==0) sync++;
2936: if(bitv!=1||sync<11) {
2937: #if DEBUG
2938: if(dbg_g32r_c) {
2939: fprintf(stderr,"BOF_ERR ");
2940: for(si=0;si<sync;si++) fprintf(stderr,"0");
2941: if(bitv==1) fprintf(stderr,"1\n");
2942: else fprintf(stderr,"?\n");
2943: };
2944: #endif
2945: return(NULL);
2946: }
2947: #if DEBUG
2948: else if(dbg_g32r_c){
2949: fprintf(stderr,"BOF_EOL ");
2950: for(si=0;si<sync;si++) fprintf(stderr,"0");
2951: fprintf(stderr,"1\n");
2952: };
2953: #else
2954: ;
2955: #endif
2956: prl->y = -1; crl->y = 0;
2957: }
2958: else crl->y = prl->y + 1;
2959:
2960: pre = (pra0=pr=prl->r) + prl->runs; /* prior line */
2961: crl->runs=0; cr=crl->r-1; /* current line */
2962: /* start on an imaginary white pixel just to left of margin */
2963: a0= -1; a0_color = DST_white;
2964:
2965: /* check 1-D / 2-D bit immediately after prior EOL */
2966: switch(bitv=getb(f)) {
2967: case 0 : /* 2-dimensionally encoded line */
2968: #if DEBUG
2969: if(dbg_g32r_c) fprintf(stderr,"2D_LINE 0\n");
2970: #endif
2971: /* start b1/b2 on prior line's first black pixel, etc;
2972: if none, then place off end of line */
2973: if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
2974: /* parse a sequence of 2D codes... */
2975: while(T/* exited only via goto trap_* and return */) {
2976: cx.tr.s = DST_2d; cx.tr.a = DST_action_NULL;
2977: #if DEBUG
2978: if(dbg_g32r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
2979: #endif
2980: do { switch(bitv=getb(f)) {
2981: case 0 :
2982: case 1 :
2983: cx.tr=t->e[cx.tr.s].t[bitv];
2984: break;
2985: case EOF: goto trap_eof; break;
2986: };
2987: #if DEBUG
2988: if(dbg_g32r_t)fprintf(stderr,"%d->(%d,%d)\n",
2989: bitv,cx.tr.s,cx.tr.a);
2990: #endif
2991: }
2992: while(cx.tr.a==DST_action_NULL);
2993: #if DEBUG
2994: if(dbg_g32r_t)fprintf(stderr,"%s %04d %s0\n",
2995: (cx.c==DST_white)? "W": "B",
2996: cx.tr.s,
2997: t->e[cx.tr.s].p);
2998: #endif
2999: switch(cx.tr.a) {
3000: case i2D_V0:
3001: #if DEBUG
3002: if(dbg_g32r_c)
3003: fprintf(stderr,"V0 %s\n",code2d[cx.tr.a]);
3004: #endif
3005: a1=b1;
3006: /* encode a0 to a1-1 */
3007: if(a0_color==DST_black) cr->xe=a1-1;
3008: /* move a0 to a1 */
3009: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3010: a0_color = flip_color(a0_color);
3011: /* encode a0 */
3012: if(a0_color==DST_black)
3013: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3014: #if g32r_strict
3015: if(a0==prl->len-1)
3016: { a0++; goto trap_expecting_eol; };
3017: #endif
3018: g32r_find_b1b2;
3019: break;
3020: case i2D_VR1:
3021: #if DEBUG
3022: if(dbg_g32r_c)
3023: fprintf(stderr,"VR1 %s\n",code2d[cx.tr.a]);
3024: #endif
3025: a1=b1+1;
3026: /* encode a0 to a1-1 */
3027: if(a0_color==DST_black) cr->xe=a1-1;
3028: /* move a0 to a1 */
3029: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3030: a0_color = flip_color(a0_color);
3031: /* encode a0 */
3032: if(a0_color==DST_black)
3033: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3034: #if !g32r_strict
3035: if(a0==prl->len-1)
3036: { a0++; goto trap_expecting_eol; };
3037: #endif
3038: g32r_find_b1b2;
3039: break;
3040: case i2D_VR2:
3041: #if DEBUG
3042: if(dbg_g32r_c)
3043: fprintf(stderr,"VR2 %s\n",code2d[cx.tr.a]);
3044: #endif
3045: a1=b1+2;
3046: /* encode a0 to a1-1 */
3047: if(a0_color==DST_black) cr->xe=a1-1;
3048: /* move a0 to a1 */
3049: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3050: a0_color = flip_color(a0_color);
3051: /* encode a0 */
3052: if(a0_color==DST_black)
3053: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3054: #if !g32r_strict
3055: if(a0==prl->len-1)
3056: { a0++; goto trap_expecting_eol; };
3057: #endif
3058: g32r_find_b1b2;
3059: break;
3060: case i2D_VR3:
3061: #if DEBUG
3062: if(dbg_g32r_c)
3063: fprintf(stderr,"VR3 %s\n",code2d[cx.tr.a]);
3064: #endif
3065: a1=b1+3;
3066: /* encode a0 to a1-1 */
3067: if(a0_color==DST_black) cr->xe=a1-1;
3068: /* move a0 to a1 */
3069: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3070: a0_color = flip_color(a0_color);
3071: /* encode a0 */
3072: if(a0_color==DST_black)
3073: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3074: #if !g32r_strict
3075: if(a0==prl->len-1)
3076: { a0++; goto trap_expecting_eol; };
3077: #endif
3078: g32r_find_b1b2;
3079: break;
3080: case i2D_VL1:
3081: #if DEBUG
3082: if(dbg_g32r_c)
3083: fprintf(stderr,"VL1 %s\n",code2d[cx.tr.a]);
3084: #endif
3085: if((a1=b1-1)<0) err("g32_to_rlel: VL1 backs up to %d",a1);
3086: /* encode a0 to a1-1 */
3087: if(a0_color==DST_black) cr->xe=a1-1;
3088: /* move a0 to a1 */
3089: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3090: a0_color = flip_color(a0_color);
3091: /* encode a0 */
3092: if(a0_color==DST_black)
3093: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3094: #if !g32_strict
3095: if(a0==prl->len-1)
3096: { a0++; goto trap_expecting_eol; };
3097: #endif
3098: g32r_find_b1b2;
3099: break;
3100: case i2D_VL2:
3101: #if DEBUG
3102: if(dbg_g32r_c)
3103: fprintf(stderr,"VL2 %s\n",code2d[cx.tr.a]);
3104: #endif
3105: if((a1=b1-2)<0) err("g32_to_rlel: VL2 backs up to %d",a1);
3106: /* encode a0 to a1-1 */
3107: if(a0_color==DST_black) cr->xe=a1-1;
3108: /* move a0 to a1 */
3109: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3110: a0_color = flip_color(a0_color);
3111: /* encode a0 */
3112: if(a0_color==DST_black)
3113: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3114: #if !g32r_strict
3115: if(a0==prl->len-1)
3116: { a0++; goto trap_expecting_eol; };
3117: #endif
3118: g32r_find_b1b2;
3119: break;
3120: case i2D_VL3:
3121: #if DEBUG
3122: if(dbg_g32r_c)
3123: fprintf(stderr,"VL3 %s\n",code2d[cx.tr.a]);
3124: #endif
3125: if((a1=b1-3)<0) err("g32_to_rlel: VL3 backs up to %d",a1);
3126: /* encode a0 to a1-1 */
3127: if(a0_color==DST_black) cr->xe=a1-1;
3128: /* move a0 to a1 */
3129: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3130: a0_color = flip_color(a0_color);
3131: /* encode a0 */
3132: if(a0_color==DST_black)
3133: { crl->runs++; (++cr)->xs = a0; cr->xe = a0; };
3134: #if !g32r_strict
3135: if(a0==prl->len-1)
3136: { a0++; goto trap_expecting_eol; };
3137: #endif
3138: g32r_find_b1b2;
3139: break;
3140: case i2D_PASS:
3141: #if DEBUG
3142: if(dbg_g32r_c)
3143: fprintf(stderr,"PASS %s\n",code2d[cx.tr.a]);
3144: #endif
3145: /* move a0 to b2; no change of color */
3146: a0=b2; if(a0>=prl->len) goto trap_expecting_eol;
3147: if(a0_color==DST_black) cr->xe = a0;
3148: #if !g32r_strict
3149: if(a0==prl->len-1)
3150: { a0++; goto trap_expecting_eol; };
3151: #endif
3152: g32r_find_b1b2;
3153: break;
3154: case i2D_HORIZ:
3155: #if DEBUG
3156: if(dbg_g32r_c)
3157: fprintf(stderr,"HORIZ %s\n",code2d[cx.tr.a]);
3158: #endif
3159: if(a0_color==DST_white) {
3160: if(a0<0) a0=0; /* first run in line starts at 0 */
3161: g32_1d_run(DST_white,a01); a1 = a0 + a01;
3162: g32_1d_run(DST_black,a12); a2 = a1 + a12;
3163: if(a12>0) /* Black run of >0 length */ {
3164: crl->runs++;
3165: (++cr)->xs = a1;
3166: cr->xe = a2-1;
3167: };
3168: a0 = a2; /* still white */
3169: if(a0>=prl->len) goto trap_expecting_eol;
3170: /* encode a0 */
3171: #if !g32r_strict
3172: if(a0==prl->len-1)
3173: { a0++; goto trap_expecting_eol; };
3174: #endif
3175: g32r_find_Bb1Wb2;
3176: }
3177: else { g32_1d_run(DST_black,a01); a1 = a0 + a01;
3178: g32_1d_run(DST_white,a12); a2 = a1 + a12;
3179: if(a01>0) /* Black run of >0 length */ {
3180: cr->xe = a1 - 1;
3181: }
3182: else { /* 0-length: very peculiar: ignore */
3183: fprintf(stderr,
3184: "g32_to_rlel: HORIZ B%d! W%d - ignore\n",
3185: a01,a12);
3186: cr--; crl->runs--;
3187: };
3188: a0 = a2; /* still black */
3189: if(a0>=prl->len) goto trap_expecting_eol;
3190: /* encode a0 */
3191: crl->runs++; (++cr)->xs = a0;
3192: #if !g32r_strict
3193: if(a0==prl->len-1) {
3194: cr->xe = a0;
3195: a0++;
3196: goto trap_expecting_eol;
3197: };
3198: #endif
3199: g32r_find_Wb1Bb2;
3200: };
3201: break;
3202: case i2D_EOL:
3203: #if DEBUG
3204: if(dbg_g32r_c)
3205: fprintf(stderr,"EOL %s\n",code2d[cx.tr.a]);
3206: #endif
3207: goto trap_eol;
3208: break;
3209: case DST_action_ERROR: goto trap_code_err; break;
3210: };
3211: };
3212: break;
3213: case 1 : /* 1-dimensionally encoded line */
3214: #if DEBUG
3215: if(dbg_g32r_c) fprintf(stderr,"1D_LINE 1\n");
3216: #endif
3217: /* read a sequence of 1-D runcodes... */
3218: while(T/* exit only via goto trap_X */) {
3219: g32_1d_run(a0_color,a01);
3220: a1 = ((a0>=0)? a0 : 0) + a01;
3221: if(a01>0) {
3222: /* encode a0 through a1-1 */
3223: if(a0_color==DST_black^g32_negative) {
3224: /* output-black run */
3225: crl->runs++;
3226: (++cr)->xs=((a0>=0)? a0 : 0);
3227: cr->xe=a1-1;
3228: };
3229: };
3230: a0=a1;
3231: a0_color=flip_color(a0_color);
3232: if(prl->len>0 && a0>=prl->len) goto trap_expecting_eol;
3233: };
3234: break;
3235: case EOF : goto trap_eof; break;
3236: };
3237:
3238: /* come here via goto's: all these traps return() */
3239:
3240: trap_expecting_eol: /* come here expecting to see EOL or FILL+EOL */
3241: sync=0; while((bitv=getb(f))==0) sync++;
3242: switch(bitv) {
3243: case 1:
3244: if(sync==11) {
3245: #if DEBUG
3246: if(dbg_g32r_c){
3247: fprintf(stderr,"EOL %s\n",EOLSTRING);
3248: };
3249: #endif
3250: goto trap_eol;
3251: }
3252: else if(sync>11) {
3253: #if DEBUG
3254: if(dbg_g32r_c){
3255: fprintf(stderr,"FILLEOL ");
3256: for(si=0;si<sync-11;si++) fprintf(stderr,"0");
3257: fprintf(stderr,"+");
3258: fprintf(stderr,"%s\n",EOLSTRING);
3259: };
3260: #endif
3261: goto trap_eol;
3262: }
3263: else {
3264: #if DEBUG
3265: if(dbg_g32r_c){
3266: fprintf(stderr,"NOT EOL ");
3267: for(si=0;si<sync;si++) fprintf(stderr,"0");
3268: fprintf(stderr,"1?");
3269: };
3270: #endif
3271: sync=0;
3272: goto trap_eol_err;
3273: };
3274: break;
3275: case EOF: goto trap_eof; break;
3276: };
3277: goto trap_eol;
3278:
3279: trap_code_err:
3280: /* unexpected coding sequence:
3281: 'px' holds last decoding context & 'bitv' latest bit value;
3282: will attempt to resynchronize on next EOL */
3283: #if DEBUG
3284: if(dbg_g32r_c)fprintf(stderr,"CODERR %s%d?",
3285: t->e[px.tr.s].p,bitv);
3286: #endif
3287: /* count trailing 0's so far (should be in table) */
3288: #if !NEW_TRAIL
3289: if(bitv==0) sync=1; else sync=0;
3290: si=strlen(t->e[px.tr.s].p)-1;
3291: while(si>=0&&t->e[px.tr.s].p[si]=='0') {sync++; si--;};
3292: fill = (si<0); /* all 0's: may be fill bits */
3293: #else
3294: if(bitv==0) sync=t->e[px.tr.s].z+1; else sync=t->e[px.tr.s].z;
3295: fill = (sync>t->e[px.tr.s].l); /* all 0's: maybe fill bits */
3296: #endif
3297: #if DEBUG
3298: if(dbg_trail)err("sync %d fill %d",sync,fill);
3299: #endif
3300: trap_eol_err:
3301: while(sync<11) {
3302: switch(bitv=getb(f)) {
3303: case 0: sync++;
3304: #if DEBUG
3305: if(dbg_g32r_c) fprintf(stderr,"0");
3306: #endif
3307: break;
3308: case 1: sync=0;
3309: #if DEBUG
3310: if(dbg_g32r_c) fprintf(stderr,"1");
3311: #endif
3312: break;
3313: case EOF: goto trap_eof; break;
3314: };
3315: };
3316: /* next `1' will synchronize */
3317: do { switch(bitv=getb(f)) {
3318: case 0:
3319: #if DEBUG
3320: if(dbg_g32r_c) fprintf(stderr,"0");
3321: #endif
3322: break;
3323: case 1:
3324: #if DEBUG
3325: if(dbg_g32r_c) fprintf(stderr,"1");
3326: #endif
3327: break;
3328: case EOF: goto trap_eof; break;
3329: };
3330: }
3331: while(bitv!=1);
3332: #if DEBUG
3333: if(dbg_g32r_c) fprintf(stderr," EOL\n");
3334: #endif
3335: goto trap_eol;
3336:
3337: trap_eol: /* come here having seen (and reported) EOL */
3338: /* learn/check line-length */
3339: if(a0>=0) crl->len=a0; else crl->len=0;
3340: if(crl->len==0) {
3341: /* no pixels coded -- may be the 1st of 6 RTC EOLs */
3342: /* check suffix 1 bit */
3343: if((bitv=getb(f))!=1) goto trap_eol_err;
3344: rtc_eols=1;
3345: #if DEBUG
3346: if(dbg_g32r_c)fprintf(stderr,"RTC_EOL +1 (%d)\n",rtc_eols);
3347: #endif
3348: do { sync=0; while((bitv=getb(f))==0) sync++;
3349: switch(bitv) {
3350: case 1:
3351: if(sync<11) {
3352: #if DEBUG
3353: if(dbg_g32r_c){
3354: fprintf(stderr,"NOT RTC ");
3355: for(si=0;si<sync;si++)
3356: fprintf(stderr,"0");
3357: fprintf(stderr,"1?\n");
3358: };
3359: #endif
3360: sync=0;
3361: goto trap_eol_err;
3362: };
3363: break;
3364: case EOF: goto trap_eof; break;
3365: };
3366: /* check suffix 1 bit */
3367: if((bitv=getb(f))!=1) goto trap_eol_err;
3368: rtc_eols++;
3369: #if DEBUG
3370: if(dbg_g32r_c) {
3371: fprintf(stderr,"RTC_EOL ");
3372: for(si=0;si<sync;si++) fprintf(stderr,"0");
3373: fprintf(stderr,"1+1 (%d)\n",rtc_eols);
3374: };
3375: #endif
3376: }
3377: while(rtc_eols<6);
3378: /* normal RTC */
3379: #if DEBUG
3380: if(dbg_g32r_c)fprintf(stderr,"RTC\n");
3381: #endif
3382: return(NULL);
3383: }
3384: else if(prl->len==0) {
3385: #if DEBUG
3386: if(dbg_g32r_c)fprintf(stderr,"LINELEN %d\n",crl->len);
3387: #endif
3388: }
3389: else if(crl->len!=prl->len) {
3390: err("g32_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
3391: crl->y,crl->len,prl->len,prl->len);
3392: crl->len = prl->len;
3393: };
3394: swap_rl(crl,prl);
3395: return(prl);
3396:
3397: trap_eof:
3398: #if DEBUG
3399: if(dbg_g32r_c) fprintf(stderr,"<EOF>\n");
3400: #endif
3401: return(NULL);
3402:
3403: }
3404:
3405: /* Translate a sequence of RLE_Line's (describing a binary image)
3406: into a file (a stream of bits) in CCITT FAX Group 3 (2-D) compression format.
3407: BOF_to_g32() must be called first; then call rlel_to_g32() for each line
3408: (including blank lines); finally, EOF_to_g32() must be called. Each line's
3409: EOL and the RTC's first EOL will be padded so they end on a byte boundary.
3410: */
3411: /* debugging flags: trace to stderr */
3412: #define dbg_rg32_e (0) /* entry */
3413: #define dbg_rg32_r (0) /* runs */
3414: #define dbg_rg32_s (0) /* bitstrings */
3415: #define rg32_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
3416:
3417: #if DEBUG
3418: #define bits_g32(bits) { \
3419: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
3420: if(dbg_rg32_s) fprintf(stderr,"%s",(bits)); \
3421: if(dbg_rg32_r) fprintf(stderr," "); \
3422: }
3423: #else
3424: #define bits_g32(bits) { \
3425: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
3426: }
3427: #endif
3428: #if DEBUG
3429: #define EOL_g32 { \
3430: if(dbg_rg32_r) fprintf(stderr,"EOL "); \
3431: bits_g32(EOLSTRING); \
3432: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3433: }
3434: #else
3435: #define EOL_g32 { \
3436: bits_g32(EOLSTRING); \
3437: }
3438: #endif
3439:
3440: BOF_to_g32(f)
3441: BITFILE *f;
3442: { char *cs;
3443: /* a NOP: no header for Group 3 (2-D) */
3444: #if DEBUG
3445: if(dbg_rg32_e) fprintf(stderr,"BOF\n");
3446: #endif
3447: };
3448:
3449: rlel_to_g32(pl,cl,wid,f)
3450: RLE_Line *pl; /* prior "reference" line: if NULL, use 1-D coding on cl */
3451: RLE_Line *cl; /* current "coding" line: if NULL, is blank (all white) */
3452: int wid; /* width of an output line in pixels */
3453: BITFILE *f;
3454: { int runl,codi;
3455: char *cs,*p01;
3456: #if DEBUG
3457: #define Wrun_g32(rn) { \
3458: runl=(rn); \
3459: if(dbg_rg32_r) fprintf(stderr,"W %5d ",runl); \
3460: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
3461: p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
3462: if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
3463: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3464: }
3465: #else
3466: #define Wrun_g32(rn) { \
3467: runl=(rn); \
3468: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
3469: p01=codewht[codi=rtoi(runl)]; bits_g32(p01); \
3470: if(codi>=64) {p01=codewht[runl%64]; bits_g32(p01);}; \
3471: }
3472: #endif
3473: #if DEBUG
3474: #define Brun_g32(rn) { \
3475: runl=(rn); \
3476: if(dbg_rg32_r) fprintf(stderr,"B %5d ",runl); \
3477: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
3478: p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
3479: if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
3480: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3481: }
3482: #else
3483: #define Brun_g32(rn) { \
3484: runl=(rn); \
3485: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g32(p01); runl-=2560;}; \
3486: p01=codeblk[codi=rtoi(runl)]; bits_g32(p01); \
3487: if(codi>=64) {p01=codeblk[runl%64]; bits_g32(p01);}; \
3488: }
3489: #endif
3490: #if DEBUG
3491: #define V0_g32 { \
3492: if(dbg_rg32_r) fprintf(stderr,"V0 "); \
3493: bits_g32(code2d[i2D_V0]); \
3494: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3495: }
3496: #else
3497: #define V0_g32 { \
3498: bits_g32(code2d[i2D_V0]); \
3499: }
3500: #endif
3501: #if DEBUG
3502: #define VR1_g32 { \
3503: if(dbg_rg32_r) fprintf(stderr,"VR1 "); \
3504: bits_g32(code2d[i2D_VR1]); \
3505: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3506: }
3507: #else
3508: #define VR1_g32 { \
3509: bits_g32(code2d[i2D_VR1]); \
3510: }
3511: #endif
3512: #if DEBUG
3513: #define VR2_g32 { \
3514: if(dbg_rg32_r) fprintf(stderr,"VR2 "); \
3515: bits_g32(code2d[i2D_VR2]); \
3516: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3517: }
3518: #else
3519: #define VR2_g32 { \
3520: bits_g32(code2d[i2D_VR2]); \
3521: }
3522: #endif
3523: #if DEBUG
3524: #define VR3_g32 { \
3525: if(dbg_rg32_r) fprintf(stderr,"VR3 "); \
3526: bits_g32(code2d[i2D_VR3]); \
3527: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3528: }
3529: #else
3530: #define VR3_g32 { \
3531: bits_g32(code2d[i2D_VR3]); \
3532: }
3533: #endif
3534: #if DEBUG
3535: #define VL1_g32 { \
3536: if(dbg_rg32_r) fprintf(stderr,"VL1 "); \
3537: bits_g32(code2d[i2D_VL1]); \
3538: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3539: }
3540: #else
3541: #define VL1_g32 { \
3542: bits_g32(code2d[i2D_VL1]); \
3543: }
3544: #endif
3545: #if DEBUG
3546: #define VL2_g32 { \
3547: if(dbg_rg32_r) fprintf(stderr,"VL2 "); \
3548: bits_g32(code2d[i2D_VL2]); \
3549: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3550: }
3551: #else
3552: #define VL2_g32 { \
3553: bits_g32(code2d[i2D_VL2]); \
3554: }
3555: #endif
3556: #if DEBUG
3557: #define VL3_g32 { \
3558: if(dbg_rg32_r) fprintf(stderr,"VL3 "); \
3559: bits_g32(code2d[i2D_VL3]); \
3560: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3561: }
3562: #else
3563: #define VL3_g32 { \
3564: bits_g32(code2d[i2D_VL3]); \
3565: }
3566: #endif
3567: #if DEBUG
3568: #define PASS_g32 { \
3569: if(dbg_rg32_r) fprintf(stderr,"PASS "); \
3570: bits_g32(code2d[i2D_PASS]); \
3571: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3572: }
3573: #else
3574: #define PASS_g32 { \
3575: bits_g32(code2d[i2D_PASS]); \
3576: }
3577: #endif
3578: #if DEBUG
3579: #define HORIZ_g32 { \
3580: if(dbg_rg32_r) fprintf(stderr,"HORIZ "); \
3581: bits_g32(code2d[i2D_HORIZ]); \
3582: if(dbg_rg32_r) fprintf(stderr,"\n"); \
3583: }
3584: #else
3585: #define HORIZ_g32 { \
3586: bits_g32(code2d[i2D_HORIZ]); \
3587: }
3588: #endif
3589: #define detect_a1a2_BW { \
3590: /* find leftmost black changing pel > a0 */ \
3591: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
3592: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
3593: /* look beyond cra, until cr->xs>a0 */ \
3594: cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
3595: if(cr<cre) a2=cr->xe+1; \
3596: else a1=a2=wid; \
3597: }
3598: #define detect_a1a2_WB { \
3599: /* find leftmost white changing pel > a0 */ \
3600: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
3601: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
3602: /* look beyond cra, until cr->xe+1>a0 */ \
3603: cr=cra; while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
3604: if(cr<cre) { \
3605: if((cr+1)<cre) a2=(cr+1)->xs; \
3606: else a2=wid; \
3607: } \
3608: else a1=a2=wid; \
3609: }
3610: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
3611: #define detect_b1b2_BW {\
3612: /* find leftmost black changing pel > a0 */ \
3613: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
3614: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
3615: /* look beyond pra */ \
3616: pr=pra; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
3617: /* move b2 to 1st changing white pel > b1 */ \
3618: if(pr<pre) b2=pr->xe+1; \
3619: else b1=b2=wid; \
3620: }
3621: #define detect_b1b2_WB {\
3622: /* find leftmost white changing pel > a0 */ \
3623: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
3624: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
3625: /* look beyond pra */ \
3626: pr=pra; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
3627: /* move b2 to 1st changing black pel > b1 */ \
3628: if(pr<pre) { \
3629: if((pr+1)<pre) b2=(pr+1)->xs; \
3630: else b2=wid; \
3631: } \
3632: else b1=b2=wid; \
3633: }
3634: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
3635:
3636: #if DEBUG
3637: if(dbg_rg32_e) err("rlel_to_g32(pl[%d],cl[%d],w%d)",
3638: (pl==NULL)? -1: pl->runs,
3639: (cl==NULL)? -1: cl->runs,
3640: wid);
3641: #endif
3642: /* fill so that EOL ends on byte boundary */
3643: padb(f,0,8,EOLLENGTH);
3644: #if DEBUG
3645: if(dbg_rg32_s) fprintf(stderr,"FILL +0?");
3646: #endif
3647: EOL_g32; /* begin with EOL (sic) */
3648: if(pl==NULL) /* use 1-D coding for *cl */ {
3649: int pi; /* input pixel index on line */
3650: RLE_Run *rp,*pp,*sp;
3651: putb(1,f);
3652: #if DEBUG
3653: if(dbg_rg32_r) fprintf(stderr,"1D_LINE 1\n");
3654: #endif
3655: if(cl!=NULL&&cl->runs>0) {
3656: pi=0; /* bit to write next */
3657: for(sp=(rp=cl->r)+cl->runs; rp<sp; rp++) {
3658: Wrun_g32(rp->xs-pi); pi=rp->xs;
3659: Brun_g32(rp->xe-pi+1); pi=rp->xe+1;
3660: };
3661: if((--rp)->xe+1<wid) Wrun_g32(wid-rp->xe-1);
3662: }
3663: else Wrun_g32(wid); /* blank scanline */
3664: }
3665: else /* use 2-D coding for *cl */ {
3666: RLE_Run *cr,*cre,*pr,*pre; /* into current/prior rle lines */
3667: int a0,a1,a2,b1,b2; /* indices {0,1,...} of pixels */
3668: DST_color a0_color; /* a0's color: same as a2 & b2, opp of a1 & b1 */
3669: RLE_Run *cra; /* rightmost in current st xe<=a0 (none: ==cl->r) */
3670: RLE_Run *pra; /* rightmost in prior st xe<=a0 (none: ==pl->r) */
3671: int a01,a12,a1b1; /* lengths of runs a0-a1 a1-a2 a1-b1 */
3672: putb(0,f);
3673: #if DEBUG
3674: if(dbg_rg32_r) fprintf(stderr,"2D_LINE 0\n");
3675: #endif
3676: /* start on an imaginary white pixel just to left of margin */
3677: a0= -1; a0_color = DST_white;
3678: pre = (pra=pl->r) + pl->runs; /* prior line's runs */
3679: /* start b1/b2 on prior line's first black pixel, etc;
3680: if none, then place off end of line */
3681: if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
3682: if(cl!=NULL&&cl->runs>0) {
3683: cre = (cra=cl->r) + cl->runs;
3684: a1=cra->xs; a2=cra->xe+1;
3685: #if rg32_strict
3686: while(a0 < wid) {
3687: #else
3688: while(a0 < wid-1) {
3689: #endif
3690: /* a0, a1, a2, b1, b2 are as in CCITT Rec T.4 */
3691: #if DEBUG
3692: if(dbg_rg32_r)
3693: fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
3694: cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
3695: #endif
3696: if(b2<a1) /* PASS mode */ {
3697: PASS_g32;
3698: a0=b2;
3699: /* a0-color, a1, & a2 are unchanged */
3700: detect_b1b2;
3701: }
3702: else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
3703: /* VERTICAL mode */
3704: switch(a1b1) {
3705: case -3: VL3_g32; break;
3706: case -2: VL2_g32; break;
3707: case -1: VL1_g32; break;
3708: case 0: V0_g32; break;
3709: case 1: VR1_g32; break;
3710: case 2: VR2_g32; break;
3711: case 3: VR3_g32; break;
3712: };
3713: a0=a1; a0_color=flip_color(a0_color);
3714: detect_a1a2;
3715: detect_b1b2;
3716: }
3717: else { /* HORIZONTAL mode */
3718: HORIZ_g32;
3719: a01=a1-a0; if(a0== -1) a01--;
3720: a12=a2-a1;
3721: if(a0_color==DST_white) {
3722: Wrun_g32(a01);
3723: Brun_g32(a12);
3724: }
3725: else { Brun_g32(a01);
3726: Wrun_g32(a12);
3727: };
3728: a0=a2;
3729: /* a0_color is unchanged */
3730: detect_a1a2;
3731: detect_b1b2;
3732: };
3733: };
3734: }
3735: else /* current line is blank */ {
3736: a1=a2=wid;
3737: #if rg32_strict
3738: while(a0 < wid) {
3739: #else
3740: while(a0 < wid-1) {
3741: #endif
3742: /* a0, a1, a2, b1, b2 are as in CCITT Rec. T.4 */
3743: #if DEBUG
3744: if(dbg_rg32_r)
3745: fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
3746: a0,a1,a2,pra-(pl->r),b1,b2);
3747: #endif
3748: if(b2<a1) /* PASS mode */ {
3749: PASS_g32;
3750: a0=b2;
3751: /* a0-color, a1, & a2 are unchanged */
3752: detect_b1b2;
3753: }
3754: else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
3755: /* VERTICAL mode */
3756: switch(a1b1) {
3757: case -3: VL3_g32; break;
3758: case -2: VL2_g32; break;
3759: case -1: VL1_g32; break;
3760: case 0: V0_g32; break;
3761: case 1: VR1_g32; break;
3762: case 2: VR2_g32; break;
3763: case 3: VR3_g32; break;
3764: };
3765: a0=a1; a0_color=flip_color(a0_color);
3766: /* a1, & a2 are unchanged */
3767: detect_b1b2;
3768: }
3769: else { /* HORIZONTAL mode */
3770: HORIZ_g32;
3771: a01=a1-a0; if(a0== -1) a01--;
3772: a12=a2-a1;
3773: if(a0_color==DST_white) {
3774: Wrun_g32(a01);
3775: Brun_g32(a12);
3776: }
3777: else { Brun_g32(a01);
3778: Wrun_g32(a12);
3779: };
3780: a0=a2;
3781: /* a0_color, a1, & a2 are unchanged */
3782: detect_b1b2;
3783: };
3784: };
3785: };
3786: };
3787: }
3788:
3789: EOF_to_g32(f)
3790: BITFILE *f;
3791: { char *cs;
3792: padb(f,0,8,EOLLENGTH); /* fill so that EOL ends on byte boundary */
3793: #if DEBUG
3794: if(dbg_rg32_s) fprintf(stderr,"FILL +0?");
3795: #endif
3796: /* write RTC */
3797: EOL_g32;
3798: EOL_g32;
3799: EOL_g32;
3800: EOL_g32;
3801: EOL_g32;
3802: EOL_g32;
3803: #if DEBUG
3804: if(dbg_rg32_e) fprintf(stderr,"EOF\n");
3805: #endif
3806: }
3807:
3808: /* Macro for use within g4_to_rlel, to read one 1-D Modified Huffman coded
3809: run-length of color C, placing the result in variable V.
3810: Exceptionally, goto trap_eol, trap_eof, or trap_code_err.
3811: */
3812: #if DEBUG
3813: #define g4_1d_run(C,V) { \
3814: run = 0; \
3815: do { cx.tr.s = (C); \
3816: do { px = cx; \
3817: switch(bitv=getb(f)) { \
3818: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
3819: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
3820: case EOF : goto trap_eof; break; \
3821: }; \
3822: } \
3823: while(cx.tr.a==DST_action_NULL); \
3824: switch(cx.tr.a) { \
3825: case DST_EOL : \
3826: if(dbg_g4r_c)fprintf(stderr,"EOL %s\n",EOLSTRING); \
3827: goto trap_eol; \
3828: break; \
3829: case DST_action_ERROR : goto trap_code_err; break; \
3830: default : \
3831: if(dbg_g4r_c)fprintf(stderr,"%s%6d %s%d\n", \
3832: ((C)==DST_white)? "W": "B", \
3833: cx.tr.a, \
3834: t->e[px.tr.s].p, \
3835: bitv); \
3836: run += cx.tr.a; \
3837: break; \
3838: }; \
3839: } \
3840: while(cx.tr.a>63); \
3841: (V) = run; \
3842: }
3843: #else
3844: #define g4_1d_run(C,V) { \
3845: run = 0; \
3846: do { cx.tr.s = (C); \
3847: do { px = cx; \
3848: switch(bitv=getb(f)) { \
3849: case 0 : cx.tr=t->e[cx.tr.s].t[0]; break; \
3850: case 1 : cx.tr=t->e[cx.tr.s].t[1]; break; \
3851: case EOF : goto trap_eof; break; \
3852: }; \
3853: } \
3854: while(cx.tr.a==DST_action_NULL); \
3855: switch(cx.tr.a) { \
3856: case DST_EOL : \
3857: goto trap_eol; \
3858: break; \
3859: case DST_action_ERROR : goto trap_code_err; break; \
3860: default : \
3861: run += cx.tr.a; \
3862: break; \
3863: }; \
3864: } \
3865: while(cx.tr.a>63); \
3866: (V) = run; \
3867: }
3868: #endif
3869:
3870: /* Translate a stream of bits in CCITT FAX Group 4 compression format, of known
3871: fixed line-length, into a sequence of RLE_Lines. Returns one (RLE_Line *)
3872: on each call (or NULL if EOF or error). The first pixel (black or white)
3873: in each g4 line is assigned run index 0.
3874: WARNING: the RLE_Line returned must NOT be modified by the caller, since
3875: it is used to decode the next line. */
3876: RLE_Line *g4_to_rlel(t,f,bof,len)
3877: DST_table *t;
3878: BITFILE *f;
3879: boolean bof; /* beginning of file */
3880: int len; /* line-length in pixels (used only on bof) */
3881: #define dbg_g4r_e (0) /* trace entry-to / exit-from function */
3882: #define dbg_g4r_r (0) /* trace each run/EOL/ERR_SYN */
3883: #define dbg_g4r_c (0) /* trace each Huffman code (or, fill+EOL)*/
3884: #define dbg_g4r_t (0) /* trace each state-transition */
3885: #define g4r_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
3886: { static RLE_Line rl0,rl1,*prl,*crl; /* prior, current run-lines */
3887: RLE_Line *swrl;
3888: int bitv; /* the last-read bit value */
3889: DST_context cx,px; /* the current/prior decoding context */
3890: RLE_Run *cr,*pr,*pre; /* into current/prior rle lines */
3891: RLE_Run *pra0; /* rightmost in prior line with xe<=a0
3892: (if none: prl->r) */
3893: int run,sync,si,rtc_eols;
3894: /* pixel indices (0,1,...): current-line a*; prior-line b*.
3895: a0 is the index of the most recently completely encoded bit */
3896: int a0,a1,a2,b1,b2;
3897: DST_color a0_color; /* a0's color: same as a2 & b2, opposite of a1 & b1 */
3898: int a01,a12; /* lengths of runs a0-a1 & a1-a2 */
3899: #define g4_first_color (DST_white) /* color of 1st run in each line */
3900: #define g4_negative (0) /* if 1, invert Black/White on output */
3901: #define swap_rl(f,b) {swrl=(f); (f)=(b); (b)=swrl;}
3902: /* detect b1 & b2: sensitive to a0, a0_color, and prior runs *pr *(pr+1) */
3903: #define g4r_find_Bb1Wb2 { \
3904: /* find 1st black changing pel>a0 */ \
3905: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
3906: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
3907: /* look beyond pra0 */ \
3908: pr=pra0; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
3909: /* move b2 to 1st changing white pel > b1 */ \
3910: if(pr<pre) b2=pr->xe+1; \
3911: else b1=b2=prl->len; \
3912: }
3913: #define g4r_find_Wb1Bb2 { \
3914: /* find 1st white changing pel>a0 */ \
3915: /* advance pra0 as far as possible s.t. pra0->xe<=a0 */ \
3916: while((pra0+1)<pre && (pra0+1)->xe<=a0) pra0++; \
3917: /* look beyond pra0 */ \
3918: pr=pra0; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
3919: /* move b2 to 1st changing black pel > b1 */ \
3920: if(pr<pre) { \
3921: if((pr+1)<pre) b2=(pr+1)->xs; \
3922: else b2=prl->len; \
3923: } \
3924: else b1=b2=prl->len; \
3925: }
3926: #define g4r_find_b1b2 { \
3927: if(a0_color==DST_white) g4r_find_Bb1Wb2 else g4r_find_Wb1Bb2; \
3928: if(b1<=a0) err("g4_to_rlel: y%d: b1 %d <= a0 %d ?",crl->y,a0,b1); \
3929: }
3930:
3931: if(bof){/* initial reference line is all white, of known length */
3932: prl= &rl0; prl->y= -1; prl->len=len; prl->runs=0;
3933: /* initial coding line has y-coordinate 0 */
3934: crl= &rl1; crl->y=0; crl->len=0; crl->runs=0;
3935: }
3936: else crl->y = prl->y + 1;
3937: #if DEBUG
3938: if(dbg_g4r_e)
3939: fprintf(stderr,
3940: "g4_to_rlel(t,f,bof%d,len%d) y%d,l%d\n",
3941: bof,len,prl->y,prl->len);
3942: #endif
3943:
3944: pre = (pra0=pr=prl->r) + prl->runs; /* prior line */
3945: crl->runs=0; cr=crl->r-1; /* current line */
3946: /* start on an imaginary white pixel just to left of margin */
3947: a0= -1; a0_color = DST_white;
3948: #if DEBUG
3949: a1=a2=b1=b2=0; /* immaterial; looks better when debugging */
3950: #endif
3951:
3952: /* start b1/b2 on prior line's first black pixel, etc;
3953: if none, then place off end of line */
3954: if(pr<pre) {b1=pr->xs; b2=pr->xe+1;} else b1=b2=prl->len;
3955: /* parse a sequence of 2D codes... */
3956: while(T/* exit only via 'goto trap_X' */) {
3957: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
3958: #if DEBUG
3959: if(dbg_g4r_r)
3960: fprintf(stderr,"a(%d,%d,%d) b(%d,%d)\n",a0,a1,a2,b1,b2);
3961: #endif
3962: cx.tr.s = DST_2d; cx.tr.a = DST_action_NULL;
3963: #if DEBUG
3964: if(dbg_g4r_t)fprintf(stderr,"(%d,%d)\n",cx.tr.s,cx.tr.a);
3965: #endif
3966: do { switch(bitv=getb(f)) {
3967: case 0 :
3968: case 1 :
3969: cx.tr=t->e[cx.tr.s].t[bitv];
3970: break;
3971: case EOF: goto trap_eof; break;
3972: };
3973: #if DEBUG
3974: if(dbg_g4r_t)fprintf(stderr,"%d->(%d,%d)\n",
3975: bitv,cx.tr.s,cx.tr.a);
3976: #endif
3977: }
3978: while(cx.tr.a==DST_action_NULL);
3979: #if DEBUG
3980: if(dbg_g4r_t)fprintf(stderr,"%s %04d %s0\n",
3981: (cx.c==DST_white)? "W": "B",
3982: cx.tr.s,
3983: t->e[cx.tr.s].p);
3984: #endif
3985: switch(cx.tr.a) {
3986: case i2D_V0:
3987: #if DEBUG
3988: if(dbg_g4r_c)
3989: fprintf(stderr,"V0 %s\n",code2d[cx.tr.a]);
3990: #endif
3991: a1=b1;
3992: /* interpret (a0,a1-1] */
3993: if(a0_color==DST_black) cr->xe=a1-1;
3994: /* move a0 to a1 */
3995: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
3996: a0_color = flip_color(a0_color);
3997: /* interpret a0 */
3998: if(a0_color==DST_black) {
3999: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4000: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4001: crl->y,crl->runs,cr->xs,cr->xe);
4002: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4003: };
4004: #if !g4r_strict
4005: if(a0==prl->len-1)
4006: { a0++; goto trap_expecting_eol; };
4007: #endif
4008: g4r_find_b1b2;
4009: break;
4010: case i2D_VR1:
4011: #if DEBUG
4012: if(dbg_g4r_c)
4013: fprintf(stderr,"VR1 %s\n",code2d[cx.tr.a]);
4014: #endif
4015: a1=b1+1;
4016: /* encode a0 to a1-1 */
4017: if(a0_color==DST_black) cr->xe=a1-1;
4018: /* move a0 to a1 */
4019: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4020: a0_color = flip_color(a0_color);
4021: /* encode a0 */
4022: if(a0_color==DST_black) {
4023: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4024: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4025: crl->y,crl->runs,cr->xs,cr->xe);
4026: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4027: };
4028: #if !g4r_strict
4029: if(a0==prl->len-1)
4030: { a0++; goto trap_expecting_eol; };
4031: #endif
4032: g4r_find_b1b2;
4033: break;
4034: case i2D_VR2:
4035: #if DEBUG
4036: if(dbg_g4r_c)
4037: fprintf(stderr,"VR2 %s\n",code2d[cx.tr.a]);
4038: #endif
4039: a1=b1+2;
4040: /* encode a0 to a1-1 */
4041: if(a0_color==DST_black) cr->xe=a1-1;
4042: /* move a0 to a1 */
4043: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4044: a0_color = flip_color(a0_color);
4045: /* encode a0 */
4046: if(a0_color==DST_black) {
4047: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4048: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4049: crl->y,crl->runs,cr->xs,cr->xe);
4050: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4051: };
4052: #if !g4r_strict
4053: if(a0==prl->len-1)
4054: { a0++; goto trap_expecting_eol; };
4055: #endif
4056: g4r_find_b1b2;
4057: break;
4058: case i2D_VR3:
4059: #if DEBUG
4060: if(dbg_g4r_c)
4061: fprintf(stderr,"VR3 %s\n",code2d[cx.tr.a]);
4062: #endif
4063: a1=b1+3;
4064: /* encode a0 to a1-1 */
4065: if(a0_color==DST_black) cr->xe=a1-1;
4066: /* move a0 to a1 */
4067: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4068: a0_color = flip_color(a0_color);
4069: /* encode a0 */
4070: if(a0_color==DST_black) {
4071: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4072: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4073: crl->y,crl->runs,cr->xs,cr->xe);
4074: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4075: };
4076: #if !g4r_strict
4077: if(a0==prl->len-1)
4078: { a0++; goto trap_expecting_eol; };
4079: #endif
4080: g4r_find_b1b2;
4081: break;
4082: case i2D_VL1:
4083: #if DEBUG
4084: if(dbg_g4r_c)
4085: fprintf(stderr,"VL1 %s\n",code2d[cx.tr.a]);
4086: #endif
4087: if((a1=b1-1)<=a0)
4088: err("g4_to_rlel: y%d: VL1 a1 %d <= a0 %d ?",
4089: crl->y,a1,a0);
4090: /* encode a0 to a1-1 */
4091: if(a0_color==DST_black) cr->xe=a1-1;
4092: /* move a0 to a1 */
4093: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4094: a0_color = flip_color(a0_color);
4095: /* encode a0 */
4096: if(a0_color==DST_black) {
4097: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4098: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4099: crl->y,crl->runs,cr->xs,cr->xe);
4100: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4101: };
4102: #if !g4r_strict
4103: if(a0==prl->len-1)
4104: { a0++; goto trap_expecting_eol; };
4105: #endif
4106: g4r_find_b1b2;
4107: break;
4108: case i2D_VL2:
4109: #if DEBUG
4110: if(dbg_g4r_c)
4111: fprintf(stderr,"VL2 %s\n",code2d[cx.tr.a]);
4112: #endif
4113: if((a1=b1-2)<=a0)
4114: err("g4_to_rlel: y%d: VL2 a1 %d <= a0 %d ?",
4115: crl->y,a1,a0);
4116: /* encode a0 to a1-1 */
4117: if(a0_color==DST_black) cr->xe=a1-1;
4118: /* move a0 to a1 */
4119: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4120: a0_color = flip_color(a0_color);
4121: /* encode a0 */
4122: if(a0_color==DST_black) {
4123: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4124: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4125: crl->y,crl->runs,cr->xs,cr->xe);
4126: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4127: };
4128: #if !g4r_strict
4129: if(a0==prl->len-1)
4130: { a0++; goto trap_expecting_eol; };
4131: #endif
4132: g4r_find_b1b2;
4133: break;
4134: case i2D_VL3:
4135: #if DEBUG
4136: if(dbg_g4r_c)
4137: fprintf(stderr,"VL3 %s\n",code2d[cx.tr.a]);
4138: #endif
4139: if((a1=b1-3)<=a0)
4140: err("g4_to_rlel: y%d: VL3 a1 %d <= a0 %d ?",
4141: crl->y,a1,a0);
4142: /* encode a0 to a1-1 */
4143: if(a0_color==DST_black) cr->xe=a1-1;
4144: /* move a0 to a1 */
4145: a0=a1; if(a0>=prl->len) goto trap_expecting_eol;
4146: a0_color = flip_color(a0_color);
4147: /* encode a0 */
4148: if(a0_color==DST_black) {
4149: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4150: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4151: crl->y,crl->runs,cr->xs,cr->xe);
4152: crl->runs++; (++cr)->xs = a0; cr->xe = a0;
4153: };
4154: #if !g4r_strict
4155: if(a0==prl->len-1)
4156: { a0++; goto trap_expecting_eol; };
4157: #endif
4158: g4r_find_b1b2;
4159: break;
4160: case i2D_PASS:
4161: #if DEBUG
4162: if(dbg_g4r_c)
4163: fprintf(stderr,"PASS %s\n",code2d[cx.tr.a]);
4164: #endif
4165: /* move a0 to b2; no change of color */
4166: a0=b2; if(a0>=prl->len) goto trap_expecting_eol;
4167: if(a0_color==DST_black) cr->xe = a0;
4168: #if !g4r_strict
4169: if(a0==prl->len-1)
4170: { a0++; goto trap_expecting_eol; };
4171: #endif
4172: g4r_find_b1b2;
4173: break;
4174: case i2D_HORIZ:
4175: #if DEBUG
4176: if(dbg_g4r_c)
4177: fprintf(stderr,"HORIZ %s\n",code2d[cx.tr.a]);
4178: #endif
4179: if(a0_color==DST_white) {
4180: if(a0<0) a0=0; /* first run in line starts at 0 */
4181: g4_1d_run(DST_white,a01); a1 = a0 + a01;
4182: g4_1d_run(DST_black,a12); a2 = a1 + a12;
4183: if(a12>0) /* Black run of >0 length */ {
4184: if(cr->xs>cr->xe&&cr->xs<prl->len&&cr->xe>0)
4185: err("g4_to_rlel: y%d: r%d[%d,%d] not monotone ?",
4186: crl->y,crl->runs,cr->xs,cr->xe);
4187: crl->runs++; (++cr)->xs = a1; cr->xe = a2-1;
4188: };
4189: a0 = a2; /* still white */
4190: if(a0>=prl->len) goto trap_expecting_eol;
4191: /* encode a0 */
4192: #if !g4r_strict
4193: if(a0==prl->len-1)
4194: { a0++; goto trap_expecting_eol; };
4195: #endif
4196: g4r_find_Bb1Wb2;
4197: }
4198: else { g4_1d_run(DST_black,a01); a1 = a0 + a01;
4199: g4_1d_run(DST_white,a12); a2 = a1 + a12;
4200: if(a01>0) /* Black run of >0 length */ {
4201: cr->xe = a1 - 1;
4202: }
4203: else { /* 0-length: very peculiar: ignore */
4204: fprintf(stderr,
4205: "g4_to_rlel: HORIZ B%d! W%d - ignore\n",
4206: a01,a12);
4207: cr--; crl->runs--;
4208: };
4209: a0 = a2; /* still black */
4210: if(a0>=prl->len) goto trap_expecting_eol;
4211: /* encode a0 */
4212: crl->runs++; (++cr)->xs = a0;
4213: #if !g4r_strict
4214: if(a0==prl->len-1) {
4215: cr->xe = a0;
4216: a0++;
4217: goto trap_expecting_eol;
4218: };
4219: #endif
4220: g4r_find_Wb1Bb2;
4221: };
4222: break;
4223: case i2D_EOL:
4224: #if DEBUG
4225: if(dbg_g4r_c)
4226: fprintf(stderr,"EOL %s\n",code2d[cx.tr.a]);
4227: #endif
4228: goto trap_eol;
4229: break;
4230: case DST_action_ERROR: goto trap_code_err; break;
4231: };
4232: };
4233:
4234: /* come here via goto's: all these traps return() */
4235:
4236: trap_expecting_eol: /* come here having detected (computed) end-of-line */
4237: /* learn/check/correct line-length */
4238: crl->len = (a0>0)? a0 : 0;
4239: if(crl->len!=prl->len) {
4240: err("g4_to_rlel: y%d: LINELEN changes c%d != p%d ? (force to %d)",
4241: crl->y,crl->len,prl->len,prl->len);
4242: crl->len = prl->len;
4243: };
4244: swap_rl(crl,prl);
4245: #if DEBUG
4246: if(dbg_g4r_e)
4247: fprintf(stderr,
4248: "exit g4_to_rlel: expg_eol y%d,l%d\n",
4249: prl->y,prl->len);
4250: #endif
4251: return(prl);
4252:
4253: trap_eol: /* come here having seen an EOL code (rare in Group 4) */
4254: /* It must be the first of two EOL codes making up the EOB signal */
4255: /* look for 2nd EOL */
4256: sync=0; while((bitv=getb(f))==0) sync++;
4257: switch(bitv) {
4258: case 1:
4259: if(sync==11) {
4260: #if DEBUG
4261: if(dbg_g4r_c) {
4262: fprintf(stderr,"EOB_EOL %s\n",EOLSTRING);
4263: fprintf(stderr,"EOB\n");
4264: };
4265: #endif
4266: }
4267: else {
4268: #if DEBUG
4269: if(dbg_g4r_c){
4270: fprintf(stderr,"NOT EOB ");
4271: for(si=0;si<sync;si++)
4272: fprintf(stderr,"0");
4273: fprintf(stderr,"1?\n");
4274: fprintf(stderr,"ABORT\n");
4275: };
4276: #endif
4277: };
4278: break;
4279: case EOF: goto trap_eof; break;
4280: };
4281: #if DEBUG
4282: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eol\n");
4283: #endif
4284: return(NULL);
4285:
4286: trap_code_err:
4287: /* unexpected coding sequence:
4288: 'px' holds last decoding context & 'bitv' latest bit value;
4289: will attempt to resynchronize on next EOL */
4290: #if DEBUG
4291: if(dbg_g4r_c)fprintf(stderr,"CODERR %s%d? (px.tr.s=%d)\n",
4292: t->e[px.tr.s].p,bitv,px.tr.s);
4293: #endif
4294: err("g4_to_rlel: code error");
4295: #if DEBUG
4296: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: code_err\n");
4297: #endif
4298: return(NULL);
4299:
4300: trap_eof:
4301: #if DEBUG
4302: if(dbg_g4r_c) fprintf(stderr,"<EOF>\n");
4303: if(dbg_g4r_e) fprintf(stderr,"exit g4_to_rlel: eof\n");
4304: #endif
4305: return(NULL);
4306:
4307: }
4308:
4309: /* Translate a sequence of RLE_Line's (describing a binary image)
4310: into a file (a stream of bits) in CCITT FAX Group 4 compression format.
4311: BOF_to_g4() must be called first; then call rlel_to_g4() for each line
4312: (including blank lines); finally, EOF_to_g4() must be called. The EOFB
4313: is padded (suffixed) with 0's to a byte boundary if necessary; no other
4314: filling or padding is performed.
4315: */
4316: /* debugging flags: trace to stderr */
4317: #define dbg_rg4_e (0) /* entry */
4318: #define dbg_rg4_r (0) /* runs */
4319: #define dbg_rg4_c (0) /* codes (bitstrings) */
4320: #define rg4_strict (1) /* 1 is CORRECT: explicitly code the last black pel */
4321:
4322: #if DEBUG
4323: #define bits_g4(bits) { \
4324: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
4325: if(dbg_rg4_c) fprintf(stderr,"%s",(bits)); \
4326: if(dbg_rg4_r) fprintf(stderr," "); \
4327: }
4328: #else
4329: #define bits_g4(bits) { \
4330: cs=(bits); while(*cs!='\0') {putb(*cs-'0',f); cs++;}; \
4331: }
4332: #endif
4333: #if DEBUG
4334: #define EOFB_g4 { \
4335: if(dbg_rg4_r) fprintf(stderr,"EOFB "); \
4336: bits_g4(EOFB); \
4337: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4338: }
4339: #else
4340: #define EOFB_g4 { \
4341: bits_g4(EOFB); \
4342: }
4343: #endif
4344:
4345: BOF_to_g4(f)
4346: BITFILE *f;
4347: { char *cs;
4348: /* a NOP: no header for Group 4 */
4349: #if DEBUG
4350: if(dbg_rg4_e) fprintf(stderr,"BOF\n");
4351: #endif
4352: };
4353:
4354: rlel_to_g4(pl,cl,wid,f)
4355: RLE_Line *pl; /* prior "reference" line */
4356: RLE_Line *cl; /* current "coding" line: if NULL, is blank (all white) */
4357: int wid; /* width of an output line in pixels */
4358: BITFILE *f;
4359: { int runl,codi;
4360: char *cs,*p01;
4361: #if DEBUG
4362: #define Wrun_g4(rn) { \
4363: runl=(rn); \
4364: if(dbg_rg4_r) fprintf(stderr,"W %5d ",runl); \
4365: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
4366: p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
4367: if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
4368: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4369: }
4370: #else
4371: #define Wrun_g4(rn) { \
4372: runl=(rn); \
4373: while(runl>2560) {p01=codewht[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
4374: p01=codewht[codi=rtoi(runl)]; bits_g4(p01); \
4375: if(codi>=64) {p01=codewht[runl%64]; bits_g4(p01);}; \
4376: }
4377: #endif
4378: #if DEBUG
4379: #define Brun_g4(rn) { \
4380: runl=(rn); \
4381: if(dbg_rg4_r) fprintf(stderr,"B %5d ",runl); \
4382: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
4383: p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
4384: if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
4385: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4386: }
4387: #else
4388: #define Brun_g4(rn) { \
4389: runl=(rn); \
4390: while(runl>2560) {p01=codeblk[rtoi(2560)]; bits_g4(p01); runl-=2560;}; \
4391: p01=codeblk[codi=rtoi(runl)]; bits_g4(p01); \
4392: if(codi>=64) {p01=codeblk[runl%64]; bits_g4(p01);}; \
4393: }
4394: #endif
4395: #if DEBUG
4396: #define V0_g4 { \
4397: if(dbg_rg4_r) fprintf(stderr,"V0 "); \
4398: bits_g4(code2d[i2D_V0]); \
4399: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4400: }
4401: #else
4402: #define V0_g4 { \
4403: bits_g4(code2d[i2D_V0]); \
4404: }
4405: #endif
4406: #if DEBUG
4407: #define VR1_g4 { \
4408: if(dbg_rg4_r) fprintf(stderr,"VR1 "); \
4409: bits_g4(code2d[i2D_VR1]); \
4410: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4411: }
4412: #else
4413: #define VR1_g4 { \
4414: bits_g4(code2d[i2D_VR1]); \
4415: }
4416: #endif
4417: #if DEBUG
4418: #define VR2_g4 { \
4419: if(dbg_rg4_r) fprintf(stderr,"VR2 "); \
4420: bits_g4(code2d[i2D_VR2]); \
4421: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4422: }
4423: #else
4424: #define VR2_g4 { \
4425: bits_g4(code2d[i2D_VR2]); \
4426: }
4427: #endif
4428: #if DEBUG
4429: #define VR3_g4 { \
4430: if(dbg_rg4_r) fprintf(stderr,"VR3 "); \
4431: bits_g4(code2d[i2D_VR3]); \
4432: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4433: }
4434: #else
4435: #define VR3_g4 { \
4436: bits_g4(code2d[i2D_VR3]); \
4437: }
4438: #endif
4439: #if DEBUG
4440: #define VL1_g4 { \
4441: if(dbg_rg4_r) fprintf(stderr,"VL1 "); \
4442: bits_g4(code2d[i2D_VL1]); \
4443: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4444: }
4445: #else
4446: #define VL1_g4 { \
4447: bits_g4(code2d[i2D_VL1]); \
4448: }
4449: #endif
4450: #if DEBUG
4451: #define VL2_g4 { \
4452: if(dbg_rg4_r) fprintf(stderr,"VL2 "); \
4453: bits_g4(code2d[i2D_VL2]); \
4454: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4455: }
4456: #else
4457: #define VL2_g4 { \
4458: bits_g4(code2d[i2D_VL2]); \
4459: }
4460: #endif
4461: #if DEBUG
4462: #define VL3_g4 { \
4463: if(dbg_rg4_r) fprintf(stderr,"VL3 "); \
4464: bits_g4(code2d[i2D_VL3]); \
4465: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4466: }
4467: #else
4468: #define VL3_g4 { \
4469: bits_g4(code2d[i2D_VL3]); \
4470: }
4471: #endif
4472: #if DEBUG
4473: #define PASS_g4 { \
4474: if(dbg_rg4_r) fprintf(stderr,"PASS "); \
4475: bits_g4(code2d[i2D_PASS]); \
4476: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4477: }
4478: #else
4479: #define PASS_g4 { \
4480: bits_g4(code2d[i2D_PASS]); \
4481: }
4482: #endif
4483: #if DEBUG
4484: #define HORIZ_g4 { \
4485: if(dbg_rg4_r) fprintf(stderr,"HORIZ "); \
4486: bits_g4(code2d[i2D_HORIZ]); \
4487: if(dbg_rg4_r) fprintf(stderr,"\n"); \
4488: }
4489: #else
4490: #define HORIZ_g4 { \
4491: bits_g4(code2d[i2D_HORIZ]); \
4492: }
4493: #endif
4494: #define detect_a1a2_BW { \
4495: /* find leftmost black changing pel > a0 */ \
4496: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
4497: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
4498: /* look beyond cra, until cr->xs>a0 */ \
4499: cr=cra; while(cr<cre && (a1=cr->xs)<=a0) cr++; \
4500: if(cr<cre) a2=cr->xe+1; \
4501: else a1=a2=wid; \
4502: }
4503: #define detect_a1a2_WB { \
4504: /* find leftmost white changing pel > a0 */ \
4505: /* advance cra as far as possible s.t. cra->xe<=a0 */ \
4506: while((cra+1)<cre && (cra+1)->xe<=a0) cra++; \
4507: /* look beyond cra, until cr->xe+1>a0 */ \
4508: cr=cra; while(cr<cre && (a1=cr->xe+1)<=a0) cr++; \
4509: if(cr<cre) { \
4510: if((cr+1)<cre) a2=(cr+1)->xs; \
4511: else a2=wid; \
4512: } \
4513: else a1=a2=wid; \
4514: }
4515: #define detect_a1a2 {if(a0_color==DST_white) detect_a1a2_BW else detect_a1a2_WB;}
4516: #define detect_b1b2_BW {\
4517: /* find leftmost black changing pel > a0 */ \
4518: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
4519: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
4520: /* look beyond pra */ \
4521: pr=pra; while(pr<pre && (b1=pr->xs)<=a0) pr++; \
4522: /* move b2 to 1st changing white pel > b1 */ \
4523: if(pr<pre) b2=pr->xe+1; \
4524: else b1=b2=wid; \
4525: }
4526: #define detect_b1b2_WB {\
4527: /* find leftmost white changing pel > a0 */ \
4528: /* advance pra as far as possible s.t. pra->xe<=a0 */ \
4529: while((pra+1)<pre && (pra+1)->xe<=a0) pra++; \
4530: /* look beyond pra */ \
4531: pr=pra; while(pr<pre && (b1=pr->xe+1)<=a0) pr++; \
4532: /* move b2 to 1st changing black pel > b1 */ \
4533: if(pr<pre) { \
4534: if((pr+1)<pre) b2=(pr+1)->xs; \
4535: else b2=wid; \
4536: } \
4537: else b1=b2=wid; \
4538: }
4539: #define detect_b1b2 {if(a0_color==DST_white) detect_b1b2_BW else detect_b1b2_WB;}
4540:
4541: RLE_Run *cr,*cre,*pr,*pre; /* into current/prior rle lines */
4542: int a0,a1,a2,b1,b2; /* indices {0,1,...} of pixels */
4543: DST_color a0_color; /* a0's color: same as a2 & b2, opp of a1 & b1 */
4544: RLE_Run *cra; /* rightmost in current st xe<=a0 (none: ==cl->r) */
4545: RLE_Run *pra; /* rightmost in prior st xe<=a0 (none: ==pl->r) */
4546: int a01,a12,a1b1; /* lengths of runs a0-a1 a1-a2 a1-b1 */
4547: #if DEBUG
4548: if(dbg_rg4_e) err("rlel_to_g4(pl[%d],cl[%d],w%d)",
4549: (pl==NULL)? -1: pl->runs,
4550: (cl==NULL)? -1: cl->runs,
4551: wid);
4552: #endif
4553: /* start on an imaginary white pixel just to left of margin */
4554: a0= -1; a0_color = DST_white;
4555: pre = (pra=pl->r) + pl->runs; /* prior line's runs */
4556: /* start b1/b2 on prior line's first black pixel, etc;
4557: if none, then place off end of line */
4558: if(pra<pre) {b1=pra->xs; b2=pra->xe+1;} else b1=b2=wid;
4559: if(cl!=NULL&&cl->runs>0) {
4560: cre = (cra=cl->r) + cl->runs;
4561: a1=cra->xs; a2=cra->xe+1;
4562: #if rg4_strict
4563: while( a0 < wid ) {
4564: #else
4565: while( a0 < wid-1 ) {
4566: #endif
4567: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
4568: #if DEBUG
4569: if(dbg_rg4_r)
4570: fprintf(stderr,"f%d(%d,%d,%d) b%d(%d,%d)\n",
4571: cra-(cl->r),a0,a1,a2,pra-(pl->r),b1,b2);
4572: #endif
4573: if(b2<a1) /* PASS mode */ {
4574: PASS_g4;
4575: a0=b2;
4576: /* a0-color, a1, & a2 are unchanged */
4577: detect_b1b2;
4578: }
4579: else if((a1b1=(a1-b1))<=3 && a1b1>= -3) {
4580: /* VERTICAL mode */
4581: switch(a1b1) {
4582: case -3: VL3_g4; break;
4583: case -2: VL2_g4; break;
4584: case -1: VL1_g4; break;
4585: case 0: V0_g4; break;
4586: case 1: VR1_g4; break;
4587: case 2: VR2_g4; break;
4588: case 3: VR3_g4; break;
4589: };
4590: a0=a1; a0_color=flip_color(a0_color);
4591: detect_a1a2;
4592: detect_b1b2;
4593: }
4594: else { /* HORIZONTAL mode */
4595: HORIZ_g4;
4596: a01=a1-a0; if(a0== -1) a01--;
4597: a12=a2-a1;
4598: if(a0_color==DST_white) {
4599: Wrun_g4(a01);
4600: Brun_g4(a12);
4601: }
4602: else { Brun_g4(a01);
4603: Wrun_g4(a12);
4604: };
4605: a0=a2;
4606: /* a0_color is unchanged */
4607: detect_a1a2;
4608: detect_b1b2;
4609: };
4610: };
4611: }
4612: else /* current line is blank */ {
4613: a1=a2=wid;
4614: #if rg4_strict
4615: while( a0 < wid ) {
4616: #else
4617: while( a0 < wid-1 ) {
4618: #endif
4619: /* a0, a1, a2, b1, b2 are as defined in CCITT Rec. T.6 */
4620: #if DEBUG
4621: if(dbg_rg4_r)
4622: fprintf(stderr,"f(%d,%d,%d) b%d(%d,%d)\n",
4623: a0,a1,a2,pra-(pl->r),b1,b2);
4624: #endif
4625: if(b2<a1) /* PASS mode */ {
4626: PASS_g4;
4627: a0=b2;
4628: /* a0-color, a1, & a2 are unchanged */
4629: detect_b1b2;
4630: }
4631: else if((a1b1=a1-b1)<=3 && a1b1>= -3) {
4632: /* VERTICAL mode */
4633: switch(a1b1) {
4634: case -3: VL3_g4; break;
4635: case -2: VL2_g4; break;
4636: case -1: VL1_g4; break;
4637: case 0: V0_g4; break;
4638: case 1: VR1_g4; break;
4639: case 2: VR2_g4; break;
4640: case 3: VR3_g4; break;
4641: };
4642: a0=a1; a0_color=flip_color(a0_color);
4643: /* a1, & a2 are unchanged */
4644: detect_b1b2;
4645: }
4646: else { /* HORIZONTAL mode */
4647: HORIZ_g4;
4648: a01=a1-a0; if(a0== -1) a01--;
4649: a12=a2-a1;
4650: if(a0_color==DST_white) {
4651: Wrun_g4(a01);
4652: Brun_g4(a12);
4653: }
4654: else { Brun_g4(a01);
4655: Wrun_g4(a12);
4656: };
4657: a0=a2;
4658: /* a0_color, a1, & a2 are unchanged */
4659: detect_b1b2;
4660: };
4661: };
4662: };
4663: }
4664:
4665: EOF_to_g4(f)
4666: BITFILE *f;
4667: { char *cs;
4668: /* write EOFB */
4669: EOFB_g4;
4670: #if DEBUG
4671: if(dbg_rg4_e) fprintf(stderr,"EOF\n");
4672: #endif
4673: }
4674:
4675: 0707070035351137051006640007620000050000010261160476773366600001000000024315CCITT.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
4676: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
4677: /* The copyright notice does not imply actual or intended publication. */
4678: /* AUTHORS: */
4679: /* H. S. Baird - ATT-BL MH - first versions */
4680: /* CCITT Group 3 FAX compression codes */
4681: #define EOLSTRING "000000000001"
4682: #define EOLLENGTH 12 /* length of EOLSTRING */
4683: #define MAXCODELEN 24
4684:
4685: #define DST_EOL -3
4686:
4687: /* translate a runlength value <=2560 to an index into the Huffman code table;
4688: if the index is >=64, then must repeat for (r%64) */
4689: #define rtoi(r) (((r)<64)? (r): 64+((r)/64))
4690: /* translate an index into the Huffman code table to a runlength value */
4691: #define itor(i) (((i)<64)? (i): (((i)>64)? (((i)-64)*64): DST_EOL))
4692:
4693: /* Black run code table */
4694: static char *codeblk[] = {
4695: /* code run-length value */
4696: "0000110111", /* 0, */
4697: "010", /* 1, */
4698: "11", /* 2, */
4699: "10", /* 3, */
4700: "011", /* 4, */
4701: "0011", /* 5, */
4702: "0010", /* 6, */
4703: "00011", /* 7, */
4704: "000101", /* 8, */
4705: "000100", /* 9, */
4706: "0000100", /* 10, */
4707: "0000101", /* 11, */
4708: "0000111", /* 12, */
4709: "00000100", /* 13, */
4710: "00000111", /* 14, */
4711: "000011000", /* 15, */
4712: "0000010111", /* 16, */
4713: "0000011000", /* 17, */
4714: "0000001000", /* 18, */
4715: "00001100111", /* 19, */
4716: "00001101000", /* 20, */
4717: "00001101100", /* 21, */
4718: "00000110111", /* 22, */
4719: "00000101000", /* 23, */
4720: "00000010111", /* 24, */
4721: "00000011000", /* 25, */
4722: "000011001010", /* 26, */
4723: "000011001011", /* 27, */
4724: "000011001100", /* 28, */
4725: "000011001101", /* 29, */
4726: "000001101000", /* 30, */
4727: "000001101001", /* 31, */
4728: "000001101010", /* 32, */
4729: "000001101011", /* 33, */
4730: "000011010010", /* 34, */
4731: "000011010011", /* 35, */
4732: "000011010100", /* 36, */
4733: "000011010101", /* 37, */
4734: "000011010110", /* 38, */
4735: "000011010111", /* 39, */
4736: "000001101100", /* 40, */
4737: "000001101101", /* 41, */
4738: "000011011010", /* 42, */
4739: "000011011011", /* 43, */
4740: "000001010100", /* 44, */
4741: "000001010101", /* 45, */
4742: "000001010110", /* 46, */
4743: "000001010111", /* 47, */
4744: "000001100100", /* 48, */
4745: "000001100101", /* 49, */
4746: "000001010010", /* 50, */
4747: "000001010011", /* 51, */
4748: "000000100100", /* 52, */
4749: "000000110111", /* 53, */
4750: "000000111000", /* 54, */
4751: "000000100111", /* 55, */
4752: "000000101000", /* 56, */
4753: "000001011000", /* 57, */
4754: "000001011001", /* 58, */
4755: "000000101011", /* 59, */
4756: "000000101100", /* 60, */
4757: "000001011010", /* 61, */
4758: "000001100110", /* 62, */
4759: "000001100111", /* 63 */
4760: EOLSTRING, /* EOL */
4761: "0000001111", /* 64, */
4762: "000011001000", /* 128, */
4763: "000011001001", /* 192, */
4764: "000001011011", /* 256, */
4765: "000000110011", /* 320, */
4766: "000000110100", /* 384, */
4767: "000000110101", /* 448, */
4768: "0000001101100", /* 512, */
4769: "0000001101101", /* 576, */
4770: "0000001001010", /* 640, */
4771: "0000001001011", /* 704, */
4772: "0000001001100", /* 768, */
4773: "0000001001101", /* 832, */
4774: "0000001110010", /* 896, */
4775: "0000001110011", /* 960, */
4776: "0000001110100", /* 1024, */
4777: "0000001110101", /* 1088, */
4778: "0000001110110", /* 1152, */
4779: "0000001110111", /* 1216, */
4780: "0000001010010", /* 1280, */
4781: "0000001010011", /* 1344, */
4782: "0000001010100", /* 1408, */
4783: "0000001010101", /* 1472, */
4784: "0000001011010", /* 1536, */
4785: "0000001011011", /* 1600, */
4786: "0000001100100", /* 1664, */
4787: "0000001100101", /* 1728 */
4788: /* extended length: */
4789: "00000001000", /* 1792, */
4790: "00000001100", /* 1856, */
4791: "00000001101", /* 1920, */
4792: "000000010010", /* 1984, */
4793: "000000010011", /* 2048, */
4794: "000000010100", /* 2112, */
4795: "000000010101", /* 2176, */
4796: "000000010110", /* 2240, */
4797: "000000010111", /* 2304, */
4798: "000000011100", /* 2368, */
4799: "000000011101", /* 2432, */
4800: "000000011110", /* 2496, */
4801: "000000011111", /* 2560 */
4802: NULL /* are there codes beyond 2560? */
4803: };
4804: /* No. bits in the codes in the above table */
4805: static short bitcblk[] = {
4806: 10,3,2,2,3,4,4,5,6,6, /* 0 - 9 */
4807: 7,7,7,8,8,9,10,10,10,11, /* 10 - 19 */
4808: 11,11,11,11,11,11,12,12,12,12, /* 20 - 29 */
4809: 12,12,12,12,12,12,12,12,12,12, /* 30 - 39 */
4810: 12,12,12,12,12,12,12,12,12,12, /* 40 - 49 */
4811: 12,12,12,12,12,12,12,12,12,12, /* 50 - 59 */
4812: 12,12,12,12, /* 60 - 63 */
4813: 12, /* EOL */
4814: 10, /* 64 */
4815: 12,12,12,12,12,12, /* 128 - 448 */
4816: 13,13,13,13,13,13,13,13,13, /* 512 - */
4817: 13,13,13,13,13,13,13,13,13,
4818: 13,13, /* - 1728 */
4819: 11,11,11, /* 1792 - 1920 */
4820: 12,12,12,12,12,12,12,12,12,12, /* 1984 - 2560 */
4821: /* for codes over 2560 */
4822: 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
4823: -1
4824: };
4825:
4826: /* White run code table */
4827: static char *codewht[] = {
4828: /* code run-length value */
4829: "00110101", /* 0, */
4830: "000111", /* 1, */
4831: "0111", /* 2, */
4832: "1000", /* 3, */
4833: "1011", /* 4, */
4834: "1100", /* 5, */
4835: "1110", /* 6, */
4836: "1111", /* 7, */
4837: "10011", /* 8, */
4838: "10100", /* 9, */
4839: "00111", /* 10, */
4840: "01000", /* 11, */
4841: "001000", /* 12, */
4842: "000011", /* 13, */
4843: "110100", /* 14, */
4844: "110101", /* 15, */
4845: "101010", /* 16, */
4846: "101011", /* 17, */
4847: "0100111", /* 18, */
4848: "0001100", /* 19, */
4849: "0001000", /* 20, */
4850: "0010111", /* 21, */
4851: "0000011", /* 22, */
4852: "0000100", /* 23, */
4853: "0101000", /* 24, */
4854: "0101011", /* 25, */
4855: "0010011", /* 26, */
4856: "0100100", /* 27, */
4857: "0011000", /* 28, */
4858: "00000010", /* 29, */
4859: "00000011", /* 30, */
4860: "00011010", /* 31, */
4861: "00011011", /* 32, */
4862: "00010010", /* 33, */
4863: "00010011", /* 34, */
4864: "00010100", /* 35, */
4865: "00010101", /* 36, */
4866: "00010110", /* 37, */
4867: "00010111", /* 38, */
4868: "00101000", /* 39, */
4869: "00101001", /* 40, */
4870: "00101010", /* 41, */
4871: "00101011", /* 42, */
4872: "00101100", /* 43, */
4873: "00101101", /* 44, */
4874: "00000100", /* 45, */
4875: "00000101", /* 46, */
4876: "00001010", /* 47, */
4877: "00001011", /* 48, */
4878: "01010010", /* 49, */
4879: "01010011", /* 50, */
4880: "01010100", /* 51, */
4881: "01010101", /* 52, */
4882: "00100100", /* 53, */
4883: "00100101", /* 54, */
4884: "01011000", /* 55, */
4885: "01011001", /* 56, */
4886: "01011010", /* 57, */
4887: "01011011", /* 58, */
4888: "01001010", /* 59, */
4889: "01001011", /* 60, */
4890: "00110010", /* 61, */
4891: "00110011", /* 62, */
4892: "00110100", /* 63 */
4893: EOLSTRING, /* EOL */
4894: "11011", /* 64, */
4895: "10010", /* 128, */
4896: "010111", /* 192, */
4897: "0110111", /* 256, */
4898: "00110110", /* 320, */
4899: "00110111", /* 384, */
4900: "01100100", /* 448, */
4901: "01100101", /* 512, */
4902: "01101000", /* 576, */
4903: "01100111", /* 640, */
4904: "011001100", /* 704, */
4905: "011001101", /* 768, */
4906: "011010010", /* 832, */
4907: "011010011", /* 896, */
4908: "011010100", /* 960, */
4909: "011010101", /* 1024, */
4910: "011010110", /* 1088, */
4911: "011010111", /* 1152, */
4912: "011011000", /* 1216, */
4913: "011011001", /* 1280, */
4914: "011011010", /* 1344, */
4915: "011011011", /* 1408, */
4916: "010011000", /* 1472, */
4917: "010011001", /* 1536, */
4918: "010011010", /* 1600, */
4919: "011000", /* 1664, */
4920: "010011011", /* 1728 */
4921: /* extended length: */
4922: "00000001000", /* 1792, */
4923: "00000001100", /* 1856, */
4924: "00000001101", /* 1920, */
4925: "000000010010", /* 1984, */
4926: "000000010011", /* 2048, */
4927: "000000010100", /* 2112, */
4928: "000000010101", /* 2176, */
4929: "000000010110", /* 2240, */
4930: "000000010111", /* 2304, */
4931: "000000011100", /* 2368, */
4932: "000000011101", /* 2432, */
4933: "000000011110", /* 2496, */
4934: "000000011111", /* 2560 */
4935: NULL /* are there codes beyond 2560? */
4936: };
4937: /* no. bits in the codes in the above table */
4938: static short bitcwht[] = {
4939: 8,6,4,4,4,4,4,4,5,5, /* 0 - 9 */
4940: 5,5,6,6,6,6,6,6,7,7, /* 10 - 19 */
4941: 7,7,7,7,7,7,7,7,7,8, /* 20 - 29 */
4942: 8,8,8,8,8,8,8,8,8,8, /* 30 - 39 */
4943: 8,8,8,8,8,8,8,8,8,8, /* 40 - 49 */
4944: 8,8,8,8,8,8,8,8,8,8, /* 50 - 59 */
4945: 8,8,8,8, /* 60 - 63 */
4946: 12, /* EOL */
4947: 5,5, /* 64,128 */
4948: 6, /* 192 */
4949: 7, /* 256 */
4950: 8,8,8,8,8,8, /* 320 - 640 */
4951: 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, /* 704 - 1600 */
4952: 6, /* 1664 */
4953: 9, /* 1728 */
4954: 11,11,11, /* 1792,1856,1920 */
4955: 12,12,12,12,12,12,12,12,12,12, /* 1984 - 2560 */
4956: /* for codes over 2560 */
4957: 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
4958: -1
4959: };
4960:
4961: /* 2-D codes (indices into code2d[] table) */
4962: #define i2D_V0 0
4963: #define i2D_VR1 1
4964: #define i2D_VR2 2
4965: #define i2D_VR3 3
4966: #define i2D_VL1 4
4967: #define i2D_VL2 5
4968: #define i2D_VL3 6
4969: #define i2D_PASS 7
4970: #define i2D_HORIZ 8
4971: #define i2D_EOL 9
4972:
4973: static char *code2d[] = {
4974: "1", /* V0 */
4975: "011", /* VR1 */
4976: "000011", /* VR2 */
4977: "0000011", /* VR3 */
4978: "010", /* VL1 */
4979: "000010", /* VL2 */
4980: "0000010", /* VL3 */
4981: "0001", /* PASS */
4982: "001", /* HORIZ */
4983: EOLSTRING, /* EOL */
4984: NULL };
4985: static short bitc2d[] = { 1,3,6,7,3,6,7,4,3,12 };
4986:
4987: #define EOL0STRING "0000000000010"
4988: #define EOL1STRING "0000000000011"
4989: #define EOFB "000000000001000000000001"
4990:
4991: static char *spare1d[] = {
4992: "000000001", /* 0, */
4993: "0000000001", /* 0, */
4994: "00000000001", /* 0 */
4995: NULL };
4996: static char *spare2d[] = {
4997: "0000001", /* 0, */
4998: "00000001", /* 0, */
4999: "000000001", /* 0, */
5000: "0000000001", /* 0, */
5001: "00000000001", /* 0 */
5002: NULL };
5003:
5004: /* State-transition table for decoding CCITT G3-1 */
5005:
5006: /* bit colors; also, starting index in table of 1-D codes*/
5007: #define DST_color short
5008: #define DST_white 0
5009: #define DST_black 1
5010:
5011: #define flip_color(c) ((c)? 0: 1)
5012:
5013: #define DST_2d 2 /* starting index in table of 2-D codes */
5014:
5015: #define DST_state short /* state-id: index into DST_tbl.e[] */
5016: #define DST_state_NULL (-1)
5017: #define DST_state_ERROR (-2)
5018:
5019: #define DST_action int
5020: #define DST_action_NULL (-1)
5021: #define DST_action_ERROR (-2)
5022:
5023: /* transition in finite-state machine */
5024: typedef struct DST_transit {
5025: DST_action a; /* action to perform */
5026: DST_state s; /* next state */
5027: } DST_transit;
5028: typedef struct DST_entry {
5029: char p[MAXCODELEN+1]; /* code prefix so far (in ASCII) */
5030: short l; /* strlen(.p) */
5031: short z; /* no. of trailing "0"'s in .p */
5032: DST_transit t[2]; /* two transitions: on 0 & 1 */
5033: } DST_entry;
5034: typedef struct DST_table {
5035: int mny; /* no. entries so far */
5036: DST_entry *e; /* array in malloc space:
5037: e[DST_white] starts white 1-D codes;
5038: e[DST_black] starts black 1-D codes;
5039: e[DST_2d] starts 2-D codes */
5040: } DST_table;
5041: typedef struct DST_context {
5042: DST_color c; /* current run-color */
5043: int l; /* length of current code in bits: 0..(len-1) */
5044: DST_table *t; /* table */
5045: DST_state s; /* current state */
5046: DST_transit tr; /* current state/action */
5047: } DST_context;
5048:
5049:
5050: DST_table *ccitt_table();
5051: RLE_Line *g31_to_rlel();
5052: int rlel_to_g31();
5053: RLE_Line *g32_to_rlel();
5054: int rlel_to_g32();
5055: RLE_Line *g4_to_rlel();
5056: int rlel_to_g4();
5057: 0707070035351137061006640007620000050000010261170476773366600000600000010272CPU.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
5058: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
5059: /* The copyright notice does not imply actual or intended publication. */
5060: /* AUTHORS: */
5061: /* H. S. Baird - ATT-BL MH - first versions */
5062: /* T. Thompson - ATT-BL HO - portable versions */
5063: /* C. Macey - ATT-DSG LZ - portable versions */
5064:
5065: /* Specify the environment: CPU, OS, graphics, etc.
5066: This is an attempt to maintain a single master source tailorable at compile
5067: time, while encapsulating as many as possible of the required #if's and
5068: #ifdef's in this one file.
5069: OS-dependent #includes are triggered by these prior statements:
5070: #define LIBC_INCL 1 -- strcpy(), etc
5071: #define VALUES_INCL 1 -- math constants (PI etc)
5072: #define FILE_TREE_INCL 1 -- UNIX file-tree walking
5073: */
5074:
5075: /* CPUs with some support: */
5076: #define VAX 0
5077: #define CRAY 1
5078: #define SUN 2 /* including SPARC */
5079: #define ATT3B 3
5080: #define I386 4
5081: #define MIPS 5 /* including SGI */
5082:
5083: /*** Select CPU here: */
5084: #define CPU VAX
5085:
5086:
5087: /* Operating systems with some support: */
5088: #define V9_OS 1 /* ATT-BL research UNIX, 9th edition */
5089: #define SV_OS 2 /* ATT UNIX System V */
5090: #define SUN_OS 3 /* Sun OS 4.x */
5091:
5092: /*** Select OS here: */
5093: #define OS V9_OS
5094:
5095:
5096: /* Graphics display environments with some support: */
5097: #define NO_GRAPHICS 0 /* defeat all graphics */
5098: #define Y_GRAPHICS 1 /* the Y graphics interface (used in 1127 for Metheus) */
5099: #define SUN_GRAPHICS 2 /* Tim Thompson's Sun interface */
5100: #define X_GRAPHICS 3 /* Mark Tuomenoksa's X interface */
5101:
5102: /*** Select graphics environment here: */
5103: #define GRAPHICS Y_GRAPHICS
5104:
5105:
5106: /* OCR installation directory */
5107: #ifndef OCRDIR
5108: #define OCRDIR "/usr/ocr"
5109: #endif
5110:
5111: /*** Miscellaneous arcane options: best left alone **/
5112:
5113: #define FILE_TREE (1) /* set to zero to defeat UNIX file tree code */
5114:
5115:
5116: /*** END OF SELECTIONS ** The rest of this file merely implements their effects */
5117:
5118: /* define byte ordering in CPU */
5119:
5120: #if CPU == SUN || CPU == MIPS
5121: #define BIG_ENDIAN 1
5122: #endif
5123:
5124: /* deal with compilers that don't like (void *) */
5125:
5126: #if CPU == MIPS
5127: #define VOID char
5128: #else
5129: #define VOID void
5130: #endif
5131:
5132: /* include libc functions defs, if necessary */
5133:
5134: #if LIBC_INCL
5135:
5136: #if OS == V9_OS || CPU == CRAY
5137: #include <libc.h>
5138: #else
5139: #if OS == SV_OS || OS == SUN_OS || CPU == MIPS
5140: #include <string.h>
5141: #endif
5142: #endif
5143:
5144: #endif
5145:
5146: /* include values */
5147:
5148: #if VALUES_INCL
5149: #include <values.h>
5150: #endif
5151:
5152: /* UNIX file-tree-walk includes */
5153:
5154: #if FILE_TREE_INCL
5155:
5156: #if CPU==VAX || CPU==CRAY || CPU==MIPS
5157: #include <sys/types.h>
5158: #include <sys/stat.h>
5159: #include <ftw.h>
5160: #else
5161: #if CPU==SUN || CPU==I386
5162: #include <sys/types.h>
5163: #include <sys/stat.h>
5164: #include "myftw.h" /* T. Thompson's version */
5165: #endif
5166: #endif
5167:
5168: #endif
5169:
5170: #if CPU==SUN||CPU==ATT3B||CPU==MIPS||CPU==I386
5171: #define sgn(V) (((V)>0)? 1: (((V)<0)? -1: 0))
5172: #endif
5173:
5174: #if CPU==SUN||CPU==ATT3B||CPU==MIPS
5175: /* These are all big-endian machines */
5176: #define swapshortin(x) (((x)<<8)&0xff00)|(((x)>>8)&0xff)
5177: #define swapintin(x) \
5178: ((((x)<<24)&0xff000000)| \
5179: (((x)<<8) &0x00ff0000)| \
5180: (((x)>>8) &0x0000ff00)| \
5181: (((x)>>24)&0x000000ff))
5182: /* The order of bytes in an int */
5183: #define INDEX0 3
5184: #define INDEX1 2
5185: #define INDEX2 1
5186: #define INDEX3 0
5187: /* disable fast trick for picking out a short from an int */
5188: #define USESHIFT /* cf. skewlib.c */
5189: #else
5190: #define swapshortin(x) (x)
5191: #define swapintin(x) (x)
5192: #define INDEX0 0
5193: #define INDEX1 1
5194: #define INDEX2 2
5195: #define INDEX3 3
5196: #endif
5197:
5198: /* global max no. classes -- gradually being made dynamic everywhere */
5199: #if CPU==SUN
5200: #define MAX_CL 128
5201: #else
5202: #define MAX_CL 3200 /* adequate for JIS Level 1 */
5203: #endif
5204:
5205: /* include char types (is this really necessary?) */
5206:
5207: #if CTYPE_INCL
5208:
5209: #if CPU == SUN
5210: #include <string.h>
5211: #else
5212: #include <ctype.h>
5213: #endif
5214:
5215: #endif
5216:
5217: /* includes for atan2 special configurations */
5218:
5219: #if ATAN_INCL
5220:
5221: #if CPU == CRAY
5222: #define use_fast_atan2 F
5223: #include "CRAY.h"
5224: #else
5225: #define use_fast_atan2 T
5226: #endif
5227:
5228: #endif
5229:
5230: /* regular expression includes (fix to use standard regexp?) */
5231:
5232: #if REGEXP_INCL
5233:
5234: #if OS == V9_OS
5235: #include <regexp.h>
5236: #else
5237: #include "regexp.h"
5238: #endif
5239:
5240: #endif
5241:
5242: /* Use of the graphics display */
5243:
5244: #if CPU != CRAY
5245: #define SHOW_GRAPHICS 1
5246: #endif
5247:
5248: #ifndef PI
5249: #define PI 3.14159265358979323846
5250: #endif
5251: 0707070035351137071006640007620000050000010261230476773366600001000000027244Coord.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
5252: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
5253: /* The copyright notice does not imply actual or intended publication. */
5254: /* AUTHORS: */
5255: /* H. S. Baird - ATT-BL MH - first versions */
5256: /* T. J. Thompson - ATT-BL HO - improvements */
5257:
5258: /* Coord.c - function bodies for basic Coordinate geometry.
5259: See Coord.h for associated defines, typedefs, etc.
5260: */
5261:
5262: #include <stdio.h>
5263: #include <math.h>
5264: #include <string.h>
5265: #define ATAN_INCL 1
5266: #include "CPU.h"
5267: #include "boole.h"
5268: #include "Units.h"
5269: #include "Coord.h"
5270:
5271: /* Added by Tim Thompson ... */
5272: int Readvax = 0;
5273:
5274: VOID
5275: setreadvax()
5276: {
5277: char *getenv();
5278: char *p = getenv("READVAX");
5279: /* any non-null value of READVAX will set it */
5280: if ( p!=NULL && strlen(p)>0 )
5281: Readvax = 1;
5282: }
5283:
5284: /* ... */
5285:
5286: /* Convert a real value, a units specification, and a resolution
5287: into a value in scanner coordinates. */
5288: int vto_scoor(v,u,r)
5289: double v; /* value in special units */
5290: char u; /* units: one of UNITS (see ric.h) */
5291: int r; /* resolution in pixels/inch */
5292: { int c;
5293: switch(u) {
5294: case 'i': /* inches */
5295: c = (int)(v*r + 0.5);
5296: break;
5297: case 'c': /* cm */
5298: c = (int)((v*r/2.54) + 0.5);
5299: break;
5300: case 'p': /* points */
5301: c = (int)((v*INCHES_PER_POINT*r) + 0.5);
5302: break;
5303: case 'P': /* picas */
5304: c = (int)((v*12.0*INCHES_PER_POINT*r) + 0.5);
5305: break;
5306: case 's': /* scanner pixel (Scoor) */
5307: case 'u': /* basic unit */
5308: c = (int)(v + 0.5);
5309: break;
5310: default:
5311: c = (int)(v + 0.5);
5312: break;
5313: };
5314: return(c);
5315: }
5316:
5317: /* Return pointer to empty Sp from malloc space */
5318: Sp *alloc_sp()
5319: { Sp *spp;
5320: if((spp=(Sp *)malloc(sizeof(Sp)))==NULL)
5321: abort("alloc_sp: can't");
5322: *spp = zero_Sp;
5323: return(spp);
5324: }
5325:
5326: /* Free Sp from malloc space */
5327: free_sp(spp)
5328: Sp *spp;
5329: { free(spp);
5330: }
5331:
5332: Sp *ato_sp(s)
5333: char *s;
5334: { char *d;
5335: static Sp p;
5336: char *p_x,*p_y;
5337: #define SP_DELIM "(), "
5338: d = strdup(s);
5339: p_x = strtok(d,SP_DELIM);
5340: p_y = strtok((char *)0,SP_DELIM);
5341: if(p_x==NULL||p_y==NULL)
5342: {free(d); return(NULL);};
5343: p.x = atoi(p_x);
5344: p.y = atoi(p_y);
5345: free(d);
5346: return(&p);
5347: }
5348:
5349: char *sp_toa(sp)
5350: Sp *sp;
5351: #define sp_toa_distinct (5)
5352: { static char s[sp_toa_distinct][40];
5353: static int sp_toa_cur = -1;
5354: sp_toa_cur = (sp_toa_cur+1)%sp_toa_distinct;
5355: sprintf(s[sp_toa_cur],"(%d,%d)",sp->x,sp->y);
5356: return(s[sp_toa_cur]);
5357: }
5358:
5359: /* Read a list of Sp's (in ascii) from file *fp, into set *spsp */
5360: frda_sps(fp,spsp)
5361: FILE *fp;
5362: Sps *spsp;
5363: #define MAX_SPS_LINE (80)
5364: { Sp *spp,**bb;
5365: long seek;
5366: char line[MAX_SPS_LINE+1];
5367: *spsp = empty_Sps;
5368: seek = ftell(fp);
5369: /* count all points quickly, in advance */
5370: while(!feof(fp)) {
5371: line[0] = '\0';
5372: fgets(line,MAX_SPS_LINE,fp);
5373: if(strlen(line)>0) {
5374: spsp->mny++;
5375: };
5376: };
5377: if((spsp->pa=(Sp **)malloc((spsp->mny+1)*sizeof(Sp *)))==NULL)
5378: abort("frda_sps: can't alloc spsp->pa[%d]",spsp->mny+1);
5379: /* next, reread points */
5380: fseek(fp,(long)seek,0);
5381: bb=spsp->pa;
5382: while(!feof(fp)) {
5383: line[0] = '\0';
5384: fgets(line,MAX_SPS_LINE,fp);
5385: if(strlen(line)>0) {
5386: *(spp = alloc_sp()) = *ato_sp(line);
5387: *(bb++) = spp;
5388: };
5389: };
5390: *bb = NULL;
5391: }
5392:
5393: err_sps(p)
5394: Sps *p;
5395: { int i;
5396: Sp **s;
5397: fprintf(stderr,"Sps: %d points: ",p->mny);
5398: if(p->mny>0) for(s=p->pa; (*s)!=NULL; s++) {
5399: fprintf(stderr,"%s ",sp_toa(*s));
5400: };
5401: fprintf(stderr,"\n");
5402: }
5403:
5404: Sp *append_sp_sps(sp,sps)
5405: Sp *sp;
5406: Sps *sps;
5407: { if(sps->mny>0) {
5408: if((sps->pa=(Sp **)realloc(sps->pa,(sps->mny+2)*sizeof(Sp *)))==NULL)
5409: abort("append_sp_sps: can't realloc sps->pa[%d]",sps->mny+2);
5410: }
5411: else { sps->mny=0;
5412: if((sps->pa=(Sp **)malloc((sps->mny+2)*sizeof(Sp *)))==NULL)
5413: abort("append_sp_sps: can't alloc sps->pa[%d]",sps->mny+2);
5414: };
5415: sps->pa[sps->mny++] = sp;
5416: sps->pa[sps->mny] = NULL;
5417: }
5418:
5419: /* Return pointer to local static Sps which holds a duplicate of the
5420: given Sps (all contents are freshly malloc'ed) */
5421: Sps *dup_sps(old)
5422: Sps *old;
5423: { static Sps new;
5424: Sp **o,**n;
5425: if(old->mny>0) {
5426: new.mny = old->mny;
5427: if((new.pa=(Sp **)malloc((new.mny+1)*sizeof(Sp *)))==NULL)
5428: abort("dup_sps: can't alloc new.pa[%d]",new.mny+1);
5429: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) {
5430: *(*n = alloc_sp()) = **o;
5431: };
5432: *n = NULL;
5433: }
5434: else new = empty_Sps;
5435: return(&new);
5436: }
5437:
5438: free_sps(p)
5439: Sps *p;
5440: { if(p->pa!=NULL) free(p->pa);
5441: *p = empty_Sps;
5442: }
5443:
5444: Sp *append_sp_spa(sp,spa)
5445: Sp *sp;
5446: Spa *spa;
5447: { if(spa->mny>0) {
5448: if((spa->a=(Sp *)realloc(spa->a,(spa->mny+1)*sizeof(Sp)))==NULL)
5449: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1);
5450: }
5451: else { spa->mny=0;
5452: if((spa->a=(Sp *)malloc((spa->mny+1)*sizeof(Sp)))==NULL)
5453: abort("append_sp_spa: can't alloc spa->a[%d]",spa->mny+1);
5454: };
5455: spa->a[spa->mny++] = *sp;
5456: }
5457:
5458: err_spa(p)
5459: Spa *p;
5460: { int i;
5461: Sp *sp;
5462: fprintf(stderr,"Spa: %d points: ",p->mny);
5463: for(i=0,sp=p->a;i<p->mny;i++,sp++) {
5464: fprintf(stderr,"%s ",sp_toa(sp));
5465: };
5466: fprintf(stderr,"\n");
5467: }
5468:
5469: free_spa(p)
5470: Spa *p;
5471: { if(p->a!=NULL) free(p->a);
5472: *p = empty_Spa;
5473: }
5474:
5475: /* Rotate the Scanner point `(x,y') about origin `*orp' by angle `ang',
5476: and return pointer to the result. This is slow, but no matter. */
5477: Sp *rotate_Sp(ang,orp,x,y)
5478: double ang;
5479: Sp *orp;
5480: int x,y;
5481: { static Sp res;
5482: Sp of;
5483: of.x = x - orp->x; of.y = y - orp->y;
5484: res.x = (short)(((cos(ang)*of.x - sin(ang)*of.y)) + orp->x + 0.5);
5485: res.y = (short)(((sin(ang)*of.x + cos(ang)*of.y)) + orp->y + 0.5);
5486: return(&res);
5487: }
5488:
5489: /* Horizontally shear the Scanner point `(x,y') about origin `*orp' by shear
5490: angle `ang', and return pointer to the result. `Ang' is close to 90 degrees.
5491: This is slow, but no matter. */
5492: Sp *hshear_Sp(ang,orp,x,y)
5493: double ang;
5494: Sp *orp;
5495: int x,y;
5496: { static Sp res;
5497: Scoor of_y,tr_x;
5498: res.x = (short)(orp->x - (y - orp->y)*tan(ang-(90.0*DtoR)) + 0.5);
5499: res.y = orp->y;
5500: return(&res);
5501: }
5502:
5503: /* Return pointer to initialized Edge from malloc space */
5504: Edge *alloc_edge()
5505: { Edge *ep;
5506: if((ep=(Edge *)malloc(sizeof(Edge)))==NULL)
5507: abort("alloc_edge: can't");
5508: *ep = empty_Edge;
5509: return(ep);
5510: }
5511:
5512: /* Free Edge from malloc space */
5513: free_edge(ep)
5514: Edge *ep;
5515: { free(ep);
5516: }
5517:
5518: char *edge_toa(ep)
5519: Edge *ep;
5520: { static char s[40];
5521: strcpy(s,sp_toa(&(ep->a)));
5522: strcat(s,"-");
5523: strcat(s,sp_toa(&(ep->b)));
5524: return(s);
5525: }
5526:
5527: Edge *ato_edge(s)
5528: char *s;
5529: { char *d;
5530: static Edge e;
5531: char *a_x,*a_y,*b_x,*b_y;
5532: #define EDGE_DELIM "(),- "
5533: d = strdup(s);
5534: a_x = strtok(d,EDGE_DELIM);
5535: a_y = strtok((char *)0,EDGE_DELIM);
5536: b_x = strtok((char *)0,EDGE_DELIM);
5537: b_y = strtok((char *)0,EDGE_DELIM);
5538: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL)
5539: {free(d); return(NULL);};
5540: e.a.x = atoi(a_x);
5541: e.a.y = atoi(a_y);
5542: e.b.x = atoi(b_x);
5543: e.b.y = atoi(b_y);
5544: free(d);
5545: return(&e);
5546: }
5547:
5548: /* Return pointer to empty Bbx from malloc space */
5549: Bbx *alloc_bbx()
5550: { Bbx *bxp;
5551: if((bxp=(Bbx *)malloc(sizeof(Bbx)))==NULL)
5552: abort("alloc_bbx: can't");
5553: *bxp = empty_Bbx;
5554: return(bxp);
5555: }
5556:
5557: /* Free Bbx from malloc space */
5558: free_bbx(bxp)
5559: Bbx *bxp;
5560: { free(bxp);
5561: }
5562:
5563: char *bbx_toa(bxp)
5564: Bbx *bxp;
5565: { static char s[40];
5566: strcpy(s,sp_toa(&(bxp->a)));
5567: strcat(s,sp_toa(&(bxp->b)));
5568: return(s);
5569: }
5570:
5571: Bbx *ato_bbx(s)
5572: char *s;
5573: { char *d;
5574: static Bbx bx;
5575: char *a_x,*a_y,*b_x,*b_y;
5576: #define BBX_DELIM "(), "
5577: d = strdup(s);
5578: a_x = strtok(d,BBX_DELIM);
5579: a_y = strtok((char *)0,BBX_DELIM);
5580: b_x = strtok((char *)0,BBX_DELIM);
5581: b_y = strtok((char *)0,BBX_DELIM);
5582: if(a_x==NULL||a_y==NULL||b_x==NULL||b_y==NULL)
5583: {free(d); return(NULL);};
5584: bx.a.x = atoi(a_x);
5585: bx.a.y = atoi(a_y);
5586: bx.b.x = atoi(b_x);
5587: bx.b.y = atoi(b_y);
5588: free(d);
5589: return(&bx);
5590: }
5591:
5592: Bbx *expand_bbx(bxp,X)
5593: Bbx *bxp;
5594: int X; /* expansion code */
5595: { static Bbx xbx;
5596: xbx = *bxp;
5597: switch(X) {
5598: case -3:
5599: xbx.a.x += 2;
5600: xbx.a.y += 2;
5601: xbx.b.x -= 1;
5602: xbx.b.y -= 1;
5603: break;
5604: case -2:
5605: xbx.a.x += 1;
5606: xbx.a.y += 1;
5607: xbx.b.x -= 1;
5608: xbx.b.y -= 1;
5609: break;
5610: case -1:
5611: xbx.a.x += 1;
5612: xbx.a.y += 1;
5613: break;
5614: case 0:
5615: break;
5616: case 1:
5617: xbx.b.x += 1;
5618: xbx.b.y += 1;
5619: break;
5620: case 2:
5621: xbx.a.x -= 1;
5622: xbx.a.y -= 1;
5623: xbx.b.x += 1;
5624: xbx.b.y += 1;
5625: break;
5626: case 3:
5627: xbx.a.x -= 1;
5628: xbx.a.y -= 1;
5629: xbx.b.x += 2;
5630: xbx.b.y += 2;
5631: break;
5632: default:
5633: break;
5634: };
5635: return(&xbx);
5636: }
5637:
5638: /* Predicate: Is most of Bbx 1 inside Bbx 2? ``Most'' is defined
5639: as more than half of the first Bbx's area inside BBx 2.*/
5640: boolean bbx_inside_most(b1,b2)
5641: Bbx *b1,*b2;
5642: { struct { /* overlap between blob box and selection box */
5643: Bbx bx; /* Bbx of intersection */
5644: Sp sd; /* side-lengths of overlap box, >=0 */
5645: long area; /* area is square pixels, >=0 */
5646: } ov;
5647: if(!bbx_inside_any(b1,b2)) return(F);
5648: else if(bbx_inside_all(b1,b2)) return(T);
5649: else { /* compute overlap box */
5650: ov.bx.a.x = ((b1)->a.x>(b2)->a.x)? (b1)->a.x: (b2)->a.x;
5651: ov.bx.a.y = ((b1)->a.y>(b2)->a.y)? (b1)->a.y: (b2)->a.y;
5652: ov.bx.b.x = ((b1)->b.x<(b2)->b.x)? (b1)->b.x: (b2)->b.x;
5653: ov.bx.b.y = ((b1)->b.y<(b2)->b.y)? (b1)->b.y: (b2)->b.y;
5654: ov.sd.x = bbx_wid(&ov.bx); if(ov.sd.x<0) ov.sd.x=0;
5655: ov.sd.y = bbx_hgt(&ov.bx); if(ov.sd.y<0) ov.sd.y=0;
5656: ov.area = ov.sd.x*ov.sd.y;
5657: return( (ov.area>0) && ( 2*ov.area > bbx_area(b1) ) );
5658: };
5659: }
5660:
5661: Bbx *translate_bbx(bxp,off)
5662: Bbx *bxp;
5663: Sp off;
5664: { static Bbx res;
5665: res.a.x = bxp->a.x + off.x;
5666: res.a.y = bxp->a.y + off.y;
5667: res.b.x = bxp->b.x + off.x;
5668: res.b.y = bxp->b.y + off.y;
5669: return(&res);
5670: }
5671:
5672: /* Free Bbxs (but not the contents) */
5673: free_bbxs(bxsp)
5674: Bbxs *bxsp;
5675: { Bbx **b;
5676: if(bxsp->mny>0) {
5677: if(bxsp->pa!=NULL) free(bxsp->pa);
5678: };
5679: *bxsp = empty_Bbxs;
5680: }
5681:
5682: /* Free Bbxs (and the individually-malloc'ed contents) */
5683: free_bbxs_etc(bxsp)
5684: Bbxs *bxsp;
5685: { Bbx **b;
5686: if(bxsp->mny>0) {
5687: for(b=bxsp->pa; (*b)!=NULL; b++) free(*b);
5688: if(bxsp->pa!=NULL) free(bxsp->pa);
5689: };
5690: *bxsp = empty_Bbxs;
5691: }
5692:
5693: /* Return pointer to local static Bbxs which holds a duplicate of the
5694: given Bbxs (all contents are freshly malloc'ed) */
5695: Bbxs *dup_bbxs(old)
5696: Bbxs *old;
5697: { static Bbxs new;
5698: Bbx **o,**n;
5699: if(old->mny>0) {
5700: new.mny = old->mny;
5701: new.alloc = old->alloc;
5702: new.incr = old->incr;
5703: if((new.pa=(Bbx **)malloc((new.alloc)*sizeof(Bbx *)))==NULL)
5704: abort("dup_bbxs: can't alloc new.pa[%d]",new.alloc);
5705: for(o=old->pa,n=new.pa; *o!=NULL; o++,n++) {
5706: *(*n = alloc_bbx()) = **o;
5707: };
5708: *n = NULL;
5709: }
5710: else new = empty_Bbxs;
5711: return(&new);
5712: }
5713:
5714: Bbx *append_bbx(bxp,bxsp)
5715: Bbx *bxp;
5716: Bbxs *bxsp;
5717: { if(bxsp->mny>0) {
5718: if((bxsp->mny+2)>bxsp->alloc) {
5719: bxsp->alloc += bxsp->incr;
5720: if( ( bxsp->pa =
5721: (Bbx **)realloc(bxsp->pa,bxsp->alloc*sizeof(Bbx *)) )
5722: ==NULL )
5723: abort("append_bbx: can't alloc bxsp->pa[%d]",bxsp->alloc);
5724: };
5725: }
5726: else { bxsp->mny=0;
5727: if(bxsp->pa!=NULL) free(bxsp->pa);
5728: bxsp->alloc=0;
5729: while((bxsp->mny+2)>bxsp->alloc) bxsp->alloc += bxsp->incr;
5730: if((bxsp->pa=(Bbx **)malloc(bxsp->alloc*sizeof(Bbx *)))==NULL)
5731: abort("append_bbx: can't alloc bxsp->a[%d]",bxsp->alloc);
5732: };
5733: bxsp->pa[bxsp->mny++] = bxp;
5734: bxsp->pa[bxsp->mny] = NULL;
5735: }
5736:
5737: frda_bbxs(fp,bxsp)
5738: FILE *fp;
5739: Bbxs *bxsp;
5740: #define MAX_BBX_LINE (80)
5741: { Bbx *bxp,**bb;
5742: long seek;
5743: char line[MAX_BBX_LINE+1];
5744: *bxsp = empty_Bbxs;
5745: seek = ftell(fp);
5746: /* count all boxes quickly, in advance */
5747: while(!feof(fp)) {
5748: line[0] = '\0';
5749: fgets(line,MAX_BBX_LINE,fp);
5750: if(strlen(line)>0) {
5751: bxsp->mny++;
5752: };
5753: };
5754: if((bxsp->pa=(Bbx **)malloc((bxsp->mny+1)*sizeof(Bbx *)))==NULL)
5755: abort("frda_bbxs: can't alloc bxsp->pa[%d]",bxsp->mny+1);
5756: bxsp->alloc = bxsp->mny+1;
5757: /* next, reread boxes */
5758: fseek(fp,(long)seek,0);
5759: bb=bxsp->pa;
5760: while(!feof(fp)) {
5761: line[0] = '\0';
5762: fgets(line,MAX_BBX_LINE,fp);
5763: if(strlen(line)>0) {
5764: *(bxp = alloc_bbx()) = *ato_bbx(line);
5765: *(bb++) = bxp;
5766: };
5767: };
5768: *bb = NULL;
5769: }
5770:
5771: fwra_bbxs(fp,bxsp)
5772: FILE *fp;
5773: Bbxs *bxsp;
5774: { Bbx **b;
5775: if(bxsp->mny>0) for(b=bxsp->pa; *b!=NULL; b++) {
5776: fputs(bbx_toa(*b),fp);
5777: fputs("\n",fp);
5778: };
5779: fflush(fp);
5780: }
5781: 0707070035351137101006640007620000050000010261240476773366600001000000017772Coord.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
5782: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
5783: /* The copyright notice does not imply actual or intended publication. */
5784: /* AUTHORS: */
5785: /* H. S. Baird - ATT-BL MH - first versions */
5786: /* Coord.h - defines, typedefs, Inits, empties, and function declarations
5787: for basic Coordinate geometry data items.
5788: See Coord.c for associated functions.
5789: */
5790:
5791: /* Round signed floating-pt no. F:
5792: (a) ROUND - to nearest integer;
5793: (b) ROUND_UP - up to next int;
5794: (c) ROUND_DN - down to prior int.
5795: Evaluates the argument exactly once. */
5796: static double _round,_round_up,_round_dn;
5797: #define ROUND(F) ((int)(((_round=(F))>=0.0)? _round+0.5: _round-0.5))
5798: #define ROUND_UP(F) ((int)(((_round_up=(F))>=0.0)? _round_up+0.999999: _round_up))
5799: #define ROUND_DN(F) ((int)(((_round_dn=(F))>=0.0)? _round_dn: _round_dn-0.999999))
5800:
5801: /* The basic unit is the scanner pixel, located in the X,Y plane. As in many
5802: graphics coordinate systems, X increases left-to-right, while Y increases
5803: top-down. Pixel coordinates are usually integer values. The physical extent
5804: of integer coordinate `x' along the real X-axis is the half-open interval
5805: [x,x+1), and similarly for Y. The actual digitizing resolution (e.g.
5806: pixels/inch) represented can vary from document to document, and is almost
5807: always known to the algorithms. X & Y resolution can be different, though
5808: for simplicity of discussion we will usually assume that they are equal,
5809: i.e. that pixels are square. Thus pixel (x,y) may be thought of as the region
5810: [x,x+1)X[y,y+1) in the real plane.
5811: Half-pixel resolution is also supported, with its own data types for
5812: clarity. However, to avoid distracting struggles with the type system, they
5813: are for the most part #defined to be identical to ordinary coordinates. The
5814: principle effect is that the limits of scanner coordinates have been halved
5815: to allow for safe use of half-pixels everywhere. (This still permits images
5816: 80 inches square at 400 pixels/inch, assuming `short' is at least 16-bit 2's
5817: complement.)
5818: Half-pixel coordinates can also be used to describe boundaries of regions,
5819: as a set of ideal point locations at the corners and edge midpoints of pixels.
5820: The half-pixel data type is used; boundary points are identified by flags
5821: in the Bdy "boundary" structure, and may be displayed differently. */
5822:
5823: #define Scoor short /* Scanner pixel coordinate value */
5824: #define Hcoor Scoor /* Half-pixel coordinate value */
5825: #define Bcoor Hcoor /* Half-pixel boundary coordinate value */
5826:
5827: /* Each Scoor value `v' is associated of course with two Hcoor values `a' < `b'.
5828: Conventionally, the physical extent of the `a' half-coordinate is the real
5829: interval [v,v+0.5), and `b' is [v+0.5,v+1). */
5830: #define StoHa(S) ((S)*2)
5831: #define StoHb(S) ((S)*2+1)
5832: #define HtoS(H) ((H)/2)
5833:
5834: /* The 3 half-pixel boundary points of a pixel coordinate `C' are: */
5835: #define StoBa(S) (StoHa((S))) /* minimum of interval */
5836: #define StoBb(S) (StoHb((S))) /* midpoint of interval */
5837: #define StoBc(S) (StoHa((S)+1)) /* maximum of interval */
5838:
5839: #define Scoor_MIN (SHRT_MIN/2) /* minimum possible value */
5840: #define Scoor_MAX (SHRT_MAX/2) /* maximum possible value */
5841:
5842: #define Hcoor_MIN (SHRT_MIN) /* minimum possible value */
5843: #define Hcoor_MAX (SHRT_MAX) /* maximum possible value */
5844:
5845: #define fwri_Scoor(F,V) fwri_int2((F),(V))
5846: #define frdi_Scoor(F) frdi_int2(F)
5847:
5848: #define fwri_Hcoor(F,V) fwri_int2((F),(V))
5849: #define frdi_Hcoor(F) frdi_int2(F)
5850:
5851: #define fwri_Bcoor(F,V) fwri_int2((F),(V))
5852: #define frdi_Bcoor(F) frdi_int2(F)
5853:
5854: typedef struct Sp { /* point: pixel address */
5855: Scoor x; /* increases left-to-right: Scoor_MIN is left of image */
5856: Scoor y; /* increases down: Scoor_MIN is top of image */
5857: } Sp;
5858: #define Hp Sp /* Half-pixel point */
5859:
5860: #define Init_Zero_Sp {0,0}
5861: #define Init_Min_Sp {Scoor_MIN,Scoor_MIN}
5862: #define Init_Max_Sp {Scoor_MAX,Scoor_MAX}
5863:
5864: #if MAIN
5865: Sp zero_Sp = Init_Zero_Sp;
5866: #else
5867: extern Sp zero_Sp;
5868: #endif
5869:
5870: #define fwri_Sp(F,P) { fwri_Scoor((F),(P)->x); fwri_Scoor((F),(P)->y); }
5871: #define frdi_Sp(F,P) (feof(F)? 0: ( \
5872: (P)->x=frdi_Scoor(F), \
5873: (P)->y=frdi_Scoor(F), \
5874: (ferror(F)? -errno: 1) ) )
5875:
5876: /* Is Sp *p1 exactly equal to Sp *p2? */
5877: #define sp_eq(p1,p2) ( \
5878: ((p1)->x == (p2)->x) \
5879: && ((p1)->y == (p2)->y) \
5880: )
5881:
5882: typedef struct Sps { /* Set of Points */
5883: int mny; /* no. points (mny==0 ==> pa==NULL) */
5884: Sp **pa; /* NULL-terminated Sp *pa[mny+1] (malloc space)*/
5885: } Sps;
5886:
5887: #define Init_Sps {0,NULL}
5888: #if MAIN
5889: Sps empty_Sps = Init_Sps;
5890: #else
5891: extern Sps empty_Sps;
5892: #endif
5893:
5894: typedef struct Spa { /* array of Points */
5895: int mny; /* no. points in array */
5896: Sp *a; /* Sp a[mny] (malloc space)*/
5897: } Spa;
5898: /** #define Pointa Spa **/ /* OBSOLESCENT */
5899:
5900: #define Init_Spa {0,NULL}
5901: #if MAIN
5902: Spa empty_Spa = Init_Spa;
5903: #else
5904: extern Spa empty_Spa;
5905: #endif
5906:
5907: /* An edge is an ordered pair of vertices. */
5908: typedef struct Edge {
5909: Sp a,b; /* endpoints */
5910: } Edge;
5911:
5912: #define Init_Edge {Init_Zero_Sp,Init_Zero_Sp}
5913: #if MAIN
5914: Edge empty_Edge = Init_Edge;
5915: #else
5916: extern Edge empty_Edge;
5917: #endif
5918:
5919: #define fwri_Edge(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
5920: #define frdi_Edge(F,P) ( feof(F)? 0: ( \
5921: frdi_Sp(F,&((P)->a)), \
5922: frdi_Sp(F,&((P)->b)), \
5923: (ferror(F)? -errno: 1) ) )
5924:
5925: /* A bounding box is a rectangle */
5926: typedef struct { /* bounding box: inclusive of boundary values */
5927: Sp a; /* top-left corner */
5928: Sp b; /* bottom-right corner */
5929: } Bbx;
5930:
5931: typedef struct DSp { /* point: pixel address */
5932: double x; /* increases down the page, MinScoor at top */
5933: double y; /* increases across the page, MinScoor at left */
5934: } DSp;
5935:
5936: #define Init_Bbx {Init_Max_Sp,Init_Min_Sp}
5937: #define Init_Max_Bbx {Init_Min_Sp,Init_Max_Sp}
5938: #if MAIN
5939: Bbx empty_Bbx = Init_Bbx;
5940: Bbx max_Bbx = Init_Max_Bbx;
5941: #else
5942: extern Bbx empty_Bbx;
5943: extern Bbx max_Bbx;
5944: #endif
5945:
5946: #define fwri_Bbx(F,P) { fwri_Sp((F),&((P)->a)); fwri_Sp((F),&((P)->b)); }
5947: #define frdi_Bbx(F,P) ( feof(F)? 0: ( \
5948: frdi_Sp(F,&((P)->a)), \
5949: frdi_Sp(F,&((P)->b)), \
5950: (ferror(F)? -errno: 1) ) )
5951:
5952: /* OBSOLESCENT: */
5953: #if MAIN
5954: Bbx null_Bbx = {Init_Max_Sp,Init_Min_Sp};
5955: #else
5956: extern Bbx null_Bbx;
5957: #endif
5958:
5959: /* height, width, area of Bbx in pixels */
5960: #define bbx_hgt(bxp) ((bxp)->b.y-(bxp)->a.y+1)
5961: #define bbx_wid(bxp) ((bxp)->b.x-(bxp)->a.x+1)
5962: #define bbx_area(bxp) (bbx_hgt((bxp))*bbx_wid((bxp)))
5963:
5964: /* Is Bbx *b1 exactly equal to Bbx *b2? */
5965: #define bbx_eq(b1,b2) ( \
5966: ((b1)->a.x == (b2)->a.x) \
5967: && ((b1)->a.y == (b2)->a.y) \
5968: && ((b1)->b.x == (b2)->b.x) \
5969: && ((b1)->b.y == (b2)->b.y) \
5970: )
5971:
5972: /* Is Bbx *b1 wholly inside Bbx *b2? */
5973: #define bbx_inside_all(b1,b2) ( \
5974: ((b1)->a.x >= (b2)->a.x) \
5975: && ((b1)->a.y >= (b2)->a.y) \
5976: && ((b1)->b.x <= (b2)->b.x) \
5977: && ((b1)->b.y <= (b2)->b.y) \
5978: )
5979:
5980: /* Is any of Bbx *b1 inside Bbx *b2? */
5981: #define bbx_inside_any(b1,b2) ( \
5982: ((b1)->a.x <= (b2)->b.x) \
5983: && ((b1)->a.y <= (b2)->b.y) \
5984: && ((b1)->b.x >= (b2)->a.x) \
5985: && ((b1)->b.y >= (b2)->a.y) \
5986: )
5987:
5988: typedef struct Bbxs { /* A set of Bbxs */
5989: int mny; /* if mny==0, then pa==NULL */
5990: Bbx **pa; /* NULL-terminated array (in malloc space) of `mny+1'
5991: pointers to Bbxs (in malloc space) */
5992: int alloc; /* no. slots in pa[] actually allocated (>=mny+1) */
5993: int incr; /* no. slots in pa[] to reallocate at a time */
5994: } Bbxs;
5995:
5996: #define Init_Bbxs {0,NULL,0,512}
5997: #if MAIN
5998: Bbxs empty_Bbxs = Init_Bbxs;
5999: #else
6000: extern Bbxs empty_Bbxs;
6001: #endif
6002:
6003: Sp *alloc_sp();
6004: free_sp();
6005: char *sp_toa(); /* Sp to ascii printable string */
6006: Sp *ato_sp(); /* Sp from ascii printable string */
6007: frda_sps();
6008: Sps *dup_sps();
6009: Sp *append_sp_sps();
6010: Sp *append_sp_spa();
6011: Sp *rotate_Sp(); /* rotate Sp about given fixed-point */
6012: Sp *hshear_Sp(); /* horiz-shear Sp about given fixed-point */
6013: Edge *alloc_edge();
6014: free_edge();
6015: char *edge_toa(); /* Edge to ascii printable string */
6016: Edge *ato_edge(); /* Edge from ascii printable string */
6017: Bbx *alloc_bbx();
6018: Bbx *append_bbx();
6019: Bbxs *dup_bbxs();
6020: char *bbx_toa(); /* Bbx to ascii printable string */
6021: Bbx *ato_bbx(); /* Bbx from ascii printable string */
6022: Bbx *translate_bbx();
6023: boolean bbx_inside_most(); /* Is Bbx 1 mostly inside Bbx 2? */
6024: Bbx *expand_bbx();
6025: 0707070035351137111006640007620000050000010261300476773366600000700000016417Path.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
6026: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
6027: /* The copyright notice does not imply actual or intended publication. */
6028: /* AUTHORS: */
6029: /* H. S. Baird - ATT-BL MH - first versions */
6030: /* Path.c - Path functions */
6031:
6032: #include <errno.h>
6033: #include <stdio.h>
6034: #include <string.h>
6035: #define FILE_TREE_INCL 1
6036: #include "CPU.h"
6037: #include "Path.h"
6038:
6039: #define dbg_FTW (0)
6040:
6041: /* Return full path string in Path *pp, starting at level `sl';
6042: if the level is too deep or the name at level `sl' is null, return null string.
6043: */
6044: char *path_toa(pp,sl)
6045: Path *pp;
6046: int sl; /* starting level: 0 is first */
6047: { int len,lvl;
6048: static char s[MAX_PATH_DEPTH*(32)];
6049: s[0] = '\0';
6050: if( sl<=pp->level && pp->name[sl]!=NULL && pp->name[sl][0]!='\0' ) {
6051: for(lvl=sl; lvl<=pp->level; lvl++) {
6052: strcat(s,pp->name[lvl]);
6053: strcat(s,"/");
6054: };
6055: };
6056: if((len=strlen(s))>0) s[len-1] = '\0';
6057: return(s);
6058: }
6059:
6060: /* no. slashes in a name */
6061: int slashes(n)
6062: char *n;
6063: { register int res;
6064: register char *c;
6065: res=0;
6066: c=n;
6067: while(*c!='\0') {
6068: if(*c=='/') res++;
6069: c++;
6070: };
6071: return(res);
6072: }
6073:
6074: /* basename */
6075: char *bname(n)
6076: char *n;
6077: { register char *res,*c;
6078: res=n-1;
6079: c=n;
6080: while(*c!='\0') {
6081: if(*c=='/') res=c;
6082: c++;
6083: };
6084: return(res+1);
6085: }
6086:
6087: #if CPU==VAX || CPU==CRAY
6088:
6089: int process_file_tree_node(n,s,code,S)
6090: char *n;
6091: struct stat *s;
6092: int code;
6093: struct FTW *S;
6094: /* Uses global `path_process' structure */
6095: { char *out_n;
6096: int persist;
6097: struct stat sbuf;
6098: switch(code) {
6099: case FTW_F: if(dbg_FTW)err("visit file %s %s %d",n,n+(S->base),S->level);
6100: if(S->level>0) {
6101: if(path_process.path.name[S->level]!=NULL)
6102: free(path_process.path.name[S->level]);
6103: path_process.path.name[S->level]=strdup(n+(S->base));
6104: };
6105: path_process.path.level = S->level;
6106: out_n = strdup(path_toa(&path_process.path,0));
6107: if(dbg_FTW)err("file: %s ==> %s",n,out_n);
6108: (*path_process.process)(n,out_n,path_process.arg);
6109: if(out_n!=NULL) free(out_n);
6110: break;
6111: case FTW_SL: if(dbg_FTW)err("visit link %s %s %d",n,n+(S->base),S->level);
6112: S->quit = FTW_FOLLOW; /* follow symbolic link */
6113: break;
6114: case FTW_D: /* pre-visit of directory */
6115: if(dbg_FTW)err("visit dir %s %s %d",n,n+(S->base),S->level);
6116: if(S->level>0) {
6117: if(path_process.path.name[S->level]!=NULL)
6118: free(path_process.path.name[S->level]);
6119: path_process.path.name[S->level]=strdup(n+(S->base));
6120: };
6121: path_process.path.level = S->level;
6122: out_n = path_toa(&path_process.path,0);
6123: if(dbg_FTW)err("dir: %s --> %s",n,out_n);
6124: if(out_n[0]=='\0') /* no output name */ break;
6125: /* ensure directory named out_n exists */
6126: if(stat(out_n,&sbuf)==0) {
6127: /* file exists */
6128: if(!(sbuf.st_mode&S_IFDIR)) {
6129: /* not a directory - try to remove */
6130: if(unlink(out_n)==0) {
6131: if(mkdir(out_n,0777)!=0) {
6132: /* irrecoverable mkdir */
6133: abort("can't mkdir %s",
6134: out_n);
6135: };
6136: }
6137: else { /* irrecoverable unlink */
6138: abort("can't unlink %s",out_n);
6139: };
6140: };
6141: }
6142: else if(errno==ENOENT) {
6143: /* file doesn't exist */
6144: if(mkdir(out_n,0777)!=0) {
6145: /* irrecoverable mkdir */
6146: abort("can't mkdir %s",out_n);
6147: };
6148: }
6149: else { /* irrecoverable stat */
6150: abort("can't stat %s",out_n);
6151: };
6152: break;
6153: case FTW_DP: /* post-visit of directory: ignore it*/
6154: break;
6155: case FTW_DNR:
6156: err("can't read dir %s (FTW_DNR) - ignore it",n);
6157: break;
6158: case FTW_NS:
6159: err("can't stat %s (FTW_NS) - ignore it",n);
6160: break;
6161: case FTW_NSL:
6162: if(0) /* happens if file is missing */
6163: err("can't stat symbolic link %s (FTW_NSL) - ignore it",n);
6164: break;
6165: default:
6166: err("unexpected FTW code %d - ignore it",code);
6167: break;
6168: };
6169: return(0);
6170: }
6171:
6172: #else
6173: #if CPU==MIPS
6174: int process_file_tree_node(n,s,code)
6175: char *n; /* name of the object */
6176: struct stat *s; /* info. about object */
6177: int code;
6178: /* Uses global `path_process' structure */
6179: #define lvl path_process.path.level
6180: { char *out_n;
6181: int persist;
6182: struct stat sbuf;
6183: char *bn;
6184: lvl = slashes(n) - path_process.sl0;
6185: bn = bname(n);
6186: switch(code) {
6187: case FTW_F: if(dbg_FTW) err("visit file %s, bn %s, lvl %d",n,bn,lvl);
6188: if(lvl>0) {
6189: if(path_process.path.name[lvl]!=NULL)
6190: free(path_process.path.name[lvl]);
6191: path_process.path.name[lvl]=strdup(bn);
6192: };
6193: out_n = strdup(path_toa(&path_process.path,0));
6194: if(dbg_FTW)err("file: %s ==> %s",n,out_n);
6195: (*path_process.process)(n,out_n,path_process.arg);
6196: if(out_n!=NULL) free(out_n);
6197: break;
6198: case FTW_D: /* pre-visit of directory */
6199: if(dbg_FTW) err("visit dir %s, bn %s, lvl %d",n,bn,lvl);
6200: if(lvl>0) {
6201: if(path_process.path.name[lvl]!=NULL)
6202: free(path_process.path.name[lvl]);
6203: path_process.path.name[lvl]=strdup(bn);
6204: };
6205: out_n = path_toa(&path_process.path,0);
6206: if(dbg_FTW)err("dir: %s --> %s",n,out_n);
6207: if(out_n[0]=='\0') /* no output name */ break;
6208: /* ensure directory named out_n exists */
6209: if(stat(out_n,&sbuf)==0) {
6210: /* file exists */
6211: if(!(sbuf.st_mode&S_IFDIR)) {
6212: /* not a directory - try to remove */
6213: if(unlink(out_n)==0) {
6214: if(mkdir(out_n,0777)!=0) {
6215: /* irrecoverable mkdir */
6216: abort("can't mkdir %s",
6217: out_n);
6218: };
6219: }
6220: else { /* irrecoverable unlink */
6221: abort("can't unlink %s",out_n);
6222: };
6223: };
6224: }
6225: else if(errno==ENOENT) {
6226: /* file doesn't exist */
6227: if(mkdir(out_n,0777)!=0) {
6228: /* irrecoverable mkdir */
6229: abort("can't mkdir %s",out_n);
6230: };
6231: }
6232: else { /* irrecoverable stat */
6233: abort("can't stat %s",out_n);
6234: };
6235: break;
6236: case FTW_DNR:
6237: err("can't read dir %s (FTW_DNR) - ignore it",n);
6238: break;
6239: case FTW_NS:
6240: err("can't stat %s (FTW_NS) - ignore it",n);
6241: break;
6242: default:
6243: err("unexpected FTW code %d - ignore it",code);
6244: break;
6245: };
6246: return(0);
6247: }
6248:
6249: #endif
6250: #endif
6251:
6252: /* Process every leaf file (non-directory) in the file-tree rooted at `in_ftn'.
6253: If `in_ftn' is itself a leaf, then only it is processed. If it is a directory,
6254: then a corresponding file-tree is built, rooted at `out_ftn', and paths
6255: to its leaves created by `mkdir's as required; for each pair of corresponding
6256: leaf filenames, `process' is called. The filenames have not yet been opened.
6257: If `out_ftn' is the empty string, then no output file-tree will be generated
6258: and the corresponding output filenames will all be null. If `in_ftn' is the
6259: empty string, then `process' is called only once, with the input filename
6260: empty. Pass 'arg' to 'process' as third argument. */
6261: process_file_trees(process,in_ftn,out_ftn,arg)
6262: VOID (*process)();
6263: char *in_ftn; /* may be empty */
6264: char *out_ftn; /* may be empty */
6265: VOID *arg; /* passed to '(*process)()' as 3rd argument */
6266: /* Uses global `path_process' structure */
6267: { int level;
6268: if(in_ftn[0]=='\0') (*process)(in_ftn,out_ftn,arg);
6269: else { if(dbg_FTW) err("process_file_trees(%s,%s)",in_ftn,out_ftn);
6270: path_process.path.level = 0;
6271: path_process.path.name[0] = out_ftn;
6272: path_process.sl0 = slashes(in_ftn);
6273: for(level=1; level<MAX_PATH_DEPTH; level++)
6274: path_process.path.name[level] = NULL;
6275: path_process.process = process;
6276: path_process.arg = arg;
6277: if(ftw(in_ftn,process_file_tree_node,MAX_PATH_DEPTH)<0)
6278: err("ftw error: errno %d",errno);
6279: };
6280: }
6281: 0707070035351137121006640007620000050000010261310476773366700000700000001611Path.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
6282: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
6283: /* The copyright notice does not imply actual or intended publication. */
6284: /* AUTHORS: */
6285: /* H. S. Baird - ATT-BL MH - first versions */
6286:
6287: /* Path.h - Path names */
6288:
6289: #define MAX_PATH_DEPTH (16) /* maximum expected names in path */
6290:
6291: typedef struct Path {
6292: int level; /* current level */
6293: char *name[MAX_PATH_DEPTH]; /* name[0] is output root name;
6294: the rest are basenames (both input
6295: and output) */
6296: } Path;
6297:
6298: typedef struct Path_process {
6299: int sl0; /* no. slashes in input root name */
6300: Path path;
6301: VOID (*process)();
6302: VOID *arg; /* passed as 3rd arg to (*process)() */
6303: } Path_process;
6304:
6305: Path_process path_process; /* controls file-tree processing */
6306:
6307: char *path_toa(); /* see Path.c */
6308: 0707070035351137131006640007620000050000010261330476773367000000700000404335Text.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
6309: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
6310: /* The copyright notice does not imply actual or intended publication. */
6311: /* AUTHORS: */
6312: /* H. S. Baird - ATT-BL MH - first versions */
6313:
6314: /* Text.c - functions for Document-image file ("dim" file) handling
6315:
6316: General Introduction
6317: --------------------
6318:
6319: Dim files describe a document as a collection of records of these types:
6320: Page full page
6321: Block block (often a column) of text
6322: Txtln line of text
6323: Word word
6324: Char character, isolated symbol, `graph'
6325: Interp interpretation of a character (result of classification)
6326: Sfeats scalar features of a character
6327: Shapes local shape features of a character
6328: Bfeats binary indicator features of a character
6329: Blob connected component (maximal subset of 8-connected black pixels)
6330: Lag line-adjacency graph of runs
6331: Run horizontal run of black pixels
6332: Pixel bilevel (black/white) picture element (symbols are expected to
6333: be black against a white background); usually square
6334:
6335: They may be organized hierarchically --
6336: a Page may own : Blocks, Txtlns, Words, Chars, & Blobs
6337: a Block may own : Blocks, Txtlns, Words, Chars, & Blobs
6338: a Txtln may own : Txtlns, Words, Chars, & Blobs
6339: a Word may own : Words, Chars & Blobs
6340: a Char may own : Blobs, Interps, Sfeats, Shapes, & Bfeats
6341: a Blob may own : Runs (variously represented)
6342: a Run owns : black Pixels
6343: Note that the hierarchy is strict except that Blocks, Txtlns, & Words may
6344: own records of their own type. This serves several functions:
6345: -- a Block may own other Blocks, conventionally nested within it, to
6346: represent a physical or logical page layout decomposition;
6347: -- a Txtln may have alternative interpretations & segmentations into Words;
6348: -- a Word may have alternative segmentations into Chars.
6349:
6350: For each record type R, there should exist these data-structures:
6351: R struct
6352: Init_R #define'd initialization string
6353: empty_R an extern ``empty'' (initialized) instance of R
6354: Also there are library functions (in which _R is spelled in lower-case):
6355: R *alloc_R() allocate memory and initialize to ``empty''
6356: free_R(R *) free memory (only of record R, not what it owns)
6357: free_R_etc(R *,ids) free R and what it owns (as specified by `ids')
6358: R *dup_R(R *) return distinct copy, with duplicated contents
6359: R *dup_R_etc(R *,ids) return distinct copy, duplicated contents & parts
6360: char *R_toa(R *) convert to printable ASCII string
6361: frdb_R(FILE *, R *) fread R (binary) from file thru pointer
6362: frdb_R_etc(",",ids) fread R (binary) and what it owns (as specified)
6363: fwrb_R(FILE *, R *) fwrite R (binary) to file thru pointer
6364: fwrb_R_etc(",",ids) fwrite R (binary) and what it owns (as specified)
6365: (some of these may be unimplemented if they haven't yet been needed)
6366:
6367: I/O conventions:
6368: -- frd?_... return one of:
6369: 1 normal & successful
6370: 0 EOF
6371: <0 I/O errors
6372: Quite a few functions don't obey this rule yet.
6373: Many intermediate fns that don't directly perform I/O
6374: don't bother passing back status from fns they call.
6375: Those that perform I/O directly often complain to stderr and exit(2).
6376: The situation is fairly chaotic, and has already caused bugs.
6377:
6378: Generally:
6379: -- An `etc' argument is a set of Ident bits specifying a set of record types;
6380: it is passed along unchanged in calls to other _etc functions.
6381: -- `fwrb_R_etc' fns obey the `etc' instructions carefully, writing only those
6382: record types specified
6383: -- `frdb_R_etc' fns mostly ignore `etc', blindly reading everything they
6384: see (since they aren't clever enough to skip past yet); however, the
6385: Blob-reading fns look at the Runs_?? bits to select a main memory
6386: format for Runs
6387: -- `frdb_R_etc' uses alloc_Y to allocate all new Y
6388: -- `fwrb_R_etc', however, does NOT free anything: this must be done explicitly
6389: afterwards.
6390:
6391: Ownership of a set of records is implemented by two fields in the owner record:
6392: (1) a count of the number of members, and (2) either a ``set'' or a ``list''
6393: pointer:
6394: set: to a NULL-terminated array of pointers to records
6395: list: to the first in a singly-linked, NULL-terminated, chain
6396: sets are used for sets of Blocks, Txtlns, Words, Chars, and Blobs
6397: lists are used for Interpl, and for Blobs owned by Chars, since they tend
6398: to be fewer
6399:
6400: Blobs and Runs are treated more elaborately than other records. Blobs are
6401: collected in lists when owned by Chars, but in sets otherwise --
6402: the motivation was that the Char lists are usually very short, and the malloc
6403: overhead of creating them might be unpleasant -- however, maintaining two
6404: kinds of sets has caused other headaches; it might be good someday to
6405: abolish lists in favor of sets throughout.
6406: Runs can often be compressed to about half the usual size by using char
6407: fields instead of shorts, and this is done automatically when writing to files. There is both a set and a list form of Run.
6408:
6409: The peripheral file format is:
6410: - deliberately decoupled from the internal (main memory) format: i.e.
6411: the main memory structs can be (and are) changed frequently for
6412: purposes of experimentation without forcing frequent reformatting
6413: of the (by now large) backlog of archived files (particularly the
6414: character image databases). To bring such files up-to-date, the program
6415: `renew' should be used: it must be edited to reflect changes since
6416: the last overhaul of the file format.
6417: - designed to be ``scannable'': that is, one can skip rapidly from record
6418: to record (using the Ident headers) without minding the hierarchy.
6419: This is most useful for the graphics editor "met", where it permits
6420: quick response at the outset. It is also used widely in the
6421: off-line training programs, where main memory is at a premium.
6422: - machine-independent: floating-point representations are forced to
6423: fixed point and scaled to integer; all integer representations are
6424: written as a sequence of bytes in a fixed order, via putc()/getc().
6425: fwrite()/fread() are never used for binary I/O. This seems to work
6426: on virtually all UNIX machines. See fioi.h.
6427:
6428: CCITT Group 4 encodings have been implemented and are available
6429: as a peripheral file format for Blobs. They offer a large compression
6430: factor (x8) over RunF and RunFS records, and the CPU overhead is not
6431: excessive. It turns out that the connectivity information represented
6432: explicitly in Run records but lost in ccitt-g4 can be recovered in linear
6433: time and space (see fix_lag()); in practice the extra recovery time is
6434: negligible and the extra space is 0. This is possible because Blobs are
6435: known to be connected: if not, then (I suspect that) superlinear time is
6436: required in general to recover the lag.
6437:
6438: */
6439:
6440: #include <stdio.h>
6441: #include <math.h>
6442: #define LIBC_INCL 1
6443: #include "CPU.h"
6444: #include "stdocr.h"
6445: #include "rle.h"
6446: #include "Text.h"
6447: #include "bitio.h"
6448: #include "CCITT.h"
6449:
6450: long fseek(),lseek();
6451:
6452: #define dbg_fwrb T /* failsafe consistency checking */
6453: #define dbg_frdb T /* failsafe consistency checking */
6454: #define dbg_fwrb_runs F /* announce no. bytes used to write each Blob's Runs */
6455: #define dbg_frdb_runs F /* announce no. bytes used to write each Blob's Runs */
6456:
6457: /* return ASCII string describing ident bits */
6458: char *ident_toa(id)
6459: Ident id;
6460: { static char s[80];
6461: s[0]='\0';
6462: if((id&IsALL)==IsALL) strcat(s,"ALL");
6463: else {
6464: if(id&IsPage) {
6465: strcat(s,"PG");
6466: if(id&(Page_label)) {
6467: strcat(s,".");
6468: if(id&Page_label) strcat(s,"l");
6469: };
6470: }
6471: if(id&IsBlock) {
6472: strcat(s,"BK");
6473: if(id&(Block_wst|Block_label)) {
6474: strcat(s,".");
6475: if(id&Block_wst) strcat(s,"w");
6476: if(id&Block_label) strcat(s,"l");
6477: };
6478: };
6479: if(id&IsTxtln) {
6480: strcat(s,"TL");
6481: if(id&(Txtln_basl|Txtln_size|Txtln_label)) {
6482: strcat(s,".");
6483: if(id&Txtln_basl) strcat(s,"b");
6484: if(id&Txtln_size) strcat(s,"s");
6485: if(id&Txtln_label) strcat(s,"l");
6486: };
6487: };
6488: if(id&IsWord) {
6489: strcat(s,"WD");
6490: if(id&(Word_spelled|Word_label)) {
6491: strcat(s,".");
6492: if(id&Word_spelled) strcat(s,"s");
6493: if(id&Word_label) strcat(s,"l");
6494: };
6495: };
6496: if(id&IsWordInterp) {
6497: strcat(s,"WI");
6498: if(id&(Word_spelled|Word_numeric|Word_initcap|Word_allcaps|Word_hyphens|Word_slashes|Word_termhyp|Word_endsent)) {
6499: strcat(s,".");
6500: if(id&Word_spelled) strcat(s,"s");
6501: if(id&Word_numeric) strcat(s,"n");
6502: if(id&Word_initcap) strcat(s,"i");
6503: if(id&Word_allcaps) strcat(s,"a");
6504: if(id&Word_hyphens) strcat(s,"-");
6505: if(id&Word_slashes) strcat(s,"/");
6506: if(id&Word_termhyp) strcat(s,"h");
6507: if(id&Word_endsent) strcat(s,".");
6508: };
6509: };
6510: if(id&IsChar) {
6511: strcat(s,"CH");
6512: if(id&(Char_spelled|Char_confused|Char_termhyp|Char_omit|Char_label|Char_ranparms)) {
6513: strcat(s,".");
6514: if(id&Char_spelled) strcat(s,"s");
6515: if(id&Char_confused) strcat(s,"c");
6516: if(id&Char_termhyp) strcat(s,"h");
6517: if(id&Char_omit) strcat(s,"o");
6518: if(id&Char_label) strcat(s,"l");
6519: if(id&Char_ranparms) strcat(s,"r");
6520: if(id&Char_split) strcat(s,"S");
6521: if(id&Char_merged) strcat(s,"M");
6522: };
6523: };
6524: if(id&IsInterp) {
6525: strcat(s,"IN");
6526: if(id&Interp_spelled) {
6527: strcat(s,".s");
6528: };
6529: };
6530: if(id&IsBlob) {
6531: strcat(s,"BB");
6532: if( id&(Blob_lm|Blob_rm|Blob_tm|Blob_bm
6533: |Blob_chopt|Blob_chopb|Blob_chopl|Blob_chopr
6534: |Blob_small|Blob_local)
6535: ) {
6536: strcat(s,".");
6537: if(id&(Blob_tm|Blob_bm|Blob_lm|Blob_rm)) {
6538: if(id&Blob_lm) strcat(s,"l");
6539: if(id&Blob_rm) strcat(s,"r");
6540: if(id&Blob_tm) strcat(s,"t");
6541: if(id&Blob_bm) strcat(s,"b");
6542: };
6543: if(id&(Blob_chopt|Blob_chopb|Blob_chopl|Blob_chopr)) {
6544: if(id&Blob_chopl) strcat(s,"L");
6545: if(id&Blob_chopr) strcat(s,"R");
6546: if(id&Blob_chopt) strcat(s,"T");
6547: if(id&Blob_chopb) strcat(s,"B");
6548: };
6549: if(id&Blob_small) strcat(s,"s");
6550: if(id&Blob_local) strcat(s,"o");
6551: };
6552: }
6553: };
6554: return(s);
6555: }
6556:
6557: /* convert a conventional character-code to a record type */
6558: Ident cto_ident(c)
6559: char c;
6560: { Ident type;
6561: switch(c) {
6562: case 'b':
6563: type=IsBlob; break;
6564: case 'B': case 'k':
6565: type=IsBlock; break;
6566: case 'c':
6567: type=IsChar; break;
6568: case 'i':
6569: type=IsInterp; break;
6570: case 'p': case 'P':
6571: type=IsPage; break;
6572: case 'r':
6573: type=IsRun; break;
6574: case 't': case 'l':
6575: type=IsTxtln; break;
6576: case 'w':
6577: type=IsWord; break;
6578: case 'y':
6579: type=IsBdy; break;
6580: };
6581: return(type);
6582: }
6583:
6584: Ident cto_flag(c,type)
6585: char c;
6586: Ident type;
6587: { Ident flag;
6588: flag = IsNONE;
6589: if(type&IsPage) {
6590: switch(c) {
6591: case 'l': flag |= Page_label; break;
6592: };
6593: }
6594: else if(type&IsBlock) {
6595: switch(c) {
6596: case 'w': flag |= Block_wst; break;
6597: case 'l': flag |= Block_label; break;
6598: };
6599: }
6600: else if(type&IsTxtln) {
6601: switch(c) {
6602: case 'b': flag |= Txtln_basl; break;
6603: case 's': flag |= Txtln_size; break;
6604: case 'l': flag |= Txtln_label; break;
6605: };
6606: }
6607: else if(type&IsWord) {
6608: switch(c) {
6609: case 's': flag |= Word_spelled; break;
6610: case 'n': flag |= Word_numeric; break;
6611: case 'i': flag |= Word_initcap; break;
6612: case 'a': flag |= Word_allcaps; break;
6613: case '-': flag |= Word_hyphens; break;
6614: case '/': flag |= Word_slashes; break;
6615: case 'h': flag |= Word_termhyp; break;
6616: case '.': flag |= Word_endsent; break;
6617: case 'l': flag |= Word_label; break;
6618: };
6619: }
6620: else if(type&IsChar) {
6621: switch(c) {
6622: case 's': flag |= Char_spelled; break;
6623: case 'c': flag |= Char_confused; break;
6624: case 'h': flag |= Char_termhyp; break;
6625: case 'o': flag |= Char_omit; break;
6626: case 'l': flag |= Char_label; break;
6627: case 'r': flag |= Char_ranparms; break;
6628: case 'S': flag |= Char_split; break;
6629: case 'M': flag |= Char_merged; break;
6630: };
6631: }
6632: else if(type&IsBlob) {
6633: switch(c) {
6634: case 'B': flag |= Blob_chopb; break;
6635: case 'L': flag |= Blob_chopl; break;
6636: case 'R': flag |= Blob_chopr; break;
6637: case 'T': flag |= Blob_chopt; break;
6638: case 'b': flag |= Blob_bm; break;
6639: case 'l': flag |= Blob_lm; break;
6640: case 'o': flag |= Blob_local; break;
6641: case 'r': flag |= Blob_rm; break;
6642: case 's': flag |= Blob_small; break;
6643: case 't': flag |= Blob_tm; break;
6644: };
6645: }
6646: else if(type&IsInterp) {
6647: switch(c) {
6648: case 's': flag |= Interp_spelled; break;
6649: };
6650: };
6651: return(flag);
6652: }
6653:
6654: #if FRDI
6655: /* read only the Ident of the next record; if EOF, return 0 */
6656: Ident frdb_ident(fp)
6657: FILE *fp;
6658: { Ident ident;
6659: ident = frdi_Ident(fp);
6660: #if dbg_frdb_toa
6661: err("frdb_ident: %s",ident_toa(ident));
6662: #endif
6663: if(feof(fp)) return(0);
6664: else return(ident);
6665: }
6666: #else
6667: /* read only the Ident of the next record; return 0 iff EOF */
6668: Ident frdb_ident(fp)
6669: FILE *fp;
6670: { Ident ident;
6671: int stat;
6672: if((stat=fread(&ident,sizeof(Ident),1,fp))!=1) {
6673: if(stat==0) return(0);
6674: else abort("frdb_ident: can't fread, status %d",stat);
6675: };
6676: if( Readvax ) ident = swapintin(ident);
6677: #if dbg_frdb_toa
6678: err("frdb_ident: %s",ident_toa(ident));
6679: #endif
6680: if(feof(fp)) return(0);
6681: else return(ident);
6682: }
6683: #endif
6684:
6685: #if FRDI
6686: /* read label into malloc space */
6687: char *frdb_label(f)
6688: FILE *f;
6689: { register char *res;
6690: res=frdi_str(f);
6691: #if dbg_frdb_toa
6692: err("frdb_label: \"%s\"",res);
6693: #endif
6694: return(res);
6695: }
6696: #else
6697: /* read label into malloc space */
6698: char *frdb_label(fp)
6699: FILE *fp;
6700: { static char s[MAX_LABEL_LEN];
6701: char *c,*ce,*l;
6702: int ch;
6703: ce=(c=s)+MAX_LABEL_LEN-1;
6704: while((c<ce)&&((ch=getc(fp))!=EOF)&&(ch!='\0')) *(c++) = ch;
6705: *c='\0';
6706: if(c==ce) {
6707: /* label is truncated; find end of it */
6708: while(((ch=getc(fp))!=EOF)&&(ch!='\0')) ;
6709: };
6710: if((l=strdup(s))==NULL)
6711: abort("frdb_label: can't dup char *s[%d]",strlen(s));
6712: #if dbg_frdb_toa
6713: err("frdb_label: \"%s\"",l);
6714: #endif
6715: return(l);
6716: }
6717: #endif
6718:
6719: /* skip label */
6720: fskb_label(fp)
6721: FILE *fp;
6722: { int ch;
6723: while(((ch=getc(fp))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
6724: if(ch==EOF) return(0); else return(1);
6725: }
6726:
6727: /* Skip the REST of this record (the Ident is assumed to have been read),
6728: and return the Ident of the next record in the file;
6729: else return:
6730: 0 EOF
6731: -1 I/O error
6732: -2 not one of: Page, Block, Txtln, Char, Interp
6733: */
6734: char *pp_toa(ppp)
6735: Pp *ppp;
6736: { static char s[30];
6737: sprintf(s,"(%0.2f,%0.2f)",ppp->x,ppp->y);
6738: return(s);
6739: }
6740:
6741: /* return integer string in the range 00-99 */
6742: char *merit_toa(m)
6743: Merit m;
6744: { static char s[3];
6745: int im;
6746: im = (int)(m * 100);
6747: if(im>99) im=99; else if(im<0) im=0;
6748: if(im<10) {
6749: s[0] = '0';
6750: sprintf(s+1,"%d",im);
6751: }
6752: else sprintf(s,"%2d",im);
6753: s[3] = '\0';
6754: return(s);
6755: }
6756:
6757: char *pts_toa(p)
6758: Pts p;
6759: { static char s[10];
6760: sprintf(s,"%g",((int)((p*10.0)+0.5))/10.0);
6761: return(s);
6762: }
6763:
6764: Bdy *alloc_bdy()
6765: { Bdy *p;
6766: if((p=(Bdy *)malloc(sizeof(Bdy)))==NULL)
6767: abort("alloc_bdy: can't malloc");
6768: else { *p = empty_Bdy;
6769: return(p);
6770: };
6771: }
6772:
6773: Bdys *alloc_bdys()
6774: { Bdys *p;
6775: if((p=(Bdys *)malloc(sizeof(Bdys)))==NULL)
6776: abort("alloc_bdys: can't malloc");
6777: else { *p = empty_Bdys;
6778: return(p);
6779: };
6780: }
6781:
6782: char *bdyedge_toa(bep)
6783: BdyEdge *bep;
6784: { static char s[80];
6785: char aps[20];
6786: strcpy(aps,sp_toa(bep->ap));
6787: sprintf(s,"%s,%s p%d c%s a%0.2f",
6788: aps, sp_toa(bep->bp),
6789: bep->per,
6790: pp_toa(&(bep->ctr)),
6791: (bep->ang/PI)*180.0);
6792: return(s);
6793: }
6794:
6795: free_bdyedges(besp)
6796: BdyEdges *besp;
6797: { register BdyEdge *bep,**bepp;
6798: if(besp->pa!=NULL) {
6799: if(besp->mny>0) {
6800: for(bep= *(bepp=besp->pa); bep!=NULL; bep= *(++bepp))
6801: free(bep);
6802: };
6803: free(besp->pa);
6804: };
6805: *besp = empty_BdyEdges;
6806: }
6807:
6808: /* Skip past the "TYPE=document-image\n\n" (or "TYPE=dim\n\n") ASCII header from
6809: file *fp, read and check the Doc record, and, if all's well, return 1.
6810: If an immediate EOF, return 0. If not EOF, and no "TYPE=" header,
6811: leave fp as it was, and return -1. If a malformed "TYPE=" header, leave fp
6812: as it was, and return -2. */
6813: int skip_type(fp)
6814: FILE *fp;
6815: { int ich,stat;
6816: long seek;
6817: #define MAX_TYPE_HDR_LEN (100)
6818: char type_eq[MAX_TYPE_HDR_LEN+1];
6819: register char *pcp,*ccp,*ecp;
6820: int version;
6821:
6822: seek = ftell(fp);
6823: /* test for EOF */
6824: if(feof(fp) || (ich=getc(fp))==EOF)
6825: /* premature EOF*/ return(0);
6826: if((type_eq[0]=ich)!='T') {
6827: /* no "TYPE=" header */
6828: ungetc(ich,fp); /* fast, guaranteed push-back */
6829: return(-1);
6830: };
6831: /* try to read the rest of "TYPE=" */
6832: for(ecp=(ccp=type_eq+1)+4; ccp<ecp; ccp++) {
6833: if(feof(fp) || (ich=getc(fp))==EOF) {
6834: /* no "TYPE=" header */
6835: fseek(fp,seek,0);
6836: return(-1);
6837: }
6838: else *ccp=ich;
6839: }
6840: *ccp='\0';
6841: /* check for "TYPE=" so far */
6842: if(strcmp(type_eq,"TYPE=")==0) {
6843: /* read rest of ASCII header */
6844: ccp=(pcp=type_eq+3)+1; ecp=type_eq+MAX_TYPE_HDR_LEN;
6845: do { ccp++; pcp++;
6846: if((ich=getc(fp))==EOF) {
6847: /* malformed "TYPE=" header */
6848: fseek(fp,seek,0);
6849: return(-2);
6850: }
6851: else *ccp=ich;
6852: }
6853: while(ccp<ecp && (*ccp!='\n'||*pcp!='\n'));
6854: if(ccp==ecp) {
6855: /* malformed "TYPE=" header */
6856: fseek(fp,seek,0);
6857: return(-2);
6858: };
6859: *pcp='\0';
6860: /* check that it is "TYPE=document-image\n\n" or "TYPE=dim\n\n" */
6861: if(strcmp(type_eq,"TYPE=document-image")!=0
6862: && strcmp(type_eq,"TYPE=dim")!=0) {
6863: /* malformed "TYPE=" header */
6864: fseek(fp,seek,0);
6865: return(-2);
6866: };
6867: #if dbg_frdb_toa
6868: err("skip_type: \"%s\\n\\n\"",type_eq);
6869: #endif
6870: return(1); /* normal and successful TYPE= header */
6871: }
6872: else { /* no "TYPE=" header */
6873: fseek(fp,seek,0);
6874: return(-1);
6875: };
6876: }
6877:
6878: Doc *alloc_doc()
6879: { Doc *p;
6880: if((p=(Doc *)malloc(sizeof(Doc)))==NULL)
6881: abort("alloc_doc: can't malloc");
6882: else { *p = empty_Doc;
6883: return(p);
6884: };
6885: }
6886:
6887: char *doc_toa(p)
6888: Doc *p;
6889: { static char s[80];
6890: sprintf(s,"Doc v%d p%d l%s",
6891: p->version,
6892: p->ps.mny,
6893: (p->l!=NULL)? p->l: "");
6894: return(s);
6895: }
6896:
6897: #if FWRI
6898: /* write the given doc (record only) */
6899: fwrb_doc(f,p)
6900: FILE *f;
6901: Doc *p;
6902: { int stat;
6903: fwri_uint1(f,p->version);
6904: fwri_uint2(f,p->ps.mny);
6905: #if dbg_fwrb_toa
6906: err("fwrb_doc: %s",doc_toa(p));
6907: #endif
6908: if(p->l!=NULL) {
6909: fwri_ch(f,'l');
6910: fwrb_label(f,p->l);
6911: }
6912: else fwri_ch(f,'\0');
6913: }
6914: #else
6915: fwrb_doc(f,p)
6916: FILE *f;
6917: Doc *p;
6918: {}
6919: #endif
6920:
6921: #if FRDI
6922: /* read a Doc record (only) - it must be next in the file;
6923: don't immediately read its parts; return 0 iff immediate EOF.
6924: Check for correct version no: if fails, abort. */
6925: int frdb_doc(f,p)
6926: FILE *f;
6927: Doc *p;
6928: { char qlabel;
6929: *p = empty_Doc;
6930: if(feof(f))
6931: return(0);
6932: p->version=frdi_uint1(f);
6933: p->ps.mny=frdi_uint2(f);
6934: if((qlabel=frdi_ch(f))=='l')
6935: p->l=frdb_label(f);
6936: #if dbg_frdb_toa
6937: err("frdb_doc: %s",doc_toa(p));
6938: #endif
6939: if(ferror(f)) return(-errno); else return(1);
6940: }
6941: #else
6942: int frdb_doc(f,p)
6943: FILE *f;
6944: Doc *p;
6945: { return(1);
6946: }
6947: #endif
6948:
6949: #if FWRI
6950: /* Write the initial Doc record */
6951: put_doc(f)
6952: FILE *f;
6953: { Doc doc;
6954: doc = empty_Doc;
6955: doc.version = DIM_VERSION;
6956: doc.ps.mny = 1;
6957: fwrb_doc(f,&doc);
6958: }
6959: #else
6960: put_doc(f)
6961: FILE *f;
6962: {}
6963: #endif
6964:
6965: #if FRDI
6966: /* read, check, discard, and skip past the Doc record */
6967: int skip_doc(f)
6968: FILE *f;
6969: { Doc doc;
6970: frdb_doc(f,&doc);
6971: if(doc.version!=DIM_VERSION)
6972: abort("skip_doc: version %d != DIM_VERSION %d",
6973: doc.version,DIM_VERSION);
6974: if(doc.l!=NULL) free(doc.l);
6975: return(1);
6976: }
6977: #else
6978: int skip_doc(f)
6979: FILE *f;
6980: { Doc doc;
6981: return(1);
6982: }
6983: #endif
6984:
6985: Page *alloc_page()
6986: { Page *p;
6987: if((p=(Page *)malloc(sizeof(Page)))==NULL)
6988: abort("alloc_page: can't malloc");
6989: alloc_census(Page,1);
6990: *p = empty_Page;
6991: return(p);
6992: }
6993:
6994: char *page_toa(p)
6995: Page *p;
6996: { static char s[80];
6997: sprintf(s,"%s bx%s res%d,%d sk%0.2f,sh%0.2f bk%d l%d c%d b%d",
6998: ident_toa(p->ident),
6999: bbx_toa(&(p->bx)),
7000: p->res_x,p->res_y,
7001: (p->skew/PI)*180.0,
7002: (p->shear/PI)*180.0,
7003: p->bks.mny,p->ls.mny,p->cs.mny,p->bs.mny,
7004: (p->l!=NULL)? p->l: "");
7005: return(s);
7006: }
7007:
7008: #if FWRI
7009: /* write the given page (record only) */
7010: fwrb_page(f,p)
7011: FILE *f;
7012: Page *p;
7013: { int stat;
7014: #if dbg_fwrb
7015: if(f==stdout||f==stderr||ftell(f)<=0L) {
7016: fprintf(f,"TYPE=dim\n\n");
7017: #if dbg_fwrb_toa
7018: err("fwrb_page: \"TYPE=dim\\n\\n\"");
7019: #endif
7020: put_doc(f);
7021: };
7022: if((!(p->ident&IsPage))||(p->ident&(IsALL&(~IsPage))))
7023: err("fwrb_page: %s",page_toa(p));
7024: if(p->ident&Page_label && p->l==NULL) {
7025: err("fwrb_page: Page_label set but .l==NULL");
7026: p->ident &= ~Page_label;
7027: };
7028: #endif
7029: fwri_Ident(f,p->ident);
7030: fwri_Bbx(f,&(p->bx));
7031: fwri_int2(f,p->res_x);
7032: fwri_int2(f,p->res_y);
7033: fwri_Radians(f,p->skew);
7034: fwri_Radians(f,p->shear);
7035: fwri_uint2(f,p->bks.mny);
7036: fwri_uint2(f,p->ls.mny);
7037: fwri_uint2(f,p->ws.mny);
7038: fwri_uint2(f,p->cs.mny);
7039: fwri_uint3(f,p->bs.mny);
7040: #if dbg_fwrb_toa
7041: err("fwrb_page: %s",page_toa(p));
7042: #endif
7043: if(p->ident&Page_label) fwrb_label(f,p->l);
7044: }
7045: #else
7046: /* write the given page (record only) */
7047: fwrb_page(fp,pp)
7048: FILE *fp;
7049: Page *pp;
7050: { PageF pf;
7051: int stat;
7052: #if dbg_fwrb
7053: if((!(pp->ident&IsPage))||(pp->ident&(IsALL&(~IsPage))))
7054: err("fwrb_page: %s",page_toa(pp));
7055: #endif
7056: memset(&pf,'\0',sizeof(pf));
7057: pf.ident = pp->ident;
7058: pf.res_x=pp->res_x;
7059: pf.res_y=pp->res_y;
7060: pf.bx=pp->bx;
7061: pf.skew=pp->skew;
7062: pf.shear=pp->shear;
7063: pf.bkmny=pp->bks.mny;
7064: pf.lmny=pp->ls.mny;
7065: pf.wmny=pp->ws.mny;
7066: pf.cmny=pp->cs.mny;
7067: pf.bmny=pp->bs.mny;
7068: if(fp==stdout||fp==stderr||ftell(fp)<=0L) {
7069: fprintf(fp,"TYPE=document-image\n\n");
7070: #if dbg_fwrb_toa
7071: err("fwrb_page: \"TYPE=document-image\\n\\n\"");
7072: #endif
7073: };
7074: if((stat=fwrite(&pf,sizeof(PageF),1,fp))!=1)
7075: abort("fwrb_page: can't fwrite - status %d",stat);
7076: #if dbg_fwrb_toa
7077: err("fwrb_page: %s",page_toa(pp));
7078: #endif
7079: if(pf.ident&Page_label) fwrb_label(fp,pp->l);
7080: }
7081: #endif
7082:
7083: /* write a page and its specified parts */
7084: fwrb_page_etc(fp,pp,etc)
7085: FILE *fp;
7086: Page *pp;
7087: Ident etc;
7088: { static Ident parts = (IsBlock|IsTxtln|IsWord|IsChar|IsBlob);
7089: Page pg;
7090: if((etc&parts)!=parts) /* write selected parts */ {
7091: pg = *pp;
7092: if(!(etc&IsBlock)) pg.bks.mny=0;
7093: if(!(etc&IsTxtln)) pg.ls.mny=0;
7094: if(!(etc&IsWord)) pg.ws.mny=0;
7095: if(!(etc&IsChar)) pg.cs.mny=0;
7096: if(!(etc&IsBlob)) pg.bs.mny=0;
7097: pp = &pg; /* write modified record */
7098: };
7099: fwrb_page(fp,pp);
7100: fwrb_blocks_etc(fp,pp->bks,etc);
7101: fwrb_txtlns_etc(fp,pp->ls,etc);
7102: fwrb_words_etc(fp,pp->ws,etc);
7103: fwrb_chars_etc(fp,pp->cs,etc);
7104: fwrb_blobs_etc(fp,pp->bs,etc);
7105: }
7106:
7107: /* write a page and its specified parts, ASCII (INCOMPLETE) */
7108: fwra_page_etc(fp,pp,etc)
7109: FILE *fp;
7110: Page *pp;
7111: Ident etc;
7112: { static Ident parts = (IsBlock|IsTxtln|IsWord|IsChar|IsBlob);
7113: Page pg;
7114: if((etc&parts)!=parts) /* write selected parts */ {
7115: pg = *pp;
7116: if(!(etc&IsBlock)) pg.bks.mny=0;
7117: if(!(etc&IsTxtln)) pg.ls.mny=0;
7118: if(!(etc&IsWord)) pg.ws.mny=0;
7119: if(!(etc&IsChar)) pg.cs.mny=0;
7120: if(!(etc&IsBlob)) pg.bs.mny=0;
7121: pp = &pg; /* write modified record */
7122: };
7123: if(etc&IsPage) fwrb_page(fp,pp);
7124: fwrb_blocks_etc(fp,pp->bks,etc);
7125: fwrb_txtlns_etc(fp,pp->ls,etc);
7126: fwrb_words_etc(fp,pp->ws,etc);
7127: fwrb_chars_etc(fp,pp->cs,etc);
7128: fwrb_blobs_etc(fp,pp->bs,etc);
7129: }
7130:
7131: #if FRDI
7132: /* read a Page record (only) - it must be next in the file;
7133: don't immediately read its parts; return 0 iff immediate EOF */
7134: int frdb_page(f,p)
7135: FILE *f;
7136: Page *p;
7137: { char *pfc; /* for debugging */
7138: int stat;
7139: switch(skip_type(f)) {
7140: case 1: /* "TYPE=" header */
7141: skip_doc(f);
7142: break;
7143: case 0: /* immediate EOF */
7144: return(0);
7145: break;
7146: case -1: /* no "TYPE=" header */
7147: break;
7148: case -2: /* garbled "TYPE=" header */
7149: abort("frdb_page: garbled \"TYPE=\" header");
7150: break;
7151: };
7152: *p = empty_Page;
7153: if(feof(f))
7154: return(0);
7155: p->ident=frdi_Ident(f);
7156: frdi_Bbx(f,&(p->bx));
7157: p->res_x=frdi_int2(f);
7158: p->res_y=frdi_int2(f);
7159: p->skew=frdi_Radians(f);
7160: p->shear=frdi_Radians(f);
7161: p->bks.mny=frdi_uint2(f);
7162: p->ls.mny=frdi_uint2(f);
7163: p->ws.mny=frdi_uint2(f);
7164: p->cs.mny=frdi_uint2(f);
7165: p->bs.mny=frdi_uint3(f);
7166: #if dbg_frdb
7167: if((!(p->ident&IsPage))||(p->ident&(IsALL&(~IsPage))))
7168: err("frdb_page: %s",page_toa(p));
7169: #endif
7170: #if dbg_frdb_toa
7171: err("frdb_page: %s",page_toa(p));
7172: #endif
7173: if(p->ident&Page_label) p->l = frdb_label(f);
7174: if(ferror(f)) return(-errno); else return(1);
7175: }
7176: #else
7177: /* read a Page record (only) - it must be next in the file;
7178: don't immediately read its parts; return T iff not early EOF */
7179: int frdb_page(fp,pp)
7180: FILE *fp;
7181: Page *pp;
7182: { PageF pf;
7183: char *pfc; /* for debugging */
7184: int stat;
7185: if((stat=skip_type(fp))!=1 /* "TYPE=" header */
7186: && stat!=-1 /* no "TYPE=" header */ ) {
7187: /* premature EOF or error */ return(stat);
7188: };
7189: if((stat=fread(&pf,sizeof(PageF),1,fp))!=1)
7190: /* premature EOF*/ return(stat);
7191: pfc = (char *)&pf;
7192: *pp = empty_Page;
7193: pp->ident=pf.ident;
7194: pp->res_x=pf.res_x;
7195: pp->res_y=pf.res_y;
7196: pp->bx=pf.bx;
7197: pp->skew=pf.skew;
7198: pp->shear=pf.shear;
7199: pp->bks.mny = pf.bkmny; pp->bks.bpa=NULL;
7200: pp->ls.mny = pf.lmny; pp->ls.lpa=NULL;
7201: pp->ws.mny = pf.wmny; pp->ws.wpa=NULL;
7202: pp->cs.mny = pf.cmny; pp->cs.cpa=NULL;
7203: pp->bs.mny = pf.bmny; pp->bs.bpa=NULL;
7204: #if dbg_frdb_toa
7205: err("frdb_page: %s",page_toa(pp));
7206: #endif
7207: if(pp->ident&Page_label) pp->l = frdb_label(fp);
7208: #if dbg_frdb
7209: if((!(pp->ident&IsPage))||(pp->ident&(IsALL&(~IsPage))))
7210: err("frdb_page: %s",page_toa(pp));
7211: #endif
7212: return(stat);
7213: }
7214: #endif
7215:
7216: /* Read a page and selected parts */
7217: int frdb_page_etc(fp,pp,etc)
7218: FILE *fp;
7219: Page *pp;
7220: Ident etc;
7221: { int stat;
7222: if((etc&IsALL)==IsALL) {
7223: long here;
7224: /* In order to minimize malloc time to read an often huge file,
7225: malloc and then free storage roughly equal to what's needed */
7226: if( /* DEFEATED */ F && (here=ftell(fp))>=0 && fseek(fp,0,2)>=0 ) {
7227: /* *fp is connected to a file, not a pipe */
7228: free(malloc(ftell(fp)));
7229: fseek(fp,here,0);
7230: };
7231: };
7232: if((stat=frdb_page(fp,pp))!=1) return(stat);
7233: if(etc&IsBlock && pp->bks.mny>0)
7234: frdb_blocks_etc(fp,&(pp->bks),etc);
7235: else pp->bks = empty_Blocks;
7236: if(etc&IsTxtln && pp->ls.mny>0)
7237: frdb_txtlns_etc(fp,&(pp->ls),etc);
7238: else pp->ls = empty_Txtlns;
7239: if(etc&IsWord && pp->ws.mny>0)
7240: frdb_words_etc(fp,&(pp->ws),etc);
7241: else pp->ws = empty_Words;
7242: if(etc&IsChar && pp->cs.mny>0)
7243: frdb_chars_etc(fp,&(pp->cs),etc);
7244: else pp->cs = empty_Chars;
7245: if(etc&IsBlob && pp->bs.mny>0)
7246: frdb_blobs_etc(fp,&(pp->bs),etc);
7247: else pp->bs = empty_Blobs;
7248: return(1/*normal return*/);
7249: }
7250:
7251: free_page_etc(p,etc)
7252: Page *p;
7253: Ident etc;
7254: { free_blocks_etc(&(p->bks),etc);
7255: free_txtlns_etc(&(p->ls),etc);
7256: free_words_etc(&(p->ws),etc);
7257: free_chars_etc(&(p->cs),etc);
7258: free_blobs_etc(&(p->bs),etc);
7259: if(p->ident&Page_label && p->l!=NULL) {
7260: free(p->l); p->l=NULL; p->ident &= ~Page_label;
7261: };
7262: if(etc&IsPage) {
7263: free(p);
7264: free_census(Page,1);
7265: };
7266: }
7267:
7268: /* return a pointer to a distinct and duplicate copy of record Page *p,
7269: created out of malloc space */
7270: Page *dup_page(p)
7271: Page *p;
7272: { Page *dup;
7273: dup=alloc_page(); *dup = *p; return(dup);
7274: }
7275:
7276: /* Return a pointer to a distinct and duplicate copy of Page *p, and its parts
7277: as specified by `etc', created out of malloc space. */
7278: Page *dup_page_etc(p,etc)
7279: Page *p;
7280: Ident etc;
7281: { Page *dup;
7282: dup = dup_page(p);
7283: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(p->bs),etc);
7284: else dup->bs = empty_Blobs;
7285: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(p->cs),etc);
7286: else dup->cs = empty_Chars;
7287: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(p->ws),etc);
7288: else dup->ws = empty_Words;
7289: if(etc&IsTxtln&&dup->ls.mny>0) dup->ls = *dup_txtlns_etc(&(p->ls),etc);
7290: else dup->ls = empty_Txtlns;
7291: if(etc&IsBlock&&dup->bks.mny>0) dup->bks = *dup_blocks_etc(&(p->bks),etc);
7292: else dup->bks = empty_Blocks;
7293: return(dup);
7294: }
7295:
7296: Block *alloc_block()
7297: { Block *p;
7298: if((p=(Block *)malloc(sizeof(Block)))==NULL)
7299: abort("alloc_block: can't malloc");
7300: alloc_census(Block,1);
7301: *p = empty_Block;
7302: return(p);
7303: }
7304:
7305: char *block_toa(p)
7306: Block *p;
7307: { static char s[80];
7308: sprintf(s,"%s bx%s sk%0.2f,sh%0.2f wst%0.2f m%s bk%d l%d w%d c%d b%d",
7309: ident_toa(p->ident),
7310: bbx_toa(&(p->bx)),
7311: p->skew/DtoR,
7312: p->shear/DtoR,
7313: p->wst,
7314: merit_toa(p->m),
7315: p->bks.mny,p->ls.mny,p->ws.mny,p->cs.mny,p->bs.mny,
7316: (p->l!=NULL)? p->l: "");
7317: return(s);
7318: }
7319:
7320: #if FWRI
7321: fwrb_block(f,p)
7322: FILE *f;
7323: Block *p;
7324: { int stat;
7325: #if dbg_fwrb
7326: if((!(p->ident&IsBlock))||(p->ident&(IsALL&(~IsBlock))))
7327: err("fwrb_block: %s",block_toa(p));
7328: if(p->ident&Block_label && p->l==NULL) {
7329: err("fwrb_page: Block_label set but .l==NULL");
7330: p->ident &= ~Block_label;
7331: };
7332: #endif
7333: fwri_Ident(f,p->ident);
7334: fwri_Bbx(f,&(p->bx));
7335: fwri_Radians(f,p->skew);
7336: fwri_Radians(f,p->shear);
7337: fwri_Ems(f,p->wst);
7338: fwri_Merit(f,p->m);
7339: fwri_uint2(f,p->bks.mny);
7340: fwri_uint2(f,p->ls.mny);
7341: fwri_uint2(f,p->ws.mny);
7342: fwri_uint2(f,p->cs.mny);
7343: fwri_uint3(f,p->bs.mny);
7344: #if dbg_fwrb_toa
7345: err("fwrb_block: %s",block_toa(p));
7346: #endif
7347: if(p->ident&Block_label) fwrb_label(f,p->l);
7348: }
7349: #else
7350: fwrb_block(fp,bkp)
7351: FILE *fp;
7352: Block *bkp;
7353: { BlockF bf;
7354: int stat;
7355: #if dbg_fwrb
7356: if((!(bkp->ident&IsBlock))||(bkp->ident&(IsALL&(~IsBlock))))
7357: err("fwrb_block: %s",block_toa(bkp));
7358: #endif
7359: memset(&bf,'\0',sizeof(bf));
7360: bf.ident = bkp->ident;
7361: bf.bx = bkp->bx;
7362: bf.wst = bkp->wst;
7363: bf.skew = bkp->skew;
7364: bf.shear = bkp->shear;
7365: bf.lmny = bkp->ls.mny;
7366: bf.wmny = bkp->ws.mny;
7367: bf.cmny = bkp->cs.mny;
7368: bf.bmny = bkp->bs.mny;
7369: #if dbg_fwrb_toa
7370: err("fwrb_block: %s",block_toa(bkp));
7371: #endif
7372: if((stat=fwrite(&bf,sizeof(BlockF),1,fp))!=1)
7373: abort("fwrb_block: can't fwrite - status %d",stat);
7374: }
7375: #endif
7376:
7377: fwrb_blocks_etc(fp,bks,etc)
7378: FILE *fp;
7379: Blocks bks;
7380: Ident etc;
7381: { register Block *bkp,**bkpp;
7382: if(bks.mny>0) for(bkp= *(bkpp=bks.bpa); bkp!=NULL; bkp= *(++bkpp))
7383: fwrb_block_etc(fp,bkp,etc);
7384: }
7385:
7386: fwrb_block_etc(fp,bkp,etc)
7387: FILE *fp;
7388: Block *bkp;
7389: Ident etc;
7390: { static Ident parts = (IsTxtln|IsWord|IsChar|IsBlob);
7391: Block bk;
7392: if((etc&parts)!=parts) /* write selected parts */ {
7393: bk = *bkp;
7394: if(!(etc&IsTxtln)) bk.ls.mny=0;
7395: if(!(etc&IsWord)) bk.ws.mny=0;
7396: if(!(etc&IsChar)) bk.cs.mny=0;
7397: if(!(etc&IsBlob)) bk.bs.mny=0;
7398: bkp = &bk; /* write modified record */
7399: };
7400: fwrb_block(fp,bkp);
7401: fwrb_txtlns_etc(fp,bkp->ls,etc);
7402: fwrb_words_etc(fp,bkp->ws,etc);
7403: fwrb_chars_etc(fp,bkp->cs,etc);
7404: fwrb_blobs_etc(fp,bkp->bs,etc);
7405: }
7406:
7407: #if FRDI
7408: int frdb_block(f,p)
7409: FILE *f;
7410: Block *p;
7411: { *p = empty_Block;
7412: if(feof(f))
7413: return(0);
7414: p->ident=frdi_Ident(f);
7415: frdi_Bbx(f,&(p->bx));
7416: p->skew=frdi_Radians(f);
7417: p->shear=frdi_Radians(f);
7418: p->wst=frdi_Ems(f);
7419: p->m=frdi_Merit(f);
7420: p->bks.mny=frdi_uint2(f);
7421: p->ls.mny=frdi_uint2(f);
7422: p->ws.mny=frdi_uint2(f);
7423: p->cs.mny=frdi_uint2(f);
7424: p->bs.mny=frdi_uint3(f);
7425: #if dbg_frdb_toa
7426: err("frdb_block: %s",block_toa(p));
7427: #endif
7428: #if dbg_frdb
7429: if((!(p->ident&IsBlock))||(p->ident&(IsALL&(~IsBlock))))
7430: err("frdb_block: %s",block_toa(p));
7431: #endif
7432: if(p->ident&Block_label) p->l = frdb_label(f);
7433: if(ferror(f)) return(-errno); else return(1);
7434: }
7435: #else
7436: int frdb_block(fp,bkp)
7437: FILE *fp;
7438: Block *bkp;
7439: { BlockF bf;
7440: int stat;
7441: if((stat=fread(&bf,sizeof(BlockF),1,fp))!=1)
7442: abort("frdb_block: can't fread - status %d",stat);
7443: *bkp = empty_Block;
7444: bkp->ident = bf.ident;
7445: bkp->bx = bf.bx;
7446: bkp->skew = bf.skew;
7447: bkp->shear = bf.shear;
7448: bkp->wst = bf.wst;
7449: bkp->ls.mny = bf.lmny;
7450: bkp->ws.mny = bf.wmny;
7451: bkp->cs.mny = bf.cmny;
7452: bkp->bs.mny = bf.bmny;
7453: #if dbg_frdb
7454: if((!(bkp->ident&IsBlock))||(bkp->ident&(IsALL&(~IsBlock))))
7455: err("frdb_block: %s",block_toa(bkp));
7456: #endif
7457: #if dbg_frdb_toa
7458: err("frdb_block: %s",block_toa(bkp));
7459: #endif
7460: if(bkp->ident&Block_label) bkp->l = frdb_label(fp);
7461: if(ferror(fp)) return(-errno); else return(1);
7462: }
7463: #endif
7464:
7465: frdb_block_etc(fp,bkp,etc)
7466: FILE *fp;
7467: Block *bkp;
7468: Ident etc;
7469: { BlockF bf;
7470: int stat;
7471: frdb_block(fp,bkp);
7472: if(etc&IsTxtln && bkp->ls.mny>0)
7473: frdb_txtlns_etc(fp,&(bkp->ls),etc);
7474: else bkp->ls = empty_Txtlns;
7475: if(etc&IsWord && bkp->ws.mny>0)
7476: frdb_words_etc(fp,&(bkp->ws),etc);
7477: else bkp->ws = empty_Words;
7478: if(etc&IsChar && bkp->cs.mny>0)
7479: frdb_chars_etc(fp,&(bkp->cs),etc);
7480: else bkp->cs = empty_Chars;
7481: if(etc&IsBlob && bkp->bs.mny>0)
7482: frdb_blobs_etc(fp,&(bkp->bs),etc);
7483: else bkp->bs = empty_Blobs;
7484: if(ferror(fp)) return(-errno); else return(1);
7485: }
7486:
7487: /* read number of blocks, and their parts */
7488: frdb_blocks_etc(fp,bksp,etc)
7489: FILE *fp;
7490: Blocks *bksp;
7491: Ident etc;
7492: { int bi;
7493: register Block *bkp,**bkpp;
7494: if(bksp->mny<=0) {
7495: *bksp = empty_Blocks;
7496: return(1);
7497: };
7498:
7499: if((bkpp=bksp->bpa=(Block **)malloc((bksp->mny+1)*sizeof(Block *)))==NULL)
7500: abort("can't alloc Blocks.bpa array");
7501: for(bi=0; bi<bksp->mny; bi++) {
7502: *(bkpp++) = bkp = alloc_block();
7503: frdb_block_etc(fp,bkp,etc);
7504: };
7505: *bkpp = NULL;
7506: if(ferror(fp)) return(-errno); else return(1);
7507: }
7508:
7509: free_block_etc(p,etc)
7510: Block *p;
7511: Ident etc;
7512: { free_txtlns_etc(&(p->ls),etc);
7513: free_words_etc(&(p->ws),etc);
7514: free_chars_etc(&(p->cs),etc);
7515: free_blobs_etc(&(p->bs),etc);
7516: if(p->ident&Block_label && p->l!=NULL) {
7517: free(p->l); p->l=NULL; p->ident &= ~Block_label;
7518: };
7519: if(etc&IsBlock) {
7520: free(p);
7521: free_census(Block,1);
7522: };
7523: }
7524:
7525: /* Unconditionally free the malloc-space array of pointers, and empty the set.
7526: Don't free the records that it owned.
7527: */
7528: free_blocks(p)
7529: Blocks *p;
7530: { if(p->bpa!=NULL) { free(p->bpa); p->bpa = NULL; }
7531: p->mny = 0;
7532: }
7533:
7534: free_blocks_etc(p,etc)
7535: Blocks *p;
7536: Ident etc;
7537: { register Block *bkp,**bkpp;
7538: if(p->mny>0&&(etc&IsBlock))
7539: for(bkp= *(bkpp=p->bpa); bkp!=NULL; bkp= *(++bkpp))
7540: free_block_etc(bkp,etc);
7541: free_blocks(p);
7542: }
7543:
7544: /* return a pointer to a distinct and duplicate copy of *bkp,
7545: created out of malloc space */
7546: Block *dup_block(bkp)
7547: Block *bkp;
7548: { Block *dup;
7549: dup=alloc_block();
7550: *dup = *bkp;
7551: return(dup);
7552: }
7553:
7554: /* Return a pointer to a distinct and duplicate copy of *bkp, and its parts
7555: as specified by `etc', created out of malloc space. */
7556: Block *dup_block_etc(bkp,etc)
7557: Block *bkp;
7558: Ident etc;
7559: { Block *dup;
7560: dup = dup_block(bkp);
7561: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(bkp->bs),etc);
7562: else dup->bs = empty_Blobs;
7563: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(bkp->cs),etc);
7564: else dup->cs = empty_Chars;
7565: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(bkp->ws),etc);
7566: else dup->ws = empty_Words;
7567: if(etc&IsTxtln&&dup->ls.mny>0) dup->ls = *dup_txtlns_etc(&(bkp->ls),etc);
7568: else dup->ls = empty_Txtlns;
7569: return(dup);
7570: }
7571:
7572: /* Return a pointer to a distinct local static duplicate of non-empty *bksp.
7573: Its bkpa array is created newly out of malloc space.
7574: If etc&IsBlock, all its Blocks are also duplicated,
7575: else the contents of bkpa point to the old unduplicated Blocks.
7576: */
7577: Blocks *dup_blocks_etc(bksp,etc)
7578: Blocks *bksp;
7579: Ident etc; /* parts to duplicate */
7580: { static Blocks dup;
7581: register Block **bkpp,**dpp;
7582: if((dup.mny = bksp->mny)<=0) dup = empty_Blocks;
7583: else { if((dup.bpa=(Block **)malloc((dup.mny+1)*sizeof(Block *)))==NULL)
7584: abort("can't dup bks.bpa");
7585: for(bkpp=bksp->bpa,dpp=dup.bpa; *bkpp!=NULL; bkpp++,dpp++) {
7586: if(etc&IsBlock) *dpp = dup_block_etc(*bkpp,etc);
7587: else *dpp = *bkpp;
7588: };
7589: *dpp = NULL;
7590: };
7591: return(&dup);
7592: }
7593:
7594: /* Append a block to the end of a blocks set.
7595: Return appended Block *. */
7596: Block *append_block(bkp,bksp)
7597: Block *bkp;
7598: Blocks *bksp;
7599: { register Block *rp,**rpp,**npp;
7600: if(bksp->mny==0) {
7601: if((bksp->bpa=(Block **)malloc(2*sizeof(Block *)))==NULL)
7602: abort("append_block: can't malloc bksp->bpa");
7603: }
7604: else { if((bksp->bpa=(Block **)realloc(
7605: bksp->bpa,
7606: (bksp->mny+2)*sizeof(Block *))
7607: )==NULL)
7608: abort("append_block: can't realloc bksp->bpa");
7609: };
7610: bksp->bpa[bksp->mny] = bkp;
7611: bksp->bpa[++bksp->mny] = NULL;
7612: return(bkp);
7613: }
7614:
7615: /* remove a block from a blocks set */
7616: remove_block(bkp,bksp)
7617: Block *bkp;
7618: Blocks *bksp;
7619: { register Block *rp,**rpp,**npp;
7620: if(bksp->mny==0) err("can't remove Block - Blocks empty");
7621: else { for(rp= *(rpp=bksp->bpa); rp!=NULL; rp= *(++rpp)) if(rp==bkp) break;
7622: if(rp==NULL) err("can't remove Block - not found");
7623: else { /* move later entries up */
7624: npp=rpp+1;
7625: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
7626: if((--(bksp->mny))==0) {free(bksp->bpa); bksp->bpa=NULL;};
7627: /* don't bother to realloc downwards */
7628: };
7629: };
7630: }
7631:
7632: ConstPitch *alloc_constpitch()
7633: { ConstPitch *p;
7634: if((p=(ConstPitch *)malloc(sizeof(ConstPitch)))==NULL)
7635: abort("can't alloc ConstPitch");
7636: else { *p = empty_ConstPitch;
7637: return(p);
7638: };
7639: }
7640:
7641: char *constpitch_toa(p)
7642: ConstPitch *p;
7643: { static char s[80];
7644: sprintf(s,"{w%.3f,o%d,r%.1f}",
7645: p->w,p->o,p->r);
7646: return(s);
7647: }
7648:
7649: free_constpitch(p)
7650: ConstPitch *p;
7651: { free(p);
7652: }
7653:
7654: Txtln *alloc_txtln()
7655: { Txtln *p;
7656: if((p=(Txtln *)malloc(sizeof(Txtln)))==NULL)
7657: abort("can't alloc Txtln");
7658: alloc_census(Txtln,1);
7659: *p = empty_Txtln;
7660: return(p);
7661: }
7662:
7663: char *txtln_toa(p)
7664: Txtln *p;
7665: { static char s[80];
7666: sprintf(s,"%s bx%s sz%s ba%d cw%s m%s l%d w%d c%d b%d %s",
7667: ident_toa(p->ident),
7668: bbx_toa(&(p->bx)),
7669: pts_toa(p->size),
7670: p->basl,
7671: /** proj omitted **/
7672: ((p->cp!=NULL)? constpitch_toa(p->cp): "0"),
7673: merit_toa(p->m),
7674: p->ls.mny,p->ws.mny,p->cs.mny,p->bs.mny,
7675: (p->l!=NULL)? p->l: "");
7676: return(s);
7677: }
7678:
7679: #if FWRI
7680: fwrb_txtln(f,p)
7681: FILE *f;
7682: Txtln *p;
7683: {
7684: #if dbg_fwrb
7685: if((!(p->ident&IsTxtln))||(p->ident&(IsALL&(~IsTxtln))))
7686: err("fwrb_txtln: %s",txtln_toa(p));
7687: if(p->ident&Txtln_label && p->l==NULL) {
7688: err("fwrb_page: Txtln_label set but .l==NULL");
7689: p->ident &= ~Txtln_label;
7690: };
7691: #endif
7692: fwri_Ident(f,p->ident);
7693: fwri_Bbx(f,&(p->bx));
7694: fwri_Pts(f,p->size);
7695: fwri_Scoor(f,p->basl);
7696: /* fwri_?(f,p->proj); */
7697: /* fwri_ConstPitch(f,p->cp); */
7698: fwri_Merit(f,p->m);
7699: fwri_uint2(f,p->ls.mny);
7700: fwri_uint2(f,p->ws.mny);
7701: fwri_uint2(f,p->cs.mny);
7702: fwri_uint3(f,p->bs.mny);
7703: #if dbg_fwrb_toa
7704: err("fwrb_txtln: %s",txtln_toa(p));
7705: #endif
7706: if(p->ident&Txtln_label) fwrb_label(f,p->l);
7707: }
7708: #else
7709: fwrb_txtln(fp,lp)
7710: FILE *fp;
7711: Txtln *lp;
7712: { TxtlnF lf;
7713: int stat;
7714: #if dbg_fwrb
7715: if((!(lp->ident&IsTxtln))||(lp->ident&(IsALL&(~IsTxtln))))
7716: err("fwrb_txtln: %s",txtln_toa(lp));
7717: #endif
7718: memset(&lf,'\0',sizeof(lf));
7719: lf.ident = lp->ident;
7720: lf.bx = lp->bx;
7721: lf.basl = lp->basl;
7722: lf.size = lp->size;
7723: if(lp->proj!=NULL) lf.pmny = lp->bx.b.y - lp->bx.a.y + 1;
7724: else lf.pmny = 0;
7725: /* ignore lp->cp for now */
7726: lf.wmny = lp->ws.mny;
7727: lf.cmny = lp->cs.mny;
7728: lf.bmny = lp->bs.mny;
7729: if((stat=fwrite(&lf,sizeof(TxtlnF),1,fp))!=1)
7730: abort("can't write TxtlnF, status %d",stat);
7731: #if dbg_fwrb_toa
7732: err("fwrb_txtln: %s",txtln_toa(lp));
7733: #endif
7734: if(lf.ident&Txtln_label) fwrb_label(fp,lp->l);
7735: }
7736: #endif
7737:
7738: fwrb_txtlns_etc(fp,ls,etc)
7739: FILE *fp;
7740: Txtlns ls;
7741: Ident etc;
7742: { register Txtln *lp,**lpp;
7743: if(ls.mny>0) for(lp= *(lpp=ls.lpa); lp!=NULL; lp= *(++lpp))
7744: fwrb_txtln_etc(fp,lp,etc);
7745: }
7746:
7747: fwrb_txtln_etc(fp,lp,etc)
7748: FILE *fp;
7749: Txtln *lp;
7750: Ident etc;
7751: { static Ident parts = (IsWord|IsChar|IsBlob);
7752: Txtln tl;
7753: if((etc&parts)!=parts) /* write selected parts */ {
7754: tl = *lp;
7755: if(!(etc&IsWord)) tl.ws.mny=0;
7756: if(!(etc&IsChar)) tl.cs.mny=0;
7757: if(!(etc&IsBlob)) tl.bs.mny=0;
7758: lp = &tl; /* write modified record */
7759: };
7760: fwrb_txtln(fp,lp);
7761: if(lp->proj!=NULL) {/* write projection array someday */};
7762: fwrb_words_etc(fp,lp->ws,etc);
7763: fwrb_chars_etc(fp,lp->cs,etc);
7764: fwrb_blobs_etc(fp,lp->bs,etc);
7765: }
7766:
7767: #if FRDI
7768: int frdb_txtln(f,p)
7769: FILE *f;
7770: Txtln *p;
7771: { *p = empty_Txtln;
7772: if(feof(f))
7773: return(0);
7774: p->ident=frdi_Ident(f);
7775: frdi_Bbx(f,&(p->bx));
7776: p->size=frdi_Pts(f);
7777: p->basl=frdi_Scoor(f);
7778: /* p->proj=frdi_?(f); */
7779: /* p->cp=frdi_ConstPitch(f); */
7780: p->m=frdi_Merit(f);
7781: p->ls.mny=frdi_uint2(f);
7782: p->ws.mny=frdi_uint2(f);
7783: p->cs.mny=frdi_uint2(f);
7784: p->bs.mny=frdi_uint3(f);
7785: #if dbg_frdb
7786: if((!(p->ident&IsTxtln))||(p->ident&(IsALL&(~IsTxtln))))
7787: err("frdb_txtln: %s",txtln_toa(p));
7788: #endif
7789: #if dbg_frdb_toa
7790: err("frdb_txtln: %s",txtln_toa(p));
7791: #endif
7792: if(p->ident&Txtln_label) p->l = frdb_label(f);
7793: if(ferror(f)) return(-errno); else return(1);
7794: }
7795: #else
7796: int frdb_txtln(fp,lp)
7797: FILE *fp;
7798: Txtln *lp;
7799: { TxtlnF lf;
7800: int stat;
7801: if((stat=fread(&lf,sizeof(TxtlnF),1,fp))!=1)
7802: abort("can't read TxtlnF, status %d",stat);
7803: *lp = empty_Txtln;
7804: lp->ident = lf.ident;
7805: lp->bx = lf.bx;
7806: lp->basl = lf.basl;
7807: lp->size = lf.size;
7808: if(lf.pmny>0) lp->proj=(short *)malloc(lf.pmny);
7809: else lp->proj = NULL;
7810: lp->cp = NULL;
7811: lp->ws.mny = lf.wmny;
7812: lp->cs.mny = lf.cmny;
7813: lp->bs.mny = lf.bmny;
7814: #if dbg_frdb
7815: if((!(lp->ident&IsTxtln))||(lp->ident&(IsALL&(~IsTxtln))))
7816: err("frdb_txtln: %s",txtln_toa(lp));
7817: #endif
7818: #if dbg_frdb_toa
7819: err("frdb_txtln: %s",txtln_toa(lp));
7820: #endif
7821: if(lp->ident&Txtln_label) lp->l = frdb_label(fp);
7822: if(ferror(fp)) return(-errno); else return(1);
7823: }
7824: #endif
7825:
7826: frdb_txtln_etc(fp,lp,etc)
7827: FILE *fp;
7828: Txtln *lp;
7829: Ident etc;
7830: { TxtlnF lf;
7831: int stat;
7832: frdb_txtln(fp,lp);
7833: if(lp->proj!=NULL) {/* read projection array someday */};
7834: if(etc&IsWord && lp->ws.mny>0)
7835: frdb_words_etc(fp,&(lp->ws),etc);
7836: else lp->ws = empty_Words;
7837: if(etc&IsChar && lp->cs.mny>0)
7838: frdb_chars_etc(fp,&(lp->cs),etc);
7839: else lp->cs = empty_Chars;
7840: if(etc&IsBlob && lp->bs.mny>0)
7841: frdb_blobs_etc(fp,&(lp->bs),etc);
7842: else lp->bs = empty_Blobs;
7843: if(ferror(fp)) return(-errno); else return(1);
7844: }
7845:
7846: /* read number of txtlns, and parts */
7847: frdb_txtlns_etc(fp,lsp,etc)
7848: FILE *fp;
7849: Txtlns *lsp;
7850: Ident etc;
7851: { int li;
7852: register Txtln *lp,**lpp;
7853: if(lsp->mny<=0) {
7854: *lsp = empty_Txtlns;
7855: return(1);
7856: };
7857: if((lpp=lsp->lpa=(Txtln **)malloc((lsp->mny+1)*sizeof(Txtln *)))==NULL)
7858: abort("can't alloc Txtlns.lpa array");
7859: for(li=0; li<lsp->mny; li++) {
7860: *(lpp++) = lp = alloc_txtln();
7861: frdb_txtln_etc(fp,lp,etc);
7862: };
7863: *lpp = NULL;
7864: if(ferror(fp)) return(-errno); else return(1);
7865: }
7866:
7867: /* Append a txtln to the end of a txtlns set.
7868: Do NOT maintain Txtlns in order sorted ascending on Txtln.bx.a.y.
7869: Return appended Txtln *. */
7870: Txtln *append_txtln(lp,lsp)
7871: Txtln *lp;
7872: Txtlns *lsp;
7873: { register Txtln *rp,**rpp,**npp;
7874: if(lsp->mny==0) {
7875: if((lsp->lpa=(Txtln **)malloc(2*sizeof(Txtln *)))==NULL)
7876: abort("append_txtln: can't malloc lsp->lpa");
7877: }
7878: else { if((lsp->lpa=(Txtln **)realloc(
7879: lsp->lpa,
7880: (lsp->mny+2)*sizeof(Txtln *))
7881: )==NULL)
7882: abort("append_txtln: can't realloc lsp->lpa");
7883: };
7884: lsp->lpa[lsp->mny] = lp;
7885: lsp->lpa[++lsp->mny] = NULL;
7886: return(lp);
7887: }
7888:
7889: /* remove a txtln from a txtlns set */
7890: remove_txtln(lp,lsp)
7891: Txtln *lp;
7892: Txtlns *lsp;
7893: { register Txtln *rp,**rpp,**npp;
7894: if(lsp->mny==0) err("can't remove Txtln - Txtlns empty");
7895: else { for(rp= *(rpp=lsp->lpa); rp!=NULL; rp= *(++rpp)) if(rp==lp) break;
7896: if(rp==NULL) err("can't remove Txtln - not found");
7897: else { /* move later entries up */
7898: npp=rpp+1;
7899: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
7900: if((--(lsp->mny))==0) {free(lsp->lpa); lsp->lpa=NULL;};
7901: /* don't bother to realloc downwards */
7902: };
7903: };
7904: }
7905:
7906: free_txtln_etc(p,etc)
7907: Txtln *p;
7908: Ident etc;
7909: { free_words_etc(&(p->ws),etc);
7910: free_chars_etc(&(p->cs),etc);
7911: free_blobs_etc(&(p->bs),etc);
7912: if(p->ident&Txtln_label && p->l!=NULL) {
7913: free(p->l); p->l=NULL; p->ident &= ~Txtln_label;
7914: };
7915: if(etc&IsTxtln) {
7916: if(p->l!=NULL) free(p->l);
7917: free(p);
7918: free_census(Txtln,1);
7919: };
7920: }
7921:
7922: /* Unconditionally free the malloc-space array of pointers, and empty the set.
7923: Don't free the records that it owned.
7924: */
7925: free_txtlns(lsp)
7926: Txtlns *lsp;
7927: { if(lsp->lpa!=NULL) { free(lsp->lpa); lsp->lpa = NULL; }
7928: lsp->mny = 0;
7929: }
7930:
7931: free_txtlns_etc(lsp,etc)
7932: Txtlns *lsp;
7933: Ident etc;
7934: { register Txtln *lp,**lpp;
7935: if(lsp->mny>0&&(etc&IsTxtln))
7936: for(lp= *(lpp=lsp->lpa); lp!=NULL; lp= *(++lpp))
7937: free_txtln_etc(lp,etc);
7938: free_txtlns(lsp);
7939: }
7940:
7941: /* return a pointer to a distinct and duplicate copy of *lp,
7942: created out of malloc space */
7943: Txtln *dup_txtln(lp)
7944: Txtln *lp;
7945: { Txtln *dup;
7946: if((dup=(Txtln *)malloc(sizeof(Txtln)))==NULL)
7947: abort("can't dup Txtln");
7948: alloc_census(Txtln,1);
7949: *dup = *lp;
7950: return(dup);
7951: }
7952:
7953: /* Return a pointer to a distinct and duplicate copy of *lp, and its parts
7954: as specified by `etc', created out of malloc space. */
7955: Txtln *dup_txtln_etc(lp,etc)
7956: Txtln *lp;
7957: Ident etc;
7958: { Txtln *dup;
7959: dup = dup_txtln(lp);
7960: if(etc&IsBlob&&dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(lp->bs),etc);
7961: else dup->bs = empty_Blobs;
7962: if(etc&IsChar&&dup->cs.mny>0) dup->cs = *dup_chars_etc(&(lp->cs),etc);
7963: else dup->cs = empty_Chars;
7964: if(etc&IsWord&&dup->ws.mny>0) dup->ws = *dup_words_etc(&(lp->ws),etc);
7965: else dup->ws = empty_Words;
7966: return(dup);
7967: }
7968:
7969: /* Return a pointer to a distinct local static duplicate of non-empty *lsp.
7970: Its lpa array is created newly out of malloc space.
7971: If etc&IsTxtln, all its Txtlns are also duplicated,
7972: else the contents of lpa point to the old unduplicated Txtlns.
7973: */
7974: Txtlns *dup_txtlns_etc(lsp,etc)
7975: Txtlns *lsp;
7976: Ident etc; /* parts to duplicate */
7977: { static Txtlns dup;
7978: register Txtln **lpp,**dpp;
7979: if((dup.mny = lsp->mny)<=0) dup = empty_Txtlns;
7980: else { if((dup.lpa=(Txtln **)malloc((dup.mny+1)*sizeof(Txtln *)))==NULL)
7981: abort("can't dup ls.lpa");
7982: for(lpp=lsp->lpa,dpp=dup.lpa; *lpp!=NULL; lpp++,dpp++) {
7983: if(etc&IsTxtln) *dpp = dup_txtln_etc(*lpp,etc);
7984: else *dpp = *lpp;
7985: };
7986: *dpp = NULL;
7987: };
7988: return(&dup);
7989: }
7990:
7991: Word *alloc_word()
7992: { Word *p;
7993: if((p=(Word *)malloc(sizeof(Word)))==NULL)
7994: abort("can't alloc Word");
7995: alloc_census(Word,1);
7996: *p = empty_Word;
7997: return(p);
7998: }
7999:
8000: char *word_toa(p)
8001: Word *p;
8002: { static char s[80];
8003: sprintf(s,"%s bx%s ws%0.2f c%d b%d m%s w%d",
8004: ident_toa(p->ident),
8005: bbx_toa(&(p->bx)),
8006: p->wsp,
8007: p->cs.mny,p->bs.mny,merit_toa(p->m),p->ws.mny);
8008: return(s);
8009: }
8010:
8011: /* Are two Words identical? A not quite exhaustively-detailed test. */
8012: boolean eq_word(w1,w2)
8013: Word *w1,*w2;
8014: { register Char **c1,**c2;
8015: if(w1->cs.mny!=w2->cs.mny) return(F);
8016: for(c1=w1->cs.cpa,c2=w2->cs.cpa; *c1!=NULL; c1++,c2++) {
8017: if((*c1)->area!=(*c2)->area) return(F);
8018: if(!bbx_eq(&((*c1)->bx),&((*c2)->bx))) return(F);
8019: if((*c1)->bmny!=(*c2)->bmny) return(F);
8020: };
8021: /* don't bother to compare Blob lists in detail (they aren't
8022: in any particular order). */
8023: return(T);
8024: }
8025:
8026: /* Compute a hash key for this Word that is likely to indicate whether or
8027: not it is geometrically identical to another Word. */
8028: int hash_word(w)
8029: Word *w;
8030: { register int k;
8031: register Char **c;
8032: if(w->cs.mny==0) return(0);
8033: k = w->bx.a.x * w->bx.a.y * w->bx.b.x * w->bx.b.y;
8034: for(c=w->cs.cpa; (*c)!=NULL; c++) {
8035: k += (*c)->bx.a.x * (*c)->bx.a.y * (*c)->bx.b.x
8036: * (*c)->bx.b.y * (*c)->bmny * (*c)->area;
8037: };
8038: return(k);
8039: }
8040:
8041: #if FWRI
8042: fwrb_word(f,p)
8043: FILE *f;
8044: Word *p;
8045: {
8046: #if dbg_fwrb
8047: if((!(p->ident&IsWord))||(p->ident&(IsALL&(~IsWord))))
8048: err("fwrb_word: %s",word_toa(p));
8049: if(p->ident&Word_label && p->l==NULL) {
8050: err("fwrb_page: Word_label set but .l==NULL");
8051: p->ident &= ~Word_label;
8052: };
8053: #endif
8054: fwri_Ident(f,p->ident);
8055: fwri_Bbx(f,&(p->bx));
8056: fwri_int2(f,p->wsp*UCHAR_MAX);
8057: fwri_Merit(f,p->m);
8058: fwri_Prob(f,p->p);
8059: fwri_uint2(f,p->ws.mny);
8060: fwri_uint2(f,p->cs.mny);
8061: fwri_uint3(f,p->bs.mny);
8062: /* fwri_int4(f,p->hash); */
8063: #if dbg_fwrb_toa
8064: err("fwrb_word: %s",word_toa(p));
8065: #endif
8066: if(p->ident&Word_label) fwrb_label(f,p->l);
8067: }
8068: #else
8069: fwrb_word(fp,wp)
8070: FILE *fp;
8071: Word *wp;
8072: { WordF wf;
8073: int stat;
8074: #if dbg_fwrb
8075: if((!(wp->ident&IsWord))||(wp->ident&(IsALL&(~IsWord))))
8076: err("fwrb_word: %s",word_toa(wp));
8077: #endif
8078: memset(&wf,'\0',sizeof(wf));
8079: wf.ident = wp->ident;
8080: wf.bx = wp->bx;
8081: wf.wsp = wp->wsp;
8082: wf.m = wp->m;
8083: wf.wmny = wp->ws.mny;
8084: wf.cmny = wp->cs.mny;
8085: wf.bmny = wp->bs.mny;
8086: if((stat=fwrite(&wf,sizeof(WordF),1,fp))!=1)
8087: abort("can't write WordF, status %d",stat);
8088: #if dbg_fwrb_toa
8089: err("fwrb_word: %s",word_toa(wp));
8090: #endif
8091: if(wf.ident&Word_label) fwrb_label(fp,wp->l);
8092: }
8093: #endif
8094:
8095: fwrb_words_etc(fp,ws,etc)
8096: FILE *fp;
8097: Words ws;
8098: Ident etc;
8099: { register Word *wp,**wpp;
8100: if(ws.mny>0) for(wp= *(wpp=ws.wpa); wp!=NULL; wp= *(++wpp))
8101: fwrb_word_etc(fp,wp,etc);
8102: }
8103:
8104: fwrb_word_etc(fp,wp,etc)
8105: FILE *fp;
8106: Word *wp;
8107: Ident etc;
8108: { static Ident parts = (IsWord|IsChar|IsBlob);
8109: Word wd;
8110: if((etc&parts)!=parts) /* write selected parts */ {
8111: wd = *wp;
8112: if(!(etc&IsWord)) wd.ws.mny=0;
8113: if(!(etc&IsChar)) wd.cs.mny=0;
8114: if(!(etc&IsBlob)) wd.bs.mny=0;
8115: wp = &wd; /* write modified record */
8116: };
8117: fwrb_word(fp,wp);
8118: if(etc&IsWord) fwrb_words_etc(fp,wp->ws,IsALL);
8119: fwrb_chars_etc(fp,wp->cs,etc);
8120: fwrb_blobs_etc(fp,wp->bs,etc);
8121: }
8122:
8123: #if FRDI
8124: int frdb_word(f,p)
8125: FILE *f;
8126: Word *p;
8127: { *p = empty_Word;
8128: if(feof(f))
8129: return(0);
8130: p->ident=frdi_Ident(f);
8131: frdi_Bbx(f,&(p->bx));
8132: p->wsp=frdi_int2(f)/(float)UCHAR_MAX;
8133: p->m=frdi_Merit(f);
8134: p->p=frdi_Prob(f);
8135: p->ws.mny=frdi_uint2(f);
8136: p->cs.mny=frdi_uint2(f);
8137: p->bs.mny=frdi_uint3(f);
8138: /* p->hash=frdi_int4(f); */
8139: #if dbg_frdb
8140: if((!(p->ident&IsWord))||(p->ident&(IsALL&(~IsWord))))
8141: err("frdb_word: %s",word_toa(p));
8142: #endif
8143: #if dbg_frdb_toa
8144: err("frdb_word: %s",word_toa(p));
8145: #endif
8146: if(p->ident&Word_label) p->l = frdb_label(f);
8147: if(ferror(f)) return(-errno); else return(1);
8148: }
8149: #else
8150: int frdb_word(fp,wp)
8151: FILE *fp;
8152: Word *wp;
8153: { WordF wf;
8154: int stat;
8155: if((stat=fread(&wf,sizeof(WordF),1,fp))!=1)
8156: abort("can't read WordF, status %d",stat);
8157: *wp = empty_Word;
8158: wp->ident = wf.ident;
8159: wp->bx = wf.bx;
8160: wp->wsp = wf.wsp;
8161: wp->m = wf.m;
8162: wp->ws.mny = wf.wmny;
8163: wp->cs.mny = wf.cmny;
8164: wp->bs.mny = wf.bmny;
8165: #if dbg_frdb
8166: if((!(wp->ident&IsWord))||(wp->ident&(IsALL&(~IsWord))))
8167: err("frdb_word: %s",word_toa(wp));
8168: #endif
8169: #if dbg_frdb_toa
8170: err("frdb_word: %s",word_toa(wp));
8171: #endif
8172: if(wp->ident&Word_label) wp->l = frdb_label(fp);
8173: if(ferror(fp)) return(-errno); else return(1);
8174: }
8175: #endif
8176:
8177: frdb_word_etc(fp,wp,etc)
8178: FILE *fp;
8179: Word *wp;
8180: Ident etc;
8181: { WordF cf;
8182: int stat;
8183: frdb_word(fp,wp);
8184: frdb_words_etc(fp,&(wp->ws),IsALL); /* rd alternatives entirely, if any */
8185: if(etc&IsChar && wp->cs.mny>0)
8186: frdb_chars_etc(fp,&(wp->cs),etc);
8187: else wp->cs = empty_Chars;
8188: if(etc&IsBlob && wp->bs.mny>0)
8189: frdb_blobs_etc(fp,&(wp->bs),etc);
8190: else wp->bs = empty_Blobs;
8191: if(ferror(fp)) return(-errno); else return(1);
8192: }
8193:
8194: /* read words, and their parts */
8195: frdb_words_etc(fp,wsp,etc)
8196: FILE *fp;
8197: Words *wsp;
8198: Ident etc;
8199: { int wi;
8200: register Word *wp,**wpp;
8201: if(wsp->mny<=0) {
8202: *wsp = empty_Words;
8203: return(1);
8204: };
8205: if((wpp=wsp->wpa=(Word **)malloc((wsp->mny+1)*sizeof(Word *)))==NULL)
8206: abort("can't alloc Words.wpa array");
8207: for(wi=0; wi<wsp->mny; wi++) {
8208: *(wpp++) = wp = alloc_word();
8209: frdb_word_etc(fp,wp,etc);
8210: };
8211: *wpp = NULL;
8212: if(ferror(fp)) return(-errno); else return(1);
8213: }
8214:
8215: /* remove a word from a words set */
8216: remove_word(wp,wsp)
8217: Word *wp;
8218: Words *wsp;
8219: { register Word *rp,**rpp,**npp;
8220: if(wsp->mny==0) err("can't remove Word - Words empty");
8221: else { for(rp= *(rpp=wsp->wpa); rp!=NULL; rp= *(++rpp)) if(rp==wp) break;
8222: if(rp==NULL) err("can't remove Word - not found");
8223: else { /* move later entries up */
8224: npp=rpp+1;
8225: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
8226: if((--(wsp->mny))==0) {free(wsp->wpa); wsp->wpa=NULL;};
8227: /* don't bother to realloc downwards */
8228: };
8229: };
8230: }
8231:
8232: /* Remove a Word from a Txtln's Words set.
8233: Shrink the Txtln's Bbx if the Word abuts it on the left or right.
8234: Ensure that the first Word in the line has wsp==0.0
8235: BUG: doesn't update wsp of trailing Word */
8236: remove_word_txtln(wp,lp)
8237: Word *wp;
8238: Txtln *lp;
8239: { register Word *cwp,**wpp;
8240: remove_word(wp,&(lp->ws));
8241: if(lp->ws.mny>0) {
8242: if(wp->bx.a.x==lp->bx.a.x || wp->bx.b.x==lp->bx.b.x) {
8243: /* recompute possibly shrunken bx */
8244: lp->bx=empty_Bbx;
8245: for(cwp= *(wpp=lp->ws.wpa); cwp!=NULL; cwp= *(++wpp))
8246: merge_bbx(&(cwp->bx),&(lp->bx));
8247: };
8248: (lp->ws.wpa[0])->wsp=0.0;
8249: };
8250: }
8251:
8252: /* Append a word to the end of a words set.
8253: Do NOT maintain set in order ascending on Word.bx.a.x.
8254: Return the appended Word. */
8255: Word *append_word(wp,wsp)
8256: Word *wp;
8257: Words *wsp;
8258: { if(wsp->mny==0) {
8259: if((wsp->wpa=(Word **)malloc(2*sizeof(Word *)))==NULL)
8260: abort("append_word: can't malloc wsp->wpa");
8261: }
8262: else { if((wsp->wpa=(Word **)realloc(
8263: wsp->wpa,
8264: (wsp->mny+2)*sizeof(Word *))
8265: )==NULL)
8266: abort("append_word: can't realloc wsp->wpa");
8267: };
8268: wsp->wpa[wsp->mny++] = wp;
8269: wsp->wpa[wsp->mny] = NULL;
8270: return(wp);
8271: }
8272:
8273: /* Insert a Word into a Words set. Words is assumed to be sorted ascending
8274: on Word.bx.a.x, and this order is maintained.
8275: Words with equal Word.bx.a.x are stored in the order that they were
8276: inserted: so that the first one inserted remains the first among equals
8277: (this feature is important for certain WordSet applications).
8278: Return inserted (Word *) */
8279: Word *insert_word(wp,wsp)
8280: Word *wp;
8281: Words *wsp;
8282: { register Word **wpp,*nwp,*pwp;
8283: if(wsp->mny==0) {
8284: if((wsp->wpa=(Word **)malloc(2*sizeof(Word *)))==NULL)
8285: abort("insert_word: can't malloc wsp->wpa");
8286: wsp->wpa[wsp->mny] = wp;
8287: }
8288: else { if((wpp=wsp->wpa=(Word **)realloc(
8289: wsp->wpa,
8290: (wsp->mny+2)*sizeof(Word *))
8291: )==NULL)
8292: abort("insert_word: can't realloc wsp->wpa");
8293: while(((*wpp)!=NULL)&&(*wpp)->bx.a.x<=wp->bx.a.x) wpp++;
8294: /* **wpp is now 1st entry > *wp in sorted order; insert
8295: new word just before it */
8296: pwp=wp;
8297: do { nwp= *wpp;
8298: *(wpp++)=pwp;
8299: pwp=nwp;
8300: }
8301: while(pwp!=NULL);
8302: };
8303: wsp->wpa[++wsp->mny] = NULL;
8304: return(wp);
8305: }
8306:
8307: /* Insert a Word into the Words owned by a given Txtln,
8308: maintaining the Txtln's Bbx and sorted order in the Words set.
8309: Return the inserted Word * */
8310: Word *insert_word_txtln(wp,lp)
8311: Word *wp;
8312: Txtln *lp;
8313: { merge_bbx(&(wp->bx),&(lp->bx));
8314: return(insert_word(wp,&(lp->ws)));
8315: }
8316:
8317: /* Free wordinterp and its parts as specified in etc.
8318: Always free its strings (if any).
8319: If etc&IsWordInterp, free the record itself also.
8320: */
8321: free_wordinterp_etc(p,etc)
8322: WordInterp *p;
8323: Ident etc;
8324: { if(p->s!=NULL) { free(p->s); p->s=NULL; };
8325: if(p->pp!=NULL) { free(p->pp); p->pp=NULL; };
8326: if(p->by!=NULL) { free(p->by); p->by=NULL; };
8327: if(p->po!=NULL) { free(p->po); p->po=NULL; };
8328: if(p->ps!=NULL) { free(p->ps); p->ps=NULL; };
8329: if(etc&IsWordInterp) free(p);
8330: }
8331:
8332: /* Duplicate (return ptr to local static copy of) a WordInterp.
8333: Always free its strings (if any).
8334: 'etc' is ignored.
8335: */
8336: WordInterp *dup_wordinterp_etc(p,etc)
8337: WordInterp *p;
8338: Ident etc;
8339: { static WordInterp d;
8340: d = *p;
8341: if(p->s!=NULL) d.s = strdup(p->s);
8342: if(p->pp!=NULL) d.pp = strdup(p->pp);
8343: if(p->by!=NULL) d.by = strdup(p->by);
8344: if(p->po!=NULL) d.po = strdup(p->po);
8345: if(p->ps!=NULL) d.ps = strdup(p->ps);
8346: return(&d);
8347: }
8348:
8349: /* Unconditionally free the malloc-space array of pointers, and empty the set.
8350: Don't free the records that it owned.
8351: */
8352: free_words(wsp)
8353: Words *wsp;
8354: { if(wsp->wpa!=NULL) { free(wsp->wpa); wsp->wpa = NULL; }
8355: wsp->mny = 0;
8356: }
8357:
8358: free_words_etc(wsp,etc)
8359: Words *wsp;
8360: Ident etc;
8361: { register Word *wp,**wpp;
8362: int wi;
8363: if(wsp->mny>0&&(etc&IsWord))
8364: for(wp= *(wpp=wsp->wpa); wp!=NULL; wp= *(++wpp))
8365: free_word_etc(wp,etc);
8366: free_words(wsp);
8367: }
8368:
8369: /* return a pointer to a distinct and duplicate copy of *wp,
8370: created out of malloc space */
8371: Word *dup_word(wp)
8372: Word *wp;
8373: { Word *dup;
8374: if((dup=(Word *)malloc(sizeof(Word)))==NULL)
8375: abort("can't dup Word");
8376: alloc_census(Word,1);
8377: *dup = *wp;
8378: return(dup);
8379: }
8380:
8381: /* Return a pointer to a distinct and duplicate copy of *wp, and ALL it owns,
8382: created out of malloc space. (HOW they are duplicated is controlled by flags
8383: in etc.) */
8384: Word *dup_word_etc(wp,etc)
8385: Word *wp;
8386: Ident etc;
8387: { Word *dup;
8388: dup = dup_word(wp);
8389: if(dup->ws.mny>0) dup->ws = *dup_words_etc(&(wp->ws),etc);
8390: else dup->ws = empty_Words;
8391: if(dup->cs.mny>0) dup->cs = *dup_chars_etc(&(wp->cs),etc);
8392: else dup->cs = empty_Chars;
8393: if(dup->bs.mny>0) dup->bs = *dup_blobs_etc(&(wp->bs),etc);
8394: else dup->bs = empty_Blobs;
8395: return(dup);
8396: }
8397:
8398: /* Return a pointer to a distinct local static duplicate of non-empty *wsp.
8399: Its wpa array is created newly out of malloc space.
8400: If etc&IsWord, all its Words are also duplicated,
8401: else the contents of wpa point to the old unduplicated Words.
8402: */
8403: Words *dup_words_etc(wsp,etc)
8404: Words *wsp;
8405: Ident etc; /* parts to duplicate */
8406: { static Words dup;
8407: register Word **wpp,**dpp;
8408: if((dup.mny=wsp->mny)<=0) dup = empty_Words;
8409: else { if((dup.wpa=(Word **)malloc((dup.mny+1)*sizeof(Word *)))==NULL)
8410: abort("can't dup ws.wpa");
8411: for(wpp=wsp->wpa,dpp=dup.wpa; *wpp!=NULL; wpp++,dpp++) {
8412: if(etc&IsWord) *dpp = dup_word_etc(*wpp,etc);
8413: else *dpp = *wpp;
8414: };
8415: *dpp = NULL;
8416: };
8417: return(&dup);
8418: }
8419:
8420: WordInterp *alloc_wordinterp()
8421: { WordInterp *p;
8422: if((p=(WordInterp *)malloc(sizeof(WordInterp)))==NULL)
8423: abort("can't alloc WordInterp");
8424: else { *p = empty_WordInterp;
8425: return(p);
8426: };
8427: }
8428:
8429: char *wordinterp_toa(p)
8430: WordInterp *p;
8431: { static char s[80];
8432: sprintf(s,"%s %s %s|%s|%s|%s",
8433: ident_toa(p->ident),
8434: ((p->s!=NULL)? p->s: ""),
8435: ((p->pp!=NULL)? p->pp: ""),
8436: ((p->by!=NULL)? p->by: ""),
8437: ((p->po!=NULL)? p->po: ""),
8438: ((p->ps!=NULL)? p->ps: "")
8439: );
8440: return(s);
8441: }
8442:
8443: /* Free Word and its parts, as specified by etc.
8444: Always free the pointer-arrays of ws, cs & bs.
8445: If etc&IsWord, free all Words in ws also.
8446: If etc&IsChar, free all Chars in cs also.
8447: If etc&IsBlob, free all Blobs in bs also.
8448: */
8449: free_word_etc(p,etc)
8450: Word *p;
8451: Ident etc;
8452: #define dbg_fwe (F)
8453: { if(dbg_fwe) {
8454: err("free_word_etc: %s",word_toa(p));
8455: err("free_word_etc: %s",ident_toa(etc));
8456: err_census_all;
8457: };
8458: free_words_etc(&(p->ws),IsALL);
8459: free_chars_etc(&(p->cs),etc);
8460: free_blobs_etc(&(p->bs),etc);
8461: if(p->ident&Word_label && p->l!=NULL) {
8462: free(p->l); p->l=NULL; p->ident &= ~Word_label;
8463: };
8464: if(etc&IsWord) free_word(p);
8465: if(dbg_fwe) err_census_all;
8466: }
8467:
8468: free_word(wp)
8469: Word *wp;
8470: { free(wp);
8471: free_census(Word,1);
8472: }
8473:
8474: fwrb_sfeats(fp,sfv)
8475: FILE *fp;
8476: SFv sfv;
8477: { register Pval *vp,*vq;
8478: for(vq=(vp=sfv)+SF_MNY; vp<vq; vp++)
8479: fwri_int3(fp,USHRT_MAX*(*vp)+0.5);
8480: #if dbg_fwrb_toa
8481: /** err("fwrb_sfeats: %s",sfeats_toa(sfv)); **/
8482: #endif
8483: }
8484:
8485: int frdb_sfeats(fp,sfv)
8486: FILE *fp;
8487: SFv sfv;
8488: { register Pval *vp,*vq;
8489: for(vq=(vp=sfv)+SF_MNY; vp<vq; vp++)
8490: *vp = frdi_int3(fp)/((Pval)USHRT_MAX);
8491: #if dbg_frdb_toa
8492: /** err("frdb_sfeats: %s",sfeats_toa(sfv)); **/
8493: #endif
8494: }
8495:
8496: /* return ptr to local static copy of Shapes of given size */
8497: Shapes *alloc_shapes(mny)
8498: int mny;
8499: { static Shapes shs;
8500: shs.mny = shs.alloc = mny;
8501: if((shs.sa=(Nb_s *)malloc(shs.alloc*sizeof(Nb_s)))==NULL)
8502: abort("can't alloc Shapes.sa[%d]",shs.alloc);
8503: return(&shs);
8504: }
8505:
8506: fwrb_shapes(fp,p)
8507: FILE *fp;
8508: Shapes *p; /* on entry, p->mny has already been written */
8509: { int dim;
8510: register Nb_s *sp,*sq;
8511: register Pval *vp;
8512: if(p->mny>0&&p->sa!=NULL) {
8513: for(sq=(sp=p->sa)+p->mny; sp<sq; sp++) {
8514: dim=Sh_dim[sp->t&(~Sh_tiny)];
8515: fwri_uint1(fp,(sp->t&0x7F)|((sp->t&Sh_tiny)?0x80:0x00));
8516: fwri_int2(fp,(*(vp=sp->p))*SHRT_MAX);
8517: if(dim>1) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
8518: if(dim>2) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
8519: if(dim>3) { fwri_int2(fp,(*(++vp))*SHRT_MAX);
8520: } } };
8521: };
8522: };
8523: #if dbg_fwrb_toa
8524: /** err("fwrb_shapes: %s",shapes_toa(p)); **/
8525: #endif
8526: }
8527:
8528: int frdb_shapes(fp,p)
8529: FILE *fp;
8530: Shapes *p; /* on entry, p->mny has already been read */
8531: { register Nb_s *sp,*sq;
8532: register Pval *vp;
8533: uint1 ui1;
8534: int dim;
8535:
8536: if(p->mny>0) {
8537: *p = *alloc_shapes(p->mny);
8538: for(sq=(sp=p->sa)+p->mny; sp<sq; sp++) {
8539: ui1 = frdi_uint1(fp);
8540: sp->t = ui1&0x7F|((ui1&0x80)?Sh_tiny:0);
8541: dim=Sh_dim[sp->t&(~Sh_tiny)];
8542: *(vp=sp->p) = ((float)frdi_int2(fp))/SHRT_MAX;
8543: if(dim>1) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
8544: if(dim>2) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
8545: if(dim>3) { *(++vp) = ((float)frdi_int2(fp))/SHRT_MAX;
8546: } } };
8547: };
8548: }
8549: else { p->alloc = 0;
8550: if(p->sa!=NULL) free(p->sa);
8551: p->sa = NULL;
8552: };
8553: #if dbg_frdb_toa
8554: /** err("frdb_shapes: %s",shapes_toa(p)); **/
8555: #endif
8556: }
8557:
8558: fwra_shapes_etc(fp,p,t)
8559: FILE *fp;
8560: Shapes *p;
8561: char *t; /* string of shape types (empty => all) */
8562: { Nb_s *s;
8563: int i,j;
8564: char a[80],f[10];
8565: for(i=0,s=p->sa; i<p->mny; i++,s++) {
8566: if(t[0]=='\0'||strchr(t,Sh_nam[s->t&(~Sh_tiny)])!=NULL) {
8567: sprintf(a,"%c%c ",
8568: Sh_nam[s->t&(~Sh_tiny)],
8569: (s->t&Sh_tiny)?'\'':' '
8570: );
8571: for(j=0;j<Sh_dim[s->t&(~Sh_tiny)];j++) {
8572: sprintf(f," %0.3f",s->p[j]);
8573: strcat(a,f);
8574: };
8575: fprintf(fp,"%s\n",a);
8576: };
8577: };
8578: }
8579:
8580: err_shapes(shp)
8581: Shapes *shp;
8582: { int si,di;
8583: Nb_s *sp;
8584: fprintf(stderr,"shapes %d:\n",shp->mny);
8585: for(si=0,sp=shp->sa; si<shp->mny; si++,sp++) {
8586: fprintf(stderr," %c",Sh_nam[sp->t]);
8587: for(di=0; di<Sh_dim[sp->t]; di++)
8588: fprintf(stderr," %6.3f",sp->p[di]);
8589: fprintf(stderr,"\n");
8590: };
8591: }
8592:
8593: /* Unconditionally free the malloc-space array of pointers, and empty the set.
8594: Don't free the records that it owned.
8595: */
8596: free_shapes(shp)
8597: Shapes *shp;
8598: { if(shp->sa!=NULL) {
8599: if(shp->alloc<=0) abort("can't free unalloc'ed shapes");
8600: else { free(shp->sa); shp->sa=NULL; };
8601: };
8602: shp->mny = shp->alloc = 0;
8603: }
8604:
8605: /* functions for RanParms */
8606:
8607: RanParms *alloc_ranparms()
8608: { RanParms *rp;
8609: if((rp=(RanParms *)malloc(sizeof(RanParms)))==NULL)
8610: abort("alloc_ranparms: can't alloc");
8611: *rp = empty_RanParms;
8612: return(rp);
8613: }
8614:
8615: free_ranparms(ran)
8616: RanParms *ran;
8617: { free(ran);
8618: }
8619:
8620: RanParms *dup_ranparms(p)
8621: RanParms *p;
8622: { RanParms *dup;
8623: dup = alloc_ranparms();
8624: *dup = *p;
8625: return(dup);
8626: }
8627:
8628: char *ranparms_toa(ran,select)
8629: RanParms *ran;
8630: char *select; /* a string, subset of: "*rpabejkstxy" if "*" or "" ALL */
8631: { static char s[200];
8632: char p[20];
8633: char *cp;
8634: static char select_all[] = "abejkprstxy";
8635: s[0]='\0';
8636: if(select[0]=='*'||select[0]=='\0') select=select_all;
8637: for(cp=select; *cp!='\0'; cp++) {
8638: switch(*cp) {
8639: case 'a': sprintf(p,"a%0.3f ",ran->skew/DtoR); strcat(s,p); break;
8640: case 'b': sprintf(p,"b%0.3f ",ran->bhgt); strcat(s,p); break;
8641: case 'e': sprintf(p,"e%0.3f ",ran->blur); strcat(s,p); break;
8642: case 'j': sprintf(p,"j%0.3f ",ran->jitter); strcat(s,p); break;
8643: case 'k': sprintf(p,"k%0.3f ",ran->kern); strcat(s,p); break;
8644: case 'p': sprintf(p,"p%g ",ran->size); strcat(s,p); break;
8645: case 'r': sprintf(p,"r%d,%d ",ran->res_x,ran->res_y); strcat(s,p); break;
8646: case 's': sprintf(p,"s%0.4f ",ran->speckle); strcat(s,p); break;
8647: case 't': sprintf(p,"t%0.3f ",ran->thresh); strcat(s,p); break;
8648: case 'x': sprintf(p,"x%0.3f ",ran->xscale); strcat(s,p); break;
8649: case 'y': sprintf(p,"y%0.3f ",ran->yscale); strcat(s,p); break;
8650: };
8651: };
8652: return(s);
8653: }
8654:
8655: RanParms *ato_ranparms(s)
8656: char *s;
8657: { static RanParms ran;
8658: char *f,n,*v;
8659: #define TOKEN_SEP "=, \n"
8660: f=strtok(s,TOKEN_SEP);
8661: while(f!=NULL&&strlen(f)>0) {
8662: n=f[0]; v=f+1;
8663: switch(n) {
8664: case 'r': /* res */
8665: ran.res_x = atoi(v);
8666: v=strtok((char *)0,TOKEN_SEP);
8667: ran.res_y = atoi(v);
8668: break;
8669: case 'p': ran.size = atof(v); break;
8670: case 'a': ran.skew = atof(v)*DtoR; break;
8671: case 'b': ran.bhgt = atof(v); break;
8672: case 'e': ran.blur = atof(v); break;
8673: case 'j': ran.jitter = atof(v); break;
8674: case 'k': ran.kern = atof(v); break;
8675: case 's': ran.speckle = atof(v); break;
8676: case 't': ran.thresh = atof(v); break;
8677: case 'x': ran.xscale = atof(v); break;
8678: case 'y': ran.yscale = atof(v); break;
8679: };
8680: f=strtok((char *)0,TOKEN_SEP);
8681: };
8682: return(&ran);
8683: }
8684:
8685: #if FWRI
8686: fwrb_ranparms(f,p)
8687: FILE *f;
8688: RanParms *p;
8689: { fwri_int2(f,p->res_x);
8690: fwri_int2(f,p->res_y);
8691: fwri_Pts(f,p->size);
8692: fwri_Radians(f,p->skew);
8693: fwri_Ems(f,p->bhgt);
8694: fwri_int3(f,p->blur*10000.0);
8695: fwri_int3(f,p->jitter*10000.0);
8696: fwri_int3(f,p->kern*10000.0);
8697: fwri_int3(f,p->speckle*10000.0);
8698: fwri_int3(f,p->thresh*10000.0);
8699: fwri_int3(f,p->xscale*10000.0);
8700: fwri_int3(f,p->yscale*10000.0);
8701: #if dbg_fwrb_toa
8702: err("fwrb_ranparms: %s",ranparms_toa(p));
8703: #endif
8704: }
8705: #else
8706: fwrb_ranparms(f,p)
8707: FILE *f;
8708: RanParms *p;
8709: { if((fwrite(p,sizeof(RanParms),1,f))!=1) return(0);
8710: #if dbg_fwrb_toa
8711: err("fwrb_ranparms: %s",ranparms_toa(p));
8712: #endif
8713: }
8714: #endif
8715:
8716: #if FRDI
8717: int frdb_ranparms(f,p)
8718: FILE *f;
8719: RanParms *p;
8720: { *p = empty_RanParms;
8721: if(feof(f))
8722: return(0);
8723: p->res_x=frdi_int2(f);
8724: p->res_y=frdi_int2(f);
8725: p->size=frdi_Pts(f);
8726: p->skew=frdi_Radians(f);
8727: p->bhgt=frdi_Ems(f);
8728: p->blur=frdi_int3(f)/10000.0;
8729: p->jitter=frdi_int3(f)/10000.0;
8730: p->kern=frdi_int3(f)/10000.0;
8731: p->speckle=frdi_int3(f)/10000.0;
8732: p->thresh=frdi_int3(f)/10000.0;
8733: p->xscale=frdi_int3(f)/10000.0;
8734: p->yscale=frdi_int3(f)/10000.0;
8735: #if dbg_frdb_toa
8736: err("frdb_ranparms: %s",ranparms_toa(p));
8737: #endif
8738: if(ferror(f)) return(-errno); else return(1);
8739: }
8740: #else
8741: int frdb_ranparms(fp,ran)
8742: FILE *fp;
8743: RanParms *ran;
8744: { if((fread(ran,sizeof(RanParms),1,fp))<1) return(0);
8745: #if dbg_frdb_toa
8746: err("frdb_ranparms: %s",ranparms_toa(ran));
8747: #endif
8748: }
8749: #endif
8750:
8751: Char *alloc_char()
8752: { Char *p;
8753: if((p=(Char *)malloc(sizeof(Char)))==NULL)
8754: abort("can't alloc Char");
8755: alloc_census(Char,1);
8756: *p = empty_Char;
8757: return(p);
8758: }
8759:
8760: char *char_toa(cp)
8761: Char *cp;
8762: { static char s[100],bfs[24];
8763: if(cp->bfsp==NULL) strcpy(bfs,"0");
8764: else if(cp->bfsp->bm.n==0) strcpy(bfs,"0");
8765: else if(cp->bfsp->bm.mny==0) sprintf(bfs,"%d",cp->bfsp->bm.n);
8766: else sprintf(bfs,"%d,%d",cp->bfsp->bm.n,cp->bfsp->bm.mny);
8767: sprintf(s,"%s bx%s w%d,h%d cs%d bl%d ar%d pe%d sf%d sh%d bf%s i%d",
8768: ident_toa(cp->ident),
8769: bbx_toa(&(cp->bx)),
8770: bbx_wid(&cp->bx),bbx_hgt(&cp->bx),
8771: cp->csp,
8772: cp->bmny,
8773: cp->area,cp->per,
8774: (cp->sfv==NULL)? 0: 1,
8775: cp->sh.mny,
8776: bfs,
8777: cp->il.mny
8778: );
8779: return(s);
8780: }
8781:
8782: /* compute the centroid of the Char (offset from bx.a) */
8783: Pp *char_centroid(cp)
8784: Char *cp;
8785: { static Pp c;
8786: Pp *bc; /* blob centroid */
8787: Blob *bp;
8788: int bi;
8789: c.x = c.y = 0.0;
8790: for(bi=0, bp=cp->fi; bi<cp->bmny; bi++, bp=bp->n) {
8791: bc = blob_centroid(bp);
8792: c.x += bp->area * (bc->x + (cp->bx.a.x - cp->bx.a.x));
8793: c.y += bp->area * (bc->y + (cp->bx.a.y - cp->bx.a.y));
8794: };
8795: c.x /= cp->area;
8796: c.y /= cp->area;
8797: return(&c);
8798: }
8799:
8800: #if FWRI
8801: fwrb_char(f,p)
8802: FILE *f;
8803: Char *p;
8804: {
8805: #if dbg_fwrb
8806: if((!(p->ident&IsChar))||(p->ident&(IsALL&(~IsChar))))
8807: err("fwrb_char: %s",char_toa(p));
8808: if(p->ident&Char_label && p->l==NULL) {
8809: err("fwrb_page: Char_label set but .l==NULL");
8810: p->ident &= ~Char_label;
8811: };
8812: if(p->ident&Char_ranparms && p->rp==NULL) {
8813: err("fwrb_page: Char_ranparms set but .rp==NULL");
8814: p->ident &= ~Char_ranparms;
8815: };
8816: #endif
8817: fwri_Ident(f,p->ident);
8818: fwri_Bbx(f,&(p->bx));
8819: fwri_Scoor(f,p->csp);
8820: fwri_uint4(f,p->area);
8821: fwri_uint4(f,p->per);
8822: fwri_Scoor(f,p->basl);
8823: fwri_uint3(f,p->bmny);
8824: fwri_uint2(f,p->il.mny);
8825: fwri_uint1(f,(p->sfv!=NULL)?SF_MNY:0);
8826: fwri_uint2(f,p->sh.mny);
8827: fwri_uint2(f,(p->bfsp!=NULL)?p->bfsp->bm.n:0);
8828: #if dbg_fwrb_toa
8829: err("fwrb_char: %s",char_toa(p));
8830: #endif
8831: if(p->ident&Char_label) fwrb_label(f,p->l);
8832: if(p->ident&Char_ranparms) fwrb_ranparms(f,p->rp);
8833: }
8834: #else
8835: fwrb_char(fp,cp)
8836: FILE *fp;
8837: Char *cp;
8838: { CharF cf;
8839: int stat;
8840: #if dbg_fwrb
8841: if((!(cp->ident&IsChar))||(cp->ident&(IsALL&(~IsChar))))
8842: err("fwrb_char: %s",char_toa(cp));
8843: #endif
8844: memset(&cf,'\0',sizeof(cf));
8845: if(cp->ident&Char_ranparms && cp->rp==NULL)
8846: cp->ident &= ~Char_ranparms;
8847: cf.ident = cp->ident | IsChar;
8848: cf.bx = cp->bx;
8849: cf.csp = cp->csp;
8850: cf.area = cp->area;
8851: cf.per = cp->per;
8852: /* basl omitted */
8853: cf.bmny = cp->bmny;
8854: cf.imny = cp->il.mny;
8855: cf.sfmny = (cp->sfv!=NULL)?SF_MNY:0;
8856: cf.shmny = cp->sh.mny;
8857: if(cp->bfsp!=NULL) cf.bfmny = cp->bfsp->bm.n; else cf.bfmny=0;
8858: if((stat=fwrite(&cf,sizeof(CharF),1,fp))!=1)
8859: abort("can't write CharF, status %d",stat);
8860: #if dbg_fwrb_toa
8861: err("fwrb_char: %s",char_toa(cp));
8862: #endif
8863: if(cf.ident&Char_ranparms) fwrb_ranparms(fp,cp->rp);
8864: if(cf.ident&Char_label) fwrb_label(fp,cp->l);
8865: }
8866: #endif
8867:
8868: fwrb_chars_etc(fp,cs,etc)
8869: FILE *fp;
8870: Chars cs;
8871: Ident etc;
8872: { register Char *cp,**cpp;
8873: if(cs.mny>0) for(cp= *(cpp=cs.cpa); cp!=NULL; cp= *(++cpp))
8874: fwrb_char_etc(fp,cp,etc);
8875: }
8876:
8877: fwrb_char_etc(fp,cp,etc)
8878: FILE *fp;
8879: Char *cp;
8880: Ident etc;
8881: { static Ident parts = (IsInterp|IsBlob|IsShapes|IsBfeats|IsSfeats);
8882: Char ch;
8883: if((etc&parts)!=parts) /* write selected parts */ {
8884: ch = *cp;
8885: if(!(etc&IsInterp)) ch.il.mny=0;
8886: if(!(etc&IsBlob)) ch.bmny=0;
8887: if(!(etc&IsSfeats)) ch.sfv = NULL;
8888: if(!(etc&IsShapes)) ch.sh = empty_Shapes;
8889: if(!(etc&IsBfeats)) ch.bfsp = NULL;
8890: cp = &ch; /* write modified record */
8891: };
8892: fwrb_char(fp,cp);
8893: if(cp->sfv!=NULL) fwrb_sfeats(fp,cp->sfv);
8894: if(cp->sh.mny>0) fwrb_shapes(fp,&(cp->sh));
8895: #if CPU!=CRAY
8896: if(cp->bfsp!=NULL) fwrb_bfeats(fp,cp->bfsp);
8897: #endif
8898: fwrb_interpl_etc(fp,cp->il,etc);
8899: if(cp->bmny>0) fwrb_blobl_etc(fp,cp->bmny,cp->fi,etc);
8900: }
8901:
8902: #if FRDI
8903: int frdb_char(f,p)
8904: FILE *f;
8905: Char *p;
8906: { int sf_mny,bf_mny;
8907: *p = empty_Char;
8908: if(feof(f))
8909: return(0);
8910: p->ident=frdi_Ident(f);
8911: frdi_Bbx(f,&(p->bx));
8912: p->csp=frdi_Scoor(f);
8913: p->area=frdi_uint4(f);
8914: p->per=frdi_uint4(f);
8915: p->basl=frdi_Scoor(f);
8916: p->bmny=frdi_uint3(f);
8917: p->il.mny=frdi_uint2(f);
8918: if((sf_mny=frdi_uint1(f))>0) {
8919: if((p->sfv=(Pval *)malloc(sf_mny*sizeof(Pval)))==NULL)
8920: abort("frdb_char: can't alloc p->sfv[%d]",sf_mny);
8921: memset(p->sfv,'\0',sf_mny*sizeof(Pval));
8922: };
8923: p->sh.mny=frdi_uint2(f);
8924: if((bf_mny=frdi_uint2(f))>0) {
8925: p->bfsp = alloc_bfeats(bf_mny,0);
8926: };
8927: #if dbg_frdb
8928: if((!(p->ident&IsChar))||(p->ident&(IsALL&(~IsChar))))
8929: err("frdb_char: %s",char_toa(p));
8930: #endif
8931: #if dbg_frdb_toa
8932: err("frdb_char: %s",char_toa(p));
8933: #endif
8934: if(p->ident&Char_label) p->l = frdb_label(f);
8935: if(p->ident&Char_ranparms) {
8936: p->rp = alloc_ranparms();
8937: frdb_ranparms(f,p->rp);
8938: };
8939: if(ferror(f)) return(-errno); else return(1);
8940: }
8941: #else
8942: int frdb_char(fp,cp)
8943: FILE *fp;
8944: Char *cp;
8945: { CharF cf;
8946: int stat;
8947: if((stat=fread(&cf,sizeof(CharF),1,fp))!=1)
8948: abort("frdb_char: can't read CharF, status %d",stat);
8949: *cp = empty_Char;
8950: cp->ident = cf.ident;
8951: cp->bx = cf.bx;
8952: cp->csp = cf.csp;
8953: cp->area = cf.area;
8954: cp->per = cf.per;
8955: cp->basl = 0;
8956: cp->bmny = cf.bmny;
8957: cp->il.mny = cf.imny;
8958: if(cf.sfmny>0) {
8959: if((cp->sfv=(Pval *)malloc(SF_MNY*sizeof(Pval)))==NULL)
8960: abort("frdb_char: can't alloc cp->sfv[%d]",SF_MNY);
8961: memset(cp->sfv,'\0',SF_MNY*sizeof(Pval));
8962: }
8963: else cp->sfv = NULL;
8964: cp->sh.mny = cf.shmny;
8965: #if CPU!=CRAY
8966: #if dbg_frdb
8967: if((!(cp->ident&IsChar))||(cp->ident&(IsALL&(~IsChar))))
8968: err("frdb_char: %s",char_toa(cp));
8969: #endif
8970: #endif
8971: #if dbg_frdb_toa
8972: err("frdb_char: %s",char_toa(cp));
8973: #endif
8974: if(cp->ident&Char_ranparms) {
8975: cp->rp = alloc_ranparms();
8976: frdb_ranparms(fp,cp->rp);
8977: };
8978: if(cp->ident&Char_label) cp->l = frdb_label(fp);
8979: #if CPU!=CRAY
8980: if(cf.bfmny>0) cp->bfsp = alloc_bfeats(cf.bfmny,0);
8981: else
8982: #endif
8983: cp->bfsp = NULL;
8984: if(ferror(fp)) return(-errno); else return(1);
8985: }
8986: #endif
8987:
8988: frdb_char_etc(fp,cp,etc)
8989: FILE *fp;
8990: Char *cp;
8991: Ident etc;
8992: { frdb_char(fp,cp);
8993: if(cp->sfv!=NULL) frdb_sfeats(fp,cp->sfv);
8994: if(cp->sh.mny>0) frdb_shapes(fp,&(cp->sh));
8995: #if CPU!=CRAY
8996: if(cp->bfsp!=NULL) {
8997: frdb_bfeats(fp,cp->bfsp);
8998: };
8999: #endif
9000: if(cp->il.mny>0) {
9001: frdb_interpl_etc(fp,&(cp->il),etc);
9002: /**if(!(etc&IsInterp)) free_interpl_etc(&(cp->il),IsALL);**/
9003: };
9004: if(etc&IsBlob && cp->bmny>0)
9005: frdb_blobl_etc(fp,cp->bmny,&(cp->fi),etc);
9006: else { cp->bmny = 0; cp->fi = NULL; };
9007: if(ferror(fp)) return(-errno); else return(1);
9008: }
9009:
9010: /* read a set of chars, and parts */
9011: frdb_chars_etc(fp,csp,etc)
9012: FILE *fp;
9013: Chars *csp;
9014: Ident etc;
9015: { int ci;
9016: register Char *cp,**cpp;
9017: if(csp->mny<=0) {
9018: *csp = empty_Chars;
9019: return(1);
9020: };
9021: if((cpp=csp->cpa=(Char **)malloc((csp->mny+1)*sizeof(Char *)))==NULL)
9022: abort("frdb_chars_etc: can't alloc Chars.cpa array");
9023: for(ci=0; ci<csp->mny; ci++) {
9024: *(cpp++) = cp = alloc_char();
9025: frdb_char_etc(fp,cp,etc);
9026: };
9027: *cpp = NULL;
9028: if(ferror(fp)) return(-errno); else return(1);
9029: }
9030:
9031: /* return a pointer to a distinct and duplicate copy of *cp;
9032: it is created out of malloc space.
9033: RanParms & label are treated as an integral part of the Char. */
9034: Char *dup_char(cp)
9035: Char *cp;
9036: { Char *dup;
9037: if((dup=(Char *)malloc(sizeof(Char)))==NULL)
9038: abort("can't dup Char");
9039: alloc_census(Char,1);
9040: *dup = *cp;
9041: if(dup->ident&Char_label && dup->l!=NULL)
9042: dup->l = strdup(cp->l);
9043: else {dup->ident &= ~Char_label; dup->l = NULL;};
9044: if(dup->ident&Char_ranparms && dup->rp!=NULL)
9045: dup->rp = dup_ranparms(cp->rp);
9046: else {dup->ident &= ~Char_ranparms; dup->rp = NULL;};
9047: return(dup);
9048: }
9049:
9050: /* return a pointer to a distinct and duplicate copy of *cp and those of
9051: its lists as specified by etc. (Does not conform to practice for dup_word_etc.)
9052: */
9053: Char *dup_char_etc(cp,etc)
9054: Char *cp;
9055: Ident etc;
9056: { Char *dup;
9057: dup = dup_char(cp);
9058: if(dup->bmny>0&&etc&IsBlob) dup->fi = dup_blobl_etc(cp->fi,etc);
9059: else {dup->bmny=0; dup->fi=NULL;};
9060: if(dup->il.mny>0&&etc&IsInterp) dup->il = *dup_interpl_etc(&(cp->il),etc);
9061: else dup->il = empty_Interpl;
9062: /**
9063: if(dup->sfv!=NULL>0&&etc&IsSfeats) dup->sfv = dup_sfeats(cp->sfv);
9064: else dup->sfv = NULL;
9065: if(dup->sh.mny>0&&etc&IsShapes) dup->sh = *dup_shapes(&cp->sh);
9066: else dup->sh = empty_Shapes;
9067: **/
9068: #if CPU!=CRAY
9069: if(dup->bfsp!=NULL>0&&etc&IsBfeats) dup->bfsp = dup_bfeats(cp->bfsp);
9070: else
9071: #endif
9072: dup->bfsp = NULL;
9073: return(dup);
9074: }
9075:
9076: /* Return a pointer to a local static duplicate of non-empty *csp.
9077: Its cpa array is new, created out of malloc space.
9078: If etc&IsChar, all its Characters are also duplicated,
9079: else the contents of cpa point to the old unduplicated Chars.
9080: */
9081: Chars *dup_chars_etc(csp,etc)
9082: Chars *csp;
9083: Ident etc; /* parts to duplicate */
9084: { static Chars dup;
9085: register Char **cpp,**dpp;
9086: if((dup.mny=csp->mny)<=0) dup = empty_Chars;
9087: else { if((dup.cpa=(Char **)malloc((dup.mny+1)*sizeof(Char *)))==NULL)
9088: abort("can't dup cs.cpa");
9089: for(cpp=csp->cpa,dpp=dup.cpa; (*cpp)!=NULL; cpp++,dpp++) {
9090: if(etc&IsChar) *dpp = dup_char_etc(*cpp,etc);
9091: else *dpp = *cpp;
9092: };
9093: *dpp = NULL;
9094: };
9095: return(&dup);
9096: }
9097:
9098: err_chars(p)
9099: Chars *p;
9100: { register Char **cpp;
9101: fprintf(stderr,"Chars %d: ",p->mny);
9102: if(p->mny>0) for(cpp=p->cpa; (*cpp)!=NULL; cpp++)
9103: fprintf(stderr,"%X ",*cpp);
9104: fprintf(stderr,"\n");
9105: }
9106:
9107: /* Make a Char out of a single Blob. Return a freshly-allocated Char
9108: that owns the given Blob as is (not duplicated, copied or freed).
9109: The Blob's next pointer is set to NULL. */
9110: Char *char_of_blob(b)
9111: Blob *b;
9112: { Char *c;
9113: c=alloc_char();
9114: c->bx = b->bx;
9115: c->area = b->area;
9116: c->per = b->per;
9117: c->bmny = 1;
9118: c->fi = b;
9119: b->n = NULL;
9120: return(c);
9121: }
9122:
9123: Interp *alloc_interp()
9124: { Interp *new;
9125: if((new=(Interp *)malloc(sizeof(Interp)))==NULL)
9126: abort("alloc_interp: can't malloc");
9127: alloc_census(Interp,1);
9128: *new = empty_Interp;
9129: return(new);
9130: }
9131:
9132: Interp *dup_interp(ip)
9133: Interp *ip;
9134: { Interp *dup;
9135: if((dup=(Interp *)malloc(sizeof(Interp)))==NULL)
9136: abort("dup_interp: can't malloc");
9137: alloc_census(Interp,1);
9138: *dup = *ip;
9139: return(dup);
9140: }
9141:
9142: /* Print the interpl */
9143: fwra_interpl(fp,ilp)
9144: FILE *fp;
9145: Interpl *ilp;
9146: { register Interp *cp;
9147: fprintf(fp,"Interpl[%d] ",ilp->mny);
9148: for(cp=ilp->fi; cp!=NULL; cp=cp->n) {
9149: fprintf(fp," %s --",interp_toa(cp));
9150: };
9151: fprintf(fp,"\n");
9152: }
9153:
9154: /* Print the interpl very briefly */
9155: fwra_interpl_brief(fp,ilp)
9156: FILE *fp;
9157: Interpl *ilp;
9158: { register Interp *ip;
9159: for(ip=ilp->fi; ip!=NULL; ip=ip->n) {
9160: fprintf(fp,"%s %s ",ip->ci.c,merit_toa(ip->m));
9161: };
9162: fprintf(fp,"\n");
9163: }
9164:
9165: err_interpl(ilp)
9166: Interpl *ilp;
9167: { fwra_interpl(stderr,ilp);
9168: }
9169:
9170: /* return the address of a local static copy of the given Interpl,
9171: for which each Interp is a duplicate of those in the given list */
9172: Interpl *dup_interpl_etc(ilp,etc)
9173: Interpl *ilp;
9174: Ident etc;
9175: { static Interpl lis;
9176: register Interp *cp,*pp,*dp;
9177: lis = *ilp;
9178: if(ilp->fi==NULL) return(NULL);
9179: for(pp=NULL,cp=ilp->fi; cp!=NULL; pp=dp,cp=cp->n) {
9180: dp=dup_interp(cp);
9181: if(pp==NULL) lis.fi = dp;
9182: else pp->n = dp;
9183: };
9184: pp->n=NULL;
9185: return(&lis);
9186: }
9187:
9188: /* Return a pointer to a local static duplicate of *isp.
9189: Its pa array is new, created out of malloc space.
9190: If etc&IsInterp, all its Interps are also duplicated,
9191: else the contents of pa point to the old unduplicated Interps.
9192: */
9193: Interps *dup_interps_etc(isp,etc)
9194: Interps *isp;
9195: Ident etc; /* parts to duplicate */
9196: { static Interps dup;
9197: register Interp **ipp,**dpp;
9198: dup = *isp;
9199: if(dup.mny<=0) dup = empty_Interps;
9200: else { if((dup.pa=(Interp **)malloc((dup.mny+1)*sizeof(Interp *)))==NULL)
9201: abort("can't dup (Interp *)is.pa[%d]",(dup.mny+1));
9202: for(ipp=isp->pa,dpp=dup.pa; *ipp!=NULL; ipp++,dpp++) {
9203: if(etc&IsInterp) *dpp = dup_interp(*ipp);
9204: else *dpp = *ipp;
9205: };
9206: *dpp = NULL;
9207: };
9208: return(&dup);
9209: }
9210:
9211: free_interps_etc(isp,etc)
9212: Interps *isp;
9213: Ident etc; /* parts to free */
9214: { register Interp **ipp,**dpp;
9215: if(etc&IsInterp) {
9216: /* free contents */
9217: for(ipp=isp->pa; *ipp!=NULL; ipp++) free_interp(*ipp);
9218: };
9219: if(isp->pa!=NULL) { free(isp->pa); isp->pa = NULL; };
9220: isp->mny = 0;
9221: }
9222:
9223: /* remove a char from a chars set */
9224: remove_char(cp,csp)
9225: Char *cp;
9226: Chars *csp;
9227: { register Char *rp,**rpp,**npp;
9228: if(csp->mny==0) err("remove_char: can't - Chars empty");
9229: else { for(rp= *(rpp=csp->cpa); rp!=NULL; rp= *(++rpp)) if(rp==cp) break;
9230: if(rp==NULL) err("remove_char: can't - not found");
9231: else { /* move later entries up */
9232: npp=rpp+1;
9233: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
9234: if((--(csp->mny))==0) {free(csp->cpa); csp->cpa=NULL;};
9235: /* don't bother to realloc downwards */
9236: };
9237: };
9238: }
9239:
9240: /* Append a char to the end of a chars set.
9241: Do NOT attempt to maintain Chars in order sorted ascending on Char.bx.a.x.
9242: Return appended Char *. */
9243: Char *append_char(cp,csp)
9244: Char *cp;
9245: Chars *csp;
9246: { register Char *rp,**rpp,**npp;
9247: if(csp->mny==0) {
9248: if((csp->cpa=(Char **)malloc(2*sizeof(Char *)))==NULL)
9249: abort("append_char: can't malloc csp->cpa[%d]",2);
9250: }
9251: else { if((csp->cpa=(Char **)realloc(
9252: csp->cpa,
9253: (csp->mny+2)*sizeof(Char *))
9254: )==NULL)
9255: abort("append_char: can't realloc csp->cpa[%d]",
9256: (csp->mny+2));
9257: };
9258: csp->cpa[csp->mny] = cp;
9259: csp->cpa[++csp->mny] = NULL;
9260: return(cp);
9261: }
9262:
9263: /* Insert a Char into a Chars set. Chars is assumed to be sorted ascending
9264: on on Char.bx.a.x, and this order is maintained.
9265: Return inserted Char * */
9266: Char *insert_char(cp,csp)
9267: Char *cp;
9268: Chars *csp;
9269: { register Char **cpp,*ncp,*pcp;
9270: if(csp->mny==0) {
9271: if((csp->cpa=(Char **)malloc(2*sizeof(Char *)))==NULL)
9272: abort("insert_char: can't malloc csp->cpa[%d]",2);
9273: csp->cpa[csp->mny] = cp;
9274: }
9275: else { if((cpp=csp->cpa=(Char **)realloc(
9276: csp->cpa,
9277: (csp->mny+2)*sizeof(Char *))
9278: )==NULL)
9279: abort("insert_char: can't realloc csp->cpa[%d]",csp->mny+2);
9280: while(((*cpp)!=NULL)&&(*cpp)->bx.a.x<cp->bx.a.x) cpp++;
9281: /* **cpp is now 1st entry >= *cp in sorted order */
9282: pcp=cp;
9283: do { ncp= *cpp;
9284: *(cpp++)=pcp;
9285: pcp=ncp;
9286: }
9287: while(pcp!=NULL);
9288: };
9289: csp->cpa[++csp->mny] = NULL;
9290: return(cp);
9291: }
9292:
9293: /* Append the contents of a "source" chars set to a "destination" chars set.
9294: Merely copy (Char *) pointers: don't duplicate Chars.
9295: Do NOT attempt to maintain Chars in order sorted ascending on Char.bx.a.x.
9296: Return destination (Chars *). */
9297: Chars *append_chars(s,d)
9298: Chars *s; /* source */
9299: Chars *d; /* destination */
9300: { register Char *rp,**rpp,**npp;
9301: if(s->mny==0) return(d);
9302: if(d->mny==0) {
9303: if((d->cpa=(Char **)malloc((s->mny+1)*sizeof(Char *)))==NULL)
9304: abort("append_chars: can't malloc d->cpa[%d]",2);
9305: }
9306: else { if((d->cpa=(Char **)realloc(
9307: d->cpa,
9308: (d->mny+s->mny+1)*sizeof(Char *))
9309: )==NULL)
9310: abort("append_chars: can't realloc d->cpa[%d]",
9311: (d->mny+s->mny+1));
9312: };
9313: memcpy(d->cpa+d->mny,s->cpa,(s->mny+1)*sizeof(Char *));
9314: d->mny += s->mny;
9315: return(d);
9316: }
9317:
9318: /* Insert a Char into the Chars owned by a given Word,
9319: maintaining order in set, and updating the Word's bx */
9320: Char *insert_char_word(cp,wp)
9321: Char *cp;
9322: Word *wp;
9323: { merge_bbx(&(cp->bx),&(wp->bx));
9324: return(insert_char(cp,&(wp->cs)));
9325: }
9326:
9327: free_char_etc(p,etc)
9328: Char *p; /* !=NULL */
9329: Ident etc;
9330: { if(etc&IsBlob) free_blobl_etc(&(p->bmny),&(p->fi),etc);
9331: if(etc&IsInterp) free_interpl(&(p->il));
9332: if(etc&IsSfeats && p->sfv!=NULL) { free(p->sfv); p->sfv=NULL; };
9333: if(etc&IsShapes) free_shapes(&(p->sh));
9334: #if CPU!=CRAY
9335: if(etc&IsBfeats && p->bfsp!=NULL) { free_bfeats(p->bfsp); p->bfsp=NULL; };
9336: #endif
9337: if(etc&IsChar) {
9338: if(p->ident&Char_label && p->l!=NULL) {
9339: free(p->l); p->l=NULL;
9340: p->ident &= ~Char_label;
9341: };
9342: if(p->ident&Char_ranparms && p->rp!=NULL) {
9343: free_ranparms(p->rp); p->rp=NULL;
9344: p->ident &= ~Char_ranparms;
9345: };
9346: free(p);
9347: free_census(Char,1);
9348: };
9349: }
9350:
9351: /* Unconditionally free the malloc-space array of pointers, and empty the set.
9352: Don't free the records that it owned.
9353: */
9354: free_chars(csp)
9355: Chars *csp;
9356: { if(csp->cpa!=NULL) { free(csp->cpa); csp->cpa = NULL; }
9357: csp->mny = 0;
9358: }
9359:
9360: free_chars_etc(csp,etc)
9361: Chars *csp;
9362: Ident etc;
9363: { register Char *cp,**cpp;
9364: if(csp->mny>0&&(etc&IsChar))
9365: for(cp= *(cpp=csp->cpa); cp!=NULL; cp= *(++cpp))
9366: free_char_etc(cp,etc);
9367: free_chars(csp);
9368: }
9369:
9370: /** Blob handling:
9371: alloc_blob_pool(sz,debug) - create pool of free blob records
9372: free_blob_pool() - free the pool
9373: Blob *alloc_blob() - allocate a new blob (in pool)
9374: free_blob(bp) - free a specified blob
9375: free_blob_runs(bp) - free a blob & the runs in its blob set
9376: free_blobl_etc(int *,Blob **,etc) - free blobs etc in char's blob list
9377: out_blob(bp) - print (ascii) to stdout
9378: fwrb_blob(fp,bp) - write binary Blob (only) to fp
9379: fwrb_blob_etc(fp,bp,etc) - write binary Blob & specified parts to fp
9380: frdb_blob_etc(fp,bp,etc) - read binary Blob & parts in specified form
9381: frdb_runfs(fp,bp,max) - read *bp's (binary) RunF's from fp
9382: err_blob(s,bp) - print (ascii) to stderr
9383: err_blob_runs(s,bp) - print Blob & its Runs (ascii) to stderr
9384: err_blob_runfs(s,bp) - print Blob & its RunFs (ascii) to stderr
9385: err_blob_briefly(s,bp) - print (ascii) to stderr
9386: err_blobf(s,bp) - print file-format blob (ascii) to stderr
9387: err_blob_stats() - report blob statistics
9388: blob_small(bp) - test whether its runs' data can be compressed to chars
9389: BUGS
9390: most fread/fwrite/fseek should be read/write/lseek, for speed
9391: -- but how to choose?
9392: **/
9393:
9394: /* make (empty) pool of `size' Blobs (return F if can't allocate) */
9395: boolean alloc_blob_pool(size,dbg)
9396: int size;
9397: boolean dbg;
9398: { register Blob *cbp, *cbq, *pbp;
9399: blob_max=size;
9400: if((blob_pool=(Blob *)malloc(blob_max*sizeof(Blob)))==NULL) return(F);
9401: blob_debug = dbg;
9402: pbp= &blob_fr;
9403: /* link up all blobs into free list using only first-ptrs */
9404: for(cbq=(cbp=blob_pool)+blob_max; cbp<cbq; cbp++) {
9405: pbp->n = cbp;
9406: pbp = cbp;
9407: };
9408: pbp->n = NULL; /* marks end of free list */
9409: blob_fr_mny = blob_max; blob_hi=0; blob_chopped = 0;
9410: hi_blob_no = 0;
9411: return(T);
9412: }
9413:
9414: free_blob_pool()
9415: { free(blob_pool);
9416: }
9417:
9418: Blob *alloc_blob()
9419: { Blob *p;
9420: if((p=(Blob *)malloc(sizeof(Blob)))==NULL)
9421: abort("alloc_blob: can't");
9422: alloc_census(Blob,1);
9423: *p = empty_Blob;
9424: return(p);
9425: }
9426:
9427: /* Unconditionally free this Blob record. */
9428: free_blob(bp)
9429: Blob *bp;
9430: { free(bp);
9431: free_census(Blob,1);
9432: }
9433:
9434: /* Allocate new Blob record and assign to it the next blob no */
9435: Blob *alloc_pool_blob()
9436: { register Blob *bp;
9437: if((bp = blob_fr.n)==NULL) {
9438: err("too many alloc_blob() calls - aborting:");
9439: #ifdef STATS
9440: err_blob_stats();
9441: #endif
9442: exit(1);
9443: };
9444: blob_fr.n = bp->n;
9445: #ifdef STATS
9446: blob_fr_mny--;
9447: if(blob_hi<(blob_max-blob_fr_mny)) blob_hi = blob_max-blob_fr_mny;
9448: #endif
9449: bp->no = hi_blob_no++;
9450: return(bp);
9451: }
9452:
9453: free_pool_blob(bp)
9454: Blob *bp;
9455: {
9456: if(blob_debug&&bp==NULL) abort("free_pool_blob: can't free a NULL Blob");
9457: #ifdef STATS
9458: blob_fr_mny++;
9459: if(blob_debug&&(blob_fr_mny>blob_max)) {
9460: err("free_pool_blob: too many free_blob() calls - aborting:");
9461: #ifdef STATS
9462: err_blob_stats();
9463: #endif
9464: exit(1);
9465: };
9466: #endif
9467: bp->n = blob_fr.n;
9468: blob_fr.n = bp;
9469: }
9470:
9471: /* free the runs belonging to this blob */
9472: free_runs(bp)
9473: Blob *bp;
9474: { register Run *crp,*nrp;
9475: if(bp->ident&Runs_ff) {
9476: if(bp->r.ff!=NULL) free(bp->r.ff);
9477: bp->r.ff=NULL;
9478: }
9479: else if(bp->ident&Runs_f) {
9480: for(crp=bp->r.f; crp!=NULL; crp=nrp) {
9481: nrp=crp->n;
9482: free_run(crp);
9483: };
9484: }
9485: else if(bp->ident&Runs_seek) /* none to free */ ;
9486: }
9487:
9488: /* free blob *bp and those parts (runs) specified */
9489: free_blob_etc(bp,etc)
9490: Blob *bp;
9491: Ident etc;
9492: { if(etc&IsRun) free_runs(bp);
9493: if(etc&IsBlob) free_blob(bp);
9494: }
9495:
9496: /* return a pointer to a distinct and duplicate copy of *bp;
9497: it is created out of malloc space */
9498: Blob *dup_blob(bp)
9499: Blob *bp;
9500: { Blob *dup;
9501: if((dup=(Blob *)malloc(sizeof(Blob)))==NULL)
9502: abort("dup_blob: can't malloc");
9503: alloc_census(Blob,1);
9504: *dup = *bp;
9505: return(dup);
9506: }
9507:
9508: /* return a pointer to a distinct and duplicate copy of *bp and what it owns,
9509: as described by etc; created out of malloc space */
9510: Blob *dup_blob_etc(bp,etc)
9511: Blob *bp;
9512: Ident etc;
9513: { Blob *dup;
9514: dup = dup_blob(bp);
9515: if(bp->runs>0) {
9516: if(bp->ident&Runs_ff) {
9517: int ri;
9518: RunF *rp,*drp;
9519: if((dup->r.ff=
9520: (RunF *)malloc(bp->runs*sizeof(RunF)))==NULL)
9521: abort("dup_blob_etc: can't malloc RunF[%d]",
9522: bp->runs);
9523: for(ri=0,rp=bp->r.ff,drp=dup->r.ff; ri<bp->runs; ri++)
9524: *(drp++) = *(rp++);
9525: }
9526: else abort("dup_blob_etc: only Runs_ff implemented");
9527: };
9528: return(dup);
9529: }
9530:
9531: /* Return a pointer to a local static duplicate of non-empty *bsp.
9532: Its bpa array is created newly out of malloc space.
9533: If etc&IsBlob, all its Blobs are also fresh duplicates,
9534: else the contents of bpa point to the old unduplicated Blobs.
9535: */
9536: Blobs *dup_blobs_etc(bsp,etc)
9537: Blobs *bsp;
9538: Ident etc; /* parts to duplicate */
9539: { static Blobs dup;
9540: register Blob **bpp,**dpp;
9541: if((dup.mny = bsp->mny)<=0) dup = empty_Blobs;
9542: else { if((dup.bpa=(Blob **)malloc((dup.mny+1)*sizeof(Blob *)))==NULL)
9543: abort("dup_blobs_etc: can't malloc bs.bpa[%d]",dup.mny+1);
9544: for(bpp=bsp->bpa,dpp=dup.bpa; *bpp!=NULL; bpp++,dpp++) {
9545: if(etc&IsBlob) *dpp = dup_blob_etc(*bpp,etc);
9546: else *dpp = *bpp;
9547: };
9548: *dpp = NULL;
9549: };
9550: return(&dup);
9551: }
9552:
9553: /* Split the given Blobs into two, *b0 & *b1, according to the value 0 or !0
9554: respectively returned by the function s(b,a) applied to each Blob *b and
9555: blind argument *a.
9556: s() will be evaluated exactly once for each Blob, and the Blob's will be
9557: assigned in the order found in the original Blobs. Only pointers to Blob's
9558: are created; the Blob's themselves are not duplicated. The original Blobs
9559: record is unchanged.
9560: */
9561: split_blobs(b,s,a,b0,b1)
9562: Blobs *b;
9563: int (*s)();
9564: VOID *a; /* passed transparently to s() */
9565: Blobs *b0,*b1;
9566: { char *sel,*sp;
9567: register Blob *bp,**bpp;
9568: Blob **b0pp;
9569: Blob **b1pp;
9570: *b0 = *b1 = empty_Blobs;
9571: if(b->mny<=0) return;
9572: if((sel=(char *)malloc(b->mny))==NULL)
9573: abort("split_blobs: can't malloc sel[%d]",b->mny);
9574: for(bp= *(bpp=b->bpa),sp=sel; bp!=NULL; bp= *(++bpp),sp++)
9575: if(*sp = s(bp,a)) b1->mny++; else b0->mny++;
9576: if(b0->mny>0)
9577: if((b0->bpa=(Blob **)malloc((b0->mny+1)*sizeof(Blob *)))==NULL)
9578: abort("split_blobs: can't malloc b0->bpa[%d]",b0->mny+1);
9579: if(b1->mny>0)
9580: if((b1->bpa=(Blob **)malloc((b1->mny+1)*sizeof(Blob *)))==NULL)
9581: abort("split_blobs: can't malloc b1->bpa[%d]",b1->mny+1);
9582: b0pp=b0->bpa;
9583: b1pp=b1->bpa;
9584: for(bp= *(bpp=b->bpa),sp=sel; bp!=NULL; bp= *(++bpp),sp++)
9585: if(*sp) *(b1pp++)=bp; else *(b0pp++)=bp;
9586: if(b0->mny>0) *b0pp=NULL;
9587: if(b1->mny>0) *b1pp=NULL;
9588: free(sel);
9589: }
9590:
9591: /* Return the address of the first in a list of Blobs, duplicated from
9592: the given list. */
9593: Blob *dup_blobl_etc(bp,etc)
9594: Blob *bp;
9595: Ident etc;
9596: { Blob *fi,*cp,*pp,*dp;
9597: if(bp==NULL) return(NULL);
9598: for(pp=NULL,cp=bp; cp!=NULL; pp=dp,cp=cp->n) {
9599: dp=dup_blob_etc(cp,etc);
9600: if(pp==NULL) fi = dp;
9601: else pp->n = dp;
9602: };
9603: pp->n=NULL;
9604: return(fi);
9605: }
9606:
9607: /* Prepend this blob to the given Char's bloblist; update Char's bx, area, & per.
9608: Inverse of `remove_blobl()'. */
9609: Blob *insert_blobl(bp,cp)
9610: Blob *bp;
9611: Char *cp;
9612: { register Blob *pbp,*nbp;
9613: if(cp->bmny>0) bp->n = cp->fi;
9614: else bp->n = NULL;
9615: cp->fi = bp;
9616: cp->bmny++;
9617: merge_bbx(&(bp->bx),&(cp->bx));
9618: cp->area += bp->area;
9619: cp->per += bp->per;
9620: return(bp);
9621: }
9622:
9623: /* Remove this blob from a char's bloblist; update Char's bx, area, per.
9624: Inverse of `insert_blobl()'. */
9625: remove_blobl(bp,cp)
9626: Blob *bp;
9627: Char *cp;
9628: { Blob *rp,*pp;
9629: Bbx bx; /* Char's new Bbx */
9630: if(cp->bmny==1) { /* frequent case */
9631: cp->fi=NULL; cp->bmny=0;
9632: }
9633: else if(cp->bmny>1){
9634: bx=empty_Bbx;
9635: pp=NULL;
9636: for(rp=cp->fi; rp!=NULL; pp=rp,rp=rp->n) {
9637: if(rp==bp) break;
9638: else { if(bx.a.x > rp->bx.a.x) bx.a.x = rp->bx.a.x;
9639: if(bx.a.y > rp->bx.a.y) bx.a.y = rp->bx.a.y;
9640: if(bx.b.x < rp->bx.b.x) bx.b.x = rp->bx.b.x;
9641: if(bx.b.y < rp->bx.b.y) bx.b.y = rp->bx.b.y;
9642: };
9643: };
9644: if(rp!=NULL) { /* remove from list */
9645: if(pp==NULL) cp->fi=bp->n;
9646: else pp->n=bp->n;
9647: cp->bmny--;
9648: for(rp=bp->n; rp!=NULL; rp=rp->n) {
9649: if(bx.a.x > rp->bx.a.x) bx.a.x = rp->bx.a.x;
9650: if(bx.a.y > rp->bx.a.y) bx.a.y = rp->bx.a.y;
9651: if(bx.b.x < rp->bx.b.x) bx.b.x = rp->bx.b.x;
9652: if(bx.b.y < rp->bx.b.y) bx.b.y = rp->bx.b.y;
9653: };
9654: cp->bx = bx;
9655: }
9656: else err("remove_blobl: can't - not found");
9657: }
9658: else err("remove_blobl: can't - Blobl empty");
9659: cp->area -= bp->area;
9660: cp->per -= bp->per;
9661: }
9662:
9663: /* prepend this blob to the given Blob list */
9664: Blob *prepend_blobl(bp,blp)
9665: Blob *bp;
9666: Blobl *blp;
9667: { register Blob *pbp,*nbp;
9668: if(blp->mny>0) bp->n = blp->fi;
9669: else { bp->n = NULL;
9670: blp->la = bp;
9671: };
9672: blp->fi = bp;
9673: blp->mny++;
9674: return(bp);
9675: }
9676:
9677: /* append this blob to the given Blob list */
9678: Blob *append_blobl(bp,blp)
9679: Blob *bp;
9680: Blobl *blp;
9681: { register Blob *pbp,*nbp;
9682: if(blp->mny==0) blp->fi = bp;
9683: else blp->la->n = bp;
9684: blp->la = bp;
9685: bp->n = NULL;
9686: blp->mny++;
9687: return(bp);
9688: }
9689:
9690: /* remove a blob from a blobs set */
9691: remove_blob(bp,bsp)
9692: Blob *bp;
9693: Blobs *bsp;
9694: { register Blob *rp,**rpp,**npp;
9695: if(bsp->mny==0) err("remove_blob: can't - Blobs empty");
9696: else { for(rp= *(rpp=bsp->bpa); rp!=NULL; rp= *(++rpp)) if(rp==bp) break;
9697: if(rp==NULL) err("remove_blob: can't - not found");
9698: else { /* move later entries up */
9699: npp=rpp+1;
9700: do *(rpp++)= *(npp++); while ((*rpp)!=NULL);
9701: if((--(bsp->mny))==0) {free(bsp->bpa); bsp->bpa=NULL;};
9702: /* don't bother to realloc downwards */
9703: };
9704: };
9705: }
9706:
9707: /* Append a blob to the end of a blobs set.
9708: Return appended Blob *. */
9709: Blob *append_blob(p,sp)
9710: Blob *p;
9711: Blobs *sp;
9712: { register Blob *rp,**rpp,**npp;
9713: if(sp->mny==0) {
9714: if((sp->bpa=(Blob **)malloc(2*sizeof(Blob *)))==NULL)
9715: abort("append_blob: can't malloc sp->bpa[2]");
9716: }
9717: else { if((sp->bpa=(Blob **)realloc(
9718: sp->bpa,
9719: (sp->mny+2)*sizeof(Blob *))
9720: )==NULL)
9721: abort("append_blob: can't realloc sp->bpa[%d]",sp->mny+2);
9722: };
9723: sp->bpa[sp->mny] = p;
9724: sp->bpa[++sp->mny] = NULL;
9725: return(p);
9726: }
9727:
9728: /* Append Blobs *p1 to Blobs *p2. On return, *p1 is unchanged, *p2 is in general
9729: longer, and all the Blob's owned by *p1 are now also owned by *p2. */
9730: append_blobs_blobs(p1,p2)
9731: Blobs *p1,*p2;
9732: { int mny;
9733: register Blob **pp1,**pp2;
9734: if(p1->mny==0) return;
9735: if(p2->mny==0) { *p2 = *dup_blobs_etc(p1,IsNONE); return; };
9736: mny = p2->mny + p1->mny;
9737: if((p2->bpa=(Blob **)realloc(p2->bpa,(mny+1)*sizeof(Blob *)))==NULL)
9738: abort("append_blobs_blobs: can't realloc p2->bpa[%d]",mny+1);
9739: pp1=p1->bpa; pp2=p2->bpa+p2->mny; while(*pp1!=NULL) *(pp2++) = *(pp1++);
9740: *pp2 = NULL;
9741: p2->mny = mny;
9742: }
9743:
9744: free_blobl_etc(mnyp,fip,etc)
9745: int *mnyp;
9746: Blob **fip;
9747: Ident etc;
9748: { register Blob *bp,*nbp;
9749: if(*mnyp>0) {
9750: for(bp= *fip; bp != NULL; bp=nbp)
9751: { nbp=bp->n; free_blob_etc(bp,etc); };
9752: };
9753: *mnyp=0;
9754: *fip=NULL;
9755: }
9756:
9757: /* Unconditionally free the malloc-space array of pointers, and empty the set.
9758: Don't free the records that it owned.
9759: */
9760: free_blobs(bsp)
9761: Blobs *bsp;
9762: { if(bsp->bpa!=NULL) { free(bsp->bpa); bsp->bpa=NULL; };
9763: bsp->mny = 0;
9764: }
9765:
9766: free_blobs_etc(bsp,etc)
9767: Blobs *bsp;
9768: Ident etc;
9769: { register Blob *bp, **bpp;
9770: if(bsp->mny>0&&(etc&IsBlob)) for(bp= *(bpp=bsp->bpa); bp!=NULL; bp= *(++bpp))
9771: free_blob_etc(bp,etc);
9772: free_blobs(bsp);
9773: }
9774:
9775: Blobs *blobl_to_blobs(blp)
9776: Blobl *blp;
9777: { static Blobs bs;
9778: register Blob *bp,**bpp;
9779: bs = empty_Blobs;
9780: bs.mny = blp->mny;
9781: if(bs.mny>0) {
9782: if((bs.bpa=(Blob **)malloc((bs.mny+1)*sizeof(Blob *)))==NULL)
9783: abort("blobl_to_blobs: can't malloc Blobs.bpa[%d]",bs.mny+1);
9784: for(bp=blp->fi,bpp=bs.bpa; bp!=NULL; bp=bp->n,bpp++)
9785: *bpp = bp;
9786: *bpp = NULL;
9787: };
9788: return(&bs);
9789: }
9790:
9791: int bp_tod(bp)
9792: Blob *bp;
9793: { if(bp==NULL) return(-2);
9794: else return(bp-blob_pool);
9795: }
9796:
9797: /* test whether for this Blob, each runs's data fields could all be compressed
9798: from a short to a char */
9799: boolean blob_small(bp)
9800: Blob *bp;
9801: { if(bp->runs>255) return(F);
9802: if(bbx_wid(&bp->bx)>255) return(F);
9803: if(bbx_hgt(&bp->bx)>255) return(F);
9804: return(T);
9805: }
9806:
9807: char *blob_toa(bp)
9808: Blob *bp;
9809: { char s1[80];
9810: static char s[80];
9811: Scoor hgt,wid;
9812: if(bp==NULL) strcpy(s,"NULL");
9813: else { hgt = bp->bx.b.y - bp->bx.a.y + 1;
9814: wid = bp->bx.b.x - bp->bx.a.x + 1;
9815: sprintf(s1,"%s bx%s w%d,h%d ar%d pe%d r.",
9816: ident_toa(bp->ident),
9817: bbx_toa(&(bp->bx)),
9818: wid,
9819: hgt,
9820: bp->area,
9821: bp->per
9822: );
9823: if(bp->ident&Runs_f) strcat(s1,"f");
9824: else if(bp->ident&Runs_ff) strcat(s1,"ff");
9825: else if(bp->ident&Runs_seek) strcat(s1,"sk");
9826: else if(bp->ident&Runs_g4) strcat(s1,"g");
9827: else strcat(s1,"?");
9828: sprintf(s,"%s%d",s1,bp->runs);
9829: };
9830: return(s);
9831: }
9832:
9833: /* compute the centroid of the Blob, w.r.t bx.a */
9834: Pp *blob_centroid(bp)
9835: Blob *bp;
9836: { static Pp c;
9837: RunF *rfp;
9838: int ri,area;
9839: c.x = c.y = 0.0;
9840: if(bp->ident&Runs_ff) {
9841: for(ri=0, rfp=bp->r.ff; ri<bp->runs; ri++, rfp++) {
9842: c.x += (area=(rfp->xe-rfp->xs+1)) * (rfp->xe+rfp->xs);
9843: c.y += area * rfp->y;
9844: };
9845: c.x /= 2.0*bp->area;
9846: c.y /= bp->area;
9847: }
9848: else abort("blob_centroid: only Runs_ff supported");
9849: return(&c);
9850: }
9851:
9852: /* write (printably) to stdout */
9853: out_blob(bp)
9854: Blob *bp;
9855: { Run *crp;
9856: static char pad[] = " ";
9857: short y;
9858: if(bp==NULL) fprintf(stderr,"Bb NULL.\n");
9859: else fprintf(stdout,"%s\n",blob_toa(bp));
9860: fprintf(stdout,"%sy%d:",pad,bp->bx.a.y);
9861: for(crp=bp->r.f,y=crp->y; crp!=NULL; crp=crp->n) {
9862: if(crp->y!=y) {
9863: fprintf(stdout,"\n%sy%d:",pad,crp->y);
9864: y=crp->y;
9865: };
9866: fprintf(stdout," [%d,%d]",crp->xs,crp->xe);
9867: };
9868: fprintf(stdout,"\n");
9869: }
9870:
9871: #if FWRI
9872: /* Write blob record (only) to FILE *f.
9873: Check whether Blob is ``small'' and label *p accordingly. */
9874: fwrb_blob(f,p)
9875: FILE *f;
9876: Blob *p;
9877: {
9878: #if dbg_fwrb
9879: if((!(p->ident&IsBlob))||(p->ident&(IsALL&(~IsBlob))))
9880: err("fwrb_blob: %s",blob_toa(p));
9881: #endif
9882: if(blob_small(p)) p->ident |= Blob_small; else p->ident &= ~Blob_small;
9883: fwri_Ident(f,p->ident);
9884: /* fwri_Seq(f,p->no); */
9885: fwri_Bbx(f,&(p->bx));
9886: fwri_uint4(f,p->area);
9887: fwri_uint4(f,p->per);
9888: /* don't write .n */
9889: fwri_Merit(f,p->m);
9890: fwri_uint3(f,p->runs);
9891: fwri_uint2(f,((p->bdsp==NULL)? 0: p->bdsp->mny));
9892: #if dbg_fwrb_toa
9893: err("fwrb_blob: %s",blob_toa(p));
9894: #endif
9895: }
9896: #else
9897: /* Write blob record (only) to FILE *fp.
9898: Check whether Blob is ``small'' and label *bp accordingly. */
9899: fwrb_blob(fp,bp)
9900: FILE *fp;
9901: Blob *bp;
9902: { BlobF bf;
9903: #if dbg_fwrb
9904: if((!(bp->ident&IsBlob))||(bp->ident&(IsALL&(~IsBlob))))
9905: err("fwrb_blob: %s",blob_toa(bp));
9906: #endif
9907: memset(&bf,'\0',sizeof(bf));
9908: if(blob_small(bp)) bp->ident |= Blob_small;
9909: else bp->ident &= ~Blob_small;
9910: bf.ident = bp->ident;
9911: bf.bx=bp->bx;
9912: bf.area=bp->area;
9913: bf.per=bp->per;
9914: bf.runs=bp->runs;
9915: if(bp->bdsp==NULL) bf.bdys=0;
9916: else bf.bdys=bp->bdsp->mny;
9917: if(blob_debug) err_blobf("",&bf);
9918: if(fwrite(&bf,sizeof(BlobF),1,fp)!=1)
9919: abort("fwrb_blob: can't fwrite");
9920: #if dbg_fwrb_toa
9921: err("fwrb_blob: %s",blob_toa(bp));
9922: #endif
9923: }
9924: #endif
9925:
9926: /* Write detailed description of Runs to stderr. */
9927: Blob *err_runs(name,bp)
9928: char *name;
9929: Blob *bp;
9930: { Run *rp;
9931: RunF *rfp,*rfe;
9932: int ri;
9933: if(bp->ident&Runs_f) {
9934: fprintf(stderr,"%s Runs_f[%d] in %s:\n",
9935: name,bp->runs,bbx_toa(&bp->bx));
9936: for(rp=bp->r.f,ri=0; rp!=NULL; rp=rp->n,ri++) {
9937: fprintf(stderr," %2d: %d[%d,%d]\n",
9938: ri,rp->y,rp->xs,rp->xe);
9939: };
9940: }
9941: else if(bp->ident&Runs_ff) {
9942: fprintf(stderr,"%s Runs_ff[%d] in %s: ",
9943: name,bp->runs,bbx_toa(&(bp->bx)));
9944: for(rfe=(rfp=bp->r.ff)+bp->runs,ri=0; rfp<rfe; rfp++,ri++) {
9945: fprintf(stderr," %d:%d[%d,%d]",
9946: ri,rfp->y,rfp->xs,rfp->xe);
9947: };
9948: fprintf(stderr,"\n");
9949: }
9950: else if(bp->ident&Runs_seek) {
9951: goto unsupported;
9952: }
9953: else { goto unsupported;
9954: };
9955: return;
9956: unsupported:
9957: abort("err_runs: %s unsupported",ident_toa(bp->ident));
9958: }
9959:
9960: /* Convert the type of Runs in *bp to the type specified by id.
9961: Supported: only bp->ident&Runs_f to id&Runs_ff.
9962: Return pointer to local static duplicate of *bp.
9963: */
9964: Blob *runs_to_runs(bp,id)
9965: Blob *bp;
9966: Ident id;
9967: { static Blob b;
9968: register Run *rp;
9969: RunF *rfp;
9970:
9971: b = *bp;
9972: if(bp->ident&Runs_f) {
9973: if(id&Runs_ff) {
9974: b.ident &= ~(Runs_f|Blob_small);
9975: b.ident |= Runs_ff;
9976: if(blob_small(bp)) b.ident |= Blob_small;
9977: if((b.r.ff=(RunF *)malloc(b.runs*sizeof(RunF)))==NULL)
9978: abort("runs_to_runs: can't malloc Blob.r.ff[%d]",
9979: b.runs); for(rp=bp->r.f,rfp=b.r.ff; rp!=NULL; rp=rp->n,rfp++) {
9980: /* y, xs, xe will be relative to Blob.bx.a */
9981: rfp->y = rp->y - bp->bx.a.y;
9982: rfp->xs = rp->xs - bp->bx.a.x;
9983: rfp->xe = rp->xe - bp->bx.a.x;
9984: /* above,below connecting indices are relative to
9985: the sequence no. of this run (ac>0 & bc>0) */
9986: if((rfp->ad = rp->ad)!=0)
9987: rfp->ac = rp->u.no - rp->ac->u.no;
9988: else rfp->ac = 0;
9989: if((rfp->bd = rp->bd)!=0)
9990: rfp->bc = rp->bc->u.no - rp->u.no;
9991: else rfp->bc = 0;
9992: if(0) err_runf(" ",rfp);
9993: };
9994: }
9995: else { goto unsupported;
9996: };
9997: }
9998: else if(bp->ident&Runs_ff) {
9999: if(bp->ident&Blob_small) {
10000: goto unsupported;
10001: }
10002: else { goto unsupported;
10003: };
10004: }
10005: else if(bp->ident&Runs_seek) {
10006: goto unsupported;
10007: }
10008: else { goto unsupported;
10009: };
10010: return(&b);
10011:
10012: unsupported:
10013: abort("runs_to_runs: %s --> %s unsupported",
10014: ident_toa(bp->ident),ident_toa(id));
10015: }
10016:
10017: #if CPU!=CRAY
10018: /* Write these RunFs to FILE *fp in CCITT Group 4 format.
10019: BUG: uses bitio to one end of a pipe, just to store the entire
10020: byte-stream so it can be counted; then, it is copied to *fp.
10021: This fails on large bitmaps since the space available for pipe
10022: buffering is limited by system constraints and can run out at any
10023: time (symptom: the user process hangs in I state). Also, since
10024: it relies so heavily on streams, it may not prove to be very portable.
10025: Should be rewritten with an expandable byte-buffer of some kind,
10026: which requires that the `putting' function in bitio be user-selectable.
10027: */
10028: fwrb_runfs_g4(fp,bxp,runs,ff)
10029: FILE *fp;
10030: Bbx *bxp;
10031: int runs;
10032: RunF *ff;
10033: #define dbg_fwrb_runfs_g4_detail F
10034: { RLE_Line l0,l1;
10035: RLE_Line *cl,*pl,*swap; /* current/prior/swap line */
10036: int wid,hgt; /* width,height of rectangular box of pixels */
10037: BITFILE *bf;
10038: int iri;
10039: RunF *irp;
10040: RLE_Run *crp;
10041: static int pipe_fd[2] = {-1,-1};
10042: static FILE *pipe_fp[2] = {NULL,NULL};
10043: unsigned long bytes,bi;
10044: int och;
10045: /* buffer g4 code in a pipe in order to count it */
10046: if(pipe_fd[0]==-1) {
10047: pipe(pipe_fd);
10048: if((pipe_fp[0] = fdopen(pipe_fd[0],"r"))==NULL)
10049: abort("fwrb_runfs_g4: can't open pipe \"r\", fd=%d",
10050: pipe_fd[0]);
10051: if((pipe_fp[1] = fdopen(pipe_fd[1],"w"))==NULL)
10052: abort("fwrb_runfs_g4: can't open pipe \"w\", fd=%d",
10053: pipe_fd[1]);
10054: /* leave this pipe open for the duration of the process */
10055: };
10056: /* treat pipe_fp[1] as a sequence of bits */
10057: if((bf=bopen(pipe_fp[1],"w"))==NULL)
10058: abort("fwrb_runfs_g4: can't open bitfile");
10059: wid = bbx_wid(bxp); hgt=bbx_hgt(bxp);
10060: BOF_to_g4(bf);
10061: cl= &l0; pl= &l1; cl->len = pl->len = wid; cl->y=0; pl->runs=0;
10062: iri=0; irp=ff;
10063: do { /* build current RLE_Line */
10064: crp=cl->r;
10065: while(iri<runs&&irp->y==cl->y) {
10066: crp->xs=irp->xs;
10067: crp->xe=irp->xe;
10068: if(dbg_fwrb_runfs_g4_detail)
10069: err("i%d: y%d x[%d,%d]",
10070: iri,cl->y,crp->xs,crp->xe);
10071: iri++; irp++; crp++;
10072: };
10073: cl->runs = crp-cl->r;
10074: /* write current RLE_line to file */
10075: rlel_to_g4(pl,cl,wid,bf);
10076: /* save current line as prior */
10077: swap=pl; pl=cl; cl=swap; cl->runs=0; cl->y=pl->y+1;
10078: }
10079: while(cl->y<hgt);
10080: /** By policy, don't append EOFB (i.e. omit EOF_to_g4(bf)) **/
10081: bytes = bclose(bf);
10082: if(dbg_fwrb_runs) err("fwrb_runfs_g4: %d bytes",bytes);
10083: #if FWRI
10084: fwri_uint4(fp,bytes);
10085: #else
10086: fwrite(&bytes,sizeof(bytes),1,fp);
10087: #endif
10088: /* copy contents in pipe to fp */
10089: fflush(pipe_fp[1]);
10090: for(bi=0;bi<bytes;bi++) {
10091: putc(och=getc(pipe_fp[0]),fp);
10092: #if dbg_fwrb_runs
10093: fprintf(stderr,"%02x",(unsigned char)och);
10094: #endif
10095: };
10096: if(dbg_fwrb_runs) fprintf(stderr,"\n");
10097: }
10098: #else
10099: fwrb_runfs_g4(fp,bxp,runs,ff)
10100: FILE *fp;
10101: Bbx *bxp;
10102: int runs;
10103: RunF *ff;
10104: { abort("fwrb_runfs_g4: unimplemented on Cray");
10105: }
10106: #endif
10107:
10108: #if CPU != CRAY
10109: /* Read a connected group of Runs in CCITT Group 4 format, into an array of RunFs.
10110: Return: 1 if normal & successful, 0 if EOF, and -1 if error.
10111: */
10112: int frdb_g4_runfs(fp,bxp,runs,ff)
10113: FILE *fp;
10114: Bbx *bxp; /* their bounding box, shrink-wrapped to fit exactly */
10115: int runs; /* expect exactly this number of runs */
10116: RunF *ff; /* space for `runs' RunFs */
10117: #define dbg_frdb_g4_runfs_detail F
10118: { RLE_Line *cl; /* current line */
10119: int wid,hgt; /* width,height of rectangular box of pixels */
10120: int y; /* height of current line */
10121: boolean bof;
10122: BITFILE *bf;
10123: static DST_table *tbl = NULL;
10124: int iri;
10125: RLE_Run *irp;
10126: int ori;
10127: RunF *orp;
10128: unsigned long bytes,g4_bytes;
10129: #if FRDI
10130: bytes=frdi_uint4(fp);
10131: #else
10132: fread(&bytes,sizeof(bytes),1,fp);
10133: #endif
10134: if(dbg_frdb_runs) err("frdb_g4_runfs: %d bytes",bytes);
10135: /* read FILE *fp as a sequence of bits */
10136: if((bf=bopen(fp,"r"))==NULL)
10137: abort("frdb_g4_runfs: can't open bitfile");
10138: if(tbl==NULL) {
10139: tbl=ccitt_table();
10140: if(dbg_frdb_g4_runfs_detail) ccitt_err_tbl(tbl);
10141: };
10142: wid=bbx_wid(bxp); hgt=bbx_hgt(bxp);
10143: y=0; bof=T; ori=0; orp=ff;
10144: while((y<hgt)&&(cl=g4_to_rlel(tbl,bf,bof,wid))!=NULL) {
10145: /* copy runs to RunF ff[] */
10146: for(iri=0,irp=cl->r; iri<cl->runs; iri++,irp++) {
10147: if(dbg_frdb_g4_runfs_detail)
10148: err("o%d i%d: y%d x[%d,%d]",
10149: ori,iri,y,irp->xs,irp->xe);
10150: if(ori<runs) {
10151: orp->y = y; orp->xs = irp->xs; orp->xe = irp->xe;
10152: orp++;
10153: }
10154: else err("frdb_g4_runfs: too many runs: ori%d >= runs%d",
10155: ori,runs);
10156: ori++;
10157: };
10158: y++; bof=F;
10159: };
10160: if(cl==NULL) {
10161: err("frdb_g4_runfs: unexpected EOF");
10162: return(0);
10163: };
10164: /* recover connectivity among runs, on the assumption that they
10165: are still in increasing lexicographic order on (y,xs) */
10166: fix_lag(orp-ff,(char *)ff,Runs_ff);
10167: if(ori!=runs) {
10168: err("frdb_g4_runfs: expected %d runs, but read %d",runs,ori);
10169: return(-1);
10170: };
10171: if((g4_bytes=bclose(bf))!=bytes) {
10172: err("frdb_g4_runfs: expected %d bytes, but read %d",
10173: bytes,g4_bytes);
10174: return(-1);
10175: };
10176: if(ferror(fp)) return(-errno); else return(1);
10177: }
10178: #else
10179: int frdb_g4_runfs(fp,bxp,runs,ff)
10180: FILE *fp;
10181: Bbx *bxp; /* exact bounding box, shrink-wrapped to fit */
10182: int runs; /* expect exactly this number of runs */
10183: RunF *ff; /* space for `runs' RunFs */
10184: { abort("frdb_g4_runfs: unimplemented on Cray");
10185: }
10186: #endif
10187:
10188: /* Write blob, etc to FILE *fp in binary format.
10189: If !(etc&IsBlob), then do nothing.
10190: else write Blob record and:
10191: If etc&IsRun, then also try to write Runs:
10192: If Blob.runs==0, write no runs.
10193: else
10194: if etc&Runs_g4, write in CCITT G4 format
10195: compact but needs large streams; may not port well;
10196: else write in Runs_ff format
10197: if blob is small enough, use compressed RunFS form on output.
10198:
10199: */
10200: fwrb_blob_etc(fp,bp,etc)
10201: FILE *fp;
10202: Blob *bp;
10203: Ident etc;
10204: { Ident sv_ident;
10205: int sv_runs;
10206: Run *rp;
10207: RunF rf;
10208: register RunF *rfp, *rfq;
10209: RunFS *rsp;
10210: #if FWRI
10211: RunFS rfs;
10212: #else
10213: static RunFS rfsa[256];
10214: #endif
10215: int ri;
10216: if(!(etc&IsBlob)) return;
10217:
10218: sv_ident = bp->ident;
10219: sv_runs = bp->runs;
10220: if(etc&IsRun) {
10221: /* decide which Runs_* bits should be set on output */
10222: bp->ident &= ~(Runs_f|Runs_ff|Runs_seek|Runs_g4);
10223: if(etc&Runs_g4) {
10224: bp->ident |= Runs_g4;
10225: }
10226: else { /* assume Runs_ff is wanted */
10227: bp->ident |= Runs_ff;
10228: };
10229: }
10230: else { bp->ident &= ~(IsRun|Runs_f|Runs_ff|Runs_seek|Runs_g4);
10231: bp->runs = 0;
10232: };
10233: fwrb_blob(fp,bp);
10234: bp->ident = sv_ident;
10235: bp->runs = sv_runs;
10236:
10237: if(bp->runs==0) return;
10238:
10239: if(etc&Runs_g4) {
10240: /* write CCITT Group 4 encoding for Runs */
10241: if(bp->ident&Runs_ff) {
10242: fwrb_runfs_g4(fp,&(bp->bx),bp->runs,bp->r.ff);
10243: }
10244: else abort("fwrb_blob_etc: etc&Runs_g4 but !(id&Runs_ff)");
10245: }
10246: else { /* Assume Runs_ff format is desired */
10247: if(bp->ident&Runs_f) {
10248: rp=bp->r.f;
10249: if(bp->ident&Blob_small) { /* use compressed Run records */
10250: if(blob_debug) err("small");
10251: /* can use small local static array */
10252: #if FWRI
10253: rsp= &rfs;
10254: #else
10255: rsp=rfsa;
10256: #endif
10257: while(rp!=NULL) {
10258: /* y, xs, xe will be relative to Blob.bx.a */
10259: rsp->y = rp->y - bp->bx.a.y;
10260: rsp->xs = rp->xs - bp->bx.a.x;
10261: rsp->xe = rp->xe - bp->bx.a.x;
10262: /* above,below connecting run indices are relative to
10263: the sequence no. of this run (ac>0 & bc>0) */
10264: if((rsp->ad = rp->ad)!=0)
10265: rsp->ac = rp->u.no - rp->ac->u.no;
10266: else rsp->ac = 0;
10267: if((rsp->bd = rp->bd)!=0)
10268: rsp->bc = rp->bc->u.no - rp->u.no;
10269: else rsp->bc = 0;
10270: if(blob_debug) err_runfs(" ",rsp);
10271: rp=rp->n;
10272: #if FWRI
10273: fwri_RunFS(fp,rsp);
10274: #else
10275: rsp++;
10276: #endif
10277: };
10278: #if !FWRI
10279: if(fwrite(rfsa,sizeof(RunFS),bp->runs,fp)!=bp->runs)
10280: abort("fwrb_blob_etc: can't fwrite RunFS[%d]",bp->runs);
10281: if(dbg_fwrb_runs)
10282: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunFS));
10283: #endif
10284: }
10285: else { if(blob_debug) err("large");
10286: while(rp!=NULL) {
10287: /* y, xs, xe will be relative to Blob.bx.a */
10288: rf.y = rp->y - bp->bx.a.y;
10289: rf.xs = rp->xs - bp->bx.a.x;
10290: rf.xe = rp->xe - bp->bx.a.x;
10291: /* above,below connecting run indices are relative to
10292: the sequence no. of this run (ac>0 & bc>0) */
10293: if((rf.ad = rp->ad)!=0)
10294: rf.ac = rp->u.no - rp->ac->u.no;
10295: else rf.ac = 0;
10296: if((rf.bd = rp->bd)!=0)
10297: rf.bc = rp->bc->u.no - rp->u.no;
10298: else rf.bc = 0;
10299: if(blob_debug) err_runf(" ",&rf);
10300:
10301: /* since there may be many, won't use a local array */
10302: #if FWRI
10303: fwri_RunF(fp,&rf);
10304: #else
10305: if(fwrite(&rf,sizeof(RunF),1,fp)!=1)
10306: abort("fwrb_blob_etc: can't fwrite RunF");
10307: #endif
10308: rp=rp->n;
10309: };
10310: if(dbg_fwrb_runs)
10311: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunF));
10312: };
10313: }
10314: else if(bp->ident&Runs_ff) {
10315: if(bp->ident&Blob_small) { /* use compressed Run records */
10316: if(blob_debug) err("small");
10317: /* can use small local static array */
10318: #if FWRI
10319: rsp= &rfs;
10320: #else
10321: rsp=rfsa;
10322: #endif
10323: for(rfp=bp->r.ff,ri=0; ri<bp->runs; rfp++,ri++) {
10324: rsp->y = rfp->y;
10325: rsp->xs = rfp->xs;
10326: rsp->xe = rfp->xe;
10327: rsp->ad = rfp->ad;
10328: rsp->bd = rfp->bd;
10329: rsp->ac = rfp->ac;
10330: rsp->bc = rfp->bc;
10331: #if FWRI
10332: fwri_RunFS(fp,rsp);
10333: #else
10334: rsp++;
10335: #endif
10336: };
10337: #if !FWRI
10338: if(fwrite(rfsa,sizeof(RunFS),bp->runs,fp)!=bp->runs)
10339: abort("fwrb_blob_etc: can't fwrite RunFS[%d]",bp->runs);
10340: if(dbg_fwrb_runs)
10341: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunFS));
10342: #endif
10343: }
10344: else { if(blob_debug) err("large");
10345: #if FWRI
10346: for(rfq=(rfp=bp->r.ff)+bp->runs; rfp<rfq; rfp++) {
10347: fwri_RunF(fp,rfp);
10348: };
10349:
10350: #else
10351: if(fwrite(bp->r.ff,sizeof(RunF),bp->runs,fp)!=bp->runs)
10352: abort("fwrb_blob_etc: can't fwrite RunF[%d]",bp->runs);
10353: if(dbg_fwrb_runs)
10354: err("fwrb_blob_etc: %d bytes",bp->runs*sizeof(RunF));
10355: #endif
10356: };
10357: };
10358: };
10359: }
10360:
10361: /* Read a given Blob's RunF's (binary) from FILE *fp; return F on EOF.
10362: If bp->runs<=max, read the RunF's into bp->r.ff, and set Runs_ff bit.
10363: otherwise ignore them all and set bp->r.ff==NULL. */
10364: int frdb_runfs(fp,bp,max)
10365: FILE *fp;
10366: Blob *bp; /* *bp's fields already set up */
10367: int max; /* maximum no. RunF records expected */
10368: { register RunFS *rsp,*rsq;
10369: static RunFS rfsa[256];
10370: register RunF *rfp,*rfq;
10371: if(bp->r.ff!=NULL && bp->runs <= max) {
10372: bp->ident |= Runs_ff; bp->ident &= ~(Runs_f|Runs_seek);
10373: if(bp->ident&Blob_small) {
10374: if(blob_debug) err("small");
10375: #if FRDI
10376: for(rsq=(rsp=rfsa)+bp->runs; rsp<rsq; rsp++) {
10377: frdi_RunFS(fp,rsp);
10378: };
10379: #else
10380: if(fread(rfsa,sizeof(RunFS),bp->runs,fp) < bp->runs)
10381: return(0);
10382: #endif
10383: /* copy compressed RunFS's into RunF's */
10384: for(rsq=(rsp=rfsa)+bp->runs,rfp=bp->r.ff;
10385: rsp<rsq;
10386: rsp++,rfp++) {
10387: /* beware sign extension from unsigned chars */
10388: if(blob_debug) err_runfs(" ",rsp);
10389: rfp->y = 0377&rsp->y;
10390: rfp->xs = 0377&rsp->xs;
10391: rfp->xe = 0377&rsp->xe;
10392: rfp->ad = 0377&rsp->ad;
10393: rfp->bd = 0377&rsp->bd;
10394: rfp->ac = 0377&rsp->ac;
10395: rfp->bc = 0377&rsp->bc;
10396: };
10397: }
10398: else { if(blob_debug) err("large");
10399: #if FRDI
10400: for(rfq=(rfp=bp->r.ff)+bp->runs; rfp<rfq; rfp++)
10401: frdi_RunF(fp,rfp);
10402: #else
10403: if(fread(bp->r.ff,sizeof(RunF),bp->runs,fp) != bp->runs)
10404: return(F);
10405: #endif
10406: };
10407: }
10408: else { bp->ident &= ~(Runs_ff|Runs_f);
10409: bp->ident |= Runs_seek;
10410: bp->r.seek=ftell(fp);
10411: /* skip past excessive no. of runs */
10412: /** What if FRDI?? **/
10413: if(bp->ident&Blob_small)
10414: fseek(fp,(long)((bp->runs)*sizeof(RunFS)),1);
10415: else
10416: fseek(fp,(long)((bp->runs)*sizeof(RunF)),1);
10417: };
10418: if(ferror(fp)) return(-errno); else return(1);
10419: }
10420:
10421: #if FRDI
10422: /* read a Blob record (only) into *p */
10423: int frdb_blob(f,p)
10424: FILE *f;
10425: Blob *p;
10426: { int bdy_mny;
10427: *p = empty_Blob;
10428: if(feof(f))
10429: return(0);
10430: p->ident=frdi_Ident(f);
10431: /* p->no=frdi_Seq(f); */
10432: frdi_Bbx(f,&(p->bx));
10433: p->area=frdi_uint4(f);
10434: p->per=frdi_uint4(f);
10435: /* don't read .n */
10436: p->m=frdi_Merit(f);
10437: p->runs=frdi_uint3(f);
10438: if((bdy_mny=frdi_uint2(f))>0) {
10439: p->bdsp = alloc_bdys();
10440: p->bdsp->mny = bdy_mny;
10441: };
10442: #if dbg_frdb
10443: if((!(p->ident&IsBlob))||(p->ident&(IsALL&(~IsBlob))))
10444: err("frdb_blob: %s",blob_toa(p));
10445: #endif
10446: #if dbg_frdb_toa
10447: err("frdb_blob: %s",blob_toa(p));
10448: #endif
10449: if(ferror(f))
10450: return(-errno);
10451: else return(1);
10452: }
10453: #else
10454: /* read a Blob record (only) into *bp; return F if EOF */
10455: int frdb_blob(fp,bp)
10456: FILE *fp;
10457: Blob *bp;
10458: { BlobF bf;
10459: if(fread(&bf,sizeof(BlobF),1,fp)!=1) return(0);
10460: if(blob_debug) err_blobf("bf",&bf);
10461: bp->ident=bf.ident;
10462: bp->no = 0;
10463: bp->bx=bf.bx;
10464: bp->area=bf.area;
10465: /*bp->per=bf.per;*/
10466: bp->runs=bf.runs;
10467: /*bp->bdys=bf.bdys;*/
10468: bp->n = NULL;
10469: bp->r.f = NULL;
10470: bp->bdsp = NULL;
10471: #if dbg_frdb
10472: if((!(bp->ident&IsBlob))||(bp->ident&(IsALL&(~IsBlob))))
10473: err("frdb_blob: %s",blob_toa(bp));
10474: #endif
10475: #if dbg_frdb_toa
10476: err("frdb_blob: %s",blob_toa(bp));
10477: #endif
10478: if(ferror(fp)) return(-errno); else return(1);
10479: }
10480: #endif
10481:
10482: err_blob(s,bp)
10483: char *s;
10484: Blob *bp;
10485: { fprintf(stderr,"%s ",s);
10486: if(bp==NULL) fprintf(stderr,"Blob NULL.\n");
10487: else fprintf(stderr,
10488: "Blob %d: x[%d,%d],y[%d,%d] ar%d ft%s r(#%d f%d)\n",
10489: bp->no,bp->bx.a.x,bp->bx.b.x,bp->bx.a.y,bp->bx.b.y,
10490: bp->area,ident_toa(bp->ident),bp->runs,rp_tod(bp->r.f));
10491: }
10492:
10493: err_blob_runs(s,bp)
10494: char *s;
10495: Blob *bp;
10496: { Run *crp;
10497: char cs[20];
10498: fprintf(stderr,"%s ",s);
10499: err_blob(s,bp);
10500: if(bp!=NULL&&bp->runs>0&&bp->r.f!=NULL) {
10501: sprintf(cs,"%*s",strlen(s)+2," ");
10502: for(crp=bp->r.f; crp!=NULL; crp=crp->n) err_run(cs,crp);
10503: };
10504: }
10505:
10506: err_blob_runfs(s,bp)
10507: char *s;
10508: Blob *bp;
10509: { RunF *crp;
10510: int ri;
10511: char cs[20];
10512: fprintf(stderr,"%s ",s);
10513: err_blob_briefly("",bp);
10514: if(bp!=NULL&&bp->runs>0&&bp->r.ff!=NULL) {
10515: sprintf(cs,"%*s",strlen(s)+2," ");
10516: for(crp=bp->r.ff,ri=0; ri<bp->runs; crp++,ri++) err_runf(cs,crp);
10517: };
10518: }
10519:
10520: err_blobf(s,bp)
10521: char *s;
10522: BlobF *bp;
10523: { Run *crp;
10524: char cs[20];
10525: fprintf(stderr,"%s ",s);
10526: if(bp==NULL) fprintf(stderr,"BlobF NULL.\n");
10527: else fprintf(stderr,
10528: "BlobF: x[%d,%d],y[%d,%d] ar%d ft%s #r%d\n",
10529: bp->bx.a.x,bp->bx.b.x,bp->bx.a.y,bp->bx.b.y,
10530: bp->area,ident_toa(bp->ident),bp->runs);
10531: }
10532:
10533: err_blob_briefly(s,bp)
10534: char s[];
10535: Blob *bp;
10536: { Run *crp;
10537: if(bp==NULL) err("%s Blob NULL.",s);
10538: else { fprintf(stderr,
10539: "%s Blob #%d: bx(%d,%d),(%d,%d) ar%d f%s runs%d ",
10540: s,
10541: bp->no,
10542: bp->bx.a.x,bp->bx.a.y,bp->bx.b.x,bp->bx.b.y,
10543: bp->area,
10544: ident_toa(bp->ident),
10545: bp->runs);
10546: fprintf(stderr,"\n");
10547: };
10548: }
10549:
10550: err_blob_stats()
10551: { err("Blob stats: %d now, %d total, %d hi-water\n",
10552: blob_max-blob_fr_mny,hi_blob_no+1,blob_hi);
10553: }
10554:
10555: /* write blob list starting at fi */
10556: fwrb_blobl_etc(fp,mny,fi,etc)
10557: FILE *fp;
10558: int mny;
10559: Blob *fi;
10560: Ident etc;
10561: { int bi;
10562: Blob *bp;
10563: if(mny>0) for(bi=0,bp=fi; bi<mny; bi++,bp=bp->n) {
10564: if(bp!=NULL) fwrb_blob_etc(fp,bp,etc);
10565: else { err("fwrb_blobl_etc: bmny==%d but %dth (Blob *) is NULL",
10566: mny,bi);
10567: break;
10568: };
10569: };
10570: }
10571:
10572: fwrb_blobs_etc(fp,bs,etc)
10573: FILE *fp;
10574: Blobs bs;
10575: Ident etc;
10576: { register Blob *bp,**bpp;
10577: if(bs.mny==0) return;
10578: for(bp= *(bpp=bs.bpa); bp!=NULL; bp= *(++bpp))
10579: fwrb_blob_etc(fp,bp,etc);
10580: }
10581:
10582: /* read a set of blobs, and their parts */
10583: frdb_blobs_etc(fp,bsp,etc)
10584: FILE *fp;
10585: Blobs *bsp;
10586: Ident etc; /* read only the parts indicated */
10587: { int bi;
10588: register Blob *bp,**bpp;
10589: if(bsp->mny<=0) {
10590: *bsp = empty_Blobs;
10591: return(1);
10592: };
10593:
10594: if((bpp=bsp->bpa=(Blob **)malloc((bsp->mny+1)*sizeof(Blob *)))==NULL)
10595: abort("frdb_blobs_etc: can't alloc Blobs.bpa[%d]",bsp->mny+1);
10596: for(bi=0; bi<bsp->mny; bi++) {
10597: *(bpp++) = bp = alloc_blob();
10598: if(!frdb_blob_etc(fp,bp,etc))
10599: abort("frdb_blobs_etc: unexpected EOF");
10600: };
10601: *bpp = NULL;
10602: if(ferror(fp)) return(-errno); else return(1);
10603: }
10604:
10605: /* Read a blob record into *bp, and then read its parts as specified by etc.
10606: If there aren't any runs, return normally.
10607: If etc&IsRun is false, then set Runs_seek and proceed as described below.
10608: If etc&Runs_ff, then the contents of r.ff is examined:
10609: if NULL, then space is allocated here for `runs' RunF's;
10610: if non-NULL, then on the assumption that it points to space for
10611: at least `runs' many, they are read into it.
10612: If etc&Runs_seek, then the ftell value is placed in r.seek,
10613: and the runs are simply skipped over.
10614: The Runs_f (list) option is unimplemented.
10615: The Blob is marked with the appropriate Runs_X bit.
10616: Return: 1 if normal & successful, 0 if EOF, and -1 if error.
10617: */
10618: int frdb_blob_etc(fp,bp,etc)
10619: FILE *fp;
10620: Blob *bp;
10621: Ident etc;
10622: { int stat;
10623: if((stat=frdb_blob(fp,bp))!=1)
10624: return(stat);
10625: if(bp->runs<=0) {
10626: bp->runs = 0;
10627: bp->r.ff = NULL;
10628: bp->ident &= ~(Runs_f|Runs_seek|Runs_g4);
10629: bp->ident |= Runs_ff;
10630: return(1);
10631: };
10632:
10633: if(!(etc&IsRun)) {
10634: etc |= IsRun|Runs_seek;
10635: etc &= ~(Runs_f|Runs_ff|Runs_g4);
10636: };
10637: if (!(etc&(Runs_f|Runs_ff|Runs_g4|Runs_seek)) || etc&Runs_ff) {
10638: /* Want to deliver Runs in Runf ff[] format */
10639: if(bp->r.ff==NULL) {
10640: if( (bp->r.ff=
10641: (RunF *)malloc(bp->runs*sizeof(RunF)))==NULL)
10642: abort("frdb_blob_etc: can't alloc r.ff[%d]",bp->runs);
10643: };
10644: if(bp->ident&Runs_g4) {
10645: /* Runs are in CCITT Group 4 format */
10646: stat=frdb_g4_runfs(fp,&(bp->bx),bp->runs,bp->r.ff);
10647: }
10648: else { /* Runs are in RunF or RunFS format */
10649: stat=frdb_runfs(fp,bp,bp->runs);
10650: };
10651: bp->ident |= Runs_ff; bp->ident &= ~(Runs_f|Runs_seek|Runs_g4);
10652: return(stat);
10653: }
10654: else if(etc&Runs_seek) {
10655: bp->ident |= Runs_seek; bp->ident &= ~(Runs_ff|Runs_f);
10656: bp->r.seek=ftell(fp); /* save seek addr */
10657: /* skip past runs */
10658: if(bp->ident&Blob_small)
10659: fseek(fp,(long)((bp->runs)*sizeof(RunFS)),1);
10660: else fseek(fp,(long)((bp->runs)*sizeof(RunF)),1);
10661: }
10662: else /* (etc&Runs_f) || (etc&Runs_g4) */ {
10663: abort("frdb_blob_etc: Runs_f & Runs_g4 etc option unimplemented");
10664: };
10665: if(ferror(fp)) return(-errno); else return(1);
10666: }
10667:
10668: /* read a number of blobs, and their parts, into linked-list (mny, *fi);
10669: return T iff not EOF */
10670: boolean frdb_blobl_etc(fp,bmny,fip,etc)
10671: FILE *fp;
10672: int bmny;
10673: Blob **fip;
10674: Ident etc;
10675: { int bi;
10676: register Blob *bp,**bpp;
10677: RunF *rp;
10678: int stat;
10679: if(bmny<=0) return(1);
10680: bi=0; bpp=fip;
10681: do { bp=alloc_blob();
10682: if((stat=frdb_blob_etc(fp,bp,etc))!=1) return(stat);
10683: *bpp=bp; bpp= &(bp->n);
10684: }
10685: while((++bi)<bmny);
10686: *bpp=NULL;
10687: if(ferror(fp)) return(-errno); else return(1);
10688: }
10689:
10690: char *interp_toa(ip)
10691: Interp *ip;
10692: { static char s[80];
10693: char ms[3],shs[3],szs[3],hts[3],prs[3];
10694: strcpy(ms,merit_toa(ip->m));
10695: strcpy(shs,merit_toa(ip->mshap));
10696: strcpy(szs,merit_toa(ip->msize));
10697: strcpy(hts,merit_toa(ip->mbhgt));
10698: strcpy(prs,merit_toa(ip->p));
10699: sprintf(s,"%s %s sz%s ba%d m%s (sh%s sz%s ht%s) p%s",
10700: ident_toa(ip->ident),
10701: #if CPU!=CRAY
10702: classid_toa(&(ip->ci)),
10703: #else
10704: ip->ci.c,
10705: #endif
10706: pts_toa(ip->size),
10707: ip->basl,
10708: ms,shs,szs,hts,prs);
10709: return(s);
10710: }
10711:
10712: frdb_interpl_etc(fp,ilp,etc)
10713: FILE *fp;
10714: Interpl *ilp;
10715: Ident etc;
10716: { int ii,stat;
10717: Interp *ip,*pp;
10718: if(ilp->mny<=0) {
10719: *ilp = empty_Interpl;
10720: return(1);
10721: };
10722:
10723: for(ii=0; ii<ilp->mny; ii++) {
10724: ip=alloc_interp();
10725: if(ii==0) ilp->fi = ip;
10726: else pp->n = ip;
10727: if((stat=frdb_interp(fp,ip))!=1) return(stat);
10728: pp=ip;
10729: };
10730: ip->n = NULL;
10731: if(ferror(fp)) return(-errno); else return(1);
10732: }
10733:
10734: #if FRDI
10735: int frdb_interp(f,p)
10736: FILE *f;
10737: Interp *p;
10738: { int stat;
10739: *p = empty_Interp;
10740: if(feof(f))
10741: return(0);
10742: p->ident=frdi_Ident(f);
10743: frdi_ClassId(f,&(p->ci));
10744: p->mshap=frdi_Merit(f);
10745: p->size=frdi_Pts(f);
10746: p->msize=frdi_Merit(f);
10747: p->basl=frdi_Scoor(f);
10748: p->mbhgt=frdi_Merit(f);
10749: p->m=frdi_Merit(f);
10750: p->p=frdi_Prob(f);
10751: #if dbg_frdb
10752: if((!(p->ident&IsInterp))||(p->ident&(IsALL&(~IsInterp))))
10753: err("frdb_interp: %s",interp_toa(p));
10754: #endif
10755: if(ferror(f)) return(-errno); else return(1);
10756: }
10757: #else
10758: int frdb_interp(fp,ip)
10759: FILE *fp;
10760: Interp *ip;
10761: { InterpF inf;
10762: int stat;
10763: if((stat=fread(&inf,sizeof(InterpF),1,fp))!=1) {
10764: err("can't fread InterpF, status %d",stat);
10765: return(stat);
10766: };
10767: *ip = empty_Interp;
10768: ip->ident = inf.ident;
10769: ip->ci = inf.ci;
10770: ip->clp = NULL;
10771: ip->clsp = NULL;
10772: ip->mshap = inf.mshap;
10773: ip->size = inf.size;
10774: ip->msize = inf.msize;
10775: ip->basl = inf.basl;
10776: ip->mbhgt = inf.mbhgt;
10777: ip->m = inf.m;
10778: #if dbg_frdb
10779: if((!(ip->ident&IsInterp))||(ip->ident&(IsALL&(~IsInterp))))
10780: err("frdb_interp: %s",interp_toa(ip));
10781: #endif
10782: if(ferror(fp)) return(-errno); else return(1);
10783: }
10784: #endif
10785:
10786: free_interpl(ilp)
10787: Interpl *ilp;
10788: { int ii;
10789: Interp *ip,*np;
10790: if(ilp->mny>0) {
10791: for(ip=ilp->fi; ip!=NULL; ip=np) { np=ip->n; free_interp(ip); }
10792: ilp->mny=0;
10793: };
10794: ilp->fi=NULL;
10795: };
10796:
10797: fwrb_interpl_etc(fp,is,etc)
10798: FILE *fp;
10799: Interpl is;
10800: Ident etc;
10801: { Interp *ip;
10802: int ii;
10803: if(is.mny>0) for(ii=0,ip=is.fi; ii<is.mny; ii++,ip=ip->n)
10804: fwrb_interp_etc(fp,ip,etc);
10805: }
10806:
10807: /* remove this Interp from the Interp-list */
10808: remove_interpl(ip,ilp)
10809: Interp *ip;
10810: Interpl *ilp;
10811: { Interp *rp,*pp;
10812: if(ilp->mny==1) { /* frequent case */
10813: ilp->fi=NULL; ilp->mny=0;
10814: }
10815: else if(ilp->mny>1){
10816: pp=NULL;
10817: for(rp=ilp->fi; rp!=ip&&rp!=NULL; pp=rp,rp=rp->n) ;
10818: if(rp!=NULL) { /* remove from list */
10819: if(pp==NULL) ilp->fi=ip->n;
10820: else pp->n=ip->n;
10821: ilp->mny--;
10822: }
10823: else err("remove_interpl: can't - not found");
10824: }
10825: else err("remove_interpl: can't - Interpl empty");
10826: }
10827:
10828: /* prepend this Interp to the Interp-list */
10829: prepend_interpl(ip,ilp)
10830: Interp *ip;
10831: Interpl *ilp;
10832: { Interp *rp,*pp;
10833: ip->n = ilp->fi;
10834: ilp->fi = ip;
10835: ilp->mny++;
10836: }
10837:
10838: fwrb_interp_etc(fp,ip,etc)
10839: FILE *fp;
10840: Interp *ip;
10841: Ident etc;
10842: { fwrb_interp(fp,ip);
10843: }
10844:
10845: #if FWRI
10846: fwrb_interp(f,p)
10847: FILE *f;
10848: Interp *p;
10849: { InterpF inf;
10850: int stat;
10851: #if dbg_fwrb
10852: if((!(p->ident&IsInterp))||(p->ident&(IsALL&(~IsInterp))))
10853: err("fwrb_interp: %s",interp_toa(p));
10854: #endif
10855: fwri_Ident(f,p->ident);
10856: fwri_ClassId(f,&(p->ci));
10857: fwri_Merit(f,p->mshap);
10858: fwri_Pts(f,p->size);
10859: fwri_Merit(f,p->msize);
10860: fwri_Scoor(f,p->basl);
10861: fwri_Merit(f,p->mbhgt);
10862: fwri_Merit(f,p->m);
10863: fwri_Prob(f,p->p);
10864: #if dbg_fwrb_toa
10865: err("fwrb_interp: %s",interp_toa(p));
10866: #endif
10867: }
10868: #else
10869: fwrb_interp(fp,ip)
10870: FILE *fp;
10871: Interp *ip;
10872: { InterpF inf;
10873: int stat;
10874: #if dbg_fwrb
10875: if((!(ip->ident&IsInterp))||(ip->ident&(IsALL&(~IsInterp))))
10876: err("fwrb_interp: %s",interp_toa(ip));
10877: #endif
10878: memset(&inf,'\0',sizeof(inf));
10879: inf.ident = ip->ident;
10880: inf.ci = ip->ci;
10881: inf.mshap = ip->mshap;
10882: inf.size = ip->size;
10883: inf.msize = ip->msize;
10884: inf.basl = ip->basl;
10885: inf.mbhgt = ip->mbhgt;
10886: inf.m = ip->m;
10887: if((stat=fwrite(&inf,sizeof(InterpF),1,fp))!=1)
10888: abort("fwrb_interp: can't fwrite, status %d",stat);
10889: #if dbg_fwrb_toa
10890: err("fwrb_interp: %s",interp_toa(ip));
10891: #endif
10892: }
10893: #endif
10894:
10895: /** Run handling:
10896: alloc_run_pool -create pool of free run records
10897: free_run_pool - free entire pool
10898: alloc_run - allocate a new run from pool
10899: free_run - free a specified run (into pool)
10900: err_run - print Run (ascii) to stderr
10901: err_runb - print Run (ascii) to stderr (after added to blob set)
10902: err_runf - print RunF (ascii) to stderr (after added to blob set)
10903: err_runfs - print RunFS (ascii) to stderr (after added to blob set)
10904: err_run_stats - report statistics to stderr
10905: **/
10906:
10907: /* RunPool functions: variable-size pool, speed-optimized alloc/free */
10908:
10909: /* Initialize pool of Runs with increment `incr' (return F if can't allocate) */
10910: boolean alloc_run_pool(incr,dbg)
10911: int incr;
10912: boolean dbg; /* trace actions on Runs */
10913: { register Run *crp, *prp;
10914: register int i;
10915: _RunPool.incr = incr;
10916: _RunPool.pools = 1;
10917: if((_RunPool.pool=(Run **)malloc(_RunPool.pools*sizeof(Run *)))==NULL)
10918: return(F);
10919: if((_RunPool.pool[_RunPool.pools-1] =
10920: (Run *)malloc(_RunPool.incr*sizeof(Run)))==NULL) {
10921: free(_RunPool.pool);
10922: return(F);
10923: };
10924: _RunPool.next = 0;
10925: _RunPool.free = NULL;
10926: #if STATS
10927: _RunPool.total = 0;
10928: #endif
10929: _RunPool.dbg = dbg;
10930: if(_RunPool.dbg) err("alloc_run_pool: incr%d",_RunPool.incr);
10931: return(T);
10932: }
10933:
10934: free_run_pool()
10935: { register int i;
10936: for(i=0; i<_RunPool.pools; i++) free(_RunPool.pool[i]);
10937: free(_RunPool.pool);
10938: }
10939:
10940: /* The ``hard'' case of allocating runs from RunPool: can't be inline */
10941: Run *hard_alloc_run()
10942: { _RunPool.pools++;
10943: if((_RunPool.pool=
10944: (Run **)realloc(_RunPool.pool,_RunPool.pools*sizeof(Run *)))==NULL)
10945: abort("alloc_Run: can't realloc");
10946: if((_RunPool.cur=_RunPool.pool[_RunPool.pools-1] =
10947: (Run *)malloc(_RunPool.incr*sizeof(Run)))==NULL)
10948: abort("alloc_Run: can't malloc");
10949: _RunPool.next=1;
10950: *(_RunPool.cur) = empty_Run;
10951: return(_RunPool.cur);
10952: }
10953:
10954: int rp_tod(rp)
10955: Run *rp;
10956: { return((int)rp);
10957: }
10958:
10959: char *runf_toa(rp)
10960: RunF *rp;
10961: { static char s[80];
10962: char s1[80];
10963: strcpy(s,"RunF ");
10964: if(rp==NULL) strcat(s,"NULL");
10965: else { sprintf(s1,
10966: "y%d,x[%d,%d] lag(ad%d,bd%d ac%d,bc%d)",
10967: rp->y,rp->xs,rp->xe,
10968: rp->ad,rp->bd, rp->ac,rp->bc );
10969: strcat(s,s1);
10970: };
10971: return(s);
10972: }
10973:
10974: char *runfs_toa(rp)
10975: RunFS *rp;
10976: { static char s[80];
10977: char s1[80];
10978: strcpy(s,"RunFS ");
10979: if(rp==NULL) strcat(s,"NULL");
10980: else { sprintf(s1,
10981: "y%d,x[%d,%d] lag(ad%d,bd%d ac%d,bc%d)",
10982: rp->y,rp->xs,rp->xe,
10983: rp->ad,rp->bd, rp->ac,rp->bc );
10984: strcat(s,s1);
10985: };
10986: return(s);
10987: }
10988:
10989: err_run(s,rp)
10990: char *s;
10991: Run *rp;
10992: { fprintf(stderr,"%s ",s);
10993: if(rp==NULL) fprintf(stderr,"Run NULL.\n");
10994: else fprintf(stderr,
10995: "Run %d: y%d,x[%d,%d] l(n%d) t(o%x ad%d,bd%d ac%d,bc%d)\n",
10996: rp_tod(rp), rp->y,rp->xs,rp->xe,
10997: rp_tod(rp->n),
10998: #if CPU!=CRAY
10999: (int)rp->u.o,
11000: #else
11001: 0,
11002: #endif
11003: rp->ad,rp->bd,
11004: rp_tod(rp->ac),
11005: rp_tod(rp->bc) );
11006: }
11007:
11008: /* print Run after it has been added to Blob set */
11009: err_runb(s,rp)
11010: char *s;
11011: Run *rp;
11012: { fprintf(stderr,"%s ",s);
11013: if(rp==NULL) fprintf(stderr,"Run NULL.\n");
11014: else fprintf(stderr,
11015: "Run %d: y%d,x[%d,%d] l(n%d) t(no%d ad%d,bd%d ac%d,bc%d)\n",
11016: rp_tod(rp), rp->y,rp->xs,rp->xe,
11017: rp_tod(rp->n),
11018: rp->u.no, rp->ad,rp->bd, rp_tod(rp->ac),rp_tod(rp->bc) );
11019: }
11020:
11021: err_runf(s,rp)
11022: char *s;
11023: RunF *rp;
11024: { fprintf(stderr,"%s ",s);
11025: if(rp==NULL) fprintf(stderr,"RunF NULL.\n");
11026: else fprintf(stderr,
11027: "RunF: y%d,x[%d,%d] t(ad%d,bd%d ac%d,bc%d)\n",
11028: rp->y,rp->xs,rp->xe,
11029: rp->ad,rp->bd, rp->ac,rp->bc );
11030: }
11031:
11032: err_runfs(s,rp)
11033: char *s;
11034: RunFS *rp;
11035: { RunF rf;
11036: rf.y = 0377&rp->y;
11037: rf.xs = 0377&rp->xs;
11038: rf.xe = 0377&rp->xe;
11039: rf.ad = 0377&rp->ad;
11040: rf.bd = 0377&rp->bd;
11041: rf.ac = 0377&rp->ac;
11042: rf.bc = 0377&rp->bc;
11043: err_runf(s,&rf);
11044: }
11045:
11046: int runs_of_blob(p,ra,max)
11047: Blob *p;
11048: RLE_Yrun *ra;
11049: int max;
11050: { int runs,ri;
11051: RunF *rfp;
11052: runs = p->runs;
11053: if(runs>max) {
11054: err("runs_of_blob: max exceeded - skip this blob");
11055: runs = 0;
11056: }
11057: else if(runs>0) {
11058: if(p->ident&Runs_ff) {
11059: for(ri=0,rfp=p->r.ff; ri<runs; ri++,rfp++) {
11060: ra->y = p->bx.a.y + rfp->y;
11061: ra->xs = p->bx.a.x + rfp->xs;
11062: ra->xe = p->bx.a.x + rfp->xe;
11063: ra++;
11064: };
11065: }
11066: else { err("runs_of_blob: handle only Runs_ff - skip this blob");
11067: runs = 0;
11068: };
11069: };
11070: return(runs);
11071: }
11072:
11073: int no_runs_of_blobl(p)
11074: Blobl *p;
11075: { int runs;
11076: Blob *pp;
11077: runs = 0;
11078: if(p->mny>0) for(pp=p->fi; pp!=NULL; pp=pp->n) runs += pp->runs;
11079: return(runs);
11080: }
11081:
11082: int runs_of_blobl(p,ra,max)
11083: Blobl *p;
11084: RLE_Yrun *ra;
11085: int max;
11086: { int runs;
11087: Blob *pp;
11088: runs = 0;
11089: if(p->mny>0) for(pp=p->fi; pp!=NULL; pp=pp->n)
11090: runs += runs_of_blob(pp,ra+runs,max-runs);
11091: return(runs);
11092: }
11093:
11094: int no_runs_of_char(p)
11095: Char *p;
11096: { int runs;
11097: Blobl bl;
11098: runs = 0;
11099: bl.mny = p->bmny; bl.fi = p->fi;
11100: runs += no_runs_of_blobl(&bl);
11101: return(runs);
11102: }
11103:
11104: int runs_of_char(p,ra,max)
11105: Char *p;
11106: RLE_Yrun *ra;
11107: int max;
11108: { int runs;
11109: Blobl bl;
11110: runs = 0;
11111: bl.mny = p->bmny; bl.fi = p->fi;
11112: runs += runs_of_blobl(&bl,ra,max);
11113: return(runs);
11114: }
11115:
11116: /* ascending lexicographic order on y,xs */
11117: int rn_asc(r1,r2)
11118: RLE_Yrun *r1,*r2;
11119: { if(r1->y < r2->y) return(-1);
11120: else if(r1->y==r2->y) {
11121: if(r1->xs < r2->xs) return(-1);
11122: else if (r1->xs == r2->xs) return(0);
11123: else return(1);
11124: }
11125: else return(1);
11126: }
11127:
11128: RLE_Lines *rlines_of_char(chp)
11129: Char *chp;
11130: { static RLE_Lines rls;
11131: int no_runs,cy,ri;
11132: RLE_Run *lr;
11133: RLE_Yrun *ra,*cr;
11134: RLE_Line *cl;
11135: /* count runs */
11136: no_runs = no_runs_of_char(chp);
11137: /* allocate runs array */
11138: if((ra=(RLE_Yrun *)malloc(no_runs*sizeof(RLE_Yrun)))==NULL)
11139: abort("rlines_of_char: can't malloc ra[%d]",no_runs);
11140: runs_of_char(chp,ra,no_runs);
11141: /* sort runs ascending on (y,xs) */
11142: qsort(ra,no_runs,sizeof(RLE_Yrun),rn_asc);
11143: /* count RLE_lines.mny */
11144: rls.mny = 0; cy=Scoor_MIN;
11145: for(ri=0,cr=ra; ri<no_runs; ri++,cr++)
11146: if(cr->y!=cy) {
11147: rls.mny++;
11148: cy = cr->y;
11149: };
11150: /* allocate RLE_lines */
11151: if((rls.rla=(RLE_Line *)malloc(rls.mny*sizeof(RLE_Line)))==NULL)
11152: abort("rlines_of_page: can't malloc rls.rla[%d]",rls.mny);
11153: /* fill in RLE_lines */
11154: cy=Scoor_MIN; cl=rls.rla-1;
11155: for(ri=0,cr=ra; ri<no_runs; ri++,cr++) {
11156: if(cr->y!=cy) {
11157: cl++;
11158: cl->y = cy = cr->y;
11159: cl->runs = 0;
11160: lr = cl->r;
11161: };
11162: lr->xs = cr->xs; lr->xe = cr->xe; lr++; cl->runs++;
11163: };
11164: free(ra);
11165: return(&rls);
11166: }
11167:
11168: int asc_merit(m1,m2)
11169: Merit *m1,*m2;
11170: { if(*m1 < *m2) return(-1);
11171: else if(*m1 > *m2) return(1);
11172: else return(0);
11173: }
11174:
11175: /* Word merit is computed as a function of the merit of its Chars.
11176: No Chars forces merit to 0.0.
11177: The result is dominated by the weakest merit in the Word, slightly
11178: improved by the others. */
11179: Merit wordmerit(w)
11180: Word *w;
11181: { register Char *cp,**cpp;
11182: static int m_alloc = 0;
11183: static Merit *ma; /* ma[m_alloc] */
11184: int mi;
11185: Merit m;
11186: double wgt,sumwgt;
11187:
11188: if(w->cs.mny<=0) return(0.0);
11189: if(w->cs.mny>m_alloc) {
11190: if(m_alloc==0) {
11191: m_alloc=w->cs.mny;
11192: if((ma=(Merit *)malloc(m_alloc*sizeof(Merit)))==NULL)
11193: abort("wordmerit: can't malloc ma[%d]",m_alloc);
11194: }
11195: else { m_alloc=w->cs.mny;
11196: if((ma=(Merit *)realloc(ma,m_alloc*sizeof(Merit)))==NULL)
11197: abort("wordmerit: can't realloc ma[%d]",m_alloc);
11198: };
11199: };
11200: for(cp= *(cpp=w->cs.cpa),mi=0; cp!=NULL; cp= *(++cpp),mi++) {
11201: if(cp->area==0 || cp->il.mny==0) ma[mi]=0.0;
11202: else ma[mi] = cp->il.fi->m;
11203: };
11204: qsort(ma,w->cs.mny,sizeof(Merit),asc_merit);
11205: #define DOM (5.0)
11206: /* The worst merit is DOM times more significant than second worst, which
11207: is DOM times more significant than the third worst, and so on.
11208: */
11209: m=ma[0]; sumwgt=wgt=1.0;
11210: for(mi=1; mi<w->cs.mny; mi++) {
11211: m += ma[mi]*(wgt /= DOM); sumwgt += wgt;
11212: };
11213: m /= sumwgt;
11214: return(m);
11215: }
11216:
11217: WordSet *alloc_wordset(top,cut,cap)
11218: double top; /* initial maximum merit (is never reduced) */
11219: double cut; /* cut ratio: don't keep merit < cut*top */
11220: int cap; /* capacity: maximum no. at a time (0 ==> no limit) */
11221: { WordSet *res;
11222: if((res=(WordSet *)malloc(sizeof(WordSet)))==NULL)
11223: abort("alloc_wordset: can't");
11224: *res = empty_WordSet;
11225: res->top = top;
11226: res->cut = cut;
11227: if((res->cap = cap)==0) res->cap=INT_MAX;
11228: return(res);
11229: }
11230:
11231: int free_wordset_etc(s,etc)
11232: WordSet *s;
11233: Ident etc;
11234: { int high;
11235: free_words_etc(&(s->ws),etc);
11236: high = s->high;
11237: free(s);
11238: return(high);
11239: }
11240:
11241: /* Find the maximum-merit word in the set; among ties, pick the first seen. */
11242: Word *find_max_wordset(s)
11243: WordSet *s;
11244: { register Word *max,**wpp;
11245: max=NULL;
11246: if(s->ws.mny>0) for(wpp=s->ws.wpa; *wpp!=NULL; wpp++) {
11247: if(max==NULL || max->m < (*wpp)->m) max=(*wpp);
11248: };
11249: return(max);
11250: }
11251:
11252: /* Find the maximum-merit word in the set; among ties, pick the last seen. */
11253: Word *find_min_wordset(s)
11254: WordSet *s;
11255: { register Word *min,**wpp;
11256: min=NULL;
11257: if(s->ws.mny>0) for(wpp=s->ws.wpa; *wpp!=NULL; wpp++) {
11258: if(min==NULL || min->m >= (*wpp)->m) min=(*wpp);
11259: };
11260: return(min);
11261: }
11262:
11263: /* Insert a Word (without duplicating it).
11264: Update top, min, max, & high.
11265: If the new word's merit is equal to the current maximum, it does not become
11266: become the new maximum.
11267: If the new word's merit is equal to the current minimum, it becomes
11268: the new minimum.
11269: */
11270: put_wordset(w,s)
11271: Word *w; /* must have w->m set up */
11272: WordSet *s;
11273: { insert_word(w,&(s->ws));
11274: if(max_wordset(s)==NULL || max_wordset(s)->m < w->m) {
11275: max_wordset(s) = w;
11276: if(s->top < max_wordmerit(s)) s->top = max_wordmerit(s);
11277: };
11278: if(min_wordset(s)==NULL || min_wordset(s)->m >= w->m)
11279: min_wordset(s) = w;
11280: if(s->high < s->ws.mny) s->high = s->ws.mny;
11281: }
11282:
11283: /* Remove a Word (without freeing it). Maintain min/max, but don't prune items.
11284: Also, don't lower top or high. */
11285: Word *get_wordset(w,s)
11286: Word *w;
11287: WordSet *s;
11288: { if(w==NULL || s->ws.mny==0) return(NULL);
11289: remove_word(w,&s->ws);
11290: if(s->ws.mny==0) {
11291: max_wordset(s) = NULL;
11292: min_wordset(s) = NULL;
11293: }
11294: else { if(w==max_wordset(s)) max_wordset(s) = find_max_wordset(s);
11295: if(w==min_wordset(s)) min_wordset(s) = find_min_wordset(s);
11296: };
11297: return(w);
11298: }
11299:
11300: /* Remove a Word (without freeing it). Maintain min/max. Don't lower top. */
11301: Word *remove_wordset(w,s,n)
11302: Word *w;
11303: WordSet *s;
11304: char *n;
11305: { register Word *gw;
11306: #if dbg_ws
11307: if(w!=NULL) err("remove_wordset: %X %s",w,word_toa(w));
11308: else err("remove_wordset: NULL");
11309: #endif
11310: gw=get_wordset(w,s);
11311: #if dbg_ws
11312: err_wordset(s,n);
11313: #endif
11314: return(gw);
11315: }
11316:
11317: /* Check whether a given Word is identical to any already in a given set.
11318: Word *w must have its hash key set up. */
11319: boolean member_wordset(w,s)
11320: Word *w;
11321: WordSet *s;
11322: { register Word **ww;
11323: if(s->ws.mny>0) {
11324: for(ww=s->ws.wpa; (*ww)!=NULL; ww++) {
11325: if(w->hash==(*ww)->hash && eq_word(w,(*ww)))
11326: return(T);
11327: };
11328: };
11329: return(F);
11330: }
11331:
11332: /* Insert a Word into a set, maintaining uniqueness, a ``range'' property, and
11333: a maximum capacity.
11334: Uniqueness is maintained by refusing to insert words that are identical
11335: (eq_word()) to a word already in the set (or in set `u').
11336: The range property is that every word in the set must have merit no less
11337: than `s->cut' times the lifetime maximum for the set `s->top'.
11338: Maximum capacity is maintained as follows: if insertion would mean more
11339: members than `cap', then either (a) the insertion is refused (if its
11340: merit is less than the current `min', or (b) the current `min' is deleted
11341: (and silently freed in its entirety), and the insertion occurs.
11342: The inserted Word is not duplicated. If, as a result of an insertion,
11343: some of its words no longer satisfy the range property, they are silently
11344: removed (and freed in their entirety).
11345: Return T iff the Word is actually inserted.
11346: */
11347: boolean insert_wordset(w,s,n,u)
11348: Word *w;
11349: WordSet *s;
11350: char *n; /* name of set `s' */
11351: WordSet *u; /* if !=NULL, also check uniqueness here */
11352: { Word *fr;
11353: #if dbg_ws
11354: err("insert_wordset: %X %s",w,word_toa(w));
11355: #endif
11356: if((w->m = wordmerit(w)) >= (s->cut * s->top)) {
11357: w->hash = hash_word(w);
11358: if(member_wordset(w,s) || (u!=NULL&&member_wordset(w,u)))
11359: /* don't insert */
11360: return(F);
11361: if(s->ws.mny==s->cap) /* at capacity */ {
11362: if(w->m <= min_wordmerit(s)) /* too poor */ return(F);
11363: else { fr = remove_wordset(min_wordset(s),s);
11364: free_word_etc(fr,IsALL);
11365: };
11366: };
11367: put_wordset( w, s );
11368: if(max_wordset(s)==w) /* this has become the new maximum */ {
11369: while(min_wordmerit(s) < (s->cut * s->top)) {
11370: fr = remove_wordset(min_wordset(s),s);
11371: free_word_etc(fr,IsALL);
11372: };
11373: };
11374: #if dbg_ws
11375: err_wordset(s,n);
11376: #endif
11377: return(T);
11378: }
11379: else {
11380: #if dbg_ws
11381: err_wordset(s,n);
11382: #endif
11383: return(F);
11384: };
11385: }
11386:
11387: err_wordset(s,n)
11388: WordSet *s;
11389: char *n; /* name of set */
11390: { char m1[10],m2[10];
11391: register Word *wp,**wpp;
11392: fprintf( stderr,"WordSet %s: t%g c%g [%s/%X,%s/%X] m%d h%d: ",
11393: n,
11394: s->top,s->cut,
11395: strcpy(m1,merit_toa(max_wordmerit(s))),max_wordset(s),
11396: strcpy(m2,merit_toa(min_wordmerit(s))),min_wordset(s),
11397: s->ws.mny,s->high );
11398: if(s->ws.mny>0) for(wp= *(wpp=s->ws.wpa); wp!=NULL; wp= *(++wpp))
11399: fprintf(stderr,"%X/%s/%d ",wp,merit_toa(wp->m),wp->cs.mny);
11400: fprintf(stderr,"\n");
11401: }
11402:
11403: translate_txtln(lp,off)
11404: Txtln *lp;
11405: Sp off;
11406: { lp->bx = *translate_bbx(&lp->bx,off);
11407: lp->basl += off.y;
11408: translate_chars(lp->cs,off);
11409: }
11410:
11411: translate_chars(csp,off)
11412: Chars *csp;
11413: Sp off;
11414: { register Char *cp,**cpp;
11415: for(cp= *(cpp=csp->cpa); cp!=NULL; cp= *(++cpp))
11416: translate_char(cp,off);
11417: }
11418:
11419: translate_char(cp,off)
11420: Char *cp;
11421: Sp off;
11422: { cp->bx = *translate_bbx(&cp->bx,off);
11423: translate_blobl(cp,off);
11424: }
11425:
11426: translate_blobs(b,off)
11427: Blobs *b;
11428: Sp off;
11429: { register Blob *bp,**bpp;
11430: if(b->mny>0) for ( bp= *(bpp=b->bpa); bp!=NULL; bp= *(++bpp) )
11431: translate_blob(bp,off);
11432: }
11433:
11434: translate_blobl(cp,off)
11435: Char *cp;
11436: Sp off;
11437: { int bi;
11438: register Blob *bp;
11439: for(bi=0,bp=cp->fi; bi<cp->bmny&&bp!=NULL; bi++,bp=bp->n)
11440: translate_blob(bp,off);
11441: }
11442:
11443: translate_blob(bp,off)
11444: Blob *bp;
11445: Sp off;
11446: { bp->bx = *translate_bbx(&bp->bx,off);
11447: }
11448:
11449: 0707070035351137141006640007620000050000010262240476773367000000700000107063Text.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
11450: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
11451: /* The copyright notice does not imply actual or intended publication. */
11452: /* AUTHORS: */
11453: /* H. S. Baird - ATT-BL MH - first versions */
11454:
11455: /* Text.h - typedefs, constants, and function declarations for document-images
11456: (see Text.c for companion functions.)
11457: INCLUDES
11458: requires prior:
11459: #include "stdocr.h"
11460: */
11461:
11462: #define dbg_fwrb_toa (F) /* err("%s",R_toa()) for each record written */
11463: #define dbg_frdb_toa (F) /* err("%s",R_toa()) for each record read */
11464:
11465: #define DIM_VERSION (0) /* current version no. of Dim-file format */
11466:
11467: #include "Bfeats.h"
11468:
11469: #define Ident int /* identification bits [MUST BE >=32 bits] */
11470:
11471: #define fwri_Ident(F,V) fwri_uint4((F),(V))
11472: #define frdi_Ident(F) frdi_uint4(F)
11473:
11474: /* Ident bits */
11475: /* identifies external file record type(s) */
11476: #define IsPage 04000000000
11477: #define IsBlock 02000000000
11478: #define IsTxtln 01000000000
11479: #define IsWord 00020000000
11480: #define IsChar 00400000000
11481: #define IsBlob 00200000000
11482: #define IsRun 00100000000 /* should be IsRuns or IsLag */
11483: #define IsRuns (IsRun)
11484: #define IsInterp 00040000000 /* Char interpretation */
11485: #define IsBdy 00010000000
11486: #define IsShapes 00004000000
11487: #define IsLag 00002000000
11488: #define IsBfeats 00001000000
11489: #define IsSfeats 00000400000
11490: #define IsWordInterp 00000200000
11491: /* Runs: set in Blob records' ids.
11492: At most one of these may be set in main memory.
11493: Only Runs_ff or Runs_g4 may be set in peripheral file format. */
11494: #define Runs_f 00000010000 /* Runs are in list, starting *.r.f */
11495: #define Runs_ff 00000020000 /* RunFs are in array, at *.r.ff */
11496: #define Runs_seek 00000040000 /* Runs are still in file, at *.seek */
11497: #define Runs_g4 00000100000 /* Runs are in CCITT Group 4 format */
11498:
11499: /* CCITT Group 4 format in peripheral files consists of (a) an unsigned long count,
11500: then (b) that many bytes of Group 4 encoding exactly as in CCITT
11501: Recommendation T.6, except that no EOFB code is appended, since the end of
11502: the bitmap can be detected using the bounding box of the owning Blob.
11503: Instead, the last scan line of the bitmap is merely padded to the nearest
11504: full byte with '0' bits. This compresses the representation by about
11505: a factor of 8 on average, compared to RunF/RunFS encoding. */
11506:
11507: #define IsALL (IsPage|IsBlock|IsTxtln|IsWord|IsChar|IsBlob|IsRun|IsBdy|IsInterp|IsShapes|IsLag|IsBfeats|IsSfeats|IsWordInterp)
11508: #define IsNONE 0
11509:
11510:
11511: /* Enable optional debugging-support code to maintain a count of selected record
11512: types that are allocated using alloc_* free_* and dup_* functions. The counts
11513: are in units of records, not bytes. By design, has no effect at all on
11514: correctness. */
11515: #define ALLOC_CENSUS (0)
11516:
11517: #if ALLOC_CENSUS
11518:
11519: typedef struct Census {
11520: int Page_mny;
11521: int Block_mny;
11522: int Txtln_mny;
11523: int Word_mny;
11524: int Char_mny;
11525: int Blob_mny;
11526: int Run_mny;
11527: int Interp_mny;
11528: int Bfeats_mny;
11529: int BMask_mny;
11530: } Census;
11531:
11532: #define Init_Census {0,0,0,0,0,0,0,0,0,0}
11533: #if MAIN
11534: Census empty_Census = Init_Census;
11535: Census _CENSUS = Init_Census;
11536: #else
11537: extern Census empty_Census;
11538: extern Census _CENSUS;
11539: #endif
11540:
11541: #define alloc_census(id,n) _CENSUS./**/id/**/_mny += (n)
11542: #define free_census(id,n) _CENSUS./**/id/**/_mny -= (n)
11543: #define err_census(S,C) err("%s P%d B%d l%d w%d c%d b%d r%d i%d bf%d bm%d",\
11544: S,(C)->Page_mny,(C)->Block_mny,(C)->Txtln_mny,(C)->Word_mny,\
11545: (C)->Char_mny,(C)->Blob_mny,(C)->Run_mny,(C)->Interp_mny,\
11546: (C)->Bfeats_mny,(C)->BMask_mny )
11547: #define err_census_all err_census("allocated: ",&(_CENSUS))
11548: #define err_census_rec(rp) { \
11549: Census *cs; cs = (Census *)census_rec((rp)); \
11550: err_census(ident_toa((rp)->ident),cs); \
11551: }
11552: #else
11553:
11554: #define alloc_census(i,n)
11555: #define free_census(i,n)
11556: #define err_census(s,c)
11557: #define err_census_all
11558: #define err_census_rec(r)
11559:
11560: #endif
11561:
11562:
11563: /* Most record types can own an ASCII label, which is simply a
11564: '\0'-terminated string. Its uses are varied. */
11565: #define MAX_LABEL_LEN 128 /* maximum no. characters in a label string */
11566:
11567: #if FWRI
11568:
11569: #if dbg_fwrb_toa
11570: #define fwrb_label(F,L) { \
11571: fwri_str((F),(L)); \
11572: err("fwrb_label: \"%s\"",(L)); \
11573: }
11574: #else
11575: #define fwrb_label(F,L) { \
11576: fwri_str((F),(L)); \
11577: }
11578: #endif
11579:
11580: #else
11581:
11582: #if dbg_fwrb_toa
11583: #define fwrb_label(F,L) { \
11584: fputs((L),(F)); \
11585: fputc('\0',(F)); \
11586: err("fwrb_label: \"%s\"",(L)); \
11587: }
11588: #else
11589: #define fwrb_label(F,L) { \
11590: fputs((L),(F)); \
11591: fputc('\0',(F)); \
11592: }
11593: #endif
11594:
11595: #endif
11596:
11597: char *frdb_label();
11598:
11599: /* A boundary is an ordered list of vertices.
11600: In some uses, it is assumed to close: in this case, the first point
11601: is not repeated at the end.
11602: `vn' counts the no. vertices. bdy_trace omits consecutive duplicates and
11603: compresses horizontal and vertical runs.
11604: `per' counts the no. of pixels on the 8-connected boundary. An attempt has been
11605: made not to count consecutive duplicate pixels, but this may be buggy.
11606: `ren' counts the number of run-ends touched. Each run contributes two ends,
11607: even if it is one pixel long. The sum of ren-counts among all bdys for a blob
11608: should equal exactly twice the no. runs.
11609: Note that vn<=per and vn<=2*ren, and (probably) ren<=per.
11610: A ``smoothed'' version (courtesy of John Hobby) may be given in s[],
11611: expressed in fractional pixels.
11612: */
11613: typedef struct Bdy {
11614: Ident ident; /* shows type of boundary */
11615: Bbx bx; /* bounding box (usually relative to blob's bx.a) */
11616: long per; /* no. pixels in 8-connected perimeter */
11617: int ren; /* no. run-ends touched */
11618: int vn; /* no. distinct vertices in v[] */
11619: Sp *v; /* array of vn+1 vertices, v[0]==v[vn] (malloc space) */
11620: short fr; /* fraction of pixels used in smoothed outline */
11621: int sn; /* no. distinct smoothed vertices in s[] */
11622: Sp *s; /* array of sn+1 vertices, s[0]==s[sn] (malloc space) */
11623: int an; /* no. vertices in polygonal approximation */
11624: Sp **ap; /* approx'n: array of an ptrs into v[] (in malloc space) */
11625: float err; /* error tolerance used for approximation */
11626: int hn; /* no. vertices in convex hull of polygonal approx'n */
11627: Sp ***hpp; /* convex hull: array of hn ptrs into ap[] (malloc) */
11628: struct Bdy *n; /* for use when a member of a linked-list */
11629: } Bdy;
11630:
11631: #define Init_Bdy {IsBdy,Init_Bbx,0,0,0,NULL,1,0,NULL,0,NULL,0.0,0,NULL,NULL}
11632: #if MAIN
11633: Bdy empty_Bdy = Init_Bdy;
11634: #else
11635: extern Bdy empty_Bdy;
11636: #endif
11637:
11638: #define Bdy_verts 00000000001 /* vertices */
11639: #define Bdy_approx 00000000002 /* polygonal approx'n */
11640: #define Bdy_hull 00000000004 /* convex hull */
11641: #define Bdy_ALL (Bdy_verts|Bdy_approx|Bdy_hull)
11642: #define Bdy_ccw 00000000100 /* winding order is counter-clockwise*/
11643: #define Bdy_half 00000000200 /* uses half-pixel boundary points */
11644:
11645: /* A boundaries-set is an ordered list of boundaries.
11646: In some uses, they are used to enclose a connected region: in this case,
11647: all are closed, and the first is conventionally the exterior and the others
11648: are interior boundaries. The interior is then always to the left
11649: of the boundary: that is, the exterior boundary is oriented counter-
11650: clockwise, and the interior boundaries clockwise */
11651: typedef struct Bdys {
11652: int mny; /* no. boundaries */
11653: long per; /* perimeter of all bdys */
11654: Bdy *b; /* array of boundaries (malloc space) (sometimes first) */
11655: } Bdys;
11656:
11657: #define Init_Bdys {0,0,NULL}
11658: #if MAIN
11659: Bdys empty_Bdys = Init_Bdys;
11660: #else
11661: extern Bdys empty_Bdys;
11662: #endif
11663:
11664: /* A boundary edge is an ordered pair of vertices along a boundary. It implicitly
11665: describes an 8-connected sequence of pixels from a to b, inclusive. Also
11666: used for straight-line approximations to the set of pixels, and the convex hull
11667: of such an approximation. */
11668: typedef struct BdyEdge {
11669: Bdy *byp; /* boundary to which it belongs */
11670: Sp *ap,*bp; /* ptrs into byp->v */
11671: long per; /* perimeter: no. 8-connected pixels */
11672: Pp ctr; /* centroid */
11673: Radians ang; /* ls-fitted angle (directed roughly from a to b) */
11674: Pp a; /* endpoints a & b (with sub-pixel precision) */
11675: Pp b;
11676: } BdyEdge;
11677:
11678: #define Init_BdyEdge {NULL,NULL,NULL,0,Init_Zero_Pp,0.0,Init_Zero_Pp,Init_Zero_Pp}
11679: #if MAIN
11680: BdyEdge empty_BdyEdge = Init_BdyEdge;
11681: #else
11682: extern BdyEdge empty_BdyEdge;
11683: #endif
11684:
11685: /* Ordered set of BdyEdges */
11686: typedef struct BdyEdges {
11687: int mny;
11688: BdyEdge **pa; /* NULL-terminated array of pointers to BdyEdges */
11689: } BdyEdges;
11690:
11691: #define Init_BdyEdges {0,NULL}
11692: #if MAIN
11693: BdyEdges empty_BdyEdges = Init_BdyEdges;
11694: #else
11695: extern BdyEdges empty_BdyEdges;
11696: #endif
11697:
11698: /* Moments of a region (or boundary-list) of pixels */
11699:
11700: typedef struct Moments {
11701: /* 0th moment */
11702: int M00; /* area: sum of 1 */
11703: /* 1st moments */
11704: int M10; /* sum of xi */
11705: int M01; /* sum of yi */
11706: Pp c; /* centroid: M10/M00, M01/M00 */
11707: /* 2nd moments (relative to centroid) */
11708: float M20; /* sum of rxi*rxi */
11709: float M11; /* sum of rxi*ryi */
11710: float M02; /* sum of ryi*ryi */
11711: Radians a; /* orientation angle, in [-PI/2,PI/2) (radians) */
11712: Pp d; /* directional vector of principal axis */
11713: } Moments;
11714:
11715: #define Init_Moments {0,0,0,{0.0,0.0},0.0,0.0,0.0,0.0,{0.0,0.0}}
11716: #if MAIN
11717: Moments zero_Moments = Init_Moments;
11718: #else
11719: extern Moments zero_Moments;
11720: #endif
11721:
11722: /* functions in Text.c */
11723: Bdy *alloc_bdy();
11724: Bdys *alloc_bdys();
11725:
11726: /* functions in Bdy.c */
11727: Bdys *dup_bdys_etc();
11728: Bdy *dup_bdy_etc();
11729: Bdys *boundaries();
11730: char *moments_toa();
11731: Moments *bdy_moments();
11732: boolean fit_bdyedge();
11733: BdyEdge *dup_bdyedge();
11734: BdyEdge *append_bdyedge();
11735: remove_bdyedge();
11736: free_bdyedges();
11737: BdyEdges *dup_bdyedges();
11738:
11739: /* Each Run is initially inserted into a `line set', owned by its scan Line.
11740: Later, as connections are discovered, it joins a `tree set'.
11741: When the forest of trees of which it is a part is finally complete, the Run
11742: is removed from its `line set', and added to a `blob set'.
11743: */
11744:
11745: typedef struct Run { /* internal (main memory) record */
11746: Scoor y, xs, xe; /* coordinates of black interval (y,[xs,xe]) */
11747: struct Run *n; /* line & blob sets: next Run */
11748: unsigned short ad, bd; /* tree set: above,below degrees (no. conn'd)*/
11749: struct Run *ac, *bc; /* tree set: above,below leftmost connections */
11750: union { struct Tree *o; /* tree set: owner Tree */
11751: int no; /* blob set: sequence no. 0,1,... in set */
11752: } u; /* (overlain fields) */
11753: } Run;
11754:
11755: #define Init_Run {0,0,0,NULL,0,0,NULL,NULL}
11756: #if MAIN
11757: Run empty_Run = Init_Run;
11758: #else
11759: extern Run empty_Run;
11760: #endif
11761:
11762: /* Peripheral file format. `ac' and `bc' are relative to the position
11763: of this run in the canonical run order. */
11764: typedef struct RunF { /* external (peripheral file) record (full size) */
11765: Scoor y, xs, xe; /* coordinates of black interval (y,[xs,xe]) */
11766: unsigned short ad, bd; /* above,below degrees */
11767: unsigned short ac, bc; /* above,below leftmost connections (indices) */
11768: } RunF;
11769:
11770: #define Init_RunF {0,0,0,0,0,0,0}
11771: #if MAIN
11772: RunF empty_RunF = Init_RunF;
11773: #else
11774: extern RunF empty_RunF;
11775: #endif
11776:
11777: #define fwri_RunF(F,P) { \
11778: fwri_Scoor((F),(P)->y); \
11779: fwri_Scoor((F),(P)->xs); \
11780: fwri_Scoor((F),(P)->xe); \
11781: fwri_uint2((F),(P)->ad); \
11782: fwri_uint2((F),(P)->bd); \
11783: fwri_uint2((F),(P)->ac); \
11784: fwri_uint2((F),(P)->bc); \
11785: }
11786:
11787: #define frdi_RunF(F,P) ( feof(F)? 0 : ( \
11788: (P)->y=frdi_Scoor(F), \
11789: (P)->xs=frdi_Scoor(F), \
11790: (P)->xe=frdi_Scoor(F), \
11791: (P)->ad=frdi_uint2(F), \
11792: (P)->bd=frdi_uint2(F), \
11793: (P)->ac=frdi_uint2(F), \
11794: (P)->bc=frdi_uint2(F), \
11795: (ferror(F)? -errno: 1) ) )
11796:
11797: /* In `well-behaved' text, the overwhelming majority of Blobs are small
11798: enough that all their Runs can be encoded using character data fields,
11799: a factor of two saving, which is important since a dense IEEE proceedings
11800: page blob file would otherwise require 2.3Mbytes */
11801: typedef struct RunFS { /* external (peripheral file) record (small size) */
11802: unsigned char y, xs, xe;/* coordinates of black interval (y,[xs,xe]) */
11803: unsigned char ad, bd; /* above,below degrees */
11804: unsigned char ac, bc; /* above,below leftmost connections (indices) */
11805: } RunFS;
11806:
11807: #define Init_RunFS {0,0,0,0,0,0,0}
11808: #if MAIN
11809: RunFS empty_RunFS = Init_RunFS;
11810: #else
11811: extern RunFS empty_RunFS;
11812: #endif
11813:
11814: #define fwri_RunFS(F,P) { \
11815: fwri_uint1((F),(P)->y); \
11816: fwri_uint1((F),(P)->xs); \
11817: fwri_uint1((F),(P)->xe); \
11818: fwri_uint1((F),(P)->ad); \
11819: fwri_uint1((F),(P)->bd); \
11820: fwri_uint1((F),(P)->ac); \
11821: fwri_uint1((F),(P)->bc); \
11822: }
11823:
11824: #define frdi_RunFS(F,P) ( feof(F)? 0: ( \
11825: (P)->y=frdi_uint1(F), \
11826: (P)->xs=frdi_uint1(F), \
11827: (P)->xe=frdi_uint1(F), \
11828: (P)->ad=frdi_uint1(F), \
11829: (P)->bd=frdi_uint1(F), \
11830: (P)->ac=frdi_uint1(F), \
11831: (P)->bc=frdi_uint1(F), \
11832: (ferror(F)? -errno: 1) ) )
11833:
11834: /* Set of runs. PROPOSED NEW FORMAT. Not yet incorporated widely. */
11835: typedef struct Runs {
11836: Ident ident; /* IsRuns & Runs_fi, Runs_ff, Runs_fs, or Runs_sk flags */
11837: int mny; /* no. runs */
11838: union { /* access to runs */
11839: struct Run *fi; /* first run of singly-linked list */
11840: struct RunF *ff; /* top of RunF[mny] array */
11841: struct RunFS *fs; /* top of RunFS[mny] array */
11842: long sk; /* seek(F,seek,0) will find them in file F */
11843: } r;
11844: } Runs;
11845:
11846: #define Init_Runs {IsRuns,0} /* NOTE: can't initialize union */
11847: #if MAIN
11848: Runs empty_Runs = Init_Runs;
11849: #else
11850: extern Runs empty_Runs;
11851: #endif
11852:
11853: /* INTERNAL management */
11854:
11855: #if !MAIN
11856: extern
11857: #endif
11858: struct {
11859: int incr; /* size of each pool[i] */
11860: int pools; /* no. of pools allocated */
11861: Run **pool; /* malloc space Run pool[pools][0..incr-1] */
11862: int next; /* the next avail Run is: pool[pools-1][next] */
11863: Run *free; /* head of free lifo list (NULL if none) */
11864: Run *cur; /* most-recently allocated Run */
11865: int total; /* total no. ever allocated */
11866: boolean dbg;
11867: } _RunPool
11868: #if MAIN
11869: = {0,0,NULL,0,NULL,NULL,0,F}
11870: #endif
11871: ;
11872:
11873: /* Run management routines (Text.c) */
11874: boolean alloc_run_pool();
11875: free_run_pool();
11876: Run *hard_alloc_run();
11877: err_run();
11878: err_runb();
11879: err_runf();
11880: err_runfs();
11881: err_run_stats();
11882:
11883: /* Allocate a Run from the RunPool (returns (Run *)) -- mostly inline */
11884: #define alloc_run() ( _RunPool.total++, (_RunPool.free!=NULL)? \
11885: (_RunPool.cur=_RunPool.free,_RunPool.free=_RunPool.cur->n, \
11886: *(_RunPool.cur)=empty_Run,_RunPool.cur): \
11887: ( (_RunPool.next<_RunPool.incr)? \
11888: (_RunPool.cur=_RunPool.pool[_RunPool.pools-1]+(_RunPool.next++), \
11889: *(_RunPool.cur)=empty_Run,_RunPool.cur): \
11890: hard_alloc_run() ) )
11891:
11892: /* Free a Run back into the RunPool -- entirely inline */
11893: #define free_run(rp) { (rp)->n = _RunPool.free; _RunPool.free = (rp); }
11894:
11895: /* EXTERNAL file format:
11896: If BlobF.runs is zero, then conventionally the Runs have simply been omitted.
11897: The RunF.y, RunF.xs, & RunF.xe coordinates are offsets from BlobF.bx.a
11898: (their blob's left-top corner). RunF.ac & RunF.bc index into an array of
11899: only those RunF records belonging to the current BlobF, in ascending
11900: lexicographic order on (RunF.y,RunF.xs) -- so that they are in the range
11901: [0,BlobF.runs-1].
11902: IMPROVEMENTS:
11903: */
11904:
11905: /* some subroutines are too lazy to handle indefinitely large blobs */
11906: #define Runs_Max 10000
11907:
11908: /* A Blob is (formally) a maximal 8-connected set of black pixels.
11909: The connectivity algorithm finds them in strictly increasing order on
11910: (y,xe) of its Run with highest (y,xe).
11911: */
11912:
11913: typedef struct Blob { /* internal (main memory) record */
11914: Ident ident; /* identification bits */
11915: Seq no; /* blob sequence no */
11916: Bbx bx;
11917: long area;
11918: long per;
11919: struct Blob *n; /* free set: next blob */
11920: Merit m; /* Only used locally (not for peripheral file) */
11921: Runs *rsp; /* runs (not yet used) */
11922: Bdys *bdsp; /* boundaries (in malloc space); NULL if none */
11923: /* presently in use (but planned to be replaced by Runs) */
11924: int runs;
11925: union { /* to find runs */
11926: struct Run *f; /* blob set: first run */
11927: struct RunF *ff; /* top of RunF array */
11928: long seek; /* seek(f,seek,0) will find them */
11929: } r;
11930: } Blob;
11931:
11932: #define Init_Blob {IsBlob,0,Init_Bbx,0,0,NULL,0.0,NULL,NULL,0,}
11933: #if MAIN
11934: Blob empty_Blob = Init_Blob;
11935: #else
11936: extern Blob empty_Blob;
11937: #endif
11938:
11939: typedef struct Blobs { /* Blob set */
11940: int mny; /* the number of pointers in set */
11941: Blob **bpa; /* pts to NULL-terminated array[mny+1] of pointers */
11942: } Blobs;
11943:
11944: #define Init_Blobs {0,NULL}
11945: #if MAIN
11946: Blobs empty_Blobs = Init_Blobs;
11947: #else
11948: extern Blobs empty_Blobs;
11949: #endif
11950:
11951: /* Singly-linked list of Blobs. Only forward `next' links Blob.n are used. */
11952: typedef struct Blobl { /* Blob list */
11953: int mny; /* the number in set */
11954: Blob *fi; /* to first */
11955: Blob *la; /* to last */
11956: } Blobl;
11957:
11958: #define Init_Blobl {0,NULL,NULL}
11959: #if MAIN
11960: Blobl empty_Blobl = Init_Blobl;
11961: #else
11962: extern Blobl empty_Blobl;
11963: #endif
11964:
11965: typedef struct BlobF { /* external file format */
11966: Ident ident; /* identification bits: IsBlob must be set */
11967: Bbx bx;
11968: long area;
11969: long per;
11970: int runs; /* no. runs to follow */
11971: short bdys; /* no. bdys to follow */
11972: } BlobF;
11973:
11974: /* Blob identification bits */
11975: #define Blob_lm 00000000001 /* touches left margin */
11976: #define Blob_rm 00000000002 /* touches right margin */
11977: #define Blob_tm 00000000004 /* touches top margin */
11978: #define Blob_bm 00000000010 /* touches bottom margin */
11979: #define Blob_chopt 00000000020 /* chopped (at the top) */
11980: #define Blob_chopb 00000000040 /* chopped (at the bottom) */
11981: #define Blob_chopl 00000002000 /* chopped (at the left) */
11982: #define Blob_chopr 00000004000 /* chopped (at the right) */
11983: #define Blob_small 00000000200 /* its runs (can be) compressed x2 */
11984: #define Blob_local 00000000400 /* unassigned: avail for local pgm use */
11985:
11986: /* INTERNAL management: */
11987:
11988: int hi_blob_no; /* current highest blob no */
11989:
11990: /* Blobs are allocated from a pool of free ones */
11991: int blob_max;
11992: Blob *blob_pool;
11993: Blob blob_fr; /* head of list of free blobs */
11994: int blob_fr_mny;
11995: int blob_hi; /* high-water mark in blob pool */
11996: int blob_chopped; /* total no. of blobs that were chopped */
11997: boolean blob_debug; /* debug traces? */
11998:
11999: /* EXTERNAL file format:
12000: A Blob file consists of an arbitrary number of:
12001: BlobF record, followed by BlobF.runs instances of:
12002: RunF record
12003: If BlobF.runs is zero, then conventionally the Runs have simply been omitted.
12004: The RunF.y, RunF.xs, & RunF.xe coordinates are relative offsets from BlobF.bx.a
12005: (their blob's left-top corner). RunF.ac & RunF.bc index into an array of
12006: only those RunF records belonging to the current BlobF, in ascending
12007: lexicographic order on (RunF.y,RunF.xs) -- so that they are in the range
12008: [0,BlobF.runs-1]. If ad(or, bd)==0, the ac(or, bc) is undefined (conn sets
12009: them conventionally to 0).
12010: */
12011:
12012: /* Blob management routines (conBlob.c) */
12013: Blob *alloc_blob();
12014: free_blob();
12015: boolean alloc_blob_pool();
12016: free_blob_pool();
12017: Blob *alloc_pool_blob();
12018: free_pool_blob();
12019: out_blob();
12020: fwrb_blob_etc();
12021: boolean frdb_blob_etc();
12022: boolean frdb_runfs();
12023: err_blob();
12024: err_blob_runs();
12025: err_blob_runfs();
12026: err_blob_briefly();
12027: err_blobf();
12028: err_blob_stats();
12029: boolean blob_small();
12030:
12031: /* Compute height-above-baseline in ems of Char *cp w.r.t. Txtln *lp,
12032: on a page of y-resolution res. The txtln's `basl' & `size' must be set up. */
12033: #define char_bhgt(cp,lp,res) \
12034: ((((cp)->bx.b.y - (lp)->basl)/(double)(res)*INS_PER_PT*(lp)->size))
12035:
12036: /* an Interpretation of a Char */
12037: typedef struct Interp {
12038: Ident ident;
12039: struct Cl *clp;
12040: struct Class *clsp;
12041: ClassId ci; /* class id (font, size, name, variant) */
12042: Merit mshap; /* shape merit in [0,1] */
12043: Pts size; /* implied text size */
12044: Merit msize; /* size merit in [0,1] */
12045: Scoor basl; /* implied absolute baseline location */
12046: Merit mbhgt; /* height-above-baseline merit in [0,1] */
12047: Merit m; /* match merit (due to mshap, msize, & mbhgt) */
12048: Prob p; /* approximate probability */
12049: struct Interp *n; /* next in singly-linked list */
12050: } Interp;
12051:
12052: #define Init_Interp {IsInterp,NULL,NULL,Init_ClassId,0.0,0.0,0.0,0,0.0,0.0,0.0,NULL}
12053: #if MAIN
12054: Interp empty_Interp = Init_Interp;
12055: #else
12056: extern Interp empty_Interp;
12057: #endif
12058:
12059: /* Interp.ident flags: */
12060: #define Interp_spelled 00000000001 /* has passed a spelling check */
12061:
12062: #define free_interp(i) {free((i)); free_census(Interp,1); }
12063:
12064: typedef struct InterpF {
12065: Ident ident;
12066: ClassId ci; /* class id (font, size, name, variant) */
12067: Merit mshap; /* shape merit */
12068: Pts size; /* implied text size (in points) */
12069: Merit msize; /* size merit */
12070: Scoor basl; /* implied baseline location */
12071: Merit mbhgt; /* height-above-baseline merit */
12072: Merit m; /* match merit (due to shp, siz, hgt) */
12073: } InterpF;
12074:
12075: /* a list of interpretations */
12076: typedef struct Interpl {
12077: short mny; /* no. in list */
12078: struct Interp *fi; /* first in list (mny==0 -> fi==NULL) */
12079: } Interpl;
12080:
12081: #define Init_Interpl {0,NULL}
12082: #if MAIN
12083: Interpl empty_Interpl = Init_Interpl;
12084: #else
12085: extern Interpl empty_Interpl;
12086: #endif
12087:
12088: /* a set of interpretations */
12089: typedef struct Interps {
12090: short mny; /* no. in set */
12091: struct Interp **pa; /* NULL-terminated array of ptrs (malloc spc) */
12092: Merit m; /* combined merit (normalized product) */
12093: } Interps;
12094:
12095: #define Init_Interps {0,NULL,0.0}
12096: #if MAIN
12097: Interps empty_Interps = Init_Interps;
12098: #else
12099: extern Interps empty_Interps;
12100: #endif
12101:
12102: typedef struct Shapes {
12103: short mny; /* no. items in set */
12104: short alloc; /* no. items that can fit in array (alloc>=mny) */
12105: Nb_s *sa; /* ptr to contiguous array (malloc space) */
12106: } Shapes;
12107:
12108: #define Init_Shapes {0,0,NULL}
12109: #if MAIN
12110: Shapes empty_Shapes = Init_Shapes;
12111: #else
12112: extern Shapes empty_Shapes;
12113: #endif
12114:
12115: #define SH_INCR (20) /* Shapes are allocated by this increment */
12116:
12117: #define init_sh(sh) { \
12118: (sh)->alloc = SH_INCR; \
12119: if(((sh)->sa=(Nb_s *)malloc((sh)->alloc*sizeof(Nb_s)))==NULL) \
12120: abort("can't alloc sh->sa[%d]",(sh)->alloc); \
12121: (sh)->mny = 0; \
12122: }
12123:
12124: #define add_sh(s,sh) { \
12125: if((sh)->mny==(sh)->alloc) { \
12126: (sh)->alloc += SH_INCR; \
12127: if(((sh)->sa=(Nb_s *)realloc((sh)->sa,(sh)->alloc*sizeof(Nb_s)))==NULL) \
12128: abort("can't alloc (sh)->sa[%d]",(sh)->alloc); \
12129: }; \
12130: (sh)->sa[(sh)->mny++] = *(s); \
12131: }
12132:
12133: /* Parameters governing the pseudo-random generation of a Char image
12134: using a 1st-order statistical model of imaging. */
12135: typedef struct RanParms {
12136: short res_x; /* -r resolution (scanner pels/inch) */
12137: short res_y; /* (for now, equal to res_x) */
12138: Pts size; /* -p size of text */
12139: Radians skew; /* -a skew angle */
12140: Ems bhgt; /* -b height above baseline */
12141: float blur; /* -e blurring std err (scanner pels) */
12142: float jitter; /* -j jitter std err (scanner pels) */
12143: float kern; /* -k kerning std err (scanner pels) */
12144: float speckle; /* -s pel-wise additive noise std err (scanner pels) */
12145: float thresh; /* -t threshold for binarization */
12146: float xscale; /* -x horizontal scaling (dimensionless) */
12147: float yscale; /* -y vertical scaling (dimensionless) */
12148: } RanParms;
12149: #define Init_RanParms {0,0,0.0,0.0,0.0,0.7,0.0,0.0,0.125,0.25,1.0,1.0}
12150: #if MAIN
12151: RanParms empty_RanParms = Init_RanParms;
12152: #else
12153: extern RanParms empty_RanParms;
12154: #endif
12155:
12156: RanParms *alloc_ranparms();
12157: RanParms *dup_ranparms();
12158: char *ranparms_toa();
12159: RanParms *ato_ranparms();
12160: fwrb_ranparms();
12161: int frdb_ranparms();
12162:
12163: /* Char - a character: isolated, elementary symbol of the writing system;
12164: linguists might call this a `graph' */
12165: typedef struct Char {
12166: Ident ident; /* feature bits */
12167: Bbx bx;
12168: Scoor csp; /* space before character in Txtln (abs. coords) */
12169: long area; /* no. pixels */
12170: long per; /* perimeter (all bdys) */
12171: Scoor basl; /* baseline (absolute coordinates, local copy) */
12172: /* next should be Blobl */
12173: int bmny; /* no. blobs in Char */
12174: struct Blob *fi; /* 1st in list (p.n ptrs) (bmny==0 -> fi==NULL) */
12175: Pval *sfv; /* scalar-features (SFv) */
12176: Shapes sh; /* set of shapes (size- & loc'n-invariant) */
12177: Bfeats *bfsp; /* binary features */
12178: RanParms *rp; /* randomizing parameters */
12179: Interpl il; /* interpretations */
12180: char *l; /* label (ASCII string in malloc space) */
12181: } Char;
12182:
12183: #define Init_Char {IsChar,Init_Bbx,0,0L,0L,Scoor_MIN,0,NULL,NULL,Init_Shapes,NULL,NULL,Init_Interpl,NULL}
12184: #if MAIN
12185: Char empty_Char = Init_Char;
12186: #else
12187: extern Char empty_Char;
12188: #endif
12189:
12190: /* Char.ident flags: */
12191: #define Char_spelled 00000000001 /* Its 1st Interp is in correct spelling */
12192: #define Char_confused 00000000002 /* The classifier may have confused this */
12193: #define Char_termhyp 00000000004 /* a terminal hyphen of its Word */
12194: #define Char_omit 00000000010 /* can be omitted */
12195: #define Char_label 00000000020 /* has an ASCII string label */
12196: #define Char_ranparms 00000000040 /* has RanParms */
12197: #define Char_split 00000000100 /* resulted from splitting a Char */
12198: #define Char_merged 00000000200 /* resulted from merging Chars */
12199:
12200: typedef struct Chars {
12201: int mny; /* mny==0 -> cpa==NULL */
12202: Char **cpa; /* pts to NULL-term'd array of ptrs (in malloc space) */
12203: } Chars;
12204:
12205: #define Init_Chars {0,NULL}
12206: #if MAIN
12207: Chars empty_Chars = Init_Chars;
12208: #else
12209: extern Chars empty_Chars;
12210: #endif
12211:
12212: /* CharF - Char external file format */
12213: typedef struct CharF {
12214: Ident ident; /* feature bits: IsChar must be set */
12215: Bbx bx;
12216: Scoor csp; /* space before character in Txtln (abs. coords) */
12217: long area;
12218: long per;
12219: short bmny; /* no. blobs to follow */
12220: short imny; /* no. interpretations (follows immediately) */
12221: short sfmny; /* no. scalar features (follows immediately) */
12222: short shmny; /* no. shape features (follows immediately) */
12223: short bfmny; /* no. binary features (follows immediately) */
12224: /* if ident&Char_ranparms, RanParms follows CharF */
12225: /* if ident&Char_label, label follows CharF ('\0'-terminated string) */
12226: } CharF;
12227:
12228: Char *alloc_char(); /* in Text.c */
12229: Char *append_char();
12230: Char *insert_char();
12231: Char *insert_char_word();
12232: Char *dup_char();
12233: Char *dup_char_etc();
12234: Chars *append_chars();
12235: Chars *dup_chars_etc();
12236:
12237: typedef struct Words {
12238: int mny; /* mny==0 -> wpa==NULL */
12239: struct Word **wpa; /* pts to NULL-term'd array of ptrs */
12240: } Words;
12241:
12242: #define Init_Words {0,NULL}
12243: #if MAIN
12244: Words empty_Words = Init_Words;
12245: #else
12246: extern Words empty_Words;
12247: #endif
12248:
12249: /* Word - one or more Chars lying in a textline close together.
12250: wsp (word space) is always >=0 and is scaled by xheight (of Txtln) */
12251: typedef struct Word {
12252: Ident ident; /* feature bits */
12253: Bbx bx;
12254: float wsp; /* space before word (multiple of wst*em) */
12255: Merit m; /* Word merit (function of its Char's merits) */
12256: Prob p; /* probability */
12257: Words ws; /* set of alternative segmentations */
12258: Chars cs;
12259: Blobs bs;
12260: char *l; /* label (ASCII string in malloc space) */
12261: int hash; /* hash key for fast equality checking */
12262: } Word;
12263:
12264: #define Init_Word {IsWord,Init_Bbx,0.0,0.0,0.0,Init_Words,Init_Chars,Init_Blobs,NULL,0}
12265: #if MAIN
12266: Word empty_Word = Init_Word;
12267: #else
12268: extern Word empty_Word;
12269: #endif
12270:
12271: /* Word-interpretation (as printable ASCII string).
12272: All string fields must point to malloc-space strings.
12273: */
12274: typedef struct WordInterp {
12275: Ident ident; /* identifies word type */
12276: char *s; /* entire string = pp+by+po+ps */
12277: char *pp; /* punctuation prefix */
12278: char *by; /* body of word */
12279: char *po; /* possessive ('s 'S) or negative (n't N'T) suffix */
12280: char *ps; /* punctuation suffix */
12281: } WordInterp;
12282:
12283: #define Init_WordInterp {IsWordInterp,NULL,NULL,NULL,NULL,NULL}
12284: #if MAIN
12285: WordInterp empty_WordInterp = Init_WordInterp;
12286: #else
12287: extern WordInterp empty_WordInterp;
12288: #endif
12289:
12290: WordInterp *dup_wordinterp_etc();
12291:
12292: /* Word.ident & WordInterp.ident flags: */
12293: #define Word_spelled 00000000001 /* by spells correctly */
12294: #define Word_wf 00000000002 /* s is well-formed */
12295: #define Word_ok 00000000004 /* s is ok ("acceptable") */
12296: #define Word_numeric 00000000010 /* by is numeric */
12297: #define Word_initcap 00000000020 /* by has initial capital */
12298: #define Word_allcaps 00000000040 /* by is all caps */
12299: #define Word_hyphens 00000000100 /* by has imbedded hyphens */
12300: #define Word_slashes 00000000200 /* by has imbedded slashes */
12301: #define Word_endsent 00000000400 /* end of sentence: ps has .!? */
12302: #define Word_termhyp 00000001000 /* some interpretation ends with hyphen */
12303: #define Word_label 00000002000 /* has an ASCII string label */
12304: #define Word_allalp 00000004000 /* s is all alphabetic */
12305: #define Word_bodalp 00000010000 /* by is all alphabetic */
12306:
12307: /* WordF - Word external file format */
12308: typedef struct WordF {
12309: Ident ident; /* feature bits: IsWord must be set */
12310: Bbx bx;
12311: float wsp; /* space before word (multiple of thr) */
12312: float m; /* merit */
12313: short wmny; /* no. Words (in Word.ws) to follow this Word */
12314: short cmny; /* no. Chars to follow this Word */
12315: short bmny; /* no. Blobs to follow this Word */
12316: /* if ident&Word_label, label follows WordF ('\0'-terminated string) */
12317: } WordF;
12318:
12319: /* constant pitch model for a Txtln */
12320: typedef struct ConstPitch {
12321: Ems w; /* Character pitch */
12322: Scoor o; /* origin (one of the character break points) */
12323: float r; /* max/min autocorrelation ratio - the larger the better */
12324: } ConstPitch;
12325:
12326: #define Init_ConstPitch {0.0,0,0.0}
12327: #if MAIN
12328: ConstPitch empty_ConstPitch = Init_ConstPitch;
12329: #else
12330: extern ConstPitch empty_ConstPitch;
12331: #endif
12332:
12333: typedef struct Txtlns {
12334: short mny;
12335: struct Txtln **lpa; /* to array of Txtln's (if mny==0, lpa==NULL) */
12336: } Txtlns;
12337:
12338: #define Init_Txtlns {0,NULL}
12339: #if MAIN
12340: Txtlns empty_Txtlns = Init_Txtlns;
12341: #else
12342: extern Txtlns empty_Txtlns;
12343: #endif
12344:
12345: /* Text Line */
12346: #define Txtln_label 00000000004 /* has an ASCII string label */
12347: #define Txtln_size 00000000002 /* dominant text size chosen */
12348: #define Txtln_basl 00000000001 /* dominant baseline chosen */
12349:
12350: typedef struct Txtln {
12351: Ident ident;
12352: Bbx bx;
12353: Pts size; /* dominant text size (0 means unknown) */
12354: Scoor basl; /* dominant baseline (absolute y coordinate) */
12355: short *proj; /* ptr to malloc space projection array */
12356: ConstPitch *cp; /* ptr to malloc space constant-pitch model */
12357: Merit m; /* merit */
12358: Txtlns ls; /* alternative Txtln segmentations */
12359: Words ws; /* sorted asc. on x */
12360: Chars cs; /* sorted asc. on bx.a.x */
12361: Blobs bs; /* misc. non-char blobs */
12362: char *l; /* label (ASCII string in malloc space) */
12363: } Txtln;
12364:
12365: #define Init_Txtln {IsTxtln,Init_Bbx,0.0,0,NULL,NULL,0.0,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
12366: #if MAIN
12367: Txtln empty_Txtln = Init_Txtln;
12368: #else
12369: extern Txtln empty_Txtln;
12370: #endif
12371:
12372: /* Text Line */
12373: typedef struct TxtlnF {
12374: Ident ident; /* IsTxtln must be set */
12375: Bbx bx;
12376: Scoor basl; /* baseline (absolute y coordinate) */
12377: Pts size; /* text size (<=0.0 means none is known) */
12378: short pmny; /* no. shorts in projection array to follow */
12379: float m; /* merit */
12380: short lmny; /* no. alternative txtlns to follow */
12381: short wmny; /* no. words to follow */
12382: short cmny; /* no. chars to follow */
12383: int bmny; /* no. blobs to follow */
12384: /* if ident&Txtln_label, label follows TxtlnF ('\0'-terminated string) */
12385: } TxtlnF;
12386:
12387: /* blocks of text */
12388: typedef struct Blocks {
12389: short mny; /* if mny==0, bpa==NULL */
12390: struct Block **bpa; /* to NULL-term'd array of ptrs */
12391: } Blocks;
12392:
12393: #define Init_Blocks {0,NULL}
12394: #if MAIN
12395: Blocks empty_Blocks = Init_Blocks;
12396: #else
12397: extern Blocks empty_Blocks;
12398: #endif
12399:
12400: /* block of text */
12401: typedef struct Block {
12402: Ident ident;
12403: Bbx bx; /* bounding box of block */
12404: Radians skew; /* skew angle (as correction to Page.skew) */
12405: Radians shear; /* shear angle (as correction to Page.shear) */
12406: Ems wst; /* word-space threshhold */
12407: Merit m; /* merit */
12408: Blocks bks; /* Blocks nested within this one */
12409: Txtlns ls;
12410: Words ws;
12411: Chars cs;
12412: Blobs bs;
12413: char *l; /* label (ASCII string in malloc space) */
12414: } Block;
12415:
12416: #define Init_Block {IsBlock,Init_Bbx,0.0,0.0,0.0,0.0,Init_Blocks,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
12417: #if MAIN
12418: Block empty_Block = Init_Block;
12419: #else
12420: extern Block empty_Block;
12421: #endif
12422:
12423: /* Ident bits for Blocks */
12424: #define Block_wst 00000000001 /* word-space-thresh set up */
12425: #define Block_label 00000000002 /* has an ASCII string label */
12426:
12427: #define Block_mb (1)
12428:
12429: /* block of text */
12430: typedef struct BlockF {
12431: Ident ident; /* IsBlock must be set */
12432: Bbx bx;
12433: Ems wst; /* word-space threshold */
12434: float skew;
12435: float shear;
12436: #if Block_mb
12437: float m;
12438: short bkmny;
12439: #endif
12440: short lmny;
12441: short wmny;
12442: int cmny;
12443: int bmny;
12444: /* if ident&Block_label, label follows BlockF ('\0'-terminated string) */
12445: } BlockF;
12446:
12447: /* page */
12448: typedef struct Page {
12449: Ident ident;
12450: Bbx bx; /* extreme indices in pixels */
12451: short res_x; /* resolution in pixels/inch: x & y */
12452: short res_y;
12453: Radians skew; /* skew angle */
12454: Radians shear; /* shear correction */
12455: Blocks bks; /* blocks */
12456: Txtlns ls; /* textlines (those not in any block) */
12457: Words ws; /* words (not in any textline) */
12458: Chars cs; /* chars (not in any word) */
12459: Blobs bs; /* blobs (not in any char) */
12460: char *l; /* label (ASCII string in malloc space) */
12461: } Page;
12462:
12463: #define Init_Page {IsPage,Init_Bbx,0,0,0.0,0.0,Init_Blocks,Init_Txtlns,Init_Words,Init_Chars,Init_Blobs,NULL}
12464: #if MAIN
12465: Page empty_Page = Init_Page;
12466: #else
12467: extern Page empty_Page;
12468: #endif
12469:
12470: #define Page_label 00000000001 /* has a label */
12471:
12472: /* Pages of text */
12473: typedef struct Pages {
12474: unsigned short mny; /* if mny==0, pa==NULL */
12475: struct Page **pa; /* to NULL-term'd array of ptrs */
12476: } Pages;
12477:
12478: #define Init_Pages {0,NULL}
12479: #if MAIN
12480: Pages empty_Pages = Init_Pages;
12481: #else
12482: extern Pages empty_Pages;
12483: #endif
12484:
12485: typedef struct PageF {
12486: Ident ident; /* IsPage bit must be set */
12487: short res_x,res_y; /* resolution in pixels/inch: x & y */
12488: Bbx bx; /* extreme indices in pixels */
12489: float skew; /* original page skew angle, radians */
12490: float shear; /* original page shear angle, radians */
12491: short bkmny; /* no. blocks */
12492: short lmny; /* no. textlines (not in any block) */
12493: short wmny; /* no. words (not in any textline) */
12494: int cmny; /* no. chars (not in any word) */
12495: int bmny; /* no. blobs (not in any char)) */
12496: /* if ident&Page_label, label follows PageF ('\0'-terminated string) */
12497: } PageF;
12498:
12499: #define Page_new 00000000001 /* Page is in ``new'' format */
12500:
12501: /* Each Dim-file begins with a Doc record */
12502: typedef struct Doc {
12503: unsigned short version; /* file format version number */
12504: Pages ps;
12505: char *l; /* ASCII label */
12506: } Doc;
12507:
12508: #define Init_Doc {0,Init_Pages,NULL}
12509: #if MAIN
12510: Doc empty_Doc = Init_Doc;
12511: #else
12512: extern Doc empty_Doc;
12513: #endif
12514:
12515: char *ident_toa();
12516: Ident cto_ident();
12517: Ident cto_flag();
12518: char *merit_toa();
12519: Page *alloc_page();
12520: char *page_toa();
12521: Page *dup_page();
12522: Page *dup_page_etc();
12523: Block *alloc_block();
12524: char *block_toa();
12525: Block *dup_block();
12526: Block *dup_block_etc();
12527: Block *append_block();
12528: Blocks *dup_blocks_etc();
12529: ConstPitch *alloc_constpitch();
12530: char *constpitch_toa();
12531: Txtln *alloc_txtln();
12532: char *txtln_toa();
12533: Word *alloc_word();
12534: char *word_toa();
12535: boolean eq_word();
12536: int hash_word();
12537: Char *alloc_char();
12538: char *char_toa();
12539: Pp *char_centroid();
12540: Char *char_of_blob();
12541: char *interp_toa();
12542: char *blob_toa();
12543: Pp *blob_centroid();
12544: char *runf_toa();
12545: char *runfs_toa();
12546: char *pp_toa();
12547: char *bdyedge_toa();
12548: Blob *dup_blob();
12549: Blob *dup_blob_etc();
12550: Blob *dup_blobl_etc();
12551: Blob *runs_to_runs();
12552: Blobs *dup_blobs_etc();
12553: Blobs *blobl_to_blobs();
12554: Interp *alloc_interp();
12555: Interp *dup_interp();
12556: Interpl *dup_interpl_etc();
12557: Interps *dup_interps_etc();
12558: Word *append_word();
12559: Word *insert_word();
12560: Word *insert_word_txtln();
12561: Word *dup_word();
12562: Word *dup_word_etc();
12563: Words *dup_words_etc();
12564: Txtln *dup_txtln();
12565: Txtln *dup_txtln_etc();
12566: Txtlns *dup_txtlns_etc();
12567: Block *dup_block();
12568: Block *dup_block_etc();
12569: Radians add_ang();
12570: Radians subtract_ang();
12571:
12572: /* in-line macroes */
12573:
12574: /* Merge the `source' Bbx into the `destination' Bbx, expanding the dest Bbx
12575: as required. The source Bbx is unmodified. Usage:
12576: merge_bbx(s,d)
12577: Bbx *s,*d;
12578: */
12579: #define merge_bbx(s,d) { \
12580: if((s)->a.x < (d)->a.x) (d)->a.x = (s)->a.x; \
12581: if((s)->a.y < (d)->a.y) (d)->a.y = (s)->a.y; \
12582: if((s)->b.x > (d)->b.x) (d)->b.x = (s)->b.x; \
12583: if((s)->b.y > (d)->b.y) (d)->b.y = (s)->b.y; \
12584: }
12585:
12586: /* Experimental implementation of a data structure for maintaining a set
12587: of distinct Words whose merit falls within a dynamically-varying range.
12588: This implementation is worst-case quadratic time.
12589: BUGS: insert_wordset shouldn't duplicate the word.
12590: */
12591:
12592: #define dbg_ws (0) /* if !=0, enable WordSet debugging tracing */
12593:
12594: typedef struct WordSet {
12595: double cut; /* cut-fraction */
12596: int cap; /* capacity: maximum number permitted at any time */
12597: double top; /* maximum merit seen since allocation */
12598: Words ws; /* sorted by top-choice merit */
12599: Word *max,*min; /* maximum/minimum entries currently in ws */
12600: int high; /* high-water: max. no. entries in history */
12601: } WordSet;
12602: #define Init_WordSet {1.0,INT_MAX,0.0,Init_Words,NULL,NULL,0}
12603: #if MAIN
12604: WordSet empty_WordSet = Init_WordSet;
12605: #else
12606: extern WordSet empty_WordSet;
12607: #endif
12608:
12609: #define size_wordset(s) ((s)->ws.mny)
12610: #define top_wordset(s) ((s)->top)
12611: #define max_wordset(s) ((s)->max)
12612: #define min_wordset(s) ((s)->min)
12613: #define max_wordmerit(s) ((max_wordset((s))!=NULL)? (max_wordset((s)))->m: 0.0)
12614: #define min_wordmerit(s) ((min_wordset((s))!=NULL)? (min_wordset((s)))->m: 0.0)
12615:
12616: Merit wordmerit();
12617: WordSet *alloc_wordset();
12618: boolean insert_wordset();
12619: Word *remove_wordset();
12620: int free_wordset_etc();
12621: err_wordset();
12622: 0707070035351137151006640007620000050000010263160476773367000001000000001554Units.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
12623: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
12624: /* The copyright notice does not imply actual or intended publication. */
12625: /* AUTHORS: */
12626: /* H. S. Baird - ATT-BL MH - first versions */
12627:
12628: #define UNITS "icpPsu" /* units notation for: inches, cm, points, picas,
12629: scanner pixel (Scoor), and basic unit (also Scoor) */
12630:
12631: #define INCHES_PER_POINT (0.0138) /* cf. Chicago Manual of Style */
12632:
12633: #define RADIANS_PER_DEGREE (PI/180.0)
12634: #define DtoR (RADIANS_PER_DEGREE) /* degrees * DtoR = radians */
12635:
12636: #define Radians double /* angle in radians */
12637:
12638: /* machine-independent I/O has a resolution of 0.1 second of arc */
12639: #define fwri_Radians(F,V) fwri_int3((F),(V)*2062648.1)
12640: #define frdi_Radians(F) (frdi_int3(F)/(Radians)2062648.1)
12641: 0707070035351137161006640007620000050000010263200476773367000001000000012421abort.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
12642: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
12643: /* The copyright notice does not imply actual or intended publication. */
12644: /* AUTHORS: */
12645: /* H. S. Baird - ATT-BL MH - first versions */
12646:
12647: /* abort.h - three terse message, warning, and abort functions.
12648: out(s,a,...) print message to stdout
12649: err(s,a,...) print warning to stderr
12650: abort(s,a,...) complain to stderr and exit abnormally.
12651: The 's' argument is a printf string, and the 'a',... are (up to 15) arguments
12652: matching %-fields. These routines prefix the program name and append `\n' to
12653: the printf string, then write to:
12654: `out': stdout
12655: `err' & `abort': stderr
12656: Abort also says " - abort", and exits abnormally.
12657: This #include should be preceded by `#define CMDNAME "xxx"' so that `xxx:'
12658: will be prefixed to msg and abort strings. */
12659:
12660: #ifndef CMDNAME
12661: #define CMDNAME "hsb"
12662: #endif
12663:
12664: #define MSGMAX 120
12665:
12666: #ifndef boolean
12667: #define boolean int
12668: #define T 1
12669: #define F 0
12670: #endif
12671:
12672: /* WARNING: these function-call versions do not port well:
12673: e.g. floating-point arguments are botched on MIPS and SGI machines */
12674:
12675: out(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
12676: char *s;
12677: { static char m[MSGMAX];
12678: strcpy(m,CMDNAME);
12679: strcat(m,": ");
12680: strcat(m,s);
12681: strcat(m,"\n");
12682: fprintf(stdout,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
12683: }
12684:
12685: err(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
12686: char *s;
12687: { char m[MSGMAX];
12688: strcpy(m,CMDNAME);
12689: strcat(m,": ");
12690: strcat(m,s);
12691: strcat(m,"\n");
12692: fprintf(stderr,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
12693: }
12694:
12695: abort(s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
12696: char *s;
12697: { static char m[MSGMAX];
12698: strcpy(m,s);
12699: strcat(m," - abort");
12700: err(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15);
12701: exit(1);
12702: }
12703:
12704: /* These hybrid macro/function forms ports well, but are awkward to use... */
12705:
12706: char *_F(s)
12707: char *s;
12708: { static char m[MSGMAX];
12709: strcpy(m,CMDNAME);
12710: strcat(m,": ");
12711: strcat(m,s);
12712: strcat(m,"\n");
12713: return(m);
12714: }
12715:
12716: #define out0(Z) fprintf(stdout,_F(Z))
12717: #define out1(Z,A) fprintf(stdout,_F(Z),A)
12718: #define out2(Z,A,B) fprintf(stdout,_F(Z),A,B)
12719: #define out3(Z,A,B,C) fprintf(stdout,_F(Z),A,B,C)
12720: #define out4(Z,A,B,C,D) fprintf(stdout,_F(Z),A,B,C,D)
12721: #define out5(Z,A,B,C,D,E) fprintf(stdout,_F(Z),A,B,C,D,E)
12722: #define out6(Z,A,B,C,D,E,F) fprintf(stdout,_F(Z),A,B,C,D,E,F)
12723: #define out7(Z,A,B,C,D,E,F,G) fprintf(stdout,_F(Z),A,B,C,D,E,F,G)
12724: #define out8(Z,A,B,C,D,E,F,G,H) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H)
12725: #define out9(Z,A,B,C,D,E,F,G,H,I) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I)
12726: #define out10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I,J)
12727: #define out11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stdout,_F(Z),A,B,C,D,E,F,G,H,I,J,K)
12728:
12729: #define err0(Z) fprintf(stderr,_F(Z))
12730: #define err1(Z,A) fprintf(stderr,_F(Z),A)
12731: #define err2(Z,A,B) fprintf(stderr,_F(Z),A,B)
12732: #define err3(Z,A,B,C) fprintf(stderr,_F(Z),A,B,C)
12733: #define err4(Z,A,B,C,D) fprintf(stderr,_F(Z),A,B,C,D)
12734: #define err5(Z,A,B,C,D,E) fprintf(stderr,_F(Z),A,B,C,D,E)
12735: #define err6(Z,A,B,C,D,E,F) fprintf(stderr,_F(Z),A,B,C,D,E,F)
12736: #define err7(Z,A,B,C,D,E,F,G) fprintf(stderr,_F(Z),A,B,C,D,E,F,G)
12737: #define err8(Z,A,B,C,D,E,F,G,H) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H)
12738: #define err9(Z,A,B,C,D,E,F,G,H,I) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I)
12739: #define err10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I,J)
12740: #define err11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stderr,_F(Z),A,B,C,D,E,F,G,H,I,J,K)
12741:
12742: char *_G(s)
12743: char *s;
12744: { static char m[MSGMAX];
12745: strcpy(m,CMDNAME);
12746: strcat(m,": ");
12747: strcat(m,s);
12748: strcat(m," - abort\n");
12749: return(m);
12750: }
12751:
12752: #define abort0(Z) fprintf(stderr,_G(Z))
12753: #define abort1(Z,A) fprintf(stderr,_G(Z),A)
12754: #define abort2(Z,A,B) fprintf(stderr,_G(Z),A,B)
12755: #define abort3(Z,A,B,C) fprintf(stderr,_G(Z),A,B,C)
12756: #define abort4(Z,A,B,C,D) fprintf(stderr,_G(Z),A,B,C,D)
12757: #define abort5(Z,A,B,C,D,E) fprintf(stderr,_G(Z),A,B,C,D,E)
12758: #define abort6(Z,A,B,C,D,E,F) fprintf(stderr,_G(Z),A,B,C,D,E,F)
12759: #define abort7(Z,A,B,C,D,E,F,G) fprintf(stderr,_G(Z),A,B,C,D,E,F,G)
12760: #define abort8(Z,A,B,C,D,E,F,G,H) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H)
12761: #define abort9(Z,A,B,C,D,E,F,G,H,I) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I)
12762: #define abort10(Z,A,B,C,D,E,F,G,H,I,J) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I,J)
12763: #define abort11(Z,A,B,C,D,E,F,G,H,I,J,K) fprintf(stderr,_G(Z),A,B,C,D,E,F,G,H,I,J,K)
12764:
12765: boolean ask_more()
12766: { FILE *tty;
12767: char reply[20];
12768: static int skip = 0;
12769: if(skip<=0) {
12770: fputs("MORE? ",(tty=fopen("/dev/tty","w"))); fclose(tty);
12771: fgets(reply,20,(tty=fopen("/dev/tty","r"))); fclose(tty);
12772: switch (reply[0]) {
12773: case '\0': case 'y': case 'Y':
12774: return(T);
12775: case 'n': case 'N': case 'q': case 'Q':
12776: return(F);
12777: case '0': case '1': case '2': case '3': case '4':
12778: case '5': case '6': case '7': case '8': case '9':
12779: skip = atoi(reply);
12780: return(T);
12781: case '*':
12782: skip = INT_MAX;
12783: return(T);
12784: default:
12785: skip = 0;
12786: return(T);
12787: };
12788: }
12789: else skip--;
12790: return(T);
12791: }
12792:
12793: boolean ask_quit()
12794: { FILE *tty;
12795: char reply[20];
12796: fputs("QUIT? ",(tty=fopen("/dev/tty","w"))); fclose(tty);
12797: fgets(reply,20,(tty=fopen("/dev/tty","r"))); fclose(tty);
12798: switch (reply[0]) {
12799: case 'y': case 'Y':
12800: return(F);
12801: case 'n': case 'N': case 'q': case 'Q':
12802: return(T);
12803: };
12804: return(F);
12805: }
12806:
12807: 0707070035351137171006640007620000050000010263220476773367100000600000171751bcp.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
12808: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
12809: /* The copyright notice does not imply actual or intended publication. */
12810: /* AUTHORS: */
12811: /* H. S. Baird - ATT-BL MH - first versions */
12812: /* T. J. ThompsonT - ATT-BL HO - extensions */
12813:
12814: /* bcp.c - translate among binary image file formats, optionally trimming,
12815: shifting, scaling, and rotating the image on the fly. Scaling is by
12816: arbitrary real factors, separately in X & Y. Rotation is still crude and
12817: slow.
12818: USAGE:
12819: bcp [options...] [I [O]]
12820: I/O:
12821: If O is omitted, all output is concatenated to stdout.
12822: If I is also omitted, all input is read from stdin.
12823: If I is a filename, it is the sole input; but, if it is a directory name,
12824: then every leaf of its file tree is processed in turn; and, in this case,
12825: if O also is specified, it is forced to become the root directory
12826: of an isomorphic tree of output files (this use of Unix file trees
12827: may be defeated using compile-time option FILE_TREE).
12828:
12829: [PROPOSED: An input file may be a catenation of pages. These may vary
12830: in TYPE and other parameters. They will all be translated to the same
12831: output type, and catenated to one file, each with a complete translated
12832: header. Generally, a complete picfile header must be repeated at the
12833: top of each page: exceptions include TYPE=cdf, which packs pages in its
12834: own peculiar way.]
12835:
12836: OPTIONS:
12837: NOTE: lengths, distances, and pixel indices are assumed to be in
12838: units of pixels (scanner units), unless one of "icpPs" is appended,
12839: meaning inches, cm, points, picas, or (explicitly) scanner pixels.
12840: This applies to option: -w (seems buggy).
12841:
12842: -B[io] read/write bitfile(9.5) format (doesn't use TYPE= header).
12843: [doesn't run-length encode yet: may be bulky.]
12844: -M write TYPE=bitmap format.
12845: -P write Postscript format (only on Suns; by Tim Thompson, ATT-BL HO)
12846: -Rx[,y] force output resolutions to x,y (overrides -xX[,Y]) (pixels/inch).
12847: Requires a RES=X Y line in the header.
12848: -R= Force the output resolution to be equal to the greater of
12849: the input resolutions.
12850: -S write Sun rasterfile format (only on Suns; by Tim Thompson,
12851: ATT-BL HO)
12852: -Tt when reading TYPE=dump, binarize the image by thresholding each
12853: pixel value as follows: (pixel<t)? black: white. (default: -T128)
12854: -Ww shrink-wrap output around black artwork, surrounding it with equal
12855: margins of width w (pixels), then translate so that the left-top
12856: corner of the margin box is at 0,0 (works only with TYPE=document-
12857: image input). (w must be >= 0)
12858: -Zx[,y] set input resolution to RES=x y (overriding existing RES, if any)
12859: -b write binary format (TYPE=binary)
12860: -d? trace to stderr:
12861: -dR comment on any change in resolution
12862: -dc point out oddities in cdf files which are, by default,
12863: silently corrected
12864: -dh file headers (a good first debugging step)
12865: -dm margins
12866: -dr runs (exhaustive, voluminous)
12867: -ds status and summary statistics (brief)
12868: -g31 write CCITT FAX Group 3 1-dim encoding
12869: -31 ditto
12870: -g32 write CCITT FAX Group 3 2-dim encoding (see also -k option)
12871: -32 ditto
12872: -g4 write CCITT FAX Group 4 encoding (the default output format)
12873: -4 ditto
12874: -kK set the 'k' for g32 encoding on output (default: -k4)
12875: -oX,Y offset the result by X,Y (merely shift the bounding box)
12876: -p write TYPE=dump NCHAN=1 format; input binary pixels
12877: are mapped to grey as follows: (pixel==white)? 255: 0.
12878: -r write rle format (this is Pavlidis' obsolescent OCR format)
12879: -t[lrbN] top of the page is really at the left/right/bottom;
12880: after all other transformations are carried out, the image
12881: will be rotated to bring the real top of page to the top.
12882: By arbitrary convention, the top-left corner of the rotated
12883: image will be equal to the top-left corner of the image
12884: resulting from all the other transformations.
12885: [UNFINISHED, UNDER DEVELOPMENT: -tr & -tb; -tN, where N is a
12886: numeric string, is interpreted as a counterclockwise rotation by
12887: N degrees: for now, only handle +/-20 degrees. The present code
12888: for -tN is slow and subject to aliasing.]
12889: -v reverse video: swap black and white
12890: -wL,T,R,B specify window to select:
12891: (L,T) is the left-top (origin) and (R,B) the OPEN right-bottom
12892: corner (i.e. the corner coordinates are not included.) A '%'
12893: argument defaults to the input window parameter.
12894: [NOTE: since non-zero L,T windows are still not everywhere well
12895: supported (by pcp, met, etc), it might be best to shift the
12896: new L,T to 0,0 on output -- but this is not done now.]
12897: -xX[,Y] expansion factor(s), horizontally and vertically;
12898: if only one is specified, they are assumed equal
12899: (default: -x1.0,1.0) May be overridden by -Rx[,y].
12900: Requires a RES=X Y line in the header.
12901: DESCRIPTION
12902: This translates among these formats of binary images:
12903: ccitt-g31, ccitt-g32, ccitt-g4, picture (TYPE=dump NCHAN=1), binary, rle,
12904: bitfile(9.5), cdf, Sun rasterfile (TYPE=bitmap), and Postscript. All require
12905: a TYPE= header in picfile format (see below), except bitfile(9.5) (as a result,
12906: to read these, must use special option: -Bi). Most require WINDOW=ox oy cx cy
12907: and RES=x y header lines also.
12908: Optionally, the image may be modified on the fly by the following
12909: operations performed in this order:
12910: trimming - a subset of the input image is selected (-w option)
12911: shifting - the origin is shifted (-o)
12912: scaling - real scaling factors are applied, in X & Y separately (-x, -R)
12913: rotation - by 90, 180, 270 degrees - UNDER DEVELOPMENT (-t option)
12914: reverse-video - swap black and white (-v option)
12915: Note that scaling changes the effective digitizing resolution by arbitrary
12916: real factors (expansion or contraction), in X and Y separately. Presently,
12917: this is accomplished naively by replication or deletion of pixels. If it is
12918: ever desired to apply more interesting image-processing techniques (such as
12919: smoothing and resampling), the required changes may be safely confined to
12920: functions transform_rlels() (in bcp.c) & transform_rlel() (in rlelib.c).
12921: Accepts TYPE=document-image (or TYPE=dim), flattening its hierarchy,
12922: and writes it out as a single page image.
12923: PICFILE FORMAT (briefly summarized; see picture(5))
12924: Each picture file comprises an ASCII header followed by binary data.
12925: The header is terminated by two newlines (an empty line). A typical header is:
12926: TYPE=ccitt-g4
12927: WINDOW=0 0 640 480
12928: RES=300 300
12929: (note the final empty line)
12930: TYPE must come first. The other lines may come in any order. WINDOW gives
12931: the x,y coordinates of the upper left corner (inclusive) and lower right
12932: corners (exclusive). Typically, an image of WxH pixels will be described
12933: by WINDOW=0 0 W H. RES=X Y gives the digitizing resolution horizontally and
12934: vertically, in integral pixels/inch. Supported TYPEs include:
12935:
12936: dump A two-dimensional array of pixel structures. NCHAN=1 is required:
12937: one byte per pixel. On input, the grey pixel values are thresholded
12938: to binary (see option -T). On output, black is 0 and white is 255.
12939:
12940: bitmap One bit/pixel, packed into bytes high-order bit first. Black is `1'.
12941: Each horizontal row is padded to a 16-bit boundary with `0'.
12942: (This is identical to Sun rasterfile format, except for the ASCII
12943: header.)
12944:
12945: ccitt-g4 CCITT FAX Group 4 compressed image. Similarly, ccitt-g31 means
12946: Group 3/1-D and ccitt-g32 means Group 3/2-D.
12947:
12948: (Obsolescent 112 formats:
12949: rle A run-length coding, better for binary images (see rle.h).
12950: binary 1 bit/pixel, packed into bytes low-order bit first. Black is `1'.
12951: Each horizontal row is padded to a full byte with `0'.)
12952:
12953: NOTE: bitfile(9.5) doesn't use an ASCII header.
12954:
12955: (Odd formats in use outside 112, sometimes very heavily:
12956: cdf supported on input only, and only the first page of several.
12957: tiff not yet supported.)
12958:
12959: IMPLEMENTATION STATUS
12960: CCITT FAX ``uncompressed'' (or, ``transparent'') mode is not implemented,
12961: either while encoding or decoding.
12962: Cdf is an input-only option; Sun rasterfile and Postscript are output-only options.
12963: Postscript output is useful only for very small images.
12964: Rotations are only partially implemented, and are slow.
12965:
12966: KNOWN BUGS (30 May 89)
12967: WINDOW=OX OY CX CY where OX or OY are non-zero is not handled correctly
12968: for every combination of file types.
12969: Unit gets passed wrongly to vto_scoor().
12970: Rle can't be both inout and output (design flaw: they share a buffer).
12971: Beware off-by-one errors (top or bottom line omitted); has not been
12972: carefully checked for all file type combinations.
12973:
12974: AUTHORS
12975: Dec 1988 - Henry S. Baird (AT&T Bell Labs MH) - first working draft
12976: Mar 1989 - Tim Thompson (BL HO) - extensions for SunOS, bug fixes, etc
12977: */
12978:
12979: #include <stdio.h>
12980: #include <string.h>
12981: #include <ctype.h>
12982: #include "CPU.h"
12983: #define MAIN 1
12984: #include "stdocr.h"
12985: #include "rle.h"
12986: #include "pic.h"
12987: #include "Text.h"
12988: /* Ugly stubs just to prevent Text.h dragging in many other *.h & *.o files */
12989: Bfeats *alloc_bfeats(){}; free_bfeats(){}; Bfeats *dup_bfeats(){};
12990: fwrb_bfeats(){}; frdb_bfeats(){}; fix_lag(){}; char *classid_toa(){};
12991: #include "Bitmap.h"
12992: #include "CCITT.h"
12993: #include "bitio.h"
12994: #if FILE_TREE
12995: #include "Path.h"
12996: #endif
12997: #define CMDNAME "bcp"
12998: #include "abort.h"
12999:
13000: double atof(),sin(),cos();
13001: char *strchr();
13002:
13003: /* Runtime options values */
13004: static struct {
13005: boolean from_bitfile; /* -Bi */
13006: boolean to_bitfile; /* -Bo */
13007: boolean to_bitmap; /* -M */
13008: boolean to_g31; /* -g31 or -31 */
13009: boolean to_g32; /* -g32 or -32 */
13010: boolean to_g4; /* -g4 or -4 */
13011: boolean to_rle; /* -r */
13012: boolean to_bin; /* -b */
13013: boolean to_pic; /* -p */
13014: boolean to_post; /* -P */
13015: boolean to_rast; /* -S */
13016: boolean omit_hdr; /* -O */
13017: Sp out_res; /* -R (-1 = unspecified; -2 = force-equal) */
13018: Scoor shrinkwrap; /* -W (-1 = unspecified) */
13019: Sp in_res; /* -Z (SHRT_MIN,SHRT_MIN = unspecified) */
13020: int g32_k; /* -k */
13021: int metheus; /* -m */
13022: Sp offset; /* -o */
13023: boolean dbg_any;
13024: boolean dbg_R; /* -dR */
13025: boolean dbg_c; /* -dc */
13026: boolean dbg_h; /* -dh */
13027: boolean dbg_m; /* -dm */
13028: boolean dbg_r; /* -dr */
13029: boolean dbg_s; /* -ds */
13030: boolean show; /* -s */
13031: char top; /* -tT takes on values: 't', 'l', 'r', 'b', 'a' */
13032: float top_angle; /* -t angular value (set if top=='a') (Radians) */
13033: int thresh; /* -Tt */
13034: boolean reverse; /* -v */
13035: char *optarg_l; /* -w?,,, */
13036: char *optarg_t; /* -w,?,, */
13037: char *optarg_r; /* -w,,?, */
13038: char *optarg_b; /* -w,,,? */
13039: Bbx trim; /* output margins resulting from -w */
13040: Pp expand; /* -x */
13041: char *in_fn;
13042: char *out_fn;
13043: } _O = {
13044: F, F, F, F, F, T, F, F, F, F, F,
13045: F, {-1,-1}, -1, {SHRT_MIN,SHRT_MIN}, 4, -1, Init_Zero_Sp,
13046: F, F, F, F, F, F, F, F,
13047: 't',0.0,
13048: 128,
13049: F,
13050: NULL, NULL, NULL, NULL,
13051: Init_Max_Bbx,
13052: {1.0,1.0},
13053: NULL, NULL };
13054:
13055: parse_args(arc,arv)
13056: int arc; char **arv;
13057: { /* getopt support */
13058: int optch;
13059: extern int optind;
13060: extern char *optarg;
13061:
13062: char *metheus_ev,metheus_digit;
13063: char *fs;
13064:
13065: /* default metheus number */
13066: if((metheus_ev=(char *)getenv("FB"))!=NULL) {
13067: metheus_digit = metheus_ev[(int)strlen(metheus_ev)-1];
13068: if((int)isdigit(metheus_digit)) {
13069: _O.metheus = (metheus_digit - '0');
13070: };
13071: };
13072:
13073: while((optch=getopt(arc,arv,"B:MOPR:ST:W:Z:3:4bd:g:k:m:o:prst:vw:x:"))!=EOF)
13074: switch(optch) {
13075: case 'B':
13076: switch(*optarg) {
13077: case 'o':
13078: _O.to_bitfile = T;
13079: _O.to_g4 = F;
13080: break;
13081: case 'i':
13082: _O.from_bitfile = T;
13083: break;
13084: default:
13085: abort("option -B%s is illegal",optarg);
13086: break;
13087: };
13088: break;
13089: case 'M': _O.to_bitmap = T; _O.to_g4 = F; break;
13090: case 'O': _O.omit_hdr = T; break;
13091: case 'P':
13092: #if CPU==SUN
13093: _O.to_post = T; _O.to_g4 = F;
13094: #else
13095: abort("-P option available only on Suns");
13096: #endif
13097: break;
13098: case 'R':
13099: if(*optarg=='=') {
13100: _O.out_res.x = _O.out_res.y = -2;
13101: fs=NULL;
13102: }
13103: else if((fs=strtok(optarg,","))!=NULL) {
13104: if(strcmp(fs,"%")!=0) {
13105: _O.out_res.x = atoi(fs);
13106: };
13107: };
13108: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
13109: if(strcmp(fs,"%")!=0) {
13110: _O.out_res.y = atoi(fs);
13111: };
13112: }
13113: else _O.out_res.y = _O.out_res.x;
13114: break;
13115: case 'S':
13116: #if CPU==SUN
13117: _O.to_rast = T; _O.to_g4 = F;
13118: #else
13119: abort("-S option available only on Suns");
13120: #endif
13121: break;
13122: case 'T': _O.thresh=atoi(optarg); break;
13123: case 'W': _O.shrinkwrap=atoi(optarg);
13124: if(_O.shrinkwrap<0) {
13125: err("-W%d must be >=0; force to -W0",
13126: _O.shrinkwrap);
13127: _O.shrinkwrap=0;
13128: };
13129: break;
13130: case 'Z':
13131: if((fs=strtok(optarg,","))!=NULL) {
13132: if(strcmp(fs,"%")!=0) {
13133: _O.in_res.x = atoi(fs);
13134: };
13135: };
13136: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
13137: if(strcmp(fs,"%")!=0) {
13138: _O.in_res.y = atoi(fs);
13139: };
13140: }
13141: else _O.in_res.y = _O.in_res.x;
13142: break;
13143: case '3':
13144: switch (*optarg) {
13145: case '1':
13146: _O.to_g31=T;
13147: _O.to_g4=F;
13148: break;
13149: case '2':
13150: _O.to_g32=T;
13151: _O.to_g4=F;
13152: break;
13153: default:
13154: abort("bad option: -g3%s",optarg);
13155: break;
13156: };
13157: break;
13158: case '4': _O.to_g4=T; break;
13159: case 'b':
13160: _O.to_bin=T;
13161: _O.to_g4=F;
13162: break;
13163: case 'd':
13164: _O.dbg_any=T;
13165: switch(*optarg) {
13166: case 'R': _O.dbg_R = T; break;
13167: case 'c': _O.dbg_c = T; break;
13168: case 'h': _O.dbg_h = T; break;
13169: case 'm': _O.dbg_m = T; break;
13170: case 'r': _O.dbg_r = T; break;
13171: case 's': _O.dbg_s = T; break;
13172: };
13173: break;
13174: case 'g':
13175: switch (optarg[0]) {
13176: case '3':
13177: switch (optarg[1]) {
13178: case '1':
13179: _O.to_g31=T;
13180: _O.to_g4=F;
13181: break;
13182: case '2':
13183: _O.to_g32=T;
13184: _O.to_g4=F;
13185: break;
13186: default:
13187: abort("bad option: -g%s",optarg);
13188: break;
13189: };
13190: break;
13191: case '4': _O.to_g4=T; break;
13192: default:
13193: abort("bad option: -g%s",optarg);
13194: break;
13195: };
13196: break;
13197: case 'k': _O.g32_k = atoi(optarg); break;
13198: case 'm': _O.metheus = atoi(optarg); break;
13199: case 'o':
13200: if((fs=strtok(optarg,","))!=NULL) {
13201: if(strcmp(fs,"%")!=0)
13202: _O.offset.x = atoi(fs);
13203: };
13204: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
13205: if(strcmp(fs,"%")!=0)
13206: _O.offset.y = atoi(fs);
13207: };
13208: break;
13209: case 'p':
13210: _O.to_pic=T;
13211: _O.to_g4=F;
13212: break;
13213: case 'r':
13214: _O.to_rle = T;
13215: _O.to_g4 = F;
13216: break;
13217: case 's': _O.show = T; break;
13218: case 't': _O.top = *optarg;
13219: if(strchr("0123456789.+-",_O.top)!=NULL) {
13220: _O.top = 'a'; /* angular value */
13221: _O.top_angle = atof(optarg)*DtoR;
13222: };
13223: break;
13224: case 'v': _O.reverse = T; break;
13225: case 'w':
13226: if( (fs=strtok(optarg,","))!=NULL
13227: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
13228: _O.optarg_l = strdup(fs);
13229: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
13230: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
13231: _O.optarg_t = strdup(fs);
13232: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
13233: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
13234: _O.optarg_r = strdup(fs);
13235: if( fs!=NULL && (fs=strtok((char *)0,","))!=NULL
13236: && strlen(fs)>0 && strcmp(fs,"%")!=0 )
13237: _O.optarg_b = strdup(fs);
13238: break;
13239: case 'x':
13240: if((fs=strtok(optarg,","))!=NULL) {
13241: if(strcmp(fs,"%")!=0) {
13242: if(*fs=='/')
13243: _O.expand.x = 1.0/atof(fs+1);
13244: else _O.expand.x = atof(fs);
13245: if(_O.expand.x<=0.0)
13246: _O.expand.x=1.0;
13247: };
13248: };
13249: if(fs!=NULL&&(fs=strtok((char *)0,","))!=NULL) {
13250: if(strcmp(fs,"%")!=0) {
13251: if(*fs=='/')
13252: _O.expand.y = 1.0/atof(fs+1);
13253: else _O.expand.y = atof(fs);
13254: if(_O.expand.y<=0.0)
13255: _O.expand.y=1.0;
13256: };
13257: }
13258: else _O.expand.y = _O.expand.x;
13259: break;
13260: default: break;
13261: };
13262: switch(arc-optind) {
13263: case 2:
13264: _O.out_fn = strdup(arv[optind+1]);
13265: case 1:
13266: _O.in_fn = strdup(arv[optind]);
13267: case 0:
13268: break;
13269: default:
13270: abort("<= two filenames expected");
13271: break;
13272: };
13273: if(_O.show&&_O.metheus==-1) {
13274: err("FB=/dev/omM not specified, using /dev/om0");
13275: _O.metheus = 0;
13276: };
13277: }
13278:
13279: unimplemented()
13280: { abort("unimplemented");
13281: }
13282:
13283: typedef struct Copy_arg {
13284: boolean bop; /* beginning of page */
13285: PIC_hdr *ph;
13286: int wid; /* bbx_wid(&(ph->bx)) (for speed) */
13287: BITFILE *bf;
13288: DST_table *tbl; /* for CCITT input */
13289: int k; /* CCITT Group 3 2-D k */
13290: int thresh; /* for input pic files */
13291: RLE_Lines rles; /* for TYPE=document-image or TYPE=dim */
13292: } Copy_arg;
13293: #define Init_Copy_arg {T,NULL,INT_MIN,NULL,NULL,4,128,Init_RLE_Lines}
13294: #if MAIN
13295: Copy_arg empty_Copy_arg = Init_Copy_arg;
13296: #else
13297: extern Copy_arg empty_Copy_arg;
13298: #endif
13299:
13300: /* SOURCES: return the next RLE_Line from the given file type, with run indices
13301: shifted to lie within [ a->ph->bx.a.x, a->ph->bx.b.x ].
13302: **** BUGS: not all handle non-zero a->ph->bx.a.x yet.
13303: */
13304:
13305: /* Handles non-zero a->ph->bx.a.x. */
13306: RLE_Line *cdf_mrlc_source(a)
13307: Copy_arg *a;
13308: #define dbg_cdf (0)
13309: { static RLE_Line rl;
13310: int n; /* no. pixels decoded */
13311: int col; /* color: 0=white, 1=black */
13312: int byte; /* input byte */
13313: int nb; /* no. bytes read for this line */
13314: int ni; /* nibble index: 0=1st (low-order), 1=2nd(high-order) */
13315: int nib; /* current nibble */
13316: int mult; /* multiplier for current nibble */
13317: int run; /* no. pixels in current run */
13318: RLE_Run *rp;
13319: #define toggle_color() {if(col) col=0; else col=1;}
13320: /* get next byte into `byte' */
13321: #define getbyte() { \
13322: if((byte=getc(a->ph->fp))==EOF) goto eof; nb++; \
13323: if(dbg_cdf) err("byte0x%x",byte); \
13324: }
13325: /* get next nibble into `nib' */
13326: #define getnib() { \
13327: if(ni) { getbyte(); ni=0; nib=byte&0x0F; } \
13328: else { ni=1; nib=(byte>>4); } \
13329: if(dbg_cdf) err("nib0x%x byte0x%x ni%d",nib,byte,ni); \
13330: }
13331: /* get next run into `run' */
13332: #define getrun() { \
13333: run=0; mult=1; \
13334: do {getnib(); run += mult * (nib&0x07); mult *= 8;} while(nib&0x08); \
13335: if(dbg_cdf) err("run%d %c",run,((col)? 'B': 'W')); \
13336: }
13337: a->bop = F;
13338: n=0; col=0; ni=1; nb=0; rp=rl.r;
13339: do { getrun();
13340: if(col) {/* black run */
13341: if(run>0) { /* ... of >0 length */
13342: rp->xs = a->ph->bx.a.x + n+1;
13343: rp->xe = a->ph->bx.a.x + (n+=run);
13344: if((rp-rl.r)>0 && ((rp-1)->xe >= rp->xs-1) ) {
13345: if(_O.dbg_c) err("cdf_mrlc_source: abutting black runs [%d,%d] & [%d,%d] - merged",
13346: (rp-1)->xs,(rp-1)->xe,
13347: rp->xs,rp->xe );
13348: /* merge with prior black run */
13349: (rp-1)->xe = rp->xe;
13350: }
13351: else rp++;
13352: }
13353: else { /* zero-length black run */
13354: if( _O.dbg_c && (rp-rl.r)>0 )
13355: err("cdf_mrlc_source: zero-length black run [%d,%d] in middle of line - ignored",
13356: n,n);
13357: };
13358: }
13359: else { /* white run */
13360: n+=run;
13361: };
13362: toggle_color();
13363: }
13364: while(n<a->wid);
13365: /* read 2 EOL nibbles */
13366: getnib(); getnib();
13367: rl.runs = rp - rl.r;
13368: rl.len = a->wid;
13369: if(rl.runs>0 && rl.r[rl.runs-1].xe>=a->wid) {
13370: if(_O.dbg_c)
13371: err("cdf_mrlc_source: run [%d,%d] in line of length %d - truncated",
13372: rl.r[rl.runs-1].xs,rl.r[rl.runs-1].xe,a->wid);
13373: rl.r[rl.runs-1].xe = a->wid-1;
13374: if(rl.r[rl.runs-1].xs>rl.r[rl.runs-1].xe) {
13375: rl.runs--;
13376: };
13377: };
13378: rl.y = a->ph->cy++;
13379: if(_O.dbg_r) nerr_RLE_Line("cdf_source: ",&rl);
13380: return(&rl);
13381:
13382: eof: if(dbg_cdf)
13383: err("cdf_mrlc_source: unexpected EOF, input line %d",a->ph->cy);
13384: return(NULL);
13385: }
13386:
13387: int no_runs_of_page(p)
13388: Page *p;
13389: { int runs;
13390: runs = 0;
13391: runs += no_runs_of_blocks(&p->bks);
13392: runs += no_runs_of_txtlns(&p->ls);
13393: runs += no_runs_of_words(&p->ws);
13394: runs += no_runs_of_chars(&p->cs);
13395: runs += no_runs_of_blobs(&p->bs);
13396: return(runs);
13397: }
13398:
13399: int runs_of_page(p,ra,max)
13400: Page *p;
13401: RLE_Yrun *ra;
13402: int max;
13403: { int runs;
13404: runs = 0;
13405: runs += runs_of_blocks(&p->bks,ra,max);
13406: runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
13407: runs += runs_of_words(&p->ws,ra+runs,max-runs);
13408: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
13409: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
13410: return(runs);
13411: }
13412:
13413: int no_runs_of_blocks(p)
13414: Blocks *p;
13415: { int runs;
13416: Block *pp,**ppp;
13417: runs = 0;
13418: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
13419: runs += no_runs_of_block(pp);
13420: return(runs);
13421: }
13422:
13423: int runs_of_blocks(p,ra,max)
13424: Blocks *p;
13425: RLE_Yrun *ra;
13426: int max;
13427: { int runs;
13428: Block *pp,**ppp;
13429: runs = 0;
13430: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
13431: runs += runs_of_block(pp,ra+runs,max-runs);
13432: return(runs);
13433: }
13434:
13435: int no_runs_of_block(p)
13436: Block *p;
13437: { int runs;
13438: runs = 0;
13439: runs += no_runs_of_txtlns(&p->ls);
13440: runs += no_runs_of_words(&p->ws);
13441: runs += no_runs_of_chars(&p->cs);
13442: runs += no_runs_of_blobs(&p->bs);
13443: return(runs);
13444: }
13445:
13446: int runs_of_block(p,ra,max)
13447: Block *p;
13448: RLE_Yrun *ra;
13449: int max;
13450: { int runs;
13451: runs = 0;
13452: runs += runs_of_txtlns(&p->ls,ra+runs,max-runs);
13453: runs += runs_of_words(&p->ws,ra+runs,max-runs);
13454: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
13455: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
13456: return(runs);
13457: }
13458:
13459: int no_runs_of_txtlns(p)
13460: Txtlns *p;
13461: { int runs;
13462: Txtln *pp,**ppp;
13463: runs = 0;
13464: if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
13465: runs += no_runs_of_txtln(pp);
13466: return(runs);
13467: }
13468:
13469: int runs_of_txtlns(p,ra,max)
13470: Txtlns *p;
13471: RLE_Yrun *ra;
13472: int max;
13473: { int runs;
13474: Txtln *pp,**ppp;
13475: runs = 0;
13476: if(p->mny>0) for(pp= *(ppp=p->lpa); pp!=NULL; pp= *(++ppp))
13477: runs += runs_of_txtln(pp,ra+runs,max-runs);
13478: return(runs);
13479: }
13480:
13481: int no_runs_of_txtln(p)
13482: Txtln *p;
13483: { int runs;
13484: runs = 0;
13485: runs += no_runs_of_words(&p->ws);
13486: runs += no_runs_of_chars(&p->cs);
13487: runs += no_runs_of_blobs(&p->bs);
13488: return(runs);
13489: }
13490:
13491: int runs_of_txtln(p,ra,max)
13492: Txtln *p;
13493: RLE_Yrun *ra;
13494: int max;
13495: { int runs;
13496: runs = 0;
13497: runs += runs_of_words(&p->ws,ra+runs,max-runs);
13498: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
13499: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
13500: return(runs);
13501: }
13502:
13503: int no_runs_of_words(p)
13504: Words *p;
13505: { int runs;
13506: Word *pp,**ppp;
13507: runs = 0;
13508: if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
13509: runs += no_runs_of_word(pp);
13510: return(runs);
13511: }
13512:
13513: int runs_of_words(p,ra,max)
13514: Words *p;
13515: RLE_Yrun *ra;
13516: int max;
13517: { int runs;
13518: Word *pp,**ppp;
13519: runs = 0;
13520: if(p->mny>0) for(pp= *(ppp=p->wpa); pp!=NULL; pp= *(++ppp))
13521: runs += runs_of_word(pp,ra+runs,max-runs);
13522: return(runs);
13523: }
13524:
13525: int no_runs_of_word(p)
13526: Word *p;
13527: { int runs;
13528: runs = 0;
13529: runs += no_runs_of_chars(&p->cs);
13530: runs += no_runs_of_blobs(&p->bs);
13531: return(runs);
13532: }
13533:
13534: int runs_of_word(p,ra,max)
13535: Word *p;
13536: RLE_Yrun *ra;
13537: int max;
13538: { int runs;
13539: runs = 0;
13540: runs += runs_of_chars(&p->cs,ra+runs,max-runs);
13541: runs += runs_of_blobs(&p->bs,ra+runs,max-runs);
13542: return(runs);
13543: }
13544:
13545: int no_runs_of_chars(p)
13546: Chars *p;
13547: { int runs;
13548: Char *pp,**ppp;
13549: runs = 0;
13550: if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
13551: runs += no_runs_of_char(pp);
13552: return(runs);
13553: }
13554:
13555: int runs_of_chars(p,ra,max)
13556: Chars *p;
13557: RLE_Yrun *ra;
13558: int max;
13559: { int runs;
13560: Char *pp,**ppp;
13561: runs = 0;
13562: if(p->mny>0) for(pp= *(ppp=p->cpa); pp!=NULL; pp= *(++ppp))
13563: runs += runs_of_char(pp,ra+runs,max-runs);
13564: return(runs);
13565: }
13566:
13567: int no_runs_of_blobs(p)
13568: Blobs *p;
13569: { int runs;
13570: Blob *pp,**ppp;
13571: runs = 0;
13572: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
13573: runs += pp->runs;
13574: return(runs);
13575: }
13576:
13577: int runs_of_blobs(p,ra,max)
13578: Blobs *p;
13579: RLE_Yrun *ra;
13580: int max;
13581: { int runs;
13582: Blob *pp,**ppp;
13583: runs = 0;
13584: if(p->mny>0) for(pp= *(ppp=p->bpa); pp!=NULL; pp= *(++ppp))
13585: runs += runs_of_blob(pp,ra+runs,max-runs);
13586: return(runs);
13587: }
13588:
13589: /* ascending lexicographic order on y,xs */
13590: int local_rn_asc(r1,r2)
13591: RLE_Yrun *r1,*r2;
13592: { if(r1->y < r2->y) return(-1);
13593: else if(r1->y==r2->y) {
13594: if(r1->xs < r2->xs) return(-1);
13595: else if (r1->xs == r2->xs) return(0);
13596: else return(1);
13597: }
13598: else return(1);
13599: }
13600:
13601: RLE_Lines *rle_lines_of_page(pgp)
13602: Page *pgp;
13603: { static RLE_Lines rls;
13604: int no_runs,cy,ri;
13605: RLE_Yrun *ra,*cr;
13606: RLE_Run *lr;
13607: RLE_Line *cl;
13608: /* count runs */
13609: no_runs = no_runs_of_page(pgp);
13610: if(_O.dbg_r) err("no_runs %d",no_runs);
13611: /* allocate runs array */
13612: if((ra=(RLE_Yrun *)malloc(no_runs*sizeof(RLE_Yrun)))==NULL)
13613: abort("rle_lines_of_page: can't malloc ra[%d]",no_runs);
13614: runs_of_page(pgp,ra,no_runs);
13615: /* sort runs ascending on (y,xs) */
13616: qsort(ra,no_runs,sizeof(RLE_Yrun),local_rn_asc);
13617: /* count RLE_lines.mny */
13618: rls.mny = 0; cy=INT_MIN;
13619: for(ri=0,cr=ra; ri<no_runs; ri++,cr++)
13620: if(cr->y!=cy) {
13621: rls.mny++;
13622: cy = cr->y;
13623: };
13624: /* allocate RLE_lines */
13625: if((rls.rla=(RLE_Line *)malloc(rls.mny*sizeof(RLE_Line)))==NULL)
13626: abort("rle_lines_of_page: can't malloc rls.rla[%d]",rls.mny);
13627: /* fill in RLE_lines */
13628: cy=INT_MIN; cl=rls.rla-1;
13629: for(ri=0,cr=ra; ri<no_runs; ri++,cr++) {
13630: if(cr->y!=cy) {
13631: cl++;
13632: cl->y = cy = cr->y;
13633: cl->runs = 0;
13634: lr = cl->r;
13635: };
13636: lr->xs = cr->xs; lr->xe = cr->xe; lr++; cl->runs++;
13637: };
13638: free(ra);
13639: return(&rls);
13640: }
13641:
13642: Bbx *bbx_of_rle_lines(rlsp)
13643: RLE_Lines *rlsp;
13644: { static Bbx res;
13645: Bbx r;
13646: int li,ri;
13647: RLE_Line *lp;
13648: RLE_Run *rp;
13649: res = empty_Bbx;
13650: for(li=0,lp=rlsp->rla; li<rlsp->mny; li++,lp++) {
13651: r.a.y = r.b.y = lp->y;
13652: for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
13653: r.a.x = rp->xs;
13654: r.b.x = rp->xe;
13655: merge_bbx(&r,&res);
13656: };
13657: };
13658: return(&res);
13659: }
13660:
13661: translate_rle_lines(r,p)
13662: RLE_Lines *r;
13663: Sp p;
13664: { int li,ri;
13665: RLE_Line *lp;
13666: RLE_Run *rp;
13667: for(li=0,lp=r->rla; li<r->mny; li++,lp++) {
13668: lp->y += p.y;
13669: for(ri=0,rp=lp->r; ri<lp->runs; ri++,rp++) {
13670: rp->xs += p.x;
13671: rp->xe += p.x;
13672: };
13673: };
13674: }
13675:
13676: RLE_Line *binary_source(a)
13677: Copy_arg *a;
13678: { static RLE_Line rl;
13679: unsigned char *inline;
13680: a->bop = F;
13681: if(PIC_rline(a->ph,&inline)==1) {
13682: rl.runs =
13683: rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
13684: rl.y = a->ph->cy;
13685: rl.len = a->wid;
13686: if(_O.dbg_r) nerr_RLE_Line("binary_source: ",&rl);
13687: return(&rl);
13688: }
13689: else { if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
13690: return(NULL);
13691: };
13692: }
13693:
13694: RLE_Line *bitmap_source(a)
13695: Copy_arg *a;
13696: { static RLE_Line rl;
13697: unsigned char *inline;
13698: register unsigned char *cp,*ep,*rb;
13699: a->bop = F;
13700: if(PIC_rline(a->ph,&inline)==1) {
13701: /* reverse bit order in each byte */
13702: rb=bm_consts.Rbits;
13703: ep=(cp=inline)+a->ph->bpl;
13704: while(cp<ep) { *cp = rb[*cp]; cp++; };
13705: rl.runs =
13706: rlbr(inline,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
13707: rl.y = a->ph->cy;
13708: rl.len = a->wid;
13709: if(_O.dbg_r) nerr_RLE_Line("bitmap_source: ",&rl);
13710: return(&rl);
13711: }
13712: else { if(_O.dbg_r) nerr_RLE_Line("binary_source: ",NULL);
13713: return(NULL);
13714: };
13715: }
13716:
13717: RLE_Line *bitfile_source(a)
13718: Copy_arg *a;
13719: #define dbg_Bi (F)
13720: { static RLE_Line rl;
13721: unsigned char *cp,*ep,*pp;
13722: int ch,ci;
13723: a->bop = F;
13724: /* copy current line to prior */
13725: memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
13726: /* read one binary raster line */
13727: ep=(cp=a->ph->line)+a->ph->bpl;
13728: while(cp<ep) {
13729: if((ch=getc(a->ph->fp))!=EOF) {
13730: if(ch<127) {
13731: if(dbg_Bi) err("cb: %o",ch);
13732: if((fread(cp,1,2*ch,a->ph->fp))==2*ch) {
13733: cp += 2*ch;
13734: }
13735: else return(NULL);
13736: }
13737: else { ch &= 0x7F;
13738: if(dbg_Bi) err("cb: 0200+%o",ch);
13739: if((fread(cp,1,2,a->ph->fp))==2) {
13740: cp += 2;
13741: for(ci=0;ci<ch-1;ci++,cp+=2) {
13742: *cp = *(cp-2);
13743: *(cp+1) = *(cp-1);
13744: };
13745: }
13746: else return(NULL);
13747: };
13748: }
13749: else return(NULL);
13750: };
13751: /* reverse bit-order, & xor with prior line */
13752: for(ep=(cp=a->ph->line)+a->ph->bpl,pp=a->ph->pline; cp<ep; cp++,pp++) {
13753: *cp = bm_consts.Rbits[*cp] ^ *pp;
13754: if(dbg_Bi) err("db: %o = ?? ^ %o",*cp,*pp);
13755: };
13756: rl.runs =
13757: rlbr(a->ph->line,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,rl.r);
13758: rl.y = ++a->ph->cy;
13759: rl.len = a->wid;
13760: if(_O.dbg_r) nerr_RLE_Line("bitfile_source: ",&rl);
13761: return(&rl);
13762: }
13763:
13764: RLE_Line *dim_source(a)
13765: Copy_arg *a;
13766: { static RLE_Line *rlp,*rlq,rl;
13767: if(a->bop) {
13768: a->ph->cy = a->ph->bx.a.y-1;
13769: rlq=(rlp=a->rles.rla)+a->rles.mny;
13770: };
13771: if(_O.dbg_r) {
13772: err("dim_source: a->bop %d a->ph->cy %d",a->bop,a->ph->cy);
13773: nerr_RLE_Line("*rlp",rlp);
13774: };
13775: a->bop = F;
13776: a->ph->cy++;
13777: if(rlp<rlq) {
13778: if(a->ph->cy < rlp->y) {
13779: rl.y = a->ph->cy;
13780: rl.runs = 0;
13781: rl.len = a->wid;
13782: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",&rl);
13783: return(&rl);
13784: }
13785: else if(a->ph->cy == rlp->y) {
13786: rlp->len = a->wid;
13787: rlp++;
13788: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
13789: return(rlp-1);
13790: }
13791: else { while(rlp<rlq && a->ph->cy>rlp->y) rlp++;
13792: if(rlp>=rlq) {
13793: if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
13794: return(NULL);
13795: }
13796: else { rlp->len = a->wid;
13797: rlp++;
13798: if(_O.dbg_r) nerr_RLE_Line("dim_source: ",rlp-1);
13799: return(rlp-1);
13800: };
13801: };
13802: }
13803: else { if(_O.dbg_r) nerr_RLE_Line("dim_source: NULL");
13804: return(NULL);
13805: };
13806: }
13807:
13808: RLE_Line *rle_source(a)
13809: Copy_arg *a;
13810: { static RLE_Line *rl;
13811: a->bop = F;
13812: if((rl=RLE_get_Line(a->ph->bx.a.x,a->ph->bx.b.x))!=NULL) {
13813: a->ph->cy = rl->y;
13814: rl->len = a->wid;
13815: if(_O.dbg_r) nerr_RLE_Line("rle_source: ",rl);
13816: return(rl);
13817: }
13818: else { if(_O.dbg_r) nerr_RLE_Line("rle_source: ",NULL);
13819: return(NULL);
13820: };
13821: }
13822:
13823: /* Read next line of runs from pic file, with runs shifted to lie in the range
13824: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
13825: RLE_Line *pic_source(a)
13826: Copy_arg *a;
13827: { static RLE_Line rl;
13828: unsigned char *inline;
13829: a->bop = F;
13830: if(PIC_rline(a->ph,&inline)==1) {
13831: rl.runs = trcr(inline,
13832: 0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->bx.a.x,
13833: a->thresh,rl.r);
13834: rl.y = a->ph->cy;
13835: rl.len = a->wid;
13836: if(_O.dbg_r) nerr_RLE_Line("pic_source: ",&rl);
13837: return(&rl);
13838: }
13839: else { if(_O.dbg_r) nerr_RLE_Line("pic_source: ",NULL);
13840: return(NULL);
13841: };
13842: }
13843:
13844: /* Read next line of runs from g31 file, with runs shifted to lie in the range
13845: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
13846: RLE_Line *g31_source(a)
13847: Copy_arg *a;
13848: { static RLE_Line *rlp,rl;
13849: RLE_Run *rp,*ep,*np;
13850: if((rlp=g31_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
13851: a->bop = F;
13852: rlp->y = ++a->ph->cy;
13853: rlp->len = a->wid;
13854: if(a->ph->bx.a.x!=0) {
13855: /* must shift run indices */
13856: rl.y = rlp->y;
13857: rl.len = rlp->len;
13858: if((rl.runs=rlp->runs)>0) {
13859: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
13860: np->xs = rp->xs + a->ph->bx.a.x;
13861: np->xe = rp->xe + a->ph->bx.a.x;
13862: };
13863: };
13864: if(_O.dbg_r) nerr_RLE_Line("g31_source: ",&rl);
13865: return(&rl);
13866: }
13867: else { if(_O.dbg_r) nerr_RLE_Line("g31_source: ",rlp);
13868: return(rlp);
13869: };
13870: }
13871: else { if(_O.dbg_r) nerr_RLE_Line("g31_source: ",NULL);
13872: return(NULL);
13873: };
13874: }
13875:
13876: /* Read next line of runs from g32 file, with runs shifted to lie in the range
13877: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
13878: RLE_Line *g32_source(a)
13879: Copy_arg *a;
13880: { static RLE_Line *rlp,rl;
13881: RLE_Run *rp,*ep,*np;
13882: if((rlp=g32_to_rlel(a->tbl,a->bf,a->bop))!=NULL) {
13883: a->bop = F;
13884: rlp->y = ++a->ph->cy;
13885: rlp->len = a->wid;
13886: if(a->ph->bx.a.x!=0) {
13887: /* must shift run indices */
13888: if(_O.dbg_r) err("g32_source: shift +%d",a->ph->bx.a.x);
13889: rl.y = rlp->y;
13890: rl.len = rlp->len;
13891: if((rl.runs=rlp->runs)>0) {
13892: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
13893: np->xs = rp->xs + a->ph->bx.a.x;
13894: np->xe = rp->xe + a->ph->bx.a.x;
13895: };
13896: };
13897: if(_O.dbg_r) nerr_RLE_Line("g32_source: ",&rl);
13898: return(&rl);
13899: }
13900: else { if(_O.dbg_r) nerr_RLE_Line("g32_source: ",rlp);
13901: return(rlp);
13902: };
13903: }
13904: else { if(_O.dbg_r) nerr_RLE_Line("g32_source: ",NULL);
13905: return(NULL);
13906: };
13907: }
13908:
13909: /* Read next line of runs from g4 file, after shifting runs to lie in the range
13910: [ a->ph->bx.a.x, a->ph->bx.b.x ]. */
13911: RLE_Line *g4_source(a)
13912: Copy_arg *a;
13913: { static RLE_Line *rlp,rl;
13914: RLE_Run *rp,*ep,*np;
13915: if((rlp=g4_to_rlel(a->tbl,a->bf,a->bop,a->wid))!=NULL) {
13916: a->bop = F;
13917: rlp->y = ++a->ph->cy;
13918: rlp->len = a->wid;
13919: if(a->ph->bx.a.x!=0) { /* shift runs */
13920: rl.y = rlp->y;
13921: rl.len = rlp->len;
13922: if((rl.runs=rlp->runs)>0) {
13923: for(ep=(rp=rlp->r)+rlp->runs,np=rl.r; rp<ep; rp++,np++ ) {
13924: np->xs = rp->xs + a->ph->bx.a.x;
13925: np->xe = rp->xe + a->ph->bx.a.x;
13926: };
13927: };
13928: if(_O.dbg_r) nerr_RLE_Line("g4_source: ",&rl);
13929: return(&rl);
13930: }
13931: else { if(_O.dbg_r) nerr_RLE_Line("g4_source: ",rlp);
13932: return(rlp);
13933: };
13934: }
13935: else { a->bop = F;
13936: if(_O.dbg_r) nerr_RLE_Line("g4_source: ",NULL);
13937: return(NULL);
13938: };
13939: }
13940:
13941: binary_sink(rl,a)
13942: RLE_Line *rl;
13943: Copy_arg *a;
13944: { int stat;
13945: if(_O.dbg_r) nerr_RLE_Line("binary_sink: ",rl);
13946: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
13947: if(rl!=NULL) {
13948: memset(a->ph->line,'\0',a->ph->bpl);
13949: if(rl->runs>0) {
13950: /* convert *rl to binary, using ``little-endian'' bit-order */
13951: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
13952: };
13953: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
13954: abort("binary_sink: can't write: stat %d",stat);
13955: };
13956: return(1);
13957: }
13958:
13959: bitmap_sink(rl,a)
13960: RLE_Line *rl;
13961: Copy_arg *a;
13962: { int stat;
13963: if(_O.dbg_r) nerr_RLE_Line("bitmap_sink: ",rl);
13964: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
13965: if(rl!=NULL) {
13966: memset(a->ph->line,'\0',a->ph->bpl);
13967: if(rl->runs>0) {
13968: /* convert *rl to binary, using ``big-endian'' bit-order */
13969: brrlb(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
13970: };
13971: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
13972: abort("bitmap_sink: can't write: stat %d",stat);
13973: };
13974: return(1);
13975: }
13976:
13977: /* Write bitfile(9.5) format */
13978: bitfile_sink(rl,a)
13979: RLE_Line *rl;
13980: Copy_arg *a;
13981: #define dbg_Bo (F)
13982: { int stat;
13983: int ci,towrite;
13984: register unsigned char uc,*cp,*pp,*ep;
13985: if(_O.dbg_r||dbg_Bo) nerr_RLE_Line("bitfile_sink: ",rl);
13986: if(a->bop) { PIC_put_hdr(a->ph); a->bop=F; }
13987: if(rl!=NULL) {
13988: /* copy current to prior */
13989: memcpy(a->ph->pline,a->ph->line,a->ph->bpl);
13990: memset(a->ph->line,'\0',a->ph->bpl);
13991: if(rl->runs>0) {
13992: /* convert *rl to binary, using ``big-endian'' bit-order */
13993: brrlb(rl->runs,rl->r,
13994: a->ph->bx.a.x,a->ph->bx.b.x,
13995: 0,a->ph->line);
13996: if(dbg_Bo) {
13997: unsigned char *cb,*eb;
13998: fprintf(stderr,"a->ph->line: ");
13999: for(eb=(cb=a->ph->line)+a->ph->bpl;cb<eb;cb++)
14000: fprintf(stderr,"%02X",*cb);
14001: fprintf(stderr,"\n");
14002: };
14003: };
14004: /* break up output into blocks of 2*126 bytes;
14005: SHOULD also try run-length coding */
14006: ci=0; while((towrite=a->ph->bpl-ci) > 0) {
14007: if(towrite >= 2*127) towrite=2*126;
14008: /* write control byte for block */
14009: uc = towrite/2;
14010: if(dbg_Bo) err("cb: %02X",uc);
14011: putc(uc,a->ph->fp);
14012: for(ep=(cp=a->ph->line+ci)+towrite,pp=a->ph->pline+ci;
14013: cp<ep; cp++,pp++) {
14014: /* write XOR byte */
14015: uc = *cp ^ *pp;
14016: if(dbg_Bo) err("db %d: %02X = c%02X ^ p%02X",cp-a->ph->line,uc,*cp,*pp);
14017: putc(uc,a->ph->fp);
14018: };
14019: ci += towrite;
14020: };
14021: }
14022: else { free(a->ph->line); a->ph->line=NULL;
14023: free(a->ph->pline); a->ph->pline=NULL;
14024: fflush(a->ph->fp);
14025: };
14026: }
14027:
14028: rle_sink(rl,a)
14029: RLE_Line *rl;
14030: Copy_arg *a;
14031: { if(_O.dbg_r) nerr_RLE_Line("rle_sink: ",rl);
14032: if(a->bop) {
14033: RIC_hdr rh;
14034: rh.bx = a->ph->bx;
14035: rh.res_x = a->ph->res_x;
14036: rh.res_y = a->ph->res_y;
14037: RLE_put_hdr(fileno(a->ph->fp),&rh,1);
14038: a->ph->cy = a->ph->bx.a.y-1;
14039: a->bop=F;
14040: };
14041: if(rl!=NULL) {
14042: if(rl->runs>0) RLE_put_Line(fileno(a->ph->fp),rl);
14043: a->ph->cy++;
14044: }
14045: else RLE_close(fileno(a->ph->fp));
14046: return(1);
14047: }
14048:
14049: /* Write next line of runs to g31 file, after shifting runs to lie in the range
14050: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
14051: g31_sink(rl,a)
14052: RLE_Line *rl;
14053: Copy_arg *a;
14054: { int stat;
14055: RLE_Line crl;
14056: RLE_Run *rp,*ep,*np;
14057: if(_O.dbg_r) nerr_RLE_Line("g31_sink: ",rl);
14058: if(a->bop) {
14059: PIC_put_hdr(a->ph);
14060: /* treat FILE *a->ph->fp as a sequence of bits */
14061: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
14062: abort("g31_sink: can't open bitfile");
14063: BOF_to_g31(a->bf);
14064: a->bop=F;
14065: };
14066: if(rl!=NULL) {
14067: /* check that rl->len is consistent with a->ph */
14068: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
14069: err("g31_sink: rl->len %d != wid(a->ph.bx) %d",
14070: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
14071: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
14072: };
14073: if(rl->runs>0) {
14074: if(a->ph->bx.a.x!=0) { /* shift runs */
14075: crl.y = rl->y;
14076: crl.len = rl->len;
14077: crl.runs = rl->runs;
14078: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
14079: rp<ep;
14080: rp++,np++) {
14081: np->xs = rp->xs - a->ph->bx.a.x;
14082: np->xe = rp->xe - a->ph->bx.a.x;
14083: };
14084: rlel_to_g31(&crl,crl.len,a->bf);
14085: }
14086: else rlel_to_g31(rl,rl->len,a->bf);
14087: }
14088: else rlel_to_g31(NULL,rl->len,a->bf);
14089: a->ph->cy++;
14090: }
14091: else { EOF_to_g31(a->bf);
14092: bclose(a->bf);
14093: };
14094: return(1);
14095: }
14096:
14097: /* Write next line of runs to g32 file, after shifting runs to lie in the range
14098: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
14099: g32_sink(rl,a)
14100: RLE_Line *rl;
14101: Copy_arg *a;
14102: { static RLE_Line prl;
14103: RLE_Line *pl;
14104: RLE_Line crl;
14105: RLE_Run *rp,*ep,*np;
14106: if(_O.dbg_r) nerr_RLE_Line("g32_sink: ",rl);
14107: if(a->bop) {
14108: PIC_put_hdr(a->ph);
14109: /* treat FILE *a->ph->fp as a sequence of bits */
14110: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
14111: abort("can't open bitfile");
14112: BOF_to_g32(a->bf);
14113: a->bop=F;
14114: prl.runs = 0;
14115: };
14116: if(rl!=NULL) {
14117: /* check that rl->len is consistent with a->ph */
14118: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
14119: err("g32_sink: rl->len %d != wid(a->ph.bx) %d",
14120: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
14121: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
14122: };
14123: prl.len = rl->len;
14124: prl.y = rl->y - 1;
14125: if(((a->ph->cy+1-a->ph->bx.a.y)%a->k)==0) pl=NULL; else pl=&prl;
14126: if(rl->runs>0) {
14127: if(a->ph->bx.a.x!=0) { /* shift runs */
14128: crl.y = rl->y;
14129: crl.len = rl->len;
14130: crl.runs = rl->runs;
14131: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
14132: rp<ep;
14133: rp++,np++) {
14134: np->xs = rp->xs - a->ph->bx.a.x;
14135: np->xe = rp->xe - a->ph->bx.a.x;
14136: };
14137: rlel_to_g32(pl,&crl,crl.len,a->bf);
14138: prl.y=crl.y;
14139: prl.len=crl.len;
14140: prl.runs=crl.runs;
14141: memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
14142: }
14143: else { rlel_to_g32(pl,rl,rl->len,a->bf);
14144: prl.y=rl->y;
14145: prl.len=rl->len;
14146: prl.runs=rl->runs;
14147: memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
14148: };
14149: }
14150: else { rlel_to_g32(pl,NULL,rl->len,a->bf);
14151: prl.y=rl->y;
14152: prl.len=rl->len;
14153: prl.runs=0;
14154: }
14155: a->ph->cy++;
14156: }
14157: else { EOF_to_g32(a->bf);
14158: bclose(a->bf);
14159: prl.runs = 0;
14160: };
14161: return(1);
14162: }
14163:
14164: /* Write next line of runs to g4 file, after shifting runs to lie in the range
14165: [ 0, a->ph->bx.b.x - a->ph->bx.a.x ]. */
14166: g4_sink(rl,a)
14167: RLE_Line *rl;
14168: Copy_arg *a;
14169: { static RLE_Line prl;
14170: RLE_Line crl;
14171: RLE_Run *rp,*ep,*np;
14172: if(_O.dbg_r) nerr_RLE_Line("g4_sink: ",rl);
14173: if(a->bop) {
14174: PIC_put_hdr(a->ph);
14175: /* treat FILE *a->ph->fp as a sequence of bits */
14176: if((a->bf=bopen(a->ph->fp,"w"))==NULL)
14177: abort("can't open bitfile");
14178: BOF_to_g4(a->bf);
14179: a->bop=F;
14180: prl.runs = 0;
14181: };
14182: if(rl!=NULL) {
14183: /* check that rl->len is consistent with a->ph */
14184: if(rl->len != a->ph->bx.b.x - a->ph->bx.a.x + 1) {
14185: err("g4_sink: rl->len %d != wid(a->ph.bx) %d",
14186: rl->len, a->ph->bx.b.x - a->ph->bx.a.x + 1);
14187: rl->len = a->ph->bx.b.x - a->ph->bx.a.x + 1;
14188: };
14189: if(rl->runs>0) {
14190: if(a->ph->bx.a.x!=0) { /* shift runs */
14191: crl.y = rl->y;
14192: crl.len = rl->len;
14193: crl.runs = rl->runs;
14194: for(ep=(rp=rl->r)+rl->runs,np=crl.r;
14195: rp<ep;
14196: rp++,np++) {
14197: np->xs = rp->xs - a->ph->bx.a.x;
14198: np->xe = rp->xe - a->ph->bx.a.x;
14199: };
14200: rlel_to_g4(&prl,&crl,crl.len,a->bf);
14201: prl.y=crl.y;
14202: prl.len=crl.len;
14203: prl.runs=crl.runs;
14204: memcpy(prl.r,crl.r,2*prl.runs*sizeof(short));
14205: }
14206: else { rlel_to_g4(&prl,rl,rl->len,a->bf);
14207: prl.y=rl->y;
14208: prl.len=rl->len;
14209: prl.runs=rl->runs;
14210: memcpy(prl.r,rl->r,2*prl.runs*sizeof(short));
14211: };
14212: }
14213: else { rlel_to_g4(&prl,NULL,rl->len,a->bf);
14214: prl.runs=0;
14215: }
14216: a->ph->cy++;
14217: }
14218: else { EOF_to_g4(a->bf);
14219: bclose(a->bf);
14220: prl.runs = 0;
14221: };
14222: return(1);
14223: }
14224:
14225: pic_sink(rl,a)
14226: RLE_Line *rl;
14227: Copy_arg *a;
14228: { int stat;
14229: if(_O.dbg_r) nerr_RLE_Line("pic_sink: ",rl);
14230: if(a->bop) {
14231: PIC_put_hdr(a->ph);
14232: a->bop=F;
14233: };
14234: if(rl!=NULL) {
14235: crrl(rl->runs,rl->r,0,a->ph->bx.b.x-a->ph->bx.a.x,a->ph->line);
14236: if((stat=PIC_wline(a->ph,a->ph->line))!=1)
14237: abort("pic_sink: can't write: stat %d",stat);
14238: };
14239: return(1);
14240: }
14241:
14242: #if CPU==SUN
14243: post_sink(rl,a)
14244: RLE_Line *rl;
14245: Copy_arg *a;
14246: { int stat;
14247: if(_O.dbg_r) nerr_RLE_Line("post_sink: ",rl);
14248: if (a->bop) {
14249: PIC_put_hdr(a->ph); /* needed for allocation of h->line? */
14250: POST_start(a->ph);
14251: a->bop = F;
14252: };
14253: if(rl!=NULL) {
14254: memset(a->ph->line,'\0',a->ph->bpl);
14255: if(rl->runs>0) {
14256: /* convert *rl to binary, using ``little-endian'' bit-order */
14257: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
14258: };
14259: if((stat=POST_wline(a->ph,a->ph->line))!=1)
14260: abort("post_sink: can't write: stat %d",stat);
14261: }
14262: else { POST_end();
14263: };
14264: return(1);
14265: }
14266: #else
14267: post_sink() {abort("-P postscript output unimplemented");};
14268: #endif
14269:
14270: #if CPU==SUN
14271: rast_sink(rl,a)
14272: RLE_Line *rl;
14273: Copy_arg *a;
14274: { int stat;
14275: if(_O.dbg_r) nerr_RLE_Line("rast_sink: ",rl);
14276: if (a->bop) {
14277: PIC_put_hdr(a->ph); /* needed for allocation of h->line? */
14278: RAST_start(a->ph);
14279: a->bop = F;
14280: };
14281: if(rl!=NULL) {
14282: memset(a->ph->line,'\0',a->ph->bpl);
14283: if(rl->runs>0) {
14284: /* convert *rl to binary, using ``little-endian'' bit-order */
14285: brrl(rl->runs,rl->r,a->ph->bx.a.x,a->ph->bx.b.x,0,a->ph->line);
14286: };
14287: if((stat=RAST_wline(a->ph,a->ph->line))!=1)
14288: abort("rast_sink: can't write: stat %d",stat);
14289: }
14290: else { RAST_end();
14291: };
14292: return(1);
14293: }
14294: #else
14295: rast_sink() {abort("-S sunraster output unimplemented");};
14296: #endif
14297:
14298: /* Save RLE_Line *rl in buffer, as packed binary, using ``little-endian''
14299: bit-packing order, rounding each line to the nearest int for speed.
14300: If a->bop, malloc a complete, contiguous buffer holding the entire page,
14301: and initialize its contents to zeroes.
14302: On each call with rl!=NULL, convert the given line to binary & save in buffer.
14303: When called with rl==NULL but a!=NULL, signalling end-of-page, do nothing.
14304: Normally, return kludgey (unsigned int *)1, like other sink functions.
14305: When called with rl==NULL && a==NULL, return pointer to buffer.
14306: It is the responsibility of the calling code to free the buffer. */
14307: unsigned int *binary_buffer(rl,a)
14308: RLE_Line *rl;
14309: Copy_arg *a;
14310: { static unsigned int *buf = NULL;
14311: static int ipl = 0; /* ints/line */
14312: int bufsz; /* (bytes) */
14313: unsigned int *result;
14314: #define BITS_PER_INT (8*sizeof(int))
14315: if(a!=NULL && a->bop) {
14316: /* round up to int boundary */
14317: ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
14318: bufsz = sizeof(int)*ipl*bbx_hgt(&(a->ph->bx));
14319: if((buf=(unsigned int *)malloc(bufsz))==NULL)
14320: abort("binary_buffer: can't alloc int buf[%d]",bufsz/sizeof(int));
14321: memset(buf,'\0',bufsz);
14322: a->bop=F;
14323: };
14324: if(rl!=NULL) {
14325: /* convert *rl to binary, using ``little-endian'' bit-order */
14326: if(rl->runs>0) {
14327: /* *rl --> binary, with ``little-endian'' bit-order */
14328: #if BIG_ENDIAN
14329: brrlb( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
14330: 0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
14331: #else
14332: brrl( rl->runs, rl->r, a->ph->bx.a.x, a->ph->bx.b.x,
14333: 0, buf+(ipl*(rl->y-a->ph->bx.a.y)) );
14334: #endif
14335: };
14336: return((unsigned int *)1);
14337: }
14338: else { if(a!=NULL) return((unsigned int *)1);
14339: else { result = buf;
14340: buf = NULL; ipl = 0;
14341: return(result);
14342: };
14343: };
14344: }
14345:
14346: /* Rotate binary buffer *buf (whose shape is specified by a->ph->bx),
14347: through angle tra->rot, and write the resulting stream of RLE_Line's to
14348: sink() one at a time, along with a rotated version of *a as the 2nd argument.
14349: Only PI/2 is supported; UNDER DEVELOPMENT: other multiples of PI/2 and
14350: small arbitrary angles. */
14351: rotate_binary_buffer(buf,tra,sink,a)
14352: unsigned int *buf;
14353: Transform_rlel_arg *tra;
14354: int (*sink)(); /* takes args: (RLE_Line *), and int */
14355: Copy_arg *a;
14356: { register int ipl; /* ints/line in binary buffer */
14357: Copy_arg ra; /* rotated */
14358: RLE_Line rl;
14359: #define TINY_ANG (PI/1000)
14360: /* round up to int boundary */
14361: ipl = (bbx_wid(&(a->ph->bx))+BITS_PER_INT-1)/BITS_PER_INT;
14362: ra = *a;
14363: ra.bop=T;
14364: if((ra.ph = (PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
14365: abort("rotate_binary_buffer: can't malloc ra.ph");
14366: *(ra.ph) = *(a->ph);
14367: /* by arbitrary convention, rotated bx.a will coincide with input bx.a */
14368: if(tra->rot <= PI/2+TINY_ANG && tra->rot >= PI/2-TINY_ANG) {
14369: int ey,ii;
14370: register RLE_Run *rp;
14371: register unsigned int *cb,*eb,bm,obm;
14372: register short rx;
14373: ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
14374: ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
14375: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
14376: rl.y = ra.ph->bx.a.y; ey=ra.ph->bx.b.y;
14377: ii=0; bm=01;
14378: do { obm=0; /* assume 0 left of margin */
14379: rp=rl.r-1;
14380: rx=ra.ph->bx.a.x;
14381: cb=(eb=buf+ii)+((rl.len-1)*ipl);
14382: do { if((*cb & bm)!=obm) {
14383: if(obm) { rp->xe=rx-1; obm=0; }
14384: else { (++rp)->xs=rx; obm=bm; };
14385: };
14386: rx++;
14387: }
14388: while( (cb -= ipl) >= eb );
14389: if(obm) rp->xe=rx-1;
14390: rl.runs = rp - rl.r + 1;
14391: sink(&rl,&ra);
14392: if((bm<<=1)==0) {ii++; bm=01;};
14393: }
14394: while((++rl.y)<=ey);
14395: }
14396: else if(tra->rot <= PI+TINY_ANG && tra->rot >= PI-TINY_ANG) {
14397: rl.len = ra.wid;
14398: abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
14399: tra->rot/DtoR);
14400: }
14401: else if(tra->rot <= 3*PI/2+TINY_ANG && tra->rot >= 3*PI/2-TINY_ANG) {
14402: ra.ph->bx.b.x = a->ph->bx.a.x + bbx_hgt(&(a->ph->bx)) - 1;
14403: ra.ph->bx.b.y = a->ph->bx.a.y + bbx_wid(&(a->ph->bx)) - 1;
14404: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
14405: abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
14406: tra->rot/DtoR);
14407: }
14408: else if(tra->rot <= 20.0*DtoR && tra->rot >= -20.0*DtoR) {
14409: /* rotation by ``small'' angle */
14410: Sp ce; /* center of image to be rotated */
14411: double rcos,rsin; /* real rotation vector (cos,sin) */
14412: double irx,iry; /* current rotated pixel location */
14413: register int sx,sy,ex,ey,rx,ry;
14414: register RLE_Run *rp;
14415: register int pel,opel;
14416: register int orx,ory;
14417: if(0) err("rotate_binary_buffer: tra->rot==%g deg under development",
14418: tra->rot/DtoR);
14419: /* conventionally, keep the same window as the input image,
14420: while rotating about its midpoint */
14421: rl.len = ra.wid = bbx_wid(&(ra.ph->bx));
14422: sx = ra.ph->bx.a.x; ex = ra.ph->bx.b.x;
14423: sy = ra.ph->bx.a.y; ey = ra.ph->bx.b.y;
14424: ce.x = sx + bbx_wid(&(ra.ph->bx))/2;
14425: ce.y = sy + bbx_hgt(&(ra.ph->bx))/2;
14426: rcos = cos(tra->rot); rsin = sin(tra->rot);
14427: for(ory=sy; ory<=ey; ory++) {
14428: opel=0; /* left of output margin: assume pel==0 */
14429: rp=rl.r-1;
14430: irx = ((rcos*(sx - ce.x) - rsin*(ory - ce.y))) + ce.x;
14431: iry = ((rsin*(sx - ce.x) + rcos*(ory - ce.y))) + ce.y;
14432: for(orx=sx; orx<=ex; orx++) {
14433: rx = (int)(irx + 0.5); ry = (int)(iry + 0.5);
14434: if(rx<sx || rx>ex || ry<sy || ry>ey)
14435: /* outside input image: assume pel==0 */
14436: pel=0;
14437: else /* look at bit within input image */ {
14438: int ix,iy,bx;
14439: iy = (ry-sy)*ipl;
14440: ix = rx/BITS_PER_INT;
14441: bx = rx%BITS_PER_INT;
14442: #if BIG_ENDIAN
14443: pel = (buf[ iy + ix ] & (01<<(BITS_PER_INT-bx-1))) ? 1 : 0;
14444: #else
14445: pel = (buf[ iy + ix ] & (01<<bx)) ? 1 : 0;
14446: #endif
14447: };
14448: if(pel!=opel) {
14449: if(opel) { rp->xe=orx-1; opel=0; }
14450: else { (++rp)->xs=orx; opel=pel; };
14451: };
14452: /* step one pel to the right in output image */
14453: irx += rcos; iry += rsin;
14454: };
14455: if(opel) rp->xe=orx-1;
14456: rl.runs = rp - rl.r + 1;
14457: rl.y = ory;
14458: sink(&rl,&ra);
14459: };
14460: }
14461: else { abort("rotate_binary_buffer: tra->rot==%g deg unimplemented",
14462: tra->rot/DtoR);
14463: };
14464: sink(NULL,&ra); /* signal end-of-page */
14465: }
14466:
14467: /* Copy a source of RLE_Lines to a sink of RLE_Lines, transforming them
14468: by trimming, shifting, scaling, truncation, and rotation.
14469: The source is function ir(), which returns non-empty lines only,
14470: or NULL on end of page. It is passed `bop=T' on beginning of page.
14471: On return from ir(), ia->ph->cy holds the index of the line, whose height is
14472: guaranteed to lie in the range [ia->ph->bx.a.y,ia->ph->bx.b.y].
14473: All input runs are guaranteed to lie in [ia->ph->bx.a.x,ia->ph->bx.b.x].
14474: The maximum length (in pels) of each source line is ia->wid.
14475: The sink function or() takes two arguments:
14476: RLE_Line *rl; ==NULL on end-of-page
14477: Copy_arg *a;
14478: The lines sent to the sink must be in unbroken ascending integer
14479: sequence of rl->y (thus blank lines must be explicitly sent). At all times,
14480: oa->ph->cy is the line last written. After the first call to or(),
14481: oa->ph->cy lies in the range [oa->ph->bx.a.y,oa->ph->bx.b.y].
14482: Trimming, shifting, scaling, and truncation are performed either
14483: here or in function transform_rlel(). Rotation is handled specially:
14484: the complete output image (after all other transformations have been
14485: performed) is saved in an intermediate buffer (as packed binary), then
14486: rotated. Rotation is much slower than the other operations, mainly due
14487: to the necessity of touching every pixel. (Manhattan rotations might be
14488: faster if the buffer held RLE_lines, but then it would be next-to-impossible
14489: to extend to arbitrary rotations someday.)
14490: */
14491: transform_rlels(ir,ia,or,oa,tra)
14492: RLE_Line *(*ir)(); /* return next RLE_Line */
14493: Copy_arg *ia; /* used here (bop & wid) & passed to ir() */
14494: int (*or)(); /* write next RLE_Line */
14495: Copy_arg *oa; /* used here (bop && ph->bx.*.y) & passed to or() */
14496: Transform_rlel_arg *tra;
14497: { RLE_Line *irl,*orl;
14498: static RLE_Line rl0 = Init_RLE_Line; /* empty line */
14499: int tr_y; /* transformed y */
14500: int (*sv_or)();
14501: if(tra->rot!=0.0) {
14502: /* if must rotate the image, first buffer the entire
14503: set of output RLE_Lines */
14504: sv_or = or;
14505: or = (int (*)())binary_buffer;
14506: };
14507: /* signal beginning of page; reset in source() & sink() functions */
14508: ia->bop=oa->bop=T;
14509: /* set first output line number to write */
14510: tra->dy = (tra->sy = oa->ph->bx.a.y);
14511: while((irl=ir(ia))!=NULL) {
14512: if(F&&_O.dbg_r) nerr_RLE_Line("trans.i: ",irl);
14513: /* trim input lines' Y */
14514: if(irl->y < tra->tr.a.y) continue;
14515: if(irl->y > tra->tr.b.y) break;
14516: /* compute the output Y that is equal to the last
14517: of the group of transformed equivalent Y's */
14518: tr_y = (int)((irl->y + tra->off.y + 1)*tra->scl.y) - 1;
14519: /* truncate if necessary */
14520: if(tr_y>oa->ph->bx.b.y) tr_y = oa->ph->bx.b.y;
14521: /* supply implicit blank line(s) of the same length */
14522: while(tra->sy < tr_y) {
14523: rl0.len = ia->wid;
14524: transform_rlel(&rl0,tra,or,oa);
14525: };
14526: irl->len = ia->wid;
14527: transform_rlel(irl,tra,or,oa);
14528: };
14529: /* supply terminating blank line(s) of the same length */
14530: while(tra->sy < oa->ph->bx.b.y) {
14531: rl0.len = ia->wid;
14532: transform_rlel(&rl0,tra,or,oa);
14533: };
14534: transform_rlel(NULL,tra,or,oa); /* signal end of page */
14535: /* read input until end of page occurs; this is required
14536: to support catenated pages */
14537: while(irl!=NULL) irl=ir(ia);
14538: if(tra->rot!=0.0) {
14539: unsigned int *buf;
14540: buf = binary_buffer(NULL,NULL);
14541: if(buf!=NULL) {
14542: rotate_binary_buffer(buf,tra,sv_or,oa);
14543: free(buf);
14544: };
14545: };
14546: }
14547:
14548: process_page(i,o)
14549: Copy_arg *i,*o;
14550: { RLE_Line *(*source)();
14551: int (*sink)();
14552: char unit,*up,cpy[40]; /* units character */
14553: Transform_rlel_arg tra;
14554:
14555: i->wid = bbx_wid(&(i->ph->bx));
14556:
14557: _O.trim = max_Bbx; /* start by trimming nothing */
14558: /* translate units in option arguments */
14559: if(_O.optarg_l!=NULL) {
14560: strcpy(cpy,_O.optarg_l);
14561: if((up=strpbrk(cpy,UNITS))!=NULL) {
14562: unit= *up; *up='\0';
14563: _O.trim.a.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
14564: }
14565: else /* assume scanner coordinates */
14566: _O.trim.a.x=atoi(cpy);
14567: };
14568: if(_O.optarg_r!=NULL) {
14569: strcpy(cpy,_O.optarg_r);
14570: if((up=strpbrk(cpy,UNITS))!=NULL) {
14571: unit= *up; *up='\0';
14572: _O.trim.b.x=vto_scoor(atof(cpy),unit,i->ph->res_x);
14573: }
14574: else /* assume scanner coordinates */
14575: _O.trim.b.x=atoi(cpy);
14576: _O.trim.b.x--; /* -w coordinate is open, Bbx is closed */
14577: };
14578: if(_O.optarg_t!=NULL) {
14579: strcpy(cpy,_O.optarg_t);
14580: if((up=strpbrk(cpy,UNITS))!=NULL) {
14581: unit= *up; *up='\0';
14582: _O.trim.a.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
14583: }
14584: else /* assume scanner coordinates */
14585: _O.trim.a.y=atoi(cpy);
14586: };
14587: if(_O.optarg_b!=NULL) {
14588: strcpy(cpy,_O.optarg_b);
14589: if((up=strpbrk(cpy,UNITS))!=NULL) {
14590: unit= *up; *up='\0';
14591: _O.trim.b.y=vto_scoor(atof(cpy),unit,i->ph->res_y);
14592: }
14593: else /* assume scanner coordinates */
14594: _O.trim.b.y=atoi(cpy);
14595: _O.trim.b.y--; /* -w coordinate is open, Bbx is closed */
14596: };
14597: /* Modified output margins may lie OUTSIDE the input window as well
14598: as within it. */
14599: if(_O.trim.a.x==Scoor_MIN) _O.trim.a.x=i->ph->bx.a.x;
14600: if(_O.trim.b.x==Scoor_MAX) _O.trim.b.x=i->ph->bx.b.x;
14601: if(_O.trim.a.y==Scoor_MIN) _O.trim.a.y=i->ph->bx.a.y;
14602: if(_O.trim.b.y==Scoor_MAX) _O.trim.b.y=i->ph->bx.b.y;
14603: if(_O.dbg_m) err("trim: %s",bbx_toa(&(_O.trim)));
14604:
14605: if(strcmp(i->ph->type,"binary")==0) { source = binary_source; }
14606: else if(strcmp(i->ph->type,"bitmap")==0) { source = bitmap_source; }
14607: else if(strcmp(i->ph->type,"bitfile")==0) { source = bitfile_source; }
14608: else if(strcmp(i->ph->type,"document-image")==0) { source = dim_source; }
14609: else if(strcmp(i->ph->type,"dim")==0) { source = dim_source; }
14610: else if(strcmp(i->ph->type,"rle")==0) {
14611: RIC_hdr rh;
14612: /* reopen RLE file to use system I/O (awkward, obsolescent) */
14613: lseek(fileno(i->ph->fp),0L,0);
14614: RLE_open(fileno(i->ph->fp),&rh);
14615: i->ph->cy = i->ph->bx.a.y-1;
14616: source = rle_source;
14617: }
14618: else if(strcmp(i->ph->type,"pico")==0
14619: ||strcmp(i->ph->type,"dump")==0) {
14620: i->thresh = _O.thresh;
14621: source = pic_source;
14622: }
14623: else if(strcmp(i->ph->type,"ccitt-g31")==0) {
14624: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
14625: abort("can't open bitfile");
14626: i->tbl = ccitt_table();
14627: source = g31_source;
14628: }
14629: else if(strcmp(i->ph->type,"ccitt-g32")==0) {
14630: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
14631: abort("can't open bitfile");
14632: i->tbl = ccitt_table();
14633: source = g32_source;
14634: }
14635: else if(strcmp(i->ph->type,"ccitt-g4")==0) {
14636: if((i->bf=bopen(i->ph->fp,"r"))==NULL)
14637: abort("can't open bitfile");
14638: i->tbl = ccitt_table();
14639: source = g4_source;
14640: }
14641: else if(strcmp(i->ph->type,"cdf-mrlc")==0) { source = cdf_mrlc_source; }
14642: else abort("Input file TYPE=%s unsupported",i->ph->type);
14643:
14644: if(_O.dbg_h) err("In %s",PIC_hdr_toa(i->ph));
14645:
14646: /* Adjudicate -R and -x options */
14647: if(_O.out_res.x==-2) {
14648: /* -R= specified: force resolutions to be equal to the greater */
14649: if(i->ph->res_x < i->ph->res_y) {
14650: _O.out_res.x = _O.out_res.y = i->ph->res_y;
14651: }
14652: else if(i->ph->res_y < i->ph->res_x) {
14653: _O.out_res.x = _O.out_res.y = i->ph->res_x;
14654: }
14655: else _O.out_res.x = _O.out_res.y = i->ph->res_x;
14656: };
14657: if(_O.out_res.x!=-1) { /* -Rx specified; override -xX */
14658: _O.expand.x = ((double)_O.out_res.x)/i->ph->res_x;
14659: if(_O.dbg_R && _O.expand.x!=1.0)
14660: err("horizontal resolution changed: x%g (%d -> %d)",
14661: _O.expand.x,i->ph->res_x,_O.out_res.x);
14662: };
14663: if(_O.out_res.y!=-1) { /* -R,y specified; override -x,Y */
14664: _O.expand.y = ((double)_O.out_res.y)/i->ph->res_y;
14665: if(_O.dbg_R && _O.expand.y!=1.0)
14666: err("vertical resolution changed: x%g (%d -> %d)",
14667: _O.expand.y,i->ph->res_y,_O.out_res.y);
14668: };
14669:
14670: /* Setup image transformation parameters */
14671: tra = empty_Transform_rlel_arg;
14672: tra.tr = _O.trim;
14673: tra.off = _O.offset;
14674: tra.scl = _O.expand;
14675: tra.wh.x = bbx_wid(&(tra.tr));
14676: tra.wh.y = bbx_hgt(&(tra.tr));
14677: tra.rev = _O.reverse;
14678: if(tra.scl.x!=1.0) {
14679: tra.wh.x = (int)(tra.wh.x*tra.scl.x+0.5);
14680: };
14681: if(tra.scl.y!=1.0) {
14682: tra.wh.y = (int)(tra.wh.y*tra.scl.y+0.5);
14683: };
14684: switch(_O.top) {
14685: case 't': /* default */ break;
14686: case 'l': /* top is really at left */
14687: tra.rot = (Radians)(PI/2);
14688: break;
14689: case 'b': /* top is really at bottom */
14690: tra.rot = (Radians)(PI);
14691: break;
14692: case 'r': /* top is really at right */
14693: tra.rot = (Radians)((3*PI)/2);
14694: break;
14695: case 'a': /* rotation angle given */
14696: tra.rot = _O.top_angle;
14697: break;
14698: };
14699: /* is the transform the identity? (speed-optimized special case) */
14700: tra.ident = ( (bbx_eq(&(tra.tr),&(i->ph->bx)))
14701: && (tra.scl.x==1.0)
14702: && (tra.scl.y==1.0)
14703: && (tra.off.x==0)
14704: && (tra.off.y==0)
14705: && (tra.rot==0.0) );
14706:
14707: /* compute transformed output box & resolution;
14708: don't rotate here (see transform_rlels()) */
14709: if(tra.ident) {
14710: o->ph->bx = i->ph->bx;
14711: o->ph->res_x = i->ph->res_x;
14712: o->ph->res_y = i->ph->res_y;
14713: }
14714: else { o->ph->bx = tra.tr;
14715: o->ph->bx.a.x += tra.off.x;
14716: o->ph->bx.b.x += tra.off.x;
14717: o->ph->bx.a.y += tra.off.y;
14718: o->ph->bx.b.y += tra.off.y;
14719: if(tra.scl.x!=1.0) {
14720: o->ph->bx.a.x = tra.scl.x*o->ph->bx.a.x;
14721: o->ph->bx.b.x = o->ph->bx.a.x + tra.wh.x-1;
14722: };
14723: if(tra.scl.y!=1.0) {
14724: o->ph->bx.a.y = tra.scl.y*o->ph->bx.a.y;
14725: o->ph->bx.b.y = o->ph->bx.a.y + tra.wh.y-1;
14726: };
14727: o->ph->res_x = (i->ph->res_x*tra.scl.x + 0.5);
14728: o->ph->res_y = (i->ph->res_y*tra.scl.y + 0.5);
14729: };
14730:
14731: if(_O.to_bin)
14732: { strcpy(o->ph->type,"binary"); sink = binary_sink; }
14733: else if(_O.to_bitfile)
14734: { strcpy(o->ph->type,"bitfile"); sink = bitfile_sink; }
14735: else if(_O.to_bitmap)
14736: { strcpy(o->ph->type,"bitmap"); sink = bitmap_sink; }
14737: else if (_O.to_rle) {
14738: if(strcmp(i->ph->type,"rle")==0)
14739: abort("can't both read and write TYPE=rle - sorry");
14740: strcpy(o->ph->type,"rle"); sink = rle_sink;
14741: }
14742: else if(_O.to_g31) { strcpy(o->ph->type,"ccitt-g31"); sink = g31_sink; }
14743: else if(_O.to_g32) {
14744: strcpy(o->ph->type,"ccitt-g32");
14745: o->k = _O.g32_k;
14746: sink = g32_sink;
14747: }
14748: else if(_O.to_g4) { strcpy(o->ph->type,"ccitt-g4"); sink = g4_sink; }
14749: else if(_O.to_pic) { strcpy(o->ph->type,"dump"); sink = pic_sink; }
14750: #if CPU==SUN
14751: else if(_O.to_post) { strcpy(o->ph->type,"postscript"); sink = post_sink; }
14752: #endif
14753: #if CPU==SUN
14754: else if(_O.to_rast) { strcpy(o->ph->type,"sunraster"); sink = rast_sink; }
14755: #endif
14756: if(i->ph->misc!=NULL) {
14757: o->ph->misc = i->ph->misc;
14758: i->ph->misc = NULL;
14759: };
14760: if(_O.dbg_h) err("Out %s",PIC_hdr_toa(o->ph));
14761:
14762: transform_rlels(source,i,sink,o,&tra);
14763:
14764: /* Synchronize filedes pointer with stream pointer */
14765: lseek(fileno(o->ph->fp),o->ph->seek = ftell(o->ph->fp),0);
14766: }
14767:
14768: /* A file may be a catenation of pages. */
14769: process_fps(i,o)
14770: FILE *i,*o;
14771: { Copy_arg ia,oa;
14772: int stat;
14773: ia = oa = empty_Copy_arg;
14774: ia.ph = alloc_PIC_hdr(i);
14775: oa.ph = alloc_PIC_hdr(o);
14776:
14777: stat=PIC_get_hdr(ia.ph);
14778: if(_O.dbg_h && stat!=1) err("PIC_get_hdr() returns status %d",stat);
14779:
14780: /* enforce bitfile(9) I/O restrictions */
14781: if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
14782: abort("-Bi requires input to be bitfile(9.5) format");
14783: if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
14784: /* TYPE= is missing, erroneously: refuse to recognize it */
14785: abort("TYPE=... header is missing");
14786: };
14787:
14788: if(strcmp(ia.ph->type,"document-image")==0
14789: || strcmp(ia.ph->type,"dim")==0) {
14790: Page pg;
14791: skip_doc(i);
14792: if(frdb_page_etc(i,&pg,IsALL)==1) {
14793: ia.ph->bx = pg.bx;
14794: ia.ph->res_x = pg.res_x;
14795: ia.ph->res_y = pg.res_y;
14796: ia.rles = *rle_lines_of_page(&pg);
14797: if(_O.shrinkwrap!=-1) {
14798: Sp trans;
14799: ia.ph->bx = *bbx_of_rle_lines(&ia.rles);
14800: ia.ph->bx.a.x -= _O.shrinkwrap;
14801: ia.ph->bx.a.y -= _O.shrinkwrap;
14802: ia.ph->bx.b.x += _O.shrinkwrap;
14803: ia.ph->bx.b.y += _O.shrinkwrap;
14804: if(bbx_area(&(ia.ph->bx))<=0)
14805: abort("-W%d shrinks to nothing",_O.shrinkwrap);
14806: trans.x = -ia.ph->bx.a.x; trans.y = -ia.ph->bx.a.y;
14807: translate_rle_lines(&ia.rles,trans);
14808: ia.ph->bx.b.x = bbx_wid(&ia.ph->bx)-1;
14809: ia.ph->bx.b.y = bbx_hgt(&ia.ph->bx)-1;
14810: ia.ph->bx.a.x = ia.ph->bx.a.y = 0;
14811: };
14812: free_page_etc(&pg,IsALL&(~IsPage));
14813: }
14814: else { free_page_etc(&pg,IsALL&(~IsPage));
14815: abort("can't read document-image file");
14816: };
14817: };
14818: if(_O.in_res.x!=SHRT_MIN&&_O.in_res.y!=SHRT_MIN) {
14819: /* force input RES to given values */
14820: if(ia.ph->res_x!=0 || ia.ph->res_y!=0) {
14821: err("input: RES=%d %d overridden by -Z%d,%d\n",
14822: ia.ph->res_x,ia.ph->res_y,_O.in_res.x,_O.in_res.y);
14823: };
14824: ia.ph->res_x = _O.in_res.x;
14825: ia.ph->res_y = _O.in_res.y;
14826: };
14827: if(ia.ph->res_x<=0 || ia.ph->res_y<=0)
14828: err("input: RES=%d %d may cause problems (set using -Zx,y)",
14829: ia.ph->res_x,ia.ph->res_y);
14830:
14831: while(strlen(ia.ph->type)>0 && stat==1 && !feof(i)
14832: && !ferror(i) && !ferror(o)) {
14833: process_page(&ia,&oa);
14834: if( strcmp(ia.ph->type,"cdf")==0
14835: || strcmp(ia.ph->type,"cdf-mrlc")==0 ) {
14836: stat=CDF_next_page(ia.ph);
14837: }
14838: else { if((stat=PIC_get_hdr(ia.ph))==1) {
14839: /* enforce bitfile(9) I/O restrictions */
14840: if(_O.from_bitfile && strcmp(ia.ph->type,"bitfile")!=0)
14841: abort("-Bi means input must be picfile");
14842: if(!_O.from_bitfile && strcmp(ia.ph->type,"bitfile")==0) {
14843: /* TYPE= is missing, erroneously: silently quit */
14844: if(_O.dbg_h) err("strange input before normal EOF - ignored");
14845: strcpy(ia.ph->type,"");
14846: };
14847: };
14848: };
14849: if(_O.dbg_h && stat!=1)
14850: err("PIC_get_hdr() returns status %d",stat);
14851: };
14852:
14853: /* EOF or error */
14854: free_PIC_hdr(ia.ph);
14855: free_PIC_hdr(oa.ph);
14856: }
14857:
14858: #if FILE_TREE
14859: /* Process filenames: if NULL, use stdin/stdout; if files, read them;
14860: if directories, create a parallel file tree and process the leaves
14861: pairwise. */
14862: process_fns(i,o)
14863: char *i; /* may be NULL; not yet fopened for read */
14864: char *o; /* may be NULL; not yet fopened for write */
14865: #define dbg_ft (F)
14866: { FILE *i_fp;
14867: FILE *o_fp;
14868: char *branch;
14869: if(dbg_ft) err("processs(\"%s\",\"%s\")",i,o);
14870: branch=path_toa(&path_process.path,1);
14871: if(dbg_ft&&branch[0]!='\0') err("%s",branch);
14872: if(i==NULL||i[0]=='\0') i_fp=stdin;
14873: else if( (i_fp=fopen(i,"r"))==NULL ) {
14874: err("can't open input file %s - skip it",i);
14875: return;
14876: };
14877: if(o==NULL||o[0]=='\0') o_fp=stdout;
14878: else if( (o_fp=fopen(o,"w"))==NULL ) {
14879: err("can't open output file %s - skip it",o);
14880: return;
14881: };
14882: process_fps(i_fp,o_fp);
14883: if(i_fp!=stdin) fclose(i_fp);
14884: if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
14885: };
14886: #else
14887: /* Process filenames: if NULL, use stdin/stdout; if files, open and process them.
14888: */
14889: process_fns(i_fn,o_fn)
14890: char *i_fn; /* may be NULL; not yet fopened for read */
14891: char *o_fn; /* may be NULL; not yet fopened for write */
14892: { FILE *i_fp;
14893: FILE *o_fp;
14894: if(i_fn==NULL||strlen(i_fn)==0) i_fp = stdin;
14895: else { if((i_fp=fopen(i_fn,"r"))==NULL)
14896: abort("can't open input file %s",i_fn);
14897: };
14898: if(o_fn==NULL||strlen(o_fn)==0) o_fp = stdout;
14899: else { if((o_fp=fopen(o_fn,"w"))==NULL)
14900: abort("can't open output file %s",o_fn);
14901: };
14902: process_fps(i_fp,o_fp);
14903: if(i_fp!=stdin) fclose(i_fp);
14904: if(o_fp!=stdout) fclose(o_fp); else fflush(o_fp);
14905: };
14906: #endif
14907:
14908: main(arc,arv)
14909: int arc; char **arv;
14910: { parse_args(arc,arv);
14911: #if FILE_TREE
14912: process_file_trees(process_fns,_O.in_fn,_O.out_fn);
14913: #else
14914: process_fns(_O.in_fn,_O.out_fn);
14915: #endif
14916: }
14917:
14918: nerr_RLE_Line(s,rl)
14919: char *s;
14920: RLE_Line *rl;
14921: { RLE_Run *r;
14922: int ri;
14923: if(rl==NULL) fprintf(stderr,"%15s RLEL NULL.\n",s);
14924: else { fprintf(stderr,"%15s RLEL y%d r%d l%d: ",s,rl->y,rl->runs,rl->len);
14925: for(ri=0,r=rl->r; ri<rl->runs; ri++,r++)
14926: fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
14927: fprintf(stderr,"\n");
14928: };
14929: }
14930: 0707070035351137201006640007620000050000010263350476773367100001000000030702bitio.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
14931: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
14932: /* The copyright notice does not imply actual or intended publication. */
14933: /* AUTHORS: */
14934: /* H. S. Baird - ATT-BL MH - first versions */
14935:
14936: /* bitio.h - view a stream file as a sequence of binary values, hiding the
14937: bit- and byte-packing format of the file. The format of input and output
14938: files may differ. Reading and writing are performed by macroes for speed;
14939: the price for this is that the file formats must be fixed at compile time.
14940:
14941: SYNOPSIS
14942: #include <stdio.h>
14943: #include "bitio.h"
14944:
14945: BITFILE *bopen(stream,type);
14946: FILE *stream;
14947: char *type;
14948:
14949: int getb(bitfile);
14950: BITFILE *bitfile;
14951:
14952: putb(bit,bitfile);
14953: int bit;
14954:
14955: padb(bitfile,bit,bdy,len);
14956: int bit,bdy,len;
14957:
14958: char *bbuffer(bitfile);
14959:
14960: unsigned long bsize(bitfile);
14961:
14962: unsigned long bflush(bitfile);
14963:
14964: unsigned long bclose(bitfile);
14965:
14966: COMPILER DEPENDENCIES
14967: The compiler's data types must include:
14968: unsigned char: 8 bits each
14969: unsigned short: 2 unsigned chars each
14970: unsigned int: 2 unsigned shorts each
14971: DESCRIPTION
14972: Bopen views the named stream file as a bit file to be read (if type is "r")
14973: or written (if type is "w" or "wb"). The stream file must already have been
14974: fopen(3)ed, and the first bit to be read/written will be the first bit in its
14975: next byte in getc(3)/putc(3) order. Bopen returns a pointer which identifies
14976: the bitfile to the other functions. System or stream I/O to/from the
14977: associated stream should not be used until after bclose is called.
14978: If bopen's type is "wb", then the entire output stream will be buffered
14979: in main memory until bflush or bclose are called. At any time, bbuffer
14980: returns this buffer's address and bsize its length in bytes.
14981: Getb returns the next bit from the named bitfile. It returns EOF on
14982: end of file or read error. EOF may occur on a byte, short, or int boundary,
14983: depending on file format.
14984: Putb appends the given bit to the named bitfile.
14985: Padb writes 'bit' enough times (possibly 0) so that if a bitstring
14986: of length 'len' were written next it would end on a 'bdy'-bit boundary
14987: (may do the wrong thing if 'bdy' doesn't divide UINT_MAX).
14988: Bflush ensures that all written bits have been written to the stream
14989: via putc(3). The output is padded with 0 bits to a byte, short, or int
14990: boundary, depending on file format. It returns the number of bytes (not bits)
14991: written since bopen or the last bflush. The bitfile remains open. It does not
14992: fflush(3) the associated stream.
14993: Bclose causes a bflush and frees all buffers. It returns the total
14994: number of bytes (not bits) read/written since bopen. It fflush(3)'es,
14995: but does not fclose(3) the associated stream.
14996:
14997: Bitfile formats are selected at compile time: see `FORMAT:' at the
14998: end of this file. The formats for input and output may differ. Formats
14999: include:
15000: a each bit is an ASCII character: '0' or '1', in putc(3) order; not padded.
15001: 0 the low-order (0001) bit in each byte is first ("little-endian"), and
15002: bytes are in putc(3) order; EOF and padding at a byte boundary.
15003: 1 the high-order (0200) bit in each byte is first ("big-endian"), and
15004: bytes are in putc(3) order; EOF and padding at a byte boundary.
15005: 10 the low-order (0001) bit in each byte is first ("little-endian"), but
15006: bytes are reversed (in each pair) from putc(3) order; EOF and padding
15007: at a short boundary.
15008: 11 the high-order (0200) bit in each byte is first ("big-endian"), but
15009: bytes are reversed (in each pair) from putc(3) order; EOF and padding
15010: at a short boundary.
15011: Planned (data structures are in place; code will be implemented if needed):
15012: 100 the low-order (0001) bit in each byte is first ("little-endian"), and
15013: bytes (in each pair) are in putc(3) order; but shorts (in each pair)
15014: are reversed from putc(3) order; EOF and padding at an int boundary.
15015: 101, 110, 111 - by obvious analogy
15016: BUGS
15017: Putting to an input bitfile or getting from an output bitfile is
15018: erroneous, but is not checked for.
15019: */
15020:
15021: #define BUFFERED (T) /* enable buffering of output */
15022:
15023: typedef struct BITFILE {
15024: FILE *fp; /* associated stream */
15025: char type; /* one of 'r','w' */
15026: int ic; /* byte just read */
15027: unsigned long nb; /* no. bytes read/written since bopen */
15028: unsigned long alloc; /* no. bytes allocated in buffer */
15029: char *buf; /* buffer (in malloc space) */
15030: char *cp; /* next char in buffer */
15031: unsigned int n; /* no. bits written so far (mod UINT_MAX) */
15032: unsigned char cm; /* single-bit mask */
15033: unsigned short sm; /* single-bit mask */
15034: unsigned int im; /* single-bit mask */
15035: union { struct { /* used to reorder char & short order */
15036: union { struct {
15037: unsigned char c0;
15038: unsigned char c1;
15039: } cc;
15040: unsigned short s;
15041: } s0;
15042: union { struct {
15043: unsigned char c0;
15044: unsigned char c1;
15045: } cc;
15046: unsigned short s;
15047: } s1;
15048: } ss;
15049: unsigned int i;
15050: } i;
15051: } BITFILE;
15052: #define Init_BITFILE {NULL,'\0',0,0L,0L,NULL,NULL,0,0,0}
15053: #if MAIN
15054: BITFILE empty_BITFILE = Init_BITFILE;
15055: #else
15056: extern BITFILE empty_BITFILE;
15057: #endif
15058:
15059: /* Code common to all formats: */
15060: #if MAIN
15061: BITFILE *bopen_rw(s,t)
15062: FILE *s;
15063: char *t;
15064: { BITFILE *f;
15065: if((f=(BITFILE *)malloc(sizeof(BITFILE)))==NULL) {
15066: err("bopen: can't alloc");
15067: return(NULL);
15068: };
15069: *f = empty_BITFILE;
15070: f->fp = s;
15071: f->type = *t;
15072: return(f);
15073: }
15074: #else
15075: BITFILE *bopen_rw();
15076: #endif
15077:
15078: #define bbuffer(f) ((f)->buf)
15079: #define bsize(f) ((bbuffer(f)!=NULL)? ((f)->cp - (f)->buf): 0L)
15080:
15081: #if !BUFFERED
15082: #define bputc(c,f) putc((c),(f)->fp)
15083: #define bbflush(f) (0L)
15084: #else
15085: #define BITFILE_incr (512) /* buffer allocations are in these increments */
15086:
15087: #if MAIN
15088: brealloc(f)
15089: BITFILE *f;
15090: { int nbuf; /* no. bytes in buffer */
15091: nbuf = bsize(f);
15092: f->alloc += BITFILE_incr;
15093: if((f->buf=(char *)realloc(f->buf,f->alloc))==NULL)
15094: abort("");
15095: f->cp = f->buf + nbuf;
15096: }
15097: #endif
15098:
15099: #define bputc(c,f) { \
15100: if((f)->buf==NULL) putc((c),(f)->fp); \
15101: else { if(bsize(f)==(f)->alloc) brealloc(f); \
15102: *(++((f)->cp))=(c); \
15103: } \
15104: }
15105:
15106: #if MAIN
15107: unsigned long bbflush(f)
15108: BITFILE *f; /* f->buf!=NULL && bsize(f)>0 */
15109: { register char *cp,*cq;
15110: unsigned long nbuf;
15111: nbuf = bsize(f);
15112: for(cq=(cp=f->buf)+nbuf; cp<cq; cp++) putc(*cp,f->fp);
15113: f->cp=f->buf;
15114: return(nbuf);
15115: }
15116: #else
15117: unsigned long bbflush();
15118: #endif
15119: #endif
15120:
15121: /* Code particular to each format: */
15122:
15123: /* Format a: ASCII file, one printable char ('0' or '1') per bit: */
15124: #define bopen_r_a(s) bopen_rw((s),"r")
15125: #define bopen_w_a(s) bopen_rw((s),"w")
15126: #define getb_a(f) ( (((f)->ic=getc((f)->fp))!=EOF)? \
15127: ((f)->nb++, \
15128: ((f)->ic=='0')? \
15129: 0: \
15130: (((f)->ic=='1')? 1: EOF)): \
15131: EOF )
15132: #define putb_a(b,f) { if((b)) bputc('1',f); else bputc('0',f); (f)->nb++; }
15133: #define bflush_a(f) ( (bsize(f)>0)? bbflush(f): (0L) )
15134:
15135: /* Format 0: the low-order bit (0001) in each byte is first ("little-endian"),
15136: and bytes are in putc(3) order; */
15137: #if MAIN
15138: BITFILE *bopen_r_0(s)
15139: FILE *s;
15140: { BITFILE *f;
15141: if((f=bopen_rw(s,"r"))!=NULL) {
15142: f->cm=0000;
15143: };
15144: return(f);
15145: }
15146: #else
15147: BITFILE *bopen_r_0();
15148: #endif
15149: #if MAIN
15150: BITFILE *bopen_w_0(s)
15151: FILE *s;
15152: { BITFILE *f;
15153: if((f=bopen_rw(s,"w"))!=NULL) {
15154: f->i.ss.s0.cc.c0=0000;
15155: f->cm=0001;
15156: };
15157: return(f);
15158: }
15159: #else
15160: BITFILE *bopen_w_0();
15161: #endif
15162: #define getb_0(f) ( ((f)->cm)? \
15163: ( ((f)->cm&(f)->ic)? \
15164: ((f)->cm<<=1,1): \
15165: ((f)->cm<<=1,0) ): \
15166: ( (((f)->ic=getc((f)->fp))==EOF)? \
15167: EOF: \
15168: ( (f)->nb++, \
15169: (f)->cm=0001, \
15170: ((f)->cm&(f)->ic)? \
15171: ((f)->cm<<=1,1): \
15172: ((f)->cm<<=1,0) ) ) )
15173: #define putb_0(b,f) { \
15174: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \
15175: if( !((f)->cm<<=1) ) { \
15176: bputc((f)->i.ss.s0.cc.c0,f); \
15177: (f)->nb++; \
15178: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0001; \
15179: }; \
15180: (f)->n++; \
15181: }
15182: #define bflush_0(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L)
15183:
15184: /* Format 1: the high-order bit (0200) in each byte is first ("big-endian"), and
15185: bytes are in putc(3) order; */
15186: #if MAIN
15187: BITFILE *bopen_r_1(s)
15188: FILE *s;
15189: { BITFILE *f;
15190: if((f=bopen_rw(s,"r"))!=NULL) {
15191: f->cm=0000;
15192: };
15193: return(f);
15194: }
15195: #else
15196: BITFILE *bopen_r_1();
15197: #endif
15198: #if MAIN
15199: BITFILE *bopen_w_1(s)
15200: FILE *s;
15201: { BITFILE *f;
15202: if((f=bopen_rw(s,"w"))!=NULL) {
15203: f->i.ss.s0.cc.c0=0000;
15204: f->cm=0200;
15205: };
15206: return(f);
15207: }
15208: #else
15209: BITFILE *bopen_w_1();
15210: #endif
15211: #define getb_1(f) ( ((f)->cm)? \
15212: ( ((f)->cm&(f)->ic)? \
15213: ((f)->cm>>=1,1): \
15214: ((f)->cm>>=1,0) ): \
15215: ( (((f)->ic=getc((f)->fp))==EOF)? \
15216: EOF: \
15217: ( (f)->nb++, \
15218: (f)->cm=0200, \
15219: ((f)->cm&(f)->ic)? \
15220: ((f)->cm>>=1,1): \
15221: ((f)->cm>>=1,0) ) ) )
15222: #define putb_1(b,f) { \
15223: if((b)) (f)->i.ss.s0.cc.c0 |= (f)->cm; \
15224: if( !((f)->cm>>=1) ) { \
15225: bputc((f)->i.ss.s0.cc.c0,f); \
15226: (f)->nb++; \
15227: (f)->i.ss.s0.cc.c0=0000; (f)->cm=0200; \
15228: }; \
15229: (f)->n++; \
15230: }
15231: #define bflush_1(f) (padb((f),0,8,0), (bsize(f)>0)? bbflush(f): 0L)
15232:
15233: /* Format 10: the low-order (0001) bit in each byte is first ("little-endian"), and
15234: bytes are reversed (in each pair) from putc(3) order;
15235: */
15236: #if MAIN
15237: BITFILE *bopen_r_10(s)
15238: FILE *s;
15239: { BITFILE *f;
15240: if((f=bopen_rw(s,"r"))!=NULL) {
15241: f->sm=0000000;
15242: };
15243: return(f);
15244: }
15245: #else
15246: BITFILE *bopen_r_10();
15247: #endif
15248: #if MAIN
15249: BITFILE *bopen_w_10(s)
15250: FILE *s;
15251: { BITFILE *f;
15252: if((f=bopen_rw(s,"w"))!=NULL) {
15253: f->i.ss.s0.s=0000000;
15254: f->sm=0000001;
15255: };
15256: return(f);
15257: }
15258: #else
15259: BITFILE *bopen_w_10();
15260: #endif
15261: #define getb_10(f) ( ((f)->sm)? \
15262: ( ((f)->sm&(f)->i.ss.s0.s)? \
15263: ((f)->sm<<=1,1): \
15264: ((f)->sm<<=1,0) ): \
15265: ( (((f)->ic=getc((f)->fp))==EOF)? \
15266: EOF: \
15267: ( (f)->nb++, \
15268: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \
15269: ( (((f)->ic=getc((f)->fp))==EOF)? \
15270: EOF: \
15271: ( (f)->nb++, \
15272: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \
15273: (f)->sm=0000001, \
15274: ((f)->sm&(f)->i.ss.s0.s)? \
15275: ((f)->sm<<=1,1): \
15276: ((f)->sm<<=1,0) ) ) ) ) )
15277: #define putb_10(b,f) { \
15278: if((b)) (f)->i.ss.s0.s |= (f)->sm; \
15279: if( !((f)->sm<<=1) ) { \
15280: bputc((f)->i.ss.s0.cc.c1,f); \
15281: (f)->nb++; \
15282: bputc((f)->i.ss.s0.cc.c0,f); \
15283: (f)->nb++; \
15284: (f)->i.ss.s0.s=0000000; (f)->sm=0000001; \
15285: }; \
15286: (f)->n++; \
15287: }
15288: #define bflush_10(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L)
15289:
15290: /* Format 11: the high-order (0200) bit in each byte is first ("little-endian"),
15291: and bytes are reversed (in each pair) from putc(3) order.
15292: */
15293: #if MAIN
15294: BITFILE *bopen_r_11(s)
15295: FILE *s;
15296: { BITFILE *f;
15297: if((f=bopen_rw(s,"r"))!=NULL) {
15298: f->sm=0000000;
15299: };
15300: return(f);
15301: }
15302: #else
15303: BITFILE *bopen_r_11();
15304: #endif
15305: #if MAIN
15306: BITFILE *bopen_w_11(s)
15307: FILE *s;
15308: { BITFILE *f;
15309: if((f=bopen_rw(s,"w"))!=NULL) {
15310: f->i.ss.s0.s=0000000;
15311: f->sm=0100000;
15312: };
15313: return(f);
15314: }
15315: #else
15316: BITFILE *bopen_w_11();
15317: #endif
15318: #define getb_11(f) ( ((f)->sm)? \
15319: ( ((f)->sm&(f)->i.ss.s0.s)? \
15320: ((f)->sm>>=1,1): \
15321: ((f)->sm>>=1,0) ): \
15322: ( (((f)->ic=getc((f)->fp))==EOF)? \
15323: EOF: \
15324: ( (f)->nb++, \
15325: (f)->i.ss.s0.cc.c0=(f)->ic&0377, \
15326: ( (((f)->ic=getc((f)->fp))==EOF)? \
15327: EOF: \
15328: ( (f)->nb++, \
15329: (f)->i.ss.s0.cc.c1=(f)->ic&0377, \
15330: (f)->sm=0100000, \
15331: ((f)->sm&(f)->i.ss.s0.s)? \
15332: ((f)->sm>>=1,1): \
15333: ((f)->sm>>=1,0) ) ) ) ) )
15334: #define putb_11(b,f) { \
15335: if((b)) (f)->i.ss.s0.s |= (f)->sm; \
15336: if( !((f)->sm>>=1) ) { \
15337: bputc((f)->i.ss.s0.cc.c0,f); \
15338: (f)->nb++; \
15339: bputc((f)->i.ss.s0.cc.c1,f); \
15340: (f)->nb++; \
15341: (f)->i.ss.s0.s=0000000; (f)->sm=0100000; \
15342: }; \
15343: (f)->n++; \
15344: }
15345: #define bflush_11(f) (padb((f),0,16,0), (bsize(f)>0)? bbflush(f): 0L)
15346:
15347: /**************************************************************/
15348: /* FORMAT: may be selected here (input and output may differ) */
15349:
15350: /* Input: */
15351: #define bopen_r(s) bopen_r_0((s))
15352: #define getb(f) getb_0(f)
15353: /* Output: */
15354: #define bopen_w(s) bopen_w_0((s))
15355: #define putb(b,f) putb_0((b),(f))
15356: #define bflush(f) bflush_0(f)
15357:
15358: /**************************************************************/
15359:
15360: /* Code common to all formats: */
15361: #if MAIN
15362: BITFILE *bopen(s,t)
15363: FILE *s;
15364: char *t;
15365: { BITFILE *res;
15366: if(*(t)=='r') res=bopen_r(s);
15367: else if(*(t)=='w') {
15368: res=bopen_w(s);
15369: #if BUFFERED
15370: if(*(t+1)=='b') {
15371: res->alloc = BITFILE_incr;
15372: if((res->buf=(char *)malloc(res->alloc))==NULL)
15373: abort("bopen: can't alloc buffer");
15374: res->cp = res->buf;
15375: };
15376: #endif
15377: }
15378: else abort("bopen: bad type: \"%s\"",t);
15379: return(res);
15380: }
15381: #else
15382: BITFILE *bopen();
15383: #endif
15384:
15385: #if MAIN
15386: padb(f,b,B,l)
15387: BITFILE *f;
15388: char b;
15389: int l,B;
15390: { while(((f)->n+(l))%(B)) putb((b),(f));
15391: }
15392: #endif
15393:
15394: #if MAIN
15395: unsigned long bclose(f)
15396: BITFILE *f;
15397: { unsigned long nb,nbuf;
15398: if(f->type=='w') {
15399: nbuf=bflush(f);
15400: fflush(f->fp);
15401: #if BUFFERED
15402: if(f->buf!=NULL) { free(f->buf); f->buf=NULL; }
15403: #endif
15404: };
15405: nb=f->nb;
15406: free(f);
15407: return(nb);
15408: }
15409: #else
15410: unsigned long bclose();
15411: #endif
15412: 0707070035350557131006640007620000050000010263430476773367100001000000000615boole.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
15413: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
15414: /* The copyright notice does not imply actual or intended publication. */
15415: /* AUTHORS: */
15416: /* H. S. Baird - ATT-BL MH - first versions */
15417: /* boole.h */
15418:
15419: #define boolean int
15420: #define T 1
15421: #define F 0
15422: 0707070035350321011006640007620000050000010263450476773367100000700000020537fioi.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
15423: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
15424: /* The copyright notice does not imply actual or intended publication. */
15425: /* AUTHORS: */
15426: /* H. S. Baird - ATT-BL MH - first versions */
15427:
15428: /* fioi.h - buffered I/O of machine-, OS-, and compiler-independent binary values.
15429:
15430: Machine-, OS-, and compiler-independence of 'fioi' functions require that:
15431: 1) chars are exactly 8 bits and their contents are invariant under I/O;
15432: 2) the order of chars, as written by putc() and read by getc(), is
15433: also invariant, across all machines, OS, and compilers.
15434: Both of these requirements are customarily met by UNIX OS & tools.
15435:
15436: All values are written/read as a stream of char's, ultimately
15437: using putc() & getc() macroes.
15438: To maximize speed, macroes are used wherever possible:
15439: - the first argument F of each macro is a stream (FILE *).
15440: - write macroes have the form fwri_TYPE(F,value); `value' is assigned to
15441: a variable of type TYPE before it is written (so compiler-dependent type
15442: coercions may apply).
15443: - read macroes have the form frdi_TYPE(F), returning a value of type TYPE.
15444: Arguments to these macroes are evaluated exactly once.
15445: */
15446:
15447: /** MACHINE-DEPENDENT CUSTOMIZATION OF TYPES **/
15448: /* For each machine, all these types must be supported in the sense that
15449: some roughly-equivalent machine-supported type exists. If an exact
15450: equivalent doesn't exist, pick the shortest that is at least as long
15451: (in no. bytes), if possible. If there is no machine representation
15452: at least as long as specified, the only penalty will be the inevitable one:
15453: when a value is read, it may be truncated to the maximum value that can be
15454: represented.
15455: */
15456: #define int1 char /* 8-bit signed 2's complement integer */
15457: #define int2 short /* 16-bit signed 2's complement integer */
15458: #define int3 int /* 24-bit signed 2's complement integer */
15459: #define int4 int /* 32-bit signed 2's complement integer */
15460: #define int8 long /* 64-bit signed 2's complement integer */
15461: #define uint1 unsigned char /* 8-bit unsigned integer */
15462: #define uint2 unsigned short /* 16-bit unsigned integer */
15463: #define uint3 unsigned int /* 24-bit unsigned integer */
15464: #define uint4 unsigned int /* 32-bit unsigned integer */
15465: #define uint8 unsigned long /* 64-bit unsigned integer */
15466:
15467: /* IEEE 64-bit floating point format */
15468: typedef struct Ieeed {
15469: int8 l;
15470: int8 h;
15471: } Ieeed;
15472:
15473: /* Cope with unsigned chars on 3B2 & compensate for bug on MIPS */
15474: #if CPU!=ATT3B && CPU!=MIPS
15475: #define toint1(c) (int1)(c)
15476: #else
15477: #if MAIN
15478: int toint1(c)
15479: register int c;
15480: { if ( ((1<<7)&c) !=0 ) return(c-256);
15481: else return c;
15482: }
15483: #else
15484: extern int toint1();
15485: #endif
15486: #endif
15487:
15488: /** THE REST OF THIS FILE IS MACHINE-, OS-, and COMPILER-INDEPENDENT **/
15489:
15490: typedef struct Fioi {
15491: int1 i1;
15492: int2 i2;
15493: int3 i3;
15494: int4 i4;
15495: int8 i8;
15496: uint1 ui1;
15497: uint2 ui2;
15498: uint3 ui3;
15499: uint4 ui4;
15500: uint8 ui8;
15501: char str[100];
15502: } Fioi;
15503: #define Init_Fioi {0,0,0,0,0,0,0,0,0,0,""}
15504: #if MAIN
15505: Fioi _Fioi = Init_Fioi;
15506: #else
15507: extern Fioi _Fioi;
15508: #endif
15509:
15510: /* Characters */
15511: #define fwri_ch(F,V) putc((V),(F))
15512: #define frdi_ch(F) getc((F))
15513:
15514: #if T /* TRANSITIONAL: used to read: "#if FWRI" */
15515: /* Strings are '\0'-terminated both in main memory & in peripheral files. */
15516: #define fwri_str(F,S) { fputs((S),(F)); putc('\0',(F)); }
15517: #else
15518: /* Strings are '\0'-terminated in the variable and '\n'-terminated in the file.
15519: BAD, OBSOLESCENT POLICY: both should use '\0'-termination */
15520: #define fwri_str(F,S) { fputs((S),(F)); putc('\n',(F)); }
15521: #endif
15522:
15523: #define MAX_FIO_STRLEN (128)
15524:
15525: #if T /* TRANSITIONAL: used to read: "#if FRDI" */
15526:
15527: /* Strings are '\0'-terminated both in main memory & in peripheral files. */
15528: /*** TRANSITIONAL PATCH: accept '\n' as a terminator also; this will be disabled
15529: as soon as all classifier tables have been recreated with FWRI==T. ***/
15530: /* Read string of maximum length MAX_FIO_STRLEN; return pointer to malloc space */
15531: #if MAIN
15532: char *frdi_str(f)
15533: FILE *f;
15534: { static char s[MAX_FIO_STRLEN+1];
15535: register int ch;
15536: register char *c,*ce;
15537: char *res;
15538: ce=(c=s)+MAX_FIO_STRLEN;
15539: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) *(c++) = ch;
15540: *c='\0';
15541: if(c==ce) /* label is truncated; find end of it */ {
15542: while(((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
15543: };
15544: if((res=(char *)strdup(s))==NULL)
15545: abort("frdi_str: can't dup char *s[%d]",strlen(s));
15546: return(res);
15547: }
15548: #else
15549: char *frdi_str();
15550: #endif
15551: /* 's' is an already-allocated buffer of known length >=N (including '\0') */
15552: #if MAIN
15553: int frdi_strn(f,s,n)
15554: FILE *f;
15555: char s[];
15556: int n;
15557: { register int ch;
15558: register char *c,*ce;
15559: ce=(c=s)+n-1;
15560: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) *(c++) = ch;
15561: *c='\0';
15562: if(c==ce) /* label is truncated; find end of it */ {
15563: while(((ch=getc(f))!=EOF)&&(ch!='\0')&&(ch!='\n')) ;
15564: };
15565: if(ch==EOF) return(0); else if(ferror(f)) return(-errno); else return(1);
15566: }
15567: #else
15568: int frdi_strn();
15569: #endif
15570:
15571: #else
15572:
15573: /* Strings are '\0'-terminated in the variable and '\n'-terminated in the file.
15574: BAD, OBSOLESCENT POLICY: both should use '\0'-termination */
15575: /* Read string of maximum length MAX_FIO_STRLEN; return pointer to malloc space */
15576: #if MAIN
15577: char *frdi_str(f)
15578: FILE *f;
15579: { static char s[MAX_FIO_STRLEN+1];
15580: register int ch;
15581: register char *c,*ce;
15582: char *res;
15583: ce=(c=s)+MAX_FIO_STRLEN;
15584: while((c<ce)&&((ch=getc(f))!=EOF)&&(ch!='\n')) *(c++) = ch;
15585: *c='\0';
15586: if(c==ce) /* label is truncated; find end of it */ {
15587: while(((ch=getc(f))!=EOF)&&(ch!='\n')) ;
15588: };
15589: if((res=(char *)strdup(s))==NULL)
15590: abort("frdi_str: can't dup char *s[%d]",strlen(s));
15591: return(res);
15592: }
15593: #else
15594: char *frdi_str();
15595: #endif
15596: /* S is an already-allocated buffer of known length >=N (including '\0') */
15597: #define frdi_strn(F,S,N) ( feof(F)? 0 : ( \
15598: fgets((S),(N),(F)), \
15599: ( (((S)[strlen((S))-1])=='\n')? (S)[strlen((S))-1]='\0': 1 ), \
15600: (ferror(F)? -errno: 1) ) )
15601:
15602: #endif
15603:
15604: /* Integers (unsigned and signed) are written low-order byte first. */
15605: #define fwri_uint1(F,V) fwri_ch((F),(uint1)(V))
15606: #define frdi_uint1(F) ((uint1)frdi_ch((F)))
15607:
15608: #define fwri_uint2(F,V) { fwri_uint1((F),_Fioi.ui2=(V)); \
15609: fwri_uint1((F),_Fioi.ui2>>8); }
15610: #define frdi_uint2(F) ((uint2)( _Fioi.ui2=frdi_uint1((F)), \
15611: (frdi_uint1((F))<<8)|_Fioi.ui2 ))
15612:
15613: #define fwri_uint3(F,V) { fwri_uint2((F),_Fioi.ui3=(V)); \
15614: fwri_uint1((F),_Fioi.ui3>>16); }
15615: #define frdi_uint3(F) ((uint3)( _Fioi.ui3=frdi_uint2((F)), \
15616: (frdi_uint1((F))<<16)|_Fioi.ui3 ))
15617:
15618: #define fwri_uint4(F,V) { fwri_uint2((F),_Fioi.ui4=(V)); \
15619: fwri_uint2((F),_Fioi.ui4>>16); }
15620: #define frdi_uint4(F) ((uint4)( _Fioi.ui4=frdi_uint2((F)), \
15621: (frdi_uint2((F))<<16)|_Fioi.ui4 ))
15622:
15623: #define fwri_uint8(F,V) { fwri_uint4((F),_Fioi.ui8=(V)); \
15624: fwri_uint4((F),_Fioi.ui8>>32); }
15625: #define frdi_uint8(F) ((uint8)( _Fioi.ui8=frdi_uint4((F)), \
15626: (frdi_uint4((F))<<32)|_Fioi.ui8 ))
15627:
15628: /* Signed integers are assumed to be 2's complement.
15629: Note the suppression of inappropriate sign-extensions using judicious
15630: unsigned reads. */
15631:
15632: #define fwri_int1(F,V) fwri_ch((F),_Fioi.i1=(V))
15633: #define frdi_int1(F) (toint1(frdi_ch((F))))
15634:
15635: #define fwri_int2(F,V) { fwri_int1((F),_Fioi.i2=(V)); \
15636: fwri_int1((F),_Fioi.i2>>8); }
15637: #define frdi_int2(F) ((int2)( _Fioi.i2=frdi_uint1((F)), \
15638: (frdi_int1((F))<<8)|_Fioi.i2 ))
15639:
15640: #define fwri_int3(F,V) { fwri_int2((F),_Fioi.i3=(V)); \
15641: fwri_int1((F),_Fioi.i3>>16); }
15642: #define frdi_int3(F) ((int3)( _Fioi.i3=frdi_uint2((F)), \
15643: (frdi_int1((F))<<16)|_Fioi.i3 ))
15644:
15645: #define fwri_int4(F,V) { fwri_int2((F),_Fioi.i4=(V)); \
15646: fwri_int2((F),_Fioi.i4>>16); }
15647: #define frdi_int4(F) ((int4)( _Fioi.i4=frdi_uint2((F)), \
15648: (frdi_int2((F))<<16)|_Fioi.i4 ))
15649:
15650: #define fwri_int8(F,V) { fwri_int4((F),_Fioi.i8=(V)); \
15651: fwri_int4((F),_Fioi.i8>>32); }
15652: #define frdi_int8(F) ((int8)( _Fioi.i8=frdi_uint4((F)), \
15653: (frdi_int4((F))<<32)|_Fioi.i8 ))
15654:
15655:
15656: /* Floating point */
15657: #if MAIN
15658: /* See Marsha Grabow & George Gilmer & KT */
15659: void
15660: dtoieeed(ieee,native)
15661: Ieeed *ieee;
15662: double native;
15663: {
15664: double fr, ho, f;
15665: int iexp;
15666:
15667: if(native < 0) {
15668: dtoieeed(ieee, -native);
15669: ieee->h |= 0x80000000L;
15670: return;
15671: }
15672: if(native == 0) {
15673: ieee->l = 0;
15674: ieee->h = 0;
15675: return;
15676: }
15677: fr = frexp(native, &iexp);
15678: f = 2097152L; /* shouldnt use fp constants here */
15679: fr = modf(fr*f, &ho);
15680: ieee->h = ho;
15681: ieee->h &= 0xfffffL;
15682: ieee->h |= (iexp+1022L) << 20;
15683: f = 65536L;
15684: fr = modf(fr*f, &ho);
15685: ieee->l = ho;
15686: ieee->l <<= 16;
15687: ieee->l |= (long)(fr*f);
15688: }
15689: #else
15690: void dtoieeed();
15691: #endif
15692: 0707070035350321111006640007620000050000010263500476773367100000700000002300font.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
15693: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
15694: /* The copyright notice does not imply actual or intended publication. */
15695: /* AUTHORS: */
15696: /* H. S. Baird - ATT-BL MH - first versions */
15697: /* font.h - typedefs, etc for font-characteristic functions:
15698: The baseline is defined by the locus of bottoms of all characters that
15699: have no descenders and are not punctuation.
15700: The top is the top of characters without risers (negative).
15701: The `rise' is the (negative) height of risers (above baseline), and `descent'
15702: is the positive) distance below baseline.
15703: */
15704:
15705: /* font attributes, in absolute scanner coordinates */
15706: typedef struct FontAttr {
15707: Scoor body; /* point size */
15708: Scoor xhgt; /* x-height */
15709: Scoor ascd; /* height of ascenders (above xheight, >0) */
15710: Scoor caph; /* capital height (above baseline, >0) */
15711: Scoor desc; /* height of descenders (below baseline, >0) */
15712: Scoor doth; /* height of punctuation dots */
15713: } FontAttr;
15714:
15715: #ifdef MAIN
15716: FontAttr *ps_to_attr(); /* pointsize, digit'n resol'n --> attributes */
15717: xhgt_to_ps();
15718: caph_to_ps();
15719: #endif
15720: 0707070035350320471006640007620000050000010263510476773367200000700000124016jslr.c /* AT&T PROPRIETARY: Developed at AT&T Expense */
15721: /* AUTHORS: */
15722: /* H. S. Baird - ATT-BL MH - first versions */
15723: /* rlbr - run-length encode a binary raster line
15724: `rasp' is a raster line of bits. rasp[0] is the leftmost byte in the line and
15725: the 001 bit is the leftmost bit in each byte ("little-endian").
15726: Analyzes the line into a series of runs of `1's, placing them into array
15727: `runs'. Observes margins: starts at `lm' bit and continues through `rm'; bits
15728: outside margins are assumed 0. A `run' is two shorts (the starting &
15729: ending indices of the run of `1's, inclusive). The indices are shifted
15730: so that the index of `lm' becomes `olm'. Returns the number of runs.
15731: NOTES:
15732: The contents of the raster-line are restored to their orginal
15733: state on return. The user must ensure that:
15734: (1) margins fall within `rasp';
15735: (2) `rasp' has one extra byte at the end for use by this routine; and
15736: (3) `runs' is big enough to hold the worst-case no. of runs that could
15737: result, which is (rm-lm)/2+1.
15738: */
15739:
15740: int rlbr(rasp,lm,rm,olm,runp)
15741: char unsigned rasp[]; /* binary raster line (with 1 extra byte at end) */
15742: int lm,rm; /* left,right margin bit indices within raster */
15743: int olm; /* on output, `lm' index has become `olm' */
15744: short runp[]; /* array of run-segments [xs,xe] (pairs of short) */
15745: { register char unsigned *bp,*ep; /* byte pointers into raster line */
15746: register short cb; /* x_coordinate of 1st bit of current byte */
15747: register short *xp; /* ptr to x-coordinate in run-length array */
15748: register short prior; /* prior bit, coded 0400 or 0000 */
15749:
15750: char unsigned *lbp,*rbp; /* ptrs to margin bytes */
15751: int lo,ro; /* `offset' of margin bits in bytes */
15752: char unsigned svlb,svrb,svrrb; /* unmodified copies of margin bytes */
15753:
15754: if(lm>rm) return(0);
15755: /* compute margins' bytes, save copies, set bits outside margins to 0 */
15756: lbp=rasp+(lm/8); svlb= *lbp;
15757: /* force bits left of lm to 0 */
15758: lo=lm%8; if(lo>0) *lbp &= (0377<<lo);
15759: rbp=rasp+(rm/8); svrb= *rbp;
15760: /* force bits right of rm to 0 */
15761: ro=rm%8; if(ro<7) *rbp &= (0377>>(7-ro));
15762: /* place a 0000 byte to right of margin byte, to force good termination */
15763: svrrb= *(rbp+1); *(rbp+1)='\0';
15764:
15765: /* MAIN LOOP */
15766: prior=0000; /* act as if there's a 0 byte to left of margin byte */
15767: xp=runp;
15768: bp=lbp;
15769: ep=rbp+2;
15770: cb=(-lo+olm);
15771: do { switch( prior | *(bp++) ) {
15772: /* contents of rlbr.c1 come below here */
15773: case 00: break;
15774: case 01: *(xp++)=cb; *(xp++)=cb; break;
15775: case 02: *(xp++)=cb+1; *(xp++)=cb+1; break;
15776: case 03: *(xp++)=cb; *(xp++)=cb+1; break;
15777: case 04: *(xp++)=cb+2; *(xp++)=cb+2; break;
15778: case 05: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; break;
15779: case 06: *(xp++)=cb+1; *(xp++)=cb+2; break;
15780: case 07: *(xp++)=cb; *(xp++)=cb+2; break;
15781: case 010: *(xp++)=cb+3; *(xp++)=cb+3; break;
15782: case 011: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; break;
15783: case 012: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; break;
15784: case 013: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; break;
15785: case 014: *(xp++)=cb+2; *(xp++)=cb+3; break;
15786: case 015: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; break;
15787: case 016: *(xp++)=cb+1; *(xp++)=cb+3; break;
15788: case 017: *(xp++)=cb; *(xp++)=cb+3; break;
15789: case 020: *(xp++)=cb+4; *(xp++)=cb+4; break;
15790: case 021: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; break;
15791: case 022: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; break;
15792: case 023: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; break;
15793: case 024: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
15794: case 025: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
15795: case 026: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
15796: case 027: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; break;
15797: case 030: *(xp++)=cb+3; *(xp++)=cb+4; break;
15798: case 031: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; break;
15799: case 032: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; break;
15800: case 033: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; break;
15801: case 034: *(xp++)=cb+2; *(xp++)=cb+4; break;
15802: case 035: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; break;
15803: case 036: *(xp++)=cb+1; *(xp++)=cb+4; break;
15804: case 037: *(xp++)=cb; *(xp++)=cb+4; break;
15805: case 040: *(xp++)=cb+5; *(xp++)=cb+5; break;
15806: case 041: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; break;
15807: case 042: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; break;
15808: case 043: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; break;
15809: case 044: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
15810: case 045: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
15811: case 046: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
15812: case 047: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; break;
15813: case 050: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15814: case 051: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15815: case 052: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15816: case 053: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15817: case 054: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15818: case 055: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15819: case 056: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15820: case 057: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; break;
15821: case 060: *(xp++)=cb+4; *(xp++)=cb+5; break;
15822: case 061: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; break;
15823: case 062: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; break;
15824: case 063: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; break;
15825: case 064: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
15826: case 065: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
15827: case 066: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
15828: case 067: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; break;
15829: case 070: *(xp++)=cb+3; *(xp++)=cb+5; break;
15830: case 071: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; break;
15831: case 072: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
15832: case 073: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
15833: case 074: *(xp++)=cb+2; *(xp++)=cb+5; break;
15834: case 075: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; break;
15835: case 076: *(xp++)=cb+1; *(xp++)=cb+5; break;
15836: case 077: *(xp++)=cb; *(xp++)=cb+5; break;
15837: case 0100: *(xp++)=cb+6; *(xp++)=cb+6; break;
15838: case 0101: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+6; *(xp++)=cb+6; break;
15839: case 0102: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; break;
15840: case 0103: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; break;
15841: case 0104: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
15842: case 0105: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
15843: case 0106: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
15844: case 0107: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; break;
15845: case 0110: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15846: case 0111: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15847: case 0112: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15848: case 0113: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15849: case 0114: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15850: case 0115: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15851: case 0116: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15852: case 0117: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; break;
15853: case 0120: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15854: case 0121: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15855: case 0122: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15856: case 0123: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15857: case 0124: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15858: case 0125: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15859: case 0126: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15860: case 0127: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15861: case 0130: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15862: case 0131: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15863: case 0132: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15864: case 0133: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15865: case 0134: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15866: case 0135: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15867: case 0136: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15868: case 0137: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; break;
15869: case 0140: *(xp++)=cb+5; *(xp++)=cb+6; break;
15870: case 0141: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+6; break;
15871: case 0142: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; break;
15872: case 0143: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; break;
15873: case 0144: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
15874: case 0145: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
15875: case 0146: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
15876: case 0147: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; break;
15877: case 0150: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15878: case 0151: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15879: case 0152: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15880: case 0153: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15881: case 0154: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15882: case 0155: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15883: case 0156: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15884: case 0157: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; break;
15885: case 0160: *(xp++)=cb+4; *(xp++)=cb+6; break;
15886: case 0161: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; break;
15887: case 0162: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
15888: case 0163: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
15889: case 0164: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
15890: case 0165: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
15891: case 0166: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
15892: case 0167: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
15893: case 0170: *(xp++)=cb+3; *(xp++)=cb+6; break;
15894: case 0171: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; break;
15895: case 0172: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
15896: case 0173: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
15897: case 0174: *(xp++)=cb+2; *(xp++)=cb+6; break;
15898: case 0175: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; break;
15899: case 0176: *(xp++)=cb+1; *(xp++)=cb+6; break;
15900: case 0177: *(xp++)=cb; *(xp++)=cb+6; break;
15901: case 0200: *(xp++)=cb+7; prior=0400; break;
15902: case 0201: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+7; prior=0400; break;
15903: case 0202: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+7; prior=0400; break;
15904: case 0203: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+7; prior=0400; break;
15905: case 0204: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
15906: case 0205: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
15907: case 0206: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
15908: case 0207: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+7; prior=0400; break;
15909: case 0210: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15910: case 0211: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15911: case 0212: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15912: case 0213: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15913: case 0214: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15914: case 0215: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15915: case 0216: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15916: case 0217: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+7; prior=0400; break;
15917: case 0220: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15918: case 0221: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15919: case 0222: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15920: case 0223: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15921: case 0224: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15922: case 0225: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15923: case 0226: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15924: case 0227: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15925: case 0230: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15926: case 0231: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15927: case 0232: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15928: case 0233: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15929: case 0234: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15930: case 0235: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15931: case 0236: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15932: case 0237: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+7; prior=0400; break;
15933: case 0240: *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15934: case 0241: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15935: case 0242: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15936: case 0243: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15937: case 0244: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15938: case 0245: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15939: case 0246: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15940: case 0247: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15941: case 0250: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15942: case 0251: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15943: case 0252: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15944: case 0253: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15945: case 0254: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15946: case 0255: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15947: case 0256: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15948: case 0257: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15949: case 0260: *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15950: case 0261: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15951: case 0262: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15952: case 0263: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15953: case 0264: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15954: case 0265: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15955: case 0266: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15956: case 0267: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15957: case 0270: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15958: case 0271: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15959: case 0272: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15960: case 0273: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15961: case 0274: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15962: case 0275: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15963: case 0276: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15964: case 0277: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+7; prior=0400; break;
15965: case 0300: *(xp++)=cb+6; prior=0400; break;
15966: case 0301: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+6; prior=0400; break;
15967: case 0302: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; prior=0400; break;
15968: case 0303: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+6; prior=0400; break;
15969: case 0304: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
15970: case 0305: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
15971: case 0306: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
15972: case 0307: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; prior=0400; break;
15973: case 0310: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15974: case 0311: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15975: case 0312: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15976: case 0313: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15977: case 0314: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15978: case 0315: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15979: case 0316: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15980: case 0317: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; prior=0400; break;
15981: case 0320: *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15982: case 0321: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15983: case 0322: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15984: case 0323: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15985: case 0324: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15986: case 0325: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15987: case 0326: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15988: case 0327: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15989: case 0330: *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15990: case 0331: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15991: case 0332: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15992: case 0333: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15993: case 0334: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15994: case 0335: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15995: case 0336: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15996: case 0337: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; prior=0400; break;
15997: case 0340: *(xp++)=cb+5; prior=0400; break;
15998: case 0341: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+5; prior=0400; break;
15999: case 0342: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; prior=0400; break;
16000: case 0343: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+5; prior=0400; break;
16001: case 0344: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
16002: case 0345: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
16003: case 0346: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
16004: case 0347: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; prior=0400; break;
16005: case 0350: *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16006: case 0351: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16007: case 0352: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16008: case 0353: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16009: case 0354: *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16010: case 0355: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16011: case 0356: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16012: case 0357: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; prior=0400; break;
16013: case 0360: *(xp++)=cb+4; prior=0400; break;
16014: case 0361: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+4; prior=0400; break;
16015: case 0362: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; prior=0400; break;
16016: case 0363: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+4; prior=0400; break;
16017: case 0364: *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
16018: case 0365: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
16019: case 0366: *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
16020: case 0367: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; prior=0400; break;
16021: case 0370: *(xp++)=cb+3; prior=0400; break;
16022: case 0371: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+3; prior=0400; break;
16023: case 0372: *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; prior=0400; break;
16024: case 0373: *(xp++)=cb; *(xp++)=cb+1; *(xp++)=cb+3; prior=0400; break;
16025: case 0374: *(xp++)=cb+2; prior=0400; break;
16026: case 0375: *(xp++)=cb; *(xp++)=cb; *(xp++)=cb+2; prior=0400; break;
16027: case 0376: *(xp++)=cb+1; prior=0400; break;
16028: case 0377: *(xp++)=cb; prior=0400; break;
16029:
16030: case 0400: *(xp++)=cb-1; prior=0000; break;
16031: case 0401: *(xp++)=cb; prior=0000; break;
16032: case 0402: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; prior=0000; break;
16033: case 0403: *(xp++)=cb+1; prior=0000; break;
16034: case 0404: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; prior=0000; break;
16035: case 0405: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; prior=0000; break;
16036: case 0406: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; prior=0000; break;
16037: case 0407: *(xp++)=cb+2; prior=0000; break;
16038: case 0410: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
16039: case 0411: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
16040: case 0412: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
16041: case 0413: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; prior=0000; break;
16042: case 0414: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; prior=0000; break;
16043: case 0415: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; prior=0000; break;
16044: case 0416: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; prior=0000; break;
16045: case 0417: *(xp++)=cb+3; prior=0000; break;
16046: case 0420: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16047: case 0421: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16048: case 0422: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16049: case 0423: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16050: case 0424: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16051: case 0425: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16052: case 0426: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16053: case 0427: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; prior=0000; break;
16054: case 0430: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
16055: case 0431: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
16056: case 0432: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
16057: case 0433: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; prior=0000; break;
16058: case 0434: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; prior=0000; break;
16059: case 0435: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; prior=0000; break;
16060: case 0436: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; prior=0000; break;
16061: case 0437: *(xp++)=cb+4; prior=0000; break;
16062: case 0440: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16063: case 0441: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16064: case 0442: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16065: case 0443: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16066: case 0444: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16067: case 0445: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16068: case 0446: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16069: case 0447: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16070: case 0450: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16071: case 0451: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16072: case 0452: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16073: case 0453: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16074: case 0454: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16075: case 0455: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16076: case 0456: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16077: case 0457: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; prior=0000; break;
16078: case 0460: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16079: case 0461: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16080: case 0462: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16081: case 0463: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16082: case 0464: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16083: case 0465: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16084: case 0466: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16085: case 0467: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; prior=0000; break;
16086: case 0470: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
16087: case 0471: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
16088: case 0472: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
16089: case 0473: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; prior=0000; break;
16090: case 0474: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+5; prior=0000; break;
16091: case 0475: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; prior=0000; break;
16092: case 0476: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+5; prior=0000; break;
16093: case 0477: *(xp++)=cb+5; prior=0000; break;
16094: case 0500: *(xp++)=cb-1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16095: case 0501: *(xp++)=cb; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16096: case 0502: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16097: case 0503: *(xp++)=cb+1; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16098: case 0504: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16099: case 0505: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16100: case 0506: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16101: case 0507: *(xp++)=cb+2; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16102: case 0510: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16103: case 0511: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16104: case 0512: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16105: case 0513: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16106: case 0514: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16107: case 0515: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16108: case 0516: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16109: case 0517: *(xp++)=cb+3; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16110: case 0520: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16111: case 0521: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16112: case 0522: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16113: case 0523: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16114: case 0524: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16115: case 0525: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16116: case 0526: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16117: case 0527: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16118: case 0530: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16119: case 0531: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16120: case 0532: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16121: case 0533: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16122: case 0534: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16123: case 0535: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16124: case 0536: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16125: case 0537: *(xp++)=cb+4; *(xp++)=cb+6; *(xp++)=cb+6; prior=0000; break;
16126: case 0540: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16127: case 0541: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16128: case 0542: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16129: case 0543: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16130: case 0544: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16131: case 0545: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16132: case 0546: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16133: case 0547: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16134: case 0550: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16135: case 0551: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16136: case 0552: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16137: case 0553: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16138: case 0554: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16139: case 0555: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16140: case 0556: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16141: case 0557: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+6; prior=0000; break;
16142: case 0560: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16143: case 0561: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16144: case 0562: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16145: case 0563: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16146: case 0564: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16147: case 0565: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16148: case 0566: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16149: case 0567: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; prior=0000; break;
16150: case 0570: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
16151: case 0571: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
16152: case 0572: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
16153: case 0573: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; prior=0000; break;
16154: case 0574: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+6; prior=0000; break;
16155: case 0575: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+6; prior=0000; break;
16156: case 0576: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+6; prior=0000; break;
16157: case 0577: *(xp++)=cb+6; prior=0000; break;
16158: case 0600: *(xp++)=cb-1; *(xp++)=cb+7; break;
16159: case 0601: *(xp++)=cb; *(xp++)=cb+7; break;
16160: case 0602: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+7; break;
16161: case 0603: *(xp++)=cb+1; *(xp++)=cb+7; break;
16162: case 0604: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; break;
16163: case 0605: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+7; break;
16164: case 0606: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+7; break;
16165: case 0607: *(xp++)=cb+2; *(xp++)=cb+7; break;
16166: case 0610: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
16167: case 0611: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
16168: case 0612: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
16169: case 0613: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+7; break;
16170: case 0614: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; break;
16171: case 0615: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+7; break;
16172: case 0616: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+7; break;
16173: case 0617: *(xp++)=cb+3; *(xp++)=cb+7; break;
16174: case 0620: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16175: case 0621: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16176: case 0622: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16177: case 0623: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16178: case 0624: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16179: case 0625: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16180: case 0626: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16181: case 0627: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+7; break;
16182: case 0630: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
16183: case 0631: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
16184: case 0632: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
16185: case 0633: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+7; break;
16186: case 0634: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; break;
16187: case 0635: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+7; break;
16188: case 0636: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+7; break;
16189: case 0637: *(xp++)=cb+4; *(xp++)=cb+7; break;
16190: case 0640: *(xp++)=cb-1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16191: case 0641: *(xp++)=cb; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16192: case 0642: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16193: case 0643: *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16194: case 0644: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16195: case 0645: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16196: case 0646: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16197: case 0647: *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16198: case 0650: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16199: case 0651: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16200: case 0652: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16201: case 0653: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16202: case 0654: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16203: case 0655: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16204: case 0656: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16205: case 0657: *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+5; *(xp++)=cb+7; break;
16206: case 0660: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16207: case 0661: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16208: case 0662: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16209: case 0663: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16210: case 0664: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16211: case 0665: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16212: case 0666: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16213: case 0667: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+5; *(xp++)=cb+7; break;
16214: case 0670: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
16215: case 0671: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
16216: case 0672: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
16217: case 0673: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; *(xp++)=cb+7; break;
16218: case 0674: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; break;
16219: case 0675: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+5; *(xp++)=cb+7; break;
16220: case 0676: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+5; *(xp++)=cb+7; break;
16221: case 0677: *(xp++)=cb+5; *(xp++)=cb+7; break;
16222: case 0700: *(xp++)=cb-1; *(xp++)=cb+6; break;
16223: case 0701: *(xp++)=cb; *(xp++)=cb+6; break;
16224: case 0702: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+6; break;
16225: case 0703: *(xp++)=cb+1; *(xp++)=cb+6; break;
16226: case 0704: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; break;
16227: case 0705: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+6; break;
16228: case 0706: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+6; break;
16229: case 0707: *(xp++)=cb+2; *(xp++)=cb+6; break;
16230: case 0710: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
16231: case 0711: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
16232: case 0712: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
16233: case 0713: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+6; break;
16234: case 0714: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; break;
16235: case 0715: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+6; break;
16236: case 0716: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+6; break;
16237: case 0717: *(xp++)=cb+3; *(xp++)=cb+6; break;
16238: case 0720: *(xp++)=cb-1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16239: case 0721: *(xp++)=cb; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16240: case 0722: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16241: case 0723: *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16242: case 0724: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16243: case 0725: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16244: case 0726: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16245: case 0727: *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+4; *(xp++)=cb+6; break;
16246: case 0730: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
16247: case 0731: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
16248: case 0732: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
16249: case 0733: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+4; *(xp++)=cb+6; break;
16250: case 0734: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
16251: case 0735: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+4; *(xp++)=cb+6; break;
16252: case 0736: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+4; *(xp++)=cb+6; break;
16253: case 0737: *(xp++)=cb+4; *(xp++)=cb+6; break;
16254: case 0740: *(xp++)=cb-1; *(xp++)=cb+5; break;
16255: case 0741: *(xp++)=cb; *(xp++)=cb+5; break;
16256: case 0742: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+5; break;
16257: case 0743: *(xp++)=cb+1; *(xp++)=cb+5; break;
16258: case 0744: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; break;
16259: case 0745: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+5; break;
16260: case 0746: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+5; break;
16261: case 0747: *(xp++)=cb+2; *(xp++)=cb+5; break;
16262: case 0750: *(xp++)=cb-1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
16263: case 0751: *(xp++)=cb; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
16264: case 0752: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
16265: case 0753: *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+3; *(xp++)=cb+5; break;
16266: case 0754: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; break;
16267: case 0755: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+3; *(xp++)=cb+5; break;
16268: case 0756: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+3; *(xp++)=cb+5; break;
16269: case 0757: *(xp++)=cb+3; *(xp++)=cb+5; break;
16270: case 0760: *(xp++)=cb-1; *(xp++)=cb+4; break;
16271: case 0761: *(xp++)=cb; *(xp++)=cb+4; break;
16272: case 0762: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+4; break;
16273: case 0763: *(xp++)=cb+1; *(xp++)=cb+4; break;
16274: case 0764: *(xp++)=cb-1; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; break;
16275: case 0765: *(xp++)=cb; *(xp++)=cb+2; *(xp++)=cb+2; *(xp++)=cb+4; break;
16276: case 0766: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+2; *(xp++)=cb+4; break;
16277: case 0767: *(xp++)=cb+2; *(xp++)=cb+4; break;
16278: case 0770: *(xp++)=cb-1; *(xp++)=cb+3; break;
16279: case 0771: *(xp++)=cb; *(xp++)=cb+3; break;
16280: case 0772: *(xp++)=cb-1; *(xp++)=cb+1; *(xp++)=cb+1; *(xp++)=cb+3; break;
16281: case 0773: *(xp++)=cb+1; *(xp++)=cb+3; break;
16282: case 0774: *(xp++)=cb-1; *(xp++)=cb+2; break;
16283: case 0775: *(xp++)=cb; *(xp++)=cb+2; break;
16284: case 0776: *(xp++)=cb-1; *(xp++)=cb+1; break;
16285: case 0777: break;
16286:
16287: /* contents of jslr.c1 come above here */
16288: };
16289: cb += 8;
16290: }
16291: while(bp<ep);
16292: /* restore margin bytes */
16293: *lbp = svlb;
16294: *rbp = svrb;
16295: *(rbp+1) = svrrb;
16296: return((xp-runp)/2);
16297: };
16298: 0707070035350320511006640007620000050000010263540476773367200001100000001652limits.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
16299: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
16300: /* The copyright notice does not imply actual or intended publication. */
16301: /* AUTHORS: */
16302: /* H. S. Baird - ATT-BL MH - first versions */
16303: /* Extreme values of integral types (conforms to Oct 1, 86 draft ANSI C std) */
16304: #define CHAR_BIT 8
16305: #define SCHAR_MIN -128
16306: #define SCHAR_MAX 127
16307: #define UCHAR_MIN 0
16308: #define UCHAR_MAX 255
16309: #define CHAR_MIN SCHAR_MIN /* type char sign-extends */
16310: #define CHAR_MAX SCHAR_MAX /* type char sign-extends */
16311:
16312: #define SHRT_MIN -32768
16313: #define SHRT_MAX 32767
16314: #define USHRT_MIN 0
16315: #define USHRT_MAX 65535
16316:
16317: #define INT_MIN -2147483648
16318: #define INT_MAX 2147483647
16319: #define UINT_MIN 0
16320: #define UINT_MAX 4294967295
16321:
16322: #define LONG_MIN -2147483648
16323: #define LONG_MAX 2147483647
16324: #define ULONG_MIN 0
16325: #define ULONG_MAX 4294967295
16326: 0707070035351106241006640007620000050000010263560476773367300001000000025436myftw.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
16327: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
16328: /* The copyright notice does not imply actual or intended publication. */
16329: /* AUTHORS: */
16330: /* H. S. Baird - ATT-BL MH - first versions */
16331: /*
16332: * ftw - file tree walk
16333: *
16334: * int ftw (path, fn, depth) char *path; int (*fn)(); int depth;
16335: *
16336: * Given a path name, ftw starts from the file given by that path
16337: * name and visits each file and directory in the tree beneath
16338: * that file. If a single file has multiple links within the
16339: * structure, it will be visited once for each such link.
16340: * For each object visited, fn is called with four arguments.
16341: * The fourth can often be ignored; it is a pointer, say S,
16342: * declared "struct FTW *S", discussed in more detail below.
16343: * The first contains the path name of the object, the second
16344: * contains a pointer to a stat buffer which will usually hold
16345: * appropriate information for the object and the third contains
16346: * an integer value giving additional information about the
16347: * object, as follows:
16348: *
16349: * FTW_F The object is a file for which stat was
16350: * successful. It does not guarantee that the
16351: * file can actually be read.
16352: *
16353: * FTW_D The object is a directory for which stat and
16354: * open for read were both successful. This is
16355: * a preorder visit -- objects in the directory
16356: * are yet to be visited.
16357: *
16358: * FTW_DNR The object is a directory for which stat
16359: * succeeded, but which cannot be read. Because
16360: * the directory cannot be read, fn will not be
16361: * called for any descendants of this directory.
16362: *
16363: * FTW_DP The object is a directory for which stat and
16364: * open for read were both successful. This is
16365: * a postorder visit -- everything in the directory
16366: * has already been visited.
16367: *
16368: * FTW_NS Lstat failed on the object. If errno is EACCES,
16369: * then the failure stems from lack of
16370: * appropriate permission. This indication will
16371: * be given, for example, for each file in a directory
16372: * with read but no execute permission. Whenever
16373: * stat fails, it is not possible to determine
16374: * whether this object is a file or a directory.
16375: * The stat buffer passed to fn will contain garbage.
16376: *
16377: * FTW_SL The object is a symbolic link. Set S->quit
16378: * (a component of the structure pointed to by
16379: * the fourth parameter to fn) to FTW_FOLLOW to
16380: * have the link followed and the object to which
16381: * it points visited.
16382: *
16383: * FTW_NSL Lstat succeeded, but stat failed on the object.
16384: * This is only possible when following a symbolic
16385: * link.
16386: *
16387: * Among the components of the structure to which the fourth
16388: * parameter, S, to fn points is S->quit. If the caller sets
16389: * S->quit to FTW_SKR, then no more files in the current directory
16390: * will be visited. (The current directory is the one containing
16391: * the object being visited.) If the third parameter to fn is
16392: * FTW_D and the caller sets S->quit to FTW_SKD, then this directory
16393: * (the one named in the first parameter to fn) will be skipped.
16394: *
16395: * Other components pointed to by the fourth parameter S are
16396: * the current recursion level S->level (top level = 0) and
16397: * the offset S->base in the pathname of the current object
16398: * (the first parameter to fn) of the object's base name.
16399: * By expanding the definition of struct FTW given below and
16400: * including the files included below, one can arrange for
16401: * S to point to a larger structure, components of which can
16402: * be initialized (for example) on calls to fn with third
16403: * parameter FTW_D.
16404: *
16405: * If fn returns nonzero, ftw stops and returns the same value
16406: * to its caller. Ftw only initiates a nonzero return if malloc
16407: * fails; in this case ftw sets errno to ENOMEM and returns -1.
16408: *
16409: * The third argument to ftw does not limit the depth to which
16410: * ftw will go. Rather, it limits the depth to which ftw will
16411: * go before it starts recycling file descriptors. In general,
16412: * it is necessary to use a file descriptor for each level of the
16413: * tree, but they can be recycled for deep trees by saving the position,
16414: * closing, re-opening, and seeking. It is possible to start
16415: * recycling file descriptors by sensing when we have run out, but
16416: * in general this will not be terribly useful if fn expects to be
16417: * able to open files. We could also figure out how many file descriptors
16418: * are available and guarantee a certain number to fn, but we would not
16419: * know how many to guarantee, and we do not want to impose the extra
16420: * overhead on a caller who knows how many are available without
16421: * having to figure it out.
16422: *
16423: * It is possible for ftw to die with a memory fault in the event
16424: * of a file system so deeply nested that the stack overflows.
16425: */
16426:
16427: #include <sys/types.h>
16428: #include <sys/stat.h>
16429: #include "myftw.h" /* not <ftw.h>, for portability to Suns */
16430: /*
16431: * Struct FTW (whose definition starts at the end of ftw.h) must
16432: * must include at least the integers quit, base, and level.
16433: */
16434:
16435: #define FTW_PATHLEN0 1000
16436: #define FTW_PATHINC 1000
16437: #ifndef S_IFLNK
16438: #define lstat stat
16439: #endif
16440: #ifdef S_IFSOCK
16441: #include <sys/dir.h>
16442: #else
16443: #include "ndir.h"
16444: #endif
16445: #ifndef ENOMEM
16446: #include <errno.h>
16447: #endif
16448:
16449: extern int errno;
16450:
16451: /*
16452: * Each generation of ftw1 (the real ftw) allocates one copy, R, of the
16453: * following structure; it passes a pointer to this structure when it
16454: * recursively invokes itself. These structures are chained together,
16455: * so that if it becomes necessary to recycle file descriptors, then
16456: * the oldest descriptor (the one at the shallowest depth still open)
16457: * can be recycled.
16458: */
16459:
16460: struct FTW_rec {
16461: struct FTW_rec *prev;
16462: long here; /* seek to here when reopening at this level */
16463: DIR *fd; /* file descriptor at this level */
16464: };
16465:
16466: /*
16467: * One instance, T, of the following structure is allocated by ftw; a
16468: * pointer to it is passed to all generations of ftw1 (the real ftw).
16469: * T could often be a global variable, but this way the parameter fn
16470: * can invoke ftw for an independent tree walk.
16471: * Component T->path points to storage for the object path-names;
16472: * this storage may be relocated by realloc if T->path needs to be
16473: * more than T->pathlast characters long.
16474: * T->path[T->pathnext] is the next free character in the pathnames.
16475: * T->depth = parameter depth to ftw. T->lastout is the deepest level at
16476: * which a file descriptor has been recycled.
16477: */
16478:
16479: struct FTW_top {
16480: int (*fn)();
16481: char *path;
16482: unsigned pathlast, pathnext;
16483: int lastout;
16484: int depth;
16485: };
16486:
16487: static ftw_1_();
16488:
16489: int
16490: ftw (path, fn, depth)
16491: char *path;
16492: int (*fn)();
16493: int depth;
16494: {
16495: struct FTW_top T;
16496: struct FTW_rec R;
16497: struct FTW S;
16498: int rc;
16499: char *malloc(), *strcpy();
16500:
16501: T.depth = depth;
16502: T.lastout = -1;
16503: T.fn = fn;
16504: S.quit = 0;
16505: S.level = -1;
16506:
16507: /* initialize S.base, T.pathnext... */
16508: {
16509: register char c, *p, *q;
16510: for (p = q = path; c = *p; p++) if (c == '/') q = p + 1;
16511: S.base = q - path;
16512: T.pathnext = p - path;
16513: }
16514:
16515: T.pathlast = T.pathnext + FTW_PATHLEN0;
16516: T.path = malloc(T.pathlast);
16517: if (!T.path) { errno = ENOMEM; return -1; }
16518: strcpy(T.path, path);
16519: rc = ftw_1_(&R, &T, 0, &S);
16520: free(T.path);
16521: return rc;
16522: }
16523:
16524: int
16525: static
16526: ftw_1_ (R, T, level, S1)
16527: register struct FTW_rec *R;
16528: register struct FTW_top *T;
16529: int level;
16530: struct FTW *S1;
16531: {
16532: int rc, n;
16533: DIR *fd;
16534: struct direct *dirp;
16535: char *component, *path;
16536: struct stat sb;
16537: struct FTW_rec mr;
16538: unsigned nextsave;
16539: struct FTW S;
16540: char *realloc();
16541: long lseek();
16542:
16543: mr.prev = R;
16544: path = T->path;
16545: S.level = level;
16546: S.quit = 0;
16547: S.base = S1->base;
16548:
16549: /* Try to get file status. If unsuccessful, errno will say why. */
16550: if (lstat(path, &sb) < 0) {
16551: rc = (*T->fn) (path, &sb, FTW_NS, &S);
16552: S1->quit = S.quit;
16553: return rc;
16554: };
16555:
16556: /*
16557: * The stat succeeded, so we know the object exists.
16558: * If not a directory, call the user function and return.
16559: */
16560: #ifdef S_IFLNK
16561: if ((sb.st_mode & S_IFMT) == S_IFLNK) {
16562: rc = (*T->fn) (path, &sb, FTW_SL, &S);
16563: S1->quit = S.quit;
16564: if (rc || S.quit == FTW_SKR) return rc;
16565: if (S.quit != FTW_FOLLOW) return 0;
16566: S1->quit = S.quit = 0;
16567: if (stat(path, &sb) < 0) {
16568: rc = (*T->fn) (path, &sb, FTW_NSL, &S);
16569: S1->quit = S.quit;
16570: return rc;
16571: };
16572: }
16573: #endif
16574:
16575: if ((sb.st_mode & S_IFMT) != S_IFDIR) {
16576: rc = (*T->fn) (path, &sb, FTW_F, &S);
16577: S1->quit = S.quit;
16578: return rc;
16579: }
16580:
16581: /*
16582: * The object was a directory.
16583: *
16584: * Open a file to read the directory
16585: */
16586: mr.fd = fd = opendir(path);
16587:
16588: /*
16589: * Call the user function, telling it whether
16590: * the directory can be read. If it can't be read
16591: * call the user function or indicate an error,
16592: * depending on the reason it couldn't be read.
16593: */
16594: if (!fd) {
16595: rc = (*T->fn) (path, &sb, FTW_DNR, &S);
16596: S1->quit = S.quit;
16597: return rc;
16598: }
16599:
16600: /* We could read the directory. Call user function. */
16601: rc = (*T->fn) (path, &sb, FTW_D, &S);
16602: if (rc != 0)
16603: goto rtrn;
16604: if (S.quit == FTW_SKD) goto rtrn;
16605: if (S.quit == FTW_SKR) {S1->quit = FTW_SKR; goto rtrn;}
16606:
16607: /* Make sure path is big enough to hold generated pathnames. */
16608:
16609: n = nextsave = T->pathnext;
16610: if (n + MAXNAMLEN + 1 >= T->pathlast) {
16611: T->pathlast += FTW_PATHINC;
16612: path = T->path = realloc(T->path, T->pathlast);
16613: if (!path) {
16614: errno = ENOMEM;
16615: rc = -1;
16616: goto rtrn;
16617: }
16618: }
16619:
16620: /* Create a prefix to which we will append component names */
16621:
16622: if (n > 0 && path[n-1] != '/') path[n++] = '/';
16623: component = path + n;
16624:
16625: /*
16626: * Read the directory one component at a time.
16627: * We must ignore "." and "..", but other than that,
16628: * just create a path name and call self to check it out.
16629: */
16630: while (dirp = readdir(fd)) {
16631: if (dirp->d_ino != 0
16632: && strcmp (dirp->d_name, ".") != 0
16633: && strcmp (dirp->d_name, "..") != 0) {
16634: int i;
16635: struct FTW_rec *pr;
16636:
16637: /* Append the component name to the working path */
16638: strcpy(component, dirp->d_name);
16639: T->pathnext = n + strlen(dirp->d_name);
16640:
16641: /*
16642: * If we are about to exceed our depth,
16643: * remember where we are and close the file.
16644: */
16645: if (level - T->lastout >= T->depth) {
16646: pr = &mr;
16647: i = T->lastout++;
16648: while (++i < level) pr = pr->prev;
16649: pr->here = telldir(pr->fd);
16650: closedir(pr->fd);
16651: }
16652:
16653: /*
16654: * Do a recursive call to process the file.
16655: */
16656: S.quit = 0;
16657: S.base = n;
16658: rc = ftw_1_(&mr, T, level+1, &S);
16659: if (rc != 0 || S.quit == FTW_SKR) {
16660: if (level > T->lastout) closedir(fd);
16661: T->pathnext = nextsave;
16662: return rc;
16663: }
16664:
16665: /*
16666: * If we closed the file, try to reopen it.
16667: */
16668: if (level <= T->lastout) {
16669: char c = path[nextsave];
16670: path[nextsave] = 0;
16671: T->lastout = level - 1;
16672: mr.fd = fd = opendir(path);
16673: if (!fd) {
16674: rc = (*T->fn) (path, &sb, FTW_DNR, &S);
16675: S1->quit = S.quit;
16676: T->pathnext = nextsave;
16677: return rc;
16678: }
16679: path[nextsave] = c;
16680: seekdir(fd, mr.here);
16681: }
16682: }
16683: }
16684: T->pathnext = nextsave;
16685: path[nextsave] = 0;
16686:
16687: /*
16688: * We got out of the subdirectory loop. Call the user
16689: * function again at the end and clean up.
16690: */
16691:
16692: rc = (*T->fn) (path, &sb, FTW_DP, &S);
16693: S1->quit = S.quit;
16694: rtrn:
16695: closedir(fd);
16696: return rc;
16697: }
16698: 0707070035350320551006640007620000050000010263640476773367300001000000002137myftw.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
16699: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
16700: /* The copyright notice does not imply actual or intended publication. */
16701: /* AUTHORS: */
16702: /* H. S. Baird - ATT-BL MH - first versions */
16703: /*
16704: * Codes for the third argument to the user-supplied function
16705: * which is passed as the second argument to ftw...
16706: */
16707:
16708: #define FTW_F 0 /* file */
16709: #define FTW_D 1 /* directory */
16710: #define FTW_DNR 2 /* directory without read permission */
16711: #define FTW_NS 3 /* unknown type, stat failed */
16712: #define FTW_DP 4 /* directory, postorder visit */
16713: #define FTW_SL 5 /* symbolic link */
16714: #define FTW_NSL 6 /* stat failed (errno = ENOENT) on symbolic link */
16715:
16716: /* Values the user-supplied function may wish to assign to
16717: component quit of struct FTW...
16718: */
16719:
16720: #define FTW_SKD 1 /* skip this directory (2nd par = FTW_D) */
16721: #define FTW_SKR 2 /* skip rest of current directory */
16722: #define FTW_FOLLOW 3 /* follow symbolic link */
16723:
16724: struct FTW { int quit, base, level;
16725: #ifndef FTW_more_to_come
16726: };
16727: #endif
16728: 0707070035350320571006640007620000050000010263660476773367300000600000003730pic.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
16729: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
16730: /* The copyright notice does not imply actual or intended publication. */
16731: /* AUTHORS: */
16732: /* H. S. Baird - ATT-BL MH - first versions */
16733:
16734: /* pic.h - picture files. See man page for picfile(5).
16735: They have an ascii header, terminated by \n\n; see PIC_hdr for its data fields.
16736: The rest is binary scanner data. Each `PIC_hdr.bpl' bytes holds one scan-line's
16737: pixels, 1 bit/pixel. A `1' bit means black. The order of the bytes in a line
16738: is left-to-right across the page. The low-order bit in a byte is the left-most.
16739: Conventionally, X-coordinates start at 0, at the left of the page, and
16740: increase to the right. Y-coordinates start at 0 at the top of the page,
16741: and increase down.
16742: NOTE: must be preceded by #include "Coord.h"
16743: */
16744:
16745: typedef struct PIC_hdr {
16746: /* Contents of picfile ASCII header (or other structure) */
16747: char type[40]; /* "rle" "dump" "binary" "ccitt-g4" "imdir" etc */
16748: Bbx bx; /* WINDOW (bounding box) */
16749: short res_x; /* resolution in pixels/inch (x,y may differ) */
16750: short res_y;
16751: char *parms; /* PARMS= string */
16752: char *misc; /* all other unexpected header lines, catenated */
16753: /* the following are used by I/O routines */
16754: FILE *fp;
16755: long seek; /* current seek address */
16756: int bpl; /* bytes per line (in file) */
16757: unsigned char *line; /* one line of picture (malloc space) */
16758: unsigned char *pline; /* prior line of picture (malloc space) */
16759: Scoor cy; /* index no. of *line */
16760: } PIC_hdr;
16761: #define Init_PIC_hdr {"",Init_Bbx,0,0,NULL,NULL,NULL,0L,0,NULL,NULL,0}
16762: #if MAIN
16763: PIC_hdr empty_PIC_hdr = Init_PIC_hdr;
16764: #else
16765: extern PIC_hdr empty_PIC_hdr;
16766: #endif
16767:
16768: /* these functions are in /usr/hsb/ocr/piclib.c */
16769: PIC_hdr *alloc_PIC_hdr();
16770: int PIC_get_hdr();
16771: PIC_put_hdr();
16772: err_PIC_line();
16773: PIC_skip();
16774: int PIC_rline();
16775: int PIC_wline();
16776: char *PIC_hdr_toa();
16777: 0707070035350320561006640007620000050000010263700476773367300001100000044413piclib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
16778: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
16779: /* The copyright notice does not imply actual or intended publication. */
16780: /* AUTHORS: */
16781: /* H. S. Baird - ATT-BL MH - first versions */
16782:
16783: /* piclib.c - picture-file public functions.
16784: alloc_PIC_hdr() - allocate initialized PIC_hdr, associate with FILE *
16785: free_PIC_hdr() - free PIC_hdr & all malloc'ed fields
16786: PIC_get_hdr() - get picture-file header
16787: PIC_rline() - read one line of picture data
16788: PIC_put_hdr() - get picture-file header
16789: PIC_wline() - write one line of picture data
16790: err_PIC_Line() - print line on stderr
16791: PIC_hdr_toa() - PIC_hdr to ascii printable string
16792: (PIC_* functions use system I/O, for speed)
16793: */
16794:
16795: #include <stdio.h>
16796: #include <math.h>
16797: #include <string.h>
16798: #include "boole.h"
16799: #include "limits.h" /* numeric extreme values */
16800: #include "Units.h"
16801: #include "Coord.h"
16802: #include "pic.h"
16803:
16804: #define PIC_debug (0)
16805: double atof();
16806:
16807: PIC_hdr *alloc_PIC_hdr( fp )
16808: FILE *fp; /* already-open file descr */
16809: { PIC_hdr *h;
16810: if((h=(PIC_hdr *)malloc(sizeof(PIC_hdr)))==NULL)
16811: abort("piclib: alloc_PIC_hdr: can't alloc");
16812: *h = empty_PIC_hdr;
16813: h->fp = fp;
16814: return(h);
16815: }
16816:
16817: free_PIC_hdr( h )
16818: PIC_hdr *h;
16819: { if(h->parms!=NULL) free(h->parms);
16820: if(h->line!=NULL) free(h->line);
16821: if(h->pline!=NULL) free(h->pline);
16822: if(h->misc!=NULL) free(h->misc);
16823: free(h);
16824: }
16825:
16826: /* system I/O variation on fgets(3), except it replaces \n with \0,
16827: and returns the number of chars read (including \0) */
16828: int PIC_fgets(bf,max,fd)
16829: char *bf;
16830: int max;
16831: int fd;
16832: { char *cp;
16833: int stat,mny;
16834: cp=bf; mny=0;
16835: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
16836: if(stat!=1) return(stat);
16837: else if(mny>=max) return(-1);
16838: *cp='\0';
16839: return(mny);
16840: }
16841:
16842: /* Read picture file header from file descr fileno(h->fp), set up the rest of the
16843: header, and return status: 1 OK, 0 EOF, <0 error */
16844: int PIC_get_hdr( h )
16845: PIC_hdr *h;
16846: #define HL_MAX 300
16847: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
16848: { char *cp,*parm,hline[HL_MAX],oline[HL_MAX],*hl;
16849: int status,nrd,ch,mny;
16850: /* synchronize FILE * ptr with file descr ptr */
16851: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
16852: hline[0]='\0';
16853: if((mny=read(fileno(h->fp),hline,5))!=5)
16854: return(0);
16855: if(!(hline[0]=='T' && hline[1]=='Y' && hline[2]=='P'
16856: && hline[3]=='E' && hline[4]=='=')) {
16857: /* no "TYPE=" header; don't accept */
16858: if(0) /* don't accept */ {
16859: if(PIC_debug)
16860: err("PIC_get_hdr: can't find TYPE=... header");
16861: return(-1);
16862: }
16863: else /* accept as bitfile format (OBSOLESCENT) */ {
16864: strcpy(h->type,"bitfile");
16865: h->res_x = h->res_y = 0;
16866: fseek(h->fp,h->seek+2L,0); /* back up to byte no. 2 */
16867: /* read window */
16868: if((ch=getc(h->fp))!=EOF) { h->bx.a.x = ch;
16869: if((ch=getc(h->fp))!=EOF) { h->bx.a.x += (ch<<8);
16870: if((ch=getc(h->fp))!=EOF) { h->bx.a.y = ch;
16871: if((ch=getc(h->fp))!=EOF) { h->bx.a.y += (ch<<8);
16872: if((ch=getc(h->fp))!=EOF) { h->bx.b.x = ch;
16873: if((ch=getc(h->fp))!=EOF) { h->bx.b.x += (ch<<8);
16874: if((ch=getc(h->fp))!=EOF) { h->bx.b.y = ch;
16875: if((ch=getc(h->fp))!=EOF) { h->bx.b.y += (ch<<8); }}}}}}}}
16876: else return(0/*EOF*/);
16877: h->bx.b.x--; h->bx.b.y--;
16878: /* synchronize file descr ptr with FILE * ptr */
16879: lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
16880: };
16881: }
16882: else {
16883: if((status=PIC_fgets(hline+5,HL_MAX-5,fileno(h->fp)))<=0)
16884: return(status);
16885: strcpy(oline,hline);
16886: hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
16887: while(strlen(hl)>1) {
16888: if(PIC_debug) err("PIC_get_hdr: hl \"%s\"",hl);
16889: parm=strtok(hl,HTERM);
16890: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
16891: if((parm=strtok(0,HTERM))!=NULL) {
16892: strcpy(h->type,parm);
16893: if( (strcmp(h->type,"dump")==0)
16894: || (strcmp(h->type,"pico")==0)
16895: || (strcmp(h->type,"rle")==0)
16896: || (strcmp(h->type,"binary")==0)
16897: || (strcmp(h->type,"bitmap")==0)
16898: || (strcmp(h->type,"dim")==0)
16899: || (strcmp(h->type,"document-image")==0)
16900: || (strcmp(h->type,"ccitt-g31")==0)
16901: || (strcmp(h->type,"ccitt-g32")==0)
16902: || (strcmp(h->type,"ccitt-g4")==0)
16903: || (strcmp(h->type,"cdf")==0)
16904: || (strcmp(h->type,"tiff")==0)
16905: ) /* these types are expected */ {
16906: if(PIC_debug)
16907: err("PIC_get_hdr: good TYPE=\"%s\"",h->type);
16908: }
16909: else { if(PIC_debug)
16910: err("PIC_get_hdr: unexpected TYPE=\"%s\"",h->type);
16911: return(-1);
16912: };
16913: }
16914: else { if(PIC_debug)
16915: err("PIC_get_hdr: 1st line must be TYPE=...");
16916:
16917: return(-1);
16918: };
16919: }
16920: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
16921: if((parm=strtok(0,HTERM))!=NULL) h->bx.a.x=atoi(parm);
16922: else return(-1);
16923: if((parm=strtok(0,HTERM))!=NULL) h->bx.a.y=atoi(parm);
16924: else return(-1);
16925: if((parm=strtok(0,HTERM))!=NULL) h->bx.b.x=atoi(parm)-1;
16926: else return(-1);
16927: if((parm=strtok(0,HTERM))!=NULL) h->bx.b.y=atoi(parm)-1;
16928: else return(-1);
16929: }
16930: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
16931: if((parm=strtok(0,HTERM))!=NULL)
16932: h->res_x=(int)(atof(parm)+0.5);
16933: else return(-1);
16934: if((parm=strtok(0,HTERM))!=NULL)
16935: h->res_y=(int)(atof(parm)+0.5);
16936: else return(-1);
16937: }
16938: else if(parm!=NULL&&strcmp(parm,"NCHAN")==0) {
16939: int nchan;
16940: if((parm=strtok(0,HTERM))!=NULL) nchan=atoi(parm);
16941: else return(-1);
16942: if(nchan!=1) {
16943: err("PIC_get_hdr: NCHAN=%d illegal: must be 1",nchan);
16944: return(-1);
16945: };
16946: }
16947: else if(parm!=NULL&&strcmp(parm,"PARMS")==0) {
16948: int nchan;
16949: if((parm=strtok(0,"\n"))!=NULL) {
16950: h->parms = strdup(parm);
16951: }
16952: else return(-1);
16953: }
16954: else if(parm!=NULL) {
16955: char *cat;
16956: /* save all header lines with unexpected keywords */
16957: if(h->misc==NULL) h->misc=(char *)malloc(strlen(oline)+2);
16958: else { cat=(char *)malloc(strlen(h->misc)+strlen(oline)+2);
16959: strcpy(cat,h->misc);
16960: free(h->misc);
16961: h->misc=cat;
16962: };
16963: strcat(h->misc,oline);
16964: strcat(h->misc,"\n");
16965: }
16966: else return(-1);
16967: if((status=PIC_fgets(hline,HL_MAX,fileno(h->fp)))<=0)
16968: return(status);
16969: strcpy(oline,hline);
16970: hl=hline; while(*hl==' ') hl++; /* strip initial blanks */
16971: };
16972: };
16973:
16974: if(strcmp(h->type,"cdf")==0) {
16975: int stat;
16976: /* Compund Document Format has binary header */
16977: /* synchronize FILE * ptr with file descr ptr */
16978: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
16979: if((stat=CDF_get_hdr(h)) != 1) return(stat);
16980: };
16981:
16982: if(strcmp(h->type,"tiff")==0) {
16983: int stat;
16984: /* Tagged Image File Format has abinary header */
16985: /* synchronize FILE * ptr with file descr ptr */
16986: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
16987: if((stat=TIFF_get_hdr(h)) != 1) return(stat);
16988: };
16989:
16990: /* may want to allocate a line buffer here */
16991: h->bpl = bbx_wid(&(h->bx));
16992: if(strcmp(h->type,"binary")==0)
16993: h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
16994: else if(strcmp(h->type,"bitfile")==0)
16995: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
16996: else if(strcmp(h->type,"bitmap")==0)
16997: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
16998: else if( strcmp(h->type,"rle")==0
16999: || strcmp(h->type,"dim")==0
17000: || strcmp(h->type,"document-image")==0
17001: || strcmp(h->type,"cdf")==0
17002: || strcmp(h->type,"cdf-mrlc")==0
17003: || strcmp(h->type,"cdf-g31")==0
17004: || strcmp(h->type,"cdf-g32")==0
17005: || strcmp(h->type,"cdf-g4")==0
17006: || strcmp(h->type,"tiff")==0 )
17007: h->bpl = 0;
17008: if(h->bpl==0) h->line = NULL;
17009: else { /* allocate one extra byte in line buffer as a favor to RLE */
17010: if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
17011: fprintf(stderr,
17012: "piclib: PIC_get_hdr: can't alloc h->line (%d bytes) - abort\n",
17013: h->bpl+1);
17014: return(-1);
17015: };
17016: memset(h->line,'\0',h->bpl);
17017: if(strcmp(h->type,"bitfile")==0) {
17018: if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
17019: fprintf(stderr,
17020: "piclib: PIC_get_hdr: can't alloc h->pline (%d bytes) - abort\n",
17021: h->bpl+1);
17022: return(-1);
17023: };
17024: };
17025: };
17026: h->cy = h->bx.a.y-1; /* just prior to 1st line */
17027: /* synchronize FILE * ptr with file descr ptr */
17028: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
17029: return(1);
17030: }
17031:
17032: /* Read next page from AT&T Image Director file header from file descr
17033: fileno(h->fp), set up the rest of the header, and return status:
17034: 1 OK, 0 EOF, <0 error */
17035: int CDF_next_page( h )
17036: PIC_hdr *h;
17037: { return(-1); /* unimplemented */
17038: }
17039:
17040: #define HASHEADER(h) ((strcmp((h)->type,"postscript")!=0&&strcmp((h)->type,"sunraster")!=0))
17041:
17042: /* Read AT&T Image Director file header from file descr fileno(h->fp),
17043: set up the rest of the header, and return status: 1 OK, 0 EOF, <0 error */
17044: int CDF_get_hdr( h )
17045: PIC_hdr *h;
17046: { char *cp,*parm,hline[HL_MAX];
17047: int status,nrd,ch,mny;
17048: #define dbg_cdf (0)
17049: typedef struct CDF_file {
17050: unsigned char raw[16];
17051: unsigned char op,np,at;
17052: unsigned int l1,l2,len;
17053: } CDF_file;
17054: typedef struct CDF_page {
17055: unsigned char raw[16];
17056: unsigned char op,pn,at;
17057: unsigned char f1,f2,f3,f4;
17058: unsigned int ptr;
17059: } CDF_page;
17060: typedef struct CDF_recd {
17061: unsigned char raw[16];
17062: unsigned char op,a1,a2,a3;
17063: unsigned int len;
17064: Bbx bx;
17065: } CDF_recd;
17066: CDF_file fh;
17067: CDF_page ph;
17068: CDF_recd rh;
17069:
17070: if(dbg_cdf) err("CDF_get_hdr: enter %s",PIC_hdr_toa(h));
17071: /* synchronize FILE * ptr with file descr ptr */
17072: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
17073: strcpy(h->type,"cdf");
17074:
17075: /* Read CDF File header */
17076: if(fread(fh.raw,1,16,h->fp)!=16) return(0);
17077: fh.op = fh.raw[0];
17078: fh.np = fh.raw[1];
17079: fh.at = fh.raw[2];
17080: fh.l1 = fh.raw[4]+256*fh.raw[5];
17081: fh.l2 = fh.raw[6]+256*fh.raw[7];
17082: fh.len = fh.raw[12]+256*(fh.raw[13]+256*(fh.raw[14]+256*fh.raw[15]));
17083: if(dbg_cdf) err("CDF_get_hdr: file hdr: op0x%x p%d at0x%x lim1:%u lim2:%u len%u",
17084: fh.op,fh.np,fh.at,fh.l1,fh.l2,fh.len);
17085: if(fh.op!=0xA0&&fh.op!=0xAF) abort("CDF_get_hdr: file must be CDF type");
17086: if(fh.np!=1) err("CDF_get_hdr: file has %d pages - ignore all but 1st",fh.np);
17087: switch(fh.at>>4) {
17088: case 0: h->res_x = h->res_y = 100; break;
17089: case 1: h->res_x = h->res_y = 200; break;
17090: case 2: h->res_x = h->res_y = 300; break;
17091: default: err("CDF_get_hdr: file has unknown resolution nibble 0x%x -- assume 400 dpi",fh.at>>4);
17092: h->res_x = h->res_y = 400;
17093: break;
17094: };
17095: h->bx.a.x = h->bx.a.y = 0;
17096: h->bx.b.x = fh.l1;
17097: h->bx.b.y = fh.l2;
17098: if(fh.op==0xAF) {
17099: abort("CDF_get_hdr: file has continuation header");
17100: };
17101:
17102: /* Read 1st page table entry */
17103: if(fread(ph.raw,1,16,h->fp)!=16) return(0);
17104: ph.op = ph.raw[0];
17105: ph.pn = ph.raw[1];
17106: ph.at = ph.raw[2];
17107: ph.ptr = ph.raw[12]+256*(ph.raw[13]+256*(ph.raw[14]+256*ph.raw[15]));
17108: if(dbg_cdf) err("CDF_get_hdr: page hdr: op0x%x p%d at0x%x ptr%u",
17109: ph.op,ph.pn,ph.at,ph.ptr);
17110: if(ph.op!=0x80&&ph.op!=0x8F)
17111: abort("CDF_get_hdr: page opcode 0x%x is peculiar",ph.op);
17112: if(ph.pn!=1) err("CDF_get_hdr: page %d out of order - read anyway",ph.pn);
17113: switch(ph.at&0x0F) { /* low nibble */
17114: case 0: /* portrait */ break;
17115: case 1: /* landscape */
17116: default: err("CDF_get_hdr: page has peculiar format nibble 0x%x -- assume 40portrait",ph.at&0x0F);
17117: break;
17118: };
17119: switch(ph.at>>4) { /* high nibble */
17120: case 0xF: /* background is white */ break;
17121: default: err("CDF_get_hdr: page has peculiar color nibble 0x%x -- assume white",ph.at>>4);
17122: break;
17123: };
17124: /* seek top of Page */
17125: fseek(h->fp,h->seek+=ph.ptr,0);
17126:
17127: /* Read CDF Record header */
17128: if(fread(rh.raw,1,16,h->fp)!=16) return(0);
17129: rh.op = rh.raw[0];
17130: rh.a1 = rh.raw[1];
17131: rh.a2 = rh.raw[2];
17132: rh.a3 = rh.raw[3];
17133: rh.len = rh.raw[4]+256*rh.raw[5];
17134: rh.bx.a.x = rh.raw[8]+256*rh.raw[9];
17135: rh.bx.a.y = rh.raw[10]+256*rh.raw[11];
17136: rh.bx.b.x = rh.raw[12]+256*rh.raw[13];
17137: rh.bx.b.y = rh.raw[14]+256*rh.raw[15];
17138: if(dbg_cdf) err("CDF_get_hdr: record hdr: op0x%x a0x%x,0x%x,0x%x len%u bx%s",
17139: rh.op,rh.a1,rh.a2,rh.a3,rh.len,bbx_toa(&rh.bx));
17140: switch(rh.op) {
17141: case 0x20: /* Image */ break;
17142: case 0x01: /* End of Page */
17143: case 0x10: /* Text */
17144: case 0x1F: /* Text + cont. */
17145: case 0x50: /* Text Document */
17146: case 0x5F: /* Text Document + cont. */
17147: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44:
17148: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4A:
17149: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F:
17150: /* Graphics */
17151: default:
17152: abort("CDF_get_hdr: record not Image");
17153: };
17154: if(rh.a2!=0x01) err("CDF_get_hdr: record not opaque - assume opaque");
17155: switch(rh.a3&0x0F) { /* compression algorithm */
17156: case 1: /* modified run-length code */
17157: strcat(h->type,"-mrlc");
17158: break;
17159: case 0: /* raw */
17160: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
17161: break;
17162: case 2: /* ccitt_g31 */
17163: strcat(h->type,"-g31");
17164: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
17165: break;
17166: case 3: /* ccitt_g32 or ccitt_g4 */
17167: strcat(h->type,"-g32");
17168: abort("CDF_get_hdr: record compression 0x%x is legal but unsupported",rh.a3&0x0F);
17169: break;
17170: default:
17171: abort("CDF_get_hdr: record compression 0x%x is peculiar",rh.a3&0x0F);
17172: break;
17173: };
17174: switch(rh.a3>>4) { /* resolution */
17175: case 0:
17176: h->res_y = 100;
17177: break;
17178: case 1:
17179: h->res_y = 200;
17180: break;
17181: case 2:
17182: h->res_y = 300;
17183: break;
17184: default:
17185: err("CDF_get_hdr: record vert resolution peculiar 0x%x - assume 200 dpi",
17186: rh.a3>>4);
17187: h->res_y = 200;
17188: break;
17189: };
17190: /* synchronize file descr ptr with FILE * ptr */
17191: lseek(fileno(h->fp),h->seek = ftell(h->fp),0);
17192: if(dbg_cdf) err("CDF_get_hdr: normal exit %s",PIC_hdr_toa(h));
17193: return(1);
17194: }
17195:
17196: /* Read Tagged Image Format File (TIFF) header, from file descr fileno(h->fp),
17197: set up the rest of the PIC header, and return status: 1 OK, 0 EOF, <0 error */
17198: int TIFF_get_hdr( h )
17199: PIC_hdr *h;
17200: { err("TIFF not yet supported");
17201: return(-1);
17202: }
17203:
17204: /* Write header to picture file, to file descriptor fileno(h->fp), and initialize
17205: line buffer and cy. */
17206: PIC_put_hdr( h )
17207: PIC_hdr *h;
17208: { char *cp,*parm,hline[HL_MAX];
17209: int status,nrd;
17210: unsigned short s;
17211: #define put_ushort(S) { s=(S); putc(s&0377,h->fp); putc(s>>8,h->fp); }
17212:
17213: /* write type header */
17214: if( strcmp(h->type,"bitfile")==0 ) { /* bitfile header */
17215: put_ushort(0);
17216: }
17217: else if(HASHEADER(h)) {
17218: sprintf(hline,"TYPE=%s\n",h->type);
17219: write(fileno(h->fp),hline,strlen(hline));
17220: };
17221: if(strcmp(h->type,"pico")==0
17222: || strcmp(h->type,"dump")==0) {
17223: sprintf(hline,"NCHAN=1\n");
17224: write(fileno(h->fp),hline,strlen(hline));
17225: };
17226:
17227: /* write window */
17228: h->bpl = bbx_wid(&(h->bx));
17229: if(strcmp(h->type,"binary")!=0
17230: && strcmp(h->type,"bitfile")!=0
17231: && strcmp(h->type,"bitmap")!=0
17232: && HASHEADER(h)) {
17233: sprintf(hline,"WINDOW=%d %d %d %d\n",
17234: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
17235: write(fileno(h->fp),hline,strlen(hline));
17236: }
17237: else if(strcmp(h->type,"binary")==0) {
17238: h->bpl = (h->bpl+7)/8; /* round up to byte boundary */
17239: sprintf(hline,"WINDOW=%d %d %d %d\n",
17240: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
17241: write(fileno(h->fp),hline,strlen(hline));
17242: }
17243: else if(strcmp(h->type,"bitmap")==0) {
17244: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
17245: sprintf(hline,"WINDOW=%d %d %d %d\n",
17246: h->bx.a.x,h->bx.a.y,h->bx.b.x+1,h->bx.b.y+1);
17247: write(fileno(h->fp),hline,strlen(hline));
17248: }
17249: else if(strcmp(h->type,"sunraster")!=0 ) { /* bitfile window */
17250: h->bpl = 2*((h->bpl+15)/16); /* round up to 2-byte boundary */
17251: put_ushort(h->bx.a.x); put_ushort(h->bx.a.y);
17252: put_ushort(h->bx.b.x+1); put_ushort(h->bx.b.y+1);
17253: fflush(h->fp);
17254: };
17255: if( ((h->res_x!=0||h->res_y!=0)) && (HASHEADER(h))
17256: && strcmp(h->type,"bitfile")!=0 ) {
17257: sprintf(hline,"RES=%d %d\n",h->res_x,h->res_y);
17258: write(fileno(h->fp),hline,strlen(hline));
17259: };
17260: if(h->parms!=NULL && strlen(h->parms)>0 && strcmp(h->type,"bitfile")!=0 ) {
17261: sprintf(hline,"PARMS=%s\n",h->parms);
17262: write(fileno(h->fp),hline,strlen(hline));
17263: };
17264: if(h->misc!=NULL && strlen(h->misc)>0 && strcmp(h->type,"bitfile")!=0 ) {
17265: write(fileno(h->fp),h->misc,strlen(h->misc));
17266: };
17267: /* terminating blank line */
17268: if( HASHEADER(h) && strcmp(h->type,"bitfile")!=0 ) {
17269: hline[0] = '\n';
17270: write(fileno(h->fp),hline,1);
17271: };
17272:
17273: if(strcmp(h->type,"rle")==0) { h->bpl = 0; h->line = NULL; }
17274: else { /* allocate one extra byte in line buffer as a favor to RLE */
17275: if((h->line = (unsigned char *) malloc(h->bpl+1))==NULL) {
17276: fprintf(stderr,
17277: "piclib: PIC_put_hdr: can't alloc h->line (%d bytes) - abort\n",
17278: h->bpl+1);
17279: return(-1);
17280: };
17281: if(strcmp(h->type,"bitfile")==0) {
17282: memset(h->line,'\0',h->bpl);
17283: if((h->pline = (unsigned char *) malloc(h->bpl+1))==NULL) {
17284: fprintf(stderr,
17285: "piclib: PIC_put_hdr: can't alloc h->pline (%d bytes) - abort\n",
17286: h->bpl+1);
17287: return(-1);
17288: };
17289: };
17290: };
17291: h->cy = h->bx.a.y-1; /* just prior to 1st line */
17292: /* synchronize FILE * ptr with file descr ptr */
17293: fseek(h->fp,h->seek = lseek(fileno(h->fp),0L,1),0);
17294: }
17295:
17296: err_PIC_line(h,sl)
17297: PIC_hdr *h;
17298: char *sl;
17299: #define BPL 20 /* bytes to display per line */
17300: { char *cp,*ep;
17301: int bpl; /* bytes per display line */
17302: bpl=0;
17303: for(cp=sl,ep=sl+h->bpl; cp!=ep; cp++) {
17304: fprintf(stderr,"%o ",0377&(*cp));
17305: if((++bpl)%BPL==0) fprintf(stderr,"\n ");
17306: };
17307: if((bpl)%BPL!=0)fprintf(stderr,"\n");
17308: }
17309:
17310: /* Skip `y' lines of PIC file */
17311: PIC_skip(h,y)
17312: PIC_hdr *h;
17313: int y;
17314: { lseek(fileno(h->fp),(long)(y*h->bpl),1);
17315: h->seek += y*h->bpl;
17316: h->cy += y;
17317: }
17318:
17319: /* Read next full line of picture data, and if OK update line & cy;
17320: return status: 1 OK, 0 EOF, -1 ERR.
17321: Free buffer in header on EOF. */
17322: int PIC_rline(h,lbpp)
17323: PIC_hdr *h;
17324: unsigned char **lbpp;
17325: { int stat;
17326: if( (stat=read(fileno(h->fp),h->line,h->bpl)) == h->bpl) {
17327: *lbpp=h->line;
17328: h->seek += h->bpl;
17329: h->cy++;
17330: if(PIC_debug) err("read %d bytes from fileno(h->fp) - OK",stat);
17331: return(1);
17332: }
17333: else { /* EOF or ERR */
17334: *lbpp=NULL;
17335: free(h->line); h->line = NULL;
17336: if(PIC_debug) err("read from fileno(h->fp) stat%d",stat);
17337: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
17338: else return(-1);
17339: };
17340: }
17341:
17342: /* write a full line of picture data, returning status: 1 OK, 0 EOF, -1 ERR */
17343: int PIC_wline(h,line)
17344: PIC_hdr *h;
17345: unsigned char *line;
17346: { int stat;
17347: if( (stat=write(fileno(h->fp),line,h->bpl)) == h->bpl) {
17348: h->seek += h->bpl;
17349: h->cy++;
17350: if(PIC_debug) err("wrote %d bytes to fd%d - OK",stat,fileno(h->fp));
17351: return(1);
17352: }
17353: else { /* ERR */
17354: err("write to fd%d stat%d",fileno(h->fp),stat);
17355: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
17356: else return(-1);
17357: };
17358: }
17359:
17360: char *PIC_hdr_toa(h)
17361: PIC_hdr *h;
17362: { static char s[120];
17363: sprintf(s,"{type=%s bx%s res%d,%d bpl%d cy%d sk%d}",
17364: h->type,
17365: bbx_toa(&(h->bx)),
17366: h->res_x,h->res_y,
17367: h->bpl,
17368: h->cy,
17369: h->seek
17370: );
17371: return(s);
17372: }
17373: 0707070035351135641006640007620000050000010264030476773367300001200000032256postlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
17374: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
17375: /* The copyright notice does not imply actual or intended publication. */
17376: /* AUTHORS: */
17377: /* T. Thompson - ATT-BL HO - first versions */
17378: /* Routines for generating PostScript from RLE. */
17379: /* The routines at the bottom of this file, which */
17380: /* do the actual conversion to postscript, were */
17381: /* hacked out of 'sun2ps'. The original header */
17382: /* giving credit to its authors is there. */
17383:
17384: /* The 'binary' version of the output is collected in a */
17385: /* temporary file, which is then fed back to the routines */
17386: /* that generate postscript in a run-length-encoded form. */
17387: /* Ideally it should just convert the original run-length */
17388: /* encoding directly, but the REAL bottleneck is the */
17389: /* PostScript printer, of course. Printing an 800 by 800 */
17390: /* pixel image takes 5 minutes. */
17391:
17392: #include <stdio.h>
17393: #include <math.h>
17394: #include <string.h>
17395: #include "CPU.h"
17396: #include "boole.h"
17397: #include "limits.h" /* numeric extreme values */
17398: #include "Units.h"
17399: #include "Coord.h"
17400: #include "pic.h"
17401:
17402: FILE *Fp, *tmpfile();
17403: int Raswidth;
17404: int Raslength;
17405: int Rasbytes; /* bytes per row */
17406: int Inv = 0;
17407: int Aspect = 1; /* if non-zero, retain original aspect ratio */
17408: int Land = 0; /* if non-zero, print in landscape mode */
17409: char Revbyte[256];
17410: /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
17411: char Revnib[16] = {
17412: 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
17413: };
17414:
17415: void
17416: POST_start(h)
17417: PIC_hdr *h;
17418: {
17419: int n, v;
17420:
17421: /* build a table of reversed bytes */
17422: for ( n=0; n<256; n++ )
17423: Revbyte[n] = Revnib[(n>>4)&0xf] | Revnib[n&0xf]<<4;
17424:
17425: h->bpl = (h->bpl+7)/8;
17426: Rasbytes = h->bpl;
17427: Raslength = h->bpl * h->bx.b.y;
17428: Raswidth = h->bx.b.x;
17429: postmain(1,NULL,Raswidth,h->bx.b.y);
17430: #if CPU==SUN
17431: Fp = tmpfile();
17432: #else
17433: Fp = fopen("tmp.postlib.0","rw");
17434: #endif
17435: }
17436:
17437: void
17438: POST_end()
17439: {
17440: int c;
17441: rewind(Fp);
17442: (VOID) Encode(Raslength, Inv);
17443: PrintPostScriptClosing();
17444: fclose(Fp);
17445: }
17446:
17447: /* write a full line of picture data, returning status: 1 OK, 0 EOF, -1 ERR */
17448: int POST_wline(h,line)
17449: PIC_hdr *h;
17450: unsigned char *line;
17451: { int stat;
17452: if( (stat=fwrite(line,1,h->bpl,Fp)) == h->bpl) {
17453: h->seek += h->bpl;
17454: h->cy++;
17455: return(1);
17456: }
17457: else { /* ERR */
17458: err("write to fd%d stat%d",fileno(h->fp),stat);
17459: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
17460: else return(-1);
17461: };
17462: }
17463:
17464: /******************************************************************************
17465: * *
17466: * File: sun2ps.c *
17467: * Author: Glenn Boysko *
17468: * Organization: Case Western Reserve University *
17469: * EMail: {decvax, sun}!mandrill!boysko *
17470: * [email protected] *
17471: * Created: Wed Mar 23 9:25pm *
17472: * Contents: Sun Rasterfile to PostScript image (using a run-length *
17473: * encoding scheme.) *
17474: * *
17475: * (Adapted from "postimage" filter by J. R. Bammi.) *
17476: * *
17477: * @(#)sun2ps.c 1.8
17478: ******************************************************************************/
17479:
17480: /*
17481: * Usage:
17482: * sun2ps [-s sizex sizey] [-t transx transy] [-r rot] [-l] [-i] [-a] file ...
17483: *
17484: * -s sizex sizey = size of postscript image - default 7.5 x 10 inches.
17485: * -t transx transy = translate image - default 0.5 0.5 inches
17486: * -r rotate = rotate image - default 0 degress
17487: * -l = landscape (overrides *all* settings.)
17488: * -i = inverse image - default no inverse
17489: * (Inverse enabled implies white on black.)
17490: * -a = maintain correct aspect ratio - default none.
17491: *
17492: */
17493:
17494: /* Sun standard raster file format (as obtained by screendump(1)).
17495: *
17496: * Header (8 16-bit quantities)
17497: * Color Map
17498: * Image
17499: *
17500: */
17501:
17502: /* Header Format:
17503: *
17504: * ras_magic (int) Raster Magic number 0x59a66a95
17505: * ras_width (int) Width of image in pixels.
17506: * ras_height (int) Height of image in pixels.
17507: * ras_depth (int) Bits per pixel. Either 1 or 8 bits.
17508: * ras_length (int) Length of image in bytes.
17509: * ras_type (int) Type of file. Assumed to be RT_STANDARD (1) if
17510: * produced by a screendump command.
17511: * ras_maptype (int) Type of color map.
17512: * ras_maplength (int) Length of color map in bytes.
17513: *
17514: */
17515:
17516: /* Ras_maplength bytes of Color map data. */
17517:
17518: /* Ras_length bytes of Image data. */
17519:
17520: /* Buffer and Input Modes... */
17521: #define LITERAL 0
17522: #define COPY 1
17523: #define IGNORE 2
17524:
17525: /* Transmission Variables. */
17526: int BufCount;
17527:
17528: unsigned char Buffer[128],
17529: CurrByte,
17530: NextByte,
17531: *BufferP = Buffer;
17532:
17533: /* Diagnostic Variables. */
17534: int DiagNLongRuns = 0,
17535: DiagMaxRunLength = 0,
17536: DiagNumRuns = 0;
17537: double DiagSumRunLength = 0;
17538:
17539: postmain(argc,argv,width,height)
17540: int argc;
17541: char **argv;
17542: int width, height;
17543: {
17544: char *filename;
17545: double sizex, sizey, transx, transy, rotate;
17546:
17547: extern double atof();
17548:
17549: filename = "STDIN";
17550: sizex = 7.5;
17551: sizey = 10.0;
17552: transx = transy = 0.5;
17553: rotate = 0.0;
17554:
17555: while(--argc > 0)
17556: {
17557: ++argv;
17558: if((*argv)[0] == '-')
17559: {
17560: switch((*argv)[1])
17561: {
17562: case 'l':
17563: case 'L':
17564: Land = 1;
17565: break;
17566:
17567: case 's':
17568: case 'S':
17569: sizex = atof(*++argv);
17570: sizey = atof(*++argv);
17571: argc -= 2;
17572: break;
17573:
17574: case 't':
17575: case 'T':
17576: transx = atof(*++argv);
17577: transy = atof(*++argv);
17578: argc -= 2;
17579: break;
17580:
17581: case 'r':
17582: case 'R':
17583: rotate = atof(*++argv);
17584: argc--;
17585: break;
17586:
17587: case 'I':
17588: case 'i':
17589: Inv = 1;
17590: break;
17591:
17592: case 'A':
17593: case 'a':
17594: Aspect = 1;
17595: break;
17596:
17597: default:
17598: fprintf(stderr,"Illegal switch %c - ignored\n",
17599: (*argv)[1]);
17600: }
17601: }
17602: }
17603: if (Land)
17604: {
17605: transx = 8.0;
17606: transy = 0.5;
17607: sizex = 10.0;
17608: sizey = 7.5;
17609: rotate = 90.0;
17610: }
17611: if (Aspect) {
17612: if ((sizex / width) < (sizey / height)) {
17613: sizey = sizex * (height * 1.0 / width);
17614: }
17615: else {
17616: sizex = sizey * (width * 1.0 / height);
17617: }
17618: }
17619: PrintPostScriptRoutines(height, width, 1 /*depth*/ ,
17620: transx, transy, sizex, sizey, rotate);
17621: }
17622:
17623: /******************************************************************************
17624: * I/O Routines. *
17625: ******************************************************************************/
17626: int
17627: gb() /* Get a byte from Fp. */
17628: {
17629: int byte;
17630:
17631: if (!feof(Fp))
17632: byte = getc(Fp);
17633: else
17634: Error("Premature EOF.\n");
17635: if (ferror(Fp))
17636: Error("I/O Error.\n");
17637: return(Revbyte[byte]);
17638: }
17639:
17640: SendHex(Byte) /* Send a Hex char to Stdout. */
17641: unsigned char Byte;
17642: {
17643: static int LineCount = 0;
17644:
17645: printf("%02x", 0xff & Byte);
17646: if (++LineCount == Rasbytes)
17647: {
17648: putchar('\n');
17649: LineCount = 0;
17650: }
17651: }
17652:
17653: int
17654: SendBuffer(Inv) /* Send a buffer to Stdout. Return BytesSent. */
17655: int Inv;
17656: {
17657: int i, BytesSent;
17658:
17659: if (BufferMode() == LITERAL)
17660: {
17661: SendHex( (unsigned char) 0xff & BufCount );
17662: for (i = 0; i < BufCount+1; i++)
17663: {
17664: SendHex( (Inv) ? Buffer[i] : ~Buffer[i]);
17665: }
17666: BytesSent = BufCount+2;
17667: }
17668: else if (BufferMode() == COPY)
17669: {
17670: SendHex( (unsigned char) 0xff & (0x100 + BufCount) );
17671: SendHex( (Inv) ? Buffer[0] : ~Buffer[0]);
17672: BytesSent = 2;
17673: DiagRecLRun(mag(BufCount)+1);
17674: }
17675: return(BytesSent);
17676: }
17677:
17678: /******************************************************************************
17679: * Utility Routines. *
17680: ******************************************************************************/
17681: int
17682: mag(Byte) /* Magitude of a signed char. */
17683: int Byte;
17684: {
17685: if (Byte & 0x80)
17686: {
17687: /* Signed */
17688: Byte = ~(--Byte);
17689: }
17690: return( 0xff & Byte );
17691: }
17692:
17693: /******************************************************************************
17694: * Buffer Management Routines. *
17695: ******************************************************************************/
17696: int
17697: InputMode()
17698: {
17699: if (CurrByte == NextByte)
17700: return(COPY);
17701: return(LITERAL);
17702: }
17703:
17704: int
17705: BufferMode()
17706: {
17707: if (BufCount >= 0 && BufCount <= 127)
17708: return(LITERAL);
17709: else if (BufCount >= -127 && BufCount <= -1)
17710: return(COPY);
17711: return(IGNORE);
17712: }
17713:
17714: InitLitMode(NBytes, Inv)
17715: int *NBytes, Inv;
17716: {
17717: BufferP = Buffer;
17718: BufCount = -1;
17719: ContLitMode(NBytes, Inv);
17720: }
17721:
17722: ContLitMode(NBytes, Inv)
17723: int *NBytes, Inv;
17724: {
17725: if (BufCount == 127)
17726: {
17727: SendBuffer(Inv);
17728: BufferP = Buffer;
17729: BufCount = -1;
17730: }
17731: *BufferP++ = CurrByte;
17732: BufCount++;
17733: CurrByte = NextByte;
17734: NextByte = (unsigned char) gb();
17735: (*NBytes)--;
17736: }
17737:
17738: InitCopyMode(NBytes, Inv)
17739: int *NBytes, Inv;
17740: {
17741: BufferP = Buffer;
17742: *BufferP++ = CurrByte;
17743: BufCount = -1;
17744: CurrByte = (unsigned char) gb();
17745: NextByte = (unsigned char) gb();
17746: *NBytes -= 2;
17747: }
17748:
17749: ContCopyMode(NBytes, Inv)
17750: int *NBytes, Inv;
17751: {
17752: if (BufCount == -127)
17753: {
17754: SendBuffer(Inv);
17755: InitCopyMode(NBytes, Inv);
17756: DiagNLongRuns++;
17757: }
17758: BufCount--;
17759: CurrByte = NextByte;
17760: NextByte = gb();
17761: (*NBytes)--;
17762: }
17763:
17764: /******************************************************************************
17765: * Encoding Algorithm. *
17766: ******************************************************************************/
17767: int
17768: Encode(NBytes, Inv)
17769: int NBytes, Inv;
17770: {
17771: int BytesSent = 0;
17772:
17773: /* Initialize Buffer, BufCount, NextByte, CurrByte */
17774: CurrByte = (unsigned char) gb();
17775: NextByte = (unsigned char) gb();
17776: if (InputMode() == LITERAL)
17777: {
17778: InitLitMode(&NBytes, Inv);
17779: }
17780: else
17781: {
17782: InitCopyMode(&NBytes, Inv);
17783: }
17784: while (NBytes > 3)
17785: {
17786: switch(BufferMode())
17787: {
17788: case LITERAL:
17789: if (InputMode() == COPY)
17790: {
17791: BytesSent += SendBuffer(Inv);
17792: InitCopyMode(&NBytes, Inv);
17793: }
17794: else
17795: {
17796: ContLitMode(&NBytes, Inv);
17797: }
17798: break;
17799: case COPY:
17800: if (CurrByte == Buffer[0])
17801: {
17802: ContCopyMode(&NBytes, Inv);
17803: }
17804: else
17805: {
17806: BytesSent += SendBuffer(Inv);
17807: if (InputMode() == COPY)
17808: {
17809: InitCopyMode(&NBytes, Inv);
17810: }
17811: else
17812: {
17813: InitLitMode(&NBytes, Inv);
17814: }
17815: }
17816: break;
17817: default:
17818: Error("Bad Buffer Mode... Sorry\n");
17819: break;
17820: }
17821: }
17822: BytesSent += SendBuffer(Inv);
17823: /* Send out rem'g 2-3 bytes in LITERAL mode. */
17824: Buffer[0] = CurrByte;
17825: Buffer[1] = NextByte;
17826: if (NBytes == 3)
17827: Buffer[2] = gb();
17828: BufCount = NBytes-1;
17829: BytesSent += SendBuffer(Inv);
17830: return(BytesSent);
17831: }
17832:
17833: /******************************************************************************
17834: * Diagnostic Routines. *
17835: ******************************************************************************/
17836: DiagRecLRun(Rlength)
17837: int Rlength;
17838: {
17839: #ifdef DIAGS
17840: if (Rlength > DiagMaxRunLength)
17841: DiagMaxRunLength = Rlength;
17842: DiagSumRunLength += Rlength;
17843: DiagNumRuns++;
17844: #endif
17845: }
17846:
17847: Diags()
17848: {
17849: #ifdef DIAGS
17850: fprintf(stderr, "Longest Run (<= 128) = %d\n", DiagMaxRunLength);
17851: fprintf(stderr, "Number of Runs over 128 = %d\n", DiagNLongRuns);
17852: fprintf(stderr, "Average Run Length of %d. (%d Runs)\n",
17853: (int) DiagSumRunLength / DiagNumRuns, DiagNumRuns);
17854: #endif
17855: }
17856:
17857: /******************************************************************************
17858: * PostScript Output Routines. *
17859: ******************************************************************************/
17860: PrintPostScriptRoutines(ras_h, ras_w, ras_d, tx, ty, sx, sy, rot)
17861: int ras_h, ras_w, ras_d;
17862: double tx, ty, sx, sy, rot;
17863: {
17864: printf("%%!\n/inch {72 mul} def\n");
17865: printf("/bpp %d def\n", ras_d);
17866: printf("/scanlines %d def\n", ras_h);
17867: printf("/scansize %d def\n", ras_w);
17868: printf("/bitmapx\n{");
17869: printf(" %d %d %d [%d 0 0 %d 0 %d] ", ras_w, ras_h, ras_d, ras_w,
17870: -ras_h, ras_h);
17871: printf("{currentfile readrlehexstring pop } image\n} def\n");
17872: printf("gsave\n");
17873: printf("%f inch %f inch translate\n",tx, ty);
17874: printf("%f rotate\n", rot );
17875: printf("%f inch %f inch scale\n", sx, sy);
17876: printf("/readrlehexstring\t%% rle_file => decoded_string boolean\n");
17877: printf("{\n\t/fileptr exch def\n\tfileptr 1 string readhexstring {");
17878: printf("\n\t\t0 get dup 128 and 0 eq\n");
17879: printf("\t\t{ 1 add /Buffer exch string def\n");
17880: printf("\t\t\tfileptr Buffer readhexstring\n\t\t}\n\t\t{");
17881: printf(" 256 exch sub /BufCount exch def\n");
17882: printf("\t\t\t/Buffer BufCount 1 add string def\n");
17883: printf("\t\t\t/RunInt fileptr 1 string readhexstring");
17884: printf(" pop 0 get def\n");
17885: printf("\t\t\t0 1 BufCount { RunInt Buffer 3 1 roll put } for\n");
17886: printf("\t\t\tBuffer true\n\t\t} ifelse\n\t}\n\t{ false } ifelse\n");
17887: printf("} def\n");
17888: printf("/clipathx\n{\tnewpath\n\t0 0 moveto\n\t%f inch 0", sx);
17889: printf(" lineto\n\t%f inch %f inch lineto\n\t0 %f inch lineto\n",
17890: sx, sy, sy);
17891: printf("\tclosepath\n} def\nclipathx clip\n");
17892: printf("bitmapx\n");
17893: }
17894:
17895: PrintPostScriptClosing()
17896: {
17897: printf("\ngrestore\n");
17898: printf("showpage\n");
17899: }
17900:
17901: /******************************************************************************
17902: * Error Routine. *
17903: ******************************************************************************/
17904: Error(S1, S2, S3)
17905: char *S1, *S2, *S3;
17906: {
17907: fprintf(stderr, S1, S2, S3);
17908: exit(-1);
17909: }
17910: 0707070035351136011006640007620000050000010264130476773367300001200000005002rastlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
17911: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
17912: /* The copyright notice does not imply actual or intended publication. */
17913: /* AUTHORS: */
17914: /* T. Thompson - ATT-BL HO - first version */
17915: /* Routines for generating PostScript from RLE. */
17916: /* The routines at the bottom of this file, which */
17917: /* do the actual conversion to postscript, were */
17918: /* take from 'sun2ps'. The original header */
17919: /* giving credit to its authors is there. */
17920:
17921: /* The 'binary' version of the output is collected in a */
17922: /* temporary file, which is then fed back to the routines */
17923: /* that generate postscript in a run-length-encoded form. */
17924: /* Ideally it should just convert the original run-length */
17925: /* encoding directly, but this is just a hack. The REAL */
17926: /* bottleneck is the PostScript printer, of course. */
17927: /* Printing an 800 by 800 pixel image takes 5 minutes. */
17928:
17929: #include <stdio.h>
17930: #include <math.h>
17931: #include <string.h>
17932: #include "CPU.h"
17933: #include "boole.h"
17934: #include "limits.h" /* numeric extreme values */
17935: #include "Units.h"
17936: #include "Coord.h"
17937: #include "pic.h"
17938: #include <sys/types.h>
17939: #include <suntool/sunview.h>
17940: #include <pixrect/pixrect.h>
17941: #include <pixrect/pr_io.h>
17942:
17943: int Raswidth;
17944: int Raslength;
17945: extern char Revbyte[256];
17946: extern char Revnib[16];
17947:
17948: static FILE *fout;
17949:
17950: void
17951: RAST_start(h)
17952: PIC_hdr *h;
17953: {
17954: int n, v;
17955: struct rasterfile rh;
17956:
17957: /* build a table of reversed bytes */
17958: for ( n=0; n<256; n++ )
17959: Revbyte[n] = Revnib[(n>>4)&0xf] | Revnib[n&0xf]<<4;
17960:
17961: fout = h->fp;
17962: h->bpl = (h->bpl+7)/8;
17963: Raslength = h->bpl * h->bx.b.y;
17964: Raswidth = h->bx.b.x;
17965:
17966: rh.ras_magic = RAS_MAGIC;
17967: rh.ras_width = h->bx.b.x;
17968: rh.ras_height = h->bx.b.y;
17969: rh.ras_depth = 1;
17970: rh.ras_length = Raslength;
17971: rh.ras_type = RT_STANDARD;
17972: rh.ras_maptype = RMT_NONE;
17973: rh.ras_maplength = 0;
17974: pr_dump_header(fout,&rh,(colormap_t*)0);
17975: }
17976:
17977: void
17978: RAST_end()
17979: {
17980: }
17981:
17982: /* write a full line of picture data, returning status: 1 OK, 0 EOF,
17983: -1 ERR */
17984: int RAST_wline(h,line)
17985: PIC_hdr *h;
17986: unsigned char *line;
17987: { int stat;
17988: int n;
17989:
17990: for ( n=h->bpl; n>0; n-- ) {
17991: if ( putc(Revbyte[*line++],fout) == EOF )
17992: break;
17993: }
17994: if ( n == 0 ) {
17995: h->seek += h->bpl;
17996: h->cy++;
17997: return(1);
17998: }
17999: else { /* ERR */
18000: err("write to fd%d stat%d",fileno(h->fp),stat);
18001: if((stat>=0)&&(stat<h->bpl)) return(0 /*EOF*/);
18002: else return(-1);
18003: };
18004: }
18005: 0707070035351135651006640007620000050000010264150476773367300000600000003030ric.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
18006: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
18007: /* The copyright notice does not imply actual or intended publication. */
18008: /* AUTHORS: */
18009: /* H. S. Baird - ATT-BL MH - first versions */
18010: /* ric.h - Ricoh IS-30 scanner constants, typedefs, function declarations
18011: The scanner program `rscan' creates a file (typically >1Mbyte).
18012: It has an ascii header, terminated by \n\n -- see RIC_hdr for its data fields.
18013: The rest is binary scanner data. Each `RIC_hdr.bpl' bytes holds one scan-line's
18014: pixels, 1 bit/pixel. A `1' bit means black. The order of the bytes in a line
18015: is left-to-right across the page. The low-order bit in a byte is the left-most.
18016: Conventionally, X-coordinates start at 0, at the left of the page, and
18017: increase to the right. Y-coordinates start at 0 at the top of the page,
18018: and increase down.
18019:
18020: REQUIRES: prior #include "Coord.h"
18021: */
18022:
18023: typedef struct { /* Scanner file header */
18024: short res_x,res_y; /* resolution in pixels/inch (x,y may differ) */
18025: short bpl; /* bytes per scan line */
18026: Bbx bx; /* bounding box (pixel indices 0,1,...) */
18027: } RIC_hdr;
18028:
18029: /* these routines are found in /usr/hsb/ricoh/riclib.c */
18030: int RIC_get_hdr(); /* args: fd, (RIC_hdr *); returns: 1==OK, 0==EOF, -1=ERR */
18031: int RIC_line(); /* arg: (char **); returns: 1==OK, 0==EOF, -1==ERR */
18032: RIC_skip(); /* arg: int no. lines to skip */
18033: char *S_hdr_toa(); /* RIC_hdr in printable-string form */
18034:
18035: 0707070035351135321006640007620000050000010264160476773367300001100000011466riclib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
18036: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
18037: /* The copyright notice does not imply actual or intended publication. */
18038: /* AUTHORS: */
18039: /* H. S. Baird - ATT-BL MH - first versions */
18040: /* riclib.c - Ricoh scanner-file public functions:
18041:
18042: RIC_* functions use system I/O, for speed...
18043: int RIC_get_hdr(fd,RIC_hdr *) - get scanner-file header
18044: int RIC_line(char **) - read one line of scanner data
18045: err_RIC_Line(char *,RIC_hdr) - print on stderr
18046: int RIC_oline(char **) - write one line of scanner data
18047: char *RIC_hdr_toa() - RIC_hdr to ascii printable string
18048: */
18049:
18050: #include <stdio.h>
18051: #include <math.h>
18052: #include <string.h>
18053: #include "CPU.h"
18054: #include "stdocr.h"
18055:
18056: #define RIC_debug 0
18057:
18058: /* treated as local static: */
18059: int RIC_fd; /* file descr. */
18060: int RIC_bpl; /* bytes per line */
18061: char *RIC_bf = NULL; /* (malloc space *) holds one line of scanner data */
18062:
18063: /* system I/O variation on fgets(3), except it replaces \n with \0,
18064: and returns the number of chars read (including \0) */
18065: int RIC_fgets(bf,max,fd)
18066: char *bf;
18067: int max;
18068: int fd;
18069: { char *cp;
18070: int stat,mny;
18071: cp=bf; mny=0;
18072: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
18073: if(stat!=1) return(stat);
18074: else if(mny>=max) return(-1);
18075: *cp='\0';
18076: return(mny);
18077: }
18078:
18079: /* read header from scanner file, return status: 1 OK, 0 EOF, -1 error */
18080: int RIC_get_hdr( fd, hp )
18081: int fd; /* should have been open'ed earlier */
18082: RIC_hdr *hp;
18083: #define HL_MAX 80
18084: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
18085: { char *cp,*parm,hline[HL_MAX];
18086: int status,nrd;
18087: RIC_fd = fd;
18088: if((status=RIC_fgets(hline,HL_MAX,RIC_fd))<=0) return(status);
18089: while(strlen(hline)>1) {
18090: if(RIC_debug) err("hline \"%s\"",hline);
18091: parm=strtok(hline,HTERM);
18092: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
18093: if((parm=strtok(0,HTERM))!=NULL
18094: &&strcmp(parm,"binary")==0) ;
18095: else return(-1);
18096: }
18097: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
18098: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.x=atoi(parm);
18099: else return(-1);
18100: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.y=atoi(parm);
18101: else return(-1);
18102: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.x=atoi(parm)-1;
18103: else return(-1);
18104: hp->bpl=(hp->bx.b.x-hp->bx.a.x+1+7)/8;
18105: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.y=atoi(parm)-1;
18106: else return(-1);
18107: }
18108: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
18109: if((parm=strtok(0,HTERM))!=NULL) hp->res_x=atoi(parm);
18110: else return(-1);
18111: if((parm=strtok(0,HTERM))!=NULL) hp->res_y=atoi(parm);
18112: else return(-1);
18113: }
18114: else return(-1);
18115: if((status=RIC_fgets(hline,HL_MAX,RIC_fd))<=0) return(status);
18116: };
18117: RIC_bpl=hp->bpl;
18118: /* allocate one extra byte in scanner buffer as a favor to RLE */
18119: if((RIC_bf = (char *) malloc(RIC_bpl+1))==NULL) {
18120: fprintf(stderr,
18121: "riclib: can't alloc RIC_bf (%d bytes) - abort\n",
18122: RIC_bpl+1);
18123: return(-1);
18124: };
18125: return(1);
18126: }
18127:
18128: /* write header to scanner file */
18129: RIC_put_hdr( fd, hp )
18130: int fd; /* should have been open'ed earlier */
18131: RIC_hdr *hp;
18132: { char *cp,*parm,hline[HL_MAX];
18133: int status,nrd;
18134: sprintf(hline,"TYPE=binary\n");
18135: write(fd,hline,strlen(hline));
18136: sprintf(hline,"WINDOW=%d %d %d %d\n",
18137: hp->bx.a.x,hp->bx.a.y,hp->bpl,hp->bx.b.y+1);
18138: write(fd,hline,strlen(hline));
18139: sprintf(hline,"RES=%d %d\n\n",hp->res_x,hp->res_y);
18140: write(fd,hline,strlen(hline));
18141: }
18142:
18143: err_RIC_line(sl,shdr)
18144: char *sl;
18145: RIC_hdr shdr;
18146: #define BPL 20 /* bytes to display per line */
18147: { char *cp,*ep;
18148: int bpl; /* bytes per display line */
18149: bpl=0;
18150: for(cp=sl,ep=sl+shdr.bpl; cp!=ep; cp++) {
18151: fprintf(stderr,"%o ",0377&(*cp));
18152: if((++bpl)%BPL==0) fprintf(stderr,"\n ");
18153: };
18154: if((bpl)%BPL!=0)fprintf(stderr,"\n");
18155: }
18156:
18157: /* skip `y' lines, starting from current read pointer */
18158: RIC_skip(y)
18159: int y;
18160: { lseek(RIC_fd,(long)(y*RIC_bpl),1);
18161: }
18162:
18163: /* read next full line of scanner data, return status: 1 OK, 0 EOF, -1 ERR */
18164: int RIC_line(lbpp)
18165: char **lbpp;
18166: { int stat;
18167: if( (stat=read(RIC_fd,RIC_bf,RIC_bpl)) == RIC_bpl) {
18168: *lbpp=RIC_bf;
18169: if(RIC_debug) err("read %d bytes from RIC_fd - OK",stat);
18170: return(1);
18171: }
18172: else { /* EOF or ERR */
18173: *lbpp=NULL;
18174: free(RIC_bf);
18175: if(RIC_debug) err("read from RIC_fd stat%d",stat);
18176: if((stat>=0)&&(stat<RIC_bpl)) return(0 /*EOF*/);
18177: else return(-1);
18178: };
18179: }
18180:
18181: /* write a full line of scanner data, returning status: 1 OK, 0 EOF, -1 ERR */
18182: int RIC_oline(fd,bf)
18183: int fd;
18184: char *bf;
18185: { int stat;
18186: if( (stat=write(fd,bf,RIC_bpl)) == RIC_bpl) {
18187: if(RIC_debug) err("wrote %d bytes to fd%d - OK",stat,fd);
18188: return(1);
18189: }
18190: else { /* ERR */
18191: err("write to fd%d stat%d",fd,stat);
18192: if((stat>=0)&&(stat<RIC_bpl)) return(0 /*EOF*/);
18193: else return(-1);
18194: };
18195: }
18196:
18197: char *RIC_hdr_toa(hp)
18198: RIC_hdr *hp;
18199: { static char s[40];
18200: sprintf(s,"{res%d,%d bpl%d bx%s}\n",
18201: hp->res_x,hp->res_y,
18202: hp->bpl,
18203: bbx_toa(&(hp->bx)));
18204: return(s);
18205: }
18206:
18207: 0707070035351135311006640007620000050000010264170476773367400000600000007317rle.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
18208: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
18209: /* The copyright notice does not imply actual or intended publication. */
18210: /* AUTHORS: */
18211: /* H. S. Baird - ATT-BL MH - first versions */
18212: /* A rle file consists of any number of:
18213: `scan_line's, each of which has the form:
18214: (short) bytes_mny, followed by bytes_mny bytes in the form:
18215: (packed short) runs_mny
18216: if >0, then followed by runs_mny runs
18217: else if ==0, then followed by:
18218: (packed short) blank_lines_mny skipped, -1
18219: (packed short) runs_mny (>0), then...
18220: ...runs_mny runs
18221: A `run' is two (packed short) oxs,oxe which are
18222: both offset counts >=0 from the prior `?x?' (starts at 0 at left margin).
18223: Suppose that xs, xe are the corresponding accumulated pixel indices,
18224: then xs is the pixel index of the first black pixel of the run,
18225: and xe the pixel index of the first white pixel following the run.
18226: A `packed short' is a byte if its value is <128, else two bytes `HIGH' & `LOW'
18227: with the 0200 bit of its HIGH byte set.
18228: */
18229:
18230: #define HIGH(A) ((A>>8)&0177)
18231: #define LOW(A) (A&0377)
18232:
18233: /* run-length-encoding constants, typedefs */
18234:
18235: /* The following assumes a worst case page width of 17 inches (Legal page, >ISO A2)
18236: and worst case digitizing resolution of 400 pixels/inch (e.g. CCITT Group 4),
18237: for a maximum of 6800 pixels/line */
18238: #define RLE_RUNS 3401 /* maximum no. runs in a line */
18239: #define RLE_BYTES 6800 /* maximum no. data bytes in a rle line (enough?) */
18240:
18241: typedef struct RLE_Run {
18242: short xs; /* x-coord of first pixel in run */
18243: short xe; /* x-coord of last pixel in run (NOT first following) */
18244: } RLE_Run;
18245: #define Init_RLE_Run {0,0}
18246:
18247: typedef struct DRLE_Run {
18248: short xs; /* x-coord of first pixel in run */
18249: short xe; /* x-coord of last pixel in run (NOT first following) */
18250: struct DRLE_Run *next;
18251: } DRLE_Run;
18252:
18253: typedef struct RLE_Yrun {
18254: short y,xs,xe;
18255: } RLE_Yrun;
18256: #define Init_RLE_Yrun {0,0,0}
18257:
18258: typedef struct RLE_Line {
18259: short y; /* y-coord of line */
18260: short len; /* length of line in pixels (white+black) */
18261: short runs; /* no. of runs */
18262: RLE_Run r[RLE_RUNS];
18263: } RLE_Line;
18264: #define Init_RLE_Line {0,0,0,Init_RLE_Run}
18265:
18266:
18267: typedef struct DRLE_Line { /* dynamically allocated version */
18268: DRLE_Run *r; /* first run */
18269: DRLE_Run *lastr; /* last run */
18270: } DRLE_Line;
18271: #define Init_DRLE_Line {0,0}
18272:
18273: typedef struct RLE_Lines {
18274: int mny;
18275: RLE_Line *rla; /* array of RLE_Lines */
18276: } RLE_Lines;
18277: #define Init_RLE_Lines {0,NULL}
18278: #if MAIN
18279: RLE_Lines empty_RLE_Lines = Init_RLE_Lines;
18280: #else
18281: extern RLE_Lines empty_RLE_Lines;
18282: #endif
18283:
18284: typedef struct Transform_rlel_arg {
18285: boolean ident; /* if T, then no change (speed-optimization) */
18286: Bbx tr; /* trim: select just this window of input */
18287: Sp off; /* offset: translate by off.x,off.y */
18288: Pp scl; /* scale: X & Y expansion factors (about 0,0) */
18289: Sp wh; /* truncate: exact maximum output width,height */
18290: Radians rot; /* rotate: angle (multiple of PI/4) */
18291: boolean rev; /* reverse: swap black and white */
18292: int sy; /* next integer line no. to write */
18293: double dy; /* next real line no. to write */
18294: } Transform_rlel_arg;
18295: #define Init_Transform_rlel_arg {T,Init_Bbx,Init_Zero_Sp,{1.0,1.0},Init_Zero_Sp,0.0,F,0,0.0}
18296: #if MAIN
18297: Transform_rlel_arg empty_Transform_rlel_arg = Init_Transform_rlel_arg;
18298: #else
18299: extern Transform_rlel_arg empty_Transform_rlel_arg;
18300: #endif
18301:
18302: #ifdef MAIN
18303: /* these routines are found in rlelib.c */
18304:
18305: boolean RLE_open(); /* arg: (FILE *) */
18306: RLE_Line *RLE_line(); /* args: l,r - left,right interval */
18307: RLE_Line *RLE_get_Line(); /* args: l,r - left,right interval */
18308: int RLE_run(); /* arg: (RLE_Run *) */
18309: fwrb_rlines(); /* args: (FILE *), (RLE_Lines *) */
18310: insert_rlel();
18311: #endif
18312: 0707070035351135301006640007620000050000010264210476773367400001100000047356rlelib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
18313: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
18314: /* The copyright notice does not imply actual or intended publication. */
18315: /* AUTHORS: */
18316: /* T. Pavlidis - ATT-BL MH - first versions */
18317: /* H. S. Baird - ATT-BL MH - first versions */
18318:
18319: /* rlelib.c - subroutines for writing/reading run-length-encoded format files.
18320: BUG: Uses system I/O for speed, but sacrifices machine-independence:
18321: should use fioi.h macroes instead.
18322: See rle.h for summary of rle file and format of public functions.
18323: Writing a rle file:
18324: fd=creat()
18325: RLE_put_hdr(fd,hp) - once: allocate buffers, write header
18326: RLE_put_Line(fd,lp) - repeatedly
18327: RLE_close(fd) - once: flush and deallocate buffers
18328: Reading a rle file:
18329: fd=open()
18330: RLE_open(fd,hp) - once: read header, 1st line into buffer
18331: RLE_get_Line(l,r) - repeatedly (on EOF, deallocates buffer)
18332: The user can read line-at-a-time or run-at-a-time, but should not intermix them:
18333: line-at-a-time:
18334: (RLE_Line *) RLE_get_Line(l,r) - return ptr to next line with some run
18335: in the interval [l,r];
18336: read from opened file (NULL if EOF, abort on error)
18337: allocates large buffer and frees it when done
18338: run-at-a-time:
18339: int RLE_get_Run(&R) - read next run into (RLE_Run) R
18340: returns the line number (-1 for EOF, abort on ERROR)
18341: does not allocate large buffer;
18342: if only a few runs will be used, can be faster
18343: */
18344:
18345: #include <stdio.h>
18346: #define LIBC_INCL 1
18347: #include "CPU.h"
18348: #include "stdocr.h"
18349: #include "rle.h"
18350:
18351: #define RLE_dbg F
18352: #define dbg_rd F
18353: #define dbg_wr F
18354:
18355: /* Treated as local static: */
18356: typedef struct RLE_global {
18357: int fd; /* rle file descriptor */
18358: boolean eof;
18359: int cy, cx; /* current line no., x-coord */
18360: short runs, nrun; /* no. runs, next run in current line */
18361: RLE_Line *lp; /* pointer to line (malloc space) */
18362: int bpl; /* maximum no. bytes in packed rle line */
18363: char *bf; /* I/O buffer (malloc space) */
18364: int bfsize; /* size of buffer */
18365: char *cp; /* cur. ptr, into bf */
18366: } RLE_global;
18367: #define Init_RLE_global {0,F,-1,-1,0,0,NULL,0,NULL,0,NULL}
18368: RLE_global _RLE = Init_RLE_global;
18369:
18370: RLE_put_hdr( fd, rhp, bufn )
18371: int fd;
18372: RIC_hdr *rhp;
18373: int bufn; /* minimum number of lines to buffer locally */
18374: { char hdr[100];
18375: int stat;
18376: sprintf(hdr,"TYPE=rle\nWINDOW=%d %d %d %d\nRES=%d %d\n\n",
18377: /* use half-open WINDOW convention: l&t closed, r&b open*/
18378: rhp->bx.a.x,rhp->bx.a.y,rhp->bx.b.x+1,rhp->bx.b.y+1,
18379: rhp->res_x,rhp->res_y);
18380: if((stat=write(fd,hdr,strlen(hdr)))!=strlen(hdr)) {
18381: abort("rlelib: can't put hdr, stat %d",stat);
18382: };
18383: _RLE.fd = fd;
18384: _RLE.cy = rhp->bx.a.y-1;
18385: _RLE.bpl = rhp->bx.b.x-rhp->bx.a.x+9; /* maximum bytes per line */
18386: _RLE.bfsize = bufn*_RLE.bpl;
18387: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
18388: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
18389: _RLE.cp = _RLE.bf;
18390: }
18391:
18392: #define PUT(A,B) { if((A)<128) *(B)++ = (A); \
18393: else { *(B)++ = HIGH(A) | 0200; *(B)++ = LOW(A); } \
18394: }
18395:
18396: /* write out a non-blank line of runs */
18397: RLE_put_Line(fd,rlp)
18398: int fd; /* file descr (already open) */
18399: RLE_Line *rlp;
18400: { register char *bp;
18401: short blank_lines_mny; /* the number of preceding blank lines, minus 1 */
18402: register RLE_Run *rp,*ep;
18403: Scoor xsofar;
18404: short bytes_mny;
18405: int stat; /* I/O status */
18406: if((_RLE.bfsize-(_RLE.cp-_RLE.bf)) < _RLE.bpl) {
18407: /* not enough room left in buffer for worst-case line */
18408: RLE_flush();
18409: };
18410: /* leave space for (short) bytes_mny count */
18411: bp=_RLE.cp+sizeof(short);
18412: if((blank_lines_mny=(rlp->y-_RLE.cy-1))>0) /* blank lines were skipped */ {
18413: PUT(0,bp); /* ``0 runs'' signals blank lines */
18414: PUT(blank_lines_mny,bp);
18415: };
18416: _RLE.cy=rlp->y;
18417: PUT(rlp->runs,bp);
18418: xsofar=0;
18419: for(rp=rlp->r,ep=rp+rlp->runs; rp!=ep; rp++) {
18420: PUT(rp->xs-xsofar,bp); xsofar = rp->xs;
18421: PUT(rp->xe-xsofar+1,bp); xsofar = rp->xe+1;
18422: };
18423: /* go back & write no. bytes at top of line */
18424: *((short *) _RLE.cp) = bp-_RLE.cp-sizeof(short);
18425: _RLE.cp = bp;
18426: if(dbg_wr) err("RLE_put_Line y%d nh%d",_RLE.cy,bytes_mny-2);
18427: };
18428:
18429: /* write out a set of runs */
18430: RLE_put_Lines(fd,rlsp)
18431: int fd; /* file descr (already open) */
18432: RLE_Lines *rlsp;
18433: { int i;
18434: RLE_Line *rlp;
18435: for(i=0,rlp=rlsp->rla; i<rlsp->mny; i++,rlp++)
18436: RLE_put_Line(fd,rlp);
18437: }
18438:
18439: RLE_flush()
18440: { int bytes;
18441: int stat;
18442: if((bytes=(_RLE.cp-_RLE.bf))>0)
18443: if(stat=write(_RLE.fd,_RLE.bf,bytes)!=bytes)
18444: abort("can't write _RLE.bf[%d], status %d",bytes,stat);
18445: _RLE.cp = _RLE.bf;
18446: }
18447:
18448: RLE_close(fd)
18449: int fd;
18450: { RLE_flush();
18451: if(_RLE.bf!=NULL) free(_RLE.bf);
18452: _RLE.bf = _RLE.cp = NULL;
18453: _RLE.bfsize = 0;
18454: }
18455:
18456: /* ``open'' RLE_file for reading:
18457: save filedes, read header, and read first line into buffer */
18458: boolean RLE_open( fd, hp )
18459: int fd;
18460: RIC_hdr *hp;
18461: { _RLE.fd = fd;
18462: /* read header */
18463: RLE_get_hdr( fd, hp );
18464: if(_RLE.bf!=NULL) free(_RLE.bf);
18465: _RLE.bfsize = _RLE.bpl;
18466: if((_RLE.bf=(char *)malloc(_RLE.bfsize))==NULL)
18467: abort("can't alloc _RLE.bf[%d]",_RLE.bfsize);
18468: /* read first non-blank line */
18469: _RLE.cy = hp->bx.a.y-1;
18470: if (!RLE_rdbf()) return(F);
18471: _RLE.eof = F;
18472: return(T);
18473: }
18474:
18475: /* read next short from rle-line buffer, updating arg ptr */
18476: short RLE_gshort(p)
18477: char **p;
18478: { register n;
18479: register char *q;
18480: q = *p;
18481: if((*q)&0200) {
18482: n = (((*q & 0177)<<8)&077400) | (*(q+1) & 0377);
18483: (*p)++;
18484: }
18485: else n = *q;
18486: (*p)++;
18487: return(n);
18488: }
18489:
18490: /* system I/O variation on fgets(3), except it replaces \n with \0,
18491: and returns the number of chars read (including \0) */
18492: int RLE_fgets(bf,max,fd)
18493: char *bf;
18494: int max;
18495: int fd;
18496: { char *cp;
18497: int stat,mny;
18498: cp=bf; mny=0;
18499: while(((stat=read(fd,cp,1))==1)&&(++mny<max)&&((*cp)!='\n')) cp++;
18500: if(stat!=1) return(stat);
18501: else if(mny>=max) return(-1);
18502: *cp='\0';
18503: return(mny);
18504: }
18505:
18506: /* read ascii header from rle file, convert to RIC_hdr,
18507: return status: 1 OK, 0 EOF, -1 error */
18508: int RLE_get_hdr( fd, hp )
18509: int fd; /* should have been open'ed earlier */
18510: RIC_hdr *hp;
18511: #define HL_MAX 80
18512: #define HTERM "=, \n" /* terminations for header words: "=,<sp><tab>" */
18513: { char *cp,*parm,hline[HL_MAX];
18514: int status,nrd;
18515: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
18516: while(strlen(hline)>1) {
18517: if(RLE_dbg) err("hline \"%s\"",hline);
18518: parm=strtok(hline,HTERM);
18519: if(parm!=NULL&&strcmp(parm,"TYPE")==0) {
18520: if((parm=strtok(0,HTERM))!=NULL
18521: &&strcmp(parm,"rle")==0) ;
18522: else return(-1);
18523: }
18524: else if(parm!=NULL&&strcmp(parm,"WINDOW")==0) {
18525: /* assume half-open WINDOW: l&t closed, r&b open */
18526: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.x=atoi(parm);
18527: else return(-1);
18528: if((parm=strtok(0,HTERM))!=NULL) hp->bx.a.y=atoi(parm);
18529: else return(-1);
18530: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.x=atoi(parm)-1;
18531: else return(-1);
18532: if((parm=strtok(0,HTERM))!=NULL) hp->bx.b.y=atoi(parm)-1;
18533: else return(-1);
18534: }
18535: else if(parm!=NULL&&strcmp(parm,"RES")==0) {
18536: if((parm=strtok(0,HTERM))!=NULL) hp->res_x=atoi(parm);
18537: else return(-1);
18538: if((parm=strtok(0,HTERM))!=NULL) hp->res_y=atoi(parm);
18539: else return(-1);
18540: }
18541: else return(-1);
18542: if((status=RLE_fgets(hline,HL_MAX,fd))<=0) return(status);
18543: };
18544: /* maximum possible no. bytes in a packed rle line */
18545: _RLE.bpl = hp->bpl = hp->bx.b.x-hp->bx.a.x+9;
18546: if(dbg_rd) fprintf(stderr,"rlelib: RLE_get_hdr: %s\n",RIC_hdr_toa(hp));
18547: return(1);
18548: }
18549:
18550: /* read the next run into *Rp, and return line number
18551: (-1 for EOF, abort on error) */
18552: int RLE_get_Run( Rp )
18553: RLE_Run *Rp;
18554: { if(_RLE.nrun >= _RLE.runs) { /* no more, try to read next line */
18555: if (!RLE_rdbf()) /* EOF */ return(-1);
18556: };
18557: /* another run */
18558: Rp->xs = (_RLE.cx += RLE_gshort(&_RLE.cp));
18559: Rp->xe = (_RLE.cx += RLE_gshort(&_RLE.cp)) - 1;
18560: _RLE.nrun++;
18561: return(_RLE.cy);
18562: }
18563:
18564: /* Return ptr to the next line with at least one run overlapping the margins
18565: [lm,rm]. The reported runs are not trimmed to fit exactly within margins.
18566: If no more lines, return NULL. On error, abort */
18567: RLE_Line *RLE_get_Line(lm,rm)
18568: int lm, rm; /* left, right margins */
18569: { register int rr; /* runs read */
18570: register RLE_Run *rp; /* write ptr */
18571:
18572: do { if(_RLE.eof) {
18573: free(_RLE.lp); _RLE.lp = NULL;
18574: free(_RLE.bf); _RLE.bf = NULL;
18575: return(NULL);
18576: };
18577: if(_RLE.lp==NULL) { /* allocate space for RLE_Line */
18578: _RLE.lp = (RLE_Line *) malloc(sizeof(RLE_Line));
18579: if(_RLE.lp==NULL) {
18580: abort("rlelib: can't malloc RLE_Line (%d bytes)",
18581: sizeof(RLE_Line));
18582: };
18583: };
18584: _RLE.lp->y = _RLE.cy;
18585: /* guaranteed to be at least one run in line */
18586: rr=0; rp=_RLE.lp->r; _RLE.lp->runs=0;
18587: /* skip runs that are outside left margin */
18588: do RLE_get_Run(rp);
18589: while((rr++ < _RLE.runs) && (rp->xe < lm));
18590: /* accept runs until cross right margin */
18591: while(rp->xs <= rm) {
18592: _RLE.lp->runs++; /* count accepted runs */
18593: if(rr++ >= _RLE.runs) break;
18594: RLE_get_Run(++rp);
18595: };
18596: /* look ahead to next line */
18597: if (!RLE_rdbf()) /* EOF */ _RLE.eof=T;
18598: }
18599: while(_RLE.lp->runs==0); /* as result of margins, some lines may empty */
18600: return(_RLE.lp);
18601: }
18602:
18603: /* read next line buffer - return F if EOF, abort on error
18604: sideffects: sets up _RLE.cp, _RLE.cy, _RLE.cx, _RLE.runs, _RLE.nrun */
18605: boolean RLE_rdbf()
18606: { short nh;
18607: if(dbg_rd) err("enter RLE_rdbf");
18608: /* get number of bytes holding RLE of a scan line */
18609: if( read(_RLE.fd,&nh,sizeof(short)) != sizeof(short)) {
18610: return(F); /* normal EOF */
18611: };
18612: if( Readvax )
18613: nh = swapshortin( nh );
18614: if(dbg_rd) err("rlelib: RLE_rdbf: nh %d",nh);
18615: if(nh > _RLE.bpl) {
18616: abort("rlelib: too many bytes in line: %d > %d(_RLE.bpl)",
18617: nh,_RLE.bpl);
18618: };
18619:
18620: /* get those bytes */
18621: if( read(_RLE.fd,_RLE.bf,nh) != nh) {
18622: abort("rlelib: rle line truncated");
18623: };
18624: if(dbg_rd) {
18625: int bi;
18626: err("rlelib: RLE_rdbf: _RLE.bf[0-%d] octal:",nh-1);
18627: for(bi=0;bi<nh;bi++)
18628: fprintf(stderr," 0%o",0377&(_RLE.bf[bi]));
18629: fprintf(stderr,"\n");
18630: };
18631:
18632: /* decode the bytes */
18633: _RLE.cp = _RLE.bf;
18634: _RLE.runs = RLE_gshort(&_RLE.cp);
18635: if(dbg_rd) err("rlelib: _RLE.runs %d",_RLE.runs);
18636: if(_RLE.runs==0) { /* blank lines seen */
18637: _RLE.cy += RLE_gshort(&_RLE.cp);
18638: _RLE.runs = RLE_gshort(&_RLE.cp);
18639: if(dbg_rd)
18640: err("rlelib: _RLE.cy %d _RLE.runs %d",_RLE.cy,_RLE.runs);
18641: };
18642: if(_RLE.runs>RLE_RUNS || _RLE.runs<1) {
18643: abort("rlelib: illegal no. runs %d in line",_RLE.runs);
18644: };
18645: _RLE.cy++;
18646: if(dbg_rd) err("rlelib: RLE_rdbf: _RLE.runs %d _RLE.cy %d",_RLE.runs,_RLE.cy);
18647: _RLE.cx = _RLE.nrun = 0; /* next run will be first */
18648: if(dbg_rd) err("rlelib: RLE_rdbf: T exit");
18649: return(T);
18650: }
18651:
18652: /* brrl - compute a binary raster line from a run-length-encoded scanline.
18653: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
18654: and ending index (inclusive) of each run of black pixels (1 bits).
18655: xe >= xs > xe. The runs are in strictly ascending order on xs.
18656: lm & rm are the left and right margin indices of pixels, outside of which the
18657: pixels are forced to be white. rm >= lm. The `lm'th pixel is written
18658: into the `olm'th bit of the output raster (olm>=0).
18659: rasp[] is a raser line of chars; on entry, it is assumed to have been zeroed
18660: out. rasp[0] holds the leftmost byte in the line and the 001 bit of each
18661: byte is the leftmost bit in that byte.
18662: The user must ensure that rasp[] is at least (rm-lm+olm+9)/8 bytes long.
18663: Returns the number of black pixels in the raster line.
18664: NOTE: this uses the ``little-endian'' convention, in which the leftmost pixel
18665: in a byte is placed in the least-significant bit (0x01). See `brrlb()' below
18666: for the alternative ``big-endian'' version.
18667: */
18668: int brrl(runs,runa,lm,rm,olm,rasp)
18669: int runs; /* number of run-segments in runa[] */
18670: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
18671: int lm,rm; /* left,right margin bit indices within raster */
18672: int olm; /* `lm'th input pixel will be written to `olm'th bit */
18673: char unsigned rasp[]; /* binary raster line (zeroed out on entry) */
18674: { int pixels,bi;
18675: RLE_Run r,*rp,*re;
18676: pixels = 0;
18677: re = (rp = (RLE_Run *) runa) + runs;
18678: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
18679: while(rp<re && rp->xs<=rm) {
18680: /* truncate to margins */
18681: if((r.xs = rp->xs)<lm) r.xs = lm;
18682: if((r.xe = rp->xe)>rm) r.xe = rm;
18683: /* shift to output indices */
18684: r.xs += olm-lm; r.xe += olm-lm;
18685: /** SLOW **/
18686: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (01)<<(bi%8);
18687: pixels += r.xe-r.xs+1;
18688: rp++;
18689: };
18690: return(pixels);
18691: }
18692:
18693: /* ``big-endian'' version of brrl: bits are packed so that the leftmost
18694: pixel is placed in the high-order bit (0x80) of each byte.
18695: */
18696: int brrlb(runs,runa,lm,rm,olm,rasp)
18697: int runs;
18698: short runa[];
18699: int lm,rm,olm;
18700: char unsigned rasp[];
18701: { int pixels,bi;
18702: RLE_Run r,*rp,*re;
18703: pixels = 0;
18704: re = (rp = (RLE_Run *) runa) + runs;
18705: while(rp<re && rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
18706: while(rp<re && rp->xs<=rm) {
18707: /* truncate to margins */
18708: if((r.xs = rp->xs)<lm) r.xs = lm;
18709: if((r.xe = rp->xe)>rm) r.xe = rm;
18710: /* shift to output indices */
18711: r.xs += olm-lm; r.xe += olm-lm;
18712: /** SLOW **/
18713: for(bi=r.xs; bi<=r.xe; bi++) rasp[bi/8] |= (0200)>>(bi%8);
18714: pixels += r.xe-r.xs+1;
18715: rp++;
18716: };
18717: return(pixels);
18718: }
18719:
18720: /* crrl - compute a character raster line from a run-length-encoded scanline.
18721: runa[] is an array of shorts, grouped in pairs (xs,xe) to describe the starting
18722: and ending index (inclusive) of each run of black pixels (1 bits): xs<=xe.
18723: The runs are in strictly ascending order on xs. lm & rm are the left and
18724: right margin indices, outside of which pixels are forced to be white. rm >= lm.
18725: rasp[] is a raster line, one unsigned char per pixel; rasp[0] holds the
18726: leftmost pixel. The user must ensure that rasp[] is at least (rm-lm+1)
18727: bytes long. Black pixels are encoded as 0, white as 255. Returns the number
18728: of black pixels in the raster line.
18729: */
18730: #define WHITE_pel 0377
18731: #define BLACK_pel 0000
18732: int crrl(runs,runa,lm,rm,rasp)
18733: int runs; /* number of run-segments in runa[] */
18734: short runa[]; /* array of run-segments [xs,xe] (pairs of short) */
18735: int lm,rm; /* left,right margin bit indices within raster */
18736: unsigned char rasp[]; /* char raster line */
18737: { int pixels,bi,wid;
18738: RLE_Run r,*rp,*re;
18739: unsigned char *cp,*ep;
18740: wid=rm-lm+1;
18741: memset(rasp,WHITE_pel,wid);
18742: re = (rp = (RLE_Run *) runa) + runs;
18743: while(rp<re&&rp->xe<lm) rp++; /* skip runs to the left of 'lm' */
18744: if(rp>=re) return(0);
18745:
18746: r = *rp; r.xs -= lm; r.xe -= lm;
18747: pixels = 0;
18748: do { /* truncate left,right margin */
18749: if(r.xs<0) r.xs = 0;
18750: if(r.xe>(wid-1)) r.xe = wid-1;
18751: /* write r into raster line */
18752: pixels += (r.xe-r.xs+1);
18753: for(cp=rasp+r.xs,ep=rasp+r.xe; cp<=ep; cp++) *cp = BLACK_pel;
18754: /* step to next run */
18755: r = *(++rp); r.xs -= lm; r.xe -= lm;
18756: }
18757: while(r.xs<=(wid-1)&&rp<re);
18758: return(pixels);
18759: }
18760:
18761: /* trcr - threshold & run-length-encode a char raster line. `rasp' is a raster
18762: line, one unsigned char per pixel: rasp[0] is the leftmost pixel in the line.
18763: Pixels with value < 'thresh' are translated to black, else white.
18764: Analyzes the line into a series of runs of `1's, placing them into array
18765: `runs'. Observes margins: starts at `lm' bit and continues through `rm';
18766: bits outside the margins are assumed 0. A `run' is two shorts (the starting &
18767: ending indices of the run of `1's, inclusive). The indices are shifted
18768: so that the `lm'th pixel goes to run index `olm'. Returns the number of runs.
18769: NOTE: The user must ensure that: (1) margins fall within `rasp[]';
18770: (2) `runp[]' is big enough to hold the worst-case no. of runs that can result
18771: ((rm-lm+2)/2). The contents of the raster-line are unmodified.
18772: */
18773: int trcr(rasp,lm,rm,olm,thresh,runp)
18774: char unsigned rasp[]; /* binary raster line (with 1 extra byte at end) */
18775: int lm,rm; /* left,right margin indices within raster */
18776: int olm; /* `lm' pixel goes to `olm' run index */
18777: int thresh;
18778: short runp[]; /* array of run-segments [xs,xe] (pairs of short) */
18779: #define dbg_trcr (T)
18780: { unsigned char *cp,*ep;
18781: short x,*xp;
18782: int cv,pv; /* current,prior binary pixel value */
18783: ep=(cp=rasp+lm)+rm; x=olm; xp=runp;
18784: pv=0; /* assume pixels left of 'lm' are 0 */
18785: while (cp<=ep) {
18786: if((*cp)<thresh) {
18787: /* black pixel */
18788: cv=1;
18789: if(pv==0) { *xp = x; xp++; };
18790: }
18791: else { /* white pixel */
18792: cv=0;
18793: if(pv==1) { *xp = x-1; xp++; };
18794: };
18795: pv=cv; x++;
18796: cp++;
18797: };
18798: if(pv==1) { *xp = x-1; xp++; }; /* assume pixels right of 'rm' is 0 */
18799: return((xp-runp)/2);
18800: }
18801:
18802: /* Transform a sequence of rle-lines using trimming, offsetting, scaling,
18803: truncation, and reverse-video. Scaling may lead to interpolation or
18804: decimation of lines, so an input line may be mapped into 0, 1, or more
18805: output lines.
18806: Input lines may be buffered, and there may be latency. To flush buffers,
18807: this must be called with NULL argument at end of the sequence. Each output
18808: line will be passed to function `sink()', which returns 1 if OK and 0 to quit. Quits are passed back immediately with no latency. Sink's 1st arg RLE_Line
18809: *l is a line of runs in output coordinates, whose `len' is the maximum length
18810: of the line. l==NULL means end of sequence.
18811: Return 1 if OK, 0 to quit. A copy of *l is passed to sink().
18812: a->sy is incremented for every line written to the sink, and is attached to
18813: the output lines as *.y.
18814: */
18815: int transform_rlel(l,a,sink,sa)
18816: RLE_Line *l; /* NULL if end of sequence */
18817: Transform_rlel_arg *a;
18818: int (*sink)(); /* takes args: (RLE_Line *), and int */
18819: VOID *sa; /* passed to sink() as 2nd arg */
18820: { RLE_Line m,r;
18821: register RLE_Run *rp,*ep,*mp;
18822: RLE_Run mr,mm,rr;
18823: int rm;
18824: int o_a_x,o_b_x; /* maximum output index */
18825: if(l==NULL) {
18826: sink(NULL,sa);
18827: return(1);
18828: };
18829: m.len = l->len;
18830: m.runs = l->runs;
18831: if(a->ident) {
18832: if(m.runs>0) memcpy(m.r,l->r,2*m.runs*sizeof(short));
18833: m.y = a->sy;
18834: if(sink(&m,sa)==0) return(0);
18835: else { a->sy++;
18836: return(1);
18837: };
18838: };
18839: /* maximum permissable output bounds */
18840: o_a_x = (int)((a->tr.a.x + a->off.x)*a->scl.x);
18841: o_b_x = o_a_x + a->wh.x - 1;
18842: if(a->sy<=((int)a->dy)) {
18843: /* compute runs to be ouput: rp - input runs; mp - output runs*/
18844: mp=(m.r - 1);
18845: for(ep=(rp=l->r)+l->runs; rp<ep; rp++) {
18846: /* trim using a->tr */
18847: mr = *rp;
18848: if(mr.xe < a->tr.a.x) /* off left margin */ continue;
18849: if(mr.xs > a->tr.b.x) /* off right margin */ break;
18850: if(mr.xs < a->tr.a.x) /* extends left too far */
18851: mr.xs=a->tr.a.x;
18852: if(mr.xe > a->tr.b.x) /* extends right too far */
18853: mr.xe=a->tr.b.x;
18854:
18855: /* offset using a->off */
18856: mr.xs += a->off.x;
18857: mr.xe += a->off.x;
18858:
18859: /* expand using a->scl */
18860: mr.xs = (int)(mr.xs*a->scl.x);
18861: mr.xe = ((int)((mr.xe+1)*a->scl.x))-1;
18862: if(mr.xe<mr.xs) mr.xe=mr.xs;
18863:
18864: /* truncate to maximum output width */
18865: if(mr.xe<o_a_x) /* off left margin */ continue;
18866: if(mr.xs>o_b_x) /* off right margin */ break;
18867: if(mr.xs<o_a_x) /* extends left too far */ mr.xs=o_a_x;
18868: if(mr.xe>o_b_x) /* extends right too far */ mr.xe=o_b_x;
18869: /* store */
18870: if(mp < m.r) /* first */ *(++mp) = mr;
18871: else /* can merge with prior run? */ {
18872: if(mp->xe >= (mr.xs-1)) /* yes */ mp->xe = mr.xe;
18873: else /* no */ *(++mp) = mr;
18874: };
18875: };
18876: m.runs = mp - m.r + 1;
18877: m.len = a->wh.x;
18878: do { m.y = a->sy;
18879: if(a->rev) {
18880: /* r = reverse-video(m) */
18881: rp=r.r; rr.xs=o_a_x;
18882: for(ep=(mp=m.r)+m.runs; mp<ep; mp++) {
18883: if(rr.xs<mp->xs) {
18884: rr.xe=mp->xs-1;
18885: *(rp++)=rr;
18886: };
18887: rr.xs=mp->xe+1;
18888: };
18889: if(rr.xs<=o_b_x) {
18890: rr.xe=o_b_x;
18891: *(rp++)=rr;
18892: };
18893: r.runs = rp-r.r;
18894: r.len = m.len;
18895: r.y = m.y;
18896: if(sink(&r,sa)==0) return(0);
18897: }
18898: else { if(sink(&m,sa)==0) return(0); };
18899: a->sy++;
18900: }
18901: while(a->sy<=((int)a->dy));
18902: };
18903: a->dy += a->scl.y;
18904: return(1);
18905: }
18906:
18907: /* Insert a (copy of) the given RLE_Line in the RLE_Lines */
18908: insert_rlel(rlp,rlsp)
18909: RLE_Line *rlp;
18910: RLE_Lines *rlsp;
18911: { abort("insert_rlel: unimplemented");
18912: }
18913:
18914: err_RLE_line(s,rl)
18915: char *s; /* name */
18916: RLE_Line *rl;
18917: { RLE_Run *r;
18918: int ri;
18919: if(rl==NULL) fprintf(stderr,"RLEL %10s NULL\n",s);
18920: else { fprintf(stderr,"RLEL %10s y%d r%d l%d: ",
18921: s,rl->y,rl->runs,rl->len);
18922: for(ri=0,r=rl->r;ri<rl->runs;ri++,r++)
18923: fprintf(stderr,"[%d,%d] ",r->xs,r->xe);
18924: fprintf(stderr,"\n");
18925: };
18926: }
18927:
18928: 0707070035351135271006640007620000050000010264220476773367400001100000047346stdocr.h /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
18929: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
18930: /* The copyright notice does not imply actual or intended publication. */
18931: /* AUTHORS: */
18932: /* H. S. Baird - ATT-BL MH - first versions */
18933: /* stdocr.h -- conventional OCGR constants, typedefs, and file formats
18934: NOTE: sensitive to prior:
18935: `#define MAIN 1'
18936: `#define CPU ?'
18937: `#define OS ?' */
18938:
18939: extern int errno; /* UNIX system call error number */
18940:
18941: #ifndef MAIN
18942: #define MAIN 0
18943: #endif
18944:
18945: #define FWRI (T) /* use machine-independent format for dim-file writes */
18946: #define FRDI (T) /* use machine-independent format for dim-file reads */
18947:
18948: #ifndef PI
18949: #define PI 3.1415926535
18950: #endif
18951:
18952: extern int Readvax; /* T. Thompson flag: see Coord.c */
18953:
18954: #include "limits.h" /* machine-dependent numeric extreme values */
18955: #include "fioi.h" /* machine-independent types and binary I/O */
18956: #include "boole.h" /* boolean type */
18957: #include "Units.h" /* OCR-specific units */
18958: #include "Coord.h" /* scanner coordinates & basic geometry */
18959: #include "ric.h" /* ricoh scanner page & file formats */
18960:
18961: /* 5620 dimensions, in dots */
18962: #define Width5620 800
18963: #define Height5620 1024
18964:
18965: /* used (in clc.c) to compute absolute maximum value of natural
18966: log values used in Bayesian binary weights */
18967: #define LOG_ABS_MAX 3.0
18968:
18969: #define Merit float /* heuristic ``merit'' takes on values in [0,1] */
18970: /* machine-independent I/O: range [0.0-1.0], precision .0000153 */
18971: #define fwri_Merit(F,V) fwri_uint2((F),((V)*USHRT_MAX))
18972: #define frdi_Merit(F) (frdi_uint2(F)/(Merit)USHRT_MAX)
18973:
18974: #define Prob float /* ``probability'' takes on values in [0,1] */
18975: /* machine-independent I/O: range [0.0-1.0], precision .0000153 */
18976: #define fwri_Prob(F,V) fwri_uint2((F),((V)*USHRT_MAX))
18977: #define frdi_Prob(F) (frdi_uint2(F)/(Prob)USHRT_MAX)
18978:
18979: #define Pts float /* text-size units: ``points'' (1/72) inch */
18980: /* machine-independent I/O: range [0,655.36], precision 0.01 ([0,9.1] inches) */
18981: #define fwri_Pts(F,V) fwri_uint2((F),((V)*100.0))
18982: #define frdi_Pts(F) (frdi_uint2(F)/100.0)
18983:
18984: #define Ems float /* em-space units */
18985: /* machine-independent I/O: range [-32.768,32.767], precision 0.001 */
18986: #define fwri_Ems(F,V) fwri_int2((F),((V)*1000.0))
18987: #define frdi_Ems(F) (frdi_int2(F)/1000.0)
18988:
18989: /* class name - long enough to be a unix file name */
18990: #define Cln_len (14) /* maximum no. chars (DIRSIZ in some UNIX's) */
18991: #define Cln_lenp (Cln_len+1) /* maximum size of array */
18992: typedef char Cln[Cln_lenp];
18993: #define fwri_Cln(F,S) fwri_str((F),(S))
18994: #define frdi_Cln(F,S) frdi_strn((F),(S),Cln_lenp)
18995:
18996: /* font name */
18997: #define Fontn_len (Cln_len) /* maximum no. chars */
18998: #define Fontn_lenp (Cln_lenp) /* maximum size of array */
18999: typedef char Fontn[Fontn_lenp];
19000: #define fwri_Fontn(F,S) fwri_str((F),(S))
19001: #define frdi_Fontn(F,S) frdi_strn((F),(S),Fontn_lenp)
19002:
19003: typedef struct ClassId {
19004: Fontn f; /* font name */
19005: Pts s; /* size in points */
19006: Cln c; /* printable symbol name (``class-name'') */
19007: short v; /* symbol variant no. 0,1,... */
19008: } ClassId;
19009:
19010: #define Init_ClassId {"",0.0,"",0}
19011: #if MAIN
19012: ClassId empty_ClassId = Init_ClassId;
19013: #else
19014: extern ClassId empty_ClassId;
19015: #endif
19016: char *classid_toa(); /* in chcln.c */
19017: #define eq_classid(a,b) ((!strcmp((a).f,(b).f))&&((a).s==(b).s)&&(!strcmp((a).c,(b).c))&&((a).v==(b).v))
19018:
19019: #define fwri_ClassId(F,P) { \
19020: fwri_Fontn((F),(P)->f); \
19021: fwri_Pts((F),(P)->s); \
19022: fwri_Cln((F),(P)->c); \
19023: fwri_uint1((F),(P)->v); \
19024: }
19025: #define frdi_ClassId(F,P) ( feof(F)? 0: ( \
19026: frdi_Fontn((F),(P)->f), \
19027: (P)->s=frdi_Pts(F), \
19028: frdi_Cln((F),(P)->c), \
19029: (P)->v=frdi_uint1(F), \
19030: (ferror(F)? -errno: 1) ) )
19031:
19032: /* Convert variant no. to ASCII character, and vice versa */
19033: #define vtoc(V) (((V)<=9)?('0'+(V)):(((V)<=35)?('a'+((V)-10)):('A'+((V)-36))))
19034: #define ctov(C) ((((C)>='0')&&((C)<='9'))?((C)-'0'):((((C)>='a')&&((C)<='z'))?(10+((C)-'a')):(36+((C)-'A'))))
19035:
19036: /* parametric values: */
19037: #define Pval float
19038: /* machine-independent I/O: precision 0.0001 & range [-838.8608,838.8607] */
19039: #define fwri_Pval(F,V) fwri_int4((F),(V)*1000.0)
19040: #define frdi_Pval(F) (frdi_int4(F)/1000.0)
19041:
19042: typedef struct { /* parametric point */
19043: Pval x;
19044: Pval y;
19045: } Pp;
19046:
19047: #define Init_Zero_Pp {0.0,0.0}
19048: #if MAIN
19049: Pp zero_Pp = Init_Zero_Pp;
19050: #else
19051: extern Pp zero_Pp;
19052: #endif
19053:
19054: #define fwri_Pp(F,P) { fwri_Pval((F),(P)->x); fwri_Pval((F),(P)->y); }
19055: #define frdi_Pp(F,P) ( feof(F)? 0: ( \
19056: (P)->x=frdi_Pval(F), \
19057: (P)->y=frdi_Pval(F), \
19058: (ferror(F)? -errno: 1) ) )
19059:
19060: /* metrics: ABSS, EUCL, MAXV */
19061: #define ABSS 'a'
19062: #define EUCL 'e'
19063: #define MAXV 'm'
19064: typedef short Metric;
19065:
19066: #define fwri_Metric(F,V) fwri_ch((F),(V))
19067: #define frdi_Metric(F) (frdi_ch(F))
19068:
19069: /* a vectorized blob file is a sequence of blob-descriptions.
19070: a blob-description is a sequence of "vector" records; there are two
19071: types of blob descriptions:
19072: DOT:
19073: 'D'-vector (with bounding box)
19074: CHAR:
19075: 'C'-vector, followed by:
19076: one 'B'-vector (bounding-box), and
19077: any number of: 'S' (stroke),
19078: 'G' (edge),
19079: 'O' (hole),
19080: 'A' (arc),
19081: 'C' (corner),
19082: 'P' (end-point), and
19083: 'V' & 'W' (boundary angles - 1 each),
19084: and terminated with one 'E' vector (giving classname)
19085: */
19086:
19087: #define Vrec_len 5
19088: typedef short Vrec[Vrec_len];
19089:
19090: /* subshape values */
19091: /* #define U 0 uninitialized */
19092: #define NA (SHRT_MAX) /* deliberately not-assigned (classifier failure) */
19093:
19094: #define Dim short /* specifies dimension 1,..,MaxDim */
19095: #define MaxDim 4
19096:
19097: #define fwri_Dim(F,V) fwri_uint1((F),(V))
19098: #define frdi_Dim(F) (frdi_uint1(F))
19099:
19100: #define Seq int /* sequence nos; indices into tables */
19101: #define FISeq 0 /* first value */
19102: #define NLSeq -1 /* conventional NULL value */
19103: #define S1Seq 0200000000 /* special bit 1 of Seq */
19104: #define S2Seq 0100000000 /* special bit 2 of Seq */
19105: #define NSSeq 0077777777 /* non-special bits */
19106:
19107: #define fwri_Seq(F,V) fwri_int4((F),(V))
19108: #define frdi_Seq(F) (frdi_int4(F))
19109:
19110: typedef short Liv; /* limit value: scaled and truncated from floating-pt */
19111: #define Liv_MAX (SHRT_MAX)
19112: #define Liv_MIN (SHRT_MIN)
19113:
19114: #define fwri_Liv(F,V) fwri_int2((F),(V))
19115: #define frdi_Liv(F) (frdi_int2(F))
19116:
19117: typedef short Lit; /* limit type, two flavors: */
19118: #define MN 0 /* min: MN < v */
19119: #define MX 1 /* max: v <= MX */
19120:
19121: typedef Liv Ivl[2]; /* interval: ( Ivl[MN], Ivl[MX] ] */
19122:
19123: typedef Ivl Rec[MaxDim]; /* rectangular parallelopiped of limits in DIM-space */
19124:
19125: /* a normalized blob file is a sequence of:
19126: Nb_h header, followed by Nb_h.ss of:
19127: Nb_s contour shapes */
19128: typedef struct {
19129: ClassId ci; /* class name */
19130: Bbx bb; /* bounding box */
19131: Pval rsz; /* raw character size (Ems) */
19132: Pval bht; /* height-above-baseline (Ems) */
19133: Pval rwd; /* width (Ems) */
19134: Pval rar; /* area (square-Ems) */
19135: Pval rpe; /* perimiter (Ems) */
19136: Pval asp; /* aspect ratio (h/w) */
19137: Pval blk; /* fraction of Bbx area that is black */
19138: Pval per; /* perimeter of blob as multiple of Bbx perim */
19139: Pval gale; /* Gale's feature: incl. angle 'tween 2 longest sides */
19140: short ss; /* no. of shapes to follow */
19141: } Nb_h;
19142:
19143: #define MAX_SHAPES_EACH 1024 /* Max no. shapes per Blob/Char/item */
19144:
19145: /* Shape is tiny (below threshold, may be pruned): a flag ORed into shape type */
19146: #define Sh_tiny (0x80)
19147:
19148: /* Shape types: */
19149: #define U 0 /* uninitialized */
19150: #define Sh_FI 1 /* first shape no. */
19151: #define Sh_B 1 /* blob (connected black region) */
19152: #define Sh_H 2 /* hole (connected white region) */
19153: #define Sh_S 3 /* stroke (undirected line-segment) */
19154: #define Sh_E 4 /* edge (directed line-segment along boundary) */
19155: #define Sh_C 5 /* concavity (intrusion from convex hull): its `cover' edge */
19156: #define Sh_D 6 /* direction and depth of concavity */
19157: #define Sh_A 7 /* locally-maximal convex arc (encloses black) */
19158: #define Sh_V 8 /* locally-maximal concave arc (encloses white) */
19159: #define Sh_P 9 /* endpoint (0-junction) */
19160: #define Sh_T 10 /* detail (left- and right-facing ticks) */
19161: #define Sh_X 11 /* crossing (X) */
19162: #define Sh_Y 12 /* global scalar variables, combined */
19163: #define Sh_Z 13 /* more global scalar variables, combined */
19164: #define Sh_LA 13 /* last of variable-no-of-occurences shape-types */
19165: #define Sh_MNY (Sh_LA+1)
19166: #define SHS_MNY (Sh_MNY)
19167:
19168: #if (MAIN)
19169: /* shape-names, given shape-type */
19170: char Sh_nam[SHS_MNY] =
19171: {'U', 'B', 'H', 'S', 'E', 'C', 'D', 'A', 'V', 'P', 'T', 'X', 'Y', 'Z'};
19172: /* "dimension" -- no parameters in normalized form */
19173: short Sh_dim[SHS_MNY] =
19174: { 0, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 3, 1};
19175: /* absolute minimum parametric values possible -- must be >= -1.0
19176: (see norm.c & fiodict.c) */
19177: Pval Sh_MN[SHS_MNY][MaxDim]
19178: = { { 0.0, 0.0, 0.0, 0.0}, /* U */
19179: {-0.5, -0.5, -0.5/*see mkd*/}, /* B */
19180: {-0.5, -0.5, -0.5/*see mkd*/}, /* H */
19181: {-0.5, -0.5, -0.5, -0.5}, /* S */
19182: {-0.5, -0.5, -0.5, -0.5}, /* E */
19183: {-0.5, -0.5, -0.5, -0.5}, /* C */
19184: {-0.5, -0.5, -0.5, -0.5}, /* D */
19185: {-0.5, -0.5, -0.5, -0.5}, /* A */
19186: {-0.5, -0.5, -0.5, -0.5}, /* V */
19187: {-0.5, -0.5, -0.5, -0.5}, /* P */
19188: {-0.5, -0.5, -0.5}, /* T */
19189: {-0.5, -0.5}, /* X */
19190: {-0.5, -0.5, -0.5}, /* Y */
19191: {-0.5} /* Z */
19192: };
19193: /* absolute maximum parametric value possible -- must be <= 1.0
19194: (see norm.c & fiodict.c) */
19195: Pval Sh_MX[SHS_MNY][MaxDim]
19196: = { { 0.0, 0.0, 0.0, 0.0}, /* U */
19197: {0.5, 0.5, 1.0/*see mkd*/}, /* B */
19198: {0.5, 0.5, 1.0/*see mkd*/}, /* H */
19199: {0.5, 0.5, 0.5, 0.5}, /* S */
19200: {0.5, 0.5, 0.5, 0.5}, /* E */
19201: {0.5, 0.5, 0.5, 0.5}, /* C */
19202: {0.5, 0.5, 0.5, 0.5}, /* D */
19203: {0.5, 0.5, 0.5, 0.5}, /* A */
19204: {0.5, 0.5, 0.5, 0.5}, /* V */
19205: {0.5, 0.5, 0.5, 0.5}, /* P */
19206: {0.5, 0.5, 0.5}, /* T */
19207: {0.5, 0.5}, /* X */
19208: {0.5, 0.5, 0.5}, /* Y */
19209: {0.5} /* Z */
19210: };
19211: /* minimum magnitude of (r,i) part of certain shapes */
19212: Pval A_ri_minmag = 0.25;
19213: Pval P_ri_minmag = 0.25;
19214: #else
19215: extern char Sh_nam[];
19216: extern short Sh_dim[];
19217: extern Pval Sh_MN[][MaxDim];
19218: extern Pval Sh_MX[][MaxDim];
19219: extern Pval A_ri_minmag;
19220: extern Pval P_ri_minmag;
19221: #endif
19222:
19223: #define MIN_SD 0.001 /* minimum std-dev permitted */
19224:
19225: typedef Pval Spar[MaxDim]; /* shape parameters */
19226:
19227: typedef struct Nb_s {
19228: short t; /* shape type: one of U S O A C etc, perhaps |Sh_tiny */
19229: Spar p; /* parametric values */
19230: } Nb_s;
19231:
19232: /* indices into parametric values */
19233: /* blobs */
19234: #define B_x 0 /* (x,y) location of dot wrt bounding-box */
19235: #define B_y 1
19236: #define B_r 2 /* size of dot */
19237: /* holes */
19238: #define H_x 0 /* (x,y) location of center wrt bounding-box */
19239: #define H_y 1
19240: #define H_r 2 /* size of hole */
19241: /* strokes */
19242: #define S_x 0 /* (x,y) location of stroke center wrt bounding box */
19243: #define S_y 1
19244: #define S_r 2 /* (r,i) real-imag parts of rotation-length vector; */
19245: #define S_i 3 /* rotation angle *2 since strokes have only [0,PI] range */
19246: /* edges */
19247: #define E_x 0 /* (x,y) location of edge center wrt bounding box */
19248: #define E_y 1
19249: #define E_r 2 /* (r,i) real-imag parts of direction-length vector */
19250: #define E_i 3
19251: /* concavity hull edge */
19252: #define C_x 0 /* (x,y) location of center of hull-bdy edge wrt bounding-box */
19253: #define C_y 1
19254: #define C_r 2 /* (r,i) real-imag parts of hull-bdy edge */
19255: #define C_i 3
19256: /* concavity depth & direction */
19257: #define D_x 0 /* (x,y) location of center of depth & direction vector */
19258: #define D_y 1
19259: #define D_r 2 /* (r,i) real-imag parts of depth & direction vector */
19260: #define D_i 3
19261: /* locally-maximal convex arc */
19262: #define A_x 0 /* (x,y) location of center of enclosed area */
19263: #define A_y 1
19264: #define A_r 2 /* (r,i) real-imag parts of `incompleteness' vector */
19265: #define A_i 3
19266: /* locally-maximal concave arc */
19267: #define V_x 0 /* (x,y) location of center of enclosed area */
19268: #define V_y 1
19269: #define V_r 2 /* (r,i) real-imag parts of `incompleteness' vector */
19270: #define V_i 3
19271: /* endpoint */
19272: #define P_x 0 /* (x,y) location of center of hull-bdy wrt bounding-box */
19273: #define P_y 1
19274: #define P_r 2 /* (r,i) real-imag parts of direction-depth vector */
19275: #define P_i 3
19276: /* ticks: left-, right-, top-, & bottom-facing extrema near ends */
19277: #define T_x 0 /* signed distance from centroid along principal axis */
19278: #define T_y 1 /* signed perpendicular distance from axis */
19279: #define T_a 2 /* angle of principal axis, within worst-case range */
19280: /* crossings */
19281: #define X_x 0 /* (x,y) location of crossing wrt bounding-box */
19282: #define X_y 1
19283: /* global scalars, combined */
19284: #define Y_a 0 /* log(aspect_ratio=hgt/wid) */
19285: #define Y_b 1 /* ratio of area to bbx_area */
19286: #define Y_p 2 /* ratio of perimeter to bbx_perimeter */
19287: /* global scalars, combined (more) */
19288: #define Z_g 0 /* Gale's feature: included angle between two longest bdy edges */
19289:
19290: /* scalar features field indices */
19291: #define SF_RSZ 0 /* relative size (height in ems) */
19292: #define SF_BHT 1 /* height above baseline (ems) */
19293: #define SF_RWD 2 /* relative width (ems) */
19294: #define SF_RAR 3 /* relative area (square-ems) */
19295: #define SF_RPE 4 /* relative perimeter (ems) */
19296: #define SF_ASP 5 /* aspect-ratio */
19297: #define SF_BLK 6 /* fraction of Bbx that is black */
19298: #define SF_PER 7 /* ratio of perimeter to BBx per */
19299: #define SF_GALE 8 /* Gale's feature: incl. ang. between 2 longest edges */
19300: #define SF_N 8 /* index of last var that's not an occurrence-count */
19301: #define SF_MNY (SF_N+Sh_LA+1)
19302:
19303: #if MAIN
19304: /* ``Is this feature available early enough to be used in fast scalar-
19305: feature preclassifier?'' (Must not depend on shape analysis.) */
19306: boolean SFfeature[SF_MNY] = {
19307: F, F, F, F, F, T, T, T, F,
19308: T, T, T, T, T, T, T, T, T, T, T, F, F };
19309: /* ``Is this feature discrete (integer-valued)?'' (Affects construction
19310: of scalar-decision tree preclassifier.) */
19311: boolean SFdiscrete[SF_MNY] = {
19312: F, F, F, F, F, F, F, F, F,
19313: T, T, T, T, T, T, T, T, T, T, T, T, T };
19314: #else
19315: extern boolean SFfeature[];
19316: extern boolean SFdiscrete[];
19317: #endif
19318:
19319: typedef Pval SFv[SF_MNY];
19320:
19321: /* blob tracer (boundary angles) features field indices */
19322: #define TR_MNY 8
19323:
19324: typedef Pval TRv[TR_MNY];
19325:
19326: /* tracer decision-tree header */
19327: typedef struct TRtr {
19328: struct SFdnode *TRd; /* array of decision-nodes */
19329: struct Cl ***clist; /* list of (class-ptr)-lists */
19330: } TRtr;
19331:
19332: /* Ss - sub-shape list-item */
19333: typedef struct Ss {
19334: Seq seq; /* globally unique sequence no */
19335: Seq shs; /* shape-hdr seq no */
19336: Seq cls; /* class sequence no */
19337: short no; /* sub-shape number (0,1,2..., NA) */
19338: float focc; /* fraction of training set w/ >=1 occurrence */
19339: float fdup; /* fraction of training set w/ >=2 occurrence */
19340: Spar me; /* mean parameters */
19341: Spar sd; /* std-dev parameters */
19342: Spar min; /* min limits (for fast checking) */
19343: Spar max; /* max limits (for fast checking) */
19344: Rec r; /* rectangular parallelopiped in Liv space */
19345: Pval fr; /* fraction of training set covered */
19346: short nuse; /* for current blob, no. uses */
19347: float nocc; /* occurrences: no. blobs with >=1 of these */
19348: float ndup; /* duplicates: no. blobs with >=2 of these */
19349: float mind; /* minimum scaled distance from cluster among uses */
19350: float merit; /* merit score resulting from 'nuse' matches to this */
19351: struct Ss *ne; /* ptr to next in list */
19352: } Ss;
19353:
19354: #define MAX_SS 8192 /* see 'kdt.h' for reasons */
19355:
19356: /* BMask: 1-d, variable-length packed bitstring (N = no. bits). The string
19357: is stored in an array of (unsigned int). It is often accessed via a fast
19358: ascending sequence of 'short' pointers (unsigned short *) or (unsigned char *):
19359: in these cases, enough are used to completely cover all the (unsigned int)s,
19360: even though that may be more than enough, to ensure that the result is
19361: insensitive to machine-dependent short-order-in-ints and char-order-in-shorts.
19362: BMask_ni(N) no. unsigned ints holding bit-data
19363: BMask_si(N) no. unsigned shorts covering bit-data (exactly 2x _ni)
19364: BMask_ci(N) no. unsigned chars covering bit-data (exactly 4x _ni)
19365: BMask_size(N) total no. bytes in, or pointed to by BMask:
19366: sizeof(n) + sizeof(mny) + sizeof(r) + sizeof(malloc space)
19367: */
19368: #define BMask_ni(N) (((N)+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))
19369: #define BMask_si(N) (2*BMask_ni(N))
19370: #define BMask_ci(N) (4*BMask_ni(N))
19371: #define BMask_size(N) (3*sizeof(unsigned int)+(BMask_ci((N))))
19372:
19373: typedef struct BMask {
19374: unsigned int n; /* no. of bits stored (==N above) */
19375: unsigned int mny; /* no. bits set to 1 */
19376: unsigned int r; /* represents `r' BMasks altogether */
19377: union { /* packed bits: 0th bit is 01 */
19378: unsigned int *i; /* malloc space: int [Bmask_ni] */
19379: unsigned short *s; /* malloc space: short [Bmask_si] */
19380: int ii; /* index into (unsigned int)[] array */
19381: int si; /* index into (unsigned short)[] array */
19382: } u;
19383: } BMask;
19384:
19385: #define Init_BMask {0,0,0,}
19386: #if MAIN
19387: BMask empty_BMask = Init_BMask;
19388: #else
19389: extern BMask empty_BMask;
19390: #endif
19391:
19392:
19393: typedef struct BMasks {
19394: unsigned short mny; /* no. BMasks */
19395: unsigned short r; /* represents `r' BMasks altogether */
19396: unsigned short shallow; /* 0 <= shallow <= mny */
19397: unsigned short alloc; /* no. items allocated in .a[] */
19398: union { BMask *a; /* array[mny] of BMasks */
19399: int bi; /* index into (BMask)[] array */
19400: } u;
19401: } BMasks;
19402:
19403: #define Init_BMasks {0,0,0,0,}
19404: #if MAIN
19405: BMasks empty_BMasks = Init_BMasks;
19406: #else
19407: extern empty_BMasks;
19408: #endif
19409:
19410: /* Sh - shape list-item */
19411: typedef struct Sh {
19412: Seq seq; /* unique sequence no. */
19413: short t; /* shape type: S, H, X, etc */
19414: short nss; /* no. sub-shapes in the list */
19415: float mess; /* mean no. sub-shapes in training set */
19416: float sdss; /* std-dev of sub-shapes in training set */
19417: float NAocc; /* prob at least one shape not-assigned */
19418: float NAdup; /* prob more than one not-assigned */
19419: Ss NAss; /* "not-assigned" data */
19420: Ss *fi; /* first sub-shape */
19421: Ss *la; /* last sub-shape */
19422: struct Sh *ne; /* next shape */
19423: } Sh;
19424:
19425: /* Cl - class list-item */
19426: typedef struct Cl {
19427: Seq seq; /* unique sequence no. 0,1,... */
19428: Cln c; /* class name */
19429: float shNA; /* fraction of shapes unassigned */
19430: float blDP; /* fraction of blobs w/ >=1 duplicate shape-match*/
19431: float blAL; /* average extra alternate shape-matches / blob */
19432: SFv sf_me; /* scalar-features: means, std-devs */
19433: SFv sf_sd;
19434: BMask bm; /* canonical BMask */
19435: BMasks bms; /* additional representative BMask records */
19436: Sh *sha[Sh_MNY]; /* table of pointers to shape-types */
19437: Sh *fi; /* first owned shape */
19438: Sh *la; /* last owned shape */
19439: short unmat[Sh_MNY]; /* counts of unmatched shapes/shape-type */
19440: struct Ssm *ssmfi; /* first sub-shape match for this class */
19441: TRtr *tr; /* pointer to tracer decision tree (if any) */
19442: TRv tr_me; /* tracer-features: means, std-devs */
19443: TRv tr_sd;
19444: float m_me; /* mean, std-err of merit (in training set) */
19445: float m_sd;
19446: float bayes; /* Bayesian merit: a posteriori log-probability */
19447: Merit m01; /* Haming, etc. merit in range [0,1] */
19448: Merit merit; /* sort and truncate based on this merit */
19449: short pass; /* the last classification method this class passed */
19450: int ch_mny; /* No. Chars of this class in a subset */
19451: int ss_mny; /* No. Chars with given feature */
19452: boolean force_reseg; /* forcibly resegment Chars of this Class */
19453: struct Cl *ne; /* next class */
19454: } Cl;
19455:
19456: /* MAX_CL (max no. of classes) is defined in CPU.h */
19457: #define MAX_SH (MAX_CL*SH_MNY)
19458:
19459: typedef struct Classes {
19460: int mny; /* number of items in array */
19461: Cl **clpa; /* Cl *clpa[cl_mny+1]: NULL-term'd array of ptrs */
19462: } Classes;
19463: #define Init_Classes {0,NULL}
19464: #if MAIN
19465: Classes empty_Classes = Init_Classes;
19466: #else
19467: extern Classes empty_Classes;
19468: #endif
19469:
19470: typedef struct Ssm { /* sub-shape match record */
19471: Seq isn; /* input shape sequence no (w/in blob) */
19472: Cl *clp; /* owning class, shape, sub-shape... */
19473: Sh *shp;
19474: Ss *ssp;
19475: float mind; /* distance to closest assigned sub-shape */
19476: boolean alt; /* T if this is an alternative (not the first) */
19477: struct Ssm *ne; /* next, prior ptrs in list */
19478: struct Ssm *pr;
19479: } Ssm;
19480:
19481: /* return pathname of OCR directory; if environment variable OCRDIR
19482: is set, it is used; otherwise #defined variable OCRDIR is used. */
19483: #if MAIN
19484: char *getenv();
19485: char *ocrdir()
19486: { char *ocrdir_ev;
19487: if((ocrdir_ev=getenv("OCRDIR"))!=NULL) {
19488: return(ocrdir_ev);
19489: }
19490: else return(OCRDIR);
19491: }
19492: #else
19493: char *ocrdir();
19494: #endif
19495: 0707070035351135261006640007620000050000010264330476773367400001100000033171sunlib.c /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
19496: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
19497: /* The copyright notice does not imply actual or intended publication. */
19498: /* AUTHORS: */
19499: /* T. Thompson - ATT-BL HO - first versions */
19500: #include <stdio.h>
19501: #include <sys/types.h>
19502: #include <sys/stat.h>
19503: #include <sys/ioctl.h>
19504: #include <pixrect/pixrect.h>
19505: #include <pixrect/pixfont.h>
19506: #include <suntool/sunview.h>
19507: #include <suntool/canvas.h>
19508: #include "met.h"
19509: #include "boole.h"
19510: #include "Coord.h"
19511:
19512: #define XYSCALE(x,y) (x=(x-obotx)*scx+botx),(y=(y-oboty)*scy+boty)
19513:
19514: struct pixrect *source_pixrect;
19515:
19516: Frame Mainframe;
19517: Canvas Win;
19518: int Winfd;
19519: Pixwin *Pw;
19520: int Key = -1;
19521: int Mousex;
19522: int Mousey;
19523: int Colorval;
19524:
19525: /* CMAPSIZE MUST BE A POWER OF 2 (restriction in sun colormap stuff)*/
19526: #define CMAPSIZE 8
19527:
19528: #define DEFAULTCOLOR (CMAPSIZE-1)
19529:
19530: #define S_WHITE 0
19531: #define S_RED 1
19532: #define S_GREEN 2
19533: #define S_BLUE 3
19534: #define S_GREY 4
19535: #define S_AQUA 5
19536: #define S_YELLOW 6
19537: #define S_BLACK 7
19538:
19539: int mycolors[CMAPSIZE][3] = {
19540: 255, 255, 255, /* white */
19541: 230, 0, 75, /* red */
19542: 0, 200, 0, /* green */
19543: 0, 0, 200, /* blue */
19544: 200, 200, 200, /* grey */
19545: 0, 160, 170, /* aqua */
19546: 250, 220, 0, /* yellow */
19547: 0,0,0 /* foreground (black) */
19548: };
19549:
19550:
19551: void domouse();
19552:
19553: extern int Debug;
19554:
19555: extern event_proc();
19556:
19557: static int
19558: boty = 32767, /* screen bottom y */
19559: botx = 0, /* screen bottom x */
19560: topx = 32767, /* screen top x */
19561: topy = 0, /* screen top y */
19562: oboty = 0, /* user's bottom y */
19563: obotx = 0, /* user's bottom x */
19564: otopy = 32767, /* user's top y */
19565: otopx = 32767; /* user's top x */
19566:
19567: static double
19568: scx = 1.0, /* scale factor x */
19569: scy = 1.0 /* scale factor y */
19570: ;
19571: static int lastx = 0;
19572: static int lasty = 0;
19573: static int lmode = 3; /* drawing mode (default is xor)*/
19574:
19575: int Prevlmode = 3;
19576:
19577: #define signof(x) ((x)>=0.0?(1):(-1))
19578: #define absof(x) ((x)>=0.0?(x):(-x))
19579:
19580: void flushout() { }
19581:
19582: short bsy_pixrect_data[] = {
19583: /* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
19584: */
19585: 0x7FFE,0x4002,0x200C,0x1A38,0x0FF0,0x07E0,0x03C0,0x0180,
19586: 0x0180,0x0240,0x0520,0x0810,0x1108,0x23C4,0x47E2,0x7FFE
19587: };
19588: mpr_static(busy_pixrect, 16, 16, 1, bsy_pixrect_data);
19589:
19590: int childpid;
19591:
19592: Rect sweeparect();
19593:
19594: om_open()
19595: {
19596: Rect r;
19597:
19598: r = sweeparect();
19599:
19600: notify_errno = NOTIFY_OK;
19601:
19602: Mainframe = window_create((Window)NULL, FRAME,
19603: FRAME_LABEL, "ocr",
19604: 0 );
19605: Win = window_create(Mainframe, CANVAS, 0);
19606: Pw = canvas_pixwin(Win);
19607:
19608: window_set(Mainframe, WIN_X, r.r_left,
19609: WIN_Y, r.r_top, 0);
19610: window_set(Win, WIN_WIDTH, r.r_width,
19611: WIN_HEIGHT, r.r_height, 0);
19612:
19613: window_fit(Win);
19614: window_fit(Mainframe);
19615:
19616: window_set(Mainframe, WIN_SHOW, TRUE, 0);
19617:
19618: Winfd = (int) window_get(Win, WIN_FD);
19619:
19620: if ( notify_errno != NOTIFY_OK ) {
19621: notify_perror("ocr");
19622: exit(1);
19623: }
19624:
19625: setcolormap();
19626:
19627: set_color(DEFAULTCOLOR);
19628: linemod("solid");
19629:
19630: window_set(Win,
19631: WIN_CONSUME_PICK_EVENTS,
19632: WIN_NO_EVENTS,
19633: WIN_ASCII_EVENTS,
19634: WIN_MOUSE_BUTTONS,
19635: LOC_MOVE,
19636: /* LOC_DRAG, */
19637: LOC_WINEXIT, LOC_WINENTER,
19638: LOC_RGNEXIT, LOC_RGNENTER, 0,
19639: 0);
19640:
19641: window_set(Win, WIN_EVENT_PROC, event_proc, 0);
19642:
19643: space(0,0,M_WID,M_HGT);
19644: interact();
19645: }
19646:
19647: /***********************************************************/
19648: /* The code below was taken from the 'dumpregion' program. */
19649: /***********************************************************/
19650:
19651: /*
19652: * Copyright Richard Tobin 1987. You may freely copy, modify and distribute
19653: * this program in source form provided this comment remains intact.
19654: *
19655: * Richard Tobin, JANET: [email protected]
19656: * AI Applications Institute, ARPA: R.Tobin%[email protected]
19657: * Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
19658: */
19659:
19660: #include <sys/file.h>
19661: #include <suntool/fullscreen.h>
19662:
19663: short nwdata[] = {
19664: #include </usr/include/images/stretchNW.cursor>
19665: };
19666: mpr_static(nwpixrect, 16, 16, 1, nwdata);
19667:
19668: short sedata[] = {
19669: #include </usr/include/images/stretchSE.cursor>
19670: };
19671: mpr_static(sepixrect, 16, 16, 1, sedata);
19672:
19673: Rect rect = {0,0,0,0};
19674:
19675: Rect
19676: sweeparect()
19677: {
19678: int wfd, n;
19679: struct fullscreen *fs;
19680: Event event;
19681: Pixwin *pw;
19682: int left, right, top, bottom, temp;
19683: Window win;
19684: double w;
19685: Rect r;
19686:
19687: win = window_create(0, FRAME,
19688: FRAME_OPEN_RECT, &rect,
19689: WIN_CONSUME_PICK_EVENTS,
19690: WIN_ASCII_EVENTS,
19691: LOC_MOVE, WIN_MOUSE_BUTTONS, 0,
19692: 0);
19693:
19694: wfd = (int)window_get(win, WIN_FD);
19695: fs = fullscreen_init(wfd);
19696: pw = fs->fs_pixwin;
19697:
19698: window_set(win,
19699: WIN_CURSOR, cursor_create(CURSOR_IMAGE, &nwpixrect,
19700: CURSOR_XHOT, 0, CURSOR_YHOT, 0,
19701: 0),
19702: 0);
19703:
19704: for ( ;; ) {
19705: n = window_read_event(win, &event);
19706: if ( n < 0 )
19707: continue;
19708: if ( event_is_ascii(&event) ) {
19709: if ( event_id(&event) == 'F' ) {
19710: r.r_left = 10;
19711: r.r_top = 10;
19712: r.r_width = 900;
19713: r.r_height = 900;
19714: }
19715: else {
19716: r.r_left = 542;
19717: r.r_top = 0;
19718: r.r_width = 540;
19719: r.r_height = 512;
19720: }
19721: goto getout;
19722: }
19723: if ( event_is_down(&event) && event_is_button(&event) )
19724: break;
19725: }
19726:
19727: right = left = event_x(&event);
19728: bottom = top = event_y(&event);
19729:
19730: window_set(win,
19731: WIN_CURSOR, cursor_create(CURSOR_IMAGE, &sepixrect,
19732: CURSOR_XHOT, 15, CURSOR_YHOT, 15,
19733: 0),
19734: 0);
19735:
19736: drawbox(pw, left, top, right, bottom);
19737:
19738: while(window_read_event(win, &event) == -1 ||
19739: !event_is_up(&event) ||
19740: !event_is_button(&event))
19741: {
19742: drawbox(pw, left, top, right, bottom);
19743: right = event_x(&event);
19744: bottom = event_y(&event);
19745: drawbox(pw, left, top, right, bottom);
19746: }
19747:
19748: drawbox(pw, left, top, right, bottom);
19749:
19750: if(right < left)
19751: {
19752: temp = right;
19753: right = left;
19754: left = temp;
19755: }
19756: if(bottom < top)
19757: {
19758: temp = bottom;
19759: bottom = top;
19760: top = temp;
19761: }
19762: r.r_left = left;
19763: r.r_top = top;
19764: r.r_width = (right-left);
19765: r.r_height = (bottom-top);
19766: getout:
19767: fullscreen_destroy(fs);
19768:
19769: window_set(win, FRAME_NO_CONFIRM, TRUE, 0);
19770: window_destroy(win);
19771: return r;
19772: }
19773:
19774: drawbox(pw, left, top, right, bottom)
19775: Pixwin *pw;
19776: int left, top, right, bottom;
19777: {
19778: fullscreen_pw_vector(pw, left, top, right, top, PIX_NOT(PIX_DST), 0);
19779: fullscreen_pw_vector(pw, right, top, right, bottom, PIX_NOT(PIX_DST), 0);
19780: fullscreen_pw_vector(pw, right, bottom, left, bottom, PIX_NOT(PIX_DST), 0);
19781: fullscreen_pw_vector(pw, left, bottom, left, top, PIX_NOT(PIX_DST), 0);
19782: }
19783:
19784: ttygets(buff,len)
19785: char *buff;
19786: {
19787: int x, y, n, key;
19788: char *p = buff;
19789:
19790: for ( n=0; n<(len-1); n++ ) {
19791: while ( (key=mouseorkey(&x,&y)) < 0 )
19792: ;
19793: if ( key == '\r' ) /* just in case */
19794: key = '\n';
19795: *p++ = key;
19796: if ( key == '\n' || key == '\0' )
19797: break;
19798: }
19799: *p++ = '\0';
19800: }
19801:
19802: int mouseorkey(x,y)
19803: int* x;
19804: int* y;
19805: {
19806: Event anevent;
19807: char c;
19808: int n;
19809:
19810: Key = -1;
19811:
19812: notify_do_dispatch();
19813: n = read(0,&c,1);
19814: notify_no_dispatch();
19815: if ( n == 1 ) {
19816: /* character was typed in text (original) window */
19817: /* ie. stdin */
19818: Key = c;
19819: *x = Mousex;
19820: *y = Mousey;
19821: xyunscale(x,y);
19822: }
19823: else if ( Key >= 0 ) {
19824: /* character was typed in graphics window */
19825: /* so it must be echoed. */
19826: putchar(Key);
19827: if ( Key == '\r' )
19828: putchar('\n');
19829: fflush(stdout);
19830: *x = Mousex;
19831: *y = Mousey;
19832: xyunscale(x,y);
19833: }
19834: return(Key);
19835: }
19836:
19837: interact()
19838: {
19839: (void) notify_dispatch();
19840: }
19841:
19842: setcolormap()
19843: {
19844: u_char red[CMAPSIZE], green[CMAPSIZE], blue[CMAPSIZE];
19845: int n;
19846:
19847: for(n=0;n<CMAPSIZE;n++) {
19848: red[n] = mycolors[n][0];
19849: green[n] = mycolors[n][1];
19850: blue[n] = mycolors[n][2];
19851: }
19852: pw_setcmsname(Pw,"showcolor");
19853: pw_putcolormap(Pw, 0, CMAPSIZE, red, green, blue);
19854: }
19855:
19856: /*ARGSUSED*/
19857: wait_proc(window,event,arg)
19858: Window window;
19859: Event *event;
19860: caddr_t arg;
19861: {
19862: int id = event_id(event);
19863:
19864: if ( event_is_ascii(event) && id == 'q' )
19865: notify_stop(0);
19866: }
19867:
19868: om_close()
19869: {
19870: window_set(Win, WIN_EVENT_PROC, wait_proc, 0);
19871: if ( fork() == 0 ) {
19872: close(0);
19873: close(1);
19874: close(2);
19875: /* This stuff doesn't seem to work. I'm trying to */
19876: /* get the window to be able to repaint itself when */
19877: /* uncovered. */
19878: sleep(1);
19879: window_main_loop(Mainframe);
19880: exit(0);
19881: }
19882: }
19883:
19884: space(x0,y0,x1,y1)
19885: int x0, y0, x1, y1;
19886: {
19887: int tx, ty;
19888:
19889: obotx = x0;
19890: oboty = y0;
19891: otopx = x1;
19892: otopy = y1;
19893:
19894: boty = 0;
19895: botx = 0;
19896: tx = (int) window_get(Win,WIN_WIDTH);
19897: ty = (int) window_get(Win,WIN_HEIGHT);
19898: topx = tx;
19899: topy = ty;
19900: scx = (double)(topx-botx)/(otopx-obotx);
19901: scy = (double)(topy-boty)/(otopy-oboty);
19902: }
19903:
19904: #ifdef OLDSTUFF
19905: xyscale(x, y)
19906: int *x, *y;
19907: {
19908: *x = (*x-obotx)*scx+botx;
19909: *y = (*y-oboty)*scy+boty;
19910: }
19911: #endif
19912:
19913: xyunscale(x, y)
19914: int *x, *y;
19915: {
19916: /* map from device coordinates to space() coordinates */
19917:
19918: *x = ( (*x - botx)/scx + obotx );
19919: *y = ( (*y - boty)/scy + oboty );
19920: }
19921:
19922: wline(x1,y1,x2,y2)
19923: int x1, y1, x2, y2;
19924: {
19925: lastx = x2;
19926: lasty = y2;
19927:
19928: XYSCALE(x1, y1);
19929: XYSCALE(x2, y2);
19930:
19931: arawline(x1,y1,x2,y2);
19932: }
19933:
19934: wrect(x1,y1,x2,y2)
19935: int x1, y1, x2, y2;
19936: {
19937: lastx = x2;
19938: lasty = y2;
19939:
19940: XYSCALE(x1, y1);
19941: XYSCALE(x2, y2);
19942:
19943: arawbox(x1,y1,x2,y2);
19944: }
19945:
19946: arawbox(x1,y1,x2,y2)
19947: int x1, y1, x2, y2;
19948: {
19949: arawline(x1,y1,x2,y1);
19950: arawline(x2,y1,x2,y2);
19951: arawline(x2,y2,x1,y2);
19952: arawline(x1,y2,x1,y1);
19953: }
19954:
19955: arawline(x1,y1,x2,y2)
19956: int x1, y1, x2, y2;
19957: {
19958: int op, col;
19959:
19960: currentopcol(&op,&col);
19961: /* fprintf(stderr,"calling pw_vector, %d,%d %d,%d currentop=%d Colorval=%d Pw=%ld\n",x1,y1,x2,y2,op,col,Pw); */
19962: pw_vector(Pw, (int)x1,(int)y1, (int)x2,(int)y2, op, col);
19963: interact();
19964: }
19965:
19966: currentopcol(aop,acol)
19967: int *aop, *acol;
19968: {
19969: if ( lmode == 1 && Colorval == S_WHITE ) {
19970: *aop = (PIX_NOT(PIX_SRC) & PIX_DST);
19971: *acol = S_BLACK;
19972: }
19973: else {
19974: *acol = Colorval;
19975: switch (lmode) {
19976: case 0:
19977: *aop = (PIX_NOT(PIX_SRC) & PIX_DST);
19978: break;
19979: case 1:
19980: case 2:
19981: /* *aop = (PIX_SRC | PIX_DST); */
19982: *aop = PIX_SRC;
19983: break;
19984: case 3:
19985: *aop = (PIX_SRC ^ PIX_DST);
19986: break;
19987: default:
19988: *aop = (PIX_SRC | PIX_DST);
19989: break;
19990: }
19991: }
19992: }
19993:
19994: wt(s,scl,left,top,right,bot)
19995: char *s;
19996: {
19997: int op, col;
19998: /* fprintf(stderr,"wt() called, s=%s lastxy=%d,%d scl=%d left-top=%d,%d\n",
19999: s,left,top,scl,left,top); */
20000: currentopcol(&op,&col);
20001: XYSCALE(left, top);
20002: pw_ttext(Pw,(int)left,(int)top,op,NULL,s);
20003: }
20004:
20005: Sp *
20006: set_font(n)
20007: {
20008: static Sp chsz;
20009: struct pr_size prs;
20010: int x, y;
20011:
20012: prs = pf_textwidth(1,pf_default(),"x");
20013: x = prs.x;
20014: y = prs.y;
20015: xyunscale(&x,&y);
20016: chsz.x = ++x;
20017: chsz.y = y;
20018: return &chsz;
20019: }
20020:
20021: #ifdef OLDSTUFF
20022: textwidth(s)
20023: {
20024: struct pr_size prs;
20025:
20026: prs = pf_textwidth(bound,strlen(s),pf_default(),s);
20027:
20028:
20029: prs = pf_textwidth(1,pf_default(),"x");
20030: *ax = prs.x;
20031: *ay = prs.y;
20032: xyunscale(ax,ay);
20033: }
20034: #endif
20035:
20036: amove(x,y)
20037: int x,y;
20038: {
20039: lastx = x;
20040: lasty = y;
20041: }
20042:
20043: cont(x,y)
20044: int x,y;
20045: {
20046: wline(lastx,lasty,x,y);
20047: /* last[xy] are then updated by line */
20048: }
20049:
20050:
20051: set_color(n)
20052: int n;
20053: {
20054: switch(n){
20055: case M_WHITE:
20056: n = S_WHITE; break;
20057: case M_PALE_GREY:
20058: case M_GREY_7:
20059: n = S_GREY; break;
20060: case M_BLACK:
20061: n = S_BLACK; break;
20062: case M_YELLOW_13:
20063: case M_YELLOW_11:
20064: n = S_YELLOW; break;
20065: case M_MAGENTA:
20066: case M_CYAN:
20067: case M_CYAN_14:
20068: n = S_AQUA; break;
20069: case M_GREEN:
20070: case M_GREEN_7:
20071: n = S_GREEN; break;
20072: case M_BLUE:
20073: n = S_BLUE; break;
20074: case M_RED:
20075: n = S_RED; break;
20076: default:
20077: fprintf(stderr,"Unknown color in set_color (%d)\n",n);
20078: n = S_WHITE;
20079: break;
20080: }
20081: Colorval = n;
20082: /* fprintf(stderr,"set_color = (sun#) %d\n",n); */
20083: }
20084:
20085: linemod(s)
20086: char *s;
20087: {
20088: if ( strcmp(s,"erase")==0 )
20089: lmode = 0;
20090: else if ( strcmp(s,"dotted")==0 || strcmp(s,"hilight")==0 )
20091: lmode = 2;
20092: else if ( strcmp(s,"xor")==0 )
20093: lmode = 3;
20094: else { /* everything, including "solid" defaults to this */
20095: lmode = 1;
20096: }
20097: }
20098:
20099: aerase()
20100: {
20101: pw_writebackground(Pw,0,0,(int)topx,(int)topy,PIX_SRC);
20102: }
20103:
20104: wfrect(x1,y1,x2,y2)
20105: int x1, y1, x2, y2;
20106: {
20107: int op, col;
20108: int t;
20109:
20110: XYSCALE(x1, y1);
20111: XYSCALE(x2, y2);
20112:
20113: currentopcol(&op,&col);
20114:
20115: if ( x1 > x2 ) {
20116: t = x1;
20117: x1 = x2;
20118: x2 = t;
20119: }
20120: if ( y1 > y2 ) {
20121: t = y1;
20122: y1 = y2;
20123: y2 = t;
20124: }
20125: /* fprintf(stderr,"wfrect(%d,%d to %d,%d lmode=%d op=%d col=%d)\n",
20126: x1,y1,x2,y2,lmode,op,col); */
20127: for ( t=y1; t<=y2; t++ ) {
20128: pw_vector(Pw, x1,t, x2,t, op, col);
20129: }
20130: interact();
20131: }
20132:
20133: /*ARGSUSED*/
20134: event_proc(window,event,arg)
20135: Window window;
20136: Event *event;
20137: caddr_t arg;
20138: {
20139: int id = event_id(event);
20140:
20141: if ( event_is_ascii(event) ) {
20142: Key = id;
20143: notify_stop(0);
20144: return;
20145: }
20146: }
20147:
20148: /* trim a Metheus X coordinate to fit on screen */
20149: int M_trimX(x)
20150: int x;
20151: { if(x<0) return(0);
20152: else if(x>(topx-1)) return((topx-1));
20153: return(x);
20154: }
20155:
20156: /* trim a Metheus Y coordinate to fit on screen */
20157: int M_trimY(y)
20158: int y;
20159: { if(y<0) return(0);
20160: else if(y>(topy-1)) return((topy-1));
20161: return(y);
20162: }
20163:
20164: /* show Sp (Metheus coordinates) on Metheus,
20165: enlarged to a `dot'-sided square */
20166: sh_Mp(mpp,dot)
20167: Sp *mpp;
20168: int dot;
20169: { int half_dot;
20170: if(dot==1)
20171: wfrect(mpp->x,mpp->y,mpp->x,mpp->y);
20172: else {
20173: half_dot=dot/2;
20174: if((dot%2)==0)
20175: wfrect( M_trimX(mpp->x-half_dot+1),
20176: M_trimY(mpp->y-half_dot+1),
20177: M_trimX(mpp->x+half_dot),
20178: M_trimY(mpp->y+half_dot) );
20179: else wfrect( M_trimX(mpp->x-half_dot),
20180: M_trimY(mpp->y-half_dot),
20181: M_trimX(mpp->x+half_dot),
20182: M_trimY(mpp->y+half_dot) );
20183: };
20184: }
20185:
20186:
20187: om_force(){}
20188:
20189: /* write "thick" line, two pixels wide */
20190: wtline(x1,y1,x2,y2)
20191: { int absdx, absdy;
20192: wline(x1,y1,x2,y2);
20193: absdx = (x1-x2)>=0 ? x1-x2 : x2-x1;
20194: absdy = (y1-y2)>=0 ? y1-y2 : y2-y1;
20195: if(absdx>absdy)
20196: /* more horizontal -- thicken vertically */
20197: wline(x1,M_trimY(y1+1),x2,M_trimY(y2+1));
20198: else
20199: /* more vertical -- thicken horizontally */
20200: wline(M_trimX(x1+1),y1,M_trimX(x2+1),y2);
20201: }
20202:
20203: /* write "fat" line, three pixels wide */
20204: wfline(x1,y1,x2,y2)
20205: { register int absdx, absdy;
20206:
20207: wline(x1,y1,x2,y2);
20208: absdx = (x1-x2)>=0 ? x1-x2 : x2-x1;
20209: absdy = (y1-y2)>=0 ? y1-y2 : y2-y1;
20210: if(absdx>absdy) {
20211: /* more horizontal -- thicken vertically */
20212: wline(x1,M_trimY(y1+1),x2,M_trimY(y2+1));
20213: wline(x1,M_trimY(y1-1),x2,M_trimY(y2-1));
20214: }
20215: else {
20216: /* more vertical -- thicken horizontally */
20217: wline(M_trimX(x1+1),y1,M_trimX(x2+1),y2);
20218: wline(M_trimX(x1-1),y1,M_trimX(x2-1),y2);
20219: };
20220: }
20221:
20222:
20223: om_wrpix()
20224: {
20225: printf("om_wrpix called\n");
20226: }
20227:
20228: om_buffer(n) { }
20229:
20230: rreset() { }
20231: 0707070035351136761006640007620000050000011476070476773366200001100000004314makefile # for all OS --
20232: OPT = -O
20233: PROF = -p
20234: PI = -g
20235:
20236: PRODUCTION = $(OPT)
20237: DEBUG = $(PROF) $(PI)
20238:
20239: # -- for UNIX 9th Ed --
20240: CFLAGS = $(PRODUCTION)
20241: LIBS = -lY3610 -lY
20242: PORTLIB = -lport
20243: LDFLAGS =
20244: F77LIBS = $(LIBS)
20245: MLIB =
20246: REGEX =
20247: FTW =
20248: METLIB = mlib.o
20249: RASTLIB =
20250: POSTLIB =
20251: GRAPHICLIBS =
20252:
20253: # -- For Sun OS 4.x --
20254: ##GRAPHICLIBS = -lsuntool -lsunwindow -lpixrect
20255: ##MLIB = -lm
20256: ##LIBS = $(GRAPHICLIBS) $(MLIB)
20257: ##PORTLIB = /usr/lib/libport3.a
20258: ##F77LIBS = -lF77 -lI77 -lc $(MLIB) $(GRAPHICLIBS)
20259: ##REGEX = regexec.o regcomp.o regerror.o
20260: ##FTW = myftw.o
20261: ##LDFLAGS = $(PROF) -fswitch
20262: ##CFLAGS = $(PROF) -fswitch -Bstatic
20263: ##METLIB = sunlib.o
20264: ##RASTLIB = rastlib.o
20265: ##POSTLIB = postlib.o
20266:
20267: all: bcp
20268: touch bcp
20269: clean:
20270: rm -rf *.[cho15] bcp bcp.cpio *.srcs makefile
20271:
20272: # the next three targets are for use in 1127 software distribution on bowell
20273:
20274: install: /usr/bin/bcp
20275: cp bcp.1 /usr/man/man1
20276:
20277: /usr/bin/bcp: bcp
20278: strip bcp
20279: cp bcp /usr/bin
20280:
20281: ship: /usr/bin/bcp
20282: ship /usr/bin/bcp
20283:
20284: # If you want to use UNIX FILE_TREEs:
20285: Path.o: Path.c CPU.h myftw.h Path.h
20286: cc $(CFLAGS) -c Path.c
20287: FTREE=Path.o
20288:
20289: # If you DON'T want to use FILE_TREEs:
20290: ##FTREE=
20291:
20292: bcp: bcp.o CCITT.o rlelib.o riclib.o Coord.o piclib.o jslr.o Text.o $(FTREE) $(POSTLIB) $(RASTLIB)
20293: cc $(CFLAGS) bcp.o CCITT.o rlelib.o riclib.o Coord.o piclib.o jslr.o Text.o $(FTREE) $(POSTLIB) $(RASTLIB) $(MLIB) $(GRAPHICLIBS) -o bcp
20294: bcp.o: bcp.c CPU.h stdocr.h rle.h CCITT.h bitio.h pic.h Path.h Bitmap.h Text.h abort.h
20295: cc $(CFLAGS) $(MLIB) $(GRAPHICLIBS) -c bcp.c
20296:
20297: stdocr.h: boole.h limits.h Units.h ric.h fioi.h
20298: touch stdocr.h
20299: CCITT.o: CCITT.c CPU.h stdocr.h rle.h Bitmap.h CCITT.h bitio.h
20300: cc $(CFLAGS) -c CCITT.c
20301: rlelib.o: rlelib.c CPU.h stdocr.h rle.h ric.h
20302: cc $(CFLAGS) -c rlelib.c
20303: riclib.o: riclib.c CPU.h stdocr.h
20304: cc $(CFLAGS) -c riclib.c
20305: Coord.o: Coord.c CPU.h boole.h Units.h Coord.h
20306: cc $(CFLAGS) -c Coord.c
20307: Text.o: Text.c font.h Bfeats.h stdocr.h
20308: cc $(CFLAGS) -c Text.c
20309: piclib.o: piclib.c CPU.h boole.h limits.h Units.h Coord.h pic.h
20310: cc $(CFLAGS) -c piclib.c
20311: jslr.o: jslr.c
20312: cc $(CFLAGS) -c jslr.c
20313: rastlib.o: rastlib.c
20314: cc $(CFLAGS) $(MLIB) $(GRAPHICLIBS) -c rastlib.c
20315: postlib.o: postlib.c
20316: cc $(CFLAGS) -c postlib.c
20317: sunlib.o: sunlib.c
20318: cc $(CFLAGS) -c sunlib.c
20319: myftw.o: myftw.c myftw.h
20320: cc $(CFLAGS) -c myftw.c
20321: 0707070035350335411006640007620000050000010556240457561704600000700000001365README Copy bcp.cpio.z into an empty directory, cd there, and...
20322: unpack bcp.cpio.z
20323: cpio -ic <bcp.cpio
20324: If your cpu is not a VAX or your OS is not research UNIX:
20325: edit CPU.h to specify SUN, CRAY, 3B, etc (and specify OS too)
20326: edit makefile to enable SUN, CRAY, 3B, etc compilation options
20327: Next, defeat the UNIX file-tree code (later, you may decide you want this; but
20328: it seldom ports easily), by taking these steps:
20329: 1) in CPU.h, change this line to:
20330: #define FILE_TREE 0
20331: 2) in makefile, remove all references to Path.c Path.o (this is
20332: spelled out in the comments).
20333: Then say:
20334: make
20335: and hope for the best, which is a working `bcp'.
20336: Bcp.1 and picfile.5 are man pages; print them using `troff -man'.
20337: More detailed documentation can be found in source bcp.c.
20338: 0707070035351136771006640007620000050000011476110476773366300000600000011432bcp.1