]>
git.wh0rd.org - fontconfig.git/blob - src/fcmatch.c
2 * $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.11 2002/06/08 17:32:04 keithp Exp $
4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
31 FcCompareInteger (char *object
, FcValue value1
, FcValue value2
)
35 if (value2
.type
!= FcTypeInteger
|| value1
.type
!= FcTypeInteger
)
37 v
= value2
.u
.i
- value1
.u
.i
;
44 FcCompareString (char *object
, FcValue value1
, FcValue value2
)
46 if (value2
.type
!= FcTypeString
|| value1
.type
!= FcTypeString
)
48 return (double) FcStrCmpIgnoreCase (value1
.u
.s
, value2
.u
.s
) != 0;
52 FcCompareBool (char *object
, FcValue value1
, FcValue value2
)
54 if (value2
.type
!= FcTypeBool
|| value1
.type
!= FcTypeBool
)
56 return (double) value2
.u
.b
!= value1
.u
.b
;
60 FcCompareCharSet (char *object
, FcValue value1
, FcValue value2
)
62 if (value2
.type
!= FcTypeCharSet
|| value1
.type
!= FcTypeCharSet
)
64 return (double) FcCharSetSubtractCount (value1
.u
.c
, value2
.u
.c
);
68 FcCompareSize (char *object
, FcValue value1
, FcValue value2
)
72 switch (value1
.type
) {
82 switch (value2
.type
) {
101 * Order is significant, it defines the precedence of
102 * each value, earlier values are more significant than
105 static FcMatcher _FcMatchers
[] = {
106 { FC_FOUNDRY
, FcCompareString
, },
107 #define MATCH_FOUNDRY 0
109 { FC_CHARSET
, FcCompareCharSet
},
110 #define MATCH_CHARSET 1
112 { FC_LANG
, FcCompareString
},
115 { FC_FAMILY
, FcCompareString
, },
116 #define MATCH_FAMILY 3
118 { FC_SPACING
, FcCompareInteger
, },
119 #define MATCH_SPACING 4
121 { FC_PIXEL_SIZE
, FcCompareSize
, },
122 #define MATCH_PIXEL_SIZE 5
124 { FC_STYLE
, FcCompareString
, },
125 #define MATCH_STYLE 6
127 { FC_SLANT
, FcCompareInteger
, },
128 #define MATCH_SLANT 7
130 { FC_WEIGHT
, FcCompareInteger
, },
131 #define MATCH_WEIGHT 8
133 { FC_ANTIALIAS
, FcCompareBool
, },
134 #define MATCH_ANTIALIAS 9
136 { FC_RASTERIZER
, FcCompareString
, },
137 #define MATCH_RASTERIZER 10
139 { FC_OUTLINE
, FcCompareBool
, },
140 #define MATCH_OUTLINE 11
143 #define NUM_MATCHER (sizeof _FcMatchers / sizeof _FcMatchers[0])
146 FcCompareValueList (const char *object
,
147 FcValueList
*v1orig
, /* pattern */
148 FcValueList
*v2orig
, /* target */
153 FcValueList
*v1
, *v2
;
159 * Locate the possible matching entry by examining the
160 * first few characters in object
163 switch (FcToLower (object
[0])) {
165 switch (FcToLower (object
[1])) {
167 i
= MATCH_FOUNDRY
; break;
169 i
= MATCH_FAMILY
; break;
173 i
= MATCH_CHARSET
; break;
175 i
= MATCH_ANTIALIAS
; break;
177 i
= MATCH_LANG
; break;
179 switch (FcToLower (object
[1])) {
181 i
= MATCH_SPACING
; break;
183 i
= MATCH_STYLE
; break;
185 i
= MATCH_SLANT
; break;
189 i
= MATCH_PIXEL_SIZE
; break;
191 i
= MATCH_WEIGHT
; break;
193 i
= MATCH_RASTERIZER
; break;
195 i
= MATCH_OUTLINE
; break;
198 FcStrCmpIgnoreCase ((FcChar8
*) _FcMatchers
[i
].object
,
199 (FcChar8
*) object
) != 0)
202 *bestValue
= v2orig
->value
;
206 for (i
= 0; i
< NUM_MATCHER
; i
++)
208 if (!FcStrCmpIgnoreCase ((FcChar8
*) _FcMatchers
[i
].object
,
212 if (i
== NUM_MATCHER
)
215 *bestValue
= v2orig
->value
;
221 for (v1
= v1orig
; v1
; v1
= v1
->next
)
223 for (v2
= v2orig
; v2
; v2
= v2
->next
)
225 v
= (*_FcMatchers
[i
].compare
) (_FcMatchers
[i
].object
,
230 *result
= FcResultTypeMismatch
;
233 if (FcDebug () & FC_DBG_MATCHV
)
234 printf (" v %g j %d ", v
, j
);
239 *bestValue
= v2
->value
;
245 if (FcDebug () & FC_DBG_MATCHV
)
247 printf (" %s: %g ", object
, best
);
248 FcValueListPrint (v1orig
);
250 FcValueListPrint (v2orig
);
259 * Return a value indicating the distance between the two lists of
264 FcCompare (FcPattern
*pat
,
271 for (i
= 0; i
< NUM_MATCHER
; i
++)
276 while (i1
< pat
->num
&& i2
< fnt
->num
)
278 i
= strcmp (pat
->elts
[i1
].object
, fnt
->elts
[i2
].object
);
285 if (!FcCompareValueList (pat
->elts
[i1
].object
,
286 pat
->elts
[i1
].values
,
287 fnt
->elts
[i2
].values
,
298 for (i1
= 0; i1
< pat
->num
; i1
++)
300 for (i2
= 0; i2
< fnt
->num
; i2
++)
302 if (!strcmp (pat
->elts
[i1
].object
, fnt
->elts
[i2
].object
))
313 FcFontRenderPrepare (FcConfig
*config
,
319 FcPatternElt
*fe
, *pe
;
323 new = FcPatternCreate ();
326 for (i
= 0; i
< font
->num
; i
++)
329 pe
= FcPatternFindElt (pat
, fe
->object
);
333 double score
[NUM_MATCHER
];
335 for (j
= 0; j
< NUM_MATCHER
; j
++)
337 if (!FcCompareValueList (pe
->object
, pe
->values
,
338 fe
->values
, &v
, 0, &result
))
340 FcPatternDestroy (new);
343 for (j
= 0; j
< NUM_MATCHER
; j
++)
344 if (score
[j
] >= 100.0)
348 for (pv
= pe
->values
; pv
; pv
= pv
->next
)
349 FcPatternAdd (new, fe
->object
, pv
->value
, FcTrue
);
354 v
= fe
->values
->value
;
355 FcPatternAdd (new, fe
->object
, v
, FcFalse
);
357 for (i
= 0; i
< pat
->num
; i
++)
360 fe
= FcPatternFindElt (font
, pe
->object
);
362 FcPatternAdd (new, pe
->object
, pe
->values
->value
, FcTrue
);
364 FcConfigSubstitute (config
, new, FcMatchFont
);
369 FcFontSetMatch (FcConfig
*config
,
375 double score
[NUM_MATCHER
], bestscore
[NUM_MATCHER
];
382 for (i
= 0; i
< NUM_MATCHER
; i
++)
385 if (FcDebug () & FC_DBG_MATCH
)
392 config
= FcConfigGetCurrent ();
396 for (set
= 0; set
< nsets
; set
++)
401 for (f
= 0; f
< s
->nfont
; f
++)
403 if (FcDebug () & FC_DBG_MATCHV
)
405 printf ("Font %d ", f
);
406 FcPatternPrint (s
->fonts
[f
]);
408 if (!FcCompare (p
, s
->fonts
[f
], score
, result
))
410 if (FcDebug () & FC_DBG_MATCHV
)
413 for (i
= 0; i
< NUM_MATCHER
; i
++)
415 printf (" %g", score
[i
]);
419 for (i
= 0; i
< NUM_MATCHER
; i
++)
421 if (best
&& bestscore
[i
] < score
[i
])
423 if (!best
|| score
[i
] < bestscore
[i
])
425 for (i
= 0; i
< NUM_MATCHER
; i
++)
426 bestscore
[i
] = score
[i
];
433 if (FcDebug () & FC_DBG_MATCH
)
435 printf ("Best score");
436 for (i
= 0; i
< NUM_MATCHER
; i
++)
437 printf (" %g", bestscore
[i
]);
438 FcPatternPrint (best
);
442 *result
= FcResultNoMatch
;
445 return FcFontRenderPrepare (config
, p
, best
);
449 FcFontMatch (FcConfig
*config
,
458 config
= FcConfigGetCurrent ();
463 if (config
->fonts
[FcSetSystem
])
464 sets
[nsets
++] = config
->fonts
[FcSetSystem
];
465 if (config
->fonts
[FcSetApplication
])
466 sets
[nsets
++] = config
->fonts
[FcSetApplication
];
467 return FcFontSetMatch (config
, sets
, nsets
, p
, result
);
470 typedef struct _FcSortNode
{
472 double score
[NUM_MATCHER
];
476 FcSortCompare (const void *aa
, const void *ab
)
478 FcSortNode
*a
= *(FcSortNode
**) aa
;
479 FcSortNode
*b
= *(FcSortNode
**) ab
;
480 double *as
= &a
->score
[0];
481 double *bs
= &b
->score
[0];
482 double ad
= 0, bd
= 0;
486 while (i
-- && (ad
= *as
++) == (bd
= *bs
++))
488 return ad
< bd
? -1 : ad
> bd
? 1 : 0;
492 FcSortWalk (FcSortNode
**n
, int nnode
, FcFontSet
*fs
, FcCharSet
**cs
, FcBool trim
)
500 if (FcPatternGetCharSet (node
->pattern
, FC_CHARSET
, 0, &ncs
) ==
504 * If this font isn't a subset of the previous fonts,
507 if (!trim
|| !*cs
|| !FcCharSetIsSubset (ncs
, *cs
))
511 ncs
= FcCharSetUnion (ncs
, *cs
);
514 FcCharSetDestroy (*cs
);
517 ncs
= FcCharSetCopy (ncs
);
519 FcPatternReference (node
->pattern
);
520 if (!FcFontSetAdd (fs
, node
->pattern
))
522 FcPatternDestroy (node
->pattern
);
532 FcFontSetSortDestroy (FcFontSet
*fs
)
534 FcFontSetDestroy (fs
);
538 FcFontSetSort (FcConfig
*config
,
549 FcSortNode
**nodeps
, **nodep
;
558 for (set
= 0; set
< nsets
; set
++)
567 nodes
= malloc (nnodes
* sizeof (FcSortNode
) + nnodes
* sizeof (FcSortNode
*));
570 nodeps
= (FcSortNode
**) (nodes
+ nnodes
);
574 for (set
= 0; set
< nsets
; set
++)
579 for (f
= 0; f
< s
->nfont
; f
++)
581 if (FcDebug () & FC_DBG_MATCHV
)
583 printf ("Font %d ", f
);
584 FcPatternPrint (s
->fonts
[f
]);
586 new->pattern
= s
->fonts
[f
];
587 if (!FcCompare (p
, new->pattern
, new->score
, result
))
589 if (FcDebug () & FC_DBG_MATCHV
)
592 for (i
= 0; i
< NUM_MATCHER
; i
++)
594 printf (" %g", new->score
[i
]);
604 nnodes
= new - nodes
;
606 qsort (nodeps
, nnodes
, sizeof (FcSortNode
*),
609 ret
= FcFontSetCreate ();
615 if (!FcSortWalk (nodeps
, nnodes
, ret
, &cs
, trim
))
621 FcCharSetDestroy (cs
);
629 FcCharSetDestroy (cs
);
630 FcFontSetDestroy (ret
);
638 FcFontSort (FcConfig
*config
,
649 config
= FcConfigGetCurrent ();
654 if (config
->fonts
[FcSetSystem
])
655 sets
[nsets
++] = config
->fonts
[FcSetSystem
];
656 if (config
->fonts
[FcSetApplication
])
657 sets
[nsets
++] = config
->fonts
[FcSetApplication
];
658 return FcFontSetSort (config
, sets
, nsets
, p
, trim
, csp
, result
);