Bug Summary

File:bitmap/bitscale.c
Location:line 640, column 24
Description:Dereference of null pointer (loaded from variable 'ptr3')

Annotated Source Code

1/*
2
3Copyright 1991, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 * Author: Keith Packard, MIT X Consortium
31 */
32
33#ifdef HAVE_CONFIG_H1
34#include <config.h>
35#endif
36
37/*
38 * Translate monolithic #defines to modular definitions
39 */
40
41#ifdef PCFFORMAT
42#define XFONT_PCFFORMAT1 1
43#endif
44
45#ifdef SNFFORMAT
46#define XFONT_SNFFORMAT1 1
47#endif
48
49#ifdef BDFFORMAT
50#define XFONT_BDFFORMAT1 1
51#endif
52
53#include <X11/fonts/fntfilst.h>
54#include <X11/fonts/bitmap.h>
55#include <X11/fonts/fontutil.h>
56#include <math.h>
57
58#ifndef MAX
59#define MAX(a,b)(((a)>(b)) ? a : b) (((a)>(b)) ? a : b)
60#endif
61
62/* Should get this from elsewhere */
63extern unsigned long serverGeneration;
64
65static void bitmapUnloadScalable (FontPtr pFont);
66static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci,
67 CharInfoPtr pci, double *inv_xform,
68 double widthMult, double heightMult );
69static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf,
70 double widthMult, double heightMult,
71 FontScalablePtr vals);
72
73enum scaleType {
74 atom, truncate_atom, pixel_size, point_size, resolution_x,
75 resolution_y, average_width, scaledX, scaledY, unscaled, fontname,
76 raw_ascent, raw_descent, raw_pixelsize, raw_pointsize,
77 raw_average_width, uncomputed
78};
79
80typedef struct _fontProp {
81 const char *name;
82 Atom atom;
83 enum scaleType type;
84} fontProp;
85
86static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe,
87 FontEntryPtr entry,
88 FontScalablePtr vals,
89 FontScalablePtr best,
90 double *dxp, double *dyp,
91 double *sdxp, double *sdyp,
92 FontPathElementPtr *fpep );
93
94static unsigned long bitscaleGeneration = 0; /* initialization flag */
95
96static fontProp fontNamePropTable[] = {
97 { "FOUNDRY", 0, atom },
98 { "FAMILY_NAME", 0, atom },
99 { "WEIGHT_NAME", 0, atom },
100 { "SLANT", 0, atom },
101 { "SETWIDTH_NAME", 0, atom },
102 { "ADD_STYLE_NAME", 0, atom },
103 { "PIXEL_SIZE", 0, pixel_size },
104 { "POINT_SIZE", 0, point_size },
105 { "RESOLUTION_X", 0, resolution_x },
106 { "RESOLUTION_Y", 0, resolution_y },
107 { "SPACING", 0, atom },
108 { "AVERAGE_WIDTH", 0, average_width },
109 { "CHARSET_REGISTRY", 0, atom },
110 { "CHARSET_ENCODING", 0, truncate_atom },
111 { "FONT", 0, fontname },
112 { "RAW_ASCENT", 0, raw_ascent },
113 { "RAW_DESCENT", 0, raw_descent },
114 { "RAW_PIXEL_SIZE", 0, raw_pixelsize },
115 { "RAW_POINT_SIZE", 0, raw_pointsize },
116 { "RAW_AVERAGE_WIDTH", 0, raw_average_width }
117};
118
119#define TRANSFORM_POINT(matrix, x, y, dest)((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), (dest)[1]
= (matrix)[1] * (x) + (matrix)[3] * (y))
\
120 ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
121 (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
122
123#define CHECK_EXTENT(lsb, rsb, desc, asc, data)((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , (rsb) < (data
)[0] ? (rsb) = (data)[0] : 0, (-desc) > (data)[1] ? (desc)
= -(data)[1] : 0 , (asc) < (data)[1] ? (asc) = (data)[1] :
0)
\
124 ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
125 (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
126 (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
127 (asc) < (data)[1] ? (asc) = (data)[1] : 0)
128
129#define NPROPS(sizeof(fontNamePropTable) / sizeof(fontProp)) (sizeof(fontNamePropTable) / sizeof(fontProp))
130
131/* Warning: order of the next two tables is critically interdependent.
132 Location of "unscaled" properties at the end of fontPropTable[]
133 is important. */
134
135static fontProp fontPropTable[] = {
136 { "MIN_SPACE", 0, scaledX },
137 { "NORM_SPACE", 0, scaledX },
138 { "MAX_SPACE", 0, scaledX },
139 { "END_SPACE", 0, scaledX },
140 { "AVG_CAPITAL_WIDTH", 0, scaledX },
141 { "AVG_LOWERCASE_WIDTH", 0, scaledX },
142 { "QUAD_WIDTH", 0, scaledX },
143 { "FIGURE_WIDTH", 0, scaledX },
144 { "SUPERSCRIPT_X", 0, scaledX },
145 { "SUPERSCRIPT_Y", 0, scaledY },
146 { "SUBSCRIPT_X", 0, scaledX },
147 { "SUBSCRIPT_Y", 0, scaledY },
148 { "SUPERSCRIPT_SIZE", 0, scaledY },
149 { "SUBSCRIPT_SIZE", 0, scaledY },
150 { "SMALL_CAP_SIZE", 0, scaledY },
151 { "UNDERLINE_POSITION", 0, scaledY },
152 { "UNDERLINE_THICKNESS", 0, scaledY },
153 { "STRIKEOUT_ASCENT", 0, scaledY },
154 { "STRIKEOUT_DESCENT", 0, scaledY },
155 { "CAP_HEIGHT", 0, scaledY },
156 { "X_HEIGHT", 0, scaledY },
157 { "ITALIC_ANGLE", 0, unscaled },
158 { "RELATIVE_SETWIDTH", 0, unscaled },
159 { "RELATIVE_WEIGHT", 0, unscaled },
160 { "WEIGHT", 0, unscaled },
161 { "DESTINATION", 0, unscaled },
162 { "PCL_FONT_NAME", 0, unscaled },
163 { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled }
164};
165
166static fontProp rawFontPropTable[] = {
167 { "RAW_MIN_SPACE", 0, },
168 { "RAW_NORM_SPACE", 0, },
169 { "RAW_MAX_SPACE", 0, },
170 { "RAW_END_SPACE", 0, },
171 { "RAW_AVG_CAPITAL_WIDTH", 0, },
172 { "RAW_AVG_LOWERCASE_WIDTH", 0, },
173 { "RAW_QUAD_WIDTH", 0, },
174 { "RAW_FIGURE_WIDTH", 0, },
175 { "RAW_SUPERSCRIPT_X", 0, },
176 { "RAW_SUPERSCRIPT_Y", 0, },
177 { "RAW_SUBSCRIPT_X", 0, },
178 { "RAW_SUBSCRIPT_Y", 0, },
179 { "RAW_SUPERSCRIPT_SIZE", 0, },
180 { "RAW_SUBSCRIPT_SIZE", 0, },
181 { "RAW_SMALL_CAP_SIZE", 0, },
182 { "RAW_UNDERLINE_POSITION", 0, },
183 { "RAW_UNDERLINE_THICKNESS", 0, },
184 { "RAW_STRIKEOUT_ASCENT", 0, },
185 { "RAW_STRIKEOUT_DESCENT", 0, },
186 { "RAW_CAP_HEIGHT", 0, },
187 { "RAW_X_HEIGHT", 0, }
188};
189
190static void
191initFontPropTable(void)
192{
193 int i;
194 fontProp *t;
195
196 i = sizeof(fontNamePropTable) / sizeof(fontProp);
197 for (t = fontNamePropTable; i; i--, t++)
198 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE1);
199
200 i = sizeof(fontPropTable) / sizeof(fontProp);
201 for (t = fontPropTable; i; i--, t++)
202 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE1);
203
204 i = sizeof(rawFontPropTable) / sizeof(fontProp);
205 for (t = rawFontPropTable; i; i--, t++)
206 t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE1);
207}
208
209#if 0
210static FontEntryPtr
211GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name)
212{
213 FontDirectoryPtr dir;
214
215 dir = (FontDirectoryPtr) fpe->private;
216 return FontFileFindNameInDir (&dir->scalable, name);
217}
218#endif
219
220static double
221get_matrix_horizontal_component(double *matrix)
222{
223 return hypot(matrix[0], matrix[1]);
224}
225
226static double
227get_matrix_vertical_component(double *matrix)
228{
229 return hypot(matrix[2], matrix[3]);
230}
231
232
233static Bool
234ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to,
235 double *dx, double *dy, double *sdx, double *sdy,
236 double *rescale_x)
237{
238 double srcpixelset, destpixelset, srcpixel, destpixel;
239
240 srcpixelset = get_matrix_horizontal_component(from->pixel_matrix);
241 destpixelset = get_matrix_horizontal_component(to->pixel_matrix);
242 srcpixel = get_matrix_vertical_component(from->pixel_matrix);
243 destpixel = get_matrix_vertical_component(to->pixel_matrix);
244
245 if (srcpixelset >= EPS1.0e-20)
246 {
247 *dx = destpixelset / srcpixelset;
248 *sdx = 1000.0 / srcpixelset;
249 }
250 else
251 *sdx = *dx = 0;
252
253 *rescale_x = 1.0;
254
255 /* If client specified a width, it overrides setsize; in this
256 context, we interpret width as applying to the font before any
257 rotation, even though that's not what is ultimately returned in
258 the width field. */
259 if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS1.0e-20)
260 {
261 double rescale = (double)to->width / (double)from->width;
262
263 /* If the client specified a transformation matrix, the rescaling
264 for width does *not* override the setsize. Instead, just check
265 for consistency between the setsize from the matrix and the
266 setsize that would result from rescaling according to the width.
267 This assumes (perhaps naively) that the width is correctly
268 reported in the name. As an interesting side effect, this test
269 may result in choosing a different source bitmap (one that
270 scales consistently between the setsize *and* the width) than it
271 would choose if a width were not specified. Sort of a hidden
272 multiple-master functionality. */
273 if ((to->values_supplied & PIXELSIZE_MASK0x3) == PIXELSIZE_ARRAY0x2 ||
274 (to->values_supplied & POINTSIZE_MASK0xc) == POINTSIZE_ARRAY0x8)
275 {
276 /* Reject if resulting width difference is >= 1 pixel */
277 if (fabs(rescale * from->width - *dx * from->width) >= 10)
278 return FALSE0;
279 }
280 else
281 {
282 *rescale_x = rescale/(*dx);
283 *dx = rescale;
284 }
285 }
286
287 if (srcpixel >= EPS1.0e-20)
288 {
289 *dy = destpixel / srcpixel;
290 *sdy = 1000.0 / srcpixel;
291 }
292 else
293 *sdy = *dy = 0;
294
295 return TRUE1;
296}
297
298/* favor enlargement over reduction because of aliasing resulting
299 from reduction */
300#define SCORE(m,s)if (m >= 1.0) { if (m == 1.0) score += (16 * s); else if (
m == 2.0) score += (4 * s); else score += (int)(((double)(3 *
s)) / m); } else { score += (int)(((double)(2 * s)) * m); }
\
301if (m >= 1.0) { \
302 if (m == 1.0) \
303 score += (16 * s); \
304 else if (m == 2.0) \
305 score += (4 * s); \
306 else \
307 score += (int)(((double)(3 * s)) / m); \
308} else { \
309 score += (int)(((double)(2 * s)) * m); \
310}
311
312/* don't need to favor enlargement when looking for bitmap that can
313 be used unscalable */
314#define SCORE2(m,s)if (m >= 1.0) score += (int)(((double)(8 * s)) / m); else score
+= (int)(((double)(8 * s)) * m);
\
315if (m >= 1.0) \
316 score += (int)(((double)(8 * s)) / m); \
317else \
318 score += (int)(((double)(8 * s)) * m);
319
320static FontEntryPtr
321FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry,
322 FontScalablePtr vals, FontScalablePtr best,
323 double *dxp, double *dyp,
324 double *sdxp, double *sdyp,
325 FontPathElementPtr *fpep)
326{
327 FontScalableRec temp;
328 int source, i;
329 int best_score, best_unscaled_score,
330 score;
331 double dx = 0.0, sdx = 0.0, dx_amount = 0.0,
332 dy = 0.0, sdy = 0.0, dy_amount = 0.0,
333 best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0,
334 best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0,
335 best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0,
336 rescale_x = 0.0, best_rescale_x = 0.0,
337 best_unscaled_rescale_x = 0.0;
338 FontEntryPtr zero;
339 FontNameRec zeroName;
340 char zeroChars[MAXFONTNAMELEN1024];
341 FontDirectoryPtr dir;
342 FontScaledPtr scaled;
343 FontScalableExtraPtr extra;
344 FontScaledPtr best_scaled, best_unscaled;
345 FontPathElementPtr best_fpe = NULL((void*)0), best_unscaled_fpe = NULL((void*)0);
346 FontEntryPtr bitmap = NULL((void*)0);
347 FontEntryPtr result;
348 int aliascount = 20;
349 FontPathElementPtr bitmap_fpe = NULL((void*)0);
350 FontNameRec xlfdName;
351
352 /* find the best match */
353 rescale_x = 1.0;
354 best_scaled = 0;
355 best_score = 0;
356 best_unscaled = 0;
357 best_unscaled_score = -1;
358 best_dx_amount = best_dy_amount = HUGE_VAL(__builtin_huge_val());
359 memcpy (zeroChars, entry->name.name, entry->name.length);
360 zeroChars[entry->name.length] = '\0';
361 zeroName.name = zeroChars;
362 FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO2);
363 zeroName.length = strlen (zeroChars);
364 zeroName.ndashes = entry->name.ndashes;
365 xlfdName.name = vals->xlfdName;
366 xlfdName.length = strlen(xlfdName.name);
367 xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length);
368 restart_bestscale_loop: ;
369 /*
370 * Look through all the registered bitmap sources for
371 * the same zero name as ours; entries along that one
372 * can be scaled as desired.
373 */
374 for (source = 0; source < FontFileBitmapSources.count; source++)
375 {
376 /* There might already be a bitmap that satisfies the request
377 but didn't have a zero name that was found by the scalable
378 font matching logic. Keep track if there is. */
379 if (bitmap == NULL((void*)0) && vals->xlfdName != NULL((void*)0))
380 {
381 bitmap_fpe = FontFileBitmapSources.fpe[source];
382 dir = (FontDirectoryPtr) bitmap_fpe->private;
383 bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName);
384 if (bitmap && bitmap->type != FONT_ENTRY_BITMAP2)
385 {
386 if (bitmap->type == FONT_ENTRY_ALIAS3 && aliascount > 0)
387 {
388 aliascount--;
389 xlfdName.name = bitmap->u.alias.resolved;
390 xlfdName.length = strlen(xlfdName.name);
391 xlfdName.ndashes = FontFileCountDashes(xlfdName.name,
392 xlfdName.length);
393 bitmap = NULL((void*)0);
394 goto restart_bestscale_loop;
395 }
396 else
397 bitmap = NULL((void*)0);
398 }
399 }
400
401 if (FontFileBitmapSources.fpe[source] == fpe)
402 zero = entry;
403 else
404 {
405 dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
406 zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
407 if (!zero)
408 continue;
409 }
410 extra = zero->u.scalable.extra;
411 for (i = 0; i < extra->numScaled; i++)
412 {
413 scaled = &extra->scaled[i];
414 if (!scaled->bitmap)
415 continue;
416 if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy,
417 &rescale_x))
418 continue;
419 score = 0;
420 dx_amount = dx;
421 dy_amount = dy;
422 SCORE(dy_amount, 10)if (dy_amount >= 1.0) { if (dy_amount == 1.0) score += (16
* 10); else if (dy_amount == 2.0) score += (4 * 10); else score
+= (int)(((double)(3 * 10)) / dy_amount); } else { score += (
int)(((double)(2 * 10)) * dy_amount); }
;
423 SCORE(dx_amount, 1)if (dx_amount >= 1.0) { if (dx_amount == 1.0) score += (16
* 1); else if (dx_amount == 2.0) score += (4 * 1); else score
+= (int)(((double)(3 * 1)) / dx_amount); } else { score += (
int)(((double)(2 * 1)) * dx_amount); }
;
424 if ((score > best_score) ||
425 ((score == best_score) &&
426 ((dy_amount < best_dy_amount) ||
427 ((dy_amount == best_dy_amount) &&
428 (dx_amount < best_dx_amount)))))
429 {
430 best_fpe = FontFileBitmapSources.fpe[source];
431 best_scaled = scaled;
432 best_score = score;
433 best_dx = dx;
434 best_dy = dy;
435 best_sdx = sdx;
436 best_sdy = sdy;
437 best_dx_amount = dx_amount;
438 best_dy_amount = dy_amount;
439 best_rescale_x = rescale_x;
440 }
441 /* Is this font a candidate for use without ugly rescaling? */
442 if (fabs(dx) > EPS1.0e-20 && fabs(dy) > EPS1.0e-20 &&
443 fabs(vals->pixel_matrix[0] * rescale_x -
444 scaled->vals.pixel_matrix[0]) < 1 &&
445 fabs(vals->pixel_matrix[1] * rescale_x -
446 scaled->vals.pixel_matrix[1]) < EPS1.0e-20 &&
447 fabs(vals->pixel_matrix[2] -
448 scaled->vals.pixel_matrix[2]) < EPS1.0e-20 &&
449 fabs(vals->pixel_matrix[3] -
450 scaled->vals.pixel_matrix[3]) < 1)
451 {
452 /* Yes. The pixel sizes are close on the diagonal and
453 extremely close off the diagonal. */
454 score = 0;
455 SCORE2(vals->pixel_matrix[3] /if (vals->pixel_matrix[3] / scaled->vals.pixel_matrix[3
] >= 1.0) score += (int)(((double)(8 * 10)) / vals->pixel_matrix
[3] / scaled->vals.pixel_matrix[3]); else score += (int)((
(double)(8 * 10)) * vals->pixel_matrix[3] / scaled->vals
.pixel_matrix[3]);
456 scaled->vals.pixel_matrix[3], 10)if (vals->pixel_matrix[3] / scaled->vals.pixel_matrix[3
] >= 1.0) score += (int)(((double)(8 * 10)) / vals->pixel_matrix
[3] / scaled->vals.pixel_matrix[3]); else score += (int)((
(double)(8 * 10)) * vals->pixel_matrix[3] / scaled->vals
.pixel_matrix[3]);
;
457 SCORE2(vals->pixel_matrix[0] * rescale_x /if (vals->pixel_matrix[0] * rescale_x / scaled->vals.pixel_matrix
[0] >= 1.0) score += (int)(((double)(8 * 1)) / vals->pixel_matrix
[0] * rescale_x / scaled->vals.pixel_matrix[0]); else score
+= (int)(((double)(8 * 1)) * vals->pixel_matrix[0] * rescale_x
/ scaled->vals.pixel_matrix[0]);
458 scaled->vals.pixel_matrix[0], 1)if (vals->pixel_matrix[0] * rescale_x / scaled->vals.pixel_matrix
[0] >= 1.0) score += (int)(((double)(8 * 1)) / vals->pixel_matrix
[0] * rescale_x / scaled->vals.pixel_matrix[0]); else score
+= (int)(((double)(8 * 1)) * vals->pixel_matrix[0] * rescale_x
/ scaled->vals.pixel_matrix[0]);
;
459 if (score > best_unscaled_score)
460 {
461 best_unscaled_fpe = FontFileBitmapSources.fpe[source];
462 best_unscaled = scaled;
463 best_unscaled_sdx = sdx / dx;
464 best_unscaled_sdy = sdy / dy;
465 best_unscaled_score = score;
466 best_unscaled_rescale_x = rescale_x;
467 }
468 }
469 }
470 }
471 if (best_unscaled)
472 {
473 *best = best_unscaled->vals;
474 *fpep = best_unscaled_fpe;
475 *dxp = 1.0;
476 *dyp = 1.0;
477 *sdxp = best_unscaled_sdx;
478 *sdyp = best_unscaled_sdy;
479 rescale_x = best_unscaled_rescale_x;
480 result = best_unscaled->bitmap;
481 }
482 else if (best_scaled)
483 {
484 *best = best_scaled->vals;
485 *fpep = best_fpe;
486 *dxp = best_dx;
487 *dyp = best_dy;
488 *sdxp = best_sdx;
489 *sdyp = best_sdy;
490 rescale_x = best_rescale_x;
491 result = best_scaled->bitmap;
492 }
493 else
494 result = NULL((void*)0);
495
496 if (bitmap != NULL((void*)0) && (result == NULL((void*)0) || *dxp != 1.0 || *dyp != 1.0))
497 {
498 *fpep = bitmap_fpe;
499 FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE0);
500 if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x))
501 result = bitmap;
502 else
503 result = NULL((void*)0);
504 }
505
506 if (result && rescale_x != 1.0)
507 {
508 /* We have rescaled horizontally due to an XLFD width field. Change
509 the matrix appropriately */
510 vals->pixel_matrix[0] *= rescale_x;
511 vals->pixel_matrix[1] *= rescale_x;
512 vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK0xc;
513 /* Recompute and reround the FontScalablePtr values after
514 rescaling for the new width. */
515 FontFileCompleteXLFD(vals, vals);
516 }
517
518 return result;
519}
520
521static long
522doround(double x)
523{
524 return (x >= 0) ? (long)(x + .5) : (long)(x - .5);
525}
526
527static int
528computeProps(FontPropPtr pf, char *wasStringProp,
529 FontPropPtr npf, char *isStringProp,
530 unsigned int nprops, double xfactor, double yfactor,
531 double sXfactor, double sYfactor)
532{
533 int n;
534 int count;
535 fontProp *t;
536 double rawfactor = 0.0;
537
538 for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
539 n = sizeof(fontPropTable) / sizeof(fontProp);
540 for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
541 if (!n)
542 continue;
543
544 switch (t->type) {
545 case scaledX:
546 npf->value = doround(xfactor * (double)pf->value);
547 rawfactor = sXfactor;
548 break;
549 case scaledY:
550 npf->value = doround(yfactor * (double)pf->value);
551 rawfactor = sYfactor;
552 break;
553 case unscaled:
554 npf->value = pf->value;
555 npf->name = pf->name;
556 npf++;
557 count++;
558 *isStringProp++ = *wasStringProp;
559 break;
560 default:
561 break;
562 }
563 if (t->type != unscaled)
564 {
565 npf->name = pf->name;
566 npf++;
567 count++;
568 npf->value = doround(rawfactor * (double)pf->value);
569 npf->name = rawFontPropTable[t - fontPropTable].atom;
570 npf++;
571 count++;
572 *isStringProp++ = *wasStringProp;
573 *isStringProp++ = *wasStringProp;
574 }
575 }
576 return count;
577}
578
579
580static int
581ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */
582 char *name, /* name of resulting font */
583 FontScalablePtr vals,
584 double dx, double dy, /* scale factors in x and y */
585 double sdx, double sdy, /* directions */
586 long sWidth, /* 1000-pixel average width */
587 FontPropPtr *pProps, /* returns properties;
588 preallocated */
589 char **pIsStringProp) /* return booleans;
590 preallocated */
591{
592 int n;
593 char *ptr1 = NULL((void*)0), *ptr2 = NULL((void*)0);
594 char *ptr3;
595 FontPropPtr fp;
596 fontProp *fpt;
597 char *isStringProp;
598 int nProps;
599
600 if (bitscaleGeneration != serverGeneration) {
1
Taking false branch
601 initFontPropTable();
602 bitscaleGeneration = serverGeneration;
603 }
604 nProps = NPROPS(sizeof(fontNamePropTable) / sizeof(fontProp)) + 1 + sizeof(fontPropTable) / sizeof(fontProp) +
605 sizeof(rawFontPropTable) / sizeof(fontProp);
606 fp = malloc(sizeof(FontPropRec) * nProps);
607 *pProps = fp;
608 if (!fp) {
2
Assuming 'fp' is non-null
3
Taking false branch
609 fprintf(stderrstderr, "Error: Couldn't allocate font properties (%ld*%d)\n",
610 (unsigned long)sizeof(FontPropRec), nProps);
611 return 1;
612 }
613 isStringProp = malloc (nProps);
614 *pIsStringProp = isStringProp;
615 if (!isStringProp)
4
Assuming 'isStringProp' is non-null
5
Taking false branch
616 {
617 fprintf(stderrstderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps);
618 free (fp);
619 return 1;
620 }
621 ptr2 = name;
622 for (fpt = fontNamePropTable, n = NPROPS(sizeof(fontNamePropTable) / sizeof(fontProp));
6
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
623 n;
624 fp++, fpt++, n--, isStringProp++)
625 {
626
627 if (*ptr2)
7
Taking false branch
11
Taking false branch
628 {
629 ptr1 = ptr2 + 1;
630 if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
631 }
632
633 *isStringProp = 0;
634 switch (fpt->type) {
8
Control jumps to the 'default' case at line 681
12
Control jumps to 'case truncate_atom:' at line 639
635 case atom:
636 fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE1);
637 *isStringProp = 1;
638 break;
639 case truncate_atom:
640 for (ptr3 = ptr1; *ptr3; ptr3++)
13
Dereference of null pointer (loaded from variable 'ptr3')
641 if (*ptr3 == '[')
642 break;
643 if (!*ptr3) ptr3 = ptr2;
644 fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE1);
645 *isStringProp = 1;
646 break;
647 case pixel_size:
648 fp->value = doround(vals->pixel_matrix[3]);
649 break;
650 case point_size:
651 fp->value = doround(vals->point_matrix[3] * 10.0);
652 break;
653 case resolution_x:
654 fp->value = vals->x;
655 break;
656 case resolution_y:
657 fp->value = vals->y;
658 break;
659 case average_width:
660 fp->value = vals->width;
661 break;
662 case fontname:
663 fp->value = MakeAtom(name, strlen(name), TRUE1);
664 *isStringProp = 1;
665 break;
666 case raw_ascent:
667 fp->value = sourceFontInfo->fontAscent * sdy;
668 break;
669 case raw_descent:
670 fp->value = sourceFontInfo->fontDescent * sdy;
671 break;
672 case raw_pointsize:
673 fp->value = (long)(72270.0 / (double)vals->y + .5);
674 break;
675 case raw_pixelsize:
676 fp->value = 1000;
677 break;
678 case raw_average_width:
679 fp->value = sWidth;
680 break;
681 default:
682 break;
9
Execution continues on line 684
683 }
684 fp->name = fpt->atom;
685 }
686 n = NPROPS(sizeof(fontNamePropTable) / sizeof(fontProp));
687 n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
688 fp, isStringProp, sourceFontInfo->nprops, dx, dy,
689 sdx, sdy);
690 return n;
691}
692
693
694static int
695compute_xform_matrix(FontScalablePtr vals, double dx, double dy,
696 double *xform, double *inv_xform,
697 double *xmult, double *ymult)
698{
699 double det;
700 double pixel = get_matrix_vertical_component(vals->pixel_matrix);
701 double pixelset = get_matrix_horizontal_component(vals->pixel_matrix);
702
703 if (pixel < EPS1.0e-20 || pixelset < EPS1.0e-20) return 0;
704
705 /* Initialize the transformation matrix to the scaling factors */
706 xform[0] = dx / pixelset;
707 xform[1] = xform[2] = 0.0;
708 xform[3] = dy / pixel;
709
710/* Inline matrix multiply -- somewhat ugly to minimize register usage */
711#define MULTIPLY_XFORM(a,b,c,d){ register double aa = (a), bb = (b), cc = (c), dd = (d); register
double temp; temp = aa * xform[0] + cc * xform[1]; aa = aa *
xform[2] + cc * xform[3]; xform[1] = bb * xform[0] + dd * xform
[1]; xform[3] = bb * xform[2] + dd * xform[3]; xform[0] = temp
; xform[2] = aa; }
\
712{ \
713 register double aa = (a), bb = (b), cc = (c), dd = (d); \
714 register double temp; \
715 temp = aa * xform[0] + cc * xform[1]; \
716 aa = aa * xform[2] + cc * xform[3]; \
717 xform[1] = bb * xform[0] + dd * xform[1]; \
718 xform[3] = bb * xform[2] + dd * xform[3]; \
719 xform[0] = temp; \
720 xform[2] = aa; \
721}
722
723 /* Rescale the transformation matrix for size of source font */
724 MULTIPLY_XFORM(vals->pixel_matrix[0],{ register double aa = (vals->pixel_matrix[0]), bb = (vals
->pixel_matrix[1]), cc = (vals->pixel_matrix[2]), dd = (
vals->pixel_matrix[3]); register double temp; temp = aa * xform
[0] + cc * xform[1]; aa = aa * xform[2] + cc * xform[3]; xform
[1] = bb * xform[0] + dd * xform[1]; xform[3] = bb * xform[2]
+ dd * xform[3]; xform[0] = temp; xform[2] = aa; }
725 vals->pixel_matrix[1],{ register double aa = (vals->pixel_matrix[0]), bb = (vals
->pixel_matrix[1]), cc = (vals->pixel_matrix[2]), dd = (
vals->pixel_matrix[3]); register double temp; temp = aa * xform
[0] + cc * xform[1]; aa = aa * xform[2] + cc * xform[3]; xform
[1] = bb * xform[0] + dd * xform[1]; xform[3] = bb * xform[2]
+ dd * xform[3]; xform[0] = temp; xform[2] = aa; }
726 vals->pixel_matrix[2],{ register double aa = (vals->pixel_matrix[0]), bb = (vals
->pixel_matrix[1]), cc = (vals->pixel_matrix[2]), dd = (
vals->pixel_matrix[3]); register double temp; temp = aa * xform
[0] + cc * xform[1]; aa = aa * xform[2] + cc * xform[3]; xform
[1] = bb * xform[0] + dd * xform[1]; xform[3] = bb * xform[2]
+ dd * xform[3]; xform[0] = temp; xform[2] = aa; }
727 vals->pixel_matrix[3]){ register double aa = (vals->pixel_matrix[0]), bb = (vals
->pixel_matrix[1]), cc = (vals->pixel_matrix[2]), dd = (
vals->pixel_matrix[3]); register double temp; temp = aa * xform
[0] + cc * xform[1]; aa = aa * xform[2] + cc * xform[3]; xform
[1] = bb * xform[0] + dd * xform[1]; xform[3] = bb * xform[2]
+ dd * xform[3]; xform[0] = temp; xform[2] = aa; }
;
728
729 *xmult = xform[0];
730 *ymult = xform[3];
731
732
733 if (inv_xform == NULL((void*)0)) return 1;
734
735 /* Compute the determinant for use in inverting the matrix. */
736 det = xform[0] * xform[3] - xform[1] * xform[2];
737
738 /* If the determinant is tiny or zero, give up */
739 if (fabs(det) < EPS1.0e-20) return 0;
740
741 /* Compute the inverse */
742 inv_xform[0] = xform[3] / det;
743 inv_xform[1] = -xform[1] / det;
744 inv_xform[2] = -xform[2] / det;
745 inv_xform[3] = xform[0] / det;
746
747 return 1;
748}
749
750/*
751 * ScaleFont
752 * returns a pointer to the new scaled font, or NULL (due to AllocError).
753 */
754static FontPtr
755ScaleFont(FontPtr opf, /* originating font */
756 double widthMult, /* glyphs width scale factor */
757 double heightMult, /* glyphs height scale factor */
758 double sWidthMult, /* scalable glyphs width scale factor */
759 double sHeightMult, /* scalable glyphs height scale factor */
760 FontScalablePtr vals,
761 double *newWidthMult, /* return: X component of glyphs width
762 scale factor */
763 double *newHeightMult, /* return: Y component of glyphs height
764 scale factor */
765 long *sWidth) /* return: average 1000-pixel width */
766{
767 FontPtr pf;
768 FontInfoPtr pfi,
769 opfi;
770 BitmapFontPtr bitmapFont,
771 obitmapFont;
772 CharInfoPtr pci,
773 opci;
774 int nchars = 0; /* how many characters in the font */
775 int i;
776 int firstCol, lastCol, firstRow, lastRow;
777 double xform[4], inv_xform[4];
778 double xmult, ymult;
779 int totalwidth = 0, totalchars = 0;
780#define OLDINDEX(i)(((i)/(lastCol - firstCol + 1) + firstRow - opf->info.firstRow
) * (opf->info.lastCol - opf->info.firstCol + 1) + (i)%
(lastCol - firstCol + 1) + firstCol - opf->info.firstCol)
(((i)/(lastCol - firstCol + 1) + \
781 firstRow - opf->info.firstRow) * \
782 (opf->info.lastCol - opf->info.firstCol + 1) + \
783 (i)%(lastCol - firstCol + 1) + \
784 firstCol - opf->info.firstCol)
785
786 *sWidth = 0;
787
788 opfi = &opf->info;
789 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
790
791 bitmapFont = 0;
792 if (!(pf = CreateFontRec())) {
793 fprintf(stderrstderr, "Error: Couldn't allocate FontRec (%ld)\n",
794 (unsigned long)sizeof(FontRec));
795 goto bail;
796 }
797 pf->refcnt = 0;
798 pf->bit = opf->bit;
799 pf->byte = opf->byte;
800 pf->glyph = opf->glyph;
801 pf->scan = opf->scan;
802
803 pf->get_glyphs = bitmapGetGlyphs;
804 pf->get_metrics = bitmapGetMetrics;
805 pf->unload_font = bitmapUnloadScalable;
806 pf->unload_glyphs = NULL((void*)0);
807
808 pfi = &pf->info;
809 *pfi = *opfi;
810 /* If charset subsetting specified in vals, determine what our range
811 needs to be for the output font */
812 if (vals->nranges)
813 {
814 int i;
815
816 pfi->allExist = 0;
817 firstCol = 255;
818 lastCol = 0;
819 firstRow = 255;
820 lastRow = 0;
821
822 for (i = 0; i < vals->nranges; i++)
823 {
824 if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high)
825 {
826 firstCol = opfi->firstCol;
827 lastCol = opfi->lastCol;
828 }
829 if (firstCol > vals->ranges[i].min_char_low)
830 firstCol = vals->ranges[i].min_char_low;
831 if (lastCol < vals->ranges[i].max_char_low)
832 lastCol = vals->ranges[i].max_char_low;
833 if (firstRow > vals->ranges[i].min_char_high)
834 firstRow = vals->ranges[i].min_char_high;
835 if (lastRow < vals->ranges[i].max_char_high)
836 lastRow = vals->ranges[i].max_char_high;
837 }
838
839 if (firstCol > lastCol || firstRow > lastRow)
840 goto bail;
841
842 if (firstCol < opfi->firstCol)
843 firstCol = opfi->firstCol;
844 if (lastCol > opfi->lastCol)
845 lastCol = opfi->lastCol;
846 if (firstRow < opfi->firstRow)
847 firstRow = opfi->firstRow;
848 if (lastRow > opfi->lastRow)
849 lastRow = opfi->lastRow;
850 }
851 else
852 {
853 firstCol = opfi->firstCol;
854 lastCol = opfi->lastCol;
855 firstRow = opfi->firstRow;
856 lastRow = opfi->lastRow;
857 }
858
859 bitmapFont = malloc(sizeof(BitmapFontRec));
860 if (!bitmapFont) {
861 fprintf(stderrstderr, "Error: Couldn't allocate bitmapFont (%ld)\n",
862 (unsigned long)sizeof(BitmapFontRec));
863 goto bail;
864 }
865 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
866 pfi->firstRow = firstRow;
867 pfi->lastRow = lastRow;
868 pfi->firstCol = firstCol;
869 pfi->lastCol = lastCol;
870 pf->fontPrivate = (pointer) bitmapFont;
871 bitmapFont->version_num = obitmapFont->version_num;
872 bitmapFont->num_chars = nchars;
873 bitmapFont->num_tables = obitmapFont->num_tables;
874 bitmapFont->metrics = 0;
875 bitmapFont->ink_metrics = 0;
876 bitmapFont->bitmaps = 0;
877 bitmapFont->encoding = 0;
878 bitmapFont->bitmapExtra = 0;
879 bitmapFont->pDefault = 0;
880 bitmapFont->metrics = malloc(nchars * sizeof(CharInfoRec));
881 if (!bitmapFont->metrics) {
882 fprintf(stderrstderr, "Error: Couldn't allocate metrics (%d*%ld)\n",
883 nchars, (unsigned long)sizeof(CharInfoRec));
884 goto bail;
885 }
886 bitmapFont->encoding = calloc(NUM_SEGMENTS(nchars)(((nchars)+128 -1)/128), sizeof(CharInfoPtr*));
887 if (!bitmapFont->encoding) {
888 fprintf(stderrstderr, "Error: Couldn't allocate encoding (%d*%ld)\n",
889 nchars, (unsigned long)sizeof(CharInfoPtr));
890 goto bail;
891 }
892
893#undef MAXSHORT32767
894#define MAXSHORT32767 32767
895#undef MINSHORT-32768
896#define MINSHORT-32768 -32768
897
898 pfi->anamorphic = FALSE0;
899 if (heightMult != widthMult)
900 pfi->anamorphic = TRUE1;
901 pfi->cachable = TRUE1;
902
903 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
904 inv_xform, &xmult, &ymult))
905 goto bail;
906
907 pfi->fontAscent = opfi->fontAscent * ymult;
908 pfi->fontDescent = opfi->fontDescent * ymult;
909
910 pfi->minbounds.leftSideBearing = MAXSHORT32767;
911 pfi->minbounds.rightSideBearing = MAXSHORT32767;
912 pfi->minbounds.ascent = MAXSHORT32767;
913 pfi->minbounds.descent = MAXSHORT32767;
914 pfi->minbounds.characterWidth = MAXSHORT32767;
915 pfi->minbounds.attributes = MAXSHORT32767;
916
917 pfi->maxbounds.leftSideBearing = MINSHORT-32768;
918 pfi->maxbounds.rightSideBearing = MINSHORT-32768;
919 pfi->maxbounds.ascent = MINSHORT-32768;
920 pfi->maxbounds.descent = MINSHORT-32768;
921 pfi->maxbounds.characterWidth = MINSHORT-32768;
922 pfi->maxbounds.attributes = MINSHORT-32768;
923
924 /* Compute the transformation and inverse transformation matrices.
925 Can fail if the determinant is zero. */
926
927 pci = bitmapFont->metrics;
928 for (i = 0; i < nchars; i++)
929 {
930 if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))(obitmapFont->encoding[((((i)/(lastCol - firstCol + 1) + firstRow
- opf->info.firstRow) * (opf->info.lastCol - opf->info
.firstCol + 1) + (i)%(lastCol - firstCol + 1) + firstCol - opf
->info.firstCol))/128]?(obitmapFont->encoding[((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))/128][((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))%128]):0)
))
931 {
932 double newlsb, newrsb, newdesc, newasc, point[2];
933
934#define minchar(p)((p).min_char_low + ((p).min_char_high << 8)) ((p).min_char_low + ((p).min_char_high << 8))
935#define maxchar(p)((p).max_char_low + ((p).max_char_high << 8)) ((p).max_char_low + ((p).max_char_high << 8))
936
937 if (vals->nranges)
938 {
939 int row = i / (lastCol - firstCol + 1) + firstRow;
940 int col = i % (lastCol - firstCol + 1) + firstCol;
941 int ch = (row << 8) + col;
942 int j;
943 for (j = 0; j < vals->nranges; j++)
944 if (ch >= minchar(vals->ranges[j])((vals->ranges[j]).min_char_low + ((vals->ranges[j]).min_char_high
<< 8))
&&
945 ch <= maxchar(vals->ranges[j])((vals->ranges[j]).max_char_low + ((vals->ranges[j]).max_char_high
<< 8))
)
946 break;
947 if (j == vals->nranges)
948 {
949 continue;
950 }
951 }
952
953 if (opci->metrics.leftSideBearing == 0 &&
954 opci->metrics.rightSideBearing == 0 &&
955 opci->metrics.ascent == 0 &&
956 opci->metrics.descent == 0 &&
957 opci->metrics.characterWidth == 0)
958 {
959 continue;
960 }
961
962 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)((i)/128)]) {
963 bitmapFont->encoding[SEGMENT_MAJOR(i)((i)/128)]=
964 calloc(BITMAP_FONT_SEGMENT_SIZE128, sizeof(CharInfoPtr));
965 if(!bitmapFont->encoding[SEGMENT_MAJOR(i)((i)/128)])
966 goto bail;
967 }
968 ACCESSENCODINGL(bitmapFont->encoding, i)(bitmapFont->encoding[(i)/128][(i)%128]) = pci;
969
970 /* Compute new extents for this glyph */
971 TRANSFORM_POINT(xform,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (-opci
->metrics.descent))
972 opci->metrics.leftSideBearing,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (-opci
->metrics.descent))
973 -opci->metrics.descent,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (-opci
->metrics.descent))
974 point)((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (-opci
->metrics.descent))
;
975 newlsb = point[0];
976 newrsb = newlsb;
977 newdesc = -point[1];
978 newasc = -newdesc;
979 TRANSFORM_POINT(xform,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (opci
->metrics.ascent))
980 opci->metrics.leftSideBearing,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (opci
->metrics.ascent))
981 opci->metrics.ascent,((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (opci
->metrics.ascent))
982 point)((point)[0] = (xform)[0] * (opci->metrics.leftSideBearing)
+ (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.leftSideBearing) + (xform)[3] * (opci
->metrics.ascent))
;
983 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point)((newlsb) > (point)[0] ? (newlsb) = (point)[0] : 0 , (newrsb
) < (point)[0] ? (newrsb) = (point)[0] : 0, (-newdesc) >
(point)[1] ? (newdesc) = -(point)[1] : 0 , (newasc) < (point
)[1] ? (newasc) = (point)[1] : 0)
;
984 TRANSFORM_POINT(xform,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (-opci
->metrics.descent))
985 opci->metrics.rightSideBearing,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (-opci
->metrics.descent))
986 -opci->metrics.descent,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (-opci
->metrics.descent))
987 point)((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (-opci->metrics.descent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (-opci
->metrics.descent))
;
988 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point)((newlsb) > (point)[0] ? (newlsb) = (point)[0] : 0 , (newrsb
) < (point)[0] ? (newrsb) = (point)[0] : 0, (-newdesc) >
(point)[1] ? (newdesc) = -(point)[1] : 0 , (newasc) < (point
)[1] ? (newasc) = (point)[1] : 0)
;
989 TRANSFORM_POINT(xform,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (opci
->metrics.ascent))
990 opci->metrics.rightSideBearing,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (opci
->metrics.ascent))
991 opci->metrics.ascent,((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (opci
->metrics.ascent))
992 point)((point)[0] = (xform)[0] * (opci->metrics.rightSideBearing
) + (xform)[2] * (opci->metrics.ascent), (point)[1] = (xform
)[1] * (opci->metrics.rightSideBearing) + (xform)[3] * (opci
->metrics.ascent))
;
993 CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point)((newlsb) > (point)[0] ? (newlsb) = (point)[0] : 0 , (newrsb
) < (point)[0] ? (newrsb) = (point)[0] : 0, (-newdesc) >
(point)[1] ? (newdesc) = -(point)[1] : 0 , (newasc) < (point
)[1] ? (newasc) = (point)[1] : 0)
;
994
995 pci->metrics.leftSideBearing = (int)floor(newlsb);
996 pci->metrics.rightSideBearing = (int)floor(newrsb + .5);
997 pci->metrics.descent = (int)ceil(newdesc);
998 pci->metrics.ascent = (int)floor(newasc + .5);
999 /* Accumulate total width of characters before transformation,
1000 to ascertain predominant direction of font. */
1001 totalwidth += opci->metrics.characterWidth;
1002 pci->metrics.characterWidth =
1003 doround((double)opci->metrics.characterWidth * xmult);
1004 pci->metrics.attributes =
1005 doround((double)opci->metrics.characterWidth * sWidthMult);
1006 if (!pci->metrics.characterWidth)
1007 {
1008 /* Since transformation may shrink width, height, and
1009 escapement to zero, make sure existing characters
1010 are not mistaken for undefined characters. */
1011
1012 if (pci->metrics.rightSideBearing ==
1013 pci->metrics.leftSideBearing)
1014 pci->metrics.rightSideBearing++;
1015 if (pci->metrics.ascent == -pci->metrics.descent)
1016 pci->metrics.ascent++;
1017 }
1018
1019 pci++;
1020 }
1021 }
1022
1023
1024 /*
1025 * For each character, set the per-character metrics, scale the glyph, and
1026 * check per-font minbounds and maxbounds character information.
1027 */
1028
1029 pci = bitmapFont->metrics;
1030 for (i = 0; i < nchars; i++)
1031 {
1032 if ((pci = ACCESSENCODING(bitmapFont->encoding,i)(bitmapFont->encoding[(i)/128]?(bitmapFont->encoding[(i
)/128][(i)%128]):0)
) &&
1033 (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))(obitmapFont->encoding[((((i)/(lastCol - firstCol + 1) + firstRow
- opf->info.firstRow) * (opf->info.lastCol - opf->info
.firstCol + 1) + (i)%(lastCol - firstCol + 1) + firstCol - opf
->info.firstCol))/128]?(obitmapFont->encoding[((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))/128][((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))%128]):0)
))
1034 {
1035 totalchars++;
1036 *sWidth += abs((int)(INT16)pci->metrics.attributes);
1037#define MINMAX(field) \
1038 if (pfi->minbounds.field > pci->metrics.field) \
1039 pfi->minbounds.field = pci->metrics.field; \
1040 if (pfi->maxbounds.field < pci->metrics.field) \
1041 pfi->maxbounds.field = pci->metrics.field
1042
1043 MINMAX(leftSideBearing);
1044 MINMAX(rightSideBearing);
1045 MINMAX(ascent);
1046 MINMAX(descent);
1047 MINMAX(characterWidth);
1048
1049 /* Hack: Cast attributes into a signed quantity. Tread lightly
1050 for now and don't go changing the global Xproto.h file */
1051 if ((INT16)pfi->minbounds.attributes >
1052 (INT16)pci->metrics.attributes)
1053 pfi->minbounds.attributes = pci->metrics.attributes;
1054 if ((INT16)pfi->maxbounds.attributes <
1055 (INT16)pci->metrics.attributes)
1056 pfi->maxbounds.attributes = pci->metrics.attributes;
1057#undef MINMAX
1058 }
1059 }
1060 pfi->ink_minbounds = pfi->minbounds;
1061 pfi->ink_maxbounds = pfi->maxbounds;
1062 if (totalchars)
1063 {
1064 *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars;
1065 if (totalwidth < 0)
1066 {
1067 /* Dominant direction is R->L */
1068 *sWidth = -*sWidth;
1069 }
1070
1071 if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth)
1072 vals->width = pfi->minbounds.characterWidth * 10;
1073 else
1074 vals->width = doround((double)*sWidth * vals->pixel_matrix[0] /
1075 1000.0);
1076 }
1077 else
1078 {
1079 vals->width = 0;
1080 *sWidth = 0;
1081 }
1082 FontComputeInfoAccelerators (pfi);
1083
1084 if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR-1) {
1085 unsigned int r,
1086 c,
1087 cols;
1088
1089 r = pfi->defaultCh >> 8;
1090 c = pfi->defaultCh & 0xFF;
1091 if (pfi->firstRow <= r && r <= pfi->lastRow &&
1092 pfi->firstCol <= c && c <= pfi->lastCol) {
1093 cols = pfi->lastCol - pfi->firstCol + 1;
1094 r = r - pfi->firstRow;
1095 c = c - pfi->firstCol;
1096 bitmapFont->pDefault =
1097 ACCESSENCODING(bitmapFont->encoding, r * cols + c)(bitmapFont->encoding[(r * cols + c)/128]?(bitmapFont->
encoding[(r * cols + c)/128][(r * cols + c)%128]):0)
;
1098 }
1099 }
1100
1101 *newWidthMult = xmult;
1102 *newHeightMult = ymult;
1103 return pf;
1104bail:
1105 if (pf)
1106 free(pf);
1107 if (bitmapFont) {
1108 free(bitmapFont->metrics);
1109 free(bitmapFont->ink_metrics);
1110 free(bitmapFont->bitmaps);
1111 if(bitmapFont->encoding)
1112 for(i=0; i<NUM_SEGMENTS(nchars)(((nchars)+128 -1)/128); i++)
1113 free(bitmapFont->encoding[i]);
1114 free(bitmapFont->encoding);
1115 }
1116 return NULL((void*)0);
1117}
1118
1119static void
1120ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci,
1121 double *inv_xform, double widthMult, double heightMult)
1122{
1123 register char *bitmap, /* The bits */
1124 *newBitmap;
1125 register int bpr, /* Padding information */
1126 newBpr;
1127 int width, /* Extents information */
1128 height,
1129 newWidth,
1130 newHeight;
1131 register int row, /* Loop variables */
1132 col;
1133 INT32 deltaX, /* Increments for resampling loop */
1134 deltaY;
1135 INT32 xValue, /* Subscripts for resampling loop */
1136 yValue;
1137 double point[2];
1138 unsigned char *char_grayscale = 0;
1139 INT32 *diffusion_workspace = NULL((void*)0), *thisrow = NULL((void*)0),
1140 *nextrow = NULL((void*)0), pixmult = 0;
1141 int box_x = 0, box_y = 0;
1142
1143 static unsigned char masklsb[] =
1144 { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
1145 static unsigned char maskmsb[] =
1146 { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
1147 unsigned char *mask = (pFont->bit == LSBFirst0 ? masklsb : maskmsb);
1148
1149
1150 bitmap = opci->bits;
1151 newBitmap = pci->bits;
1152 width = GLYPHWIDTHPIXELS(opci)((opci)->metrics.rightSideBearing - (opci)->metrics.leftSideBearing
)
;
1153 height = GLYPHHEIGHTPIXELS(opci)((opci)->metrics.ascent + (opci)->metrics.descent);
1154 newWidth = GLYPHWIDTHPIXELS(pci)((pci)->metrics.rightSideBearing - (pci)->metrics.leftSideBearing
)
;
1155 newHeight = GLYPHHEIGHTPIXELS(pci)((pci)->metrics.ascent + (pci)->metrics.descent);
1156 if (!newWidth || !newHeight || !width || !height)
1157 return;
1158
1159 bpr = BYTES_PER_ROW(width, pFont->glyph)((pFont->glyph) == 1 ? (((width)+7)>>3) :(pFont->
glyph) == 2 ? ((((width)+15)>>3)&~1) :(pFont->glyph
) == 4 ? ((((width)+31)>>3)&~3) :(pFont->glyph) ==
8 ? ((((width)+63)>>3)&~7) : 0)
;
1160 newBpr = BYTES_PER_ROW(newWidth, pFont->glyph)((pFont->glyph) == 1 ? (((newWidth)+7)>>3) :(pFont->
glyph) == 2 ? ((((newWidth)+15)>>3)&~1) :(pFont->
glyph) == 4 ? ((((newWidth)+31)>>3)&~3) :(pFont->
glyph) == 8 ? ((((newWidth)+63)>>3)&~7) : 0)
;
1161
1162 if (widthMult > 0.0 && heightMult > 0.0 &&
1163 (widthMult < 1.0 || heightMult < 1.0))
1164 {
1165 /* We are reducing in one or both dimensions. In an attempt to
1166 reduce aliasing, we'll antialias by passing the original
1167 glyph through a low-pass box filter (which results in a
1168 grayscale image), then use error diffusion to create bitonal
1169 output in the resampling loop. */
1170
1171 /* First compute the sizes of the box filter */
1172 widthMult = ceil(1.0 / widthMult);
1173 heightMult = ceil(1.0 / heightMult);
1174 box_x = width / 2;
1175 box_y = height / 2;
1176 if (widthMult < (double)box_x) box_x = (int)widthMult;
1177 if (heightMult < (double)box_y) box_y = (int)heightMult;
1178 /* The pixmult value (below) is used to darken the image before
1179 we perform error diffusion: a necessary concession to the
1180 fact that it's very difficult to generate readable halftoned
1181 glyphs. The degree of darkening is proportional to the size
1182 of the blurring filter, hence inversely proportional to the
1183 darkness of the lightest gray that results from antialiasing.
1184 The result is that characters that exercise this logic (those
1185 generated by reducing from a larger source font) tend to err
1186 on the side of being too bold instead of being too light to
1187 be readable. */
1188 pixmult = box_x * box_y * 192;
1189
1190 if (box_x > 1 || box_y > 1)
1191 {
1192 /* Looks like we need to anti-alias. Create a workspace to
1193 contain the grayscale character plus an additional row and
1194 column for scratch */
1195 char_grayscale = malloc((width + 1) * (height + 1));
1196 if (char_grayscale)
1197 {
1198 diffusion_workspace = calloc((newWidth + 2) * 2, sizeof(int));
1199 if (!diffusion_workspace)
1200 {
1201 fprintf(stderrstderr, "Warning: Couldn't allocate diffusion"
1202 " workspace (%ld)\n",
1203 (newWidth + 2) * 2 * (unsigned long)sizeof(int));
1204 free(char_grayscale);
1205 char_grayscale = (unsigned char *)0;
1206 }
1207 /* Initialize our error diffusion workspace for later use */
1208 thisrow = diffusion_workspace + 1;
1209 nextrow = diffusion_workspace + newWidth + 3;
1210 } else {
1211 fprintf(stderrstderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1));
1212 }
1213 }
1214 }
1215
1216 if (char_grayscale)
1217 {
1218 /* We will be doing antialiasing. First copy the bitmap into
1219 our buffer, mapping input range [0,1] to output range
1220 [0,255]. */
1221 register unsigned char *srcptr, *dstptr;
1222 srcptr = (unsigned char *)bitmap;
1223 dstptr = char_grayscale;
1224 for (row = 0; row < height; row++)
1225 {
1226 for (col = 0; col < width; col++)
1227 *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0;
1228 srcptr += bpr; /* On to next row of source */
1229 dstptr++; /* Skip scratch column in dest */
1230 }
1231 if (box_x > 1)
1232 {
1233 /* Our box filter has a width > 1... let's filter the rows */
1234
1235 int right_width = box_x / 2;
1236 int left_width = box_x - right_width - 1;
1237
1238 for (row = 0; row < height; row++)
1239 {
1240 int sum = 0;
1241 int left_size = 0, right_size = 0;
1242
1243 srcptr = char_grayscale + (width + 1) * row;
1244 dstptr = char_grayscale + (width + 1) * height; /* scratch */
1245
1246 /* We've computed the shape of our full box filter. Now
1247 compute the right-hand part of the moving sum */
1248 for (right_size = 0; right_size < right_width; right_size++)
1249 sum += srcptr[right_size];
1250
1251 /* Now start moving the sum, growing the box filter, and
1252 dropping averages into our scratch buffer */
1253 for (left_size = 0; left_size < left_width; left_size++)
1254 {
1255 sum += srcptr[right_width];
1256 *dstptr++ = sum / (left_size + right_width + 1);
1257 srcptr++;
1258 }
1259
1260 /* The box filter has reached full width... continue
1261 computation of moving average until the right side
1262 hits the wall. */
1263 for (col = left_size; col + right_size < width; col++)
1264 {
1265 sum += srcptr[right_width];
1266 *dstptr++ = sum / box_x;
1267 sum -= srcptr[-left_width];
1268 srcptr++;
1269 }
1270
1271 /* Collapse the right side of the box filter */
1272 for (; right_size > 0; right_size--)
1273 {
1274 *dstptr++ = sum / (left_width + right_size);
1275 sum -= srcptr[-left_width];
1276 srcptr++;
1277 }
1278
1279 /* Done with the row... copy dest back over source */
1280 memmove(char_grayscale + (width + 1) * row,
1281 char_grayscale + (width + 1) * height,
1282 width);
1283 }
1284 }
1285 if (box_y > 1)
1286 {
1287 /* Our box filter has a height > 1... let's filter the columns */
1288
1289 int bottom_height = box_y / 2;
1290 int top_height = box_y - bottom_height - 1;
1291
1292 for (col = 0; col < width; col++)
1293 {
1294 int sum = 0;
1295 int top_size = 0, bottom_size = 0;
1296
1297 srcptr = char_grayscale + col;
1298 dstptr = char_grayscale + width; /* scratch */
1299
1300 /* We've computed the shape of our full box filter. Now
1301 compute the bottom part of the moving sum */
1302 for (bottom_size = 0;
1303 bottom_size < bottom_height;
1304 bottom_size++)
1305 sum += srcptr[bottom_size * (width + 1)];
1306
1307 /* Now start moving the sum, growing the box filter, and
1308 dropping averages into our scratch buffer */
1309 for (top_size = 0; top_size < top_height; top_size++)
1310 {
1311 sum += srcptr[bottom_height * (width + 1)];
1312 *dstptr = sum / (top_size + bottom_height + 1);
1313 dstptr += width + 1;
1314 srcptr += width + 1;
1315 }
1316
1317 /* The box filter has reached full height... continue
1318 computation of moving average until the bottom
1319 hits the wall. */
1320 for (row = top_size; row + bottom_size < height; row++)
1321 {
1322 sum += srcptr[bottom_height * (width + 1)];
1323 *dstptr = sum / box_y;
1324 dstptr += width + 1;
1325 sum -= srcptr[-top_height * (width + 1)];
1326 srcptr += width + 1;
1327 }
1328
1329 /* Collapse the bottom of the box filter */
1330 for (; bottom_size > 0; bottom_size--)
1331 {
1332 *dstptr = sum / (top_height + bottom_size);
1333 dstptr += width + 1;
1334 sum -= srcptr[-top_height * (width + 1)];
1335 srcptr += width + 1;
1336 }
1337
1338 /* Done with the column... copy dest back over source */
1339
1340 dstptr = char_grayscale + col;
1341 srcptr = char_grayscale + width; /* scratch */
1342 for (row = 0; row < height; row++)
1343 {
1344 *dstptr = *srcptr;
1345 dstptr += width + 1;
1346 srcptr += width + 1;
1347 }
1348 }
1349 }
1350
1351 /* Increase the grayvalue to increase ink a bit */
1352 srcptr = char_grayscale;
1353 for (row = 0; row < height; row++)
1354 {
1355 for (col = 0; col < width; col++)
1356 {
1357 register int pixvalue = (int)*srcptr * pixmult / 256;
1358 if (pixvalue > 255) pixvalue = 255;
1359 *srcptr = pixvalue;
1360 srcptr++;
1361 }
1362 srcptr++;
1363 }
1364 }
1365
1366 /* Compute the increment values for the resampling loop */
1367 TRANSFORM_POINT(inv_xform, 1, 0, point)((point)[0] = (inv_xform)[0] * (1) + (inv_xform)[2] * (0), (point
)[1] = (inv_xform)[1] * (1) + (inv_xform)[3] * (0))
;
1368 deltaX = (INT32)(point[0] * 65536.0);
1369 deltaY = (INT32)(-point[1] * 65536.0);
1370
1371 /* Resampling loop: resamples original glyph for generation of new
1372 glyph in transformed coordinate system. */
1373
1374 for (row = 0; row < newHeight; row++)
1375 {
1376 /* Compute inverse transformation for start of this row */
1377 TRANSFORM_POINT(inv_xform,((point)[0] = (inv_xform)[0] * ((double)(pci->metrics.leftSideBearing
) + .5) + (inv_xform)[2] * ((double)(pci->metrics.ascent -
row) - .5), (point)[1] = (inv_xform)[1] * ((double)(pci->
metrics.leftSideBearing) + .5) + (inv_xform)[3] * ((double)(pci
->metrics.ascent - row) - .5))
1378 (double)(pci->metrics.leftSideBearing) + .5,((point)[0] = (inv_xform)[0] * ((double)(pci->metrics.leftSideBearing
) + .5) + (inv_xform)[2] * ((double)(pci->metrics.ascent -
row) - .5), (point)[1] = (inv_xform)[1] * ((double)(pci->
metrics.leftSideBearing) + .5) + (inv_xform)[3] * ((double)(pci
->metrics.ascent - row) - .5))
1379 (double)(pci->metrics.ascent - row) - .5,((point)[0] = (inv_xform)[0] * ((double)(pci->metrics.leftSideBearing
) + .5) + (inv_xform)[2] * ((double)(pci->metrics.ascent -
row) - .5), (point)[1] = (inv_xform)[1] * ((double)(pci->
metrics.leftSideBearing) + .5) + (inv_xform)[3] * ((double)(pci
->metrics.ascent - row) - .5))
1380 point)((point)[0] = (inv_xform)[0] * ((double)(pci->metrics.leftSideBearing
) + .5) + (inv_xform)[2] * ((double)(pci->metrics.ascent -
row) - .5), (point)[1] = (inv_xform)[1] * ((double)(pci->
metrics.leftSideBearing) + .5) + (inv_xform)[3] * ((double)(pci
->metrics.ascent - row) - .5))
;
1381
1382 /* Adjust for coordinate system to get resampling point */
1383 point[0] -= opci->metrics.leftSideBearing;
1384 point[1] = opci->metrics.ascent - point[1];
1385
1386 /* Convert to integer coordinates */
1387 xValue = (INT32)(point[0] * 65536.0);
1388 yValue = (INT32)(point[1] * 65536.0);
1389
1390 if (char_grayscale)
1391 {
1392 INT32 *temp;
1393 for (col = 0; col < newWidth; col++)
1394 {
1395 register int x = xValue >> 16, y = yValue >> 16;
1396 int pixvalue, error;
1397
1398 pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ?
1399 char_grayscale[x + y * (width + 1)] : 0) +
1400 thisrow[col] / 16;
1401 if (pixvalue > 255) pixvalue = 255;
1402 else if (pixvalue < 0) pixvalue = 0;
1403
1404 /* Choose the bit value and set resulting error value */
1405 if (pixvalue >= 128)
1406 {
1407 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1408 error = pixvalue - 255;
1409 }
1410 else
1411 error = -pixvalue;
1412
1413 /* Diffuse the error */
1414 thisrow[col + 1] += error * 7;
1415 nextrow[col - 1] += error * 3;
1416 nextrow[col] += error * 5;
1417 nextrow[col + 1] = error;
1418
1419 xValue += deltaX;
1420 yValue += deltaY;
1421 }
1422
1423 /* Add in error values that fell off either end */
1424 nextrow[0] += nextrow[-1];
1425 nextrow[newWidth - 2] += thisrow[newWidth];
1426 nextrow[newWidth - 1] += nextrow[newWidth];
1427 nextrow[newWidth] = 0;
1428
1429 temp = nextrow;
1430 nextrow = thisrow;
1431 thisrow = temp;
1432 nextrow[-1] = nextrow[0] = 0;
1433 }
1434 else
1435 {
1436 for (col = 0; col < newWidth; col++)
1437 {
1438 register int x = xValue >> 16, y = yValue >> 16;
1439
1440 if (x >= 0 && x < width && y >= 0 && y < height)
1441 {
1442 /* Use point-sampling for rescaling. */
1443
1444 if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7])
1445 newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
1446 }
1447
1448 xValue += deltaX;
1449 yValue += deltaY;
1450 }
1451 }
1452 }
1453
1454
1455 if (char_grayscale)
1456 {
1457 free(char_grayscale);
1458 free(diffusion_workspace);
1459 }
1460}
1461
1462static FontPtr
1463BitmapScaleBitmaps(FontPtr pf, /* scaled font */
1464 FontPtr opf, /* originating font */
1465 double widthMult, /* glyphs width scale factor */
1466 double heightMult, /* glyphs height scale factor */
1467 FontScalablePtr vals)
1468{
1469 register int i;
1470 int nchars = 0;
1471 char *glyphBytes;
1472 BitmapFontPtr bitmapFont,
1473 obitmapFont;
1474 CharInfoPtr pci,
1475 opci;
1476 FontInfoPtr pfi;
1477 int glyph;
1478 unsigned bytestoalloc = 0;
1479 int firstCol, lastCol, firstRow, lastRow;
1480
1481 double xform[4], inv_xform[4];
1482 double xmult, ymult;
1483
1484 bitmapFont = (BitmapFontPtr) pf->fontPrivate;
1485 obitmapFont = (BitmapFontPtr) opf->fontPrivate;
1486
1487 if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
1488 inv_xform, &xmult, &ymult))
1489 goto bail;
1490
1491 pfi = &pf->info;
1492 firstCol = pfi->firstCol;
1493 lastCol = pfi->lastCol;
1494 firstRow = pfi->firstRow;
1495 lastRow = pfi->lastRow;
1496
1497 nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
1498 glyph = pf->glyph;
1499 for (i = 0; i < nchars; i++)
1500 {
1501 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)(bitmapFont->encoding[(i)/128]?(bitmapFont->encoding[(i
)/128][(i)%128]):0)
))
1502 bytestoalloc += BYTES_FOR_GLYPH(pci, glyph)(((pci)->metrics.ascent + (pci)->metrics.descent) * ((glyph
) == 1 ? (((((pci)->metrics.rightSideBearing - (pci)->metrics
.leftSideBearing))+7)>>3) :(glyph) == 2 ? ((((((pci)->
metrics.rightSideBearing - (pci)->metrics.leftSideBearing)
)+15)>>3)&~1) :(glyph) == 4 ? ((((((pci)->metrics
.rightSideBearing - (pci)->metrics.leftSideBearing))+31)>>
3)&~3) :(glyph) == 8 ? ((((((pci)->metrics.rightSideBearing
- (pci)->metrics.leftSideBearing))+63)>>3)&~7) :
0))
;
1503 }
1504
1505 /* Do we add the font malloc stuff for VALUE ADDED ? */
1506 /* Will need to remember to free in the Unload routine */
1507
1508
1509 bitmapFont->bitmaps = calloc(1, bytestoalloc);
1510 if (!bitmapFont->bitmaps) {
1511 fprintf(stderrstderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
1512 goto bail;
1513 }
1514
1515 glyphBytes = bitmapFont->bitmaps;
1516 for (i = 0; i < nchars; i++)
1517 {
1518 if ((pci = ACCESSENCODING(bitmapFont->encoding, i)(bitmapFont->encoding[(i)/128]?(bitmapFont->encoding[(i
)/128][(i)%128]):0)
) &&
1519 (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i))(obitmapFont->encoding[((((i)/(lastCol - firstCol + 1) + firstRow
- opf->info.firstRow) * (opf->info.lastCol - opf->info
.firstCol + 1) + (i)%(lastCol - firstCol + 1) + firstCol - opf
->info.firstCol))/128]?(obitmapFont->encoding[((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))/128][((((i)/(lastCol
- firstCol + 1) + firstRow - opf->info.firstRow) * (opf->
info.lastCol - opf->info.firstCol + 1) + (i)%(lastCol - firstCol
+ 1) + firstCol - opf->info.firstCol))%128]):0)
))
1520 {
1521 pci->bits = glyphBytes;
1522 ScaleBitmap (pf, opci, pci, inv_xform,
1523 widthMult, heightMult);
1524 glyphBytes += BYTES_FOR_GLYPH(pci, glyph)(((pci)->metrics.ascent + (pci)->metrics.descent) * ((glyph
) == 1 ? (((((pci)->metrics.rightSideBearing - (pci)->metrics
.leftSideBearing))+7)>>3) :(glyph) == 2 ? ((((((pci)->
metrics.rightSideBearing - (pci)->metrics.leftSideBearing)
)+15)>>3)&~1) :(glyph) == 4 ? ((((((pci)->metrics
.rightSideBearing - (pci)->metrics.leftSideBearing))+31)>>
3)&~3) :(glyph) == 8 ? ((((((pci)->metrics.rightSideBearing
- (pci)->metrics.leftSideBearing))+63)>>3)&~7) :
0))
;
1525 }
1526 }
1527 return pf;
1528
1529bail:
1530 if (pf)
1531 free(pf);
1532 if (bitmapFont) {
1533 free(bitmapFont->metrics);
1534 free(bitmapFont->ink_metrics);
1535 free(bitmapFont->bitmaps);
1536 if(bitmapFont->encoding)
1537 for(i=0; i<NUM_SEGMENTS(nchars)(((nchars)+128 -1)/128); i++)
1538 free(bitmapFont->encoding[i]);
1539 free(bitmapFont->encoding);
1540 }
1541 return NULL((void*)0);
1542}
1543
1544/* ARGSUSED */
1545int
1546BitmapOpenScalable (FontPathElementPtr fpe,
1547 FontPtr *pFont,
1548 int flags,
1549 FontEntryPtr entry,
1550 char *fileName, /* unused */
1551 FontScalablePtr vals,
1552 fsBitmapFormat format,
1553 fsBitmapFormatMask fmask,
1554 FontPtr non_cachable_font) /* We don't do licensing */
1555{
1556 FontScalableRec best;
1557 FontPtr font = NullFont((FontPtr) 0);
1558 double dx, sdx,
1559 dy, sdy,
1560 savedX, savedY;
1561 FontPropPtr props;
1562 char *isStringProp = NULL((void*)0);
1563 int propCount;
1564 int status;
1565 long sWidth;
1566
1567 FontEntryPtr scaleFrom;
1568 FontPathElementPtr scaleFPE = NULL((void*)0);
1569 FontPtr sourceFont;
1570 char fontName[MAXFONTNAMELEN1024];
1571
1572 /* Can't deal with mix-endian fonts yet */
1573
1574
1575 /* Reject outrageously small font sizes to keep the math from
1576 blowing up. */
1577 if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 ||
1578 get_matrix_horizontal_component(vals->pixel_matrix) < 1.0)
1579 return BadFontName83;
1580
1581 scaleFrom = FindBestToScale(fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy,
1582 &scaleFPE);
1583
1584 if (!scaleFrom)
1585 return BadFontName83;
1586
1587 status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll0x1, scaleFrom,
1588 format, fmask);
1589
1590 if (status != Successful85)
1591 return BadFontName83;
1592
1593 if (!vals->width)
1594 vals->width = best.width * dx;
1595
1596 /* Compute the scaled font */
1597
1598 savedX = dx;
1599 savedY = dy;
1600 font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth);
1601 if (font)
1602 font = BitmapScaleBitmaps(font, sourceFont, savedX, savedY, vals);
1603
1604 if (!font)
1605 {
1606 if (!sourceFont->refcnt)
1607 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1608 return AllocError80;
1609 }
1610
1611 /* Prepare font properties for the new font */
1612
1613 strcpy (fontName, scaleFrom->name.name);
1614 FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE3);
1615
1616 propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals,
1617 dx, dy, sdx, sdy, sWidth, &props,
1618 &isStringProp);
1619
1620 if (!sourceFont->refcnt)
1621 FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
1622
1623 font->info.props = props;
1624 font->info.nprops = propCount;
1625 font->info.isStringProp = isStringProp;
1626
1627 if (propCount && (!props || !isStringProp))
1628 {
1629 bitmapUnloadScalable(font);
1630 return AllocError80;
1631 }
1632
1633 *pFont = font;
1634 return Successful85;
1635}
1636
1637int
1638BitmapGetInfoScalable (FontPathElementPtr fpe,
1639 FontInfoPtr pFontInfo,
1640 FontEntryPtr entry,
1641 FontNamePtr fontName,
1642 char *fileName,
1643 FontScalablePtr vals)
1644{
1645 FontPtr pfont;
1646 int flags = 0;
1647 long format = 0; /* It doesn't matter what format for just info */
1648 long fmask = 0;
1649 int ret;
1650
1651 ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals,
1652 format, fmask, NULL((void*)0));
1653 if (ret != Successful85)
1654 return ret;
1655 *pFontInfo = pfont->info;
1656
1657 pfont->info.nprops = 0;
1658 pfont->info.props = NULL((void*)0);
1659 pfont->info.isStringProp = NULL((void*)0);
1660
1661 (*pfont->unload_font)(pfont);
1662 return Successful85;
1663}
1664
1665static void
1666bitmapUnloadScalable (FontPtr pFont)
1667{
1668 BitmapFontPtr bitmapFont;
1669 FontInfoPtr pfi;
1670 int i, nencoding;
1671
1672 bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
1673 pfi = &pFont->info;
1674 free (pfi->props);
1675 free (pfi->isStringProp);
1676 if(bitmapFont->encoding) {
1677 nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
1678 (pFont->info.lastRow - pFont->info.firstRow + 1);
1679 for(i=0; i<NUM_SEGMENTS(nencoding)(((nencoding)+128 -1)/128); i++)
1680 free(bitmapFont->encoding[i]);
1681 }
1682 free (bitmapFont->encoding);
1683 free (bitmapFont->bitmaps);
1684 free (bitmapFont->ink_metrics);
1685 free (bitmapFont->metrics);
1686 free (pFont->fontPrivate);
1687 DestroyFontRec (pFont);
1688}