[PATCH 1/3] dwrite: Implement font stretch resolution
Nikolay Sivov
nsivov at codeweavers.com
Tue Aug 18 15:48:44 CDT 2015
---
-------------- next part --------------
>From 5574bcc08e91f59ba6b96bc07bc0a06450ccfcbf Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue, 18 Aug 2015 18:17:22 +0300
Subject: [PATCH 1/3] dwrite: Implement font stretch resolution
---
dlls/dwrite/font.c | 221 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 195 insertions(+), 26 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 4e9ba27..ec230c8 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -1982,23 +1982,78 @@ static inline BOOL is_name_separator_char(WCHAR ch)
return ch == ' ' || ch == '.' || ch == '-' || ch == '_';
}
-static BOOL match_pattern_list(struct list *tokens, const WCHAR **patterns)
+struct name_pattern {
+ const WCHAR *part1; /* NULL indicates end of list */
+ const WCHAR *part2; /* optional, if not NULL should point to non-empty string */
+};
+
+static BOOL match_pattern_list(struct list *tokens, const struct name_pattern *patterns)
{
+ const struct name_pattern *pattern;
struct name_token *token;
- const WCHAR *ptr;
int i = 0;
- while ((ptr = patterns[++i])) {
- int len = strlenW(ptr);
+ while ((pattern = &patterns[++i])->part1) {
+ int len_part1 = strlenW(pattern->part1);
+ int len_part2 = pattern->part2 ? strlenW(pattern->part2) : 0;
LIST_FOR_EACH_ENTRY(token, tokens, struct name_token, entry) {
- if (token->len != len)
- continue;
+ if (len_part2 == 0) {
+ /* simple case with single part pattern */
+ if (token->len != len_part1)
+ continue;
+
+ if (!strncmpiW(token->ptr, pattern->part1, len_part1)) {
+ list_remove(&token->entry);
+ heap_free(token);
+ return TRUE;
+ }
+ }
+ else {
+ struct name_token *next_token;
+ struct list *next_entry;
+
+ /* pattern parts are stored in reading order, tokens list is reversed */
+ if (token->len < len_part2)
+ continue;
+
+ /* it's possible to have combined string as a token, like ExtraCondensed */
+ if (token->len == len_part1 + len_part2) {
+ if (strncmpiW(token->ptr, pattern->part1, len_part1))
+ continue;
+
+ if (strncmpiW(&token->ptr[len_part1], pattern->part2, len_part2))
+ continue;
+
+ /* combined string match */
+ list_remove(&token->entry);
+ heap_free(token);
+ return TRUE;
+ }
- if (!strncmpiW(token->ptr, ptr, len)) {
- list_remove(&token->entry);
- heap_free(token);
- return TRUE;
+ /* now it's only possible to have two tokens matched to respective pattern parts */
+ if (token->len != len_part2)
+ continue;
+
+ next_entry = list_next(tokens, &token->entry);
+ if (next_entry) {
+ next_token = LIST_ENTRY(next_entry, struct name_token, entry);
+ if (next_token->len != len_part1)
+ continue;
+
+ if (strncmpiW(token->ptr, pattern->part2, len_part2))
+ continue;
+
+ if (strncmpiW(next_token->ptr, pattern->part1, len_part1))
+ continue;
+
+ /* both parts matched, remove tokens */
+ list_remove(&token->entry);
+ list_remove(&next_token->entry);
+ heap_free(next_token);
+ heap_free(token);
+ return TRUE;
+ }
}
}
}
@@ -2020,22 +2075,22 @@ static DWRITE_FONT_STYLE font_extract_style(struct list *tokens, DWRITE_FONT_STY
static const WCHAR backslantW[] = {'b','a','c','k','s','l','a','n','t',0};
static const WCHAR slantedW[] = {'s','l','a','n','t','e','d',0};
- static const WCHAR *italic_patterns[] = {
- itaW,
- italW,
- italicW,
- cursiveW,
- kursivW,
- NULL
+ static const struct name_pattern italic_patterns[] = {
+ { itaW },
+ { italW },
+ { italicW },
+ { cursiveW },
+ { kursivW },
+ { NULL }
};
- static const WCHAR *oblique_patterns[] = {
- inclinedW,
- obliqueW,
- backslantedW,
- backslantW,
- slantedW,
- NULL
+ static const struct name_pattern oblique_patterns[] = {
+ { inclinedW },
+ { obliqueW },
+ { backslantedW },
+ { backslantW },
+ { slantedW },
+ { NULL }
};
/* italic patterns first */
@@ -2049,6 +2104,108 @@ static DWRITE_FONT_STYLE font_extract_style(struct list *tokens, DWRITE_FONT_STY
return style;
}
+static DWRITE_FONT_STRETCH font_extract_stretch(struct list *tokens, DWRITE_FONT_STRETCH stretch)
+{
+ static const WCHAR compressedW[] = {'c','o','m','p','r','e','s','s','e','d',0};
+ static const WCHAR condensedW[] = {'c','o','n','d','e','n','s','e','d',0};
+ static const WCHAR expandedW[] = {'e','x','p','a','n','d','e','d',0};
+ static const WCHAR extendedW[] = {'e','x','t','e','n','d','e','d',0};
+ static const WCHAR compactW[] = {'c','o','m','p','a','c','t',0};
+ static const WCHAR narrowW[] = {'n','a','r','r','o','w',0};
+ static const WCHAR wideW[] = {'w','i','d','e',0};
+ /* modifiers */
+ static const WCHAR extraW[] = {'e','x','t','r','a',0};
+ static const WCHAR ultraW[] = {'u','l','t','r','a',0};
+ static const WCHAR condW[] = {'c','o','n','d',0};
+ static const WCHAR extW[] = {'e','x','t',0};
+ static const WCHAR semiW[] = {'s','e','m','i',0};
+
+ static const struct name_pattern ultracondensed_patterns[] = {
+ { extraW, compressedW },
+ { extW, compressedW },
+ { ultraW, compressedW },
+ { ultraW, condensedW },
+ { ultraW, condW },
+ { NULL }
+ };
+
+ static const struct name_pattern extracondensed_patterns[] = {
+ { compressedW },
+ { extraW, condensedW },
+ { extW, condensedW },
+ { extraW, condW },
+ { extW, condW },
+ { NULL }
+ };
+
+ static const struct name_pattern semicondensed_patterns[] = {
+ { narrowW },
+ { compactW },
+ { semiW, condensedW },
+ { semiW, condW },
+ { NULL }
+ };
+
+ static const struct name_pattern semiexpanded_patterns[] = {
+ { wideW },
+ { semiW, expandedW },
+ { semiW, extendedW },
+ { NULL }
+ };
+
+ static const struct name_pattern extraexpanded_patterns[] = {
+ { extraW, expandedW },
+ { extW, expandedW },
+ { extraW, extendedW },
+ { extW, extendedW },
+ { NULL }
+ };
+
+ static const struct name_pattern ultraexpanded_patterns[] = {
+ { ultraW, expandedW },
+ { ultraW, extendedW },
+ { NULL }
+ };
+
+ static const struct name_pattern condensed_patterns[] = {
+ { condensedW },
+ { condW },
+ { NULL }
+ };
+
+ static const struct name_pattern expanded_patterns[] = {
+ { expandedW },
+ { extendedW },
+ { NULL }
+ };
+
+ if (match_pattern_list(tokens, ultracondensed_patterns))
+ return DWRITE_FONT_STRETCH_ULTRA_CONDENSED;
+
+ if (match_pattern_list(tokens, extracondensed_patterns))
+ return DWRITE_FONT_STRETCH_EXTRA_CONDENSED;
+
+ if (match_pattern_list(tokens, semicondensed_patterns))
+ return DWRITE_FONT_STRETCH_SEMI_CONDENSED;
+
+ if (match_pattern_list(tokens, semiexpanded_patterns))
+ return DWRITE_FONT_STRETCH_SEMI_EXPANDED;
+
+ if (match_pattern_list(tokens, extraexpanded_patterns))
+ return DWRITE_FONT_STRETCH_EXTRA_EXPANDED;
+
+ if (match_pattern_list(tokens, ultraexpanded_patterns))
+ return DWRITE_FONT_STRETCH_ULTRA_EXPANDED;
+
+ if (match_pattern_list(tokens, condensed_patterns))
+ return DWRITE_FONT_STRETCH_CONDENSED;
+
+ if (match_pattern_list(tokens, expanded_patterns))
+ return DWRITE_FONT_STRETCH_EXPANDED;
+
+ return stretch;
+}
+
static void font_apply_differentiation_rules(struct dwrite_font_data *font, WCHAR *familyW, WCHAR *faceW)
{
static const WCHAR bookW[] = {'B','o','o','k',0};
@@ -2066,6 +2223,7 @@ static void font_apply_differentiation_rules(struct dwrite_font_data *font, WCHA
NULL
};
+ DWRITE_FONT_STRETCH stretch = font->stretch;
static const WCHAR spaceW[] = {' ',0};
WCHAR familynameW[255], facenameW[255];
struct name_token *token, *token2;
@@ -2129,13 +2287,24 @@ static void font_apply_differentiation_rules(struct dwrite_font_data *font, WCHA
/* extract and resolve style */
font->style = font_extract_style(&tokens, font->style);
- /* TODO: extract stretch */
+ /* extract stretch */
+ stretch = font_extract_stretch(&tokens, font->stretch);
/* TODO: extract weight */
/* TODO: resolve weight */
- /* TODO: resolve stretch */
+ /* Resolve stretch - extracted stretch can't be normal, it will override specified stretch if
+ it's leaning in opposite direction from normal comparing to specified stretch or if specified
+ stretch itself is normal (extracted stretch is never normal). */
+ if (stretch != font->stretch) {
+ if ((font->stretch == DWRITE_FONT_STRETCH_NORMAL) ||
+ (font->stretch < DWRITE_FONT_STRETCH_NORMAL && stretch > DWRITE_FONT_STRETCH_NORMAL) ||
+ (font->stretch > DWRITE_FONT_STRETCH_NORMAL && stretch < DWRITE_FONT_STRETCH_NORMAL)) {
+
+ font->stretch = stretch;
+ }
+ }
/* release tokens */
LIST_FOR_EACH_ENTRY_SAFE(token, token2, &tokens, struct name_token, entry) {
--
2.1.4
More information about the wine-patches
mailing list