From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/analyzer.c | 121 ++++++---------- dlls/dwrite/bidi.c | 273 ++++++++++++++++++----------------- dlls/dwrite/dwrite_private.h | 11 +- 3 files changed, 199 insertions(+), 206 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c index 8d7053a066e..6c3dc7e40d1 100644 --- a/dlls/dwrite/analyzer.c +++ b/dlls/dwrite/analyzer.c @@ -30,6 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
extern const unsigned short wine_linebreak_table[] DECLSPEC_HIDDEN; extern const unsigned short wine_scripts_table[] DECLSPEC_HIDDEN; +extern const unsigned short bidi_direction_table[] DECLSPEC_HIDDEN;
/* Number of characters needed for LOCALE_SNATIVEDIGITS */ #define NATIVE_DIGITS_LEN 11 @@ -1224,50 +1225,6 @@ static ULONG WINAPI dwritetextanalyzer_Release(IDWriteTextAnalyzer2 *iface) return 1; }
-/* This helper tries to get 'length' chars from a source, allocating a buffer only if source failed to provide enough - data after a first request. */ -static HRESULT get_text_source_ptr(IDWriteTextAnalysisSource *source, UINT32 position, UINT32 length, const WCHAR **text, WCHAR **buff) -{ - HRESULT hr; - UINT32 len; - - *buff = NULL; - *text = NULL; - len = 0; - hr = IDWriteTextAnalysisSource_GetTextAtPosition(source, position, text, &len); - if (FAILED(hr)) return hr; - - if (len < length) { - UINT32 read; - - *buff = calloc(length, sizeof(WCHAR)); - if (!*buff) - return E_OUTOFMEMORY; - if (*text) - memcpy(*buff, *text, len*sizeof(WCHAR)); - read = len; - - while (read < length && *text) { - *text = NULL; - len = 0; - hr = IDWriteTextAnalysisSource_GetTextAtPosition(source, position+read, text, &len); - if (FAILED(hr)) - { - free(*buff); - return hr; - } - if (!*text) - break; - memcpy(*buff + read, *text, min(len, length-read)*sizeof(WCHAR)); - read += len; - } - - *text = *buff; - } - - return hr; -} - static HRESULT WINAPI dwritetextanalyzer_AnalyzeScript(IDWriteTextAnalyzer2 *iface, IDWriteTextAnalysisSource* source, UINT32 position, UINT32 length, IDWriteTextAnalysisSink* sink) { @@ -1284,14 +1241,24 @@ static HRESULT WINAPI dwritetextanalyzer_AnalyzeScript(IDWriteTextAnalyzer2 *ifa return analyze_script(&context, sink); }
+static inline unsigned int get_bidi_char_length(const struct bidi_char *c) +{ + return c->ch > 0xffff ? 2 : 1; +} + +static inline UINT8 get_char_bidi_class(UINT32 ch) +{ + return get_table_entry_32(bidi_direction_table, ch); +} + static HRESULT WINAPI dwritetextanalyzer_AnalyzeBidi(IDWriteTextAnalyzer2 *iface, IDWriteTextAnalysisSource* source, UINT32 position, UINT32 length, IDWriteTextAnalysisSink* sink) { - UINT8 *levels = NULL, *explicit = NULL; - UINT8 baselevel, level, explicit_level; - UINT32 pos, i, seq_length; - WCHAR *buff = NULL; - const WCHAR *text; + struct text_source_context context; + UINT8 baselevel, resolved, explicit; + unsigned int i, chars_count = 0; + struct bidi_char *chars, *ptr; + UINT32 pos, seq_length; HRESULT hr;
TRACE("%p, %u, %u, %p.\n", source, position, length, sink); @@ -1299,49 +1266,57 @@ static HRESULT WINAPI dwritetextanalyzer_AnalyzeBidi(IDWriteTextAnalyzer2 *iface if (!length) return S_OK;
- hr = get_text_source_ptr(source, position, length, &text, &buff); - if (FAILED(hr)) - return hr; + if (!(chars = calloc(length, sizeof(*chars)))) + return E_OUTOFMEMORY;
- levels = calloc(length, sizeof(*levels)); - explicit = calloc(length, sizeof(*explicit)); + ptr = chars; + text_source_context_init(&context, source, position, length); + while (!text_source_get_next_u32_char(&context)) + { + ptr->ch = context.ch; + ptr->nominal_bidi_class = ptr->bidi_class = get_char_bidi_class(context.ch); + ptr++;
- if (!levels || !explicit) { - hr = E_OUTOFMEMORY; - goto done; + ++chars_count; }
+ /* Resolve levels using utf-32 codepoints, size differences are accounted for + when levels are reported with SetBidiLevel(). */ + baselevel = IDWriteTextAnalysisSource_GetParagraphReadingDirection(source); - hr = bidi_computelevels(text, length, baselevel, explicit, levels); + hr = bidi_computelevels(chars, chars_count, baselevel); if (FAILED(hr)) goto done;
- level = levels[0]; - explicit_level = explicit[0]; pos = position; - seq_length = 1; + resolved = chars->resolved; + explicit = chars->explicit; + seq_length = get_bidi_char_length(chars);
- for (i = 1; i < length; i++) { - if (levels[i] == level && explicit[i] == explicit_level) - seq_length++; - else { - hr = IDWriteTextAnalysisSink_SetBidiLevel(sink, pos, seq_length, explicit_level, level); + for (i = 1, ptr = chars + 1; i < chars_count; ++i, ++ptr) + { + if (ptr->resolved == resolved && ptr->explicit == explicit) + { + seq_length += get_bidi_char_length(ptr); + } + else + { + hr = IDWriteTextAnalysisSink_SetBidiLevel(sink, pos, seq_length, explicit, resolved); if (FAILED(hr)) goto done;
pos += seq_length; - seq_length = 1; - level = levels[i]; - explicit_level = explicit[i]; + seq_length = get_bidi_char_length(ptr); + resolved = ptr->resolved; + explicit = ptr->explicit; } } + /* one char length case or normal completion call */ - hr = IDWriteTextAnalysisSink_SetBidiLevel(sink, pos, seq_length, explicit_level, level); + hr = IDWriteTextAnalysisSink_SetBidiLevel(sink, pos, seq_length, explicit, resolved);
done: - free(explicit); - free(levels); - free(buff); + free(chars);
return hr; } diff --git a/dlls/dwrite/bidi.c b/dlls/dwrite/bidi.c index 863283b4556..142c82f19d0 100644 --- a/dlls/dwrite/bidi.c +++ b/dlls/dwrite/bidi.c @@ -136,28 +136,19 @@ static const char debug_type[][4] = "PDI", };
-static inline void bidi_dump_types(const char* header, const UINT8 *types, UINT32 start, UINT32 end) +static inline void bidi_dump_types(const char* header, const struct bidi_char *chars, UINT32 start, UINT32 end) { int i, len = 0; TRACE("%s:", header); for (i = start; i < end && len < 200; i++) { - TRACE(" %s", debug_type[types[i]]); - len += strlen(debug_type[types[i]])+1; + TRACE(" %s", debug_type[chars[i].bidi_class]); + len += strlen(debug_type[chars[i].bidi_class]) + 1; } if (i != end) TRACE("..."); TRACE("\n"); }
-/* Convert the libwine information to the direction enum */ -static void bidi_classify(const WCHAR *string, UINT8 *chartype, UINT32 count) -{ - UINT32 i; - - for (i = 0; i < count; ++i) - chartype[i] = get_table_entry_32( bidi_direction_table, string[i] ); -} - /* RESOLVE EXPLICIT */
static inline UINT8 get_greater_even_level(UINT8 level) @@ -181,14 +172,6 @@ static inline UINT8 get_embedding_direction(UINT8 level) Recursively resolves explicit embedding levels and overrides. Implements rules X1-X9, of the Unicode Bidirectional Algorithm.
- Input: Base embedding level and direction - Character count - - Output: Array of embedding levels - - In/Out: Array of direction classes - - Note: The function uses two simple counters to keep track of matching explicit codes and PDF. Use the default argument for the outermost call. The nesting counter counts the recursion @@ -211,13 +194,13 @@ typedef struct tagStackItem
#define valid_level(x) (x <= MAX_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0)
-static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels, UINT32 count) +static void bidi_resolve_explicit(struct bidi_char *chars, unsigned int count, UINT8 baselevel) { /* X1 */ int overflow_isolate_count = 0; int overflow_embedding_count = 0; int valid_isolate_count = 0; - UINT32 i; + unsigned int i;
StackItem stack[MAX_DEPTH+2]; int stack_top = MAX_DEPTH+1; @@ -226,15 +209,18 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels stack[stack_top].override = NI; stack[stack_top].isolate = FALSE;
- for (i = 0; i < count; i++) { + for (i = 0; i < count; ++i) + { + struct bidi_char *c = &chars[i]; UINT8 least_odd, least_even;
- switch (classes[i]) { + switch (c->bidi_class) + {
/* X2 */ case RLE: least_odd = get_greater_odd_level(stack[stack_top].level); - levels[i] = valid_level(least_odd) ? least_odd : stack[stack_top].level; + c->resolved = valid_level(least_odd) ? least_odd : stack[stack_top].level; if (valid_level(least_odd)) push_stack(least_odd, NI, FALSE); else if (overflow_isolate_count == 0) @@ -244,7 +230,7 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels /* X3 */ case LRE: least_even = get_greater_even_level(stack[stack_top].level); - levels[i] = valid_level(least_even) ? least_even : stack[stack_top].level; + c->resolved = valid_level(least_even) ? least_even : stack[stack_top].level; if (valid_level(least_even)) push_stack(least_even, NI, FALSE); else if (overflow_isolate_count == 0) @@ -254,7 +240,7 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels /* X4 */ case RLO: least_odd = get_greater_odd_level(stack[stack_top].level); - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (valid_level(least_odd)) push_stack(least_odd, R, FALSE); else if (overflow_isolate_count == 0) @@ -264,7 +250,7 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels /* X5 */ case LRO: least_even = get_greater_even_level(stack[stack_top].level); - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (valid_level(least_even)) push_stack(least_even, L, FALSE); else if (overflow_isolate_count == 0) @@ -274,7 +260,7 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels /* X5a */ case RLI: least_odd = get_greater_odd_level(stack[stack_top].level); - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (valid_level(least_odd)) { valid_isolate_count++; @@ -287,7 +273,7 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels /* X5b */ case LRI: least_even = get_greater_even_level(stack[stack_top].level); - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (valid_level(least_even)) { valid_isolate_count++; @@ -304,15 +290,17 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels int skipping = 0; int j;
- levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; for (j = i+1; j < count; j++) { - if (classes[j] == LRI || classes[j] == RLI || classes[j] == FSI) + const struct bidi_char *p = &chars[j]; + + if (p->bidi_class == LRI || p->bidi_class == RLI || p->bidi_class == FSI) { skipping++; continue; } - else if (classes[j] == PDI) + else if (p->bidi_class == PDI) { if (skipping) skipping --; @@ -323,12 +311,12 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels
if (skipping) continue;
- if (classes[j] == L) + if (p->bidi_class == L) { new_level = 0; break; } - else if (classes[j] == R || classes[j] == AL) + else if (p->bidi_class == R || p->bidi_class == AL) { new_level = 1; break; @@ -372,9 +360,9 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels case ET: case S: case WS: - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (stack[stack_top].override != NI) - classes[i] = stack[stack_top].override; + c->resolved = stack[stack_top].override; break;
/* X6a */ @@ -388,12 +376,12 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels pop_stack(); valid_isolate_count--; } - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; break;
/* X7 */ case PDF: - levels[i] = stack[stack_top].level; + c->resolved = stack[stack_top].level; if (overflow_isolate_count) {/* do nothing */} else if (overflow_embedding_count) overflow_embedding_count--; else if (!stack[stack_top].isolate && stack_top < (MAX_DEPTH+1)) @@ -402,29 +390,44 @@ static void bidi_resolve_explicit(UINT8 baselevel, UINT8 *classes, UINT8 *levels
/* X8 */ default: - levels[i] = baselevel; + c->resolved = baselevel; break; } + + c->explicit = c->resolved; } + /* X9: Based on 5.2 Retaining Explicit Formatting Characters */ - for (i = 0; i < count ; i++) - if (classes[i] == RLE || classes[i] == LRE || classes[i] == RLO || classes[i] == LRO || classes[i] == PDF) - classes[i] = BN; + for (i = 0; i < count; ++i) + { + switch (chars[i].bidi_class) + { + case RLE: + case LRE: + case RLO: + case LRO: + case PDF: + chars[i].bidi_class = BN; + break; + default: + ; + } + } }
-static inline int get_prev_valid_char_index(const UINT8 *classes, int index, int back_fence) +static inline int get_prev_valid_char_index(const struct bidi_char *chars, int index, int back_fence) { if (index == -1 || index == back_fence) return index; index--; - while (index > back_fence && classes[index] == BN) index--; + while (index > back_fence && chars[index].bidi_class == BN) index--; return index; }
-static inline int get_next_valid_char_index(const UINT8 *classes, int index, int front_fence) +static inline int get_next_valid_char_index(const struct bidi_char *chars, int index, int front_fence) { if (index == front_fence) return index; index++; - while (index < front_fence && classes[index] == BN) index++; + while (index < front_fence && chars[index].bidi_class == BN) index++; return index; }
@@ -841,34 +844,31 @@ static void bidi_resolve_neutrals(IsolatedRun *run) Recursively resolves implicit embedding levels. Implements rules I1 and I2 of the Unicode Bidirectional Algorithm.
- Input: Array of direction classes - Character count - Base level - - In/Out: Array of embedding levels - Note: levels may exceed 15 on output. Accepted subset of direction classes R, L, AN, EN ------------------------------------------------------------------------*/ -static void bidi_resolve_implicit(const UINT8 *classes, UINT8 *levels, int sos, int eos) +static void bidi_resolve_implicit(struct bidi_char *chars, unsigned int count) { - int i; + unsigned int i;
/* I1/2 */ - for (i = sos; i <= eos; i++) { - if (classes[i] == BN) + for (i = 0; i < count; ++i) + { + struct bidi_char *c = &chars[i]; + + if (c->bidi_class == BN) continue;
- ASSERT(classes[i] != ON); /* "No Neutrals allowed to survive here." */ - ASSERT(classes[i] <= EN); /* "Out of range." */ + ASSERT(c->bidi_class != ON); /* "No Neutrals allowed to survive here." */ + ASSERT(c->bidi_class <= EN); /* "Out of range." */
- if (odd(levels[i]) && (classes[i] == L || classes[i] == EN || classes[i] == AN)) - levels[i]++; - else if (!odd(levels[i]) && classes[i] == R) - levels[i]++; - else if (!odd(levels[i]) && (classes[i] == EN || classes[i] == AN)) - levels[i] += 2; + if (odd(c->resolved) && (c->bidi_class == L || c->bidi_class == EN || c->bidi_class == AN)) + c->resolved++; + else if (!odd(c->resolved) && c->bidi_class == R) + c->resolved++; + else if (!odd(c->resolved) && (c->bidi_class == EN || c->bidi_class == AN)) + c->resolved += 2; } }
@@ -892,31 +892,41 @@ static inline BOOL is_rule_L1_reset_class(UINT8 class) } }
-static void bidi_resolve_resolved(UINT8 baselevel, const UINT8 *classes, UINT8 *levels, int sos, int eos) +static void bidi_resolve_resolved(struct bidi_char *chars, unsigned int count, UINT8 baselevel) { - int i; + int i, sos = 0, eos = count - 1;
/* L1 */ - for (i = sos; i <= eos; i++) { - if (classes[i] == B || classes[i] == S) { - int j = i - 1; - while (i > sos && j >= sos && is_rule_L1_reset_class(classes[j])) - levels[j--] = baselevel; - levels[i] = baselevel; - } - else if (classes[i] == LRE || classes[i] == RLE || classes[i] == LRO || classes[i] == RLO || - classes[i] == PDF || classes[i] == BN) { - levels[i] = i ? levels[i - 1] : baselevel; + for (i = sos; i <= eos; i++) + { + switch (chars[i].nominal_bidi_class) + { + case B: + case S: + { + int j = i - 1; + while (i > sos && j >= sos && is_rule_L1_reset_class(chars[j].nominal_bidi_class)) + chars[j--].resolved = baselevel; + chars[i].resolved = baselevel; + } + break; + case LRE: case RLE: case LRO: case RLO: case PDF: case BN: + chars[i].resolved = i ? chars[i - 1].resolved : baselevel; + break; + default: + ; } - if (i == eos && is_rule_L1_reset_class(classes[i])) { + + if (i == eos && is_rule_L1_reset_class(chars[i].nominal_bidi_class)) + { int j = i; - while (j >= sos && is_rule_L1_reset_class(classes[j])) - levels[j--] = baselevel; + while (j >= sos && is_rule_L1_reset_class(chars[j].nominal_bidi_class)) + chars[j--].resolved = baselevel; } } }
-static HRESULT bidi_compute_isolating_runs_set(UINT8 baselevel, UINT8 *classes, UINT8 *levels, const WCHAR *string, UINT32 count, struct list *set) +static HRESULT bidi_compute_isolating_runs_set(struct bidi_char *chars, unsigned int count, UINT8 baselevel, struct list *set) { int run_start, run_end, i; int run_count = 0; @@ -930,23 +940,26 @@ static HRESULT bidi_compute_isolating_runs_set(UINT8 baselevel, UINT8 *classes,
/* Build Runs */ run_start = 0; - while (run_start < count) { - run_end = get_next_valid_char_index(classes, run_start, count); - while (run_end < count && levels[run_end] == levels[run_start]) - run_end = get_next_valid_char_index(classes, run_end, count); + while (run_start < count) + { + run_end = get_next_valid_char_index(chars, run_start, count); + while (run_end < count && chars[run_end].resolved == chars[run_start].resolved) + run_end = get_next_valid_char_index(chars, run_end, count); run_end--; runs[run_count].start = run_start; runs[run_count].end = run_end; - runs[run_count].e = levels[run_start]; - run_start = get_next_valid_char_index(classes, run_end, count); + runs[run_count].e = chars[run_start].resolved; + run_start = get_next_valid_char_index(chars, run_end, count); run_count++; }
/* Build Isolating Runs */ i = 0; - while (i < run_count) { + while (i < run_count) + { int k = i; - if (runs[k].start >= 0) { + if (runs[k].start >= 0) + { IsolatedRun *current_isolated; int type_fence, real_end; int j; @@ -961,42 +974,45 @@ static HRESULT bidi_compute_isolating_runs_set(UINT8 baselevel, UINT8 *classes, current_isolated->e = runs[k].e; current_isolated->length = (runs[k].end - runs[k].start)+1;
- for (j = 0; j < current_isolated->length; j++) { - current_isolated->item[j].class = &classes[runs[k].start+j]; - current_isolated->item[j].ch = string[runs[k].start+j]; + for (j = 0; j < current_isolated->length; ++j) + { + current_isolated->item[j].class = &chars[runs[k].start+j].bidi_class; + current_isolated->item[j].ch = chars[runs[k].start+j].ch; }
run_end = runs[k].end;
TRACE("{ [%i -- %i]",run_start, run_end);
- if (classes[run_end] == BN) - run_end = get_prev_valid_char_index(classes, run_end, runs[k].start); + if (chars[run_end].bidi_class == BN) + run_end = get_prev_valid_char_index(chars, run_end, runs[k].start);
- while (run_end < count && (classes[run_end] == RLI || classes[run_end] == LRI || classes[run_end] == FSI)) { + while (run_end < count && (chars[run_end].bidi_class == RLI || chars[run_end].bidi_class == LRI || chars[run_end].bidi_class == FSI)) + { j = k+1; search: - while (j < run_count && classes[runs[j].start] != PDI) j++; + while (j < run_count && chars[runs[j].start].bidi_class != PDI) j++; if (j < run_count && runs[i].e != runs[j].e) { j++; goto search; }
- if (j != run_count) { + if (j != run_count) + { int l = current_isolated->length; int m;
current_isolated->length += (runs[j].end - runs[j].start)+1; for (m = 0; l < current_isolated->length; l++, m++) { - current_isolated->item[l].class = &classes[runs[j].start+m]; - current_isolated->item[l].ch = string[runs[j].start+m]; + current_isolated->item[l].class = &chars[runs[j].start + m].bidi_class; + current_isolated->item[l].ch = chars[runs[j].start + m].ch; }
TRACE("[%i -- %i]", runs[j].start, runs[j].end);
run_end = runs[j].end; - if (classes[run_end] == BN) - run_end = get_prev_valid_char_index(classes, run_end, runs[i].start); + if (chars[run_end].bidi_class == BN) + run_end = get_prev_valid_char_index(chars, run_end, runs[i].start); runs[j].start = -1; k = j; } @@ -1006,32 +1022,34 @@ search: } }
- type_fence = get_prev_valid_char_index(classes, run_start, -1); + type_fence = get_prev_valid_char_index(chars, run_start, -1);
if (type_fence == -1) - current_isolated->sos = (baselevel > levels[run_start]) ? baselevel : levels[run_start]; + current_isolated->sos = max(baselevel, chars[run_start].resolved); else - current_isolated->sos = (levels[type_fence] > levels[run_start]) ? levels[type_fence] : levels[run_start]; + current_isolated->sos = max(chars[type_fence].resolved, chars[run_start].resolved);
current_isolated->sos = get_embedding_direction(current_isolated->sos);
if (run_end == count) current_isolated->eos = current_isolated->sos; - else { + else + { /* eos could be an BN */ - if (classes[run_end] == BN) { - real_end = get_prev_valid_char_index(classes, run_end, run_start-1); + if (chars[run_end].resolved == BN) + { + real_end = get_prev_valid_char_index(chars, run_end, run_start - 1); if (real_end < run_start) real_end = run_start; } else real_end = run_end;
- type_fence = get_next_valid_char_index(classes, run_end, count); + type_fence = get_next_valid_char_index(chars, run_end, count); if (type_fence == count) - current_isolated->eos = (baselevel > levels[real_end]) ? baselevel : levels[real_end]; + current_isolated->eos = max(baselevel, chars[real_end].resolved); else - current_isolated->eos = (levels[type_fence] > levels[real_end]) ? levels[type_fence] : levels[real_end]; + current_isolated->eos = max(chars[type_fence].resolved, chars[real_end].resolved);
current_isolated->eos = get_embedding_direction(current_isolated->eos); } @@ -1046,30 +1064,24 @@ search: return hr; }
-HRESULT bidi_computelevels(const WCHAR *string, UINT32 count, UINT8 baselevel, UINT8 *explicit, UINT8 *levels) +HRESULT bidi_computelevels(struct bidi_char *chars, unsigned int count, UINT8 baselevel) { IsolatedRun *iso_run, *next; struct list IsolatingRuns; - UINT8 *chartype; HRESULT hr;
- TRACE("%s, %u\n", debugstr_wn(string, count), count); - - if (!(chartype = malloc(count * sizeof(*chartype)))) - return E_OUTOFMEMORY; - - bidi_classify(string, chartype, count); - if (TRACE_ON(bidi)) bidi_dump_types("start ", chartype, 0, count); + if (TRACE_ON(bidi)) bidi_dump_types("start ", chars, 0, count);
- bidi_resolve_explicit(baselevel, chartype, levels, count); - memcpy(explicit, levels, count*sizeof(*explicit)); + bidi_resolve_explicit(chars, count, baselevel);
- if (TRACE_ON(bidi)) bidi_dump_types("after explicit", chartype, 0, count); + if (TRACE_ON(bidi)) bidi_dump_types("after explicit", chars, 0, count);
/* X10/BD13: Compute Isolating runs */ - hr = bidi_compute_isolating_runs_set(baselevel, chartype, levels, string, count, &IsolatingRuns); - if (FAILED(hr)) - goto done; + if (FAILED(hr = bidi_compute_isolating_runs_set(chars, count, baselevel, &IsolatingRuns))) + { + WARN("Failed to compute isolating runs set, hr %#lx.\n", hr); + return hr; + }
LIST_FOR_EACH_ENTRY_SAFE(iso_run, next, &IsolatingRuns, IsolatedRun, entry) { @@ -1085,13 +1097,10 @@ HRESULT bidi_computelevels(const WCHAR *string, UINT32 count, UINT8 baselevel, U free(iso_run); }
- if (TRACE_ON(bidi)) bidi_dump_types("before implicit", chartype, 0, count); - bidi_resolve_implicit(chartype, levels, 0, count-1); + if (TRACE_ON(bidi)) bidi_dump_types("before implicit", chars, 0, count); + bidi_resolve_implicit(chars, count);
- bidi_classify(string, chartype, count); - bidi_resolve_resolved(baselevel, chartype, levels, 0, count-1); + bidi_resolve_resolved(chars, count, baselevel);
-done: - free(chartype); - return hr; + return S_OK; } diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index f5938cf0303..d0ed1db97ef 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -535,7 +535,16 @@ enum gasp_flags { extern unsigned int opentype_get_gasp_flags(const struct dwrite_fonttable *gasp, float emsize) DECLSPEC_HIDDEN;
/* BiDi helpers */ -extern HRESULT bidi_computelevels(const WCHAR*,UINT32,UINT8,UINT8*,UINT8*) DECLSPEC_HIDDEN; +struct bidi_char +{ + unsigned int ch; + UINT8 explicit; + UINT8 resolved; + UINT8 nominal_bidi_class; + UINT8 bidi_class; +}; + +extern HRESULT bidi_computelevels(struct bidi_char *chars, unsigned int count, UINT8 baselevel) DECLSPEC_HIDDEN;
struct dwrite_glyphbitmap {