aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/Xft1/xftfreetype.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/Xft1/xftfreetype.c')
-rw-r--r--nx-X11/lib/Xft1/xftfreetype.c678
1 files changed, 678 insertions, 0 deletions
diff --git a/nx-X11/lib/Xft1/xftfreetype.c b/nx-X11/lib/Xft1/xftfreetype.c
new file mode 100644
index 000000000..1021c95bf
--- /dev/null
+++ b/nx-X11/lib/Xft1/xftfreetype.c
@@ -0,0 +1,678 @@
+/*
+ * $XFree86: xc/lib/Xft1/xftfreetype.c,v 1.5 2002/08/12 22:17:49 keithp Exp $
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "xftint.h"
+
+FT_Library _XftFTlibrary;
+
+typedef struct _XftFtEncoding {
+ const char *name;
+ FT_Encoding encoding;
+} XftFtEncoding;
+
+static XftFtEncoding xftFtEncoding[] = {
+ { "iso10646-1", ft_encoding_unicode, },
+ { "iso8859-1", ft_encoding_unicode, },
+ { "apple-roman", ft_encoding_apple_roman },
+ { "adobe-fontspecific", ft_encoding_symbol, },
+ { "glyphs-fontspecific",ft_encoding_none, },
+};
+
+#define NUM_FT_ENCODINGS (sizeof xftFtEncoding / sizeof xftFtEncoding[0])
+
+#define FT_Matrix_Equal(a,b) ((a)->xx == (b)->xx && \
+ (a)->yy == (b)->yy && \
+ (a)->xy == (b)->xy && \
+ (a)->yx == (b)->yx)
+
+XftPattern *
+XftFreeTypeQuery (const char *file, int id, int *count)
+{
+ FT_Face face;
+ XftPattern *pat;
+ int slant;
+ int weight;
+ int i, j;
+
+ if (FT_New_Face (_XftFTlibrary, file, id, &face))
+ return 0;
+
+ *count = face->num_faces;
+
+ pat = XftPatternCreate ();
+ if (!pat)
+ goto bail0;
+
+
+ if (!XftPatternAddBool (pat, XFT_CORE, False))
+ goto bail1;
+
+ if (!XftPatternAddBool (pat, XFT_OUTLINE,
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+ goto bail1;
+
+ if (!XftPatternAddBool (pat, XFT_SCALABLE,
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+ goto bail1;
+
+
+ slant = XFT_SLANT_ROMAN;
+ if (face->style_flags & FT_STYLE_FLAG_ITALIC)
+ slant = XFT_SLANT_ITALIC;
+
+ if (!XftPatternAddInteger (pat, XFT_SLANT, slant))
+ goto bail1;
+
+ weight = XFT_WEIGHT_MEDIUM;
+ if (face->style_flags & FT_STYLE_FLAG_BOLD)
+ weight = XFT_WEIGHT_BOLD;
+
+ if (!XftPatternAddInteger (pat, XFT_WEIGHT, weight))
+ goto bail1;
+
+ if (!XftPatternAddString (pat, XFT_FAMILY, face->family_name))
+ goto bail1;
+
+ if (!XftPatternAddString (pat, XFT_STYLE, face->style_name))
+ goto bail1;
+
+ if (!XftPatternAddString (pat, XFT_FILE, file))
+ goto bail1;
+
+ if (!XftPatternAddInteger (pat, XFT_INDEX, id))
+ goto bail1;
+
+#if 0
+ if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
+ if (!XftPatternAddInteger (pat, XFT_SPACING, XFT_MONO))
+ goto bail1;
+#endif
+
+ if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
+ {
+ for (i = 0; i < face->num_fixed_sizes; i++)
+ if (!XftPatternAddDouble (pat, XFT_PIXEL_SIZE,
+ (double) face->available_sizes[i].height))
+ goto bail1;
+ }
+
+ for (i = 0; i < face->num_charmaps; i++)
+ {
+#if 0
+ printf ("face %s encoding %d %c%c%c%c\n",
+ face->family_name, i,
+ face->charmaps[i]->encoding >> 24,
+ face->charmaps[i]->encoding >> 16,
+ face->charmaps[i]->encoding >> 8,
+ face->charmaps[i]->encoding >> 0);
+#endif
+ for (j = 0; j < NUM_FT_ENCODINGS; j++)
+ {
+ if (face->charmaps[i]->encoding == xftFtEncoding[j].encoding)
+ {
+ if (!XftPatternAddString (pat, XFT_ENCODING,
+ xftFtEncoding[j].name))
+ goto bail1;
+ }
+ }
+ }
+
+ if (!XftPatternAddString (pat, XFT_ENCODING,
+ "glyphs-fontspecific"))
+ goto bail1;
+
+
+ FT_Done_Face (face);
+ return pat;
+
+bail1:
+ XftPatternDestroy (pat);
+bail0:
+ FT_Done_Face (face);
+ return 0;
+}
+
+/*
+ * List of all open files (each face in a file is managed separately)
+ */
+typedef struct _XftFtFile {
+ struct _XftFtFile *next;
+ int ref;
+
+ char *file;
+ int id;
+
+ FT_Face face;
+ FT_F26Dot6 size;
+ FT_Matrix matrix;
+ int charmap;
+} XftFtFile;
+
+static XftFtFile *_XftFtFiles;
+
+static XftFtFile *
+_XftFreeTypeOpenFile (char *file, int id)
+{
+ XftFtFile *f;
+ FT_Face face;
+
+ for (f = _XftFtFiles; f; f = f->next)
+ {
+ if (!strcmp (f->file, file) && f->id == id)
+ {
+ ++f->ref;
+ if (_XftFontDebug () & XFT_DBG_REF)
+ printf ("FontFile %s/%d matches existing (%d)\n",
+ file, id, f->ref);
+ return f;
+ }
+ }
+ if (FT_New_Face (_XftFTlibrary, file, id, &face))
+ return 0;
+
+ f = malloc (sizeof (XftFtFile) + strlen (file) + 1);
+ if (!f)
+ return 0;
+
+ if (_XftFontDebug () & XFT_DBG_REF)
+ printf ("FontFile %s/%d matches new\n",
+ file, id);
+ f->next = _XftFtFiles;
+ _XftFtFiles = f;
+ f->ref = 1;
+
+ f->file = (char *) (f+1);
+ strcpy (f->file, file);
+ f->id = id;
+
+ f->face = face;
+ f->size = 0;
+ f->charmap = -1;
+ f->matrix.xx = 0x10000;
+ f->matrix.xy = 0x0;
+ f->matrix.yy = 0x10000;
+ f->matrix.yx = 0x0;
+ return f;
+}
+
+Bool
+XftFreeTypeSetFace (FT_Face face, FT_F26Dot6 size, int charmap, FT_Matrix *matrix)
+{
+ XftFtFile *f, **prev;
+
+ for (prev = &_XftFtFiles; (f = *prev); prev = &f->next)
+ {
+ if (f->face == face)
+ {
+ /* LRU */
+ if (prev != &_XftFtFiles)
+ {
+ *prev = f->next;
+ f->next = _XftFtFiles;
+ _XftFtFiles = f;
+ }
+ if (f->size != size)
+ {
+ if (_XftFontDebug() & XFT_DBG_GLYPH)
+ printf ("Set face size to %d (%d)\n",
+ (int) (size >> 6), (int) size);
+ if (FT_Set_Char_Size (face, size, size, 0, 0))
+ return False;
+ f->size = size;
+ }
+ if (f->charmap != charmap && charmap != -1)
+ {
+ if (_XftFontDebug() & XFT_DBG_GLYPH)
+ printf ("Set face charmap to %d\n", charmap);
+ if (FT_Set_Charmap (face, face->charmaps[charmap]))
+ return False;
+ f->charmap = charmap;
+ }
+ if (!FT_Matrix_Equal (&f->matrix, matrix))
+ {
+ if (_XftFontDebug() & XFT_DBG_GLYPH)
+ printf ("Set face matrix to (%g,%g,%g,%g)\n",
+ (double) matrix->xx / 0x10000,
+ (double) matrix->xy / 0x10000,
+ (double) matrix->yx / 0x10000,
+ (double) matrix->yy / 0x10000);
+ FT_Set_Transform (face, matrix, 0);
+ f->matrix = *matrix;
+ }
+ break;
+ }
+ }
+ return True;
+}
+
+static void
+_XftFreeTypeCloseFile (XftFtFile *f)
+{
+ XftFtFile **prev;
+
+ if (--f->ref != 0)
+ return;
+ for (prev = &_XftFtFiles; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == f)
+ {
+ *prev = f->next;
+ break;
+ }
+ }
+ FT_Done_Face (f->face);
+ free (f);
+}
+
+/*
+ * Cache of all glyphsets
+ */
+typedef struct _XftFtGlyphSet {
+ struct _XftFtGlyphSet *next;
+ int ref;
+
+ XftFtFile *file;
+ Bool minspace;
+ int char_width;
+
+ XftFontStruct font;
+} XftFtGlyphSet;
+
+XftFontStruct *
+XftFreeTypeOpen (Display *dpy, XftPattern *pattern)
+{
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy);
+ XftFtFile *file;
+ FT_Face face;
+ XftFtGlyphSet *gs;
+ char *filename;
+ int id;
+ double dsize;
+ FT_F26Dot6 size;
+ int rgba;
+ int spacing;
+ int char_width;
+ Bool antialias;
+ Bool minspace;
+ char *encoding_name;
+ XftFontStruct *font;
+ int j;
+ FT_Encoding encoding;
+ int charmap;
+ FT_Matrix matrix;
+ XftMatrix *font_matrix;
+
+#if 0
+ int extra;
+#endif
+ int height, ascent, descent;
+ XRenderPictFormat pf, *format;
+
+ /*
+ * Open the file
+ */
+ if (XftPatternGetString (pattern, XFT_FILE, 0, &filename) != XftResultMatch)
+ goto bail0;
+
+ if (XftPatternGetInteger (pattern, XFT_INDEX, 0, &id) != XftResultMatch)
+ goto bail0;
+
+ file = _XftFreeTypeOpenFile (filename, id);
+ if (!file)
+ goto bail0;
+
+ face = file->face;
+
+ /*
+ * Extract the glyphset information from the pattern
+ */
+ if (XftPatternGetString (pattern, XFT_ENCODING, 0, &encoding_name) != XftResultMatch)
+ goto bail0;
+
+ if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &dsize) != XftResultMatch)
+ goto bail0;
+
+ switch (XftPatternGetInteger (pattern, XFT_RGBA, 0, &rgba)) {
+ case XftResultNoMatch:
+ rgba = XFT_RGBA_NONE;
+ break;
+ case XftResultMatch:
+ break;
+ default:
+ goto bail0;
+ }
+
+ switch (XftPatternGetBool (pattern, XFT_ANTIALIAS, 0, &antialias)) {
+ case XftResultNoMatch:
+ antialias = True;
+ break;
+ case XftResultMatch:
+ break;
+ default:
+ goto bail0;
+ }
+
+ switch (XftPatternGetBool (pattern, XFT_MINSPACE, 0, &minspace)) {
+ case XftResultNoMatch:
+ minspace = False;
+ break;
+ case XftResultMatch:
+ break;
+ default:
+ goto bail0;
+ }
+
+ switch (XftPatternGetInteger (pattern, XFT_SPACING, 0, &spacing)) {
+ case XftResultNoMatch:
+ spacing = XFT_PROPORTIONAL;
+ break;
+ case XftResultMatch:
+ break;
+ default:
+ goto bail1;
+ }
+
+ if (XftPatternGetInteger (pattern, XFT_CHAR_WIDTH,
+ 0, &char_width) != XftResultMatch)
+ {
+ char_width = 0;
+ }
+ else if (char_width)
+ spacing = XFT_MONO;
+
+ matrix.xx = matrix.yy = 0x10000;
+ matrix.xy = matrix.yx = 0;
+
+ switch (XftPatternGetMatrix (pattern, XFT_MATRIX, 0, &font_matrix)) {
+ case XftResultNoMatch:
+ break;
+ case XftResultMatch:
+ matrix.xx = 0x10000L * font_matrix->xx;
+ matrix.yy = 0x10000L * font_matrix->yy;
+ matrix.xy = 0x10000L * font_matrix->xy;
+ matrix.yx = 0x10000L * font_matrix->yx;
+ break;
+ default:
+ goto bail1;
+ }
+
+
+
+ if (XftPatternGetInteger (pattern, XFT_CHAR_WIDTH,
+ 0, &char_width) != XftResultMatch)
+ {
+ char_width = 0;
+ }
+ else if (char_width)
+ spacing = XFT_MONO;
+
+ encoding = face->charmaps[0]->encoding;
+
+ for (j = 0; j < NUM_FT_ENCODINGS; j++)
+ if (!strcmp (encoding_name, xftFtEncoding[j].name))
+ {
+ encoding = xftFtEncoding[j].encoding;
+ break;
+ }
+
+ size = (FT_F26Dot6) (dsize * 64.0);
+
+ if (encoding == ft_encoding_none)
+ charmap = -1;
+ else
+ {
+ for (charmap = 0; charmap < face->num_charmaps; charmap++)
+ if (face->charmaps[charmap]->encoding == encoding)
+ break;
+
+ if (charmap == face->num_charmaps)
+ goto bail1;
+ }
+
+
+ /*
+ * Match an existing glyphset
+ */
+ for (gs = info->glyphSets; gs; gs = gs->next)
+ {
+ if (gs->file == file &&
+ gs->minspace == minspace &&
+ gs->char_width == char_width &&
+ gs->font.size == size &&
+ gs->font.spacing == spacing &&
+ gs->font.charmap == charmap &&
+ gs->font.rgba == rgba &&
+ gs->font.antialias == antialias &&
+ FT_Matrix_Equal (&gs->font.matrix, &matrix))
+ {
+ ++gs->ref;
+ if (_XftFontDebug () & XFT_DBG_REF)
+ {
+ printf ("Face size %g matches existing (%d)\n",
+ dsize, gs->ref);
+ }
+ return &gs->font;
+ }
+ }
+
+ if (_XftFontDebug () & XFT_DBG_REF)
+ {
+ printf ("Face size %g matches new\n",
+ dsize);
+ }
+ /*
+ * No existing glyphset, create another
+ */
+ gs = malloc (sizeof (XftFtGlyphSet));
+ if (!gs)
+ goto bail1;
+
+ gs->ref = 1;
+
+ gs->file = file;
+ gs->minspace = minspace;
+ gs->char_width = char_width;
+
+ font = &gs->font;
+
+ if (antialias)
+ {
+ switch (rgba) {
+ case FC_RGBA_RGB:
+ case FC_RGBA_BGR:
+ case FC_RGBA_VRGB:
+ case FC_RGBA_VBGR:
+ pf.depth = 32;
+ pf.type = PictTypeDirect;
+ pf.direct.alpha = 24;
+ pf.direct.alphaMask = 0xff;
+ pf.direct.red = 16;
+ pf.direct.redMask = 0xff;
+ pf.direct.green = 8;
+ pf.direct.greenMask = 0xff;
+ pf.direct.blue = 0;
+ pf.direct.blueMask = 0xff;
+ format = XRenderFindFormat(dpy,
+ PictFormatType|
+ PictFormatDepth|
+ PictFormatAlpha|
+ PictFormatAlphaMask|
+ PictFormatRed|
+ PictFormatRedMask|
+ PictFormatGreen|
+ PictFormatGreenMask|
+ PictFormatBlue|
+ PictFormatBlueMask,
+ &pf, 0);
+ break;
+ default:
+ pf.depth = 8;
+ pf.type = PictTypeDirect;
+ pf.direct.alpha = 0;
+ pf.direct.alphaMask = 0xff;
+ format = XRenderFindFormat(dpy,
+ PictFormatType|
+ PictFormatDepth|
+ PictFormatAlpha|
+ PictFormatAlphaMask,
+ &pf, 0);
+ break;
+ }
+ }
+ else
+ {
+ pf.depth = 1;
+ pf.type = PictTypeDirect;
+ pf.direct.alpha = 0;
+ pf.direct.alphaMask = 0x1;
+ format = XRenderFindFormat(dpy,
+ PictFormatType|
+ PictFormatDepth|
+ PictFormatAlpha|
+ PictFormatAlphaMask,
+ &pf, 0);
+ }
+
+ if (!format)
+ goto bail2;
+
+ if (!XftFreeTypeSetFace (face, size, charmap, &matrix))
+ goto bail2;
+
+ descent = -(face->size->metrics.descender >> 6);
+ ascent = face->size->metrics.ascender >> 6;
+ if (minspace)
+ {
+ height = ascent + descent;
+ }
+ else
+ {
+ height = face->size->metrics.height >> 6;
+#if 0
+ extra = (height - (ascent + descent));
+ if (extra > 0)
+ {
+ ascent = ascent + extra / 2;
+ descent = height - ascent;
+ }
+ else if (extra < 0)
+ height = ascent + descent;
+#endif
+ }
+ font->ascent = ascent;
+ font->descent = descent;
+ font->height = height;
+
+ if (char_width)
+ font->max_advance_width = char_width;
+ else
+ font->max_advance_width = face->size->metrics.max_advance >> 6;
+
+ gs->next = info->glyphSets;
+ info->glyphSets = gs;
+
+ font->glyphset = XRenderCreateGlyphSet (dpy, format);
+
+ font->size = size;
+ font->spacing = spacing;
+ font->format = format;
+ font->realized =0;
+ font->nrealized = 0;
+ font->rgba = rgba;
+ font->antialias = antialias;
+ font->charmap = charmap;
+ font->transform = (matrix.xx != 0x10000 || matrix.xy != 0 ||
+ matrix.yx != 0 || matrix.yy != 0x10000);
+ font->matrix = matrix;
+ font->face = face;
+
+ return font;
+
+bail2:
+ free (gs);
+bail1:
+ _XftFreeTypeCloseFile (file);
+bail0:
+ return 0;
+}
+
+void
+XftFreeTypeClose (Display *dpy, XftFontStruct *font)
+{
+ XftFtGlyphSet *gs, **prev;
+ XftDisplayInfo *info = _XftDisplayInfoGet (dpy);
+ int i;
+ XGlyphInfo *gi;
+
+ for (prev = &info->glyphSets; (gs = *prev); prev = &gs->next)
+ {
+ if (&gs->font == font)
+ {
+ if (--gs->ref == 0)
+ {
+ XRenderFreeGlyphSet (dpy, font->glyphset);
+ for (i = 0; i < font->nrealized; i++)
+ {
+ gi = font->realized[i];
+ if (gi && gi != XftUntestedGlyph)
+ free (gi);
+ }
+ if (font->realized)
+ free (font->realized);
+
+ _XftFreeTypeCloseFile (gs->file);
+
+ *prev = gs->next;
+ free (gs);
+ }
+ break;
+ }
+ }
+}
+
+XftFontStruct *
+XftFreeTypeGet (XftFont *font)
+{
+ if (font->core)
+ return 0;
+ return font->u.ft.font;
+}
+
+/* #define XFT_DEBUG_FONTSET */
+
+Bool
+XftInitFtLibrary (void)
+{
+ if (_XftFTlibrary)
+ return True;
+ if (FT_Init_FreeType (&_XftFTlibrary))
+ return False;
+ _XftFontSet = FcConfigGetFonts (0, FcSetSystem);
+ if (!_XftFontSet)
+ return False;
+ return True;
+}