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
3d1d9a1d
Commit
3d1d9a1d
authored
Jan 31, 2019
by
Nikolay Sivov
Committed by
Alexandre Julliard
Jan 31, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Resolve script and language to apply positional features.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
d1c73489
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
255 additions
and
40 deletions
+255
-40
analyzer.c
dlls/dwrite/analyzer.c
+6
-0
dwrite_private.h
dlls/dwrite/dwrite_private.h
+27
-0
opentype.c
dlls/dwrite/opentype.c
+142
-39
shape.c
dlls/dwrite/shape.c
+80
-1
No files found.
dlls/dwrite/analyzer.c
View file @
3d1d9a1d
...
...
@@ -1313,6 +1313,9 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphPlacements(IDWriteTextAnalyzer2
context
.
text
=
text
;
context
.
length
=
text_len
;
context
.
is_rtl
=
is_rtl
;
context
.
u
.
pos
.
glyph_props
=
glyph_props
;
context
.
glyph_count
=
glyph_count
;
context
.
advances
=
advances
;
context
.
language_tag
=
get_opentype_language
(
locale
);
hr
=
shape_get_positions
(
&
context
,
scriptprops
->
scripttags
,
scriptprops
->
ops
->
gpos_features
);
...
...
@@ -1371,6 +1374,9 @@ static HRESULT WINAPI dwritetextanalyzer_GetGdiCompatibleGlyphPlacements(IDWrite
context
.
text
=
text
;
context
.
length
=
text_len
;
context
.
is_rtl
=
is_rtl
;
context
.
u
.
pos
.
glyph_props
=
glyph_props
;
context
.
glyph_count
=
glyph_count
;
context
.
advances
=
advances
;
context
.
language_tag
=
get_opentype_language
(
locale
);
hr
=
shape_get_positions
(
&
context
,
scriptprops
->
scripttags
,
scriptprops
->
ops
->
gpos_features
);
...
...
dlls/dwrite/dwrite_private.h
View file @
3d1d9a1d
...
...
@@ -331,6 +331,14 @@ struct scriptshaping_cache
const
struct
shaping_font_ops
*
font
;
void
*
context
;
UINT16
upem
;
struct
{
struct
dwrite_fonttable
table
;
unsigned
int
script_list
;
unsigned
int
feature_list
;
unsigned
int
lookup_list
;
}
gpos
;
};
struct
scriptshaping_context
...
...
@@ -341,6 +349,17 @@ struct scriptshaping_context
const
WCHAR
*
text
;
unsigned
int
length
;
BOOL
is_rtl
;
union
{
struct
{
const
DWRITE_SHAPING_GLYPH_PROPERTIES
*
glyph_props
;
}
pos
;
}
u
;
unsigned
int
glyph_count
;
float
*
advances
;
};
struct
shaping_font_ops
...
...
@@ -361,6 +380,14 @@ struct shaping_features
unsigned
int
count
;
};
extern
void
opentype_layout_scriptshaping_cache_init
(
struct
scriptshaping_cache
*
cache
)
DECLSPEC_HIDDEN
;
extern
DWORD
opentype_layout_find_script
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
DWORD
tag
,
unsigned
int
*
script_index
)
DECLSPEC_HIDDEN
;
extern
DWORD
opentype_layout_find_language
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
DWORD
tag
,
unsigned
int
script_index
,
unsigned
int
*
language_index
)
DECLSPEC_HIDDEN
;
extern
void
opentype_layout_apply_gpos_features
(
struct
scriptshaping_context
*
context
,
unsigned
int
script_index
,
unsigned
int
language_index
,
const
struct
shaping_features
*
features
)
DECLSPEC_HIDDEN
;
struct
scriptshaping_ops
{
HRESULT
(
*
contextual_shaping
)(
struct
scriptshaping_context
*
context
,
UINT16
*
clustermap
,
UINT16
*
glyph_indices
,
UINT32
*
actual_glyph_count
);
...
...
dlls/dwrite/opentype.c
View file @
3d1d9a1d
...
...
@@ -390,33 +390,38 @@ typedef struct {
WORD
FeatureIndex
[
1
];
}
OT_LangSys
;
typedef
struct
{
CHAR
LangSysTag
[
4
];
WORD
LangSys
;
}
OT_LangSysRecord
;
struct
ot_langsys_record
{
CHAR
tag
[
4
];
WORD
langsys
;
};
typedef
struct
{
WORD
DefaultLangSys
;
WORD
LangSysCount
;
OT_LangSysRecord
LangSysRecord
[
1
];
struct
ot_script
{
WORD
default_langsys
;
WORD
langsys_count
;
struct
ot_langsys_record
langsys
[
1
];
}
OT_Script
;
typedef
struct
{
CHAR
ScriptTag
[
4
];
WORD
Script
;
}
OT_ScriptRecord
;
struct
ot_script_record
{
CHAR
tag
[
4
];
WORD
script
;
};
typedef
struct
{
WORD
ScriptCount
;
OT_ScriptRecord
ScriptRecord
[
1
];
}
OT_ScriptList
;
struct
ot_script_list
{
WORD
script_count
;
struct
ot_script_record
scripts
[
1
];
};
typedef
struct
{
struct
gpos_gsub_header
{
DWORD
version
;
WORD
ScriptL
ist
;
WORD
FeatureL
ist
;
WORD
LookupL
ist
;
}
GPOS_GSUB_Header
;
WORD
script_l
ist
;
WORD
feature_l
ist
;
WORD
lookup_l
ist
;
};
enum
OPENTYPE_PLATFORM_ID
{
...
...
@@ -911,6 +916,12 @@ static DWORD table_read_be_dword(const struct dwrite_fonttable *table, unsigned
return
ptr
?
GET_BE_DWORD
(
*
ptr
)
:
0
;
}
static
DWORD
table_read_dword
(
const
struct
dwrite_fonttable
*
table
,
unsigned
int
offset
)
{
const
DWORD
*
ptr
=
table_read_ensure
(
table
,
offset
,
sizeof
(
*
ptr
));
return
ptr
?
*
ptr
:
0
;
}
BOOL
is_face_type_supported
(
DWRITE_FONT_FACE_TYPE
type
)
{
return
(
type
==
DWRITE_FONT_FACE_TYPE_CFF
)
||
...
...
@@ -1828,36 +1839,36 @@ HRESULT opentype_get_font_facename(struct file_stream_desc *stream_desc, WCHAR *
return
hr
;
}
static
inline
const
OT_Script
*
opentype_get_script
(
const
OT_ScriptL
ist
*
scriptlist
,
UINT32
scripttag
)
static
inline
const
struct
ot_script
*
opentype_get_script
(
const
struct
ot_script_l
ist
*
scriptlist
,
UINT32
scripttag
)
{
UINT16
j
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
scriptlist
->
ScriptC
ount
);
j
++
)
{
const
char
*
tag
=
scriptlist
->
ScriptRecord
[
j
].
ScriptT
ag
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
scriptlist
->
script_c
ount
);
j
++
)
{
const
char
*
tag
=
scriptlist
->
scripts
[
j
].
t
ag
;
if
(
scripttag
==
DWRITE_MAKE_OPENTYPE_TAG
(
tag
[
0
],
tag
[
1
],
tag
[
2
],
tag
[
3
]))
return
(
OT_Script
*
)((
BYTE
*
)
scriptlist
+
GET_BE_WORD
(
scriptlist
->
ScriptRecord
[
j
].
S
cript
));
return
(
struct
ot_script
*
)((
BYTE
*
)
scriptlist
+
GET_BE_WORD
(
scriptlist
->
scripts
[
j
].
s
cript
));
}
return
NULL
;
}
static
inline
const
OT_LangSys
*
opentype_get_langsys
(
const
OT_S
cript
*
script
,
UINT32
languagetag
)
static
inline
const
OT_LangSys
*
opentype_get_langsys
(
const
struct
ot_s
cript
*
script
,
UINT32
languagetag
)
{
UINT16
j
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
script
->
LangSysC
ount
);
j
++
)
{
const
char
*
tag
=
script
->
LangSysRecord
[
j
].
LangSysT
ag
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
script
->
langsys_c
ount
);
j
++
)
{
const
char
*
tag
=
script
->
langsys
[
j
].
t
ag
;
if
(
languagetag
==
DWRITE_MAKE_OPENTYPE_TAG
(
tag
[
0
],
tag
[
1
],
tag
[
2
],
tag
[
3
]))
return
(
OT_LangSys
*
)((
BYTE
*
)
script
+
GET_BE_WORD
(
script
->
LangSysRecord
[
j
].
LangS
ys
));
return
(
OT_LangSys
*
)((
BYTE
*
)
script
+
GET_BE_WORD
(
script
->
langsys
[
j
].
langs
ys
));
}
return
NULL
;
}
static
void
opentype_add_font_features
(
const
GPOS_GSUB_H
eader
*
header
,
const
OT_LangSys
*
langsys
,
static
void
opentype_add_font_features
(
const
struct
gpos_gsub_h
eader
*
header
,
const
OT_LangSys
*
langsys
,
UINT32
max_tagcount
,
UINT32
*
count
,
DWRITE_FONT_FEATURE_TAG
*
tags
)
{
const
OT_FeatureList
*
features
=
(
const
OT_FeatureList
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
FeatureL
ist
));
const
OT_FeatureList
*
features
=
(
const
OT_FeatureList
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
feature_l
ist
));
UINT16
j
;
for
(
j
=
0
;
j
<
GET_BE_WORD
(
langsys
->
FeatureCount
);
j
++
)
{
...
...
@@ -1880,9 +1891,9 @@ HRESULT opentype_get_typographic_features(IDWriteFontFace *fontface, UINT32 scri
*
count
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
tables
);
i
++
)
{
const
OT_ScriptL
ist
*
scriptlist
;
const
GPOS_GSUB_H
eader
*
header
;
const
OT_S
cript
*
script
;
const
struct
ot_script_l
ist
*
scriptlist
;
const
struct
gpos_gsub_h
eader
*
header
;
const
struct
ot_s
cript
*
script
;
const
void
*
ptr
;
void
*
context
;
UINT32
size
;
...
...
@@ -1896,8 +1907,8 @@ HRESULT opentype_get_typographic_features(IDWriteFontFace *fontface, UINT32 scri
if
(
!
exists
)
continue
;
header
=
(
const
GPOS_GSUB_Header
*
)
ptr
;
scriptlist
=
(
const
OT_ScriptList
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
ScriptL
ist
));
header
=
(
const
struct
gpos_gsub_header
*
)
ptr
;
scriptlist
=
(
const
struct
ot_script_list
*
)((
const
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
script_l
ist
));
script
=
opentype_get_script
(
scriptlist
,
scripttag
);
if
(
script
)
{
...
...
@@ -2150,10 +2161,10 @@ void opentype_colr_next_glyph(const struct dwrite_fonttable *colr, struct dwrite
BOOL
opentype_has_vertical_variants
(
IDWriteFontFace4
*
fontface
)
{
const
struct
gpos_gsub_header
*
header
;
const
OT_FeatureList
*
featurelist
;
const
OT_LookupList
*
lookup_list
;
BOOL
exists
=
FALSE
,
ret
=
FALSE
;
const
GPOS_GSUB_Header
*
header
;
const
void
*
data
;
void
*
context
;
UINT32
size
;
...
...
@@ -2165,8 +2176,8 @@ BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)
return
FALSE
;
header
=
data
;
featurelist
=
(
OT_FeatureList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
FeatureL
ist
));
lookup_list
=
(
const
OT_LookupList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
LookupL
ist
));
featurelist
=
(
OT_FeatureList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
feature_l
ist
));
lookup_list
=
(
const
OT_LookupList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
lookup_l
ist
));
for
(
i
=
0
;
i
<
GET_BE_WORD
(
featurelist
->
FeatureCount
);
i
++
)
{
if
(
*
(
UINT32
*
)
featurelist
->
FeatureRecord
[
i
].
FeatureTag
==
DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
)
{
...
...
@@ -2396,3 +2407,95 @@ DWRITE_CONTAINER_TYPE opentype_analyze_container_type(void const *data, UINT32 d
return
DWRITE_CONTAINER_TYPE_UNKNOWN
;
}
}
void
opentype_layout_scriptshaping_cache_init
(
struct
scriptshaping_cache
*
cache
)
{
cache
->
font
->
grab_font_table
(
cache
->
context
,
MS_GPOS_TAG
,
&
cache
->
gpos
.
table
.
data
,
&
cache
->
gpos
.
table
.
size
,
&
cache
->
gpos
.
table
.
context
);
if
(
cache
->
gpos
.
table
.
data
)
{
cache
->
gpos
.
script_list
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
FIELD_OFFSET
(
struct
gpos_gsub_header
,
script_list
));
cache
->
gpos
.
feature_list
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
FIELD_OFFSET
(
struct
gpos_gsub_header
,
feature_list
));
cache
->
gpos
.
lookup_list
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
FIELD_OFFSET
(
struct
gpos_gsub_header
,
lookup_list
));
}
}
DWORD
opentype_layout_find_script
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
DWORD
script
,
unsigned
int
*
script_index
)
{
WORD
script_count
;
unsigned
int
i
;
*
script_index
=
~
0u
;
if
(
kind
!=
MS_GPOS_TAG
)
return
0
;
script_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
);
if
(
!
script_count
)
return
0
;
for
(
i
=
0
;
i
<
script_count
;
i
++
)
{
DWORD
tag
=
table_read_dword
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
FIELD_OFFSET
(
struct
ot_script_list
,
scripts
)
+
i
*
sizeof
(
struct
ot_script_record
));
if
(
!
tag
)
continue
;
if
(
tag
==
script
)
{
*
script_index
=
i
;
return
script
;
}
}
return
0
;
}
DWORD
opentype_layout_find_language
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
DWORD
language
,
unsigned
int
script_index
,
unsigned
int
*
language_index
)
{
WORD
table_offset
,
lang_count
;
unsigned
int
i
;
*
language_index
=
~
0u
;
if
(
kind
!=
MS_GPOS_TAG
)
return
0
;
table_offset
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
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
0
;
lang_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
+
FIELD_OFFSET
(
struct
ot_script
,
langsys_count
));
for
(
i
=
0
;
i
<
lang_count
;
i
++
)
{
DWORD
tag
=
table_read_dword
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
+
FIELD_OFFSET
(
struct
ot_script
,
langsys
)
+
i
*
sizeof
(
struct
ot_langsys_record
));
if
(
tag
==
language
)
{
*
language_index
=
i
;
return
language
;
}
}
/* Try 'defaultLangSys' if it's set. */
if
(
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
))
return
~
0u
;
return
0
;
}
void
opentype_layout_apply_gpos_features
(
struct
scriptshaping_context
*
context
,
unsigned
int
script_index
,
unsigned
int
language_index
,
const
struct
shaping_features
*
features
)
{
/* FIXME: stub */
}
dlls/dwrite/shape.c
View file @
3d1d9a1d
...
...
@@ -23,6 +23,12 @@
#include "dwrite_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dwrite
);
#define MS_GPOS_TAG DWRITE_MAKE_OPENTYPE_TAG('G','P','O','S')
struct
scriptshaping_cache
*
create_scriptshaping_cache
(
void
*
context
,
const
struct
shaping_font_ops
*
font_ops
)
{
struct
scriptshaping_cache
*
cache
;
...
...
@@ -34,6 +40,7 @@ struct scriptshaping_cache *create_scriptshaping_cache(void *context, const stru
cache
->
font
=
font_ops
;
cache
->
context
=
context
;
opentype_layout_scriptshaping_cache_init
(
cache
);
cache
->
upem
=
cache
->
font
->
get_font_upem
(
cache
->
context
);
return
cache
;
...
...
@@ -43,6 +50,8 @@ void release_scriptshaping_cache(struct scriptshaping_cache *cache)
{
if
(
!
cache
)
return
;
cache
->
font
->
release_font_table
(
cache
->
context
,
cache
->
gpos
.
table
.
context
);
heap_free
(
cache
);
}
...
...
@@ -180,10 +189,80 @@ const struct scriptshaping_ops default_shaping_ops =
default_set_text_glyphs_props
};
static
DWORD
shape_select_script
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
const
DWORD
*
scripts
,
unsigned
int
*
script_index
)
{
static
const
DWORD
fallback_scripts
[]
=
{
DWRITE_MAKE_OPENTYPE_TAG
(
'D'
,
'F'
,
'L'
,
'T'
),
DWRITE_MAKE_OPENTYPE_TAG
(
'd'
,
'f'
,
'l'
,
't'
),
DWRITE_MAKE_OPENTYPE_TAG
(
'l'
,
'a'
,
't'
,
'n'
),
0
,
};
DWORD
script
;
/* Passed scripts in ascending priority. */
while
(
*
scripts
)
{
if
((
script
=
opentype_layout_find_script
(
cache
,
kind
,
*
scripts
,
script_index
)))
return
script
;
scripts
++
;
}
/* 'DFLT' -> 'dflt' -> 'latn' */
scripts
=
fallback_scripts
;
while
(
*
scripts
)
{
if
((
script
=
opentype_layout_find_script
(
cache
,
kind
,
*
scripts
,
script_index
)))
return
script
;
scripts
++
;
}
return
0
;
}
static
DWORD
shape_select_language
(
const
struct
scriptshaping_cache
*
cache
,
DWORD
kind
,
unsigned
int
script_index
,
DWORD
language
,
unsigned
int
*
language_index
)
{
/* Specified language -> 'dflt'. */
if
((
language
=
opentype_layout_find_language
(
cache
,
kind
,
language
,
script_index
,
language_index
)))
return
language
;
if
((
language
=
opentype_layout_find_language
(
cache
,
kind
,
DWRITE_MAKE_OPENTYPE_TAG
(
'd'
,
'f'
,
'l'
,
't'
),
script_index
,
language_index
)))
return
language
;
return
0
;
}
HRESULT
shape_get_positions
(
struct
scriptshaping_context
*
context
,
const
DWORD
*
scripts
,
const
struct
shaping_features
*
features
)
{
/* FIXME: stub */
struct
scriptshaping_cache
*
cache
=
context
->
cache
;
unsigned
int
script_index
,
language_index
;
unsigned
int
i
;
DWORD
script
;
/* Resolve script tag to actually supported script. */
if
(
cache
->
gpos
.
table
.
data
)
{
if
((
script
=
shape_select_script
(
cache
,
MS_GPOS_TAG
,
scripts
,
&
script_index
)))
{
DWORD
language
=
context
->
language_tag
;
if
((
language
=
shape_select_language
(
cache
,
MS_GPOS_TAG
,
script_index
,
language
,
&
language_index
)))
{
TRACE
(
"script %s, language %s.
\n
"
,
debugstr_tag
(
script
),
language
!=
~
0u
?
debugstr_tag
(
language
)
:
"deflangsys"
);
opentype_layout_apply_gpos_features
(
context
,
script_index
,
language_index
,
features
);
}
}
}
for
(
i
=
0
;
i
<
context
->
glyph_count
;
++
i
)
if
(
context
->
u
.
pos
.
glyph_props
[
i
].
isZeroWidthSpace
)
context
->
advances
[
i
]
=
0
.
0
f
;
return
S_OK
;
}
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