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
b57db6f8
Commit
b57db6f8
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: Collect and sort positional lookups.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
3d1d9a1d
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
183 additions
and
45 deletions
+183
-45
dwrite_private.h
dlls/dwrite/dwrite_private.h
+27
-0
opentype.c
dlls/dwrite/opentype.c
+156
-45
No files found.
dlls/dwrite/dwrite_private.h
View file @
b57db6f8
...
...
@@ -76,6 +76,33 @@ static inline const char *debugstr_matrix(const DWRITE_MATRIX *m)
m
->
dx
,
m
->
dy
);
}
static
inline
BOOL
dwrite_array_reserve
(
void
**
elements
,
size_t
*
capacity
,
size_t
count
,
size_t
size
)
{
size_t
new_capacity
,
max_capacity
;
void
*
new_elements
;
if
(
count
<=
*
capacity
)
return
TRUE
;
max_capacity
=
~
(
SIZE_T
)
0
/
size
;
if
(
count
>
max_capacity
)
return
FALSE
;
new_capacity
=
max
(
4
,
*
capacity
);
while
(
new_capacity
<
count
&&
new_capacity
<=
max_capacity
/
2
)
new_capacity
*=
2
;
if
(
new_capacity
<
count
)
new_capacity
=
max_capacity
;
if
(
!
(
new_elements
=
heap_realloc
(
*
elements
,
new_capacity
*
size
)))
return
FALSE
;
*
elements
=
new_elements
;
*
capacity
=
new_capacity
;
return
TRUE
;
}
static
inline
const
char
*
debugstr_tag
(
DWORD
tag
)
{
return
debugstr_an
((
char
*
)
&
tag
,
4
);
...
...
dlls/dwrite/opentype.c
View file @
b57db6f8
...
...
@@ -312,8 +312,6 @@ struct gasp_header
struct
gasp_range
ranges
[
1
];
};
#include "poppack.h"
enum
OS2_FSSELECTION
{
OS2_FSSELECTION_ITALIC
=
1
<<
0
,
OS2_FSSELECTION_UNDERSCORE
=
1
<<
1
,
...
...
@@ -373,22 +371,25 @@ struct vdmx_group
struct
vdmx_vtable
entries
[
1
];
};
typedef
struct
{
CHAR
FeatureTag
[
4
];
WORD
Feature
;
}
OT_FeatureRecord
;
struct
ot_feature_record
{
DWORD
tag
;
WORD
offset
;
};
typedef
struct
{
WORD
FeatureCount
;
OT_FeatureRecord
FeatureRecord
[
1
];
}
OT_FeatureList
;
struct
ot_feature_list
{
WORD
feature_count
;
struct
ot_feature_record
features
[
1
];
};
typedef
struct
{
WORD
LookupOrder
;
/* Reserved */
WORD
ReqFeatureIndex
;
WORD
FeatureCount
;
WORD
FeatureIndex
[
1
];
}
OT_LangSys
;
struct
ot_langsys
{
WORD
lookup_order
;
/* Reserved */
WORD
required_feature_index
;
WORD
feature_count
;
WORD
feature_index
[
1
];
};
struct
ot_langsys_record
{
...
...
@@ -432,11 +433,12 @@ enum OPENTYPE_PLATFORM_ID
OPENTYPE_PLATFORM_CUSTOM
};
typedef
struct
{
WORD
FeatureParams
;
WORD
LookupCount
;
WORD
LookupListIndex
[
1
];
}
OT_Feature
;
struct
ot_feature
{
WORD
feature_params
;
WORD
lookup_count
;
WORD
lookuplist_index
[
1
];
};
typedef
struct
{
WORD
LookupCount
;
...
...
@@ -469,10 +471,12 @@ typedef struct {
DWORD
ExtensionOffset
;
}
GSUB_ExtensionPosFormat1
;
enum
OPENTYPE_GPOS_LOOKUPS
#include "poppack.h"
enum
gsub_lookup_type
{
OPENTYPE_GPOS
_SINGLE_SUBST
=
1
,
OPENTYPE_GPOS_EXTENSION_SUBST
=
7
GSUB_LOOKUP
_SINGLE_SUBST
=
1
,
GSUB_LOOKUP_EXTENSION_SUBST
=
7
,
};
enum
TT_NAME_WINDOWS_ENCODING_ID
...
...
@@ -1852,31 +1856,30 @@ static inline const struct ot_script *opentype_get_script(const struct ot_script
return
NULL
;
}
static
inline
const
OT_LangS
ys
*
opentype_get_langsys
(
const
struct
ot_script
*
script
,
UINT32
languagetag
)
static
inline
const
struct
ot_langs
ys
*
opentype_get_langsys
(
const
struct
ot_script
*
script
,
UINT32
languagetag
)
{
UINT16
j
;
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
(
OT_LangSys
*
)((
BYTE
*
)
script
+
GET_BE_WORD
(
script
->
langsys
[
j
].
langsys
));
return
(
struct
ot_langsys
*
)((
BYTE
*
)
script
+
GET_BE_WORD
(
script
->
langsys
[
j
].
langsys
));
}
return
NULL
;
}
static
void
opentype_add_font_features
(
const
struct
gpos_gsub_header
*
header
,
const
OT_LangS
ys
*
langsys
,
static
void
opentype_add_font_features
(
const
struct
gpos_gsub_header
*
header
,
const
struct
ot_langs
ys
*
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
->
feature_list
));
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
->
FeatureCount
);
j
++
)
{
const
OT_FeatureRecord
*
feature
=
&
features
->
FeatureRecord
[
langsys
->
FeatureIndex
[
j
]];
const
char
*
tag
=
feature
->
FeatureTag
;
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
]
=
DWRITE_MAKE_OPENTYPE_TAG
(
tag
[
0
],
tag
[
1
],
tag
[
2
],
tag
[
3
]
);
tags
[
*
count
]
=
GET_BE_DWORD
(
feature
->
tag
);
(
*
count
)
++
;
}
...
...
@@ -1912,7 +1915,7 @@ HRESULT opentype_get_typographic_features(IDWriteFontFace *fontface, UINT32 scri
script
=
opentype_get_script
(
scriptlist
,
scripttag
);
if
(
script
)
{
const
OT_LangS
ys
*
langsys
=
opentype_get_langsys
(
script
,
languagetag
);
const
struct
ot_langs
ys
*
langsys
=
opentype_get_langsys
(
script
,
languagetag
);
if
(
langsys
)
opentype_add_font_features
(
header
,
langsys
,
max_tagcount
,
count
,
tags
);
}
...
...
@@ -2162,27 +2165,27 @@ 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_FeatureL
ist
*
featurelist
;
const
struct
ot_feature_l
ist
*
featurelist
;
const
OT_LookupList
*
lookup_list
;
BOOL
exists
=
FALSE
,
ret
=
FALSE
;
unsigned
int
i
,
j
;
const
void
*
data
;
void
*
context
;
UINT32
size
;
HRESULT
hr
;
UINT16
i
;
hr
=
IDWriteFontFace4_TryGetFontTable
(
fontface
,
MS_GSUB_TAG
,
&
data
,
&
size
,
&
context
,
&
exists
);
if
(
FAILED
(
hr
)
||
!
exists
)
return
FALSE
;
header
=
data
;
featurelist
=
(
OT_FeatureList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
feature_list
));
featurelist
=
(
struct
ot_feature_list
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
feature_list
));
lookup_list
=
(
const
OT_LookupList
*
)((
BYTE
*
)
header
+
GET_BE_WORD
(
header
->
lookup_list
));
for
(
i
=
0
;
i
<
GET_BE_WORD
(
featurelist
->
FeatureC
ount
);
i
++
)
{
if
(
*
(
UINT32
*
)
featurelist
->
FeatureRecord
[
i
].
FeatureT
ag
==
DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
)
{
const
OT_Feature
*
feature
=
(
const
OT_Feature
*
)((
BYTE
*
)
featurelist
+
GET_BE_WORD
(
featurelist
->
FeatureRecord
[
i
].
Feature
));
UINT16
lookup_count
=
GET_BE_WORD
(
feature
->
LookupCount
),
i
,
index
,
count
,
type
;
for
(
i
=
0
;
i
<
GET_BE_WORD
(
featurelist
->
feature_c
ount
);
i
++
)
{
if
(
featurelist
->
features
[
i
].
t
ag
==
DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING
)
{
const
struct
ot_feature
*
feature
=
(
const
struct
ot_feature
*
)((
BYTE
*
)
featurelist
+
GET_BE_WORD
(
featurelist
->
features
[
i
].
offset
));
UINT16
lookup_count
=
GET_BE_WORD
(
feature
->
lookup_count
)
,
index
,
count
,
type
;
const
GSUB_SingleSubstFormat2
*
subst2
;
const
OT_LookupTable
*
lookup_table
;
UINT32
offset
;
...
...
@@ -2190,13 +2193,13 @@ BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)
if
(
lookup_count
==
0
)
continue
;
for
(
i
=
0
;
i
<
lookup_count
;
i
++
)
{
for
(
j
=
0
;
j
<
lookup_count
;
++
j
)
{
/* check if lookup is empty */
index
=
GET_BE_WORD
(
feature
->
LookupListIndex
[
i
]);
index
=
GET_BE_WORD
(
feature
->
lookuplist_index
[
j
]);
lookup_table
=
(
const
OT_LookupTable
*
)((
BYTE
*
)
lookup_list
+
GET_BE_WORD
(
lookup_list
->
Lookup
[
index
]));
type
=
GET_BE_WORD
(
lookup_table
->
LookupType
);
if
(
type
!=
OPENTYPE_GPOS_SINGLE_SUBST
&&
type
!=
OPENTYPE_GPOS
_EXTENSION_SUBST
)
if
(
type
!=
GSUB_LOOKUP_SINGLE_SUBST
&&
type
!=
GSUB_LOOKUP
_EXTENSION_SUBST
)
continue
;
count
=
GET_BE_WORD
(
lookup_table
->
SubTableCount
);
...
...
@@ -2204,7 +2207,7 @@ BOOL opentype_has_vertical_variants(IDWriteFontFace4 *fontface)
continue
;
offset
=
GET_BE_WORD
(
lookup_table
->
SubTable
[
0
]);
if
(
type
==
OPENTYPE_GPOS
_EXTENSION_SUBST
)
{
if
(
type
==
GSUB_LOOKUP
_EXTENSION_SUBST
)
{
const
GSUB_ExtensionPosFormat1
*
ext
=
(
const
GSUB_ExtensionPosFormat1
*
)((
const
BYTE
*
)
lookup_table
+
offset
);
if
(
GET_BE_WORD
(
ext
->
SubstFormat
)
==
1
)
offset
+=
GET_BE_DWORD
(
ext
->
ExtensionOffset
);
...
...
@@ -2494,8 +2497,116 @@ DWORD opentype_layout_find_language(const struct scriptshaping_cache *cache, DWO
return
0
;
}
static
void
opentype_layout_apply_gpos_lookup
(
struct
scriptshaping_context
*
context
,
int
lookup_index
)
{
/* FIXME: stub */
}
struct
lookups
{
int
*
indexes
;
size_t
capacity
;
size_t
count
;
};
static
int
lookups_sorting_compare
(
const
void
*
left
,
const
void
*
right
)
{
return
*
(
int
*
)
left
-
*
(
int
*
)
right
;
};
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 */
WORD
table_offset
,
langsys_offset
,
script_feature_count
,
total_feature_count
,
total_lookup_count
;
struct
scriptshaping_cache
*
cache
=
context
->
cache
;
const
struct
ot_feature_list
*
feature_list
;
struct
lookups
lookups
=
{
0
};
unsigned
int
i
,
j
,
l
;
/* ScriptTable offset. */
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
;
if
(
language_index
==
~
0u
)
langsys_offset
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
);
else
langsys_offset
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
+
FIELD_OFFSET
(
struct
ot_script
,
langsys
)
+
language_index
*
sizeof
(
struct
ot_langsys_record
)
+
FIELD_OFFSET
(
struct
ot_langsys_record
,
langsys
));
script_feature_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
+
langsys_offset
+
FIELD_OFFSET
(
struct
ot_langsys
,
feature_count
));
if
(
!
script_feature_count
)
return
;
total_feature_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
feature_list
);
if
(
!
total_feature_count
)
return
;
total_lookup_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
lookup_list
);
if
(
!
total_lookup_count
)
return
;
feature_list
=
table_read_ensure
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
feature_list
,
FIELD_OFFSET
(
struct
ot_feature_list
,
features
[
total_feature_count
]));
if
(
!
feature_list
)
return
;
/* Collect lookups for all given features. */
for
(
i
=
0
;
i
<
features
->
count
;
++
i
)
{
for
(
j
=
0
;
j
<
script_feature_count
;
++
j
)
{
WORD
feature_index
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
script_list
+
table_offset
+
langsys_offset
+
FIELD_OFFSET
(
struct
ot_langsys
,
feature_index
[
j
]));
if
(
feature_index
>=
total_feature_count
)
continue
;
if
(
feature_list
->
features
[
feature_index
].
tag
==
features
->
tags
[
i
])
{
WORD
feature_offset
=
GET_BE_WORD
(
feature_list
->
features
[
feature_index
].
offset
);
WORD
lookup_count
;
lookup_count
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
feature_list
+
feature_offset
+
FIELD_OFFSET
(
struct
ot_feature
,
lookup_count
));
if
(
!
lookup_count
)
continue
;
if
(
!
dwrite_array_reserve
((
void
**
)
&
lookups
.
indexes
,
&
lookups
.
capacity
,
lookups
.
count
+
lookup_count
,
sizeof
(
*
lookups
.
indexes
)))
{
heap_free
(
lookups
.
indexes
);
return
;
}
for
(
l
=
0
;
l
<
lookup_count
;
++
l
)
{
WORD
lookup_index
=
table_read_be_word
(
&
cache
->
gpos
.
table
,
cache
->
gpos
.
feature_list
+
feature_offset
+
FIELD_OFFSET
(
struct
ot_feature
,
lookuplist_index
[
l
]));
if
(
lookup_index
>=
total_lookup_count
)
continue
;
lookups
.
indexes
[
lookups
.
count
++
]
=
lookup_index
;
}
}
}
}
/* Sort lookups. */
qsort
(
lookups
.
indexes
,
lookups
.
count
,
sizeof
(
*
lookups
.
indexes
),
lookups_sorting_compare
);
for
(
l
=
0
;
l
<
lookups
.
count
;
++
l
)
{
/* Skip duplicates. */
if
(
l
&&
lookups
.
indexes
[
l
]
==
lookups
.
indexes
[
l
-
1
])
continue
;
opentype_layout_apply_gpos_lookup
(
context
,
lookups
.
indexes
[
l
]);
}
heap_free
(
lookups
.
indexes
);
}
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