summaryrefslogtreecommitdiff
path: root/src/fc/fsconvert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fc/fsconvert.c')
-rw-r--r--src/fc/fsconvert.c702
1 files changed, 702 insertions, 0 deletions
diff --git a/src/fc/fsconvert.c b/src/fc/fsconvert.c
new file mode 100644
index 0000000..1c8c6d1
--- /dev/null
+++ b/src/fc/fsconvert.c
@@ -0,0 +1,702 @@
+/* $Xorg: fsconvert.c,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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 name of Network Computing Devices not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices
+ * makes no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES 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.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+/*
+ * FS data conversion
+ */
+
+#include <X11/X.h>
+#include "FS.h"
+#include "FSproto.h"
+#include "fontmisc.h"
+#include "fontstruct.h"
+#include "fservestr.h"
+
+extern char _fs_glyph_undefined;
+extern char _fs_glyph_requested;
+extern char _fs_glyph_zero_length;
+
+extern int _fs_load_glyphs();
+
+/*
+ * converts data from font server form to X server form
+ */
+
+void
+_fs_convert_char_info(src, dst)
+ fsXCharInfo *src;
+ xCharInfo *dst;
+{
+ dst->ascent = src->ascent;
+ dst->descent = src->descent;
+ dst->leftSideBearing = src->left;
+ dst->rightSideBearing = src->right;
+ dst->characterWidth = src->width;
+ dst->attributes = src->attributes;
+}
+
+void
+_fs_init_fontinfo(conn, pfi)
+ FSFpePtr conn;
+ FontInfoPtr pfi;
+{
+ if (conn->fsMajorVersion == 1) {
+ unsigned short n;
+ n = pfi->firstCol;
+ pfi->firstCol = pfi->firstRow;
+ pfi->firstRow = n;
+ n = pfi->lastCol;
+ pfi->lastCol = pfi->lastRow;
+ pfi->lastRow = n;
+ pfi->defaultCh = (pfi->defaultCh >> 8) & 0xff
+ + ((pfi->defaultCh & 0xff) << 8);
+ }
+
+ if (FontCouldBeTerminal (pfi))
+ {
+ pfi->terminalFont = TRUE;
+ pfi->minbounds.ascent = pfi->fontAscent;
+ pfi->minbounds.descent = pfi->fontDescent;
+ pfi->minbounds.leftSideBearing = 0;
+ pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
+ pfi->maxbounds = pfi->minbounds;
+ }
+
+ FontComputeInfoAccelerators (pfi);
+}
+
+int
+_fs_convert_props(pi, po, pd, pfi)
+ fsPropInfo *pi;
+ fsPropOffset *po;
+ pointer pd;
+ FontInfoPtr pfi;
+{
+ FontPropPtr dprop;
+ int i,
+ nprops;
+ char *is_str;
+ fsPropOffset local_off;
+ char *off_adr;
+
+/* stolen from server/include/resource.h */
+#define BAD_RESOURCE 0xe0000000
+
+ nprops = pfi->nprops = pi->num_offsets;
+
+ dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops);
+ is_str = (char *) xalloc(sizeof(char) * nprops);
+ if (!dprop || !is_str) {
+ xfree(is_str);
+ xfree(dprop);
+ return -1;
+ }
+ pfi->props = dprop;
+ pfi->isStringProp = is_str;
+
+ off_adr = (char *)po;
+ for (i = 0; i < nprops; i++, dprop++, is_str++) {
+ memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
+ dprop->name = MakeAtom(&pd[local_off.name.position],
+ local_off.name.length, 1);
+ if (local_off.type != PropTypeString) {
+ *is_str = FALSE;
+ dprop->value = local_off.value.position;
+ } else {
+ *is_str = TRUE;
+ dprop->value = (INT32) MakeAtom(&pd[local_off.value.position],
+ local_off.value.length, 1);
+ if (dprop->value == BAD_RESOURCE)
+ {
+ xfree (pfi->props);
+ xfree (pfi->isStringProp);
+ pfi->props = 0;
+ pfi->isStringProp = 0;
+ return -1;
+ }
+ }
+ off_adr += SIZEOF(fsPropOffset);
+ }
+
+ return nprops;
+}
+
+int
+_fs_convert_lfwi_reply(conn, pfi, fsrep, pi, po, pd)
+ FSFpePtr conn;
+ FontInfoPtr pfi;
+ fsListFontsWithXInfoReply *fsrep;
+ fsPropInfo *pi;
+ fsPropOffset *po;
+ pointer pd;
+{
+ fsUnpack_XFontInfoHeader(fsrep, pfi);
+ _fs_init_fontinfo(conn, pfi);
+
+ if (_fs_convert_props(pi, po, pd, pfi) == -1)
+ return AllocError;
+
+ return Successful;
+}
+
+
+#define ENCODING_UNDEFINED(enc) \
+ ((enc)->bits == &_fs_glyph_undefined ? \
+ TRUE : \
+ (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
+ FALSE))
+
+#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
+
+/*
+ * figures out what glyphs to request
+ *
+ * Includes logic to attempt to reduce number of round trips to the font
+ * server: when a glyph is requested, fs_build_range() requests a
+ * 16-glyph range of glyphs that contains the requested glyph. This is
+ * predicated on the belief that using a glyph increases the chances
+ * that nearby glyphs will be used: a good assumption for phonetic
+ * alphabets, but a questionable one for ideographic/pictographic ones.
+ */
+/* ARGSUSED */
+int
+fs_build_range(pfont, range_flag, count, item_size, data, nranges, ranges)
+ FontPtr pfont;
+ Bool range_flag;
+ register unsigned int count;
+ int item_size;
+ register unsigned char *data;
+ int *nranges;
+ fsRange **ranges;
+{
+ FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
+ FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
+ register CharInfoPtr encoding = fsfont->encoding;
+ FontInfoPtr pfi = &(pfont->info);
+ fsRange range;
+ int access_done = TRUE;
+ int err;
+ register unsigned long firstrow, lastrow, firstcol, lastcol;
+ register unsigned long row;
+ register unsigned long col;
+ register unsigned long loc;
+
+ if (!fsd->glyphs_to_get)
+ return AccessDone;
+
+ firstrow = pfi->firstRow;
+ lastrow = pfi->lastRow;
+ firstcol = pfi->firstCol;
+ lastcol = pfi->lastCol;
+
+ /* Make sure we have default char */
+ if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
+ {
+ loc = fsfont->pDefault - encoding;
+ row = loc / (lastcol - firstcol + 1) + firstrow;
+ col = loc % (lastcol - firstcol + 1) + firstcol;
+
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = row;
+
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[loc].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+
+ if (!range_flag && item_size == 1)
+ {
+ if (firstrow != 0) return AccessDone;
+ while (count--)
+ {
+ col = *data++;
+ if (col >= firstcol && col <= lastcol &&
+ GLYPH_UNDEFINED(col - firstcol))
+ {
+ int col1, col2;
+ col1 = col & 0xf0;
+ col2 = col1 + 15;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ /* Collect a 16-glyph neighborhood containing the requested
+ glyph... should in most cases reduce the number of round
+ trips to the font server. */
+ for (col = col1; col <= col2; col++)
+ {
+ if (!GLYPH_UNDEFINED(col - firstcol)) continue;
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = 0;
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[col - firstcol].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ fsRange fullrange[1];
+
+ if (range_flag && count == 0)
+ {
+ count = 2;
+ data = (unsigned char *)fullrange;
+ fullrange[0].min_char_high = firstrow;
+ fullrange[0].min_char_low = firstcol;
+ fullrange[0].max_char_high = lastrow;
+ fullrange[0].max_char_low = lastcol;
+ }
+
+ while (count--)
+ {
+ int row1, col1, row2, col2;
+ row1 = row2 = *data++;
+ col1 = col2 = *data++;
+ if (range_flag)
+ {
+ if (count)
+ {
+ row2 = *data++;
+ col2 = *data++;
+ count--;
+ }
+ else
+ {
+ row2 = lastrow;
+ col2 = lastcol;
+ }
+ if (row1 < firstrow) row1 = firstrow;
+ if (row2 > lastrow) row2 = lastrow;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ }
+ else
+ {
+ if (row1 < firstrow || row1 > lastrow ||
+ col1 < firstcol || col1 > lastcol)
+ continue;
+ }
+ for (row = row1; row <= row2; row++)
+ {
+ expand_glyph_range: ;
+ loc = (row - firstrow) * (lastcol + 1 - firstcol) +
+ (col1 - firstcol);
+ for (col = col1; col <= col2; col++, loc++)
+ {
+ if (GLYPH_UNDEFINED(loc))
+ {
+ if (row1 == row2 &&
+ ((col1 & 0xf) && col1 > firstcol ||
+ (col2 & 0xf) != 0xf) && (col2 < lastcol))
+ {
+ /* If we're loading from a single row, expand
+ range of glyphs loaded to a multiple of
+ a 16-glyph range -- attempt to reduce number
+ of round trips to the font server. */
+ col1 &= 0xf0;
+ col2 = (col2 & 0xf0) + 15;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ goto expand_glyph_range;
+ }
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = row;
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[loc].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ return access_done ?
+ AccessDone :
+ Successful;
+}
+
+#undef GLYPH_UNDEFINED
+#undef ENCODING_UNDEFINED
+
+
+/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
+ performed by fs_build_range(); for use if the associated LoadGlyphs
+ requests needs to be cancelled. */
+
+void
+_fs_clean_aborted_loadglyphs(pfont, num_expected_ranges, expected_ranges)
+ FontPtr pfont;
+ int num_expected_ranges;
+ fsRange *expected_ranges;
+{
+ register FSFontPtr fsfont;
+ register FSFontDataRec *fsd;
+ register int i;
+
+ fsfont = (FSFontPtr) pfont->fontPrivate;
+ fsd = (FSFontDataRec *) pfont->fpePrivate;
+ if (fsfont->encoding)
+ {
+ fsRange full_range[1];
+ if (!num_expected_ranges)
+ {
+ full_range[0].min_char_low = pfont->info.firstCol;
+ full_range[0].min_char_high = pfont->info.firstRow;
+ full_range[0].max_char_low = pfont->info.lastCol;
+ full_range[0].max_char_high = pfont->info.lastRow;
+ num_expected_ranges = 1;
+ expected_ranges = full_range;
+ }
+
+ for (i = 0; i < num_expected_ranges; i++)
+ {
+ int row, col;
+ for (row = expected_ranges[i].min_char_high;
+ row <= expected_ranges[i].max_char_high;
+ row++)
+ {
+ register CharInfoPtr encoding = fsfont->encoding +
+ ((row - pfont->info.firstRow) *
+ (pfont->info.lastCol -
+ pfont->info.firstCol + 1) +
+ expected_ranges[i].min_char_low -
+ pfont->info.firstCol);
+ for (col = expected_ranges[i].min_char_low;
+ col <= expected_ranges[i].max_char_low;
+ encoding++, col++)
+ {
+ if (encoding->bits == &_fs_glyph_requested)
+ encoding->bits = &_fs_glyph_undefined;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * figures out what extents to request
+ * this is where lots of extra
+ * smarts wants to live
+ */
+/* ARGSUSED */
+int
+_fs_check_extents(pfont, flags, nranges, range, blockrec)
+ FontPtr pfont;
+ Mask flags;
+ int nranges;
+ fsRange *range;
+ FSBlockDataPtr blockrec;
+{
+/* XXX -- either fill in the requested info if we have it somewhere
+ * and return AccessDone, or else return Successful
+ */
+ return Successful;
+}
+
+/*
+ * figures out what glyphs to request
+ * this is where lots of extra
+ * smarts wants to live
+ */
+/* ARGSUSED */
+int
+_fs_check_bitmaps(pfont, format, flags, nranges, range, blockrec)
+ FontPtr pfont;
+ fsBitmapFormat format;
+ Mask flags;
+ int nranges;
+ fsRange *range;
+ FSBlockDataPtr blockrec;
+{
+/* XXX -- either fill in the requested info if we have it somewhere
+ * and return AccessDone, or else return Successful
+ */
+ return Successful;
+}
+
+int
+_fs_get_glyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register unsigned char *chars;
+ FontEncoding charEncoding;
+ unsigned long *glyphCount; /* RETURN */
+ CharInfoPtr *glyphs; /* RETURN */
+{
+ FSFontPtr fsdata;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ CharInfoPtr *glyphsBase;
+ register unsigned int c;
+ register CharInfoPtr pci;
+ unsigned int r;
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+ FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
+ int itemSize;
+ int err = Successful;
+
+ fsdata = (FSFontPtr) pFont->fontPrivate;
+ encoding = fsdata->encoding;
+ pDefault = fsdata->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+
+ if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
+ itemSize = 1;
+ else
+ itemSize = 2;
+
+ /* In this age of glyph caching, any glyphs gotten through this
+ procedure should already be loaded. If they are not, we are
+ dealing with someone (perhaps a ddx driver optimizing a font)
+ that doesn't understand the finer points of glyph caching. The
+ CHECK_ENCODING macro checks for this condition... if found, it
+ calls fs_load_all_glyphs(), which corrects it. Since the caller
+ of this code will not know how to handle a return value of
+ Suspended, the fs_load_all_glyphs() procedure will block and
+ freeze the server until the load operation is done. Moral: the
+ glyphCachingMode flag really must indicate the capabilities of
+ the ddx drivers. */
+
+#define CHECK_ENCODING(cnum) \
+ ( pci = encoding + (cnum), \
+ fsd->glyphs_to_get ? \
+ ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
+ ((err = fs_load_all_glyphs(pFont)), pci) : \
+ pci ) : \
+ pci )
+
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (err == Successful && count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = CHECK_ENCODING(c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (err == Successful && count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols && CHECK_ENCODING(c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (err == Successful && count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = CHECK_ENCODING(c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (err == Successful && count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols && CHECK_ENCODING(c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (err == Successful && count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols &&
+ CHECK_ENCODING(r * numCols + c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return err;
+}
+
+
+static int
+_fs_get_metrics(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register unsigned char *chars;
+ FontEncoding charEncoding;
+ unsigned long *glyphCount; /* RETURN */
+ xCharInfo **glyphs; /* RETURN */
+{
+ FSFontPtr fsdata;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ xCharInfo **glyphsBase;
+ register unsigned int c;
+ unsigned int r;
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+ int itemSize;
+
+ fsdata = (FSFontPtr) pFont->fontPrivate;
+ encoding = fsdata->inkMetrics;
+ pDefault = fsdata->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+
+ /* XXX - this should be much smarter */
+ /* make sure the glyphs are there */
+ if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
+ itemSize = 1;
+ else
+ itemSize = 2;
+
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)&encoding[c];
+ else
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ } else {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ } else {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return Successful;
+}
+
+
+void
+_fs_unload_font(pfont)
+ FontPtr pfont;
+{
+ FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
+
+ if (fsdata->encoding)
+ {
+ register int i;
+ register CharInfoPtr encoding = fsdata->encoding;
+ FontInfoPtr pfi = &pfont->info;
+ for (i = (pfi->lastCol - pfi->firstCol + 1) *
+ (pfi->lastRow - pfi->firstRow + 1);
+ i > 0;
+ encoding++, i--)
+ {
+ if (encoding->bits &&
+ encoding->bits != &_fs_glyph_undefined &&
+ encoding->bits != &_fs_glyph_requested &&
+ encoding->bits != &_fs_glyph_zero_length)
+ xfree(encoding->bits);
+ }
+ }
+ xfree(fsdata->encoding);
+ xfree(fsdata);
+
+ pfont->fontPrivate = 0;
+}
+
+void
+_fs_init_font(pfont)
+ FontPtr pfont;
+{
+ /* set font function pointers */
+ pfont->get_glyphs = _fs_get_glyphs;
+ pfont->get_metrics = _fs_get_metrics;
+ pfont->unload_font = _fs_unload_font;
+ pfont->unload_glyphs = (void (*)())0;
+}