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
745452ee
Commit
745452ee
authored
Jun 09, 2020
by
Nikolay Sivov
Committed by
Alexandre Julliard
Jun 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Do not require fontface object for HasCharacter().
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
fb5eec2c
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
313 additions
and
26 deletions
+313
-26
dwrite_private.h
dlls/dwrite/dwrite_private.h
+41
-0
font.c
dlls/dwrite/font.c
+15
-26
opentype.c
dlls/dwrite/opentype.c
+257
-0
No files found.
dlls/dwrite/dwrite_private.h
View file @
745452ee
...
...
@@ -195,6 +195,47 @@ enum font_flags
FONTFACE_HAS_VERTICAL_VARIANTS
=
1
<<
4
};
struct
dwrite_cmap
;
typedef
UINT16
(
*
p_cmap_get_glyph_func
)(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
);
struct
dwrite_cmap
{
const
void
*
data
;
union
{
struct
{
unsigned
int
seg_count
;
unsigned
int
glyph_id_array_len
;
const
UINT16
*
ends
;
const
UINT16
*
starts
;
const
UINT16
*
id_delta
;
const
UINT16
*
id_range_offset
;
const
UINT16
*
glyph_id_array
;
}
format4
;
struct
{
unsigned
int
first
;
unsigned
int
last
;
}
format6_10
;
struct
{
unsigned
int
group_count
;
}
format12_13
;
}
u
;
p_cmap_get_glyph_func
get_glyph
;
unsigned
short
symbol
:
1
;
IDWriteFontFileStream
*
stream
;
void
*
table_context
;
};
extern
void
dwrite_cmap_init
(
struct
dwrite_cmap
*
cmap
,
IDWriteFontFile
*
file
,
unsigned
int
face_index
,
DWRITE_FONT_FACE_TYPE
face_type
)
DECLSPEC_HIDDEN
;
extern
void
dwrite_cmap_release
(
struct
dwrite_cmap
*
cmap
)
DECLSPEC_HIDDEN
;
extern
UINT16
opentype_cmap_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
DECLSPEC_HIDDEN
;
struct
dwrite_fontface
{
IDWriteFontFace5
IDWriteFontFace5_iface
;
...
...
dlls/dwrite/font.c
View file @
745452ee
...
...
@@ -80,6 +80,7 @@ struct dwrite_font_data
FONTSIGNATURE
fontsig
;
UINT32
flags
;
/* enum font_flags */
struct
dwrite_font_propvec
propvec
;
struct
dwrite_cmap
cmap
;
/* Static axis for weight/width/italic. */
DWRITE_FONT_AXIS_VALUE
axis
[
3
];
...
...
@@ -469,6 +470,7 @@ static void release_font_data(struct dwrite_font_data *data)
if
(
data
->
family_names
)
IDWriteLocalizedStrings_Release
(
data
->
family_names
);
dwrite_cmap_release
(
&
data
->
cmap
);
IDWriteFontFile_Release
(
data
->
file
);
heap_free
(
data
->
facename
);
heap_free
(
data
);
...
...
@@ -1958,35 +1960,23 @@ static void WINAPI dwritefont_GetMetrics(IDWriteFont3 *iface, DWRITE_FONT_METRIC
memcpy
(
metrics
,
&
This
->
data
->
metrics
,
sizeof
(
*
metrics
));
}
static
HRESULT
font_has_character
(
struct
dwrite_font
*
font
,
UINT32
ch
,
BOOL
*
exists
)
static
BOOL
dwritefont_has_character
(
struct
dwrite_font
*
font
,
UINT32
ch
)
{
IDWriteFontFace5
*
fontface
;
UINT16
index
;
HRESULT
hr
;
*
exists
=
FALSE
;
hr
=
get_fontface_from_font
(
font
,
&
fontface
);
if
(
FAILED
(
hr
))
return
hr
;
index
=
0
;
hr
=
IDWriteFontFace5_GetGlyphIndices
(
fontface
,
&
ch
,
1
,
&
index
);
IDWriteFontFace5_Release
(
fontface
);
if
(
FAILED
(
hr
))
return
hr
;
*
exists
=
index
!=
0
;
return
S_OK
;
UINT16
glyph
;
dwrite_cmap_init
(
&
font
->
data
->
cmap
,
font
->
data
->
file
,
font
->
data
->
face_index
,
font
->
data
->
face_type
);
glyph
=
opentype_cmap_get_glyph
(
&
font
->
data
->
cmap
,
ch
);
return
glyph
!=
0
;
}
static
HRESULT
WINAPI
dwritefont_HasCharacter
(
IDWriteFont3
*
iface
,
UINT32
ch
,
BOOL
*
exists
)
{
struct
dwrite_font
*
This
=
impl_from_IDWriteFont3
(
iface
);
struct
dwrite_font
*
font
=
impl_from_IDWriteFont3
(
iface
);
TRACE
(
"%p, %#x, %p.
\n
"
,
iface
,
ch
,
exists
);
TRACE
(
"(%p)->(%#x %p)
\n
"
,
This
,
ch
,
exists
);
*
exists
=
dwritefont_has_character
(
font
,
ch
);
return
font_has_character
(
This
,
ch
,
exists
)
;
return
S_OK
;
}
static
HRESULT
WINAPI
dwritefont_CreateFontFace
(
IDWriteFont3
*
iface
,
IDWriteFontFace
**
fontface
)
...
...
@@ -2088,12 +2078,11 @@ static HRESULT WINAPI dwritefont3_GetFontFaceReference(IDWriteFont3 *iface, IDWr
static
BOOL
WINAPI
dwritefont3_HasCharacter
(
IDWriteFont3
*
iface
,
UINT32
ch
)
{
struct
dwrite_font
*
This
=
impl_from_IDWriteFont3
(
iface
);
BOOL
ret
;
struct
dwrite_font
*
font
=
impl_from_IDWriteFont3
(
iface
);
TRACE
(
"
(%p)->(%#x)
\n
"
,
This
,
ch
);
TRACE
(
"
%p, %#x.
\n
"
,
iface
,
ch
);
return
font_has_character
(
This
,
ch
,
&
ret
)
==
S_OK
&&
ret
;
return
dwritefont_has_character
(
font
,
ch
)
;
}
static
DWRITE_LOCALITY
WINAPI
dwritefont3_GetLocality
(
IDWriteFont3
*
iface
)
...
...
dlls/dwrite/opentype.c
View file @
745452ee
...
...
@@ -1565,6 +1565,263 @@ static HRESULT opentype_get_font_table(const struct file_stream_desc *stream_des
* CMAP
**********/
static
UINT16
opentype_cmap_format0_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
const
UINT8
*
glyphs
=
cmap
->
data
;
return
(
ch
<
0xff
)
?
glyphs
[
ch
]
:
0
;
}
struct
cmap_format4_compare_context
{
const
struct
dwrite_cmap
*
cmap
;
unsigned
int
ch
;
};
static
int
cmap_format4_compare_range
(
const
void
*
a
,
const
void
*
b
)
{
const
struct
cmap_format4_compare_context
*
key
=
a
;
const
UINT16
*
end
=
b
;
unsigned
int
idx
;
if
(
key
->
ch
>
GET_BE_WORD
(
*
end
))
return
1
;
idx
=
end
-
key
->
cmap
->
u
.
format4
.
ends
;
if
(
key
->
ch
<
GET_BE_WORD
(
key
->
cmap
->
u
.
format4
.
starts
[
idx
]))
return
-
1
;
return
0
;
}
static
UINT16
opentype_cmap_format4_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
struct
cmap_format4_compare_context
key
=
{
.
cmap
=
cmap
,
.
ch
=
ch
};
unsigned
int
glyph
,
idx
,
range_offset
;
const
UINT16
*
end_found
;
/* Look up range. */
end_found
=
bsearch
(
&
key
,
cmap
->
u
.
format4
.
ends
,
cmap
->
u
.
format4
.
seg_count
,
sizeof
(
*
cmap
->
u
.
format4
.
ends
),
cmap_format4_compare_range
);
if
(
!
end_found
)
return
0
;
idx
=
end_found
-
cmap
->
u
.
format4
.
ends
;
range_offset
=
GET_BE_WORD
(
cmap
->
u
.
format4
.
id_range_offset
[
idx
]);
if
(
!
range_offset
)
{
glyph
=
ch
+
GET_BE_WORD
(
cmap
->
u
.
format4
.
id_delta
[
idx
]);
}
else
{
unsigned
int
index
=
range_offset
/
2
+
(
ch
-
GET_BE_WORD
(
cmap
->
u
.
format4
.
starts
[
idx
]))
+
idx
-
cmap
->
u
.
format4
.
seg_count
;
if
(
index
>=
cmap
->
u
.
format4
.
glyph_id_array_len
)
return
0
;
glyph
=
GET_BE_WORD
(
cmap
->
u
.
format4
.
glyph_id_array
[
index
]);
if
(
!
glyph
)
return
0
;
glyph
+=
GET_BE_WORD
(
cmap
->
u
.
format4
.
id_delta
[
idx
]);
}
return
glyph
&
0xffff
;
}
static
UINT16
opentype_cmap_format6_10_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
const
UINT16
*
glyphs
=
cmap
->
data
;
if
(
ch
<
cmap
->
u
.
format6_10
.
first
||
ch
>
cmap
->
u
.
format6_10
.
last
)
return
0
;
return
glyphs
[
ch
-
cmap
->
u
.
format6_10
.
first
];
}
static
int
cmap_format12_13_compare_group
(
const
void
*
a
,
const
void
*
b
)
{
const
unsigned
int
*
ch
=
a
;
const
UINT32
*
group
=
b
;
if
(
*
ch
>
GET_BE_DWORD
(
group
[
1
]))
return
1
;
if
(
*
ch
<
GET_BE_DWORD
(
group
[
0
]))
return
-
1
;
return
0
;
}
static
UINT16
opentype_cmap_format12_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
const
UINT32
*
groups
=
cmap
->
data
;
const
UINT32
*
group_found
;
if
(
!
(
group_found
=
bsearch
(
&
ch
,
groups
,
cmap
->
u
.
format12_13
.
group_count
,
3
*
sizeof
(
*
groups
),
cmap_format12_13_compare_group
)))
return
0
;
return
GET_BE_DWORD
(
group_found
[
0
])
<=
GET_BE_DWORD
(
group_found
[
1
])
?
GET_BE_DWORD
(
group_found
[
2
])
+
(
ch
-
GET_BE_DWORD
(
group_found
[
0
]))
:
0
;
}
static
UINT16
opentype_cmap_format13_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
const
UINT32
*
groups
=
cmap
->
data
;
const
UINT32
*
group_found
;
if
(
!
(
group_found
=
bsearch
(
&
ch
,
groups
,
cmap
->
u
.
format12_13
.
group_count
,
3
*
sizeof
(
*
groups
),
cmap_format12_13_compare_group
)))
return
0
;
return
GET_BE_DWORD
(
group_found
[
2
]);
}
static
UINT16
opentype_cmap_dummy_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
return
0
;
}
UINT16
opentype_cmap_get_glyph
(
const
struct
dwrite_cmap
*
cmap
,
unsigned
int
ch
)
{
UINT16
glyph
;
if
(
!
cmap
->
get_glyph
)
return
0
;
glyph
=
cmap
->
get_glyph
(
cmap
,
ch
);
if
(
!
glyph
&&
cmap
->
symbol
&&
ch
<=
0xff
)
glyph
=
cmap
->
get_glyph
(
cmap
,
ch
+
0xf000
);
return
glyph
;
}
static
int
cmap_header_compare
(
const
void
*
a
,
const
void
*
b
)
{
const
UINT16
*
key
=
a
;
const
UINT16
*
record
=
b
;
/* Platform. */
if
(
key
[
0
]
<
GET_BE_WORD
(
record
[
0
]))
return
-
1
;
if
(
key
[
0
]
>
GET_BE_WORD
(
record
[
0
]))
return
1
;
/* Encoding. */
if
(
key
[
1
]
<
GET_BE_WORD
(
record
[
1
]))
return
-
1
;
if
(
key
[
1
]
>
GET_BE_WORD
(
record
[
1
]))
return
1
;
return
0
;
}
void
dwrite_cmap_init
(
struct
dwrite_cmap
*
cmap
,
IDWriteFontFile
*
file
,
unsigned
int
face_index
,
DWRITE_FONT_FACE_TYPE
face_type
)
{
static
const
UINT16
encodings
[][
2
]
=
{
{
3
,
0
},
/* MS Symbol encoding is preferred. */
{
3
,
10
},
{
0
,
6
},
{
0
,
4
},
{
3
,
1
},
{
0
,
3
},
{
0
,
2
},
{
0
,
1
},
{
0
,
0
},
};
const
struct
cmap_encoding_record
*
records
,
*
found_record
=
NULL
;
unsigned
int
length
,
offset
,
format
,
count
,
f
,
i
,
num_records
;
struct
file_stream_desc
stream_desc
;
struct
dwrite_fonttable
table
;
const
UINT16
*
pair
=
NULL
;
HRESULT
hr
;
if
(
cmap
->
data
)
return
;
if
(
FAILED
(
hr
=
get_filestream_from_file
(
file
,
&
stream_desc
.
stream
)))
{
WARN
(
"Failed to get file stream, hr %#x.
\n
"
,
hr
);
goto
failed
;
}
stream_desc
.
face_type
=
face_type
;
stream_desc
.
face_index
=
face_index
;
opentype_get_font_table
(
&
stream_desc
,
MS_CMAP_TAG
,
&
table
);
if
(
!
table
.
exists
)
goto
failed
;
cmap
->
table_context
=
table
.
context
;
num_records
=
table_read_be_word
(
&
table
,
2
);
records
=
table_read_ensure
(
&
table
,
4
,
sizeof
(
*
records
)
*
num_records
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
encodings
);
++
i
)
{
pair
=
encodings
[
i
];
if
((
found_record
=
bsearch
(
pair
,
records
,
num_records
,
sizeof
(
*
records
),
cmap_header_compare
)))
break
;
}
if
(
!
found_record
)
{
WARN
(
"No suitable cmap table were found.
\n
"
);
goto
failed
;
}
/* Symbol encoding. */
cmap
->
symbol
=
pair
[
0
]
==
3
&&
pair
[
1
]
==
0
;
offset
=
GET_BE_DWORD
(
found_record
->
offset
);
format
=
table_read_be_word
(
&
table
,
offset
);
switch
(
format
)
{
case
0
:
cmap
->
data
=
table_read_ensure
(
&
table
,
offset
+
6
,
256
);
cmap
->
get_glyph
=
opentype_cmap_format0_get_glyph
;
break
;
case
4
:
length
=
table_read_be_word
(
&
table
,
offset
+
2
);
cmap
->
u
.
format4
.
seg_count
=
count
=
table_read_be_word
(
&
table
,
offset
+
6
)
/
2
;
cmap
->
u
.
format4
.
ends
=
table_read_ensure
(
&
table
,
offset
+
14
,
count
*
2
);
cmap
->
u
.
format4
.
starts
=
cmap
->
u
.
format4
.
ends
+
count
+
1
;
cmap
->
u
.
format4
.
id_delta
=
cmap
->
u
.
format4
.
starts
+
count
;
cmap
->
u
.
format4
.
id_range_offset
=
cmap
->
u
.
format4
.
id_delta
+
count
;
cmap
->
u
.
format4
.
glyph_id_array
=
cmap
->
data
=
cmap
->
u
.
format4
.
id_range_offset
+
count
;
cmap
->
u
.
format4
.
glyph_id_array_len
=
(
length
-
16
-
8
*
count
)
/
2
;
cmap
->
get_glyph
=
opentype_cmap_format4_get_glyph
;
break
;
case
6
:
case
10
:
/* Format 10 uses 4 byte fields. */
f
=
format
==
6
?
1
:
2
;
cmap
->
u
.
format6_10
.
first
=
table_read_be_word
(
&
table
,
offset
+
f
*
6
);
count
=
table_read_be_word
(
&
table
,
offset
+
f
*
8
);
cmap
->
u
.
format6_10
.
last
=
cmap
->
u
.
format6_10
.
first
+
count
;
cmap
->
data
=
table_read_ensure
(
&
table
,
offset
+
f
*
10
,
count
*
2
);
cmap
->
get_glyph
=
opentype_cmap_format6_10_get_glyph
;
break
;
case
12
:
case
13
:
cmap
->
u
.
format12_13
.
group_count
=
count
=
table_read_be_dword
(
&
table
,
offset
+
12
);
cmap
->
data
=
table_read_ensure
(
&
table
,
offset
+
16
,
count
*
3
*
4
);
cmap
->
get_glyph
=
format
==
12
?
opentype_cmap_format12_get_glyph
:
opentype_cmap_format13_get_glyph
;
break
;
default:
WARN
(
"Unhandled subtable format %u.
\n
"
,
format
);
}
failed:
if
(
!
cmap
->
data
)
{
/* Dummy implementation, returns 0 unconditionally. */
cmap
->
data
=
cmap
;
cmap
->
get_glyph
=
opentype_cmap_dummy_get_glyph
;
}
}
void
dwrite_cmap_release
(
struct
dwrite_cmap
*
cmap
)
{
if
(
cmap
->
stream
)
{
IDWriteFontFileStream_ReleaseFileFragment
(
cmap
->
stream
,
cmap
->
table_context
);
IDWriteFontFileStream_Release
(
cmap
->
stream
);
}
cmap
->
data
=
NULL
;
cmap
->
stream
=
NULL
;
}
static
unsigned
int
opentype_cmap_get_unicode_ranges_count
(
const
struct
dwrite_fonttable
*
cmap
)
{
unsigned
int
i
,
num_tables
,
count
=
0
;
...
...
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