mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 08:54:05 +00:00
dwrite/bidi: Prepare for characters above BMP.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
parent
d8584a16ed
commit
4a7a979e79
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue