Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
4a7a979e
Commit
4a7a979e
authored
Sep 06, 2022
by
Nikolay Sivov
Committed by
Alexandre Julliard
Sep 06, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite/bidi: Prepare for characters above BMP.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
parent
d8584a16
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
197 additions
and
204 deletions
+197
-204
analyzer.c
dlls/dwrite/analyzer.c
+48
-73
bidi.c
dlls/dwrite/bidi.c
+139
-130
dwrite_private.h
dlls/dwrite/dwrite_private.h
+10
-1
No files found.
dlls/dwrite/analyzer.c
View file @
4a7a979e
...
...
@@ -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
;
}
...
...
dlls/dwrite/bidi.c
View file @
4a7a979e
...
...
@@ -136,28 +136,19 @@ static const char debug_type[][4] =
"PDI"
,
};
static
inline
void
bidi_dump_types
(
const
char
*
header
,
const
UINT8
*
type
s
,
UINT32
start
,
UINT32
end
)
static
inline
void
bidi_dump_types
(
const
char
*
header
,
const
struct
bidi_char
*
char
s
,
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
)
c
lasses
[
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
*
classe
s
,
int
index
,
int
back_fence
)
static
inline
int
get_prev_valid_char_index
(
const
struct
bidi_char
*
char
s
,
int
index
,
int
back_fence
)
{
if
(
index
==
-
1
||
index
==
back_fence
)
return
index
;
index
--
;
while
(
index
>
back_fence
&&
c
lasses
[
index
]
==
BN
)
index
--
;
while
(
index
>
back_fence
&&
c
hars
[
index
].
bidi_class
==
BN
)
index
--
;
return
index
;
}
static
inline
int
get_next_valid_char_index
(
const
UINT8
*
classe
s
,
int
index
,
int
front_fence
)
static
inline
int
get_next_valid_char_index
(
const
struct
bidi_char
*
char
s
,
int
index
,
int
front_fence
)
{
if
(
index
==
front_fence
)
return
index
;
index
++
;
while
(
index
<
front_fence
&&
c
lasses
[
index
]
==
BN
)
index
++
;
while
(
index
<
front_fence
&&
c
hars
[
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
(
c
lasses
[
i
]
!=
ON
);
/* "No Neutrals allowed to survive here." */
ASSERT
(
c
lasses
[
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
)
{
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
(
classes
[
j
]
))
levels
[
j
--
]
=
baselevel
;
levels
[
i
]
=
baselevel
;
while
(
i
>
sos
&&
j
>=
sos
&&
is_rule_L1_reset_class
(
chars
[
j
].
nominal_bidi_class
))
chars
[
j
--
].
resolved
=
baselevel
;
chars
[
i
].
resolved
=
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
;
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
(
c
lasses
[
j
]
))
levels
[
j
--
]
=
baselevel
;
while
(
j
>=
sos
&&
is_rule_L1_reset_class
(
c
hars
[
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
(
c
lasse
s
,
run_end
,
count
);
runs
[
run_count
].
e
=
chars
[
run_start
].
resolved
;
run_start
=
get_next_valid_char_index
(
c
har
s
,
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
(
c
lasses
[
run_end
]
==
BN
)
run_end
=
get_prev_valid_char_index
(
c
lasse
s
,
run_end
,
runs
[
k
].
start
);
if
(
c
hars
[
run_end
].
bidi_class
==
BN
)
run_end
=
get_prev_valid_char_index
(
c
har
s
,
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
&&
c
lasses
[
runs
[
j
].
start
]
!=
PDI
)
j
++
;
while
(
j
<
run_count
&&
c
hars
[
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
=
&
c
lasses
[
runs
[
j
].
start
+
m
]
;
current_isolated
->
item
[
l
].
ch
=
string
[
runs
[
j
].
start
+
m
]
;
current_isolated
->
item
[
l
].
class
=
&
c
hars
[
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
(
c
lasses
[
run_end
]
==
BN
)
run_end
=
get_prev_valid_char_index
(
c
lasse
s
,
run_end
,
runs
[
i
].
start
);
if
(
c
hars
[
run_end
].
bidi_class
==
BN
)
run_end
=
get_prev_valid_char_index
(
c
har
s
,
run_end
,
runs
[
i
].
start
);
runs
[
j
].
start
=
-
1
;
k
=
j
;
}
...
...
@@ -1006,32 +1022,34 @@ search:
}
}
type_fence
=
get_prev_valid_char_index
(
c
lasse
s
,
run_start
,
-
1
);
type_fence
=
get_prev_valid_char_index
(
c
har
s
,
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
(
c
lasse
s
,
run_end
,
count
);
type_fence
=
get_next_valid_char_index
(
c
har
s
,
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_classify
(
string
,
chartype
,
count
);
if
(
TRACE_ON
(
bidi
))
bidi_dump_types
(
"start "
,
chartype
,
0
,
count
);
bidi_resolve_explicit
(
chars
,
count
,
baselevel
);
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"
,
char
type
,
0
,
count
);
bidi_resolve_implicit
(
char
type
,
levels
,
0
,
count
-
1
);
if
(
TRACE_ON
(
bidi
))
bidi_dump_types
(
"before implicit"
,
char
s
,
0
,
count
);
bidi_resolve_implicit
(
char
s
,
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
;
}
dlls/dwrite/dwrite_private.h
View file @
4a7a979e
...
...
@@ -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
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment