Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
b60796bd
Commit
b60796bd
authored
Jun 08, 2020
by
Nikolay Sivov
Committed by
Alexandre Julliard
Jun 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Sort feature tags returned from GetTypographicFeatures().
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
59c0dbb6
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
135 additions
and
126 deletions
+135
-126
analyzer.c
dlls/dwrite/analyzer.c
+9
-15
dwrite_private.h
dlls/dwrite/dwrite_private.h
+19
-9
opentype.c
dlls/dwrite/opentype.c
+47
-65
shape.c
dlls/dwrite/shape.c
+47
-0
analyzer.c
dlls/dwrite/tests/analyzer.c
+13
-37
No files found.
dlls/dwrite/analyzer.c
View file @
b60796bd
...
...
@@ -1767,29 +1767,23 @@ static HRESULT WINAPI dwritetextanalyzer2_GetTypographicFeatures(IDWriteTextAnal
IDWriteFontFace
*
fontface
,
DWRITE_SCRIPT_ANALYSIS
sa
,
const
WCHAR
*
locale
,
UINT32
max_tagcount
,
UINT32
*
actual_tagcount
,
DWRITE_FONT_FEATURE_TAG
*
tags
)
{
struct
scriptshaping_context
context
=
{
0
};
const
struct
dwritescript_properties
*
props
;
const
DWORD
*
scripts
;
HRESULT
hr
=
S_OK
;
UINT32
language
;
struct
dwrite_fontface
*
font_obj
;
TRACE
(
"
(%p %u %s %u %p %p)
\n
"
,
fontface
,
sa
.
script
,
debugstr_w
(
locale
),
max_tagcount
,
actual
_tagcount
,
tags
);
TRACE
(
"
%p, %p, %u, %s, %u, %p, %p.
\n
"
,
iface
,
fontface
,
sa
.
script
,
debugstr_w
(
locale
),
max
_tagcount
,
actual_tagcount
,
tags
);
if
(
sa
.
script
>
Script_LastId
)
return
E_INVALIDARG
;
language
=
get_opentype_language
(
locale
);
props
=
&
dwritescripts_properties
[
sa
.
script
];
*
actual_tagcount
=
0
;
font_obj
=
unsafe_impl_from_IDWriteFontFace
(
fontface
);
scripts
=
props
->
scripttags
;
while
(
*
scripts
&&
!*
actual_tagcount
)
{
hr
=
opentype_get_typographic_features
(
fontface
,
*
scripts
,
language
,
max_tagcount
,
actual_tagcount
,
tags
);
scripts
++
;
}
context
.
cache
=
fontface_get_shaping_cache
(
font_obj
);
context
.
language_tag
=
get_opentype_language
(
locale
);
props
=
&
dwritescripts_properties
[
sa
.
script
];
return
hr
;
return
shape_get_typographic_features
(
&
context
,
props
->
scripttags
,
max_tagcount
,
actual_tagcount
,
tags
)
;
};
static
HRESULT
WINAPI
dwritetextanalyzer2_CheckTypographicFeature
(
IDWriteTextAnalyzer2
*
iface
,
...
...
dlls/dwrite/dwrite_private.h
View file @
b60796bd
...
...
@@ -330,6 +330,21 @@ struct file_stream_desc {
extern
const
void
*
get_fontface_table
(
IDWriteFontFace5
*
fontface
,
UINT32
tag
,
struct
dwrite_fonttable
*
table
)
DECLSPEC_HIDDEN
;
struct
tag_array
{
unsigned
int
*
tags
;
size_t
capacity
;
size_t
count
;
};
struct
ot_gsubgpos_table
{
struct
dwrite_fonttable
table
;
unsigned
int
script_list
;
unsigned
int
feature_list
;
unsigned
int
lookup_list
;
};
extern
HRESULT
opentype_analyze_font
(
IDWriteFontFileStream
*
,
BOOL
*
,
DWRITE_FONT_FILE_TYPE
*
,
DWRITE_FONT_FACE_TYPE
*
,
UINT32
*
)
DECLSPEC_HIDDEN
;
extern
HRESULT
opentype_try_get_font_table
(
const
struct
file_stream_desc
*
stream_desc
,
UINT32
tag
,
const
void
**
data
,
void
**
context
,
UINT32
*
size
,
BOOL
*
exists
)
DECLSPEC_HIDDEN
;
...
...
@@ -343,7 +358,8 @@ extern HRESULT opentype_get_font_info_strings(const struct file_stream_desc *str
DWRITE_INFORMATIONAL_STRING_ID
id
,
IDWriteLocalizedStrings
**
strings
)
DECLSPEC_HIDDEN
;
extern
HRESULT
opentype_get_font_familyname
(
struct
file_stream_desc
*
,
IDWriteLocalizedStrings
**
)
DECLSPEC_HIDDEN
;
extern
HRESULT
opentype_get_font_facename
(
struct
file_stream_desc
*
,
WCHAR
*
,
IDWriteLocalizedStrings
**
)
DECLSPEC_HIDDEN
;
extern
HRESULT
opentype_get_typographic_features
(
IDWriteFontFace
*
,
UINT32
,
UINT32
,
UINT32
,
UINT32
*
,
DWRITE_FONT_FEATURE_TAG
*
)
DECLSPEC_HIDDEN
;
extern
void
opentype_get_typographic_features
(
struct
ot_gsubgpos_table
*
table
,
unsigned
int
script_index
,
unsigned
int
language_index
,
struct
tag_array
*
tags
)
DECLSPEC_HIDDEN
;
extern
BOOL
opentype_get_vdmx_size
(
const
struct
dwrite_fonttable
*
table
,
INT
ppem
,
UINT16
*
ascent
,
UINT16
*
descent
)
DECLSPEC_HIDDEN
;
extern
unsigned
int
opentype_get_cpal_palettecount
(
const
struct
dwrite_fonttable
*
table
)
DECLSPEC_HIDDEN
;
...
...
@@ -438,14 +454,6 @@ enum SCRIPT_JUSTIFY
SCRIPT_JUSTIFY_ARABIC_SEEN_M
};
struct
ot_gsubgpos_table
{
struct
dwrite_fonttable
table
;
unsigned
int
script_list
;
unsigned
int
feature_list
;
unsigned
int
lookup_list
;
};
struct
scriptshaping_cache
{
const
struct
shaping_font_ops
*
font
;
...
...
@@ -586,3 +594,5 @@ extern void opentype_layout_apply_gpos_features(struct scriptshaping_context *co
extern
HRESULT
shape_get_glyphs
(
struct
scriptshaping_context
*
context
,
const
unsigned
int
*
scripts
)
DECLSPEC_HIDDEN
;
extern
HRESULT
shape_get_positions
(
struct
scriptshaping_context
*
context
,
const
unsigned
int
*
scripts
)
DECLSPEC_HIDDEN
;
extern
HRESULT
shape_get_typographic_features
(
struct
scriptshaping_context
*
context
,
const
unsigned
int
*
scripts
,
unsigned
int
max_tagcount
,
unsigned
int
*
actual_tagcount
,
unsigned
int
*
tags
)
DECLSPEC_HIDDEN
;
dlls/dwrite/opentype.c
View file @
b60796bd
...
...
@@ -2454,87 +2454,69 @@ HRESULT opentype_get_font_facename(struct file_stream_desc *stream_desc, WCHAR *
return
hr
;
}
static
inline
const
struct
ot_script
*
opentype_get_script
(
const
struct
ot_script_list
*
scriptlist
,
UINT32
scripttag
)
static
const
struct
ot_langsys
*
opentype_get_langsys
(
const
struct
ot_gsubgpos_table
*
table
,
unsigned
int
script_index
,
unsigned
int
language_index
,
unsigned
int
*
feature_count
)
{
UINT16
j
;
unsigned
int
table_offset
,
langsys_offset
;
const
struct
ot_langsys
*
langsys
=
NULL
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
scriptlist
->
script_count
);
j
++
)
{
const
char
*
tag
=
scriptlist
->
scripts
[
j
].
tag
;
if
(
scripttag
==
DWRITE_MAKE_OPENTYPE_TAG
(
tag
[
0
],
tag
[
1
],
tag
[
2
],
tag
[
3
]))
return
(
struct
ot_script
*
)((
BYTE
*
)
scriptlist
+
GET_BE_WORD
(
scriptlist
->
scripts
[
j
].
script
));
}
*
feature_count
=
0
;
return
NULL
;
}
static
inline
const
struct
ot_langsys
*
opentype_get_langsys
(
const
struct
ot_script
*
script
,
UINT32
languagetag
)
{
UINT16
j
;
if
(
!
table
->
table
.
data
||
script_index
==
~
0u
)
return
NULL
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
script
->
langsys_count
);
j
++
)
{
const
char
*
tag
=
script
->
langsys
[
j
].
tag
;
if
(
languagetag
==
DWRITE_MAKE_OPENTYPE_TAG
(
tag
[
0
],
tag
[
1
],
tag
[
2
],
tag
[
3
]))
return
(
struct
ot_langsys
*
)((
BYTE
*
)
script
+
GET_BE_WORD
(
script
->
langsys
[
j
].
langsys
));
}
/* ScriptTable offset. */
table_offset
=
table_read_be_word
(
&
table
->
table
,
table
->
script_list
+
FIELD_OFFSET
(
struct
ot_script_list
,
scripts
)
+
script_index
*
sizeof
(
struct
ot_script_record
)
+
FIELD_OFFSET
(
struct
ot_script_record
,
script
));
if
(
!
table_offset
)
return
NULL
;
return
NULL
;
if
(
language_index
==
~
0u
)
langsys_offset
=
table_read_be_word
(
&
table
->
table
,
table
->
script_list
+
table_offset
);
else
langsys_offset
=
table_read_be_word
(
&
table
->
table
,
table
->
script_list
+
table_offset
+
FIELD_OFFSET
(
struct
ot_script
,
langsys
)
+
language_index
*
sizeof
(
struct
ot_langsys_record
)
+
FIELD_OFFSET
(
struct
ot_langsys_record
,
langsys
));
langsys_offset
+=
table
->
script_list
+
table_offset
;
*
feature_count
=
table_read_be_word
(
&
table
->
table
,
langsys_offset
+
FIELD_OFFSET
(
struct
ot_langsys
,
feature_count
));
if
(
*
feature_count
)
langsys
=
table_read_ensure
(
&
table
->
table
,
langsys_offset
,
FIELD_OFFSET
(
struct
ot_langsys
,
feature_index
[
*
feature_count
]));
if
(
!
langsys
)
*
feature_count
=
0
;
return
langsys
;
}
static
void
opentype_add_font_features
(
const
struct
gpos_gsub_header
*
header
,
const
struct
ot_langsys
*
langsys
,
UINT32
max_tagcount
,
UINT32
*
count
,
DWRITE_FONT_FEATURE_TAG
*
tags
)
void
opentype_get_typographic_features
(
struct
ot_gsubgpos_table
*
table
,
unsigned
int
script_index
,
unsigned
int
language_index
,
struct
tag_array
*
t
)
{
const
struct
ot_feature_list
*
features
=
(
const
struct
ot_feature_list
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
feature_list
));
UINT16
j
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
langsys
->
feature_count
);
j
++
)
{
const
struct
ot_feature_record
*
feature
=
&
features
->
features
[
langsys
->
feature_index
[
j
]];
if
(
*
count
<
max_tagcount
)
tags
[
*
count
]
=
GET_BE_DWORD
(
feature
->
tag
);
unsigned
int
i
,
total_feature_count
,
script_feature_count
;
const
struct
ot_feature_list
*
feature_list
;
const
struct
ot_langsys
*
langsys
=
NULL
;
(
*
count
)
++
;
}
}
langsys
=
opentype_get_langsys
(
table
,
script_index
,
language_index
,
&
script_feature_count
);
HRESULT
opentype_get_typographic_features
(
IDWriteFontFace
*
fontface
,
UINT32
scripttag
,
UINT32
languagetag
,
UINT32
max_tagcount
,
UINT32
*
count
,
DWRITE_FONT_FEATURE_TAG
*
tags
)
{
UINT32
tables
[
2
]
=
{
MS_GSUB_TAG
,
MS_GPOS_TAG
};
HRESULT
hr
;
UINT8
i
;
*
count
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
tables
);
i
++
)
{
const
struct
ot_script_list
*
scriptlist
;
const
struct
gpos_gsub_header
*
header
;
const
struct
ot_script
*
script
;
const
void
*
ptr
;
void
*
context
;
UINT32
size
;
BOOL
exists
;
total_feature_count
=
table_read_be_word
(
&
table
->
table
,
table
->
feature_list
);
if
(
!
total_feature_count
)
return
;
exists
=
FALSE
;
hr
=
IDWriteFontFace_TryGetFontTable
(
fontface
,
tables
[
i
],
&
ptr
,
&
size
,
&
context
,
&
exists
);
if
(
FAILED
(
hr
)
)
return
hr
;
feature_list
=
table_read_ensure
(
&
table
->
table
,
table
->
feature_list
,
FIELD_OFFSET
(
struct
ot_feature_list
,
features
[
total_feature_count
])
);
if
(
!
feature_list
)
return
;
if
(
!
exists
)
for
(
i
=
0
;
i
<
script_feature_count
;
++
i
)
{
unsigned
int
feature_index
=
GET_BE_WORD
(
langsys
->
feature_index
[
i
]);
if
(
feature_index
>=
total_feature_count
)
continue
;
header
=
(
const
struct
gpos_gsub_header
*
)
ptr
;
scriptlist
=
(
const
struct
ot_script_list
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
script_list
));
script
=
opentype_get_script
(
scriptlist
,
scripttag
);
if
(
script
)
{
const
struct
ot_langsys
*
langsys
=
opentype_get_langsys
(
script
,
languagetag
);
if
(
langsys
)
opentype_add_font_features
(
header
,
langsys
,
max_tagcount
,
count
,
tags
);
}
if
(
!
dwrite_array_reserve
((
void
**
)
&
t
->
tags
,
&
t
->
capacity
,
t
->
count
+
1
,
sizeof
(
*
t
->
tags
)))
return
;
IDWriteFontFace_ReleaseFontTable
(
fontface
,
context
)
;
t
->
tags
[
t
->
count
++
]
=
feature_list
->
features
[
feature_index
].
tag
;
}
return
*
count
>
max_tagcount
?
E_NOT_SUFFICIENT_BUFFER
:
S_OK
;
}
static
unsigned
int
find_vdmx_group
(
const
struct
vdmx_header
*
hdr
)
...
...
dlls/dwrite/shape.c
View file @
b60796bd
...
...
@@ -22,11 +22,18 @@
#define COBJMACROS
#include "dwrite_private.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dwrite
);
#ifdef WORDS_BIGENDIAN
#define GET_BE_DWORD(x) (x)
#else
#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
#endif
struct
scriptshaping_cache
*
create_scriptshaping_cache
(
void
*
context
,
const
struct
shaping_font_ops
*
font_ops
)
{
struct
scriptshaping_cache
*
cache
;
...
...
@@ -303,3 +310,43 @@ HRESULT shape_get_glyphs(struct scriptshaping_context *context, const unsigned i
return
(
context
->
glyph_count
<=
context
->
u
.
subst
.
max_glyph_count
)
?
S_OK
:
E_NOT_SUFFICIENT_BUFFER
;
}
static
int
tag_array_sorting_compare
(
const
void
*
a
,
const
void
*
b
)
{
unsigned
int
left
=
GET_BE_DWORD
(
*
(
unsigned
int
*
)
a
),
right
=
GET_BE_DWORD
(
*
(
unsigned
int
*
)
b
);
return
left
!=
right
?
(
left
<
right
?
-
1
:
1
)
:
0
;
};
HRESULT
shape_get_typographic_features
(
struct
scriptshaping_context
*
context
,
const
unsigned
int
*
scripts
,
unsigned
int
max_tagcount
,
unsigned
int
*
actual_tagcount
,
unsigned
int
*
tags
)
{
unsigned
int
i
,
j
,
script_index
,
language_index
;
struct
tag_array
t
=
{
0
};
/* Collect from both tables, sort and remove duplicates. */
shape_get_script_lang_index
(
context
,
scripts
,
MS_GSUB_TAG
,
&
script_index
,
&
language_index
);
opentype_get_typographic_features
(
&
context
->
cache
->
gsub
,
script_index
,
language_index
,
&
t
);
shape_get_script_lang_index
(
context
,
scripts
,
MS_GPOS_TAG
,
&
script_index
,
&
language_index
);
opentype_get_typographic_features
(
&
context
->
cache
->
gpos
,
script_index
,
language_index
,
&
t
);
/* Sort and remove duplicates. */
qsort
(
t
.
tags
,
t
.
count
,
sizeof
(
*
t
.
tags
),
tag_array_sorting_compare
);
for
(
i
=
1
,
j
=
0
;
i
<
t
.
count
;
++
i
)
{
if
(
t
.
tags
[
i
]
!=
t
.
tags
[
j
])
t
.
tags
[
++
j
]
=
t
.
tags
[
i
];
}
t
.
count
=
j
+
1
;
if
(
t
.
count
<=
max_tagcount
)
memcpy
(
tags
,
t
.
tags
,
t
.
count
*
sizeof
(
*
t
.
tags
));
*
actual_tagcount
=
t
.
count
;
heap_free
(
t
.
tags
);
return
t
.
count
<=
max_tagcount
?
S_OK
:
E_NOT_SUFFICIENT_BUFFER
;
}
dlls/dwrite/tests/analyzer.c
View file @
b60796bd
...
...
@@ -1795,15 +1795,6 @@ if (0) {
IDWriteTextAnalyzer_Release
(
analyzer
);
}
static
BOOL
has_feature
(
const
DWRITE_FONT_FEATURE_TAG
*
tags
,
UINT32
count
,
DWRITE_FONT_FEATURE_TAG
feature
)
{
UINT32
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
tags
[
i
]
==
feature
)
return
TRUE
;
return
FALSE
;
}
static
void
test_GetTypographicFeatures
(
void
)
{
static
const
WCHAR
arabicW
[]
=
{
0x064a
,
0x064f
,
0x0633
,
0
};
...
...
@@ -1814,7 +1805,6 @@ static void test_GetTypographicFeatures(void)
DWRITE_SCRIPT_ANALYSIS
sa
;
UINT32
count
;
HRESULT
hr
;
BOOL
ret
;
hr
=
IDWriteFactory_CreateTextAnalyzer
(
factory
,
&
analyzer
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
...
...
@@ -1831,45 +1821,31 @@ static void test_GetTypographicFeatures(void)
get_script_analysis
(
L"abc"
,
&
sa
);
count
=
0
;
hr
=
IDWriteTextAnalyzer2_GetTypographicFeatures
(
analyzer2
,
fontface
,
sa
,
NULL
,
0
,
&
count
,
NULL
);
todo_wine
{
ok
(
hr
==
E_NOT_SUFFICIENT_BUFFER
,
"got 0x%08x
\n
"
,
hr
);
ok
(
count
>
0
,
"got %u
\n
"
,
count
);
}
ok
(
hr
==
E_NOT_SUFFICIENT_BUFFER
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
count
,
"Unexpected count %u.
\n
"
,
count
);
/* invalid locale name is ignored */
get_script_analysis
(
L"abc"
,
&
sa
);
count
=
0
;
hr
=
IDWriteTextAnalyzer2_GetTypographicFeatures
(
analyzer2
,
fontface
,
sa
,
L"cadabra"
,
0
,
&
count
,
NULL
);
todo_wine
{
ok
(
hr
==
E_NOT_SUFFICIENT_BUFFER
,
"got 0x%08x
\n
"
,
hr
);
ok
(
count
>
0
,
"got %u
\n
"
,
count
);
}
/* both GSUB and GPOS features are reported */
ok
(
hr
==
E_NOT_SUFFICIENT_BUFFER
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
count
,
"Unexpected count %u.
\n
"
,
count
);
/* Make some calls for different scripts. */
get_script_analysis
(
arabicW
,
&
sa
);
memset
(
tags
,
0
,
sizeof
(
tags
));
count
=
0
;
hr
=
IDWriteTextAnalyzer2_GetTypographicFeatures
(
analyzer2
,
fontface
,
sa
,
NULL
,
ARRAY_SIZE
(
tags
),
&
count
,
tags
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
todo_wine
{
ok
(
count
>
0
,
"got %u
\n
"
,
count
);
ret
=
has_feature
(
tags
,
count
,
DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES
);
ok
(
ret
,
"expected 'calt' feature
\n
"
);
ret
=
has_feature
(
tags
,
count
,
DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING
);
ok
(
ret
,
"expected 'mkmk' feature
\n
"
);
}
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
count
,
"Unexpected count %u.
\n
"
,
count
);
get_script_analysis
(
L"abc"
,
&
sa
);
memset
(
tags
,
0
,
sizeof
(
tags
));
count
=
0
;
hr
=
IDWriteTextAnalyzer2_GetTypographicFeatures
(
analyzer2
,
fontface
,
sa
,
NULL
,
ARRAY_SIZE
(
tags
),
&
count
,
tags
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
todo_wine
{
ok
(
count
>
0
,
"got %u
\n
"
,
count
);
ret
=
has_feature
(
tags
,
count
,
DWRITE_FONT_FEATURE_TAG_GLYPH_COMPOSITION_DECOMPOSITION
);
ok
(
ret
,
"expected 'ccmp' feature
\n
"
);
ret
=
has_feature
(
tags
,
count
,
DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING
);
ok
(
ret
,
"expected 'mkmk' feature
\n
"
);
}
ret
=
has_feature
(
tags
,
count
,
DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES
);
ok
(
!
ret
,
"unexpected 'calt' feature
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#x.
\n
"
,
hr
);
ok
(
!!
count
,
"Unexpected count %u.
\n
"
,
count
);
IDWriteFontFace_Release
(
fontface
);
IDWriteTextAnalyzer2_Release
(
analyzer2
);
...
...
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