From cbfb19790917d271b8ca6156554b16acc802719f Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 28 Mar 2014 17:35:36 +0100 Subject: libxtrans fontconfig mesa xserver git update 28 Mar 2014 xserver commit a2880699e8f1f576e1a48ebf25e8982463323f84 libxtrans commit 68f60238c4224f954ff6556ae778c72e420175f0 fontconfig commit fcba9ef01c978323fc71c17e455d3cd6ae35edcc mesa commit 029ccd773d01a5f801c809c499516d7b0c4cc3f8 --- fontconfig/configure.ac | 4 + fontconfig/doc/Makefile.am | 1 + fontconfig/doc/fcpattern.fncs | 27 ++++- fontconfig/doc/fcrange.fncs | 64 +++++++++++ fontconfig/doc/fontconfig-devel.sgml | 7 ++ fontconfig/fontconfig/fcprivate.h | 3 + fontconfig/fontconfig/fontconfig.h | 28 ++++- fontconfig/src/Makefile.am | 1 + fontconfig/src/fccfg.c | 48 +++++--- fontconfig/src/fcdbg.c | 13 ++- fontconfig/src/fcdefault.c | 47 ++++---- fontconfig/src/fcfreetype.c | 35 ++++++ fontconfig/src/fcint.h | 85 +++++++++++--- fontconfig/src/fclist.c | 2 + fontconfig/src/fcmatch.c | 45 ++++++++ fontconfig/src/fcname.c | 49 ++++++++- fontconfig/src/fcobjs.h | 2 +- fontconfig/src/fcpat.c | 73 ++++++++++++ fontconfig/src/fcrange.c | 207 +++++++++++++++++++++++++++++++++++ fontconfig/src/fcxml.c | 108 ++++++++++++++---- 20 files changed, 755 insertions(+), 94 deletions(-) create mode 100644 fontconfig/doc/fcrange.fncs create mode 100644 fontconfig/src/fcrange.c (limited to 'fontconfig') diff --git a/fontconfig/configure.ac b/fontconfig/configure.ac index 1086a9a55..80875dfa2 100644 --- a/fontconfig/configure.ac +++ b/fontconfig/configure.ac @@ -321,6 +321,10 @@ AC_CHECK_MEMBER(FT_Bitmap_Size.y_ppem, #include FT_FREETYPE_H]) AC_DEFINE_UNQUOTED(HAVE_FT_BITMAP_SIZE_Y_PPEM,$HAVE_FT_BITMAP_SIZE_Y_PPEM, [FT_Bitmap_Size structure includes y_ppem field]) +AC_CHECK_MEMBERS([TT_OS2.usLowerOpticalPointSize, TT_OS2.usUpperOpticalPointSize], [], [], [[ +#include +#include FT_FREETYPE_H +#include FT_TRUETYPE_TABLES_H]]) CFLAGS="$fontconfig_save_cflags" LIBS="$fontconfig_save_libs" diff --git a/fontconfig/doc/Makefile.am b/fontconfig/doc/Makefile.am index 78a7cdbf1..7503219b8 100644 --- a/fontconfig/doc/Makefile.am +++ b/fontconfig/doc/Makefile.am @@ -81,6 +81,7 @@ DOC_FUNCS_FNCS = \ fcobjectset.fncs \ fcobjecttype.fncs \ fcpattern.fncs \ + fcrange.fncs \ fcstring.fncs \ fcstrset.fncs \ fcvalue.fncs \ diff --git a/fontconfig/doc/fcpattern.fncs b/fontconfig/doc/fcpattern.fncs index 1df1c4f61..1049d77af 100644 --- a/fontconfig/doc/fcpattern.fncs +++ b/fontconfig/doc/fcpattern.fncs @@ -181,12 +181,21 @@ values added to the list have binding weak instead of FcPatternAddRange are available since 2.11.91. @@ @RET@ FcResult @@ -257,16 +266,24 @@ within the pattern directly. Applications must not free this value. @FUNC++++++@ FcPatternGetFTFace @TYPE1++++++@ FcPattern * @ARG1++++++@ p @TYPE2++++++@ const char * @ARG2++++++@ object -@TYPE3+++++@ int% @ARG3+++++@ n -@TYPE3++++++@ FT_Face * @ARG3++++++@ f +@TYPE3++++++@ int% @ARG3++++++@ n +@TYPE4++++++@ FT_Face * @ARG4++++++@ f @PROTOTYPE+++++++@ @RET+++++++@ FcResult @FUNC+++++++@ FcPatternGetLangSet @TYPE1+++++++@ FcPattern * @ARG1+++++++@ p @TYPE2+++++++@ const char * @ARG2+++++++@ object -@TYPE3+++++@ int% @ARG3+++++@ n -@TYPE3+++++++@ FcLangSet ** @ARG3+++++++@ l +@TYPE3+++++++@ int% @ARG3+++++++@ n +@TYPE4+++++++@ FcLangSet ** @ARG4+++++++@ l + +@PROTOTYPE++++++++@ +@RET++++++++@ FcResult +@FUNC++++++++@ FcPatternGetRange +@TYPE1++++++++@ FcPattern * @ARG1++++++++@ p +@TYPE2++++++++@ const char * @ARG2++++++++@ object +@TYPE3++++++++@ int% @ARG3++++++++@ n +@TYPE4++++++++@ FcRange ** @ARG4++++++++@ r @PURPOSE@ Return a typed value from a pattern @DESC@ @@ -275,6 +292,8 @@ returned data is of the expected type. They return FcResultTypeMismatch if this is not the case. Note that these (like FcPatternGet) do not make a copy of any data structure referenced by the return value. Use these in preference to FcPatternGet to provide compile-time typechecking. + +FcPatternGetRange are available since 2.11.91. @@ @RET@ FcPattern * diff --git a/fontconfig/doc/fcrange.fncs b/fontconfig/doc/fcrange.fncs new file mode 100644 index 000000000..605459525 --- /dev/null +++ b/fontconfig/doc/fcrange.fncs @@ -0,0 +1,64 @@ +/* + * fontconfig/doc/fcrange.fncs + * + * Copyright © 2003 Keith Packard + * + * 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 the author(s) not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHOR(S) 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. + */ +@RET@ FcRange * +@FUNC@ FcRangeCopy +@TYPE1@ const FcRange * @ARG1@ range +@PURPOSE@ Copy a range object +@DESC@ +FcRangeCopy creates a new FcRange object and +populates it with the contents of range. +@SINCE@ 2.11.91 +@@ + +@RET@ FcRange * +@FUNC@ FcRangeCreateDouble +@TYPE1@ double @ARG1@ begin +@TYPE2@ double @ARG2@ end +@PURPOSE@ create a range object for double +@DESC@ +FcRangeCreateDouble creates a new FcRange object with +double sized value. +@SINCE@ 2.11.91 +@@ + +@RET@ FcRange * +@FUNC@ FcRangeCreateInteger +@TYPE1@ int @ARG1@ begin +@TYPE2@ int @ARG2@ end +@PURPOSE@ create a range object for integer +@DESC@ +FcRangeCreateInteger creates a new FcRange object with +integer sized value. +@SINCE@ 2.11.91 +@@ + +@RET@ void +@FUNC@ FcRangeDestroy +@TYPE1@ FcRange * @ARG1@ range +@PURPOSE@ destroy a range object +@DESC@ +FcRangeDestroy destroys a FcRange object, freeing +all memory associated with it. +@SINCE@ 2.11.91 +@@ diff --git a/fontconfig/doc/fontconfig-devel.sgml b/fontconfig/doc/fontconfig-devel.sgml index 7306d7924..e2cb1c281 100644 --- a/fontconfig/doc/fontconfig-devel.sgml +++ b/fontconfig/doc/fontconfig-devel.sgml @@ -16,6 +16,7 @@ + @@ -508,6 +509,12 @@ FcMatrix structures hold an affine transformation in matrix form. &fcmatrix; + FcRange + +An FcRange holds two variables to indicate a range in between. + + &fcrange; + FcConfig An FcConfig object holds the internal representation of a configuration. diff --git a/fontconfig/fontconfig/fcprivate.h b/fontconfig/fontconfig/fcprivate.h index 210c1d8a3..a6ee5c234 100644 --- a/fontconfig/fontconfig/fcprivate.h +++ b/fontconfig/fontconfig/fcprivate.h @@ -77,6 +77,9 @@ case FcTypeLangSet: \ __v__.u.l = va_arg (va, const FcLangSet *); \ break; \ + case FcTypeRange: \ + __v__.u.r = va_arg (va, const FcRange *); \ + break; \ } \ if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \ goto _FcPatternVapBuild_bail1; \ diff --git a/fontconfig/fontconfig/fontconfig.h b/fontconfig/fontconfig/fontconfig.h index 225825127..069cb60dd 100644 --- a/fontconfig/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig/fontconfig.h @@ -75,7 +75,7 @@ typedef int FcBool; #define FC_STYLE "style" /* String */ #define FC_SLANT "slant" /* Int */ #define FC_WEIGHT "weight" /* Int */ -#define FC_SIZE "size" /* Double */ +#define FC_SIZE "size" /* Range (double) */ #define FC_ASPECT "aspect" /* Double */ #define FC_PIXEL_SIZE "pixelsize" /* Double */ #define FC_SPACING "spacing" /* Int */ @@ -194,7 +194,8 @@ typedef enum _FcType { FcTypeMatrix, FcTypeCharSet, FcTypeFTFace, - FcTypeLangSet + FcTypeLangSet, + FcTypeRange } FcType; typedef struct _FcMatrix { @@ -231,6 +232,8 @@ typedef struct _FcPattern FcPattern; typedef struct _FcLangSet FcLangSet; +typedef struct _FcRange FcRange; + typedef struct _FcValue { FcType type; union { @@ -242,6 +245,7 @@ typedef struct _FcValue { const FcCharSet *c; void *f; const FcLangSet *l; + const FcRange *r; } u; } FcValue; @@ -853,6 +857,9 @@ FcPatternAddBool (FcPattern *p, const char *object, FcBool b); FcPublic FcBool FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls); +FcPublic FcBool +FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r); + FcPublic FcResult FcPatternGetInteger (const FcPattern *p, const char *object, int n, int *i); @@ -874,6 +881,9 @@ FcPatternGetBool (const FcPattern *p, const char *object, int n, FcBool *b); FcPublic FcResult FcPatternGetLangSet (const FcPattern *p, const char *object, int n, FcLangSet **ls); +FcPublic FcResult +FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r); + FcPublic FcPattern * FcPatternVaBuild (FcPattern *p, va_list va); @@ -883,6 +893,20 @@ FcPatternBuild (FcPattern *p, ...) FC_ATTRIBUTE_SENTINEL(0); FcPublic FcChar8 * FcPatternFormat (FcPattern *pat, const FcChar8 *format); +/* fcrange.c */ +FcPublic FcRange * +FcRangeCreateDouble (double begin, double end); + +FcPublic FcRange * +FcRangeCreateInteger (FcChar32 begin, FcChar32 end); + +FcPublic void +FcRangeDestroy (FcRange *range); + +FcPublic FcRange * +FcRangeCopy (const FcRange *r); + + /* fcstr.c */ FcPublic FcChar8 * diff --git a/fontconfig/src/Makefile.am b/fontconfig/src/Makefile.am index 066cc03e7..be20eba05 100644 --- a/fontconfig/src/Makefile.am +++ b/fontconfig/src/Makefile.am @@ -151,6 +151,7 @@ libfontconfig_la_SOURCES = \ fcobjs.h \ fcobjshash.h \ fcpat.c \ + fcrange.c \ fcserialize.c \ fcstat.c \ fcstr.c \ diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index 6377fd7c6..cdb8c0f25 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -722,6 +722,11 @@ FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf) v.u.l = FcLangSetPromote (v.u.s, buf); v.type = FcTypeLangSet; } + if (buf && v.type == FcTypeDouble && u.type == FcTypeRange) + { + v.u.r = FcRangePromote (v.u.d, buf); + v.type = FcTypeRange; + } return v; } @@ -894,6 +899,9 @@ FcConfigCompareValue (const FcValue *left_o, break; } break; + case FcTypeRange: + ret = FcRangeCompare (op, left.u.r, right.u.r); + break; } } else @@ -915,10 +923,11 @@ FcConfigCompareValue (const FcValue *left_o, static FcValue FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) { - FcValue v, vl, vr; + FcValue v, vl, vr, vle, vre; FcMatrix *m; FcChar8 *str; FcOp op = FC_OP_GET_OP (e->op); + FcValuePromotionBuffer buf1, buf2; switch ((int) op) { case FcOpInteger: @@ -967,6 +976,11 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) v.u.l = e->u.lval; v = FcValueSave (v); break; + case FcOpRange: + v.type = FcTypeRange; + v.u.r = e->u.rval; + v = FcValueSave (v); + break; case FcOpBool: v.type = FcTypeBool; v.u.b = e->u.bval; @@ -1033,28 +1047,28 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) case FcOpDivide: vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left); vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right); - vl = FcConfigPromote (vl, vr, NULL); - vr = FcConfigPromote (vr, vl, NULL); - if (vl.type == vr.type) + vle = FcConfigPromote (vl, vr, &buf1); + vre = FcConfigPromote (vr, vle, &buf2); + if (vle.type == vre.type) { - switch ((int) vl.type) { + switch ((int) vle.type) { case FcTypeDouble: switch ((int) op) { case FcOpPlus: v.type = FcTypeDouble; - v.u.d = vl.u.d + vr.u.d; + v.u.d = vle.u.d + vre.u.d; break; case FcOpMinus: v.type = FcTypeDouble; - v.u.d = vl.u.d - vr.u.d; + v.u.d = vle.u.d - vre.u.d; break; case FcOpTimes: v.type = FcTypeDouble; - v.u.d = vl.u.d * vr.u.d; + v.u.d = vle.u.d * vre.u.d; break; case FcOpDivide: v.type = FcTypeDouble; - v.u.d = vl.u.d / vr.u.d; + v.u.d = vle.u.d / vre.u.d; break; default: v.type = FcTypeVoid; @@ -1071,11 +1085,11 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) switch ((int) op) { case FcOpOr: v.type = FcTypeBool; - v.u.b = vl.u.b || vr.u.b; + v.u.b = vle.u.b || vre.u.b; break; case FcOpAnd: v.type = FcTypeBool; - v.u.b = vl.u.b && vr.u.b; + v.u.b = vle.u.b && vre.u.b; break; default: v.type = FcTypeVoid; @@ -1086,7 +1100,7 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) switch ((int) op) { case FcOpPlus: v.type = FcTypeString; - str = FcStrPlus (vl.u.s, vr.u.s); + str = FcStrPlus (vle.u.s, vre.u.s); v.u.s = FcStrdup (str); FcStrFree (str); @@ -1105,7 +1119,7 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) m = malloc (sizeof (FcMatrix)); if (m) { - FcMatrixMultiply (m, vl.u.m, vr.u.m); + FcMatrixMultiply (m, vle.u.m, vre.u.m); v.u.m = m; } else @@ -1122,13 +1136,13 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) switch ((int) op) { case FcOpPlus: v.type = FcTypeCharSet; - v.u.c = FcCharSetUnion (vl.u.c, vr.u.c); + v.u.c = FcCharSetUnion (vle.u.c, vre.u.c); if (!v.u.c) v.type = FcTypeVoid; break; case FcOpMinus: v.type = FcTypeCharSet; - v.u.c = FcCharSetSubtract (vl.u.c, vr.u.c); + v.u.c = FcCharSetSubtract (vle.u.c, vre.u.c); if (!v.u.c) v.type = FcTypeVoid; break; @@ -1141,13 +1155,13 @@ FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e) switch ((int) op) { case FcOpPlus: v.type = FcTypeLangSet; - v.u.l = FcLangSetUnion (vl.u.l, vr.u.l); + v.u.l = FcLangSetUnion (vle.u.l, vre.u.l); if (!v.u.l) v.type = FcTypeVoid; break; case FcOpMinus: v.type = FcTypeLangSet; - v.u.l = FcLangSetSubtract (vl.u.l, vr.u.l); + v.u.l = FcLangSetSubtract (vle.u.l, vre.u.l); if (!v.u.l) v.type = FcTypeVoid; break; diff --git a/fontconfig/src/fcdbg.c b/fontconfig/src/fcdbg.c index d74bc2769..ef038f017 100644 --- a/fontconfig/src/fcdbg.c +++ b/fontconfig/src/fcdbg.c @@ -29,6 +29,8 @@ static void _FcValuePrintFile (FILE *f, const FcValue v) { + FcRange r; + switch (v.type) { case FcTypeUnknown: fprintf (f, ""); @@ -61,6 +63,10 @@ _FcValuePrintFile (FILE *f, const FcValue v) case FcTypeFTFace: fprintf (f, "face"); break; + case FcTypeRange: + r = FcRangeCanonicalize (v.u.r); + fprintf (f, "(%g, %g)", r.u.d.begin, r.u.d.end); + break; } } @@ -261,6 +267,8 @@ FcOpPrint (FcOp op_) void FcExprPrint (const FcExpr *expr) { + FcRange r; + if (!expr) printf ("none"); else switch (FC_OP_GET_OP (expr->op)) { case FcOpInteger: printf ("%d", expr->u.ival); break; @@ -277,7 +285,10 @@ FcExprPrint (const FcExpr *expr) FcExprPrint (expr->u.mexpr->yy); printf ("]"); break; - case FcOpRange: break; + case FcOpRange: + r = FcRangeCanonicalize (expr->u.rval); + printf ("(%g, %g)", r.u.d.begin, r.u.d.end); + break; case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break; case FcOpCharSet: printf ("charset\n"); break; case FcOpLangSet: diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c index 4beda7c00..7c16f4841 100644 --- a/fontconfig/src/fcdefault.c +++ b/fontconfig/src/fcdefault.c @@ -219,6 +219,7 @@ FcDefaultSubstitute (FcPattern *pattern) { FcValue v, namelang, v2; int i; + double dpi, size, scale, pixelsize; if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch ) FcPatternObjectAddInteger (pattern, FC_WEIGHT_OBJECT, FC_WEIGHT_NORMAL); @@ -233,32 +234,30 @@ FcDefaultSubstitute (FcPattern *pattern) if (FcPatternObjectGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch) FcPatternObjectAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value); - if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) == FcResultNoMatch) - { - double dpi, size, scale; + if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch) + size = 12.0L; + if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch) + scale = 1.0; + if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch) + dpi = 75.0; - if (FcPatternObjectGetDouble (pattern, FC_SIZE_OBJECT, 0, &size) != FcResultMatch) - { - size = 12.0; - (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT); - FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size); - } - if (FcPatternObjectGetDouble (pattern, FC_SCALE_OBJECT, 0, &scale) != FcResultMatch) - { - scale = 1.0; - (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT); - FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale); - } - size *= scale; - if (FcPatternObjectGetDouble (pattern, FC_DPI_OBJECT, 0, &dpi) != FcResultMatch) - { - dpi = 75.0; - (void) FcPatternObjectDel (pattern, FC_DPI_OBJECT); - FcPatternObjectAddDouble (pattern, FC_DPI_OBJECT, dpi); - } - size *= dpi / 72.0; - FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, size); + if (FcPatternObjectGet (pattern, FC_PIXEL_SIZE_OBJECT, 0, &v) != FcResultMatch) + { + (void) FcPatternObjectDel (pattern, FC_SCALE_OBJECT); + FcPatternObjectAddDouble (pattern, FC_SCALE_OBJECT, scale); + pixelsize = size * scale; + (void) FcPatternObjectDel (pattern, FC_DPI_OBJECT); + FcPatternObjectAddDouble (pattern, FC_DPI_OBJECT, dpi); + pixelsize *= dpi / 72.0; + FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, pixelsize); + } + else + { + size = v.u.d; + size = size / dpi * 72.0 / scale; } + (void) FcPatternObjectDel (pattern, FC_SIZE_OBJECT); + FcPatternObjectAddDouble (pattern, FC_SIZE_OBJECT, size); if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch) { diff --git a/fontconfig/src/fcfreetype.c b/fontconfig/src/fcfreetype.c index d271d69e2..d0932b31b 100644 --- a/fontconfig/src/fcfreetype.c +++ b/fontconfig/src/fcfreetype.c @@ -1107,6 +1107,8 @@ FcFreeTypeQueryFace (const FT_Face face, FcChar8 *hashstr = NULL; FT_Error err; FT_ULong len = 0, alen; + FcRange *r = NULL; + double lower_size = 0.0L, upper_size = DBL_MAX; pat = FcPatternCreate (); if (!pat) @@ -1514,6 +1516,39 @@ FcFreeTypeQueryFace (const FT_Face face, free (complex_); } +#if defined (HAVE_TT_OS2_USUPPEROPTICALPOINTSIZE) && defined (HAVE_TT_OS2_USLOWEROPTICALPOINTSIZE) + if (os2 && os2->version >= 0x0005 && os2->version != 0xffff) + { + /* usLowerPointSize and usUpperPointSize is actually twips */ + lower_size = os2->usLowerOpticalPointSize / 20.0L; + upper_size = os2->usUpperOpticalPointSize / 20.0L; + } +#endif + if (os2) + { + r = FcRangeCreateDouble (lower_size, upper_size); + if (!FcPatternAddRange (pat, FC_SIZE, r)) + { + FcRangeDestroy (r); + goto bail1; + } + FcRangeDestroy (r); + } + else + { + for (i = 0; i < face->num_fixed_sizes; i++) + { + double d = FcGetPixelSize (face, i); + r = FcRangeCreateDouble (d, d); + if (!FcPatternAddRange (pat, FC_SIZE, r)) + { + FcRangeDestroy (r); + goto bail1; + } + FcRangeDestroy (r); + } + } + /* * Type 1: Check for FontInfo dictionary information * Code from g2@magestudios.net (Gerard Escalante) diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index cdf2daba0..dd26fd89a 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include #include @@ -94,6 +96,11 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA; #define FC_MAX(a,b) ((a) > (b) ? (a) : (b)) #define FC_ABS(a) ((a) < 0 ? -(a) : (a)) +#define FcDoubleIsZero(a) (fabs ((a)) <= DBL_EPSILON) +#define FcDoubleCmpEQ(a,b) (fabs ((a) - (b)) <= DBL_EPSILON) +#define FcDoubleCmpGE(a,b) (FcDoubleCmpEQ (a, b) || (a) > (b)) +#define FcDoubleCmpLE(a,b) (FcDoubleCmpEQ (a, b) || (a) < (b)) + /* slim_internal.h */ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun) #define FcPrivate __attribute__((__visibility__("hidden"))) @@ -161,6 +168,7 @@ typedef enum _FcValueBinding { #define FcValueString(v) FcPointerMember(v,u.s,FcChar8) #define FcValueCharSet(v) FcPointerMember(v,u.c,const FcCharSet) #define FcValueLangSet(v) FcPointerMember(v,u.l,const FcLangSet) +#define FcValueRange(v) FcPointerMember(v,u.r,const FcRange) typedef struct _FcValueList *FcValueListPtr; @@ -244,20 +252,38 @@ typedef struct _FcExprName { FcMatchKind kind; } FcExprName; +typedef struct _FcRangeInt { + FcChar32 begin; + FcChar32 end; +} FcRangeInt; +typedef struct _FcRangeDouble { + double begin; + double end; +} FcRangeDouble; +struct _FcRange { + FcBool is_double; + FcBool is_inclusive; + union { + FcRangeInt i; + FcRangeDouble d; + } u; +}; + typedef struct _FcExpr { FcOp op; union { - int ival; - double dval; - const FcChar8 *sval; - FcExprMatrix *mexpr; - FcBool bval; - FcCharSet *cval; - FcLangSet *lval; - - FcExprName name; - const FcChar8 *constant; + int ival; + double dval; + const FcChar8 *sval; + FcExprMatrix *mexpr; + FcBool bval; + FcCharSet *cval; + FcLangSet *lval; + FcRange *rval; + + FcExprName name; + const FcChar8 *constant; struct { struct _FcExpr *left, *right; } tree; @@ -532,13 +558,6 @@ typedef struct _FcFileTime { typedef struct _FcCharMap FcCharMap; -typedef struct _FcRange FcRange; - -struct _FcRange { - FcChar32 begin; - FcChar32 end; -}; - typedef struct _FcStatFS FcStatFS; struct _FcStatFS { @@ -1008,6 +1027,9 @@ FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b); FcPrivate FcBool FcPatternObjectAddLangSet (FcPattern *p, FcObject object, const FcLangSet *ls); +FcPrivate FcBool +FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r); + FcPrivate FcResult FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int n, int *i); @@ -1029,6 +1051,9 @@ FcPatternObjectGetBool (const FcPattern *p, FcObject object, int n, FcBool *b); FcPrivate FcResult FcPatternObjectGetLangSet (const FcPattern *p, FcObject object, int n, FcLangSet **ls); +FcPrivate FcResult +FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r); + FcPrivate FcBool FcPatternAppend (FcPattern *p, FcPattern *s); @@ -1056,6 +1081,32 @@ extern FcPrivate const FcMatrix FcIdentityMatrix; FcPrivate void FcMatrixFree (FcMatrix *mat); +/* fcrange.c */ + +FcPrivate FcRange +FcRangeCanonicalize (const FcRange *range); + +FcPrivate FcRange * +FcRangePromote (double v, FcValuePromotionBuffer *vbuf); + +FcPrivate FcBool +FcRangeIsZero (const FcRange *r); + +FcPrivate FcBool +FcRangeIsInRange (const FcRange *a, const FcRange *b); + +FcPrivate FcBool +FcRangeCompare (FcOp op, const FcRange *a, const FcRange *b); + +FcPrivate FcChar32 +FcRangeHash (const FcRange *r); + +FcPrivate FcBool +FcRangeSerializeAlloc (FcSerialize *serialize, const FcRange *r); + +FcPrivate FcRange * +FcRangeSerialize (FcSerialize *serialize, const FcRange *r); + /* fcstat.c */ FcPrivate int diff --git a/fontconfig/src/fclist.c b/fontconfig/src/fclist.c index a365098a4..6ad297ca4 100644 --- a/fontconfig/src/fclist.c +++ b/fontconfig/src/fclist.c @@ -273,6 +273,8 @@ FcListValueHash (FcValue *value) return (long) v.u.f; case FcTypeLangSet: return FcLangSetHash (v.u.l); + case FcTypeRange: + return FcRangeHash (v.u.r); } return 0; } diff --git a/fontconfig/src/fcmatch.c b/fontconfig/src/fcmatch.c index 93e013f9b..0c0a0670e 100644 --- a/fontconfig/src/fcmatch.c +++ b/fontconfig/src/fcmatch.c @@ -188,6 +188,49 @@ FcCompareSize (FcValue *value1, FcValue *value2) return v; } +static double +FcCompareSizeRange (FcValue *v1, FcValue *v2) +{ + FcValue value1 = FcValueCanonicalize (v1); + FcValue value2 = FcValueCanonicalize (v2); + FcRange *r1 = NULL, *r2 = NULL; + double ret = -1.0; + + switch ((int) value1.type) { + case FcTypeDouble: + r1 = FcRangeCreateDouble (value1.u.d, value1.u.d); + break; + case FcTypeRange: + r1 = FcRangeCopy (value1.u.r); + break; + default: + goto bail; + } + switch ((int) value2.type) { + case FcTypeDouble: + r2 = FcRangeCreateDouble (value2.u.d, value2.u.d); + break; + case FcTypeRange: + r2 = FcRangeCopy (value2.u.r); + break; + default: + goto bail; + } + + if (FcRangeIsInRange (r1, r2)) + ret = 0.0; + else + ret = FC_MIN (fabs (r1->u.d.end - r2->u.d.begin), fabs (r1->u.d.begin - r2->u.d.end)); + +bail: + if (r1) + FcRangeDestroy (r1); + if (r2) + FcRangeDestroy (r2); + + return ret; +} + static double FcCompareFilename (FcValue *v1, FcValue *v2) { @@ -227,6 +270,7 @@ FcCompareHash (FcValue *v1, FcValue *v2) #define PRI_FcCompareLang(n) PRI1(n) #define PRI_FcComparePostScript(n) PRI1(n) #define PRI_FcCompareHash(n) PRI1(n) +#define PRI_FcCompareSizeRange(n) PRI1(n) #define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME) @@ -255,6 +299,7 @@ typedef enum _FcMatcherPriority { PRI_FAMILY_WEAK, PRI_POSTSCRIPT_NAME_WEAK, PRI1(SPACING), + PRI1(SIZE), PRI1(PIXEL_SIZE), PRI1(STYLE), PRI1(SLANT), diff --git a/fontconfig/src/fcname.c b/fontconfig/src/fcname.c index f302948dd..466617872 100644 --- a/fontconfig/src/fcname.c +++ b/fontconfig/src/fcname.c @@ -87,6 +87,10 @@ FcObjectValidType (FcObject object, FcType type) if (type == FcTypeLangSet || type == FcTypeString) return FcTrue; break; + case FcTypeRange: + if (type == FcTypeRange || type == FcTypeDouble) + return FcTrue; + break; default: if (type == t->type) return FcTrue; @@ -273,6 +277,8 @@ FcNameConvert (FcType type, FcChar8 *string) { FcValue v; FcMatrix m; + double b, e; + char *p; v.type = type; switch ((int) v.type) { @@ -307,6 +313,20 @@ FcNameConvert (FcType type, FcChar8 *string) if (!v.u.l) v.type = FcTypeVoid; break; + case FcTypeRange: + if (sscanf ((char *) string, "(%lg %lg)", &b, &e) != 2) + { + v.u.d = strtod ((char *) string, &p); + if (p != NULL && p[0] != 0) + { + v.type = FcTypeVoid; + break; + } + v.type = FcTypeDouble; + } + else + v.u.r = FcRangeCreateDouble (b, e); + break; default: break; } @@ -476,6 +496,7 @@ FcNameUnparseValue (FcStrBuf *buf, { FcChar8 temp[1024]; FcValue v = FcValueCanonicalize(v0); + FcRange r; switch (v.type) { case FcTypeUnknown: @@ -501,6 +522,18 @@ FcNameUnparseValue (FcStrBuf *buf, return FcNameUnparseLangSet (buf, v.u.l); case FcTypeFTFace: return FcTrue; + case FcTypeRange: + r = FcRangeCanonicalize (v.u.r); + if (!FcDoubleIsZero (r.u.d.begin) || !FcDoubleIsZero (r.u.d.end)) + { + if (FcDoubleCmpEQ (r.u.d.begin, r.u.d.end)) + sprintf ((char *) temp, "%g", r.u.d.begin); + else + sprintf ((char *) temp, "(%g %g)", r.u.d.begin, r.u.d.end); + return FcNameUnparseString (buf, temp, 0); + } + else + return FcTrue; } return FcFalse; } @@ -533,12 +566,13 @@ FcNameUnparse (FcPattern *pat) FcChar8 * FcNameUnparseEscaped (FcPattern *pat, FcBool escape) { - FcStrBuf buf; - FcChar8 buf_static[8192]; + FcStrBuf buf, buf2; + FcChar8 buf_static[8192], buf2_static[256]; int i; FcPatternElt *e; FcStrBufInit (&buf, buf_static, sizeof (buf_static)); + FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static)); e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT); if (e) { @@ -548,10 +582,17 @@ FcNameUnparseEscaped (FcPattern *pat, FcBool escape) e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT); if (e) { - if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0)) + FcChar8 *p; + + if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0)) goto bail0; - if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) + if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) goto bail0; + p = FcStrBufDoneStatic (&buf2); + FcStrBufDestroy (&buf2); + if (strlen ((const char *)p) > 1) + if (!FcStrBufString (&buf, p)) + goto bail0; } for (i = 0; i < NUM_OBJECT_TYPES; i++) { diff --git a/fontconfig/src/fcobjs.h b/fontconfig/src/fcobjs.h index a0ee0795b..72e71f99c 100644 --- a/fontconfig/src/fcobjs.h +++ b/fontconfig/src/fcobjs.h @@ -31,7 +31,7 @@ FC_OBJECT (FULLNAMELANG, FcTypeString, NULL) FC_OBJECT (SLANT, FcTypeInteger, FcCompareNumber) FC_OBJECT (WEIGHT, FcTypeInteger, FcCompareNumber) FC_OBJECT (WIDTH, FcTypeInteger, FcCompareNumber) -FC_OBJECT (SIZE, FcTypeDouble, NULL) +FC_OBJECT (SIZE, FcTypeRange, FcCompareSizeRange) FC_OBJECT (ASPECT, FcTypeDouble, NULL) FC_OBJECT (PIXEL_SIZE, FcTypeDouble, FcCompareSize) FC_OBJECT (SPACING, FcTypeInteger, FcCompareNumber) diff --git a/fontconfig/src/fcpat.c b/fontconfig/src/fcpat.c index 986cca391..7e7d54a4e 100644 --- a/fontconfig/src/fcpat.c +++ b/fontconfig/src/fcpat.c @@ -57,6 +57,9 @@ FcValueDestroy (FcValue v) case FcTypeLangSet: FcLangSetDestroy ((FcLangSet *) v.u.l); break; + case FcTypeRange: + FcRangeDestroy ((FcRange *) v.u.r); + break; default: break; } @@ -81,6 +84,10 @@ FcValueCanonicalize (const FcValue *v) new.u.l = FcValueLangSet(v); new.type = FcTypeLangSet; break; + case FcTypeRange: + new.u.r = FcValueRange(v); + new.type = FcTypeRange; + break; default: new = *v; break; @@ -112,6 +119,11 @@ FcValueSave (FcValue v) if (!v.u.l) v.type = FcTypeVoid; break; + case FcTypeRange: + v.u.r = FcRangeCopy (v.u.r); + if (!v.u.r) + v.type = FcTypeVoid; + break; default: break; } @@ -145,6 +157,9 @@ FcValueListDestroy (FcValueListPtr l) FcLangSetDestroy ((FcLangSet *) (l->value.u.l)); break; + case FcTypeRange: + FcRangeDestroy ((FcRange *) (l->value.u.r)); + break; default: break; } @@ -267,6 +282,8 @@ FcValueEqual (FcValue va, FcValue vb) return va.u.f == vb.u.f; case FcTypeLangSet: return FcLangSetEqual (va.u.l, vb.u.l); + case FcTypeRange: + return FcRangeIsInRange (va.u.r, vb.u.r); } return FcFalse; } @@ -320,6 +337,8 @@ FcValueHash (const FcValue *v) FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name); case FcTypeLangSet: return FcLangSetHash (FcValueLangSet(v)); + case FcTypeRange: + return FcRangeHash (v->u.r); } return 0; } @@ -841,6 +860,22 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls) return FcPatternAdd (p, object, v, FcTrue); } +FcBool +FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r) +{ + FcValue v; + + v.type = FcTypeRange; + v.u.r = (FcRange *)r; + return FcPatternObjectAdd (p, object, v, FcTrue); +} + +FcBool +FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r) +{ + return FcPatternObjectAddRange (p, FcObjectFromName (object), r); +} + FcResult FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v) { @@ -1025,6 +1060,31 @@ FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet ** return FcResultMatch; } +FcResult +FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r) +{ + FcValue v; + FcResult res; + + res = FcPatternObjectGet (p, object, id, &v); + if (res != FcResultMatch) + return res; + switch ((int)v.type) { + case FcTypeRange: + *r = (FcRange *)v.u.r; + break; + default: + return FcResultTypeMismatch; + } + return FcResultMatch; +} + +FcResult +FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r) +{ + return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r); +} + FcPattern * FcPatternDuplicate (const FcPattern *orig) { @@ -1230,6 +1290,10 @@ FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl) if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l)) return FcFalse; break; + case FcTypeRange: + if (!FcRangeSerializeAlloc (serialize, vl->value.u.r)) + return FcFalse; + break; default: break; } @@ -1245,6 +1309,7 @@ FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl) FcChar8 *s_serialized; FcCharSet *c_serialized; FcLangSet *l_serialized; + FcRange *r_serialized; FcValueList *head_serialized = NULL; FcValueList *prev_serialized = NULL; @@ -1303,6 +1368,14 @@ FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl) l_serialized, FcLangSet); break; + case FcTypeRange: + r_serialized = FcRangeSerialize (serialize, vl->value.u.r); + if (!r_serialized) + return NULL; + vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value, + r_serialized, + FcRange); + break; default: break; } diff --git a/fontconfig/src/fcrange.c b/fontconfig/src/fcrange.c new file mode 100644 index 000000000..7d0c1c0b1 --- /dev/null +++ b/fontconfig/src/fcrange.c @@ -0,0 +1,207 @@ +/* + * fontconfig/src/fcrange.c + * + * Copyright © 2002 Keith Packard + * + * 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 the author(s) not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHOR(S) 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 "fcint.h" + + +FcRange * +FcRangeCreateDouble (double begin, double end) +{ + FcRange *ret = malloc (sizeof (FcRange)); + + if (ret) + { + ret->is_double = FcTrue; + ret->is_inclusive = FcDoubleCmpEQ (begin, end); + ret->u.d.begin = begin; + ret->u.d.end = end; + } + + return ret; +} + +FcRange * +FcRangeCreateInteger (FcChar32 begin, FcChar32 end) +{ + FcRange *ret = malloc (sizeof (FcRange)); + + if (ret) + { + ret->is_double = FcFalse; + ret->is_inclusive = (begin == end); + ret->u.i.begin = begin; + ret->u.i.end = end; + } + + return ret; +} + +void +FcRangeDestroy (FcRange *range) +{ + free (range); +} + +FcRange * +FcRangeCopy (const FcRange *range) +{ + FcRange *ret; + + if (range->is_double) + ret = FcRangeCreateDouble (range->u.d.begin, range->u.d.end); + else + ret = FcRangeCreateInteger (range->u.i.begin, range->u.i.end); + + return ret; +} + +FcRange +FcRangeCanonicalize (const FcRange *range) +{ + FcRange new; + + if (range->is_double) + new = *range; + else + { + new.is_double = FcTrue; + new.is_inclusive = range->is_inclusive; + new.u.d.begin = (double)range->u.i.begin; + new.u.d.end = (double)range->u.i.end; + } + return new; +} + +FcRange * +FcRangePromote (double v, FcValuePromotionBuffer *vbuf) +{ + typedef struct { + FcRange r; + } FcRangePromotionBuffer; + FcRangePromotionBuffer *buf = (FcRangePromotionBuffer *) vbuf; + + FC_ASSERT_STATIC (sizeof (FcRangePromotionBuffer) <= sizeof (FcValuePromotionBuffer)); + buf->r.is_double = FcTrue; + buf->r.is_inclusive = FcTrue; + buf->r.u.d.begin = v; + buf->r.u.d.end = v; + + return &buf->r; +} + +FcBool +FcRangeIsZero (const FcRange *r) +{ + FcRange c; + + if (!r) + return FcFalse; + c = FcRangeCanonicalize (r); + + return FcDoubleIsZero (c.u.d.begin) && FcDoubleIsZero (c.u.d.end); +} + +FcBool +FcRangeIsInRange (const FcRange *a, const FcRange *b) +{ + FcRange ca, cb; + FcBool f; + + if (!a || !b) + return FcFalse; + + ca = FcRangeCanonicalize (a); + cb = FcRangeCanonicalize (b); + if (ca.is_inclusive & cb.is_inclusive) + f = ca.u.d.end <= cb.u.d.end; + else + f = ca.u.d.end < cb.u.d.end; + + return FcDoubleCmpGE (ca.u.d.begin, cb.u.d.begin) && f; +} + +FcBool +FcRangeCompare (FcOp op, const FcRange *a, const FcRange *b) +{ + FcRange ca, cb; + + switch ((int) op) { + case FcOpEqual: + case FcOpContains: + case FcOpListing: + return FcRangeIsInRange (a, b); + case FcOpNotEqual: + case FcOpNotContains: + return !FcRangeIsInRange (a, b); + case FcOpLess: + ca = FcRangeCanonicalize (a); + cb = FcRangeCanonicalize (b); + return ca.u.d.begin < cb.u.d.begin; + case FcOpLessEqual: + ca = FcRangeCanonicalize (a); + cb = FcRangeCanonicalize (b); + return FcDoubleCmpLE (ca.u.d.begin, cb.u.d.begin); + case FcOpMore: + ca = FcRangeCanonicalize (a); + cb = FcRangeCanonicalize (b); + return ca.u.d.end > cb.u.d.end; + case FcOpMoreEqual: + ca = FcRangeCanonicalize (a); + cb = FcRangeCanonicalize (b); + return FcDoubleCmpGE (ca.u.d.end, cb.u.d.end); + default: + break; + } + return FcFalse; +} + +FcChar32 +FcRangeHash (const FcRange *r) +{ + FcRange c = FcRangeCanonicalize (r); + int b = (int) (c.u.d.begin * 100); + int e = (int) (c.u.d.end * 100); + + return b ^ (b << 1) ^ (e << 9); +} + +FcBool +FcRangeSerializeAlloc (FcSerialize *serialize, const FcRange *r) +{ + if (!FcSerializeAlloc (serialize, r, sizeof (FcRange))) + return FcFalse; + return FcTrue; +} + +FcRange * +FcRangeSerialize (FcSerialize *serialize, const FcRange *r) +{ + FcRange *r_serialize = FcSerializePtr (serialize, r); + + if (!r_serialize) + return NULL; + memcpy (r_serialize, r, sizeof (FcRange)); + + return r_serialize; +} diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c index 91d166f38..c68b0cfce 100644 --- a/fontconfig/src/fcxml.c +++ b/fontconfig/src/fcxml.c @@ -168,6 +168,18 @@ FcExprCreateMatrix (FcConfig *config, const FcExprMatrix *matrix) return e; } +static FcExpr * +FcExprCreateRange (FcConfig *config, FcRange *range) +{ + FcExpr *e = FcConfigAllocExpr (config); + if (e) + { + e->op = FcOpRange; + e->u.rval = FcRangeCopy (range); + } + return e; +} + static FcExpr * FcExprCreateBool (FcConfig *config, FcBool b) { @@ -258,6 +270,7 @@ FcExprDestroy (FcExpr *e) FcExprMatrixFree (e->u.mexpr); break; case FcOpRange: + FcRangeDestroy (e->u.rval); break; case FcOpCharSet: FcCharSetDestroy (e->u.cval); @@ -503,7 +516,7 @@ typedef struct _FcVStack { int integer; double _double; FcExprMatrix *matrix; - FcRange range; + FcRange *range; FcBool bool_; FcCharSet *charset; FcLangSet *langset; @@ -593,6 +606,8 @@ FcTypeName (FcType type) return "FT_Face"; case FcTypeLangSet: return "langset"; + case FcTypeRange: + return "range"; default: return "unknown"; } @@ -608,7 +623,9 @@ FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type) if (value != type) { if ((value == FcTypeLangSet && type == FcTypeString) || - (value == FcTypeString && type == FcTypeLangSet)) + (value == FcTypeString && type == FcTypeLangSet) || + (value == FcTypeInteger && type == FcTypeRange) || + (value == FcTypeDouble && type == FcTypeRange)) return; if (type == FcTypeUnknown) return; @@ -651,6 +668,9 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type) case FcOpLangSet: FcTypecheckValue (parse, FcTypeLangSet, type); break; + case FcOpRange: + FcTypecheckValue (parse, FcTypeRange, type); + break; case FcOpNil: break; case FcOpField: @@ -865,11 +885,10 @@ FcVStackPushMatrix (FcConfigParse *parse, FcExprMatrix *matrix) static FcBool FcVStackPushRange (FcConfigParse *parse, FcRange *range) { - FcVStack *vstack = FcVStackCreateAndPush (parse); + FcVStack *vstack = FcVStackCreateAndPush (parse); if (!vstack) return FcFalse; - vstack->u.range.begin = range->begin; - vstack->u.range.end = range->end; + vstack->u.range = range; vstack->tag = FcVStackRange; return FcTrue; } @@ -1017,9 +1036,11 @@ FcVStackPopAndDestroy (FcConfigParse *parse) case FcVStackMatrix: FcExprMatrixFreeShallow (vstack->u.matrix); break; - case FcVStackRange: case FcVStackBool: break; + case FcVStackRange: + FcRangeDestroy (vstack->u.range); + break; case FcVStackCharSet: FcCharSetDestroy (vstack->u.charset); break; @@ -1232,7 +1253,9 @@ static void FcParseBlank (FcConfigParse *parse) { int n = FcVStackElements (parse); - FcChar32 i; + FcChar32 i, begin, end; + FcRange r; + while (n-- > 0) { FcVStack *v = FcVStackFetch (parse, n); @@ -1248,9 +1271,12 @@ FcParseBlank (FcConfigParse *parse) goto bail; break; case FcVStackRange: - if (v->u.range.begin <= v->u.range.end) + r = FcRangeCanonicalize (v->u.range); + begin = (FcChar32)r.u.d.begin; + end = (FcChar32)r.u.d.end; + if (begin <= end) { - for (i = v->u.range.begin; i <= v->u.range.end; i++) + for (i = begin; i <= end; i++) { if (!FcBlanksAdd (parse->config->blanks, i)) goto bail; @@ -1463,9 +1489,11 @@ static void FcParseRange (FcConfigParse *parse) { FcVStack *vstack; - FcRange r = {0, 0}; - FcChar32 n; + FcRange *r; + FcChar32 n[2] = {0, 0}; int count = 1; + double d[2] = {0.0L, 0.0L}; + FcBool dflag = FcFalse; while ((vstack = FcVStackPeek (parse))) { @@ -1476,31 +1504,52 @@ FcParseRange (FcConfigParse *parse) } switch ((int) vstack->tag) { case FcVStackInteger: - n = vstack->u.integer; + if (dflag) + d[count] = (double)vstack->u.integer; + else + n[count] = vstack->u.integer; + break; + case FcVStackDouble: + if (count == 0 && !dflag) + d[1] = (double)n[1]; + d[count] = vstack->u._double; + dflag = FcTrue; break; default: FcConfigMessage (parse, FcSevereError, "invalid element in range"); - n = 0; + if (dflag) + d[count] = 0.0L; + else + n[count] = 0; break; } - if (count == 1) - r.end = n; - else - r.begin = n; count--; FcVStackPopAndDestroy (parse); } - if (count < 0) + if (count >= 0) + { + FcConfigMessage (parse, FcSevereError, "invalid range"); + return; + } + if (dflag) { - if (r.begin > r.end) + if (d[0] > d[1]) { FcConfigMessage (parse, FcSevereError, "invalid range"); return; } - FcVStackPushRange (parse, &r); + r = FcRangeCreateDouble (d[0], d[1]); } else - FcConfigMessage (parse, FcSevereError, "invalid range"); + { + if (n[0] > n[1]) + { + FcConfigMessage (parse, FcSevereError, "invalid range"); + return; + } + r = FcRangeCreateInteger (n[0], n[1]); + } + FcVStackPushRange (parse, r); } static FcBool @@ -1536,7 +1585,8 @@ FcParseCharSet (FcConfigParse *parse) { FcVStack *vstack; FcCharSet *charset = FcCharSetCreate (); - FcChar32 i; + FcChar32 i, begin, end; + FcRange r; int n = 0; while ((vstack = FcVStackPeek (parse))) @@ -1551,9 +1601,13 @@ FcParseCharSet (FcConfigParse *parse) n++; break; case FcVStackRange: - if (vstack->u.range.begin <= vstack->u.range.end) + r = FcRangeCanonicalize (vstack->u.range); + begin = (FcChar32)r.u.d.begin; + end = (FcChar32)r.u.d.end; + + if (begin <= end) { - for (i = vstack->u.range.begin; i <= vstack->u.range.end; i++) + for (i = begin; i <= end; i++) { if (!FcCharSetAddChar (charset, i)) { @@ -1888,6 +1942,7 @@ FcPopExpr (FcConfigParse *parse) expr = FcExprCreateMatrix (parse->config, vstack->u.matrix); break; case FcVStackRange: + expr = FcExprCreateRange (parse->config, vstack->u.range); break; case FcVStackBool: expr = FcExprCreateBool (parse->config, vstack->u.bool_); @@ -2653,6 +2708,11 @@ FcPopValue (FcConfigParse *parse) if (value.u.l) value.type = FcTypeLangSet; break; + case FcVStackRange: + value.u.r = FcRangeCopy (vstack->u.range); + if (value.u.r) + value.type = FcTypeRange; + break; default: FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d", vstack->tag); -- cgit v1.2.3