2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #define MYABS(n) ((n) < 0 ? -(n) : (n))
30 #define MAX(h, i) ((h) > (i) ? (h) : (i))
33 #define MIN(l, o) ((l) < (o) ? (l) : (o))
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,
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,
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,
180 * Determine the actual ink bounds.
183 _bdf_grid_ink_bounds(bdf_glyph_grid_t *grid, short *x, short *y,
184 short *width, short *height)
186 short bx, by, bwd, bht, minx, maxx, miny, maxy, dx, dy;
187 unsigned short bpr, ink, sel, col;
188 unsigned char *bmap, *masks;
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;
198 if (grid->sel.width != 0 && grid->sel.height != 0) {
201 bwd = grid->sel.width;
202 bht = grid->sel.height;
203 bmap = grid->sel.bitmap;
208 bwd = grid->glyph_bbx.width;
209 bht = grid->glyph_bbx.height;
216 bpr = ((bwd * grid->bpp) + 7) >> 3;
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]) {
225 minx = MIN(minx, dx);
226 miny = MIN(miny, dy);
227 maxx = MAX(maxx, dx);
228 maxy = MAX(maxy, dy);
233 *x = minx + ((sel) ? grid->sel.x : 0);
234 *y = miny + ((sel) ? grid->sel.y : 0);
236 *width = *height = 0;
238 *width = (maxx - minx) + 1;
239 *height = (maxy - miny) + 1;
244 /**************************************************************************
246 * Glyph grid create and destroy functions.
248 **************************************************************************/
251 * Make a glyph grid with the glyph bitmap set in the bitmap.
254 bdf_make_glyph_grid(bdf_font_t *font, int code, int unencoded)
256 unsigned short si, di, col, colx, byte;
257 short ht, as, ds, gsize, bpr, x, y, nx, ny;
259 bdf_glyph_grid_t *gr;
260 bdf_glyph_t *gl, *glp;
262 unsigned char *masks;
271 * Allocate the grid and initialize it.
273 gr = (bdf_glyph_grid_t *) malloc(sizeof(bdf_glyph_grid_t));
274 (void) memset((char *) gr, 0, sizeof(bdf_glyph_grid_t));
277 * Set the encoding and the unencoded flag.
279 gr->bpp = (font) ? font->bpp : 1;
281 gr->unencoded = unencoded;
284 * Set the glyph grid spacing.
286 gr->spacing = (font) ? font->spacing : BDF_CHARCELL;
289 * Set the point size and resolutions.
292 gr->point_size = font->point_size;
293 gr->resolution_x = font->resolution_x;
294 gr->resolution_y = font->resolution_y;
297 gr->resolution_x = gr->resolution_y = 100;
301 * Set the CAP_HEIGHT and X_HEIGHT if they exist in the 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;
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;
319 * Copy the font bounding box into the grid.
322 (void) memcpy((char *) &gr->font_bbx, (char *) &font->bbx,
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;
335 gl = font->unencoded;
336 r = font->unencoded_used;
339 r = font->glyphs_used;
347 * Locate the specified glyph using a simple binary search.
351 for (l = 0; r >= l; ) {
354 if (glp->encoding == code)
356 if (glp->encoding > code)
358 else if (glp->encoding < code)
364 ht = gr->font_bbx.height;
365 as = gr->font_bbx.ascent;
366 ds = gr->font_bbx.descent;
369 * 1. Determine width and height needed from the largest of the
372 gr->grid_width = gr->grid_height =
373 MAX(gr->font_bbx.width, gr->font_bbx.height);
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.
381 * Set the glyph name and other metrics.
384 gr->name = (char *) malloc(strlen(glp->name) + 1);
385 (void) memcpy(gr->name, glp->name, strlen(glp->name) + 1);
387 sprintf(name, "char%d", code);
388 gr->name = (char *) malloc(strlen(name) + 1);
389 (void) memcpy(gr->name, name, strlen(name) + 1);
391 gr->dwidth = glp->dwidth;
394 * Copy the glyph bounding box into the grid.
396 (void) memcpy((char *) &gr->glyph_bbx, (char *) &glp->bbx,
399 if (glp->bbx.height < glp->bbx.ascent + glp->bbx.descent)
400 gsize = glp->bbx.ascent + glp->bbx.descent;
402 gsize = glp->bbx.height;
405 * Figure the maximum of the glyph width and height.
407 gsize = MAX(gr->glyph_bbx.width, gsize);
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.
413 gr->grid_width = MAX(gr->grid_width, gsize);
414 gr->grid_height = MAX(gr->grid_height, gsize);
417 * The glyph doesn't exist, so make up a name for it.
420 sprintf(name, "unencoded%d", code);
422 sprintf(name, "char%d", code);
423 gr->name = (char *) malloc(strlen(name) + 1);
424 (void) memcpy(gr->name, name, strlen(name) + 1);
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.
431 if (gr->spacing != BDF_PROPORTIONAL)
432 gr->dwidth = (font) ? font->monowidth : 8;
435 * Determine the vertical origin based on the font bounding box.
438 gr->base_y = (((gr->grid_height >> 1) - (ht >> 1)) + ht) - ds;
440 gr->base_y = ((gr->grid_height >> 1) - ((as + ds) >> 1)) + as;
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.
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);
454 * Determine the horizontal origin based on the font bounding box and
455 * centered within the grid.
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);
462 * Allocate double the storage needed for the grid bitmap. The extra
463 * storage will be used for transformations.
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);
471 * Initialize the top-left coordinates of the glyph to the baseline
474 gr->glyph_x = gr->base_x;
475 gr->glyph_y = gr->base_y;
478 * If the glyph was not found, simply return the empty grid.
484 * Determine the top-left coordinates of the glyph with respect to the
485 * baseline coordinates.
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;
491 * Now copy the glyph bitmap to the appropriate location in the grid.
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];
501 di = (colx & 7) / gr->bpp;
503 byte <<= (si - di) * gr->bpp;
505 byte >>= (di - si) * gr->bpp;
506 gr->bitmap[(ny * gsize) + (colx >> 3)] |= byte;
512 * Always crop the glyph to the ink bounds before editing.
514 bdf_grid_crop(gr, 0);
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.
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);
535 bdf_free_glyph_grid(bdf_glyph_grid_t *grid)
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);
551 /**************************************************************************
553 * Glyph grid resize functions.
555 **************************************************************************/
558 * Enlarge the grid without affecting the font or glyph metrics.
561 bdf_grid_enlarge(bdf_glyph_grid_t *grid, unsigned short width,
562 unsigned short height)
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;
569 if (grid == 0 || (width < grid->grid_width && height < grid->grid_height))
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;
581 as = grid->font_bbx.ascent;
582 ds = grid->font_bbx.descent;
584 gwd = MAX(width, grid->grid_width);
585 ght = MAX(height, grid->grid_height);
586 gsize = MAX(gwd, ght);
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);
594 * Determine the new baseline.
597 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
599 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
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);
605 nx = grid->base_x + grid->glyph_bbx.x_offset;
606 ny = grid->base_y - grid->glyph_bbx.ascent;
609 * Now copy the bitmap into the new storage base on the new metrics
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];
623 di = (colx & 7) / grid->bpp;
625 byte <<= (si - di) * grid->bpp;
627 byte >>= (di - si) * grid->bpp;
628 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
634 * Adjust the glyph coordinates.
636 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
637 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
640 * Get rid of the old grid bitmap and replace it with the new one.
642 free((char *) grid->bitmap);
644 grid->bitmap = bitmap;
647 * Update the new grid width and height.
649 grid->grid_width = grid->grid_height = gsize;
652 * Always mark the grid as being modified on a resize.
660 * Change the font bounding box values and resize the grid bitmap if
664 bdf_grid_resize(bdf_glyph_grid_t *grid, bdf_metrics_t *metrics)
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;
674 if (grid == 0 || metrics == 0)
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;
686 * Create new grid bitmaps in preparation for the various metrics changing.
688 if (metrics->width > grid->grid_width ||
689 metrics->height > grid->grid_height) {
692 ht = metrics->height;
693 as = metrics->ascent;
694 ds = metrics->descent;
696 gwd = MAX(metrics->width, grid->grid_width);
697 ght = MAX(metrics->height, grid->grid_height);
700 * Get the larger of the two dimensions.
702 gsize = MAX(gwd, ght);
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);
710 * Determine the new baseline.
713 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
715 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
717 grid->base_x = (gwd >> 1) - (metrics->width >> 1);
718 if (metrics->x_offset < 0)
719 grid->base_x += MYABS(metrics->x_offset);
721 nx = grid->base_x + grid->glyph_bbx.x_offset;
722 ny = grid->base_y - grid->glyph_bbx.ascent;
725 * Now copy the bitmap into the new storage base on the new metrics
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];
739 di = (colx & 7) / grid->bpp;
741 byte <<= (si - di) * grid->bpp;
743 byte >>= (di - si) * grid->bpp;
744 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
750 * Adjust the glyph coordinates.
752 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
753 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
756 * Get rid of the old grid bitmap and replace it with the new one.
758 free((char *) grid->bitmap);
760 grid->bitmap = bitmap;
763 * Update the new grid width and height.
765 grid->grid_width = grid->grid_height = gsize;
768 * Copy the metrics info into the font bounding box.
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;
778 * The grid does not need to resized, but the baseline must
779 * be recalculated and the bitmap copied again.
781 bytes = grid->bytes >> 1;
782 bitmap = grid->bitmap + bytes;
783 (void) memset((char *) bitmap, 0, bytes);
785 ht = metrics->height;
786 as = metrics->ascent;
787 ds = metrics->descent;
789 gwd = grid->grid_width;
790 ght = grid->grid_height;
793 * Determine the new baseline.
796 grid->base_y = (((ght >> 1) - (ht >> 1)) + ht) - ds;
798 grid->base_y = ((ght >> 1) - ((as + ds) >> 1)) + as;
800 grid->base_x = (gwd >> 1) - (metrics->width >> 1);
801 if (metrics->x_offset < 0)
802 grid->base_x += MYABS(metrics->x_offset);
804 nx = grid->base_x + grid->glyph_bbx.x_offset;
805 ny = grid->base_y - grid->glyph_bbx.ascent;
807 wd = grid->glyph_x + grid->glyph_bbx.width;
808 ht = grid->glyph_y + grid->glyph_bbx.height;
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];
819 di = (colx & 7) / grid->bpp;
821 byte <<= (si - di) * grid->bpp;
823 byte >>= (di - si) * grid->bpp;
824 bitmap[(ny * nbpr) + (colx >> 3)] |= byte;
830 * Copy the adjusted bitmap back into the main area.
832 (void) memcpy((char *) grid->bitmap, (char *) bitmap, bytes);
835 * Adjust the glyph coordinates.
837 grid->glyph_x = grid->base_x + grid->glyph_bbx.x_offset;
838 grid->glyph_y = grid->base_y - grid->glyph_bbx.ascent;
841 * Copy the metrics info into the font bounding box.
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;
852 * If the font is not proportional, make sure the device width is adjusted
853 * to meet the new font bounding box.
855 if (changed && grid->spacing != BDF_PROPORTIONAL)
856 grid->dwidth = grid->font_bbx.width;
859 * Always mark the grid as being modified on a resize.
867 bdf_grid_crop(bdf_glyph_grid_t *grid, int grid_modified)
870 short x, y, delta, maxx, minx, maxy, miny, col;
872 unsigned char *masks;
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;
886 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
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]) {
903 * Handle an empty bitmap as a special case.
907 * If the glyph bounding box indicated something was there originally,
908 * then indicate that it was cropped.
910 if (grid->glyph_bbx.width != 0 || grid->glyph_bbx.height != 0)
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)
921 * Increment the max points so width and height calculations won't go
927 if (minx != grid->glyph_x) {
929 delta = minx - grid->glyph_x;
930 grid->glyph_x += delta;
931 grid->glyph_bbx.x_offset += delta;
933 if (maxx - minx != grid->glyph_bbx.width) {
935 delta = (maxx - minx) - grid->glyph_bbx.width;
936 grid->glyph_bbx.width += delta;
939 if (miny != grid->glyph_y) {
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));
946 if (maxy - miny != grid->glyph_bbx.height) {
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;
958 * Indicate that the grid was modified if the glyph had to be cropped.
960 if (cropped && grid_modified)
966 /**************************************************************************
968 * Glyph grid pixel functions.
970 **************************************************************************/
973 bdf_grid_set_pixel(bdf_glyph_grid_t *grid, short x, short y, int val)
975 unsigned short si, di, dx;
977 unsigned char *masks;
981 if (grid == 0 || x < 0 || x >= grid->grid_width ||
982 y < 0 || y >= grid->grid_height)
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;
995 * Remove any unused bits from the value.
1000 di = (dx & 7) / grid->bpp;
1003 * Shift up the value to the appropriate place if necessary.
1006 val <<= (si - di) * grid->bpp;
1009 * Determine the bytes-per-row.
1011 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1014 * If the pixel is already set, simply return with an indication that
1017 if ((grid->bitmap[(y * bpr) + (dx >> 3)] & masks[di]) == val)
1026 * Clear the bits that will take the new value.
1028 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
1029 grid->bitmap[(y * bpr) + (dx >> 3)] |= val;
1032 * Adjust the glyph bounding box.
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;
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;
1060 * Indicate that the glyph was modified.
1068 bdf_grid_clear_pixel(bdf_glyph_grid_t *grid, short x, short y)
1071 short delta, maxx, minx, maxy, miny, wd, ht;
1072 unsigned short di, dx;
1073 unsigned char *masks;
1077 if (grid == 0 || x < 0 || x >= grid->grid_width ||
1078 y < 0 || y >= grid->grid_height)
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;
1090 * Determine the bytes-per-row.
1092 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1095 di = (dx & 7) / grid->bpp;
1098 * If the bit is already clear, simply return with an indication that
1101 if (!(grid->bitmap[(y * bpr) + (dx >> 3)] & masks[di]))
1108 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
1111 * Determine the new min and max values.
1114 minx = miny = 32767;
1116 wd = grid->glyph_x + grid->glyph_bbx.width;
1117 ht = grid->glyph_y + grid->glyph_bbx.height;
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);
1133 * If this call clears the last bit in the image, set the glyph origin
1134 * to the base and return.
1137 grid->glyph_x = grid->base_x;
1138 grid->glyph_y = grid->base_y;
1139 if (grid->spacing == BDF_PROPORTIONAL)
1141 (void) memset((char *) &grid->glyph_bbx, 0, sizeof(grid->glyph_bbx));
1147 * Figure out the left and right bearing changes.
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;
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;
1176 * Indicate that the glyph was modified.
1184 bdf_grid_invert_pixel(bdf_glyph_grid_t *grid, short x, short y, int val)
1187 unsigned char *masks;
1189 if (grid == 0 || x < 0 || x >= grid->grid_width ||
1190 y < 0 || y >= grid->grid_height)
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;
1202 * Determine the bytes-per-row and mask index.
1204 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1205 di = ((x * grid->bpp) & 7) / grid->bpp;
1208 * If the bit is set, then clear it, otherwise, set it.
1210 if (grid->bitmap[(y * bpr) + ((x * grid->bpp) >> 3)] & masks[di])
1211 return bdf_grid_clear_pixel(grid, x, y);
1213 return bdf_grid_set_pixel(grid, x, y, val);
1216 /**************************************************************************
1218 * Glyph grid bitmap transformation functions.
1220 **************************************************************************/
1223 _bdf_ceiling(double v)
1242 return (!neg) ? val : -val;
1246 _bdf_rotate_selection(bdf_glyph_grid_t *grid, int mul90, short degrees)
1249 short wd, ht, nx, ny, cx, cy, x, y, col;
1250 short ox, oy, shiftx, shifty, si, di;
1252 unsigned short bytes, bpr;
1253 unsigned char *scratch, *masks;
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).
1261 if (grid == 0 || degrees == 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;
1272 bytes = grid->sel.bytes >> 1;
1273 scratch = grid->sel.bitmap + bytes;
1274 (void) memset((char *) scratch, 0, bytes);
1276 cx = grid->sel.width >> 1;
1277 cy = grid->sel.height >> 1;
1279 wd = ht = MAX(grid->sel.width, grid->sel.height);
1282 bpr = ((wd * grid->bpp) + 7) >> 3;
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);
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]));
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]));
1301 * Wrap the coordinates around the edges if necessary.
1304 shiftx = MIN(shiftx, nx);
1306 } else if (nx >= wd) {
1308 shiftx = MAX(shiftx, ox);
1312 shifty = MIN(shifty, ny);
1314 } else if (ny >= ht) {
1316 shifty = MAX(shifty, oy);
1320 si = (col & 7) / grid->bpp;
1321 byte = grid->sel.bitmap[(y * bpr) + (col >> 3)] & masks[si];
1325 di = (nx & 7) / grid->bpp;
1327 byte <<= (si - di) * grid->bpp;
1329 byte >>= (di - si) * grid->bpp;
1330 scratch[(ny * bpr) + (nx >> 3)] |= byte;
1337 * If a shift is required, then shift the scratch area back into
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];
1360 di = (nx & 7) / grid->bpp;
1362 byte <<= (si - di) * grid->bpp;
1364 byte >>= (di - si) * grid->bpp;
1365 grid->sel.bitmap[(ny * bpr) + (nx >> 3)] |= byte;
1371 * Copy the scratch buffer back to the main buffer.
1373 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
1376 * Determine the new selection width and height.
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]) {
1393 * Recalculate the center corrdinates so the selection will be
1394 * positioned nicely once it is shifted to the upper left corner.
1396 cx = grid->sel.width >> 1;
1397 cy = grid->sel.height >> 1;
1400 * Set the new width and height.
1402 grid->sel.width = (ox - nx) + 1;
1403 grid->sel.height = (oy - ny) + 1;
1406 * Shift again to force the selection to the upper left corner.
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)] &
1417 ox = (x - nx) * grid->bpp;
1418 di = (ox & 7) / grid->bpp;
1420 byte <<= (si - di) * grid->bpp;
1422 byte >>= (di - si) * grid->bpp;
1423 scratch[(oy * bpr) + (ox >> 3)] |= byte;
1427 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
1431 * Determine the new top left coordinates from the center coordinates.
1433 grid->sel.x = (grid->sel.x + cx) - (grid->sel.width >> 1);
1434 grid->sel.y = (grid->sel.y + cy) - (grid->sel.height >> 1);
1437 * If the rotation caused the selection rectangle to overlap the edges
1438 * of the grid, shift it so it is completely visible again.
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;
1446 * Mark the grid as being modified.
1455 _bdf_rotate_resize(bdf_glyph_grid_t *grid, int mul90, short degrees,
1458 unsigned short wd, ht;
1459 short cx, cy, x1, y1, x2, y2;
1460 double dx1, dy1, dx2, dy2;
1461 bdf_metrics_t metrics;
1464 (void) memset((char *) &metrics, 0, sizeof(bdf_metrics_t));
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;
1473 cx = grid->glyph_x + (grid->glyph_bbx.width >> 1);
1474 cy = grid->glyph_y + (grid->glyph_bbx.height >> 1);
1477 * Rotate the lower left and upper right corners and check for a potential
1481 y1 = grid->glyph_y + grid->glyph_bbx.height;
1482 x2 = grid->glyph_x + grid->glyph_bbx.width;
1485 dx1 = (double) (x1 - cx);
1486 dy1 = (double) (y1 - cy);
1487 dx2 = (double) (x2 - cx);
1488 dy2 = (double) (y2 - cx);
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]));
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]));
1510 wd = MYABS(x2 - x1);
1511 ht = MYABS(y2 - y1);
1512 if (wd > metrics.width) {
1513 metrics.width += wd - grid->font_bbx.width;
1516 if (ht > metrics.height) {
1517 metrics.ascent += ht - grid->font_bbx.height;
1518 metrics.height += ht - grid->font_bbx.height;
1523 * Rotate the upper left and lower right corners and check for a potential
1528 x2 = grid->glyph_x + grid->glyph_bbx.width;
1529 y2 = grid->glyph_y + grid->glyph_bbx.height;
1531 dx1 = (double) (x1 - cx);
1532 dy1 = (double) (y1 - cy);
1533 dx2 = (double) (x2 - cx);
1534 dy2 = (double) (y2 - cx);
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]));
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]));
1556 wd = MYABS(x2 - x1);
1557 ht = MYABS(y2 - y1);
1558 if (wd > metrics.width) {
1559 metrics.width += wd - grid->font_bbx.width;
1562 if (ht > metrics.height) {
1563 metrics.ascent += ht - grid->font_bbx.height;
1564 metrics.height += ht - grid->font_bbx.height;
1569 (void) bdf_grid_resize(grid, &metrics);
1573 _bdf_shear_resize(bdf_glyph_grid_t *grid, short degrees, int neg, int *resize)
1576 short x1, y1, x2, y2;
1577 bdf_metrics_t metrics;
1580 (void) memset((char *) &metrics, 0, sizeof(bdf_metrics_t));
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;
1590 * Shear the lower left and upper right corners and check for a potential
1594 y1 = grid->glyph_bbx.height;
1595 x2 = grid->glyph_bbx.width;
1599 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
1600 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
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]);
1608 wd = MYABS(x2 - x1);
1609 if (wd > metrics.width) {
1610 metrics.width += wd - grid->font_bbx.width;
1615 * Shear the upper left and lower right corners and check for a potential
1620 x2 = grid->glyph_bbx.width;
1621 y2 = grid->glyph_bbx.height;
1624 x1 += (short) ((double) y1 * _bdf_tan_tbl[degrees]);
1625 x2 += (short) ((double) y2 * _bdf_tan_tbl[degrees]);
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]);
1633 wd = MYABS(x2 - x1);
1634 if (wd > metrics.width) {
1635 metrics.width += wd - grid->font_bbx.width;
1640 (void) bdf_grid_resize(grid, &metrics);
1644 * Rotate the bitmap in the grid by some number of degrees.
1647 bdf_grid_rotate(bdf_glyph_grid_t *grid, short degrees, int *resize)
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;
1654 unsigned short bytes, bpr;
1655 unsigned char *scratch, *masks;
1660 * Make sure the number of degrees is between 0 and 359 and adjusted to a
1661 * positive number of degrees if necessary.
1665 while (degrees >= 360)
1668 if (grid == 0 || degrees == 0 ||
1669 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 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;
1680 mul90 = ((degrees % 90) == 0) ? 1 : 0;
1683 * Force the grid to resize if the rotation requires it.
1685 _bdf_rotate_resize(grid, mul90, degrees, resize);
1687 if (grid->sel.width != 0 && grid->sel.height != 0)
1688 return _bdf_rotate_selection(grid, mul90, degrees);
1691 * Halve the byte count in the grid for later use.
1693 bytes = grid->bytes >> 1;
1696 * Point at the scratch buffer area and initialize it.
1698 scratch = grid->bitmap + bytes;
1699 (void) memset((char *) scratch, 0, bytes);
1702 * Determine the bytes per row.
1704 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1707 * Determine the center coordinates of the glyph bitmap rectangle.
1709 cx = grid->glyph_x + (grid->glyph_bbx.width >> 1);
1710 cy = grid->glyph_y + (grid->glyph_bbx.height >> 1);
1713 * Only run over the rectangle containing the glyph itself.
1718 wd = gx + grid->glyph_bbx.width;
1719 ht = gy + grid->glyph_bbx.height;
1722 * Initialize the adjustment counts used if the bitmap
1723 * wraps around the edge.
1725 shiftx = shifty = 0;
1727 for (y = gy; y < ht; y++) {
1728 col = gx * grid->bpp;
1729 for (x = gx; x < wd; x++, col += grid->bpp) {
1734 dx = (double) (x - cx);
1735 dy = (double) (y - cy);
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]));
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]));
1749 * Wrap the coordinates around the edges if necessary.
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;
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;
1768 si = (col & 7) / grid->bpp;
1769 byte = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
1773 di = (nx & 7) / grid->bpp;
1775 byte <<= (si - di) * grid->bpp;
1777 byte >>= (di - si) * grid->bpp;
1778 scratch[(ny * bpr) + (nx >> 3)] |= byte;
1785 * If a shift is required, then shift the scratch area back into
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];
1800 nx += grid->grid_width;
1801 else if (nx >= grid->grid_width)
1802 nx -= grid->grid_width;
1804 ny += grid->grid_height;
1805 else if (ny >= grid->grid_height)
1806 ny -= grid->grid_height;
1809 di = (nx & 7) / grid->bpp;
1811 byte <<= (si - di) * grid->bpp;
1813 byte >>= (di - si) * grid->bpp;
1814 grid->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
1820 * Copy the scratch buffer back to the main buffer.
1822 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
1825 * Determine the new glyph bounding box and the top left coordinates.
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]) {
1842 * Set the new top left corrdinates.
1848 * Set the new glyph bounding box.
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;
1859 * Mark the grid as being modified.
1868 bdf_grid_shear(bdf_glyph_grid_t *grid, short degrees, int *resize)
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;
1878 if (degrees == 0 || degrees < -45 || degrees > 45 || grid == 0 ||
1879 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 0))
1882 if ((neg = (degrees < 0)))
1886 * Check to see if the grid needs to be resized to hold the sheared glyph.
1888 _bdf_shear_resize(grid, degrees, neg, resize);
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;
1899 * Halve the byte count in the grid for later use.
1901 bytes = grid->bytes >> 1;
1904 * Point at the scratch buffer area and initialize it.
1906 scratch = grid->bitmap + bytes;
1907 (void) memset((char *) scratch, 0, bytes);
1910 * Determine the bytes per row.
1912 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
1915 * Determine the center coordinates of the glyph bitmap rectangle.
1920 cx = gx + (grid->glyph_bbx.width >> 1);
1921 cy = gy + (grid->glyph_bbx.height >> 1);
1923 wd = gx + grid->glyph_bbx.width;
1924 ht = gy + grid->glyph_bbx.height;
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) {
1932 nx = x + (short) ((double) y * _bdf_tan_tbl[degrees]);
1934 nx = x + (short) ((double) (gy + (ht - y)) *
1935 _bdf_tan_tbl[degrees]);
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;
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;
1954 si = (col & 7) / grid->bpp;
1955 byte = grid->bitmap[(y * bpr) + (col >> 3)] & masks[si];
1959 di = (nx & 7) / grid->bpp;
1961 byte <<= (si - di) * grid->bpp;
1963 byte >>= (di - si) * grid->bpp;
1964 scratch[(y * bpr) + (nx >> 3)] |= byte;
1971 * If a shift is required, then shift the scratch area back into
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];
1986 nx += grid->grid_width;
1987 else if (nx >= grid->grid_width)
1988 nx -= grid->grid_width;
1990 ny += grid->grid_height;
1991 else if (ny >= grid->grid_height)
1992 ny -= grid->grid_height;
1995 di = (nx & 7) / grid->bpp;
1997 byte <<= (si - di) * grid->bpp;
1999 byte >>= (di - si) * grid->bpp;
2000 grid->bitmap[(ny * bpr) + (nx >> 3)] |= byte;
2006 * Copy the scratch buffer back to the main buffer.
2008 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
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]) {
2025 * Set the new top left corrdinates.
2031 * Set the new glyph bounding box.
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;
2042 * Mark the grid as being modified.
2051 bdf_grid_embolden(bdf_glyph_grid_t *grid)
2054 short wd, ht, gx, gy, x, y;
2055 unsigned short b1, b2, bpr, si, di, col;
2056 unsigned char *masks;
2061 (grid->glyph_bbx.width == 0 && grid->glyph_bbx.height == 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;
2073 * Determine the bytes per row.
2075 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2080 wd = gx + grid->glyph_bbx.width;
2081 ht = gy + grid->glyph_bbx.height;
2083 if (grid->spacing == BDF_PROPORTIONAL ||
2084 (grid->spacing == BDF_MONOWIDTH &&
2085 grid->glyph_bbx.width < grid->font_bbx.width))
2087 * Only allow horizontal expansion in the cases that make sense.
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)] &
2101 b2 >>= (si - di) * grid->bpp;
2103 b2 <<= (di - si) * grid->bpp;
2104 grid->bitmap[(y * bpr) + (col >> 3)] |= b2;
2106 * Mark the grid as being modified.
2108 done = grid->modified = 1;
2114 * Adjust the glyph width so it will be reflected when the glyph is stored
2117 grid->glyph_bbx.width = wd - gx;
2122 /**************************************************************************
2124 * Glyph grid selection functions.
2126 **************************************************************************/
2129 bdf_has_selection(bdf_glyph_grid_t *grid, short *x, short *y,
2130 short *width, short *height)
2132 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 0))
2140 *width = grid->sel.width;
2142 *height = grid->sel.height;
2148 * Select a rectangle on the grid.
2151 bdf_set_selection(bdf_glyph_grid_t *grid, short x, short y,
2152 short width, short height)
2154 short nx, ny, wd, ht, ssize, dx, dy, col;
2155 unsigned short bytes, bpr, sbpr, si, di, byte;
2156 unsigned char *masks;
2162 * Make sure the specified rectangle is within reasonable bounds.
2164 if (x < 0 || x >= grid->grid_width)
2166 if (y < 0 || y >= grid->grid_height)
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;
2176 grid->sel.width = width;
2177 grid->sel.height = height;
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.
2184 ssize = MAX(width, height);
2186 bytes = ((((ssize * grid->bpp) + 7) >> 3) * ssize) << 1;
2189 * If the selection is being removed (width and height are 0), then simply
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;
2203 if (bytes > grid->sel.bytes) {
2204 if (grid->sel.bytes == 0)
2205 grid->sel.bitmap = (unsigned char *) malloc(bytes);
2207 grid->sel.bitmap = (unsigned char *)
2208 realloc((char *) grid->sel.bitmap, bytes);
2209 grid->sel.bytes = bytes;
2211 bytes = grid->sel.bytes;
2214 * Initialize the selection bitmap and copy the selected bits to it.
2216 (void) memset((char *) grid->sel.bitmap, 0, bytes);
2221 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2222 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
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];
2231 di = (nx & 7) / grid->bpp;
2233 byte <<= (si - di) * grid->bpp;
2235 byte >>= (di - si) * grid->bpp;
2236 grid->sel.bitmap[(ny * sbpr) + (nx >> 3)] |= byte;
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
2248 bdf_detach_selection(bdf_glyph_grid_t *grid)
2250 short sx, sy, x, y, wd, ht, dx;
2251 unsigned short bpr, sbpr, si, di, byte;
2252 unsigned char *masks;
2254 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 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;
2265 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2266 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2268 wd = grid->sel.x + grid->sel.width;
2269 ht = grid->sel.y + grid->sel.height;
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];
2277 di = (dx & 7) / grid->bpp;
2278 grid->bitmap[(y * bpr) + (dx >> 3)] &= ~masks[di];
2284 * Crop the new image to determine the new bounds with the selection.
2286 (void) bdf_grid_crop(grid, 1);
2290 bdf_attach_selection(bdf_glyph_grid_t *grid)
2292 short sx, sy, x, y, wd, ht;
2293 unsigned short bpr, sbpr, dx, di, si, byte;
2294 unsigned char *masks;
2296 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 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;
2307 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2308 sbpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2310 wd = grid->sel.x + grid->sel.width;
2311 ht = grid->sel.y + grid->sel.height;
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];
2319 di = (dx & 7) / grid->bpp;
2321 byte <<= (si - di) * grid->bpp;
2323 byte >>= (di - si) * grid->bpp;
2324 grid->bitmap[(y * bpr) + (dx >> 3)] |= byte;
2330 * Crop the new image to determine the new bounds with the selection.
2332 (void) bdf_grid_crop(grid, 1);
2336 * Indicate the selection no longer exists by setting the width and height to
2340 bdf_lose_selection(bdf_glyph_grid_t *grid)
2344 grid->sel.width = grid->sel.height = 0;
2348 * Delete the selection by first detaching it which will erase the rectangle
2349 * on the grid and then losing the selection.
2352 bdf_delete_selection(bdf_glyph_grid_t *grid)
2354 bdf_detach_selection(grid);
2355 bdf_lose_selection(grid);
2359 * Check to see if a coordinate pair is in the selected region.
2362 bdf_in_selection(bdf_glyph_grid_t *grid, short x, short y, short *set)
2365 unsigned short bpr, si, di, byte;
2366 unsigned char *masks;
2368 if (grid == 0 || (grid->sel.width == 0 && grid->sel.height == 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;
2380 bpr = ((grid->sel.width * grid->bpp) + 7) >> 3;
2382 wd = grid->sel.x + grid->sel.width;
2383 ht = grid->sel.y + grid->sel.height;
2385 if ((x >= grid->sel.x && x < wd) && (y >= grid->sel.y && y < ht)) {
2388 * Adjust the byte back to an index value.
2391 si = (x & 7) / grid->bpp;
2392 byte = grid->sel.bitmap[(y * bpr) + (x >> 3)] & masks[si];
2394 byte >>= (di - si) * grid->bpp;
2404 bdf_grid_shift(bdf_glyph_grid_t *grid, short xcount, short ycount)
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;
2426 * Adjust the shift counts if they are larger than they should be.
2428 if (xcount > grid->grid_width)
2429 xcount -= grid->grid_width;
2430 if (ycount > grid->grid_height)
2431 ycount -= grid->grid_height;
2434 * Adjust the counts to limit the shift to the boundaries of the grid.
2436 if (grid->sel.width != 0 && grid->sel.height != 0) {
2438 * The selection is being shifted.
2442 wd = grid->sel.width;
2443 ht = grid->sel.height;
2448 wd = grid->glyph_bbx.width;
2449 ht = grid->glyph_bbx.height;
2454 * If the width and height are 0, then simply return, because there
2455 * is nothing to shift.
2457 if (wd == 0 && ht == 0)
2460 if (xdir == 1 && x + wd + xcount > grid->grid_width)
2461 xcount = grid->grid_width - (x + wd);
2462 else if (xdir == -1 && xcount > x)
2465 if (ydir == 1 && y + ht + ycount > grid->grid_height)
2466 ycount = grid->grid_height - (y + ht);
2467 else if (ydir == -1 && ycount > y)
2470 if (xcount == 0 && ycount == 0)
2474 * If the selection is the one being shifted, adjust the X and Y
2475 * coordinates and adjust the glyph metrics.
2479 * Determine the actual ink bounds of the selection so the
2480 * glyph metrics can be adjusted if necessary.
2482 if (_bdf_grid_ink_bounds(grid, &x, &y, &wd, &ht)) {
2484 * Have to adjust the glyph metrics.
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;
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;
2518 * Adjust the top-left coordinate of the selection rectangle.
2520 grid->sel.x += xdir * xcount;
2521 grid->sel.y += ydir * ycount;
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;
2535 * The glyph itself is being shifted.
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);
2543 * Shift just the glyph rectangle to keep things fast.
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];
2553 nx = dx + (xdir * xcount);
2554 ny = dy + (ydir * ycount);
2556 di = (nx & 7) / grid->bpp;
2558 byte <<= (si - di) * grid->bpp;
2560 byte >>= (di - si) * grid->bpp;
2561 scratch[(ny * bpr) + (nx >> 3)] |= byte;
2567 * Copy the scratch buffer back to the main buffer.
2569 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
2572 * Adjust the top-left coordinate of the glyph rectangle.
2574 grid->glyph_x += xdir * xcount;
2575 grid->glyph_y += ydir * ycount;
2578 * Adjust the glyph offsets relative to the baseline coordinates.
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);
2585 * Adjust the glyph ascent and descent.
2587 grid->glyph_bbx.ascent = grid->base_y - grid->glyph_y;
2588 grid->glyph_bbx.descent = (grid->glyph_y + grid->glyph_bbx.height) -
2592 * Mark the grid as being modified.
2601 bdf_grid_flip(bdf_glyph_grid_t *grid, short dir)
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;
2613 if (grid->sel.width != 0 && grid->sel.height != 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;
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;
2633 * If the width or height is 0, don't do anything.
2635 if (wd == 0|| ht == 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;
2648 * Set and initialize the scratch area.
2650 scratch = bmap + bytes;
2651 (void) memset((char *) scratch, 0, bytes);
2658 * Flip horizontally.
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];
2667 colx = nx * grid->bpp;
2668 di = (colx & 7) / grid->bpp;
2670 byte <<= (si - di) * grid->bpp;
2672 byte >>= (di - si) * grid->bpp;
2673 scratch[(dy * bpr) + (colx >> 3)] |= byte;
2679 grid->sel.x += nx + 1;
2681 grid->glyph_x = nx + 1;
2682 grid->glyph_bbx.x_offset = grid->glyph_x - grid->base_x;
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];
2696 scratch[(ny * bpr) + (col >> 3)] |= byte;
2702 grid->sel.y += ny + 1;
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;
2716 * Copy the scratch area back to the working area.
2719 (void) memcpy((char *) grid->sel.bitmap, (char *) scratch, bytes);
2721 (void) memcpy((char *) grid->bitmap, (char *) scratch, bytes);
2725 * Check to see if flipping the selection caused the glyph metrics
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;
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;
2758 * Mark the grid as being modified.
2767 bdf_grid_origin(bdf_glyph_grid_t *grid, short *x, short *y)
2777 bdf_grid_glyph(bdf_glyph_grid_t *grid)
2780 short x, y, nx, ny, wd, ht, gx, gy;
2781 unsigned short bpr, nbpr, si, di, col, byte;
2783 unsigned char *masks;
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;
2798 * Create the new glyph.
2800 glyph = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t));
2801 (void) memset((char *) glyph, 0, sizeof(bdf_glyph_t));
2807 * Copy the bounding box.
2809 (void) memcpy((char *) &glyph->bbx, (char *) &grid->glyph_bbx,
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.
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;
2822 if (glyph->bbx.width > grid->font_bbx.width)
2823 glyph->bbx.width -= glyph->bbx.width - grid->font_bbx.width;
2827 * Set up its bitmap.
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);
2835 * Set the other values.
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);
2842 glyph->encoding = grid->encoding;
2843 glyph->dwidth = grid->dwidth;
2846 * Reset the glyph SWIDTH value.
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));
2853 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
2854 wd = gx + glyph->bbx.width;
2855 ht = gy + glyph->bbx.height;
2858 * Copy the bitmap from the grid into the glyph.
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];
2866 di = (nx & 7) / grid->bpp;
2868 byte <<= (si - di) * grid->bpp;
2870 byte >>= (di - si) * grid->bpp;
2871 glyph->bitmap[(ny * nbpr) + (nx >> 3)] |= byte;
2877 * Return the new glyph.
2883 * Create a bitmap with the glyph image as well as the selection.
2886 bdf_grid_image(bdf_glyph_grid_t *grid, bdf_bitmap_t *image)
2889 unsigned short bpr, ibpr, si, di, col, colx, byte;
2890 unsigned char *masks;
2892 if (grid == 0 || image == 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;
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);
2912 * Add the selection to the bitmap if it exists.
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];
2923 colx = ix * grid->bpp;
2924 di = (colx & 7) / grid->bpp;
2926 byte <<= (si - di) * grid->bpp;
2928 byte >>= (di - si) * grid->bpp;
2929 image->bitmap[(iy * ibpr) + (colx >> 3)] |= byte;
2937 * These values are intended to give pixels mapped from 1bpp to nbpp the
2938 * darkest available index, which is 1.
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};
2945 * Routines for quick and dirty dithering.
2948 _bdf_one_to_n(bdf_bitmap_t *bmap, int n)
2950 unsigned short bpr, sbpr, bytes, col, sx, sy;
2951 unsigned char *nbmap, *ones = 0;
2953 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
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;
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);
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];
2975 free((char *) bmap->bitmap);
2977 bmap->bytes = bytes;
2978 bmap->bitmap = nbmap;
2982 _bdf_n_to_one(bdf_bitmap_t *bmap)
2984 unsigned short bpr, sbpr, bytes, col, sx, sy;
2985 unsigned char *nbmap, *masks;
2987 if (bmap == 0 || bmap->width == 0 || bmap->height == 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;
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);
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));
3011 free((char *) bmap->bitmap);
3013 bmap->bytes = bytes;
3014 bmap->bitmap = nbmap;
3018 _bdf_two_to_four(bdf_bitmap_t *bmap)
3020 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3021 unsigned char *nbmap, *masks;
3023 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
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);
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];
3040 * Shift the byte down to leave the index in the lowest 2
3044 byte >>= (3 - si) << 1;
3047 * Break 16 into 4 groups of 4 and map the 2bpp index to one
3053 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
3057 free((char *) bmap->bitmap);
3059 bmap->bytes = bytes;
3060 bmap->bitmap = nbmap;
3064 _bdf_four_to_two(bdf_bitmap_t *bmap)
3066 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3067 unsigned char *nbmap, *masks;
3069 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3072 masks = bdf_fourbpp;
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);
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];
3086 * Shift the byte down to make an index.
3092 * Scale the index to two bits per pixel and shift it into
3093 * place if necessary.
3099 si = ((sx << 1) & 7) >> 1;
3101 byte <<= (3 - si) << 1;
3103 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
3107 free((char *) bmap->bitmap);
3109 bmap->bytes = bytes;
3110 bmap->bitmap = nbmap;
3114 _bdf_two_to_eight(bdf_bitmap_t *bmap)
3116 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3117 unsigned char *nbmap, *masks;
3119 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3124 sbpr = ((bmap->width << 1) + 7) >> 3;
3126 bytes = bpr * bmap->height;
3127 nbmap = (unsigned char *) malloc(bytes);
3128 (void) memset((char *) nbmap, 0, bytes);
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];
3136 * Shift the byte down to leave the index in the lowest 2
3140 byte >>= (3 - si) << 1;
3143 * Break 256 into 4 groups of 64 and map the 2bpp index to one
3147 nbmap[(sy * bpr) + sx] = byte;
3151 free((char *) bmap->bitmap);
3153 bmap->bytes = bytes;
3154 bmap->bitmap = nbmap;
3158 _bdf_eight_to_two(bdf_bitmap_t *bmap)
3160 unsigned short bpr, sbpr, bytes, si, byte, sx, sy;
3161 unsigned char *nbmap;
3163 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
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);
3172 for (sy = 0; sy < bmap->height; sy++) {
3173 for (sx = 0; sx < bmap->width; sx++) {
3174 byte = bmap->bitmap[(sy * sbpr) + sx];
3177 * Scale the index to two bits per pixel and shift it into
3178 * place if necessary.
3184 si = ((sx << 1) & 7) >> 1;
3186 byte <<= (3 - si) << 1;
3188 nbmap[(sy * bpr) + ((sx << 1) >> 3)] |= byte;
3192 free((char *) bmap->bitmap);
3194 bmap->bytes = bytes;
3195 bmap->bitmap = nbmap;
3199 _bdf_four_to_eight(bdf_bitmap_t *bmap)
3201 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3202 unsigned char *nbmap, *masks;
3204 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
3207 masks = bdf_fourbpp;
3209 sbpr = ((bmap->width << 2) + 7) >> 3;
3211 bytes = bpr * bmap->height;
3212 nbmap = (unsigned char *) malloc(bytes);
3213 (void) memset((char *) nbmap, 0, bytes);
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];
3221 * Shift the byte down to make an index.
3227 * Multiply by 16 to get the 8bpp index.
3231 nbmap[(sy * bpr) + sx] = byte;
3235 free((char *) bmap->bitmap);
3237 bmap->bytes = bytes;
3238 bmap->bitmap = nbmap;
3242 _bdf_eight_to_four(bdf_bitmap_t *bmap)
3244 unsigned short bpr, sbpr, bytes, col, si, byte, sx, sy;
3245 unsigned char *nbmap;
3247 if (bmap == 0 || bmap->width == 0 || bmap->height == 0)
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);
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];
3261 * Divide the index by 16 to determine which 4bpp index
3269 * Shift the bits up by 4 if the index is even.
3271 si = (col & 7) >> 2;
3275 nbmap[(sy * bpr) + ((sx << 2) >> 3)] |= byte;
3279 free((char *) bmap->bitmap);
3281 bmap->bytes = bytes;
3282 bmap->bitmap = nbmap;
3286 * Add a bitmap to a grid as a selection.
3289 bdf_add_selection(bdf_glyph_grid_t *grid, bdf_bitmap_t *sel)
3291 unsigned short bytes, bpr;
3293 if (grid == 0 || sel == 0 || sel->width == 0 || sel->height == 0 ||
3297 if (sel->bpp != grid->bpp) {
3299 * Dither the incoming bitmap to match the same bits per pixel as the
3300 * grid it is being added to.
3303 _bdf_one_to_n(sel, grid->bpp);
3304 else if (grid->bpp == 1)
3306 else if (sel->bpp == 2) {
3308 _bdf_two_to_four(sel);
3310 _bdf_two_to_eight(sel);
3311 } else if (sel->bpp == 4) {
3313 _bdf_four_to_two(sel);
3315 _bdf_four_to_eight(sel);
3316 } else if (sel->bpp == 8) {
3318 _bdf_eight_to_two(sel);
3320 _bdf_eight_to_four(sel);
3325 * If the bitmap is too big then trim the right and/or the bottom to fit
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;
3334 * If the positioning puts the selection bitmap off one of the edges,
3335 * adjust it so it is completely on the grid.
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;
3342 bpr = ((sel->width * grid->bpp) + 7) >> 3;
3343 bytes = (bpr * sel->height) << 1;
3346 * Resize the storage for the selection bitmap if necessary.
3348 if (bytes > grid->sel.bytes) {
3349 if (grid->sel.bytes == 0)
3350 grid->sel.bitmap = (unsigned char *) malloc(bytes);
3352 grid->sel.bitmap = (unsigned char *)
3353 realloc((char *) grid->sel.bitmap, bytes);
3354 grid->sel.bytes = bytes;
3358 * Copy the width and height values.
3360 grid->sel.x = sel->x;
3361 grid->sel.y = sel->y;
3362 grid->sel.width = sel->width;
3363 grid->sel.height = sel->height;
3366 * Copy the incoming bitmap to the new selection bitmap.
3368 (void) memcpy((char *) grid->sel.bitmap, (char *) sel->bitmap,
3372 * Crop the image to adjust the glyph bounding box.
3374 (void) bdf_grid_crop(grid, 1);
3378 bdf_grid_color_at(bdf_glyph_grid_t *grid, short x, short y)
3380 unsigned short bpr, si, di, byte;
3381 unsigned char *masks = 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;
3395 bpr = ((grid->grid_width * grid->bpp) + 7) >> 3;
3396 si = (x & 7) / grid->bpp;
3398 byte = grid->bitmap[(y * bpr) + (x >> 3)] & masks[si];
3400 byte >>= (di - si) * grid->bpp;