1
/* $Xorg: charinfo.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ */
4
Copyright 1990, 1991, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Except as contained in this notice, the name of The Open Group shall not be
23
used in advertising or otherwise to promote the sale, use or other dealings
24
in this Software without prior written authorization from The Open Group.
26
* Copyright 1990, 1991 Network Computing Devices;
27
* Portions Copyright 1987 by Digital Equipment Corporation
29
* Permission to use, copy, modify, distribute, and sell this software and
30
* its documentation for any purpose is hereby granted without fee, provided
31
* that the above copyright notice appear in all copies and that both that
32
* copyright notice and this permission notice appear in supporting
33
* documentation, and that the names of Network Computing Devices, or Digital
34
* not be used in advertising or publicity pertaining to distribution
35
* of the software without specific, written prior permission.
37
* NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
38
* REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
39
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
40
* OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
41
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
42
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
43
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
47
* Defines GetExtents() and GetBitmaps(), which are
48
* called from routines in fontinfo.c.
49
* This file was once on the other side of
50
* the font library interface as util/fsfuncs.c.
52
/* $XFree86: xc/programs/xfs/difs/charinfo.c,v 1.12 2001/12/14 20:01:33 dawes Exp $ */
56
#include "fontstruct.h"
58
#include "clientstr.h"
63
extern void TwoByteSwap(unsigned char *, int);
64
extern void FourByteSwap(unsigned char *, int);
66
#define GLWIDTHBYTESPADDED(bits,nbytes) \
67
((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
68
:(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
69
:(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
70
:(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
73
#define GLYPH_SIZE(ch, nbytes) \
74
GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
75
(ch)->metrics.leftSideBearing, (nbytes))
77
#define n2dChars(pfi) (((pfi)->lastRow - (pfi)->firstRow + 1) * \
78
((pfi)->lastCol - (pfi)->firstCol + 1))
81
static CharInfoRec junkDefault;
84
typedef int (*MetricsFunc)(FontPtr, unsigned long, unsigned char *,
85
FontEncoding, unsigned long *, CharInfoPtr *);
93
int *nump, /* return */
94
CharInfoPtr **retp) /* return */
96
CharInfoPtr *xchars, *xci;
98
FontInfoPtr pinfo = &pfont->info;
101
int firstCol = pinfo->firstCol;
102
int firstRow = pinfo->firstRow;
103
int lastRow = pinfo->lastRow;
104
int lastCol = pinfo->lastCol;
105
fsRange local_range, *rp;
107
FontEncoding encoding;
109
unsigned long glyphCount;
110
unsigned short defaultCh;
111
CharInfoPtr defaultPtr;
112
MetricsFunc metrics_func;
117
if (num_ranges == 0) {
119
nchars = n2dChars(pinfo);
121
nchars = lastCol - firstCol + 1;
122
local_range.min_char_low = firstCol;
123
local_range.min_char_high = firstRow;
124
local_range.max_char_low = lastCol;
125
local_range.max_char_high = lastRow;
126
range = &local_range;
130
for (i = 0, rp = range; i < num_ranges; i++, rp++) {
131
if (rp->min_char_high > rp->max_char_high ||
132
rp->min_char_low > rp->max_char_low)
134
nchars += (rp->max_char_high - rp->min_char_high + 1) *
135
(rp->max_char_low - rp->min_char_low + 1);
139
xchars = (CharInfoPtr *) fsalloc (sizeof (CharInfoPtr) * nchars);
142
bzero (xchars, sizeof (CharInfoPtr) * nchars);
145
metrics_func = (MetricsFunc)pfont->get_metrics;
147
metrics_func = pfont->get_glyphs;
150
encoding = Linear16Bit;
152
encoding = TwoD16Bit;
153
defaultCh = pinfo->defaultCh;
154
ch[0] = defaultCh >> 8;
155
ch[1] = defaultCh & 0xff;
156
/* get the default character */
157
(*metrics_func) (pfont, 1, ch, encoding,
158
&glyphCount, &defaultPtr);
162
/* for each range, get each character individually, undoing the
163
default character substitution so we get zero metrics for
164
non-existent characters. */
165
for (i = 0, rp = range; i < num_ranges; i++, rp++) {
166
for (r = rp->min_char_high; r <= rp->max_char_high; r++)
168
for (c = rp->min_char_low; c <= rp->max_char_low; c++) {
171
err = (*metrics_func) (pfont, 1, ch, encoding,
173
if (err != Successful)
179
if (glyphCount != 1 ||
180
(*xci == defaultPtr && defaultCh != ((r<<8)+c)))
197
unsigned long num_ranges,
199
unsigned long *num_extents, /* return */
200
fsXCharInfo **data) /* return */
206
CharInfoPtr *xchars, *xchars_cur;
213
err = getCharInfos (pfont, num_ranges, range,
214
client->major_version > 1 ? TRUE : FALSE,
216
if (err != Successful)
219
size = SIZEOF(fsXCharInfo) * nchars;
220
pci = (char *) fsalloc(size);
226
ci = (fsXCharInfo *) pci;
227
*num_extents = nchars;
233
cilocal.ascent = xci->metrics.ascent;
234
cilocal.descent = xci->metrics.descent;
235
cilocal.left = xci->metrics.leftSideBearing;
236
cilocal.right = xci->metrics.rightSideBearing;
237
cilocal.width = xci->metrics.characterWidth;
238
cilocal.attributes = xci->metrics.attributes;
239
memcpy(pci, &cilocal, SIZEOF(fsXCharInfo));
240
pci += SIZEOF(fsXCharInfo);
256
unsigned long num_ranges,
259
unsigned long *num_glyphs,
260
fsOffset32 **offsets,
265
fsOffset32 *lengths, *l;
266
unsigned long size = 0;
269
int bitorder, byteorder, scanlinepad, scanlineunit, mappad;
270
int height = 0, dstbpr = 0, charsize = 0;
271
int dst_off = 0, src_off;
272
Bool contiguous, reformat;
274
int src_glyph_pad = pfont->glyph;
275
int src_bit_order = pfont->bit;
276
int src_byte_order = pfont->byte;
278
int max_ascent = 0, max_descent = 0;
279
int min_left = 0, max_right;
281
int lshift = 0, rshift = 0, dst_left_bytes = 0, src_left_bytes = 0;
284
unsigned char bits1, bits2;
289
CharInfoPtr *bitChars, *bitCharsFree, bitc;
290
CharInfoPtr *inkChars, *inkCharsFree = 0, inkc;
291
FontInfoPtr pinfo = &pfont->info;
292
xCharInfo *bitm, *inkm;
294
err = CheckFSFormat(format, (fsBitmapFormatMask) ~ 0,
295
&bitorder, &byteorder, &scanlineunit, &scanlinepad, &mappad);
297
if (err != Successful)
303
err = getCharInfos (pfont, num_ranges, range, FALSE, &nchars, &bitCharsFree);
305
if (err != Successful)
308
/* compute dstbpr for padded out fonts */
309
reformat = bitorder != src_bit_order || byteorder != src_byte_order;
311
/* we need the ink metrics when shrink-wrapping a TE font (sigh),
312
* but only for protocol version > 1 */
313
if (mappad != BitmapFormatImageRectMax &&
315
client->major_version > 1)
317
err = getCharInfos (pfont, num_ranges, range, TRUE, &nchars, &inkCharsFree);
318
if (err != Successful)
320
fsfree (bitCharsFree);
326
/* get space for glyph offsets */
327
lengths = (fsOffset32 *) fsalloc(SIZEOF(fsOffset32) * nchars);
329
fsfree (bitCharsFree);
330
fsfree (inkCharsFree);
336
case BitmapFormatImageRectMax:
337
max_ascent = FONT_MAX_ASCENT(pinfo);
338
max_descent = FONT_MAX_DESCENT(pinfo);
339
height = max_ascent + max_descent;
340
/* do font ascent and font descent match bitmap bounds ? */
341
if (height != pinfo->minbounds.ascent + pinfo->minbounds.descent)
344
case BitmapFormatImageRectMaxWidth:
345
min_left = FONT_MIN_LEFT(pinfo);
346
max_right = FONT_MAX_RIGHT(pinfo);
347
if (min_left != pinfo->maxbounds.leftSideBearing)
349
if (max_right != pinfo->maxbounds.rightSideBearing)
351
dstbpr = GLWIDTHBYTESPADDED(max_right - min_left, scanlinepad);
353
case BitmapFormatImageRectMin:
356
if (mappad == BitmapFormatImageRectMax)
357
charsize = dstbpr * height;
362
inkChars = inkCharsFree;
363
bitChars = bitCharsFree;
364
for (i = 0; i < nchars; i++)
366
inkc = bitc = *bitChars++;
367
/* when ink metrics != bitmap metrics, use ink metrics */
372
* Do not repad characters with no bits except for those
373
* with non-zero width.
375
if (bitc && (bitc->bits || bitc->metrics.characterWidth)) {
377
gdata = (pointer) bitc->bits;
378
if ((char *) gdata + size != bitc->bits)
380
if (mappad == BitmapFormatImageRectMin)
381
dstbpr = GLYPH_SIZE(inkc, scanlinepad);
382
if (dstbpr != GLYPH_SIZE(bitc, src_glyph_pad)) reformat = TRUE;
383
if (mappad != BitmapFormatImageRectMax)
385
height = inkc->metrics.ascent + inkc->metrics.descent;
386
charsize = height * dstbpr;
388
l->length = charsize;
395
if (contiguous && !reformat)
397
*num_glyphs = nchars;
402
fsfree (bitCharsFree);
403
fsfree (inkCharsFree);
408
gdata = (pointer) fsalloc(size);
410
fsfree (bitCharsFree);
411
fsfree (inkCharsFree);
415
bzero ((char *) gdata, size);
424
/* finally do the work */
425
bitChars = bitCharsFree;
426
inkChars = inkCharsFree;
427
for (i = 0; i < nchars; i++, l++)
429
inkc = bitc = *bitChars++;
433
/* ignore missing chars */
437
bitm = &bitc->metrics;
438
inkm = &inkc->metrics;
440
/* start address for the destination of bits for this char */
444
if (mappad == BitmapFormatImageRectMax)
445
height = max_ascent + max_descent;
447
height = inkm->ascent + inkm->descent;
449
/* adjust destination and calculate shift offsets */
451
case BitmapFormatImageRectMax:
452
/* leave the first padded rows blank */
453
if (max_ascent > inkm->ascent)
455
height -= (max_ascent - inkm->ascent);
456
dstp += dstbpr * (max_ascent - inkm->ascent);
458
if (max_descent > inkm->descent)
460
height -= (max_descent - inkm->descent);
463
case BitmapFormatImageRectMaxWidth:
464
dst_off = inkm->leftSideBearing - min_left;
465
if (dst_off < 0) dst_off = 0;
467
case BitmapFormatImageRectMin:
469
dstbpr = GLYPH_SIZE(inkc, scanlinepad);
473
srcbpr = GLYPH_SIZE (bitc, src_glyph_pad);
474
srcp = (unsigned char *) bitc->bits;
480
srcp += (bitm->ascent - inkm->ascent) * srcbpr;
481
src_off = inkm->leftSideBearing - bitm->leftSideBearing;
484
dst_left_bytes = dst_off >> 3;
486
src_left_bytes = src_off >> 3;
489
/* minimum of source/dest bytes per row */
490
width = srcbpr - src_left_bytes;
491
if (width > dstbpr - dst_left_bytes)
492
width = dstbpr - dst_left_bytes;
493
/* extra bytes in source and dest for padding */
494
src_extra = srcbpr - width - src_left_bytes;
495
dst_extra = dstbpr - width - dst_left_bytes;
497
#define MSBBitLeft(b,c) ((b) << (c))
498
#define MSBBitRight(b,c) ((b) >> (c))
499
#define LSBBitLeft(b,c) ((b) >> (c))
500
#define LSBBitRight(b,c) ((b) << (c))
502
if (dst_off == src_off)
504
if (srcbpr == dstbpr && src_left_bytes == dst_left_bytes)
507
memmove( dstp, srcp, r);
512
for (r = height; r; r--)
514
dstp += dst_left_bytes;
515
srcp += src_left_bytes;
516
for (w = width; w; w--)
525
if (dst_off > src_off)
527
rshift = dst_off - src_off;
532
lshift = src_off - dst_off;
534
/* run the loop one fewer time if necessary */
535
if (src_extra <= dst_extra)
544
for (r = inkm->ascent + inkm->descent; r; r--)
546
dstp += dst_left_bytes;
547
srcp += src_left_bytes;
549
/* fetch first part of source when necessary */
550
if (dst_off < src_off)
553
* XXX I bet this does not work when
554
* src_bit_order != src_byte_order && scanlineunit > 1
556
for (w = width; w; w--)
559
if (src_bit_order == MSBFirst)
561
*dstp++ = MSBBitRight(bits1, rshift) |
562
MSBBitLeft (bits2, lshift);
566
*dstp++ = LSBBitRight(bits1, rshift) |
567
LSBBitLeft (bits2, lshift);
571
/* get the last few bits if we have a place to store them */
574
if (src_bit_order == MSBFirst)
575
*dstp = MSBBitLeft (bits2, lshift);
577
*dstp = LSBBitLeft (bits2, lshift);
583
/* skip the amount we just filled in */
588
/* now do the bit, byte, word swapping */
589
if (bitorder != src_bit_order)
590
BitOrderInvert(gdata, size);
591
if (byteorder != src_byte_order)
593
if (scanlineunit == 2)
594
TwoByteSwap(gdata, size);
595
else if (scanlineunit == 4)
596
FourByteSwap(gdata, size);
598
fsfree (bitCharsFree);
599
fsfree (inkCharsFree);
600
*num_glyphs = nchars;
613
fsBitmapFormat format,
615
unsigned long num_ranges,
618
unsigned long *num_glyphs,
619
fsOffset32 **offsets,
630
err = LoadGlyphRanges(client, pfont, TRUE, num_ranges * 2, 0,
633
if (err != Successful)
636
return packGlyphs (client, pfont, format, flags,
637
num_ranges, range, size, num_glyphs,
638
offsets, data, freeData);