summaryrefslogtreecommitdiff
path: root/difs/charinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'difs/charinfo.c')
-rw-r--r--difs/charinfo.c631
1 files changed, 631 insertions, 0 deletions
diff --git a/difs/charinfo.c b/difs/charinfo.c
new file mode 100644
index 0000000..f664311
--- /dev/null
+++ b/difs/charinfo.c
@@ -0,0 +1,631 @@
+/* $Xorg: charinfo.c,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ */
+/*
+
+Copyright 1990, 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the names of Network Computing Devices, or Digital
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
+ * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+/*
+ * Defines GetExtents() and GetBitmaps(), which are
+ * called from routines in fontinfo.c.
+ * This file was once on the other side of
+ * the font library interface as util/fsfuncs.c.
+ */
+
+#include <X11/Xos.h>
+#include "misc.h"
+#include "fontstruct.h"
+#include "clientstr.h"
+#define FSMD_H
+#include "FSproto.h"
+
+extern void TwoByteSwap();
+extern void FourByteSwap();
+
+#define GLWIDTHBYTESPADDED(bits,nbytes) \
+ ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
+ :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
+ :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
+ :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
+ : 0)
+
+#define GLYPH_SIZE(ch, nbytes) \
+ GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
+ (ch)->metrics.leftSideBearing, (nbytes))
+
+#define n2dChars(pfi) (((pfi)->lastRow - (pfi)->firstRow + 1) * \
+ ((pfi)->lastCol - (pfi)->firstCol + 1))
+
+static CharInfoRec junkDefault;
+
+static int
+getCharInfos (pfont, num_ranges, range, ink_metrics, nump, retp)
+ FontPtr pfont;
+ int num_ranges;
+ fsRange *range;
+ Bool ink_metrics;
+ int *nump; /* return */
+ CharInfoPtr **retp; /* return */
+{
+ CharInfoPtr *xchars, *xci;
+ int nchars;
+ FontInfoPtr pinfo = &pfont->info;
+ unsigned int r, c;
+ unsigned char ch[2];
+ int firstCol = pinfo->firstCol;
+ int firstRow = pinfo->firstRow;
+ int lastRow = pinfo->lastRow;
+ int lastCol = pinfo->lastCol;
+ int minCol, maxCol;
+ int num_cols = lastCol - firstCol + 1;
+ fsRange local_range, *rp;
+ int i;
+ FontEncoding encoding;
+ int err;
+ unsigned long glyphCount;
+ unsigned short defaultCh;
+ CharInfoPtr defaultPtr;
+ int (*metrics_func) ();
+
+ /*
+ * compute nchars
+ */
+ if (num_ranges == 0) {
+ if (lastRow)
+ nchars = n2dChars(pinfo);
+ else
+ nchars = lastCol - firstCol + 1;
+ local_range.min_char_low = firstCol;
+ local_range.min_char_high = firstRow;
+ local_range.max_char_low = lastCol;
+ local_range.max_char_high = lastRow;
+ range = &local_range;
+ num_ranges = 1;
+ } else {
+ nchars = 0;
+ for (i = 0, rp = range; i < num_ranges; i++, rp++) {
+ if (rp->min_char_high > rp->max_char_high ||
+ rp->min_char_low > rp->max_char_low)
+ return BadCharRange;
+ nchars += (rp->max_char_high - rp->min_char_high + 1) *
+ (rp->max_char_low - rp->min_char_low + 1);
+ }
+ }
+
+ xchars = (CharInfoPtr *) fsalloc (sizeof (CharInfoPtr) * nchars);
+ if (!xchars)
+ return AllocError;
+
+ if (ink_metrics)
+ metrics_func = pfont->get_metrics;
+ else
+ metrics_func = pfont->get_glyphs;
+
+ xci = xchars;
+ encoding = Linear16Bit;
+ if (lastRow)
+ encoding = TwoD16Bit;
+ defaultCh = pinfo->defaultCh;
+ ch[0] = defaultCh >> 8;
+ ch[1] = defaultCh & 0xff;
+ /* get the default character */
+ (*metrics_func) (pfont, 1, ch, encoding,
+ &glyphCount, &defaultPtr);
+ if (glyphCount != 1)
+ defaultPtr = 0;
+
+ /* for each range, get each character individually, undoing the
+ default character substitution so we get zero metrics for
+ non-existent characters. */
+ for (i = 0, rp = range; i < num_ranges; i++, rp++) {
+ for (r = rp->min_char_high; r <= rp->max_char_high; r++)
+ {
+ for (c = rp->min_char_low; c <= rp->max_char_low; c++) {
+ ch[0] = r;
+ ch[1] = c;
+ err = (*metrics_func) (pfont, 1, ch, encoding,
+ &glyphCount, xci);
+ if (err != Successful)
+ {
+ fsfree (xchars);
+ return err;
+ }
+ if (glyphCount != 1 ||
+ *xci == defaultPtr && defaultCh != ((r<<8)+c))
+ *xci = &junkDefault;
+ xci++;
+ }
+ }
+ }
+ *retp = xchars;
+ *nump = nchars;
+ return Successful;
+}
+
+int
+GetExtents(client, pfont, flags, num_ranges, range, num_extents, data)
+ ClientPtr client;
+ FontPtr pfont;
+ Mask flags;
+ unsigned long num_ranges;
+ fsRange *range;
+ unsigned long *num_extents; /* return */
+ fsXCharInfo **data; /* return */
+{
+ unsigned long size;
+ fsXCharInfo *ci;
+ fsXCharInfo cilocal;
+ char *pci;
+ CharInfoPtr *xchars, *xchars_cur;
+ CharInfoPtr xci;
+ int nchars;
+ int err;
+
+ if (flags & LoadAll)
+ num_ranges = 0;
+ err = getCharInfos (pfont, num_ranges, range,
+ client->major_version > 1 ? TRUE : FALSE,
+ &nchars, &xchars);
+ if (err != Successful)
+ return err;
+
+ size = SIZEOF(fsXCharInfo) * nchars;
+ pci = (char *) fsalloc(size);
+ if (!pci) {
+ fsfree (xchars);
+ return AllocError;
+ }
+
+ ci = (fsXCharInfo *) pci;
+ *num_extents = nchars;
+
+ /* pack the data */
+ xchars_cur = xchars;
+ while (nchars--) {
+ xci = *xchars_cur++;
+ cilocal.ascent = xci->metrics.ascent;
+ cilocal.descent = xci->metrics.descent;
+ cilocal.left = xci->metrics.leftSideBearing;
+ cilocal.right = xci->metrics.rightSideBearing;
+ cilocal.width = xci->metrics.characterWidth;
+ cilocal.attributes = xci->metrics.attributes;
+ memcpy(pci, &cilocal, SIZEOF(fsXCharInfo));
+ pci += SIZEOF(fsXCharInfo);
+ }
+
+ fsfree (xchars);
+
+ *data = ci;
+
+ return Successful;
+}
+
+static int
+packGlyphs (client, pfont, format, flags, num_ranges, range, tsize, num_glyphs,
+ offsets, data, freeData)
+ ClientPtr client;
+ FontPtr pfont;
+ int format;
+ Mask flags;
+ unsigned long num_ranges;
+ fsRange *range;
+ int *tsize;
+ unsigned long *num_glyphs;
+ fsOffset32 **offsets;
+ pointer *data;
+ int *freeData;
+{
+ int i;
+ fsOffset32 *lengths, *l;
+ unsigned long size = 0;
+ pointer gdata,
+ gd;
+ int bitorder, byteorder, scanlinepad, scanlineunit, mappad;
+ int height, dstbpr, charsize;
+ int dst_off, src_off;
+ Bool contiguous, reformat;
+ long nchars;
+ int src_glyph_pad = pfont->glyph;
+ int src_bit_order = pfont->bit;
+ int src_byte_order = pfont->byte;
+ int err;
+ int max_ascent, max_descent;
+ int min_left, max_right;
+ int srcbpr;
+ int lshift = 0, rshift = 0, dst_left_bytes = 0, src_left_bytes = 0;
+ unsigned char *srcp;
+ unsigned char *dstp;
+ unsigned char bits1, bits2;
+ int width;
+ int src_extra;
+ int dst_extra;
+ int r, w;
+ CharInfoPtr *bitChars, *bitCharsFree, bitc;
+ CharInfoPtr *inkChars, *inkCharsFree = 0, inkc;
+ FontInfoPtr pinfo = &pfont->info;
+ xCharInfo *bitm, *inkm;
+
+ err = CheckFSFormat(format, (fsBitmapFormatMask) ~ 0,
+ &bitorder, &byteorder, &scanlineunit, &scanlinepad, &mappad);
+
+ if (err != Successful)
+ return err;
+
+ if (flags & LoadAll)
+ num_ranges = 0;
+
+ err = getCharInfos (pfont, num_ranges, range, FALSE, &nchars, &bitCharsFree);
+
+ if (err != Successful)
+ return err;
+
+ /* compute dstbpr for padded out fonts */
+ reformat = bitorder != src_bit_order || byteorder != src_byte_order;
+
+ /* we need the ink metrics when shrink-wrapping a TE font (sigh),
+ * but only for protocol version > 1 */
+ if (mappad != BitmapFormatImageRectMax &&
+ pinfo->inkMetrics &&
+ client->major_version > 1)
+ {
+ err = getCharInfos (pfont, num_ranges, range, TRUE, &nchars, &inkCharsFree);
+ if (err != Successful)
+ {
+ fsfree (bitCharsFree);
+ return err;
+ }
+ reformat = TRUE;
+ }
+
+ /* get space for glyph offsets */
+ lengths = (fsOffset32 *) fsalloc(SIZEOF(fsOffset32) * nchars);
+ if (!lengths) {
+ fsfree (bitCharsFree);
+ fsfree (inkCharsFree);
+ return AllocError;
+ }
+
+ switch (mappad)
+ {
+ case BitmapFormatImageRectMax:
+ max_ascent = FONT_MAX_ASCENT(pinfo);
+ max_descent = FONT_MAX_DESCENT(pinfo);
+ height = max_ascent + max_descent;
+ /* do font ascent and font descent match bitmap bounds ? */
+ if (height != pinfo->minbounds.ascent + pinfo->minbounds.descent)
+ reformat = TRUE;
+ /* fall through */
+ case BitmapFormatImageRectMaxWidth:
+ min_left = FONT_MIN_LEFT(pinfo);
+ max_right = FONT_MAX_RIGHT(pinfo);
+ if (min_left != pinfo->maxbounds.leftSideBearing)
+ reformat = TRUE;
+ if (max_right != pinfo->maxbounds.rightSideBearing)
+ reformat = TRUE;
+ dstbpr = GLWIDTHBYTESPADDED(max_right - min_left, scanlinepad);
+ break;
+ case BitmapFormatImageRectMin:
+ break;
+ }
+ if (mappad == BitmapFormatImageRectMax)
+ charsize = dstbpr * height;
+ size = 0;
+ gdata = 0;
+ contiguous = TRUE;
+ l = lengths;
+ inkChars = inkCharsFree;
+ bitChars = bitCharsFree;
+ for (i = 0; i < nchars; i++)
+ {
+ inkc = bitc = *bitChars++;
+ /* when ink metrics != bitmap metrics, use ink metrics */
+ if (inkChars)
+ inkc = *inkChars++;
+ l->position = size;
+ /*
+ * Do not repad characters with no bits except for those
+ * with non-zero width.
+ */
+ if (bitc && (bitc->bits || bitc->metrics.characterWidth)) {
+ if (!gdata)
+ gdata = (pointer) bitc->bits;
+ if ((char *) gdata + size != bitc->bits)
+ contiguous = FALSE;
+ if (mappad == BitmapFormatImageRectMin)
+ dstbpr = GLYPH_SIZE(inkc, scanlinepad);
+ if (dstbpr != GLYPH_SIZE(bitc, src_glyph_pad)) reformat = TRUE;
+ if (mappad != BitmapFormatImageRectMax)
+ {
+ height = inkc->metrics.ascent + inkc->metrics.descent;
+ charsize = height * dstbpr;
+ }
+ l->length = charsize;
+ size += charsize;
+ }
+ else
+ l->length = 0;
+ l++;
+ }
+ if (contiguous && !reformat)
+ {
+ *num_glyphs = nchars;
+ *freeData = FALSE;
+ *data = gdata;
+ *tsize = size;
+ *offsets = lengths;
+ fsfree (bitCharsFree);
+ fsfree (inkCharsFree);
+ return Successful;
+ }
+ if (size)
+ {
+ gdata = (pointer) fsalloc(size);
+ if (!gdata) {
+ fsfree (bitCharsFree);
+ fsfree (inkCharsFree);
+ fsfree (lengths);
+ return AllocError;
+ }
+ bzero ((char *) gdata, size);
+ }
+ else
+ gdata = NULL;
+
+ *freeData = TRUE;
+ l = lengths;
+ gd = gdata;
+
+ /* finally do the work */
+ bitChars = bitCharsFree;
+ inkChars = inkCharsFree;
+ for (i = 0; i < nchars; i++, l++)
+ {
+ inkc = bitc = *bitChars++;
+ if (inkChars)
+ inkc = *inkChars++;
+
+ /* ignore missing chars */
+ if (l->length == 0)
+ continue;
+
+ bitm = &bitc->metrics;
+ inkm = &inkc->metrics;
+
+ /* start address for the destination of bits for this char */
+
+ dstp = gd;
+
+ if (mappad == BitmapFormatImageRectMax)
+ height = max_ascent + max_descent;
+ else
+ height = inkm->ascent + inkm->descent;
+
+ /* adjust destination and calculate shift offsets */
+ switch (mappad) {
+ case BitmapFormatImageRectMax:
+ /* leave the first padded rows blank */
+ if (max_ascent > inkm->ascent)
+ {
+ height -= (max_ascent - inkm->ascent);
+ dstp += dstbpr * (max_ascent - inkm->ascent);
+ }
+ if (max_descent > inkm->descent)
+ {
+ height -= (max_descent - inkm->descent);
+ }
+ /* fall thru */
+ case BitmapFormatImageRectMaxWidth:
+ dst_off = inkm->leftSideBearing - min_left;
+ if (dst_off < 0) dst_off = 0;
+ break;
+ case BitmapFormatImageRectMin:
+ dst_off = 0;
+ dstbpr = GLYPH_SIZE(inkc, scanlinepad);
+ break;
+ }
+
+ srcbpr = GLYPH_SIZE (bitc, src_glyph_pad);
+ srcp = (unsigned char *) bitc->bits;
+
+ /* adjust source */
+ src_off = 0;
+ if (inkm != bitm)
+ {
+ srcp += (bitm->ascent - inkm->ascent) * srcbpr;
+ src_off = inkm->leftSideBearing - bitm->leftSideBearing;
+ }
+
+ dst_left_bytes = dst_off >> 3;
+ dst_off &= 7;
+ src_left_bytes = src_off >> 3;
+ src_off &= 7;
+
+ /* minimum of source/dest bytes per row */
+ width = srcbpr - src_left_bytes;
+ if (width > dstbpr - dst_left_bytes)
+ width = dstbpr - dst_left_bytes;
+ /* extra bytes in source and dest for padding */
+ src_extra = srcbpr - width - src_left_bytes;
+ dst_extra = dstbpr - width - dst_left_bytes;
+
+#define MSBBitLeft(b,c) ((b) << (c))
+#define MSBBitRight(b,c) ((b) >> (c))
+#define LSBBitLeft(b,c) ((b) >> (c))
+#define LSBBitRight(b,c) ((b) << (c))
+
+ if (dst_off == src_off)
+ {
+ if (srcbpr == dstbpr && src_left_bytes == dst_left_bytes)
+ {
+ r = height * srcbpr;
+ memmove( dstp, srcp, r);
+ dstp += r;
+ }
+ else
+ {
+ for (r = height; r; r--)
+ {
+ dstp += dst_left_bytes;
+ srcp += src_left_bytes;
+ for (w = width; w; w--)
+ *dstp++ = *srcp++;
+ dstp += dst_extra;
+ srcp += src_extra;
+ }
+ }
+ }
+ else
+ {
+ if (dst_off > src_off)
+ {
+ rshift = dst_off - src_off;
+ lshift = 8 - rshift;
+ }
+ else
+ {
+ lshift = src_off - dst_off;
+ rshift = 8 - lshift;
+ /* run the loop one fewer time if necessary */
+ if (src_extra <= dst_extra)
+ {
+ dst_extra++;
+ width--;
+ }
+ else
+ src_extra--;
+ }
+
+ for (r = inkm->ascent + inkm->descent; r; r--)
+ {
+ dstp += dst_left_bytes;
+ srcp += src_left_bytes;
+ bits2 = 0;
+ /* fetch first part of source when necessary */
+ if (dst_off < src_off)
+ bits2 = *srcp++;
+ /*
+ * XXX I bet this does not work when
+ * src_bit_order != src_byte_order && scanlineunit > 1
+ */
+ for (w = width; w; w--)
+ {
+ bits1 = *srcp++;
+ if (src_bit_order == MSBFirst)
+ {
+ *dstp++ = MSBBitRight(bits1, rshift) |
+ MSBBitLeft (bits2, lshift);
+ }
+ else
+ {
+ *dstp++ = LSBBitRight(bits1, rshift) |
+ LSBBitLeft (bits2, lshift);
+ }
+ bits2 = bits1;
+ }
+ /* get the last few bits if we have a place to store them */
+ if (dst_extra > 0)
+ {
+ if (src_bit_order == MSBFirst)
+ *dstp = MSBBitLeft (bits2, lshift);
+ else
+ *dstp = LSBBitLeft (bits2, lshift);
+ }
+ dstp += dst_extra;
+ srcp += src_extra;
+ }
+ }
+ /* skip the amount we just filled in */
+ gd += l->length;
+ }
+
+
+ /* now do the bit, byte, word swapping */
+ if (bitorder != src_bit_order)
+ BitOrderInvert(gdata, size);
+ if (byteorder != src_byte_order)
+ {
+ if (scanlineunit == 2)
+ TwoByteSwap(gdata, size);
+ else if (scanlineunit == 4)
+ FourByteSwap(gdata, size);
+ }
+ fsfree (bitCharsFree);
+ fsfree (inkCharsFree);
+ *num_glyphs = nchars;
+ *data = gdata;
+ *tsize = size;
+ *offsets = lengths;
+
+ return Successful;
+}
+
+/* ARGSUSED */
+int
+GetBitmaps(client, pfont, format, flags, num_ranges, range,
+ size, num_glyphs, offsets, data, freeData)
+ ClientPtr client;
+ FontPtr pfont;
+ fsBitmapFormat format;
+ Mask flags;
+ unsigned long num_ranges;
+ fsRange *range;
+ int *size;
+ unsigned long *num_glyphs;
+ fsOffset32 **offsets;
+ pointer *data;
+ int *freeData;
+{
+ int err;
+
+ assert(pfont);
+
+ *size = 0;
+ *data = (pointer) 0;
+
+ err = LoadGlyphRanges(client, pfont, TRUE, num_ranges * 2, 0, range);
+
+ if (err != Successful)
+ return err;
+
+ return packGlyphs (client, pfont, format, flags,
+ num_ranges, range, size, num_glyphs,
+ offsets, data, freeData);
+}