dwrite/bidi: Prepare for characters above BMP.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2022-09-06 07:24:53 +03:00 committed by Alexandre Julliard
parent d8584a16ed
commit 4a7a979e79
3 changed files with 199 additions and 206 deletions

View file

@ -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;
}

View file

@ -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;
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:
;
}
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;
}
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 (TRACE_ON(bidi)) bidi_dump_types("start ", chars, 0, count);
if (!(chartype = malloc(count * sizeof(*chartype))))
return E_OUTOFMEMORY;
bidi_resolve_explicit(chars, count, baselevel);
bidi_classify(string, chartype, count);
if (TRACE_ON(bidi)) bidi_dump_types("start ", chartype, 0, count);
bidi_resolve_explicit(baselevel, chartype, levels, count);
memcpy(explicit, levels, count*sizeof(*explicit));
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;
}

View file

@ -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
{