1 /*
2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "bdfP.h"
24
25 #ifndef MYABS
26 #define MYABS(n) ((n) < 0 ? -(n) : (n))
27 #endif
28
29 #undef MAX
30 #define MAX(h, i) ((h) > (i) ? (h) : (i))
31
32 #undef MIN
33 #define MIN(l, o) ((l) < (o) ? (l) : (o))
34
35 double _bdf_cos_tbl[360] = {
36 0.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,
37 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
38 0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305,
39 0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505,
40 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620,
41 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
42 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710,
43 0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,
44 0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815,
45 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
46 0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618,
47 0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568,
48 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
49 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
50 0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452,
51 0.000000, -0.017452, -0.034899, -0.052336, -0.069756, -0.087156,
52 -0.104528, -0.121869, -0.139173, -0.156434, -0.173648, -0.190809,
53 -0.207912, -0.224951, -0.241922, -0.258819, -0.275637, -0.292372,
54 -0.309017, -0.325568, -0.342020, -0.358368, -0.374607, -0.390731,
55 -0.406737, -0.422618, -0.438371, -0.453990, -0.469472, -0.484810,
56 -0.500000, -0.515038, -0.529919, -0.544639, -0.559193, -0.573576,
57 -0.587785, -0.601815, -0.615661, -0.629320, -0.642788, -0.656059,
58 -0.669131, -0.681998, -0.694658, -0.707107, -0.719340, -0.731354,
59 -0.743145, -0.754710, -0.766044, -0.777146, -0.788011, -0.798636,
60 -0.809017, -0.819152, -0.829038, -0.838671, -0.848048, -0.857167,
61 -0.866025, -0.874620, -0.882948, -0.891007, -0.898794, -0.906308,
62 -0.913545, -0.920505, -0.927184, -0.933580, -0.939693, -0.945519,
63 -0.951057, -0.956305, -0.961262, -0.965926, -0.970296, -0.974370,
64 -0.978148, -0.981627, -0.984808, -0.987688, -0.990268, -0.992546,
65 -0.994522, -0.996195, -0.997564, -0.998630, -0.999391, -0.999848,
66 -1.000000, -0.999848, -0.999391, -0.998630, -0.997564, -0.996195,
67 -0.994522, -0.992546, -0.990268, -0.987688, -0.984808, -0.981627,
68 -0.978148, -0.974370, -0.970296, -0.965926, -0.961262, -0.956305,
69 -0.951057, -0.945519, -0.939693, -0.933580, -0.927184, -0.920505,
70 -0.913545, -0.906308, -0.898794, -0.891007, -0.882948, -0.874620,
71 -0.866025, -0.857167, -0.848048, -0.838671, -0.829038, -0.819152,
72 -0.809017, -0.798636, -0.788011, -0.777146, -0.766044, -0.754710,
73 -0.743145, -0.731354, -0.719340, -0.707107, -0.694658, -0.681998,
74 -0.669131, -0.656059, -0.642788, -0.629320, -0.615661, -0.601815,
75 -0.587785, -0.573576, -0.559193, -0.544639, -0.529919, -0.515038,
76 -0.500000, -0.484810, -0.469472, -0.453990, -0.438371, -0.422618,
77 -0.406737, -0.390731, -0.374607, -0.358368, -0.342020, -0.325568,
78 -0.309017, -0.292372, -0.275637, -0.258819, -0.241922, -0.224951,
79 -0.207912, -0.190809, -0.173648, -0.156434, -0.139173, -0.121869,
80 -0.104528, -0.087156, -0.069756, -0.052336, -0.034899, -0.017452,
81 -0.000000, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156,
82 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
83 0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
84 0.309017, 0.325568, 0.342020, 0.358368, 0.374607, 0.390731,
85 0.406737, 0.422618, 0.438371, 0.453990, 0.469472, 0.484810,
86 0.500000, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
87 0.587785, 0.601815, 0.615661, 0.629320, 0.642788, 0.656059,
88 0.669131, 0.681998, 0.694658, 0.707107, 0.719340, 0.731354,
89 0.743145, 0.754710, 0.766044, 0.777146, 0.788011, 0.798636,
90 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
91 0.866025, 0.874620, 0.882948, 0.891007, 0.898794, 0.906308,
92 0.913545, 0.920505, 0.927184, 0.933580, 0.939693, 0.945519,
93 0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.974370,
94 0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
95 0.994522, 0.996195, 0.997564, 0.998630, 0.999391, 0.999848,
96 };
97
98 double _bdf_sin_tbl[360] = {
99 0.000000, 0.017452, 0.034899, 0.052336, 0.069756, 0.087156,
100 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
101 0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
102 0.309017, 0.325568, 0.342020, 0.358368, 0.374607, 0.390731,
103 0.406737, 0.422618, 0.438371, 0.453990, 0.469472, 0.484810,
104 0.500000, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
105 0.587785, 0.601815, 0.615661, 0.629320, 0.642788, 0.656059,
106 0.669131, 0.681998, 0.694658, 0.707107, 0.719340, 0.731354,
107 0.743145, 0.754710, 0.766044, 0.777146, 0.788011, 0.798636,
108 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
109 0.866025, 0.874620, 0.882948, 0.891007, 0.898794, 0.906308,
110 0.913545, 0.920505, 0.927184, 0.933580, 0.939693, 0.945519,
111 0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.974370,
112 0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
113 0.994522, 0.996195, 0.997564, 0.998630, 0.999391, 0.999848,
114 1.000000, 0.999848, 0.999391, 0.998630, 0.997564, 0.996195,
115 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
116 0.978148, 0.974370, 0.970296, 0.965926, 0.961262, 0.956305,
117 0.951057, 0.945519, 0.939693, 0.933580, 0.927184, 0.920505,
118 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.874620,
119 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
120 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.754710,
121 0.743145, 0.731354, 0.719340, 0.707107, 0.694658, 0.681998,
122 0.669131, 0.656059, 0.642788, 0.629320, 0.615661, 0.601815,
123 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
124 0.500000, 0.484810, 0.469472, 0.453990, 0.438371, 0.422618,
125 0.406737, 0.390731, 0.374607, 0.358368, 0.342020, 0.325568,
126 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
127 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
128 0.104528, 0.087156, 0.069756, 0.052336, 0.034899, 0.017452,
129 0.000000, -0.017452, -0.034899, -0.052336, -0.069756, -0.087156,
130 -0.104528, -0.121869, -0.139173, -0.156434, -0.173648, -0.190809,
131 -0.207912, -0.224951, -0.241922, -0.258819, -0.275637, -0.292372,
132 -0.309017, -0.325568, -0.342020, -0.358368, -0.374607, -0.390731,
133 -0.406737, -0.422618, -0.438371, -0.453990, -0.469472, -0.484810,
134 -0.500000, -0.515038, -0.529919, -0.544639, -0.559193, -0.573576,
135 -0.587785, -0.601815, -0.615661, -0.629320, -0.642788, -0.656059,
136 -0.669131, -0.681998, -0.694658, -0.707107, -0.719340, -0.731354,
137 -0.743145, -0.754710, -0.766044, -0.777146, -0.788011, -0.798636,
138 -0.809017, -0.819152, -0.829038, -0.838671, -0.848048, -0.857167,
139 -0.866025, -0.874620, -0.882948, -0.891007, -0.898794, -0.906308,
140 -0.913545, -0.920505, -0.927184, -0.933580, -0.939693, -0.945519,
141 -0.951057, -0.956305, -0.961262, -0.965926, -0.970296, -0.974370,
142 -0.978148, -0.981627, -0.984808, -0.987688, -0.990268, -0.992546,
143 -0.994522, -0.996195, -0.997564, -0.998630, -0.999391, -0.999848,
144 -1.000000, -0.999848, -0.999391, -0.998630, -0.997564, -0.996195,
145 -0.994522, -0.992546, -0.990268, -0.987688, -0.984808, -0.981627,
146 -0.978148, -0.974370, -0.970296, -0.965926, -0.961262, -0.956305,
147 -0.951057, -0.945519, -0.939693, -0.933580, -0.927184, -0.920505,
148 -0.913545, -0.906308, -0.898794, -0.891007, -0.882948, -0.874620,
149 -0.866025, -0.857167, -0.848048, -0.838671, -0.829038, -0.819152,
150 -0.809017, -0.798636, -0.788011, -0.777146, -0.766044, -0.754710,
151 -0.743145, -0.731354, -0.719340, -0.707107, -0.694658, -0.681998,
152 -0.669131, -0.656059, -0.642788, -0.629320, -0.615661, -0.601815,
153 -0.587785, -0.573576, -0.559193, -0.544639, -0.529919, -0.515038,
154 -0.500000, -0.484810, -0.469472, -0.453990, -0.438371, -0.422618,
155 -0.406737, -0.390731, -0.374607, -0.358368, -0.342020, -0.325568,
156 -0.309017, -0.292372, -0.275637, -0.258819, -0.241922, -0.224951,
157 -0.207912, -0.190809, -0.173648, -0.156434, -0.139173, -0.121869,
158 -0.104528, -0.087156, -0.069756, -0.052336, -0.034899, -0.017452,
159 };
160
161 double _bdf_tan_tbl[90] = {
162 0.000000, 0.017455, 0.034921, 0.052408, 0.069927, 0.087489,
163 0.105104, 0.122785, 0.140541, 0.158384, 0.176327, 0.194380,
164 0.212557, 0.230868, 0.249328, 0.267949, 0.286745, 0.305731,
165 0.324920, 0.344328, 0.363970, 0.383864, 0.404026, 0.424475,
166 0.445229, 0.466308, 0.487733, 0.509525, 0.531709, 0.554309,
167 0.577350, 0.600861, 0.624869, 0.649408, 0.674509, 0.700208,
168 0.726543, 0.753554, 0.781286, 0.809784, 0.839100, 0.869287,
169 0.900404, 0.932515, 0.965689, 1.000000, 1.035530, 1.072369,
170 1.110613, 1.150368, 1.191754, 1.234897, 1.279942, 1.327045,
171 1.376382, 1.428148, 1.482561, 1.539865, 1.600335, 1.664279,
172 1.732051, 1.804048, 1.880726, 1.962611, 2.050304, 2.144507,
173 2.246037, 2.355852, 2.475087, 2.605089, 2.747477, 2.904211,
174 3.077684, 3.270853, 3.487414, 3.732051, 4.010781, 4.331476,
175 4.704630, 5.144554, 5.671282, 6.313752, 7.115370, 8.144346,
176 9.514364, 11.430052, 14.300666, 19.081137, 28.636253, 57.289962,
177 };
178
179 /*
180 * Determine the actual ink bounds.
181 */
182 static int
_bdf_grid_ink_bounds(bdf_glyph_grid_t * grid,short * x,short * y,short * width,short * height)183 _bdf_grid_ink_bounds(bdf_glyph_grid_t *grid, short *x, short *y,
184 short *width, short *height)
185 {
186 short bx, by, bwd, bht, minx, maxx, miny, maxy, dx, dy;
187 unsigned short bpr, ink, sel, col;
188 unsigned char *bmap, *masks;
189
190 masks = 0;
191 switch (grid->bpp) {
192 case 1: masks = bdf_onebpp; break;
193 case 2: masks = bdf_twobpp; break;
194 case 4: masks = bdf_fourbpp; break;
195 case 8: masks = bdf_eightbpp; break;
196 }
197
198 if (grid->sel.width != 0 && grid->sel.height != 0) {
199 sel = 1;
200 bx = by = 0;
201 bwd = grid->sel.width;
202 bht = grid->sel.height;
203 bmap = grid->sel.bitmap;
204 } else {
205 sel = 0;
206 bx = grid->glyph_x;
207 by = grid->glyph_y;
208 bwd = grid->glyph_bbx.width;
209 bht = grid->glyph_bbx.height;
210 bmap = grid->bitmap;
211 }
212 maxx = maxy = 0;
213 minx = bx + bwd;
214 miny = by + bht;
215
216 bpr = ((bwd * grid->bpp) + 7) >> 3;
217 ink = 0;
218
219 bwd += bx;
220 bht += by;
221 for (dy = by; dy < bht; dy++) {
222 for (col = bx * grid->bpp, dx = bx; dx < bwd; dx++, col += grid->bpp) {
223 if (bmap[(dy * bpr) + (col >> 3)] & masks[(col & 7) / grid->bpp]) {
224 ink = 1;
225 minx = MIN(minx, dx);
226 miny = MIN(miny, dy);
227 maxx = MAX(maxx, dx);
228 maxy = MAX(maxy, dy);
229 }
230 }
231 }
232
233 *x = minx + ((sel) ? grid->sel.x : 0);
234 *y = miny + ((sel) ? grid->sel.y : 0);
235 if (ink == 0)
236 *width = *height = 0;
237 else {
238 *width = (maxx - minx) + 1;
239 *height = (maxy - miny) + 1;
240 }
241 return ink;
242 }
243
244 /**************************************************************************
245 *
246 * Glyph grid create and destroy functions.
247 *
248 **************************************************************************/
249
250 /*
251 * Make a glyph grid with the glyph bitmap set in the bitmap.
252 */
253 bdf_glyph_grid_t *
bdf_make_glyph_grid(bdf_font_t * font,int code,int unencoded)254 bdf_make_glyph_grid(bdf_font_t *font, int code, int unencoded)
255 {
256 unsigned short si, di, col, colx, byte;
257 short ht, as, ds, gsize, bpr, x, y, nx, ny;
258 long l, r, m;
259 bdf_glyph_grid_t *gr;
260 bdf_glyph_t *gl, *glp;
261 bdf_property_t *p;
262 unsigned char *masks;
263 char name[24];
264
265 #if 0
266 if (font == 0)
267 return 0;
268 #endif
269
270 /*
271 * Allocate the grid and initialize it.
272 */
273 gr = (bdf_glyph_grid_t *) malloc(sizeof(bdf_glyph_grid_t));
274 (void) memset((char *) gr, 0, sizeof(bdf_glyph_grid_t));
275
276 /*
277 * Set the encoding and the unencoded flag.
278 */
279 gr->bpp = (font) ? font->bpp : 1;
280 gr->encoding = code;
281 gr->unencoded = unencoded;
282
283 /*
284 * Set the glyph grid spacing.
285 */
286 gr->spacing = (font) ? font->spacing : BDF_CHARCELL;
287
288 /*
289 * Set the point size and resolutions.
290 */
291 if (font) {
292 gr->point_size = font->point_size;
293 gr->resolution_x = font->resolution_x;
294 gr->resolution_y = font->resolution_y;
295 } else {
296 gr->point_size = 12;
297 gr->resolution_x = gr->resolution_y = 100;
298 }
299
300 /*
301 * Set the CAP_HEIGHT and X_HEIGHT if they exist in the font.
302 */
303 if (font) {
304 if ((p = bdf_get_font_property(font, "CAP_HEIGHT")) != 0)
305 gr->cap_height = (short) p->value.int32;
306 if ((p = bdf_get_font_property(font, "X_HEIGHT")) != 0)
307 gr->x_height = (short) p->value.int32;
308 }
309
310 masks = 0;
311 switch (gr->bpp) {
312 case 1: masks = bdf_onebpp; break;
313 case 2: masks = bdf_twobpp; break;
314 case 4: masks = bdf_fourbpp; break;
315 case 8: masks = bdf_eightbpp; break;
316 }
317
318 /*
319 * Copy the font bounding box into the grid.
320 */
321 if (font)
322 (void) memcpy((char *) &gr->font_bbx, (char *) &font->bbx,
323 sizeof(bdf_bbx_t));
324 else {
325 gr->font_bbx.height = 17;
326 gr->font_bbx.width = 8;
327 gr->font_bbx.descent = 8;
328 gr->font_bbx.ascent = 9;
329 gr->font_bbx.y_offset = -8;
330 }
331
332
333 if (font) {
334 if (unencoded) {
335 gl = font->unencoded;
336 r = font->unencoded_used;
337 } else {
338 gl = font->glyphs;
339 r = font->glyphs_used;
340 }
341 } else {
342 gl = 0;
343 r = 0;
344 }
345
346 /*
347 * Locate the specified glyph using a simple binary search.
348 */
349 glp = 0;
350 if (r > 0) {
351 for (l = 0; r >= l; ) {
352 m = (l + r) >> 1;
353 glp = gl + m;
354 if (glp->encoding == code)
355 break;
356 if (glp->encoding > code)
357 r = m - 1;
358 else if (glp->encoding < code)
359 l = m + 1;
360 glp = 0;
361 }
362 }
363
364 ht = gr->font_bbx.height;
365 as = gr->font_bbx.ascent;
366 ds = gr->font_bbx.descent;
367
368 /*
369 * 1. Determine width and height needed from the largest of the
370 * width or height.
371 */
372 gr->grid_width = gr->grid_height =
373 MAX(gr->font_bbx.width, gr->font_bbx.height);
374
375 /*
376 * 2. Make sure the grid is at least a square of the largest of the width
377 * or height of the glyph itself to allow room for transformations.
378 */
379 if (glp != 0) {
380 /*
381 * Set the glyph name and other metrics.
382 */
383 if (glp->name) {
384 gr->name = (char *) malloc(strlen(glp->name) + 1);
385 (void) memcpy(gr->name, glp->name, strlen(glp->name) + 1);
386 } else {
387 sprintf(name, "char%d", code);
388 gr->name = (char *) malloc(strlen(name) + 1);
389 (void) memcpy(gr->name, name, strlen(name) + 1);
390 }
391 gr->dwidth = glp->dwidth;
392
393 /*
394 * Copy the glyph bounding box into the grid.
395 */
396 (void) memcpy((char *) &gr->glyph_bbx, (char *) &glp->bbx,
397 sizeof(bdf_bbx_t));
398
399 if (glp->bbx.height < glp->bbx.ascent + glp->bbx.descent)
400 gsize = glp->bbx.ascent + glp->bbx.descent;
401 else
402 gsize = glp->bbx.height;
403
404 /*
405 * Figure the maximum of the glyph width and height.
406 */
407 gsize = MAX(gr->glyph_bbx.width, gsize);
408
409 /*
410 * If either the grid width or grid height is less than the
411 * grid size just determined, then adjust them to the new grid size.
412 */
413 gr->grid_width = MAX(gr->grid_width, gsize);
414 gr->grid_height = MAX(gr->grid_height, gsize);
415 } else {
416 /*
417 * The glyph doesn't exist, so make up a name for it.
418 */
419 if (unencoded)
420 sprintf(name, "unencoded%d", code);
421 else
422 sprintf(name, "char%d", code);
423 gr->name = (char *) malloc(strlen(name) + 1);
424 (void) memcpy(gr->name, name, strlen(name) + 1);
425 }
426
427 /*
428 * If the font has character-cell or mono spacing, make sure the grid
429 * device width is set to the width stored in the font.
430 */
431 if (gr->spacing != BDF_PROPORTIONAL)
432 gr->dwidth = (font) ? font->monowidth : 8;
433
434 /*
435 * Determine the vertical origin based on the font bounding box.
436 */
437 if (ht >= as + ds)
438 gr->base_y = (((gr->grid_height >> 1) - (ht >> 1)) + ht) - ds;
439 else
440 gr->base_y = ((gr->grid_height >> 1) - ((as + ds) >> 1)) + as;
441
442 /*
443 * The final adjust is to check to see if the glyph positioned relative to
444 * the baseline would cause the grid to change size. This sometimes
445 * happens in fonts that have incorrect metrics.
446 */
447 if (gr->base_y + gr->glyph_bbx.descent > gr->grid_height) {
448 gsize = gr->base_y + gr->glyph_bbx.descent;
449 gr->grid_width = MAX(gsize, gr->grid_width);
450 gr->grid_height = MAX(gsize, gr->grid_height);
451 }
452
453 /*
454 * Determine the horizontal origin based on the font bounding box and
455 * centered within the grid.
456 */
457 gr->base_x = (gr->grid_width >> 1) - (gr->font_bbx.width >> 1);
458 if (gr->font_bbx.x_offset < 0)
459 gr->base_x += MYABS(gr->font_bbx.x_offset);
460
461 /*
462 * Allocate double the storage needed for the grid bitmap. The extra
463 * storage will be used for transformations.
464 */
465 gr->bytes = ((((gr->grid_width * gr->bpp) + 7) >> 3) *
466 gr->grid_height) << 1;
467 gr->bitmap = (unsigned char *) malloc(gr->bytes);
468 (void) memset((char *) gr->bitmap, 0, gr->bytes);
469
470 /*
471 * Initialize the top-left coordinates of the glyph to the baseline
472 * coordinates.
473 */
474 gr->glyph_x = gr->base_x;
475 gr->glyph_y = gr->base_y;
476
477 /*
478 * If the glyph was not found, simply return the empty grid.
479 */
480 if (glp == 0)
481 return gr;
482
483 /*
484 * Determine the top-left coordinates of the glyph with respect to the
485 * baseline coordinates.
486 */
487 gr->glyph_x = nx = gr->base_x + gr->glyph_bbx.x_offset;
488 gr->glyph_y = ny = gr->base_y - gr->glyph_bbx.ascent;
489
490 /*
491 * Now copy the glyph bitmap to the appropriate location in the grid.
492 */
493 bpr = ((gr->glyph_bbx.width * gr->bpp) + 7) >> 3;
494 gsize = ((gr->grid_width * gr->bpp) + 7) >> 3;
495 for (y = 0; y < gr->glyph_bbx.height; y++, ny++) {
496 for (colx = nx * gr->bpp, col = x = 0; x < gr->glyph_bbx.width;
497 x++, col += gr->bpp, colx += gr->bpp) {
498 si = (col & 7) / gr->bpp;
499 byte = glp->bitmap[(y * bpr) + (col >> 3)] & masks[si];
500 if (byte) {
501 di = (colx & 7) / gr->bpp;
502 if (di < si)
503 byte <<= (si - di) * gr->bpp;
504 else if (di > si)
505 byte >>= (di - si) * gr->bpp;
506 gr->bitmap[(ny * gsize) + (colx >> 3)] |= byte;
507 }
508 }
509 }
510
511 /*
512 * Always crop the glyph to the ink bounds before editing.
513 */
514 bdf_grid_crop(gr, 0);
515
516 /*
517 * Copy any Unicode mappings that might be present for this glyph, even if
518 * it is a proportional font. It might be changed to a character cell or
519 * monowidth font later.
520 */
521 gr->unicode.map_size = glp->unicode.map_size;
522 gr->unicode.map_used = glp->unicode.map_used;
523 gr->unicode.map = (unsigned char *)
524 malloc(sizeof(unsigned char) * gr->unicode.map_size);
525 (void) memcpy((char *) gr->unicode.map, (char *) glp->unicode.map,
526 sizeof(unsigned char) * gr->unicode.map_used);
527
528 /*
529 * Return the grid.
530 */
531 return gr;
532 }
533
534 void
bdf_free_glyph_grid(bdf_glyph_grid_t * grid)535 bdf_free_glyph_grid(bdf_glyph_grid_t *grid)
536 {
537 if (grid == 0)
538 return;
539
540 if (grid->name != 0)
541 free(grid->name);
542 if (grid->bytes > 0)
543 free((char *) grid->bitmap);
544 if (grid->sel.bytes > 0)
545 free((char *) grid->sel.bitmap);
546 if (grid->unicode.map_size > 0)
547 free((char *) grid->unicode.map);
548 free((char *) grid);
549 }
550
551 /**************************************************************************
552 *
553 * Glyph grid resize functions.
554 *
555 **************************************************************************/
556
557 /*
558 * Enlarge the grid without affecting the font or glyph metrics.
559 */
560 int
bdf_grid_enlarge(bdf_glyph_grid_t * grid,unsigned short width,unsigned short height)561 bdf_grid_enlarge(bdf_glyph_grid_t *grid, unsigned short width,
562 unsigned short height)
563 {
564 unsigned short si, di, col, colx, byte;
565 short ht, wd, as, ds, x, y, nx, ny;
566 unsigned short gwd, ght, bytes, obpr, nbpr, gsize;
567 unsigned char *bitmap, *masks;
568
569 if (grid == 0 || (width < grid->grid_width && height < grid->grid_height))
570 return 0;
571
572 masks = 0;
573 switch (grid->bpp) {
574 case 1: masks = bdf_onebpp; break;
575 case 2: masks = bdf_twobpp; break;
576 case 4: masks = bdf_fourbpp; break;
577 case 8: masks = bdf_eightbpp; break;
578 }
579
580 ht = height;
581 as = grid->font_bbx.ascent;
582 ds = grid->font_bbx.descent;
583
584 gwd = MAX(width, grid->grid_width);
585 ght = MAX(height, grid->grid_height);
586 gsize = MAX(gwd, ght);
587
588 nbpr = ((gsize * grid->bpp) + 7) >> 3;
589 bytes = (nbpr * ght) << 1;
590 bitmap = (unsigned char *) malloc(bytes);
591 (void) memset((char *) bitmap, 0, bytes);
592
593 /*
594 * Determine the new baseline.
595 */
596 if (ht >= as + ds)
597 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
598 else
599 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
600
601 grid->base_x = (gwd >> 1) - (grid->font_bbx.width >> 1);
602 if (grid->font_bbx.x_offset < 0)
603 grid->base_x += MYABS(grid->font_bbx.x_offset);
604
605 nx = grid->base_x + grid->glyph_bbx.x_offset;
606 ny = grid->base_y - grid->glyph_bbx.ascent;
607
608 /*
609 * Now copy the bitmap into the new storage base on the new metrics
610 * values.
611 */
612 obpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
613 wd = grid->glyph_x + grid->glyph_bbx.width;
614 ht = grid->glyph_y + grid->glyph_bbx.height;
615 for (y = grid->glyph_y; y < ht; y++, ny++) {
616 col = grid->glyph_x * grid->bpp;
617 colx = nx * grid->bpp;
618 for (x = grid->glyph_x; x < wd;
619 x++, col += grid->bpp, colx += grid->bpp) {
620 si = (col & 7) / grid->bpp;
621 byte = grid->bitmap[(y * obpr) + (col >> 3)] & masks[si];
622 if (byte) {
623 di = (colx & 7) / grid->bpp;
624 if (di < si)
625 byte <<= (si - di) * grid->bpp;
626 else if (di > si)
627 byte >>= (di - si) * grid->bpp;
628 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
629 }
630 }
631 }
632
633 /*
634 * Adjust the glyph coordinates.
635 */
636 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
637 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
638
639 /*
640 * Get rid of the old grid bitmap and replace it with the new one.
641 */
642 free((char *) grid->bitmap);
643 grid->bytes = bytes;
644 grid->bitmap = bitmap;
645
646 /*
647 * Update the new grid width and height.
648 */
649 grid->grid_width = grid->grid_height = gsize;
650
651 /*
652 * Always mark the grid as being modified on a resize.
653 */
654 grid->modified = 1;
655
656 return 1;
657 }
658
659 /*
660 * Change the font bounding box values and resize the grid bitmap if
661 * necessary.
662 */
663 int
bdf_grid_resize(bdf_glyph_grid_t * grid,bdf_metrics_t * metrics)664 bdf_grid_resize(bdf_glyph_grid_t *grid, bdf_metrics_t *metrics)
665 {
666 int changed;
667 unsigned short si, di, col, colx, byte;
668 short ht, wd, as, ds, x, y, nx, ny;
669 unsigned short gwd, ght, bytes, obpr, nbpr, gsize;
670 unsigned char *bitmap, *masks;
671
672 changed = 0;
673
674 if (grid == 0 || metrics == 0)
675 return changed;
676
677 masks = 0;
678 switch (grid->bpp) {
679 case 1: masks = bdf_onebpp; break;
680 case 2: masks = bdf_twobpp; break;
681 case 4: masks = bdf_fourbpp; break;
682 case 8: masks = bdf_eightbpp; break;
683 }
684
685 /*
686 * Create new grid bitmaps in preparation for the various metrics changing.
687 */
688 if (metrics->width > grid->grid_width ||
689 metrics->height > grid->grid_height) {
690 changed = 1;
691
692 ht = metrics->height;
693 as = metrics->ascent;
694 ds = metrics->descent;
695
696 gwd = MAX(metrics->width, grid->grid_width);
697 ght = MAX(metrics->height, grid->grid_height);
698
699 /*
700 * Get the larger of the two dimensions.
701 */
702 gsize = MAX(gwd, ght);
703
704 nbpr = ((gsize * grid->bpp) + 7) >> 3;
705 bytes = (nbpr * gsize) << 1;
706 bitmap = (unsigned char *) malloc(bytes);
707 (void) memset((char *) bitmap, 0, bytes);
708
709 /*
710 * Determine the new baseline.
711 */
712 if (ht >= as + ds)
713 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
714 else
715 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
716
717 grid->base_x = (gwd >> 1) - (metrics->width >> 1);
718 if (metrics->x_offset < 0)
719 grid->base_x += MYABS(metrics->x_offset);
720
721 nx = grid->base_x + grid->glyph_bbx.x_offset;
722 ny = grid->base_y - grid->glyph_bbx.ascent;
723
724 /*
725 * Now copy the bitmap into the new storage base on the new metrics
726 * values.
727 */
728 obpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
729 wd = grid->glyph_x + grid->glyph_bbx.width;
730 ht = grid->glyph_y + grid->glyph_bbx.height;
731 for (y = grid->glyph_y; y < ht; y++, ny++) {
732 col = grid->glyph_x * grid->bpp;
733 colx = nx * grid->bpp;
734 for (x = grid->glyph_x; x < wd;
735 x++, col += grid->bpp, colx += grid->bpp) {
736 si = (col & 7) / grid->bpp;
737 byte = grid->bitmap[(y * obpr) + (col >> 3)] & masks[si];
738 if (byte) {
739 di = (colx & 7) / grid->bpp;
740 if (di < si)
741 byte <<= (si - di) * grid->bpp;
742 else if (di > si)
743 byte >>= (di - si) * grid->bpp;
744 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
745 }
746 }
747 }
748
749 /*
750 * Adjust the glyph coordinates.
751 */
752 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
753 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
754
755 /*
756 * Get rid of the old grid bitmap and replace it with the new one.
757 */
758 free((char *) grid->bitmap);
759 grid->bytes = bytes;
760 grid->bitmap = bitmap;
761
762 /*
763 * Update the new grid width and height.
764 */
765 grid->grid_width = grid->grid_height = gsize;
766
767 /*
768 * Copy the metrics info into the font bounding box.
769 */
770 grid->font_bbx.width = metrics->width;
771 grid->font_bbx.x_offset = metrics->x_offset;
772 grid->font_bbx.height = metrics->height;
773 grid->font_bbx.ascent = metrics->ascent;
774 grid->font_bbx.descent = metrics->descent;
775 grid->font_bbx.y_offset = metrics->y_offset;
776 } else {
777 /*
778 * The grid does not need to resized, but the baseline must
779 * be recalculated and the bitmap copied again.
780 */
781 bytes = grid->bytes >> 1;
782 bitmap = grid->bitmap + bytes;
783 (void) memset((char *) bitmap, 0, bytes);
784
785 ht = metrics->height;
786 as = metrics->ascent;
787 ds = metrics->descent;
788
789 gwd = grid->grid_width;
790 ght = grid->grid_height;
791
792 /*
793 * Determine the new baseline.
794 */
795 if (ht >= as + ds)
796 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
797 else
798 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
799
800 grid->base_x = (gwd >> 1) - (metrics->width >> 1);
801 if (metrics->x_offset < 0)
802 grid->base_x += MYABS(metrics->x_offset);
803
804 nx = grid->base_x + grid->glyph_bbx.x_offset;
805 ny = grid->base_y - grid->glyph_bbx.ascent;
806
807 wd = grid->glyph_x + grid->glyph_bbx.width;
808 ht = grid->glyph_y + grid->glyph_bbx.height;
809
810 obpr = nbpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
811 for (y = grid->glyph_y; y < ht; y++, ny++) {
812 col = grid->glyph_x * grid->bpp;
813 colx = nx * grid->bpp;
814 for (x = grid->glyph_x; x < wd;
815 x++, col += grid->bpp, colx += grid->bpp) {
816 si = (col & 7) / grid->bpp;
817 byte = grid->bitmap[(y * obpr) + (col >> 3)] & masks[si];
818 if (byte) {
819 di = (colx & 7) / grid->bpp;
820 if (di < si)
821 byte <<= (si - di) * grid->bpp;
822 else if (di > si)
823 byte >>= (di - si) * grid->bpp;
824 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
825 }
826 }
827 }
828
829 /*
830 * Copy the adjusted bitmap back into the main area.
831 */
832 (void) memcpy((char *) grid->bitmap, (char *) bitmap, bytes);
833
834 /*
835 * Adjust the glyph coordinates.
836 */
837 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
838 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
839
840 /*
841 * Copy the metrics info into the font bounding box.
842 */
843 grid->font_bbx.width = metrics->width;
844 grid->font_bbx.x_offset = metrics->x_offset;
845 grid->font_bbx.height = metrics->height;
846 grid->font_bbx.ascent = metrics->ascent;
847 grid->font_bbx.descent = metrics->descent;
848 grid->font_bbx.y_offset = metrics->y_offset;
849 }
850
851 /*
852 * If the font is not proportional, make sure the device width is adjusted
853 * to meet the new font bounding box.
854 */
855 if (changed && grid->spacing != BDF_PROPORTIONAL)
856 grid->dwidth = grid->font_bbx.width;
857
858 /*
859 * Always mark the grid as being modified on a resize.
860 */
861 grid->modified = 1;
862
863 return changed;
864 }
865
866 int
bdf_grid_crop(bdf_glyph_grid_t * grid,int grid_modified)867 bdf_grid_crop(bdf_glyph_grid_t *grid, int grid_modified)
868 {
869 int cropped;
870 short x, y, delta, maxx, minx, maxy, miny, col;
871 unsigned short bpr;
872 unsigned char *masks;
873
874 cropped = 0;
875 if (grid == 0)
876 return cropped;
877
878 masks = 0;
879 switch (grid->bpp) {
880 case 1: masks = bdf_onebpp; break;
881 case 2: masks = bdf_twobpp; break;
882 case 4: masks = bdf_fourbpp; break;
883 case 8: masks = bdf_eightbpp; break;
884 }
885
886 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
887
888 maxx = maxy = -1;
889 minx = miny = grid->grid_width;
890 for (y = 0; y < grid->grid_height; y++) {
891 for (col = x = 0; x < grid->grid_width; x++, col += grid->bpp) {
892 if (grid->bitmap[(y * bpr) + (col >> 3)] &
893 masks[(col & 7) / grid->bpp]) {
894 minx = MIN(minx, x);
895 maxx = MAX(maxx, x);
896 miny = MIN(miny, y);
897 maxy = MAX(maxy, y);
898 }
899 }
900 }
901
902 /*
903 * Handle an empty bitmap as a special case.
904 */
905 if (maxx == -1) {
906 /*
907 * If the glyph bounding box indicated something was there originally,
908 * then indicate that it was cropped.
909 */
910 if (grid->glyph_bbx.width != 0 || grid->glyph_bbx.height != 0)
911 cropped = 1;
912 (void) memset((char *) &grid->glyph_bbx, 0, sizeof(bdf_bbx_t));
913 grid->glyph_x = grid->base_x;
914 grid->glyph_y = grid->base_y;
915 if (cropped && grid_modified)
916 grid->modified = 1;
917 return cropped;
918 }
919
920 /*
921 * Increment the max points so width and height calculations won't go
922 * wrong.
923 */
924 maxx++;
925 maxy++;
926
927 if (minx != grid->glyph_x) {
928 cropped = 1;
929 delta = minx - grid->glyph_x;
930 grid->glyph_x += delta;
931 grid->glyph_bbx.x_offset += delta;
932 }
933 if (maxx - minx != grid->glyph_bbx.width) {
934 cropped = 1;
935 delta = (maxx - minx) - grid->glyph_bbx.width;
936 grid->glyph_bbx.width += delta;
937 }
938
939 if (miny != grid->glyph_y) {
940 cropped = 1;
941 delta = miny - grid->glyph_y;
942 grid->glyph_y += delta;
943 grid->glyph_bbx.y_offset =
944 grid->base_y - (grid->glyph_y + (maxy - miny));
945 }
946 if (maxy - miny != grid->glyph_bbx.height) {
947 cropped = 1;
948 delta = (maxy - miny) - grid->glyph_bbx.height;
949 grid->glyph_bbx.height += delta;
950 grid->glyph_bbx.y_offset =
951 grid->base_y - (grid->glyph_y + (maxy - miny));
952 grid->glyph_bbx.ascent =
953 grid->glyph_bbx.height + grid->glyph_bbx.y_offset;
954 grid->glyph_bbx.descent = -grid->glyph_bbx.y_offset;
955 }
956
957 /*
958 * Indicate that the grid was modified if the glyph had to be cropped.
959 */
960 if (cropped && grid_modified)
961 grid->modified = 1;
962
963 return cropped;
964 }
965
966 /**************************************************************************
967 *
968 * Glyph grid pixel functions.
969 *
970 **************************************************************************/
971
972 int
bdf_grid_set_pixel(bdf_glyph_grid_t * grid,short x,short y,int val)973 bdf_grid_set_pixel(bdf_glyph_grid_t *grid, short x, short y, int val)
974 {
975 unsigned short si, di, dx;
976 int set, bpr, delta;
977 unsigned char *masks;
978
979 set = 0;
980
981 if (grid == 0 || x < 0 || x >= grid->grid_width ||
982 y < 0 || y >= grid->grid_height)
983 return set;
984
985 si = 0;
986 masks = 0;
987 switch (grid->bpp) {
988 case 1: masks = bdf_onebpp; si = 7; break;
989 case 2: masks = bdf_twobpp; si = 3; break;
990 case 4: masks = bdf_fourbpp; si = 1; break;
991 case 8: masks = bdf_eightbpp; si = 0; break;
992 }
993
994 /*
995 * Remove any unused bits from the value.
996 */
997 val &= masks[si];
998
999 dx = x * grid->bpp;
1000 di = (dx & 7) / grid->bpp;
1001
1002 /*
1003 * Shift up the value to the appropriate place if necessary.
1004 */
1005 if (di < si)
1006 val <<= (si - di) * grid->bpp;
1007
1008 /*
1009 * Determine the bytes-per-row.
1010 */
1011 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1012
1013 /*
1014 * If the pixel is already set, simply return with an indication that
1015 * nothing changed.
1016 */
1017 if ((grid->bitmap[(y * bpr) + (dx >> 3)] & masks[di]) == val)
1018 return set;
1019
1020 /*
1021 * Set the bit.
1022 */
1023 set = 1;
1024
1025 /*
1026 * Clear the bits that will take the new value.
1027 */
1028 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
1029 grid->bitmap[(y * bpr) + (dx >> 3)] |= val;
1030
1031 /*
1032 * Adjust the glyph bounding box.
1033 */
1034 if (x < grid->glyph_x) {
1035 delta = grid->glyph_x - x;
1036 grid->glyph_bbx.width += delta;
1037 grid->glyph_bbx.x_offset -= delta;
1038 if (grid->spacing == BDF_PROPORTIONAL)
1039 grid->dwidth = grid->glyph_bbx.width + grid->glyph_bbx.x_offset;
1040 grid->glyph_x -= delta;
1041 } else if (x >= grid->glyph_x + grid->glyph_bbx.width) {
1042 delta = x - (grid->glyph_x + grid->glyph_bbx.width) + 1;
1043 grid->glyph_bbx.width += delta;
1044 if (grid->spacing == BDF_PROPORTIONAL)
1045 grid->dwidth = grid->glyph_bbx.width + grid->glyph_bbx.x_offset;
1046 }
1047 if (y < grid->glyph_y) {
1048 delta = grid->glyph_y - y;
1049 grid->glyph_bbx.ascent += delta;
1050 grid->glyph_bbx.height += delta;
1051 grid->glyph_y -= delta;
1052 } else if (y >= grid->glyph_y + grid->glyph_bbx.height) {
1053 delta = y - (grid->glyph_y + grid->glyph_bbx.height) + 1;
1054 grid->glyph_bbx.descent += delta;
1055 grid->glyph_bbx.height += delta;
1056 grid->glyph_bbx.y_offset = -grid->glyph_bbx.descent;
1057 }
1058
1059 /*
1060 * Indicate that the glyph was modified.
1061 */
1062 grid->modified = 1;
1063
1064 return set;
1065 }
1066
1067 int
bdf_grid_clear_pixel(bdf_glyph_grid_t * grid,short x,short y)1068 bdf_grid_clear_pixel(bdf_glyph_grid_t *grid, short x, short y)
1069 {
1070 int cleared, bpr;
1071 short delta, maxx, minx, maxy, miny, wd, ht;
1072 unsigned short di, dx;
1073 unsigned char *masks;
1074
1075 cleared = 0;
1076
1077 if (grid == 0 || x < 0 || x >= grid->grid_width ||
1078 y < 0 || y >= grid->grid_height)
1079 return cleared;
1080
1081 masks = 0;
1082 switch (grid->bpp) {
1083 case 1: masks = bdf_onebpp; break;
1084 case 2: masks = bdf_twobpp; break;
1085 case 4: masks = bdf_fourbpp; break;
1086 case 8: masks = bdf_eightbpp; break;
1087 }
1088
1089 /*
1090 * Determine the bytes-per-row.
1091 */
1092 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1093
1094 dx = x * grid->bpp;
1095 di = (dx & 7) / grid->bpp;
1096
1097 /*
1098 * If the bit is already clear, simply return with an indication that
1099 * nothing changed.
1100 */
1101 if (!(grid->bitmap[(y * bpr) + (dx >> 3)] & masks[di]))
1102 return cleared;
1103
1104 /*
1105 * Clear the bit.
1106 */
1107 cleared = 1;
1108 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
1109
1110 /*
1111 * Determine the new min and max values.
1112 */
1113 maxx = maxy = 0;
1114 minx = miny = 32767;
1115
1116 wd = grid->glyph_x + grid->glyph_bbx.width;
1117 ht = grid->glyph_y + grid->glyph_bbx.height;
1118
1119 for (y = grid->glyph_y; y < ht; y++) {
1120 dx = grid->glyph_x * grid->bpp;
1121 for (x = grid->glyph_x; x < wd; x++, dx += grid->bpp) {
1122 di = (dx & 7) / grid->bpp;
1123 if (grid->bitmap[(y * bpr) + (dx >> 3)] & masks[di]) {
1124 minx = MIN(minx, x);
1125 maxx = MAX(maxx, x);
1126 miny = MIN(miny, y);
1127 maxy = MAX(maxy, y);
1128 }
1129 }
1130 }
1131
1132 /*
1133 * If this call clears the last bit in the image, set the glyph origin
1134 * to the base and return.
1135 */
1136 if (maxx == 0) {
1137 grid->glyph_x = grid->base_x;
1138 grid->glyph_y = grid->base_y;
1139 if (grid->spacing == BDF_PROPORTIONAL)
1140 grid->dwidth = 0;
1141 (void) memset((char *) &grid->glyph_bbx, 0, sizeof(grid->glyph_bbx));
1142 grid->modified = 1;
1143 return cleared;
1144 }
1145
1146 /*
1147 * Figure out the left and right bearing changes.
1148 */
1149 if (minx > grid->glyph_x) {
1150 delta = minx - grid->glyph_x;
1151 grid->glyph_bbx.width -= delta;
1152 grid->glyph_bbx.x_offset += delta;
1153 if (grid->spacing == BDF_PROPORTIONAL)
1154 grid->dwidth = grid->glyph_bbx.width + grid->glyph_bbx.x_offset;
1155 grid->glyph_x += delta;
1156 } else if (maxx < wd - 1) {
1157 delta = (wd - 1) - maxx;
1158 grid->glyph_bbx.width -= delta;
1159 if (grid->spacing == BDF_PROPORTIONAL)
1160 grid->dwidth = grid->glyph_bbx.width + grid->glyph_bbx.x_offset;
1161 }
1162
1163 if (miny > grid->glyph_y) {
1164 delta = miny - grid->glyph_y;
1165 grid->glyph_bbx.ascent -= delta;
1166 grid->glyph_bbx.height -= delta;
1167 grid->glyph_y += delta;
1168 } else if (maxy < ht - 1) {
1169 delta = (ht - 1) - maxy;
1170 grid->glyph_bbx.descent -= delta;
1171 grid->glyph_bbx.height -= delta;
1172 grid->glyph_bbx.y_offset = -grid->glyph_bbx.descent;
1173 }
1174
1175 /*
1176 * Indicate that the glyph was modified.
1177 */
1178 grid->modified = 1;
1179
1180 return cleared;
1181 }
1182
1183 int
bdf_grid_invert_pixel(bdf_glyph_grid_t * grid,short x,short y,int val)1184 bdf_grid_invert_pixel(bdf_glyph_grid_t *grid, short x, short y, int val)
1185 {
1186 short bpr, di;
1187 unsigned char *masks;
1188
1189 if (grid == 0 || x < 0 || x >= grid->grid_width ||
1190 y < 0 || y >= grid->grid_height)
1191 return 0;
1192
1193 masks = 0;
1194 switch (grid->bpp) {
1195 case 1: masks = bdf_onebpp; break;
1196 case 2: masks = bdf_twobpp; break;
1197 case 4: masks = bdf_fourbpp; break;
1198 case 8: masks = bdf_eightbpp; break;
1199 }
1200
1201 /*
1202 * Determine the bytes-per-row and mask index.
1203 */
1204 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1205 di = ((x * grid->bpp) & 7) / grid->bpp;
1206
1207 /*
1208 * If the bit is set, then clear it, otherwise, set it.
1209 */
1210 if (grid->bitmap[(y * bpr) + ((x * grid->bpp) >> 3)] & masks[di])
1211 return bdf_grid_clear_pixel(grid, x, y);
1212 else
1213 return bdf_grid_set_pixel(grid, x, y, val);
1214 }
1215
1216 /**************************************************************************
1217 *
1218 * Glyph grid bitmap transformation functions.
1219 *
1220 **************************************************************************/
1221
1222 short
_bdf_ceiling(double v)1223 _bdf_ceiling(double v)
1224 {
1225 short val, neg;
1226
1227 val = neg = 0;
1228 if (v < 0) {
1229 neg = 1;
1230 while (v < -1.0) {
1231 val++;
1232 v += 1.0;
1233 }
1234 } else if (v > 0) {
1235 while (v > 1.0) {
1236 val++;
1237 v -= 1.0;
1238 }
1239 if (v > 0.0)
1240 val++;
1241 }
1242 return (!neg) ? val : -val;
1243 }
1244
1245 static int
_bdf_rotate_selection(bdf_glyph_grid_t * grid,int mul90,short degrees)1246 _bdf_rotate_selection(bdf_glyph_grid_t *grid, int mul90, short degrees)
1247 {
1248 int rotated, byte;
1249 short wd, ht, nx, ny, cx, cy, x, y, col;
1250 short ox, oy, shiftx, shifty, si, di;
1251 double dx, dy;
1252 unsigned short bytes, bpr;
1253 unsigned char *scratch, *masks;
1254
1255 rotated = 0;
1256
1257 /*
1258 * Check to see if the number of rotations would have no affect by
1259 * checking if the count is a multiple of 4 (mod 4 == 0).
1260 */
1261 if (grid == 0 || degrees == 0)
1262 return rotated;
1263
1264 masks = 0;
1265 switch (grid->bpp) {
1266 case 1: masks = bdf_onebpp; break;
1267 case 2: masks = bdf_twobpp; break;
1268 case 4: masks = bdf_fourbpp; break;
1269 case 8: masks = bdf_eightbpp; break;
1270 }
1271
1272 bytes = grid->sel.bytes >> 1;
1273 scratch = grid->sel.bitmap + bytes;
1274 (void) memset((char *) scratch, 0, bytes);
1275
1276 cx = grid->sel.width >> 1;
1277 cy = grid->sel.height >> 1;
1278
1279 wd = ht = MAX(grid->sel.width, grid->sel.height);
1280 cx = cy = wd >> 1;
1281
1282 bpr = ((wd * grid->bpp) + 7) >> 3;
1283
1284 for (shiftx = shifty = y = 0; y < ht; y++) {
1285 for (col = x = 0; x < wd; x++, col += grid->bpp) {
1286 dx = (double) (x - cx);
1287 dy = (double) (y - cy);
1288 if (mul90) {
1289 nx = cx + (short) ((dx * _bdf_cos_tbl[degrees]) -
1290 (dy * _bdf_sin_tbl[degrees]));
1291 ny = cy + (short) ((dx * _bdf_sin_tbl[degrees]) +
1292 (dy * _bdf_cos_tbl[degrees]));
1293 } else {
1294 nx = cx + _bdf_ceiling((dx * _bdf_cos_tbl[degrees]) -
1295 (dy * _bdf_sin_tbl[degrees]));
1296 ny = cy + _bdf_ceiling((dx * _bdf_sin_tbl[degrees]) +
1297 (dy * _bdf_cos_tbl[degrees]));
1298 }
1299
1300 /*
1301 * Wrap the coordinates around the edges if necessary.
1302 */
1303 if (nx < 0) {
1304 shiftx = MIN(shiftx, nx);
1305 nx += wd;
1306 } else if (nx >= wd) {
1307 ox = (nx - wd) + 1;
1308 shiftx = MAX(shiftx, ox);
1309 nx -= wd;
1310 }
1311 if (ny < 0) {
1312 shifty = MIN(shifty, ny);
1313 ny += ht;
1314 } else if (ny >= ht) {
1315 oy = (ny - ht) + 1;
1316 shifty = MAX(shifty, oy);
1317 ny -= ht;
1318 }
1319
1320 si = (col & 7) / grid->bpp;
1321 byte = grid->sel.bitmap[(y * bpr) + (col >> 3)] & masks[si];
1322 if (byte) {
1323 rotated = 1;
1324 nx *= grid->bpp;
1325 di = (nx & 7) / grid->bpp;
1326 if (di < si)
1327 byte <<= (si - di) * grid->bpp;
1328 else if (di > si)
1329 byte >>= (di - si) * grid->bpp;
1330 scratch[(ny * bpr) + (nx >> 3)] |= byte;
1331 }
1332 }
1333 }
1334
1335 if (rotated) {
1336 /*
1337 * If a shift is required, then shift the scratch area back into
1338 * the main bitmap.
1339 */
1340 if (shiftx || shifty) {
1341 (void) memset((char *) grid->sel.bitmap, 0, bytes);
1342 for (y = 0; y < ht; y++) {
1343 for (col = x = 0; x < wd; x++, col += grid->bpp) {
1344 si = (col & 7) / grid->bpp;
1345 byte = scratch[(y * bpr) + (col >> 3)] & masks[si];
1346 if (byte) {
1347 nx = x - shiftx;
1348 ny = y - shifty;
1349
1350 if (nx < 0)
1351 nx += wd;
1352 else if (nx >= wd)
1353 nx -= wd;
1354 if (ny < 0)
1355 ny += ht;
1356 else if (ny >= ht)
1357 ny -= ht;
1358
1359 nx *= grid->bpp;
1360 di = (nx & 7) / grid->bpp;
1361 if (di < si)
1362 byte <<= (si - di) * grid->bpp;
1363 else if (di > si)
1364 byte >>= (di - si) * grid->bpp;
1365 grid->sel.bitmap[(ny * bpr) + (nx >> 3)] |= byte;
1366 }
1367 }
1368 }
1369 } else
1370 /*
1371 * Copy the scratch buffer back to the main buffer.
1372 */
1373 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
1374
1375 /*
1376 * Determine the new selection width and height.
1377 */
1378 ox = oy = 0;
1379 nx = ny = 16384;
1380 for (y = 0; y < ht; y++) {
1381 for (col = x = 0; x < wd; x++, col += grid->bpp) {
1382 si = (col & 7) / grid->bpp;
1383 if (grid->sel.bitmap[(y * bpr) + (col >> 3)] & masks[si]) {
1384 ox = MAX(ox, x);
1385 nx = MIN(nx, x);
1386 oy = MAX(oy, y);
1387 ny = MIN(ny, y);
1388 }
1389 }
1390 }
1391
1392 /*
1393 * Recalculate the center corrdinates so the selection will be
1394 * positioned nicely once it is shifted to the upper left corner.
1395 */
1396 cx = grid->sel.width >> 1;
1397 cy = grid->sel.height >> 1;
1398
1399 /*
1400 * Set the new width and height.
1401 */
1402 grid->sel.width = (ox - nx) + 1;
1403 grid->sel.height = (oy - ny) + 1;
1404
1405 /*
1406 * Shift again to force the selection to the upper left corner.
1407 */
1408 if (nx || ny) {
1409 (void) memset((char *) scratch, 0, bytes);
1410 for (y = 0; y < ht; y++) {
1411 for (col = x = 0; x < wd; x++, col += grid->bpp) {
1412 si = (col & 7) / grid->bpp;
1413 byte = grid->sel.bitmap[(y * bpr) + (col >> 3)] &
1414 masks[si];
1415 if (byte) {
1416 oy = y - ny;
1417 ox = (x - nx) * grid->bpp;
1418 di = (ox & 7) / grid->bpp;
1419 if (di < si)
1420 byte <<= (si - di) * grid->bpp;
1421 else if (di > si)
1422 byte >>= (di - si) * grid->bpp;
1423 scratch[(oy * bpr) + (ox >> 3)] |= byte;
1424 }
1425 }
1426 }
1427 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
1428 }
1429
1430 /*
1431 * Determine the new top left coordinates from the center coordinates.
1432 */
1433 grid->sel.x = (grid->sel.x + cx) - (grid->sel.width >> 1);
1434 grid->sel.y = (grid->sel.y + cy) - (grid->sel.height >> 1);
1435
1436 /*
1437 * If the rotation caused the selection rectangle to overlap the edges
1438 * of the grid, shift it so it is completely visible again.
1439 */
1440 if (grid->sel.x + grid->sel.width > grid->grid_width)
1441 grid->sel.x -= (grid->sel.x + grid->sel.width) - grid->grid_width;
1442 if (grid->sel.y + grid->sel.height > grid->grid_height)
1443 grid->sel.y -= (grid->sel.y + grid->sel.height) - grid->grid_height;
1444
1445 /*
1446 * Mark the grid as being modified.
1447 */
1448 grid->modified = 1;
1449 }
1450
1451 return rotated;
1452 }
1453
1454 static void
_bdf_rotate_resize(bdf_glyph_grid_t * grid,int mul90,short degrees,int * resize)1455 _bdf_rotate_resize(bdf_glyph_grid_t *grid, int mul90, short degrees,
1456 int *resize)
1457 {
1458 unsigned short wd, ht;
1459 short cx, cy, x1, y1, x2, y2;
1460 double dx1, dy1, dx2, dy2;
1461 bdf_metrics_t metrics;
1462
1463 *resize = 0;
1464 (void) memset((char *) &metrics, 0, sizeof(bdf_metrics_t));
1465
1466 metrics.x_offset = grid->font_bbx.x_offset;
1467 metrics.width = grid->font_bbx.width;
1468 metrics.ascent = grid->font_bbx.ascent;
1469 metrics.descent = grid->font_bbx.descent;
1470 metrics.height = grid->font_bbx.height;
1471 metrics.y_offset = grid->font_bbx.y_offset;
1472
1473 cx = grid->glyph_x + (grid->glyph_bbx.width >> 1);
1474 cy = grid->glyph_y + (grid->glyph_bbx.height >> 1);
1475
1476 /*
1477 * Rotate the lower left and upper right corners and check for a potential
1478 * resize.
1479 */
1480 x1 = grid->glyph_x;
1481 y1 = grid->glyph_y + grid->glyph_bbx.height;
1482 x2 = grid->glyph_x + grid->glyph_bbx.width;
1483 y2 = grid->glyph_y;
1484
1485 dx1 = (double) (x1 - cx);
1486 dy1 = (double) (y1 - cy);
1487 dx2 = (double) (x2 - cx);
1488 dy2 = (double) (y2 - cx);
1489
1490 if (mul90) {
1491 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
1492 (dy1 * _bdf_sin_tbl[degrees]));
1493 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
1494 (dy1 * _bdf_cos_tbl[degrees]));
1495 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
1496 (dy2 * _bdf_sin_tbl[degrees]));
1497 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
1498 (dy2 * _bdf_cos_tbl[degrees]));
1499 } else {
1500 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
1501 (dy1 * _bdf_sin_tbl[degrees]));
1502 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
1503 (dy1 * _bdf_cos_tbl[degrees]));
1504 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
1505 (dy2 * _bdf_sin_tbl[degrees]));
1506 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
1507 (dy2 * _bdf_cos_tbl[degrees]));
1508 }
1509
1510 wd = MYABS(x2 - x1);
1511 ht = MYABS(y2 - y1);
1512 if (wd > metrics.width) {
1513 metrics.width += wd - grid->font_bbx.width;
1514 *resize = 1;
1515 }
1516 if (ht > metrics.height) {
1517 metrics.ascent += ht - grid->font_bbx.height;
1518 metrics.height += ht - grid->font_bbx.height;
1519 *resize = 1;
1520 }
1521
1522 /*
1523 * Rotate the upper left and lower right corners and check for a potential
1524 * resize.
1525 */
1526 x1 = grid->glyph_x;
1527 y1 = grid->glyph_y;
1528 x2 = grid->glyph_x + grid->glyph_bbx.width;
1529 y2 = grid->glyph_y + grid->glyph_bbx.height;
1530
1531 dx1 = (double) (x1 - cx);
1532 dy1 = (double) (y1 - cy);
1533 dx2 = (double) (x2 - cx);
1534 dy2 = (double) (y2 - cx);
1535
1536 if (mul90) {
1537 x1 = cx + (short) ((dx1 * _bdf_cos_tbl[degrees]) -
1538 (dy1 * _bdf_sin_tbl[degrees]));
1539 y1 = cy + (short) ((dx1 * _bdf_sin_tbl[degrees]) +
1540 (dy1 * _bdf_cos_tbl[degrees]));
1541 x2 = cx + (short) ((dx2 * _bdf_cos_tbl[degrees]) -
1542 (dy2 * _bdf_sin_tbl[degrees]));
1543 y2 = cy + (short) ((dx2 * _bdf_sin_tbl[degrees]) +
1544 (dy2 * _bdf_cos_tbl[degrees]));
1545 } else {
1546 x1 = cx + _bdf_ceiling((dx1 * _bdf_cos_tbl[degrees]) -
1547 (dy1 * _bdf_sin_tbl[degrees]));
1548 y1 = cy + _bdf_ceiling((dx1 * _bdf_sin_tbl[degrees]) +
1549 (dy1 * _bdf_cos_tbl[degrees]));
1550 x2 = cx + _bdf_ceiling((dx2 * _bdf_cos_tbl[degrees]) -
1551 (dy2 * _bdf_sin_tbl[degrees]));
1552 y2 = cy + _bdf_ceiling((dx2 * _bdf_sin_tbl[degrees]) +
1553 (dy2 * _bdf_cos_tbl[degrees]));
1554 }
1555
1556 wd = MYABS(x2 - x1);
1557 ht = MYABS(y2 - y1);
1558 if (wd > metrics.width) {
1559 metrics.width += wd - grid->font_bbx.width;
1560 *resize = 1;
1561 }
1562 if (ht > metrics.height) {
1563 metrics.ascent += ht - grid->font_bbx.height;
1564 metrics.height += ht - grid->font_bbx.height;
1565 *resize = 1;
1566 }
1567
1568 if (*resize)
1569 (void) bdf_grid_resize(grid, &metrics);
1570 }
1571
1572 static void
_bdf_shear_resize(bdf_glyph_grid_t * grid,short degrees,int neg,int * resize)1573 _bdf_shear_resize(bdf_glyph_grid_t *grid, short degrees, int neg, int *resize)
1574 {
1575 unsigned short wd;
1576 short x1, y1, x2, y2;
1577 bdf_metrics_t metrics;
1578
1579 *resize = 0;
1580 (void) memset((char *) &metrics, 0, sizeof(bdf_metrics_t));
1581
1582 metrics.x_offset = grid->font_bbx.x_offset;
1583 metrics.width = grid->font_bbx.width;
1584 metrics.ascent = grid->font_bbx.ascent;
1585 metrics.descent = grid->font_bbx.descent;
1586 metrics.height = grid->font_bbx.height;
1587 metrics.y_offset = grid->font_bbx.y_offset;
1588
1589 /*
1590 * Shear the lower left and upper right corners and check for a potential
1591 * resize.
1592 */
1593 x1 = 0;
1594 y1 = grid->glyph_bbx.height;
1595 x2 = grid->glyph_bbx.width;
1596 y2 = 0;
1597
1598 if (neg) {
1599 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
1600 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
1601 } else {
1602 x1 += (short) ((double) (grid->glyph_bbx.height - y1) *
1603 _bdf_tan_tbl[degrees]);
1604 x2 += (short) ((double) (grid->glyph_bbx.height - y2) *
1605 _bdf_tan_tbl[degrees]);
1606 }
1607
1608 wd = MYABS(x2 - x1);
1609 if (wd > metrics.width) {
1610 metrics.width += wd - grid->font_bbx.width;
1611 *resize = 1;
1612 }
1613
1614 /*
1615 * Shear the upper left and lower right corners and check for a potential
1616 * resize.
1617 */
1618 x1 = 0;
1619 y1 = 0;
1620 x2 = grid->glyph_bbx.width;
1621 y2 = grid->glyph_bbx.height;
1622
1623 if (neg) {
1624 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
1625 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
1626 } else {
1627 x1 += (short) ((double) (grid->glyph_bbx.height - y1) *
1628 _bdf_tan_tbl[degrees]);
1629 x2 += (short) ((double) (grid->glyph_bbx.height - y2) *
1630 _bdf_tan_tbl[degrees]);
1631 }
1632
1633 wd = MYABS(x2 - x1);
1634 if (wd > metrics.width) {
1635 metrics.width += wd - grid->font_bbx.width;
1636 *resize = 1;
1637 }
1638
1639 if (*resize)
1640 (void) bdf_grid_resize(grid, &metrics);
1641 }
1642
1643 /*
1644 * Rotate the bitmap in the grid by some number of degrees.
1645 */
1646 int
bdf_grid_rotate(bdf_glyph_grid_t * grid,short degrees,int * resize)1647 bdf_grid_rotate(bdf_glyph_grid_t *grid, short degrees, int *resize)
1648 {
1649 int rotated, mul90;
1650 short nx, ny, cx, cy, x, y, wd, ht;
1651 short ox, oy, gx, gy, shiftx, shifty;
1652 unsigned short si, di, col, byte;
1653 double dx, dy;
1654 unsigned short bytes, bpr;
1655 unsigned char *scratch, *masks;
1656
1657 rotated = 0;
1658
1659 /*
1660 * Make sure the number of degrees is between 0 and 359 and adjusted to a
1661 * positive number of degrees if necessary.
1662 */
1663 while (degrees < 0)
1664 degrees += 360;
1665 while (degrees >= 360)
1666 degrees -= 360;
1667
1668 if (grid == 0 || degrees == 0 ||
1669 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 0))
1670 return rotated;
1671
1672 masks = 0;
1673 switch (grid->bpp) {
1674 case 1: masks = bdf_onebpp; break;
1675 case 2: masks = bdf_twobpp; break;
1676 case 4: masks = bdf_fourbpp; break;
1677 case 8: masks = bdf_eightbpp; break;
1678 }
1679
1680 mul90 = ((degrees % 90) == 0) ? 1 : 0;
1681
1682 /*
1683 * Force the grid to resize if the rotation requires it.
1684 */
1685 _bdf_rotate_resize(grid, mul90, degrees, resize);
1686
1687 if (grid->sel.width != 0 && grid->sel.height != 0)
1688 return _bdf_rotate_selection(grid, mul90, degrees);
1689
1690 /*
1691 * Halve the byte count in the grid for later use.
1692 */
1693 bytes = grid->bytes >> 1;
1694
1695 /*
1696 * Point at the scratch buffer area and initialize it.
1697 */
1698 scratch = grid->bitmap + bytes;
1699 (void) memset((char *) scratch, 0, bytes);
1700
1701 /*
1702 * Determine the bytes per row.
1703 */
1704 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1705
1706 /*
1707 * Determine the center coordinates of the glyph bitmap rectangle.
1708 */
1709 cx = grid->glyph_x + (grid->glyph_bbx.width >> 1);
1710 cy = grid->glyph_y + (grid->glyph_bbx.height >> 1);
1711
1712 /*
1713 * Only run over the rectangle containing the glyph itself.
1714 */
1715 gx = grid->glyph_x;
1716 gy = grid->glyph_y;
1717
1718 wd = gx + grid->glyph_bbx.width;
1719 ht = gy + grid->glyph_bbx.height;
1720
1721 /*
1722 * Initialize the adjustment counts used if the bitmap
1723 * wraps around the edge.
1724 */
1725 shiftx = shifty = 0;
1726
1727 for (y = gy; y < ht; y++) {
1728 col = gx * grid->bpp;
1729 for (x = gx; x < wd; x++, col += grid->bpp) {
1730
1731 /*
1732 * Rotate the point.
1733 */
1734 dx = (double) (x - cx);
1735 dy = (double) (y - cy);
1736 if (mul90) {
1737 nx = cx + (short) ((dx * _bdf_cos_tbl[degrees]) -
1738 (dy * _bdf_sin_tbl[degrees]));
1739 ny = cy + (short) ((dx * _bdf_sin_tbl[degrees]) +
1740 (dy * _bdf_cos_tbl[degrees]));
1741 } else {
1742 nx = cx + _bdf_ceiling((dx * _bdf_cos_tbl[degrees]) -
1743 (dy * _bdf_sin_tbl[degrees]));
1744 ny = cy + _bdf_ceiling((dx * _bdf_sin_tbl[degrees]) +
1745 (dy * _bdf_cos_tbl[degrees]));
1746 }
1747
1748 /*
1749 * Wrap the coordinates around the edges if necessary.
1750 */
1751 if (nx < 0) {
1752 shiftx = MIN(shiftx, nx);
1753 nx += grid->grid_width;
1754 } else if (nx >= grid->grid_width) {
1755 ox = (nx - grid->grid_width) + 1;
1756 shiftx = MAX(shiftx, ox);
1757 nx -= grid->grid_width;
1758 }
1759 if (ny < 0) {
1760 shifty = MIN(shifty, ny);
1761 ny += grid->grid_height;
1762 } else if (ny >= grid->grid_height) {
1763 oy = (ny - grid->grid_height) + 1;
1764 shifty = MAX(shifty, oy);
1765 ny -= grid->grid_height;
1766 }
1767
1768 si = (col & 7) / grid->bpp;
1769 byte = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
1770 if (byte) {
1771 rotated = 1;
1772 nx *= grid->bpp;
1773 di = (nx & 7) / grid->bpp;
1774 if (di < si)
1775 byte <<= (si - di) * grid->bpp;
1776 else if (di > si)
1777 byte >>= (di - si) * grid->bpp;
1778 scratch[(ny * bpr) + (nx >> 3)] |= byte;
1779 }
1780 }
1781 }
1782
1783 if (rotated) {
1784 /*
1785 * If a shift is required, then shift the scratch area back into
1786 * the main bitmap.
1787 */
1788 if (shiftx || shifty) {
1789 (void) memset((char *) grid->bitmap, 0, bytes);
1790 for (y = 0; y < grid->grid_height; y++) {
1791 for (col = x = 0; x < grid->grid_width;
1792 x++, col += grid->bpp) {
1793 si = (col & 7) / grid->bpp;
1794 byte = scratch[(y * bpr) + (col >> 3)] & masks[si];
1795 if (byte) {
1796 nx = x - shiftx;
1797 ny = y - shifty;
1798
1799 if (nx < 0)
1800 nx += grid->grid_width;
1801 else if (nx >= grid->grid_width)
1802 nx -= grid->grid_width;
1803 if (ny < 0)
1804 ny += grid->grid_height;
1805 else if (ny >= grid->grid_height)
1806 ny -= grid->grid_height;
1807
1808 nx *= grid->bpp;
1809 di = (nx & 7) / grid->bpp;
1810 if (di < si)
1811 byte <<= (si - di) * grid->bpp;
1812 else if (di > si)
1813 byte >>= (di - si) * grid->bpp;
1814 grid->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
1815 }
1816 }
1817 }
1818 } else
1819 /*
1820 * Copy the scratch buffer back to the main buffer.
1821 */
1822 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
1823
1824 /*
1825 * Determine the new glyph bounding box and the top left coordinates.
1826 */
1827 ox = oy = 0;
1828 nx = ny = 16384;
1829 for (y = 0; y < grid->grid_height; y++) {
1830 for (col = x = 0; x < grid->grid_width; x++, col += grid->bpp) {
1831 si = (col & 7) / grid->bpp;
1832 if (grid->bitmap[(y * bpr) + (col >> 3)] & masks[si]) {
1833 nx = MIN(nx, x);
1834 ox = MAX(ox, x);
1835 ny = MIN(ny, y);
1836 oy = MAX(oy, y);
1837 }
1838 }
1839 }
1840
1841 /*
1842 * Set the new top left corrdinates.
1843 */
1844 grid->glyph_x = nx;
1845 grid->glyph_y = ny;
1846
1847 /*
1848 * Set the new glyph bounding box.
1849 */
1850 grid->glyph_bbx.width = (ox - nx) + 1;
1851 grid->glyph_bbx.x_offset = nx - grid->base_x;
1852 grid->glyph_bbx.height = (oy - ny) + 1;
1853 grid->glyph_bbx.ascent = grid->base_y - ny;
1854 grid->glyph_bbx.descent = grid->glyph_bbx.height -
1855 grid->glyph_bbx.ascent;
1856 grid->glyph_bbx.y_offset = -grid->glyph_bbx.descent;
1857
1858 /*
1859 * Mark the grid as being modified.
1860 */
1861 grid->modified = 1;
1862 }
1863
1864 return rotated;
1865 }
1866
1867 int
bdf_grid_shear(bdf_glyph_grid_t * grid,short degrees,int * resize)1868 bdf_grid_shear(bdf_glyph_grid_t *grid, short degrees, int *resize)
1869 {
1870 int sheared, neg;
1871 short cx, cy, wd, ht, gx, gy, x, y;
1872 short nx, ox, ny, oy, shiftx, shifty;
1873 unsigned short bytes, bpr, si, di, col, byte;
1874 unsigned char *scratch, *masks;
1875
1876 sheared = 0;
1877
1878 if (degrees == 0 || degrees < -45 || degrees > 45 || grid == 0 ||
1879 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 0))
1880 return sheared;
1881
1882 if ((neg = (degrees < 0)))
1883 degrees = -degrees;
1884
1885 /*
1886 * Check to see if the grid needs to be resized to hold the sheared glyph.
1887 */
1888 _bdf_shear_resize(grid, degrees, neg, resize);
1889
1890 masks = 0;
1891 switch (grid->bpp) {
1892 case 1: masks = bdf_onebpp; break;
1893 case 2: masks = bdf_twobpp; break;
1894 case 4: masks = bdf_fourbpp; break;
1895 case 8: masks = bdf_eightbpp; break;
1896 }
1897
1898 /*
1899 * Halve the byte count in the grid for later use.
1900 */
1901 bytes = grid->bytes >> 1;
1902
1903 /*
1904 * Point at the scratch buffer area and initialize it.
1905 */
1906 scratch = grid->bitmap + bytes;
1907 (void) memset((char *) scratch, 0, bytes);
1908
1909 /*
1910 * Determine the bytes per row.
1911 */
1912 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1913
1914 /*
1915 * Determine the center coordinates of the glyph bitmap rectangle.
1916 */
1917 gx = grid->glyph_x;
1918 gy = grid->glyph_y;
1919
1920 cx = gx + (grid->glyph_bbx.width >> 1);
1921 cy = gy + (grid->glyph_bbx.height >> 1);
1922
1923 wd = gx + grid->glyph_bbx.width;
1924 ht = gy + grid->glyph_bbx.height;
1925
1926 shiftx = shifty = 0;
1927 for (y = gy; y < ht; y++) {
1928 col = gx * grid->bpp;
1929 for (x = gx; x < wd; x++, col += grid->bpp) {
1930 ny = y;
1931 if (neg)
1932 nx = x + (short) ((double) y * _bdf_tan_tbl[degrees]);
1933 else
1934 nx = x + (short) ((double) (gy + (ht - y)) *
1935 _bdf_tan_tbl[degrees]);
1936
1937 if (nx < 0) {
1938 shiftx = MIN(shiftx, nx);
1939 nx += grid->grid_width;
1940 } else if (nx >= grid->grid_width) {
1941 ox = (nx - grid->grid_width) + 1;
1942 shiftx = MAX(shiftx, ox);
1943 nx -= grid->grid_width;
1944 }
1945 if (ny < 0) {
1946 shifty = MIN(shifty, ny);
1947 ny += grid->grid_height;
1948 } else if (ny >= grid->grid_height) {
1949 oy = (ny - grid->grid_height) + 1;
1950 shifty = MAX(shifty, oy);
1951 ny -= grid->grid_height;
1952 }
1953
1954 si = (col & 7) / grid->bpp;
1955 byte = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
1956 if (byte) {
1957 sheared = 1;
1958 nx *= grid->bpp;
1959 di = (nx & 7) / grid->bpp;
1960 if (di < si)
1961 byte <<= (si - di) * grid->bpp;
1962 else if (di > si)
1963 byte >>= (di - si) * grid->bpp;
1964 scratch[(y * bpr) + (nx >> 3)] |= byte;
1965 }
1966 }
1967 }
1968
1969 if (sheared) {
1970 /*
1971 * If a shift is required, then shift the scratch area back into
1972 * the main bitmap.
1973 */
1974 if (shiftx || shifty) {
1975 (void) memset((char *) grid->bitmap, 0, bytes);
1976 for (y = 0; y < grid->grid_height; y++) {
1977 for (col = x = 0; x < grid->grid_width;
1978 x++, col += grid->bpp) {
1979 si = (col & 7) / grid->bpp;
1980 byte = scratch[(y * bpr) + (col >> 3)] & masks[si];
1981 if (byte) {
1982 nx = x - shiftx;
1983 ny = y - shifty;
1984
1985 if (nx < 0)
1986 nx += grid->grid_width;
1987 else if (nx >= grid->grid_width)
1988 nx -= grid->grid_width;
1989 if (ny < 0)
1990 ny += grid->grid_height;
1991 else if (ny >= grid->grid_height)
1992 ny -= grid->grid_height;
1993
1994 nx *= grid->bpp;
1995 di = (nx & 7) / grid->bpp;
1996 if (di < si)
1997 byte <<= (si - di) * grid->bpp;
1998 else if (di > si)
1999 byte >>= (di - si) * grid->bpp;
2000 grid->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
2001 }
2002 }
2003 }
2004 } else
2005 /*
2006 * Copy the scratch buffer back to the main buffer.
2007 */
2008 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
2009
2010 ox = oy = 0;
2011 nx = ny = 16384;
2012 for (y = 0; y < grid->grid_height; y++) {
2013 for (col = x = 0; x < grid->grid_width; x++, col += grid->bpp) {
2014 si = (col & 7) / grid->bpp;
2015 if (grid->bitmap[(y * bpr) + (col >> 3)] & masks[si]) {
2016 ox = MAX(ox, x);
2017 nx = MIN(nx, x);
2018 oy = MAX(oy, y);
2019 ny = MIN(ny, y);
2020 }
2021 }
2022 }
2023
2024 /*
2025 * Set the new top left corrdinates.
2026 */
2027 grid->glyph_x = nx;
2028 grid->glyph_y = ny;
2029
2030 /*
2031 * Set the new glyph bounding box.
2032 */
2033 grid->glyph_bbx.width = (ox - nx) + 1;
2034 grid->glyph_bbx.x_offset = nx - grid->base_x;
2035 grid->glyph_bbx.height = (oy - ny) + 1;
2036 grid->glyph_bbx.ascent = grid->base_y - ny;
2037 grid->glyph_bbx.descent = grid->glyph_bbx.height -
2038 grid->glyph_bbx.ascent;
2039 grid->glyph_bbx.y_offset = -grid->glyph_bbx.descent;
2040
2041 /*
2042 * Mark the grid as being modified.
2043 */
2044 grid->modified = 1;
2045 }
2046
2047 return sheared;
2048 }
2049
2050 int
bdf_grid_embolden(bdf_glyph_grid_t * grid)2051 bdf_grid_embolden(bdf_glyph_grid_t *grid)
2052 {
2053 int done;
2054 short wd, ht, gx, gy, x, y;
2055 unsigned short b1, b2, bpr, si, di, col;
2056 unsigned char *masks;
2057
2058 done = 0;
2059
2060 if (grid == 0 ||
2061 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 0))
2062 return done;
2063
2064 masks = 0;
2065 switch (grid->bpp) {
2066 case 1: masks = bdf_onebpp; break;
2067 case 2: masks = bdf_twobpp; break;
2068 case 4: masks = bdf_fourbpp; break;
2069 case 8: masks = bdf_eightbpp; break;
2070 }
2071
2072 /*
2073 * Determine the bytes per row.
2074 */
2075 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2076
2077 gx = grid->glyph_x;
2078 gy = grid->glyph_y;
2079
2080 wd = gx + grid->glyph_bbx.width;
2081 ht = gy + grid->glyph_bbx.height;
2082
2083 if (grid->spacing == BDF_PROPORTIONAL ||
2084 (grid->spacing == BDF_MONOWIDTH &&
2085 grid->glyph_bbx.width < grid->font_bbx.width))
2086 /*
2087 * Only allow horizontal expansion in the cases that make sense.
2088 */
2089 wd++;
2090
2091 for (y = gy; y < ht; y++) {
2092 col = (wd - 1) * grid->bpp;
2093 for (x = wd - 1; x > gx; x--, col -= grid->bpp) {
2094 si = (col & 7) / grid->bpp;
2095 di = ((col - grid->bpp) & 7) / grid->bpp;
2096 b1 = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
2097 b2 = grid->bitmap[(y * bpr) + ((col - grid->bpp) >> 3)] &
2098 masks[di];
2099 if (!b1 && b2) {
2100 if (di < si)
2101 b2 >>= (si - di) * grid->bpp;
2102 else if (di > si)
2103 b2 <<= (di - si) * grid->bpp;
2104 grid->bitmap[(y * bpr) + (col >> 3)] |= b2;
2105 /*
2106 * Mark the grid as being modified.
2107 */
2108 done = grid->modified = 1;
2109 }
2110 }
2111 }
2112
2113 /*
2114 * Adjust the glyph width so it will be reflected when the glyph is stored
2115 * back in the font.
2116 */
2117 grid->glyph_bbx.width = wd - gx;
2118
2119 return done;
2120 }
2121
2122 /**************************************************************************
2123 *
2124 * Glyph grid selection functions.
2125 *
2126 **************************************************************************/
2127
2128 int
bdf_has_selection(bdf_glyph_grid_t * grid,short * x,short * y,short * width,short * height)2129 bdf_has_selection(bdf_glyph_grid_t *grid, short *x, short *y,
2130 short *width, short *height)
2131 {
2132 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 0))
2133 return 0;
2134
2135 if (x != 0)
2136 *x = grid->sel.x;
2137 if (y != 0)
2138 *y = grid->sel.y;
2139 if (width != 0)
2140 *width = grid->sel.width;
2141 if (height != 0)
2142 *height = grid->sel.height;
2143
2144 return 1;
2145 }
2146
2147 /*
2148 * Select a rectangle on the grid.
2149 */
2150 void
bdf_set_selection(bdf_glyph_grid_t * grid,short x,short y,short width,short height)2151 bdf_set_selection(bdf_glyph_grid_t *grid, short x, short y,
2152 short width, short height)
2153 {
2154 short nx, ny, wd, ht, ssize, dx, dy, col;
2155 unsigned short bytes, bpr, sbpr, si, di, byte;
2156 unsigned char *masks;
2157
2158 if (grid == 0)
2159 return;
2160
2161 /*
2162 * Make sure the specified rectangle is within reasonable bounds.
2163 */
2164 if (x < 0 || x >= grid->grid_width)
2165 x = 0;
2166 if (y < 0 || y >= grid->grid_height)
2167 y = 0;
2168
2169 if (x + width > grid->grid_width)
2170 width = (x + width) - grid->grid_width;
2171 if (y + height > grid->grid_height)
2172 height = (y + height) - grid->grid_height;
2173
2174 grid->sel.x = x;
2175 grid->sel.y = y;
2176 grid->sel.width = width;
2177 grid->sel.height = height;
2178
2179 /*
2180 * Allocate enough space to represent a square the size of the largest
2181 * of the width and height of the selection. This allows rotation and
2182 * flipping of the selected bitmap.
2183 */
2184 ssize = MAX(width, height);
2185
2186 bytes = ((((ssize * grid->bpp) + 7) >> 3) * ssize) << 1;
2187
2188 /*
2189 * If the selection is being removed (width and height are 0), then simply
2190 * return.
2191 */
2192 if (bytes == 0)
2193 return;
2194
2195 masks = 0;
2196 switch (grid->bpp) {
2197 case 1: masks = bdf_onebpp; break;
2198 case 2: masks = bdf_twobpp; break;
2199 case 4: masks = bdf_fourbpp; break;
2200 case 8: masks = bdf_eightbpp; break;
2201 }
2202
2203 if (bytes > grid->sel.bytes) {
2204 if (grid->sel.bytes == 0)
2205 grid->sel.bitmap = (unsigned char *) malloc(bytes);
2206 else
2207 grid->sel.bitmap = (unsigned char *)
2208 realloc((char *) grid->sel.bitmap, bytes);
2209 grid->sel.bytes = bytes;
2210 } else
2211 bytes = grid->sel.bytes;
2212
2213 /*
2214 * Initialize the selection bitmap and copy the selected bits to it.
2215 */
2216 (void) memset((char *) grid->sel.bitmap, 0, bytes);
2217
2218 wd = x + width;
2219 ht = y + height;
2220
2221 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2222 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2223
2224 for (ny = 0, dy = y; dy < ht; dy++, ny++) {
2225 col = x * grid->bpp;
2226 for (nx = 0, dx = x; dx < wd;
2227 dx++, nx += grid->bpp, col += grid->bpp) {
2228 si = (col & 7) / grid->bpp;
2229 byte = grid->bitmap[(dy * bpr) + (col >> 3)] & masks[si];
2230 if (byte) {
2231 di = (nx & 7) / grid->bpp;
2232 if (di < si)
2233 byte <<= (si - di) * grid->bpp;
2234 else if (di > si)
2235 byte >>= (di - si) * grid->bpp;
2236 grid->sel.bitmap[(ny * sbpr) + (nx >> 3)] |= byte;
2237 }
2238 }
2239 }
2240 }
2241
2242 /*
2243 * Detach a selection in preparation for moving it. What it does is clear the
2244 * bits set in the selection from the main grid. Again, this is only used for
2245 * move operations.
2246 */
2247 void
bdf_detach_selection(bdf_glyph_grid_t * grid)2248 bdf_detach_selection(bdf_glyph_grid_t *grid)
2249 {
2250 short sx, sy, x, y, wd, ht, dx;
2251 unsigned short bpr, sbpr, si, di, byte;
2252 unsigned char *masks;
2253
2254 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 0))
2255 return;
2256
2257 masks = 0;
2258 switch (grid->bpp) {
2259 case 1: masks = bdf_onebpp; break;
2260 case 2: masks = bdf_twobpp; break;
2261 case 4: masks = bdf_fourbpp; break;
2262 case 8: masks = bdf_eightbpp; break;
2263 }
2264
2265 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2266 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2267
2268 wd = grid->sel.x + grid->sel.width;
2269 ht = grid->sel.y + grid->sel.height;
2270
2271 for (sy = 0, y = grid->sel.y; y < ht; y++, sy++) {
2272 for (sx = 0, x = grid->sel.x; x < wd; x++, sx += grid->bpp) {
2273 si = (sx & 7) / grid->bpp;
2274 byte = grid->sel.bitmap[(sy * sbpr) + (sx >> 3)] & masks[si];
2275 if (byte) {
2276 dx = x * grid->bpp;
2277 di = (dx & 7) / grid->bpp;
2278 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
2279 }
2280 }
2281 }
2282
2283 /*
2284 * Crop the new image to determine the new bounds with the selection.
2285 */
2286 (void) bdf_grid_crop(grid, 1);
2287 }
2288
2289 void
bdf_attach_selection(bdf_glyph_grid_t * grid)2290 bdf_attach_selection(bdf_glyph_grid_t *grid)
2291 {
2292 short sx, sy, x, y, wd, ht;
2293 unsigned short bpr, sbpr, dx, di, si, byte;
2294 unsigned char *masks;
2295
2296 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 0))
2297 return;
2298
2299 masks = 0;
2300 switch (grid->bpp) {
2301 case 1: masks = bdf_onebpp; break;
2302 case 2: masks = bdf_twobpp; break;
2303 case 4: masks = bdf_fourbpp; break;
2304 case 8: masks = bdf_eightbpp; break;
2305 }
2306
2307 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2308 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2309
2310 wd = grid->sel.x + grid->sel.width;
2311 ht = grid->sel.y + grid->sel.height;
2312
2313 for (sy = 0, y = grid->sel.y; y < ht; y++, sy++) {
2314 for (sx = 0, x = grid->sel.x; x < wd; x++, sx += grid->bpp) {
2315 si = (sx & 7) / grid->bpp;
2316 byte = grid->sel.bitmap[(sy * sbpr) + (sx >> 3)] & masks[si];
2317 if (byte) {
2318 dx = x * grid->bpp;
2319 di = (dx & 7) / grid->bpp;
2320 if (di < si)
2321 byte <<= (si - di) * grid->bpp;
2322 else if (di > si)
2323 byte >>= (di - si) * grid->bpp;
2324 grid->bitmap[(y * bpr) + (dx >> 3)] |= byte;
2325 }
2326 }
2327 }
2328
2329 /*
2330 * Crop the new image to determine the new bounds with the selection.
2331 */
2332 (void) bdf_grid_crop(grid, 1);
2333 }
2334
2335 /*
2336 * Indicate the selection no longer exists by setting the width and height to
2337 * 0.
2338 */
2339 void
bdf_lose_selection(bdf_glyph_grid_t * grid)2340 bdf_lose_selection(bdf_glyph_grid_t *grid)
2341 {
2342 if (grid == 0)
2343 return;
2344 grid->sel.width = grid->sel.height = 0;
2345 }
2346
2347 /*
2348 * Delete the selection by first detaching it which will erase the rectangle
2349 * on the grid and then losing the selection.
2350 */
2351 void
bdf_delete_selection(bdf_glyph_grid_t * grid)2352 bdf_delete_selection(bdf_glyph_grid_t *grid)
2353 {
2354 bdf_detach_selection(grid);
2355 bdf_lose_selection(grid);
2356 }
2357
2358 /*
2359 * Check to see if a coordinate pair is in the selected region.
2360 */
2361 int
bdf_in_selection(bdf_glyph_grid_t * grid,short x,short y,short * set)2362 bdf_in_selection(bdf_glyph_grid_t *grid, short x, short y, short *set)
2363 {
2364 short wd, ht;
2365 unsigned short bpr, si, di, byte;
2366 unsigned char *masks;
2367
2368 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 0))
2369 return 0;
2370
2371 di = 0;
2372 masks = 0;
2373 switch (grid->bpp) {
2374 case 1: masks = bdf_onebpp; di = 7; break;
2375 case 2: masks = bdf_twobpp; di = 3; break;
2376 case 4: masks = bdf_fourbpp; di = 1; break;
2377 case 8: masks = bdf_eightbpp; di = 0; break;
2378 }
2379
2380 bpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2381
2382 wd = grid->sel.x + grid->sel.width;
2383 ht = grid->sel.y + grid->sel.height;
2384
2385 if ((x >= grid->sel.x && x < wd) && (y >= grid->sel.y && y < ht)) {
2386 if (set) {
2387 /*
2388 * Adjust the byte back to an index value.
2389 */
2390 x *= grid->bpp;
2391 si = (x & 7) / grid->bpp;
2392 byte = grid->sel.bitmap[(y * bpr) + (x >> 3)] & masks[si];
2393 if (di > si)
2394 byte >>= (di - si) * grid->bpp;
2395 *set = byte;
2396 }
2397 return 1;
2398 }
2399
2400 return 0;
2401 }
2402
2403 int
bdf_grid_shift(bdf_glyph_grid_t * grid,short xcount,short ycount)2404 bdf_grid_shift(bdf_glyph_grid_t *grid, short xcount, short ycount)
2405 {
2406 int sel, delta;
2407 short xdir, ydir, x, y, wd, ht, dx, dy, nx, ny;
2408 unsigned short bytes, bpr, si, di, byte, col;
2409 unsigned char *scratch, *masks;
2410
2411 if (grid == 0)
2412 return 0;
2413
2414 xdir = ydir = 1;
2415 if (xcount < 0) {
2416 xdir = -1;
2417 xcount = -xcount;
2418 }
2419
2420 if (ycount < 0) {
2421 ydir = -1;
2422 ycount = -ycount;
2423 }
2424
2425 /*
2426 * Adjust the shift counts if they are larger than they should be.
2427 */
2428 if (xcount > grid->grid_width)
2429 xcount -= grid->grid_width;
2430 if (ycount > grid->grid_height)
2431 ycount -= grid->grid_height;
2432
2433 /*
2434 * Adjust the counts to limit the shift to the boundaries of the grid.
2435 */
2436 if (grid->sel.width != 0 && grid->sel.height != 0) {
2437 /*
2438 * The selection is being shifted.
2439 */
2440 x = grid->sel.x;
2441 y = grid->sel.y;
2442 wd = grid->sel.width;
2443 ht = grid->sel.height;
2444 sel = 1;
2445 } else {
2446 x = grid->glyph_x;
2447 y = grid->glyph_y;
2448 wd = grid->glyph_bbx.width;
2449 ht = grid->glyph_bbx.height;
2450 sel = 0;
2451 }
2452
2453 /*
2454 * If the width and height are 0, then simply return, because there
2455 * is nothing to shift.
2456 */
2457 if (wd == 0 && ht == 0)
2458 return 0;
2459
2460 if (xdir == 1 && x + wd + xcount > grid->grid_width)
2461 xcount = grid->grid_width - (x + wd);
2462 else if (xdir == -1 && xcount > x)
2463 xcount = x;
2464
2465 if (ydir == 1 && y + ht + ycount > grid->grid_height)
2466 ycount = grid->grid_height - (y + ht);
2467 else if (ydir == -1 && ycount > y)
2468 ycount = y;
2469
2470 if (xcount == 0 && ycount == 0)
2471 return 0;
2472
2473 /*
2474 * If the selection is the one being shifted, adjust the X and Y
2475 * coordinates and adjust the glyph metrics.
2476 */
2477 if (sel) {
2478 /*
2479 * Determine the actual ink bounds of the selection so the
2480 * glyph metrics can be adjusted if necessary.
2481 */
2482 if (_bdf_grid_ink_bounds(grid, &x, &y, &wd, &ht)) {
2483 /*
2484 * Have to adjust the glyph metrics.
2485 */
2486 x += xdir * xcount;
2487 y += ydir * ycount;
2488 if (x < grid->glyph_x) {
2489 delta = grid->glyph_x - x;
2490 grid->glyph_bbx.width += delta;
2491 grid->glyph_bbx.x_offset -= delta;
2492 if (grid->spacing == BDF_PROPORTIONAL)
2493 grid->dwidth += delta;
2494 grid->glyph_x -= delta;
2495 } else if (x >= grid->glyph_x + grid->glyph_bbx.width) {
2496 delta = x - (grid->glyph_x + grid->glyph_bbx.width);
2497 grid->glyph_bbx.width += delta;
2498 if (grid->spacing == BDF_PROPORTIONAL)
2499 grid->dwidth += delta;
2500 }
2501
2502 if (y < grid->glyph_y) {
2503 delta = grid->glyph_y - y;
2504 grid->glyph_bbx.height += delta;
2505 grid->glyph_bbx.ascent += delta;
2506 grid->glyph_y -= delta;
2507 } else if (y + ht >= grid->glyph_y + grid->glyph_bbx.height) {
2508 delta = (y + ht) - (grid->glyph_y + grid->glyph_bbx.height);
2509 grid->glyph_bbx.height += delta;
2510 grid->glyph_bbx.y_offset -= delta;
2511 grid->glyph_bbx.descent += delta;
2512 }
2513
2514 grid->modified = 1;
2515 }
2516
2517 /*
2518 * Adjust the top-left coordinate of the selection rectangle.
2519 */
2520 grid->sel.x += xdir * xcount;
2521 grid->sel.y += ydir * ycount;
2522
2523 return 1;
2524 }
2525
2526 masks = 0;
2527 switch (grid->bpp) {
2528 case 1: masks = bdf_onebpp; di = 7; break;
2529 case 2: masks = bdf_twobpp; di = 3; break;
2530 case 4: masks = bdf_fourbpp; di = 1; break;
2531 case 8: masks = bdf_eightbpp; di = 0; break;
2532 }
2533
2534 /*
2535 * The glyph itself is being shifted.
2536 */
2537 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2538 bytes = grid->bytes >> 1;
2539 scratch = grid->bitmap + bytes;
2540 (void) memset((char *) scratch, 0, bytes);
2541
2542 /*
2543 * Shift just the glyph rectangle to keep things fast.
2544 */
2545 wd += x;
2546 ht += y;
2547 for (dy = y; dy < ht; dy++) {
2548 col = x * grid->bpp;
2549 for (dx = x; dx < wd; dx++, col += grid->bpp) {
2550 si = (col & 7) / grid->bpp;
2551 byte = grid->bitmap[(dy * bpr) + (col >> 3)] & masks[si];
2552 if (byte) {
2553 nx = dx + (xdir * xcount);
2554 ny = dy + (ydir * ycount);
2555 nx *= grid->bpp;
2556 di = (nx & 7) / grid->bpp;
2557 if (di < si)
2558 byte <<= (si - di) * grid->bpp;
2559 else if (di > si)
2560 byte >>= (di - si) * grid->bpp;
2561 scratch[(ny * bpr) + (nx >> 3)] |= byte;
2562 }
2563 }
2564 }
2565
2566 /*
2567 * Copy the scratch buffer back to the main buffer.
2568 */
2569 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
2570
2571 /*
2572 * Adjust the top-left coordinate of the glyph rectangle.
2573 */
2574 grid->glyph_x += xdir * xcount;
2575 grid->glyph_y += ydir * ycount;
2576
2577 /*
2578 * Adjust the glyph offsets relative to the baseline coordinates.
2579 */
2580 grid->glyph_bbx.x_offset = grid->glyph_x - grid->base_x;
2581 grid->glyph_bbx.y_offset = grid->base_y -
2582 (grid->glyph_y + grid->glyph_bbx.height);
2583
2584 /*
2585 * Adjust the glyph ascent and descent.
2586 */
2587 grid->glyph_bbx.ascent = grid->base_y - grid->glyph_y;
2588 grid->glyph_bbx.descent = (grid->glyph_y + grid->glyph_bbx.height) -
2589 grid->base_y;
2590
2591 /*
2592 * Mark the grid as being modified.
2593 */
2594 grid->modified = 1;
2595
2596 return 1;
2597 }
2598
2599
2600 int
bdf_grid_flip(bdf_glyph_grid_t * grid,short dir)2601 bdf_grid_flip(bdf_glyph_grid_t *grid, short dir)
2602 {
2603 int flipped, sel, delta;
2604 short dx, dy, x, y, nx, ny, wd, ht;
2605 unsigned short bytes, bpr, si, di, col, colx, byte;
2606 unsigned char *bmap, *scratch, *masks;
2607
2608 flipped = 0;
2609
2610 if (grid == 0)
2611 return flipped;
2612
2613 if (grid->sel.width != 0 && grid->sel.height != 0) {
2614 sel = 1;
2615 x = y = 0;
2616 wd = grid->sel.width;
2617 ht = grid->sel.height;
2618 bpr = ((wd * grid->bpp) + 7) >> 3;
2619 bytes = grid->sel.bytes >> 1;
2620 bmap = grid->sel.bitmap;
2621 } else {
2622 sel = 0;
2623 x = grid->glyph_x;
2624 y = grid->glyph_y;
2625 wd = grid->glyph_bbx.width;
2626 ht = grid->glyph_bbx.height;
2627 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2628 bytes = grid->bytes >> 1;
2629 bmap = grid->bitmap;
2630 }
2631
2632 /*
2633 * If the width or height is 0, don't do anything.
2634 */
2635 if (wd == 0|| ht == 0)
2636 return flipped;
2637
2638 nx = 0;
2639 masks = 0;
2640 switch (grid->bpp) {
2641 case 1: masks = bdf_onebpp; di = 7; break;
2642 case 2: masks = bdf_twobpp; di = 3; break;
2643 case 4: masks = bdf_fourbpp; di = 1; break;
2644 case 8: masks = bdf_eightbpp; di = 0; break;
2645 }
2646
2647 /*
2648 * Set and initialize the scratch area.
2649 */
2650 scratch = bmap + bytes;
2651 (void) memset((char *) scratch, 0, bytes);
2652
2653 wd += x;
2654 ht += y;
2655
2656 if (dir < 0) {
2657 /*
2658 * Flip horizontally.
2659 */
2660 for (dy = y; dy < ht; dy++) {
2661 col = x * grid->bpp;
2662 for (nx = wd - 1, dx = x; dx < wd; dx++, nx--, col += grid->bpp) {
2663 si = (col & 7) / grid->bpp;
2664 byte = bmap[(dy * bpr) + (col >> 3)] & masks[si];
2665 if (byte) {
2666 flipped = 1;
2667 colx = nx * grid->bpp;
2668 di = (colx & 7) / grid->bpp;
2669 if (di < si)
2670 byte <<= (si - di) * grid->bpp;
2671 else if (di > si)
2672 byte >>= (di - si) * grid->bpp;
2673 scratch[(dy * bpr) + (colx >> 3)] |= byte;
2674 }
2675 }
2676 }
2677 if (flipped) {
2678 if (sel)
2679 grid->sel.x += nx + 1;
2680 else {
2681 grid->glyph_x = nx + 1;
2682 grid->glyph_bbx.x_offset = grid->glyph_x - grid->base_x;
2683 }
2684 }
2685 } else {
2686 /*
2687 * Flip vertically.
2688 */
2689 for (ny = ht - 1, dy = y; dy < ht; dy++, ny--) {
2690 col = x * grid->bpp;
2691 for (dx = x; dx < wd; dx++, col += grid->bpp) {
2692 si = (col & 7) / grid->bpp;
2693 byte = bmap[(dy * bpr) + (col >> 3)] & masks[si];
2694 if (byte) {
2695 flipped = 1;
2696 scratch[(ny * bpr) + (col >> 3)] |= byte;
2697 }
2698 }
2699 }
2700 if (flipped) {
2701 if (sel)
2702 grid->sel.y += ny + 1;
2703 else {
2704 grid->glyph_y = ny + 1;
2705 grid->glyph_bbx.y_offset = grid->base_y -
2706 (grid->glyph_y + grid->glyph_bbx.height);
2707 grid->glyph_bbx.ascent = grid->base_y - grid->glyph_y;
2708 grid->glyph_bbx.descent =
2709 (grid->glyph_y + grid->glyph_bbx.height) - grid->base_y;
2710 }
2711 }
2712 }
2713
2714 if (flipped) {
2715 /*
2716 * Copy the scratch area back to the working area.
2717 */
2718 if (sel)
2719 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
2720 else
2721 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
2722
2723 if (sel) {
2724 /*
2725 * Check to see if flipping the selection caused the glyph metrics
2726 * to change.
2727 */
2728 if (_bdf_grid_ink_bounds(grid, &x, &y, &wd, &ht)) {
2729 if (x < grid->glyph_x) {
2730 delta = grid->glyph_x - x;
2731 grid->glyph_bbx.width += delta;
2732 grid->glyph_bbx.x_offset -= delta;
2733 grid->glyph_x -= delta;
2734 if (grid->spacing == BDF_PROPORTIONAL)
2735 grid->dwidth += delta;
2736 } else if (x >= grid->glyph_x + grid->glyph_bbx.width) {
2737 delta = x - (grid->glyph_x + grid->glyph_bbx.width);
2738 grid->glyph_bbx.width += delta;
2739 if (grid->spacing == BDF_PROPORTIONAL)
2740 grid->dwidth += delta;
2741 }
2742
2743 if (y < grid->glyph_y) {
2744 delta = grid->glyph_y - y;
2745 grid->glyph_bbx.height += delta;
2746 grid->glyph_bbx.ascent += delta;
2747 grid->glyph_y -= delta;
2748 } else if (y >= grid->glyph_y + grid->glyph_bbx.height) {
2749 delta = y - (grid->glyph_y + grid->glyph_bbx.height);
2750 grid->glyph_bbx.height += delta;
2751 grid->glyph_bbx.y_offset -= delta;
2752 grid->glyph_bbx.descent += delta;
2753 }
2754 }
2755 }
2756
2757 /*
2758 * Mark the grid as being modified.
2759 */
2760 grid->modified = 1;
2761 }
2762
2763 return flipped;
2764 }
2765
2766 void
bdf_grid_origin(bdf_glyph_grid_t * grid,short * x,short * y)2767 bdf_grid_origin(bdf_glyph_grid_t *grid, short *x, short *y)
2768 {
2769 if (grid == 0)
2770 return;
2771
2772 *x = grid->base_x;
2773 *y = grid->base_y;
2774 }
2775
2776 bdf_glyph_t *
bdf_grid_glyph(bdf_glyph_grid_t * grid)2777 bdf_grid_glyph(bdf_glyph_grid_t *grid)
2778 {
2779 int len;
2780 short x, y, nx, ny, wd, ht, gx, gy;
2781 unsigned short bpr, nbpr, si, di, col, byte;
2782 bdf_glyph_t *glyph;
2783 unsigned char *masks;
2784 double ps, dw, rx;
2785
2786 if (grid == 0)
2787 return 0;
2788
2789 masks = 0;
2790 switch (grid->bpp) {
2791 case 1: masks = bdf_onebpp; di = 7; break;
2792 case 2: masks = bdf_twobpp; di = 3; break;
2793 case 4: masks = bdf_fourbpp; di = 1; break;
2794 case 8: masks = bdf_eightbpp; di = 0; break;
2795 }
2796
2797 /*
2798 * Create the new glyph.
2799 */
2800 glyph = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t));
2801 (void) memset((char *) glyph, 0, sizeof(bdf_glyph_t));
2802
2803 gx = grid->glyph_x;
2804 gy = grid->glyph_y;
2805
2806 /*
2807 * Copy the bounding box.
2808 */
2809 (void) memcpy((char *) &glyph->bbx, (char *) &grid->glyph_bbx,
2810 sizeof(bdf_bbx_t));
2811
2812 /*
2813 * If the font has character-cell spacing, then make sure the bitmap is
2814 * cropped to fit within the bounds of the font bbx.
2815 */
2816 if (grid->spacing == BDF_CHARCELL) {
2817 if (gx < grid->base_x) {
2818 glyph->bbx.x_offset = 0;
2819 glyph->bbx.width -= grid->base_x - gx;
2820 gx += grid->base_x - gx;
2821 }
2822 if (glyph->bbx.width > grid->font_bbx.width)
2823 glyph->bbx.width -= glyph->bbx.width - grid->font_bbx.width;
2824 }
2825
2826 /*
2827 * Set up its bitmap.
2828 */
2829 nbpr = ((glyph->bbx.width * grid->bpp) + 7) >> 3;
2830 glyph->bytes = nbpr * glyph->bbx.height;
2831 glyph->bitmap = (unsigned char *) malloc(glyph->bytes);
2832 (void) memset((char *) glyph->bitmap, 0, glyph->bytes);
2833
2834 /*
2835 * Set the other values.
2836 */
2837 if (grid->name != 0) {
2838 len = strlen(grid->name) + 1;
2839 glyph->name = (char *) malloc(len);
2840 (void) memcpy(glyph->name, grid->name, len);
2841 }
2842 glyph->encoding = grid->encoding;
2843 glyph->dwidth = grid->dwidth;
2844
2845 /*
2846 * Reset the glyph SWIDTH value.
2847 */
2848 ps = (double) grid->point_size;
2849 rx = (double) grid->resolution_x;
2850 dw = (double) grid->dwidth;
2851 glyph->swidth = (unsigned short) ((dw * 72000.0) / (ps * rx));
2852
2853 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2854 wd = gx + glyph->bbx.width;
2855 ht = gy + glyph->bbx.height;
2856
2857 /*
2858 * Copy the bitmap from the grid into the glyph.
2859 */
2860 for (ny = 0, y = gy; y < ht; y++, ny++) {
2861 col = gx * grid->bpp;
2862 for (nx = 0, x = gx; x < wd; x++, nx += grid->bpp, col += grid->bpp) {
2863 si = (col & 7) / grid->bpp;
2864 byte = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
2865 if (byte) {
2866 di = (nx & 7) / grid->bpp;
2867 if (di < si)
2868 byte <<= (si - di) * grid->bpp;
2869 else if (di > si)
2870 byte >>= (di - si) * grid->bpp;
2871 glyph->bitmap[(ny * nbpr) + (nx >> 3)] |= byte;
2872 }
2873 }
2874 }
2875
2876 /*
2877 * Return the new glyph.
2878 */
2879 return glyph;
2880 }
2881
2882 /*
2883 * Create a bitmap with the glyph image as well as the selection.
2884 */
2885 void
bdf_grid_image(bdf_glyph_grid_t * grid,bdf_bitmap_t * image)2886 bdf_grid_image(bdf_glyph_grid_t *grid, bdf_bitmap_t *image)
2887 {
2888 short x, y, ix, iy;
2889 unsigned short bpr, ibpr, si, di, col, colx, byte;
2890 unsigned char *masks;
2891
2892 if (grid == 0 || image == 0)
2893 return;
2894
2895 masks = 0;
2896 switch (grid->bpp) {
2897 case 1: masks = bdf_onebpp; di = 7; break;
2898 case 2: masks = bdf_twobpp; di = 3; break;
2899 case 4: masks = bdf_fourbpp; di = 1; break;
2900 case 8: masks = bdf_eightbpp; di = 0; break;
2901 }
2902
2903 image->bpp = grid->bpp;
2904 image->x = image->y = 0;
2905 image->width = grid->grid_width;
2906 image->height = grid->grid_height;
2907 image->bytes = grid->bytes >> 1;
2908 image->bitmap = (unsigned char *) malloc(image->bytes);
2909 (void) memcpy((char *) image->bitmap, (char *) grid->bitmap, image->bytes);
2910
2911 /*
2912 * Add the selection to the bitmap if it exists.
2913 */
2914 if (grid->sel.width != 0 && grid->sel.height != 0) {
2915 ibpr = ((image->width * grid->bpp) + 7) >> 3;
2916 bpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2917 for (iy = grid->sel.y, y = 0; y < grid->sel.height; y++, iy++) {
2918 for (ix = grid->sel.x, col = x = 0; x < grid->sel.width;
2919 x++, ix++, col += grid->bpp) {
2920 si = (col & 7) / grid->bpp;
2921 byte = grid->sel.bitmap[(y * bpr) + (col >> 3)] & masks[si];
2922 if (byte) {
2923 colx = ix * grid->bpp;
2924 di = (colx & 7) / grid->bpp;
2925 if (di < si)
2926 byte <<= (si - di) * grid->bpp;
2927 else if (di > si)
2928 byte >>= (di - si) * grid->bpp;
2929 image->bitmap[(iy * ibpr) + (colx >> 3)] |= byte;
2930 }
2931 }
2932 }
2933 }
2934 }
2935
2936 /*
2937 * These values are intended to give pixels mapped from 1bpp to nbpp the
2938 * darkest available index, which is 1.
2939 */
2940 static unsigned char twobpp_ones[] = {0x40, 0x10, 0x04, 0x01};
2941 static unsigned char fourbpp_ones[] = {0x10, 0x01};
2942 static unsigned char eightbpp_ones[] = {0x01};
2943
2944 /*
2945 * Routines for quick and dirty dithering.
2946 */
2947 static void
_bdf_one_to_n(bdf_bitmap_t * bmap,int n)2948 _bdf_one_to_n(bdf_bitmap_t *bmap, int n)
2949 {
2950 unsigned short bpr, sbpr, bytes, col, sx, sy;
2951 unsigned char *nbmap, *ones = 0;
2952
2953 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
2954 return;
2955
2956 switch (n) {
2957 case 1: ones = bdf_onebpp; break;
2958 case 2: ones = twobpp_ones; break;
2959 case 4: ones = fourbpp_ones; break;
2960 case 8: ones = eightbpp_ones; break;
2961 }
2962
2963 sbpr = (bmap->width + 7) >> 3;
2964 bpr = ((bmap->width * n) + 7) >> 3;
2965 bytes = bpr * bmap->height;
2966 nbmap = (unsigned char *) malloc(bytes);
2967 (void) memset((char *) nbmap, 0, bytes);
2968
2969 for (sy = 0; sy < bmap->height; sy++) {
2970 for (col = sx = 0; sx < bmap->width; sx++, col += n) {
2971 if (bmap->bitmap[(sy * sbpr) + (sx >> 3)] & (0x80 >> (sx & 7)))
2972 nbmap[(sy * bpr) + (col >> 3)] |= ones[(col & 7) / n];
2973 }
2974 }
2975 free((char *) bmap->bitmap);
2976 bmap->bpp = n;
2977 bmap->bytes = bytes;
2978 bmap->bitmap = nbmap;
2979 }
2980
2981 static void
_bdf_n_to_one(bdf_bitmap_t * bmap)2982 _bdf_n_to_one(bdf_bitmap_t *bmap)
2983 {
2984 unsigned short bpr, sbpr, bytes, col, sx, sy;
2985 unsigned char *nbmap, *masks;
2986
2987 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
2988 return;
2989
2990 masks = 0;
2991 switch (bmap->bpp) {
2992 case 1: masks = bdf_onebpp; break;
2993 case 2: masks = bdf_twobpp; break;
2994 case 4: masks = bdf_fourbpp; break;
2995 case 8: masks = bdf_eightbpp; break;
2996 }
2997
2998 sbpr = ((bmap->width * bmap->bpp) + 7) >> 3;
2999 bpr = (bmap->width + 7) >> 3;
3000 bytes = bpr * bmap->height;
3001 nbmap = (unsigned char *) malloc(bytes);
3002 (void) memset((char *) nbmap, 0, bytes);
3003
3004 for (sy = 0; sy < bmap->height; sy++) {
3005 for (col = sx = 0; sx < bmap->width; sx++, col += bmap->bpp) {
3006 if (bmap->bitmap[(sy * sbpr) + (col >> 3)] &
3007 masks[(col & 7) / bmap->bpp])
3008 nbmap[(sy * bpr) + (sx >> 3)] |= (0x80 >> (sx & 7));
3009 }
3010 }
3011 free((char *) bmap->bitmap);
3012 bmap->bpp = 1;
3013 bmap->bytes = bytes;
3014 bmap->bitmap = nbmap;
3015 }
3016
3017 static void
_bdf_two_to_four(bdf_bitmap_t * bmap)3018 _bdf_two_to_four(bdf_bitmap_t *bmap)
3019 {
3020 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3021 unsigned char *nbmap, *masks;
3022
3023 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3024 return;
3025
3026 masks = bdf_twobpp;
3027
3028 sbpr = ((bmap->width << 1) + 7) >> 3;
3029 bpr = ((bmap->width << 2) + 7) >> 3;
3030 bytes = bpr * bmap->height;
3031 nbmap = (unsigned char *) malloc(bytes);
3032 (void) memset((char *) nbmap, 0, bytes);
3033
3034 for (sy = 0; sy < bmap->height; sy++) {
3035 for (col = sx = 0; sx < bmap->width; sx++, col += 2) {
3036 si = (col & 7) >> 1;
3037 byte = bmap->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
3038 if (byte) {
3039 /*
3040 * Shift the byte down to leave the index in the lowest 2
3041 * bits.
3042 */
3043 if (si < 3)
3044 byte >>= (3 - si) << 1;
3045
3046 /*
3047 * Break 16 into 4 groups of 4 and map the 2bpp index to one
3048 * of those 4.
3049 */
3050 bytes <<= 2;
3051 if ((sx & 1) == 0)
3052 byte <<= 4;
3053 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
3054 }
3055 }
3056 }
3057 free((char *) bmap->bitmap);
3058 bmap->bpp = 4;
3059 bmap->bytes = bytes;
3060 bmap->bitmap = nbmap;
3061 }
3062
3063 static void
_bdf_four_to_two(bdf_bitmap_t * bmap)3064 _bdf_four_to_two(bdf_bitmap_t *bmap)
3065 {
3066 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3067 unsigned char *nbmap, *masks;
3068
3069 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3070 return;
3071
3072 masks = bdf_fourbpp;
3073
3074 sbpr = ((bmap->width << 2) + 7) >> 3;
3075 bpr = ((bmap->width << 1) + 7) >> 3;
3076 bytes = bpr * bmap->height;
3077 nbmap = (unsigned char *) malloc(bytes);
3078 (void) memset((char *) nbmap, 0, bytes);
3079
3080 for (sy = 0; sy < bmap->height; sy++) {
3081 for (col = sx = 0; sx < bmap->width; sx++, col += 4) {
3082 si = (col & 7) >> 2;
3083 byte = bmap->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
3084 if (byte) {
3085 /*
3086 * Shift the byte down to make an index.
3087 */
3088 if (si == 0)
3089 byte >>= 4;
3090
3091 /*
3092 * Scale the index to two bits per pixel and shift it into
3093 * place if necessary.
3094 */
3095 byte >>= 2;
3096 if (byte == 0)
3097 byte = 1;
3098
3099 si = ((sx << 1) & 7) >> 1;
3100 if (si < 3)
3101 byte <<= (3 - si) << 1;
3102
3103 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
3104 }
3105 }
3106 }
3107 free((char *) bmap->bitmap);
3108 bmap->bpp = 2;
3109 bmap->bytes = bytes;
3110 bmap->bitmap = nbmap;
3111 }
3112
3113 static void
_bdf_two_to_eight(bdf_bitmap_t * bmap)3114 _bdf_two_to_eight(bdf_bitmap_t *bmap)
3115 {
3116 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3117 unsigned char *nbmap, *masks;
3118
3119 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3120 return;
3121
3122 masks = bdf_twobpp;
3123
3124 sbpr = ((bmap->width << 1) + 7) >> 3;
3125 bpr = bmap->width;
3126 bytes = bpr * bmap->height;
3127 nbmap = (unsigned char *) malloc(bytes);
3128 (void) memset((char *) nbmap, 0, bytes);
3129
3130 for (sy = 0; sy < bmap->height; sy++) {
3131 for (col = sx = 0; sx < bmap->width; sx++, col += 2) {
3132 si = (col & 7) >> 1;
3133 byte = bmap->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
3134 if (byte) {
3135 /*
3136 * Shift the byte down to leave the index in the lowest 2
3137 * bits.
3138 */
3139 if (si < 3)
3140 byte >>= (3 - si) << 1;
3141
3142 /*
3143 * Break 256 into 4 groups of 64 and map the 2bpp index to one
3144 * of those 4.
3145 */
3146 byte <<= 6;
3147 nbmap[(sy * bpr) + sx] = byte;
3148 }
3149 }
3150 }
3151 free((char *) bmap->bitmap);
3152 bmap->bpp = 8;
3153 bmap->bytes = bytes;
3154 bmap->bitmap = nbmap;
3155 }
3156
3157 static void
_bdf_eight_to_two(bdf_bitmap_t * bmap)3158 _bdf_eight_to_two(bdf_bitmap_t *bmap)
3159 {
3160 unsigned short bpr, sbpr, bytes, si, byte, sx, sy;
3161 unsigned char *nbmap;
3162
3163 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3164 return;
3165
3166 sbpr = bmap->width;
3167 bpr = ((bmap->width << 1) + 7) >> 3;
3168 bytes = bpr * bmap->height;
3169 nbmap = (unsigned char *) malloc(bytes);
3170 (void) memset((char *) nbmap, 0, bytes);
3171
3172 for (sy = 0; sy < bmap->height; sy++) {
3173 for (sx = 0; sx < bmap->width; sx++) {
3174 byte = bmap->bitmap[(sy * sbpr) + sx];
3175 if (byte) {
3176 /*
3177 * Scale the index to two bits per pixel and shift it into
3178 * place if necessary.
3179 */
3180 byte >>= 6;
3181 if (byte == 0)
3182 byte = 1;
3183
3184 si = ((sx << 1) & 7) >> 1;
3185 if (si < 3)
3186 byte <<= (3 - si) << 1;
3187
3188 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
3189 }
3190 }
3191 }
3192 free((char *) bmap->bitmap);
3193 bmap->bpp = 2;
3194 bmap->bytes = bytes;
3195 bmap->bitmap = nbmap;
3196 }
3197
3198 static void
_bdf_four_to_eight(bdf_bitmap_t * bmap)3199 _bdf_four_to_eight(bdf_bitmap_t *bmap)
3200 {
3201 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3202 unsigned char *nbmap, *masks;
3203
3204 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3205 return;
3206
3207 masks = bdf_fourbpp;
3208
3209 sbpr = ((bmap->width << 2) + 7) >> 3;
3210 bpr = bmap->width;
3211 bytes = bpr * bmap->height;
3212 nbmap = (unsigned char *) malloc(bytes);
3213 (void) memset((char *) nbmap, 0, bytes);
3214
3215 for (sy = 0; sy < bmap->height; sy++) {
3216 for (col = sx = 0; sx < bmap->width; sx++, col += 4) {
3217 si = (col & 7) >> 2;
3218 byte = bmap->bitmap[(sy * sbpr) + (col >> 3)] & masks[si];
3219 if (byte) {
3220 /*
3221 * Shift the byte down to make an index.
3222 */
3223 if (si == 0)
3224 byte >>= 4;
3225
3226 /*
3227 * Multiply by 16 to get the 8bpp index.
3228 */
3229 byte <<= 4;
3230
3231 nbmap[(sy * bpr) + sx] = byte;
3232 }
3233 }
3234 }
3235 free((char *) bmap->bitmap);
3236 bmap->bpp = 8;
3237 bmap->bytes = bytes;
3238 bmap->bitmap = nbmap;
3239 }
3240
3241 static void
_bdf_eight_to_four(bdf_bitmap_t * bmap)3242 _bdf_eight_to_four(bdf_bitmap_t *bmap)
3243 {
3244 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3245 unsigned char *nbmap;
3246
3247 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3248 return;
3249
3250 sbpr = bmap->width;
3251 bpr = ((bmap->width << 2) + 7) >> 3;
3252 bytes = bpr * bmap->height;
3253 nbmap = (unsigned char *) malloc(bytes);
3254 (void) memset((char *) nbmap, 0, bytes);
3255
3256 for (sy = 0; sy < bmap->height; sy++) {
3257 for (col = sx = 0; sx < bmap->width; sx++, col += 4) {
3258 byte = bmap->bitmap[(sy * sbpr) + sx];
3259 if (byte) {
3260 /*
3261 * Divide the index by 16 to determine which 4bpp index
3262 * it will be.
3263 */
3264 byte >>= 4;
3265 if (byte == 0)
3266 byte = 1;
3267
3268 /*
3269 * Shift the bits up by 4 if the index is even.
3270 */
3271 si = (col & 7) >> 2;
3272 if (si == 0)
3273 byte <<= 4;
3274
3275 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
3276 }
3277 }
3278 }
3279 free((char *) bmap->bitmap);
3280 bmap->bpp = 4;
3281 bmap->bytes = bytes;
3282 bmap->bitmap = nbmap;
3283 }
3284
3285 /*
3286 * Add a bitmap to a grid as a selection.
3287 */
3288 void
bdf_add_selection(bdf_glyph_grid_t * grid,bdf_bitmap_t * sel)3289 bdf_add_selection(bdf_glyph_grid_t *grid, bdf_bitmap_t *sel)
3290 {
3291 unsigned short bytes, bpr;
3292
3293 if (grid == 0 || sel == 0 || sel->width == 0 || sel->height == 0 ||
3294 sel->bytes == 0)
3295 return;
3296
3297 if (sel->bpp != grid->bpp) {
3298 /*
3299 * Dither the incoming bitmap to match the same bits per pixel as the
3300 * grid it is being added to.
3301 */
3302 if (sel->bpp == 1)
3303 _bdf_one_to_n(sel, grid->bpp);
3304 else if (grid->bpp == 1)
3305 _bdf_n_to_one(sel);
3306 else if (sel->bpp == 2) {
3307 if (grid->bpp == 4)
3308 _bdf_two_to_four(sel);
3309 else
3310 _bdf_two_to_eight(sel);
3311 } else if (sel->bpp == 4) {
3312 if (grid->bpp == 2)
3313 _bdf_four_to_two(sel);
3314 else
3315 _bdf_four_to_eight(sel);
3316 } else if (sel->bpp == 8) {
3317 if (grid->bpp == 2)
3318 _bdf_eight_to_two(sel);
3319 else
3320 _bdf_eight_to_four(sel);
3321 }
3322 }
3323
3324 /*
3325 * If the bitmap is too big then trim the right and/or the bottom to fit
3326 * in the grid.
3327 */
3328 if (sel->width > grid->grid_width)
3329 sel->width = grid->grid_width;
3330 if (sel->height > grid->grid_height)
3331 sel->height = grid->grid_height;
3332
3333 /*
3334 * If the positioning puts the selection bitmap off one of the edges,
3335 * adjust it so it is completely on the grid.
3336 */
3337 if (sel->x + sel->width > grid->grid_width)
3338 sel->x -= (sel->x + sel->width) - grid->grid_width;
3339 if (sel->y + sel->height > grid->grid_height)
3340 sel->y -= (sel->y + sel->height) - grid->grid_height;
3341
3342 bpr = ((sel->width * grid->bpp) + 7) >> 3;
3343 bytes = (bpr * sel->height) << 1;
3344
3345 /*
3346 * Resize the storage for the selection bitmap if necessary.
3347 */
3348 if (bytes > grid->sel.bytes) {
3349 if (grid->sel.bytes == 0)
3350 grid->sel.bitmap = (unsigned char *) malloc(bytes);
3351 else
3352 grid->sel.bitmap = (unsigned char *)
3353 realloc((char *) grid->sel.bitmap, bytes);
3354 grid->sel.bytes = bytes;
3355 }
3356
3357 /*
3358 * Copy the width and height values.
3359 */
3360 grid->sel.x = sel->x;
3361 grid->sel.y = sel->y;
3362 grid->sel.width = sel->width;
3363 grid->sel.height = sel->height;
3364
3365 /*
3366 * Copy the incoming bitmap to the new selection bitmap.
3367 */
3368 (void) memcpy((char *) grid->sel.bitmap, (char *) sel->bitmap,
3369 bytes >> 1);
3370
3371 /*
3372 * Crop the image to adjust the glyph bounding box.
3373 */
3374 (void) bdf_grid_crop(grid, 1);
3375 }
3376
3377 int
bdf_grid_color_at(bdf_glyph_grid_t * grid,short x,short y)3378 bdf_grid_color_at(bdf_glyph_grid_t *grid, short x, short y)
3379 {
3380 unsigned short bpr, si, di, byte;
3381 unsigned char *masks = 0;
3382
3383 if (grid->bpp == 1)
3384 return -1;
3385
3386 di = 0;
3387 switch (grid->bpp) {
3388 case 2: masks = bdf_twobpp; di = 3; break;
3389 case 4: masks = bdf_fourbpp; di = 1; break;
3390 case 8: masks = bdf_eightbpp; di = 0; break;
3391 }
3392
3393 x *= grid->bpp;
3394
3395 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
3396 si = (x & 7) / grid->bpp;
3397
3398 byte = grid->bitmap[(y * bpr) + (x >> 3)] & masks[si];
3399 if (di > si)
3400 byte >>= (di - si) * grid->bpp;
3401 return (int) byte;
3402 }
3403