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
ae3422c6
Commit
ae3422c6
authored
Mar 22, 2021
by
Nikolay Sivov
Committed by
Alexandre Julliard
Mar 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Return complete outline data from freetype integration code.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
ca143521
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
168 additions
and
59 deletions
+168
-59
dwrite_private.h
dlls/dwrite/dwrite_private.h
+31
-2
font.c
dlls/dwrite/font.c
+69
-2
freetype.c
dlls/dwrite/freetype.c
+68
-55
No files found.
dlls/dwrite/dwrite_private.h
View file @
ae3422c6
...
...
@@ -457,14 +457,43 @@ struct dwrite_glyphbitmap
DWRITE_MATRIX
*
m
;
};
enum
dwrite_outline_tags
{
OUTLINE_BEGIN_FIGURE
,
OUTLINE_END_FIGURE
,
OUTLINE_LINE
,
OUTLINE_BEZIER
,
};
struct
dwrite_outline
{
struct
{
unsigned
char
*
values
;
size_t
count
;
size_t
size
;
}
tags
;
struct
{
D2D1_POINT_2F
*
values
;
size_t
count
;
size_t
size
;
}
points
;
};
extern
int
dwrite_outline_push_tag
(
struct
dwrite_outline
*
outline
,
unsigned
char
tag
)
DECLSPEC_HIDDEN
;
extern
int
dwrite_outline_push_points
(
struct
dwrite_outline
*
outline
,
const
D2D1_POINT_2F
*
points
,
unsigned
int
count
)
DECLSPEC_HIDDEN
;
extern
BOOL
init_freetype
(
void
)
DECLSPEC_HIDDEN
;
extern
void
release_freetype
(
void
)
DECLSPEC_HIDDEN
;
extern
HRESULT
freetype_get_design_glyph_metrics
(
struct
dwrite_fontface
*
fontface
,
UINT16
glyph
,
DWRITE_GLYPH_METRICS
*
metrics
)
DECLSPEC_HIDDEN
;
extern
void
freetype_notify_cacheremove
(
IDWriteFontFace5
*
fontface
)
DECLSPEC_HIDDEN
;
extern
HRESULT
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
D2D1_POINT_2F
origin
,
IDWriteGeometrySink
*
sink
)
DECLSPEC_HIDDEN
;
extern
int
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
struct
dwrite_outline
*
outline
)
DECLSPEC_HIDDEN
;
extern
UINT16
freetype_get_glyphcount
(
IDWriteFontFace5
*
fontface
)
DECLSPEC_HIDDEN
;
extern
void
freetype_get_glyph_bbox
(
struct
dwrite_glyphbitmap
*
bitmap_desc
)
DECLSPEC_HIDDEN
;
extern
BOOL
freetype_get_glyph_bitmap
(
struct
dwrite_glyphbitmap
*
)
DECLSPEC_HIDDEN
;
...
...
dlls/dwrite/font.c
View file @
ae3422c6
...
...
@@ -823,13 +823,50 @@ static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace5 *iface, void
IDWriteFontFileStream_ReleaseFileFragment
(
fontface
->
stream
,
table_context
);
}
int
dwrite_outline_push_tag
(
struct
dwrite_outline
*
outline
,
unsigned
char
tag
)
{
if
(
!
dwrite_array_reserve
((
void
**
)
&
outline
->
tags
.
values
,
&
outline
->
tags
.
size
,
outline
->
tags
.
count
+
1
,
sizeof
(
*
outline
->
tags
.
values
)))
{
return
1
;
}
outline
->
tags
.
values
[
outline
->
tags
.
count
++
]
=
tag
;
return
0
;
}
int
dwrite_outline_push_points
(
struct
dwrite_outline
*
outline
,
const
D2D1_POINT_2F
*
points
,
unsigned
int
count
)
{
if
(
!
dwrite_array_reserve
((
void
**
)
&
outline
->
points
.
values
,
&
outline
->
points
.
size
,
outline
->
points
.
count
+
count
,
sizeof
(
*
outline
->
points
.
values
)))
{
return
1
;
}
memcpy
(
&
outline
->
points
.
values
[
outline
->
points
.
count
],
points
,
sizeof
(
*
points
)
*
count
);
outline
->
points
.
count
+=
count
;
return
0
;
}
static
void
apply_outline_point_offset
(
const
D2D1_POINT_2F
*
src
,
const
D2D1_POINT_2F
*
offset
,
D2D1_POINT_2F
*
dst
)
{
dst
->
x
=
src
->
x
+
offset
->
x
;
dst
->
y
=
src
->
y
+
offset
->
y
;
}
static
HRESULT
WINAPI
dwritefontface_GetGlyphRunOutline
(
IDWriteFontFace5
*
iface
,
FLOAT
emSize
,
UINT16
const
*
glyphs
,
FLOAT
const
*
advances
,
DWRITE_GLYPH_OFFSET
const
*
offsets
,
UINT32
count
,
BOOL
is_sideways
,
BOOL
is_rtl
,
IDWriteGeometrySink
*
sink
)
{
D2D1_POINT_2F
*
origins
,
baseline_origin
=
{
0
};
struct
dwrite_outline
outline
=
{{
0
}};
D2D1_BEZIER_SEGMENT
segment
;
D2D1_POINT_2F
point
;
DWRITE_GLYPH_RUN
run
;
unsigned
int
i
;
unsigned
int
i
,
j
,
p
;
HRESULT
hr
;
TRACE
(
"%p, %.8e, %p, %p, %p, %u, %d, %d, %p.
\n
"
,
iface
,
emSize
,
glyphs
,
advances
,
offsets
,
...
...
@@ -863,10 +900,40 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface,
for
(
i
=
0
;
i
<
count
;
++
i
)
{
if
(
FAILED
(
hr
=
freetype_get_glyph_outline
(
iface
,
emSize
,
glyphs
[
i
],
origins
[
i
],
sink
)))
outline
.
tags
.
count
=
outline
.
points
.
count
=
0
;
if
(
freetype_get_glyph_outline
(
iface
,
emSize
,
glyphs
[
i
],
&
outline
))
{
WARN
(
"Failed to get glyph outline for glyph %u.
\n
"
,
glyphs
[
i
]);
continue
;
}
for
(
j
=
0
,
p
=
0
;
j
<
outline
.
tags
.
count
;
++
j
)
{
switch
(
outline
.
tags
.
values
[
j
])
{
case
OUTLINE_BEGIN_FIGURE
:
apply_outline_point_offset
(
&
outline
.
points
.
values
[
p
++
],
&
origins
[
i
],
&
point
);
ID2D1SimplifiedGeometrySink_BeginFigure
(
sink
,
point
,
D2D1_FIGURE_BEGIN_FILLED
);
break
;
case
OUTLINE_END_FIGURE
:
ID2D1SimplifiedGeometrySink_EndFigure
(
sink
,
D2D1_FIGURE_END_CLOSED
);
break
;
case
OUTLINE_LINE
:
apply_outline_point_offset
(
&
outline
.
points
.
values
[
p
++
],
&
origins
[
i
],
&
point
);
ID2D1SimplifiedGeometrySink_AddLines
(
sink
,
&
point
,
1
);
break
;
case
OUTLINE_BEZIER
:
apply_outline_point_offset
(
&
outline
.
points
.
values
[
p
++
],
&
origins
[
i
],
&
segment
.
point1
);
apply_outline_point_offset
(
&
outline
.
points
.
values
[
p
++
],
&
origins
[
i
],
&
segment
.
point2
);
apply_outline_point_offset
(
&
outline
.
points
.
values
[
p
++
],
&
origins
[
i
],
&
segment
.
point3
);
ID2D1SimplifiedGeometrySink_AddBeziers
(
sink
,
&
segment
,
1
);
break
;
}
}
}
heap_free
(
outline
.
tags
.
values
);
heap_free
(
outline
.
points
.
values
);
heap_free
(
origins
);
return
S_OK
;
...
...
dlls/dwrite/freetype.c
View file @
ae3422c6
...
...
@@ -296,40 +296,46 @@ HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT
return
S_OK
;
}
struct
decompose_context
{
IDWriteGeometrySink
*
sink
;
D2D1_POINT_2F
offset
;
struct
decompose_context
{
struct
dwrite_outline
*
outline
;
BOOL
figure_started
;
BOOL
move_to
;
/* last call was 'move_to' */
FT_Vector
origin
;
/* 'pen' position from last call */
};
static
inline
void
ft_vector_to_d2d_point
(
const
FT_Vector
*
v
,
D2D1_POINT_2F
offset
,
D2D1_POINT_2F
*
p
)
static
inline
void
ft_vector_to_d2d_point
(
const
FT_Vector
*
v
,
D2D1_POINT_2F
*
p
)
{
p
->
x
=
(
v
->
x
/
64
.
0
f
)
+
offset
.
x
;
p
->
y
=
(
v
->
y
/
64
.
0
f
)
+
offset
.
y
;
p
->
x
=
v
->
x
/
64
.
0
f
;
p
->
y
=
v
->
y
/
64
.
0
f
;
}
static
void
decompose_beginfigure
(
struct
decompose_context
*
ctxt
)
static
int
decompose_beginfigure
(
struct
decompose_context
*
ctxt
)
{
D2D1_POINT_2F
point
;
int
ret
;
if
(
!
ctxt
->
move_to
)
return
;
return
0
;
ft_vector_to_d2d_point
(
&
ctxt
->
origin
,
ctxt
->
offset
,
&
point
);
ID2D1SimplifiedGeometrySink_BeginFigure
(
ctxt
->
sink
,
point
,
D2D1_FIGURE_BEGIN_FILLED
);
ft_vector_to_d2d_point
(
&
ctxt
->
origin
,
&
point
);
if
((
ret
=
dwrite_outline_push_tag
(
ctxt
->
outline
,
OUTLINE_BEGIN_FIGURE
)))
return
ret
;
if
((
ret
=
dwrite_outline_push_points
(
ctxt
->
outline
,
&
point
,
1
)))
return
ret
;
ctxt
->
figure_started
=
TRUE
;
ctxt
->
move_to
=
FALSE
;
return
0
;
}
static
int
decompose_move_to
(
const
FT_Vector
*
to
,
void
*
user
)
{
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
int
ret
;
if
(
ctxt
->
figure_started
)
{
ID2D1SimplifiedGeometrySink_EndFigure
(
ctxt
->
sink
,
D2D1_FIGURE_END_CLOSED
);
if
(
ctxt
->
figure_started
)
{
if
((
ret
=
dwrite_outline_push_tag
(
ctxt
->
outline
,
OUTLINE_END_FIGURE
)))
return
ret
;
ctxt
->
figure_started
=
FALSE
;
}
...
...
@@ -340,17 +346,19 @@ static int decompose_move_to(const FT_Vector *to, void *user)
static
int
decompose_line_to
(
const
FT_Vector
*
to
,
void
*
user
)
{
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
D2D1_POINT_2F
point
;
int
ret
;
/* Special case for empty contours, in a way freetype returns them. */
if
(
ctxt
->
move_to
&&
!
memcmp
(
to
,
&
ctxt
->
origin
,
sizeof
(
*
to
)))
return
0
;
decompose_beginfigure
(
ctx
t
);
ft_vector_to_d2d_point
(
to
,
&
poin
t
);
ft_vector_to_d2d_point
(
to
,
ctxt
->
offset
,
&
point
);
ID2D1SimplifiedGeometrySink_AddLines
(
ctxt
->
sink
,
&
point
,
1
);
if
((
ret
=
decompose_beginfigure
(
ctxt
)))
return
ret
;
if
((
ret
=
dwrite_outline_push_points
(
ctxt
->
outline
,
&
point
,
1
)))
return
ret
;
if
((
ret
=
dwrite_outline_push_tag
(
ctxt
->
outline
,
OUTLINE_LINE
)))
return
ret
;
ctxt
->
origin
=
*
to
;
return
0
;
...
...
@@ -358,11 +366,13 @@ static int decompose_line_to(const FT_Vector *to, void *user)
static
int
decompose_conic_to
(
const
FT_Vector
*
control
,
const
FT_Vector
*
to
,
void
*
user
)
{
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
D2D1_POINT_2F
points
[
3
];
FT_Vector
cubic
[
3
];
int
ret
;
decompose_beginfigure
(
ctxt
);
if
((
ret
=
decompose_beginfigure
(
ctxt
)))
return
ret
;
/* convert from quadratic to cubic */
...
...
@@ -394,10 +404,11 @@ static int decompose_conic_to(const FT_Vector *control, const FT_Vector *to, voi
cubic
[
1
].
y
+=
(
to
->
y
+
1
)
/
3
;
cubic
[
2
]
=
*
to
;
ft_vector_to_d2d_point
(
cubic
,
ctxt
->
offset
,
points
);
ft_vector_to_d2d_point
(
cubic
+
1
,
ctxt
->
offset
,
points
+
1
);
ft_vector_to_d2d_point
(
cubic
+
2
,
ctxt
->
offset
,
points
+
2
);
ID2D1SimplifiedGeometrySink_AddBeziers
(
ctxt
->
sink
,
(
D2D1_BEZIER_SEGMENT
*
)
points
,
1
);
ft_vector_to_d2d_point
(
cubic
,
points
);
ft_vector_to_d2d_point
(
cubic
+
1
,
points
+
1
);
ft_vector_to_d2d_point
(
cubic
+
2
,
points
+
2
);
if
((
ret
=
dwrite_outline_push_points
(
ctxt
->
outline
,
points
,
3
)))
return
ret
;
if
((
ret
=
dwrite_outline_push_tag
(
ctxt
->
outline
,
OUTLINE_BEZIER
)))
return
ret
;
ctxt
->
origin
=
*
to
;
return
0
;
}
...
...
@@ -405,22 +416,28 @@ static int decompose_conic_to(const FT_Vector *control, const FT_Vector *to, voi
static
int
decompose_cubic_to
(
const
FT_Vector
*
control1
,
const
FT_Vector
*
control2
,
const
FT_Vector
*
to
,
void
*
user
)
{
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
struct
decompose_context
*
ctxt
=
(
struct
decompose_context
*
)
user
;
D2D1_POINT_2F
points
[
3
];
int
ret
;
decompose_beginfigure
(
ctxt
);
if
((
ret
=
decompose_beginfigure
(
ctxt
)))
return
ret
;
ft_vector_to_d2d_point
(
control1
,
ctxt
->
offset
,
points
);
ft_vector_to_d2d_point
(
control2
,
ctxt
->
offset
,
points
+
1
);
ft_vector_to_d2d_point
(
to
,
ctxt
->
offset
,
points
+
2
);
ID2D1SimplifiedGeometrySink_AddBeziers
(
ctxt
->
sink
,
(
D2D1_BEZIER_SEGMENT
*
)
points
,
1
);
ft_vector_to_d2d_point
(
control1
,
points
);
ft_vector_to_d2d_point
(
control2
,
points
+
1
);
ft_vector_to_d2d_point
(
to
,
points
+
2
);
ctxt
->
origin
=
*
to
;
if
((
ret
=
dwrite_outline_push_points
(
ctxt
->
outline
,
points
,
3
)))
return
ret
;
if
((
ret
=
dwrite_outline_push_tag
(
ctxt
->
outline
,
OUTLINE_BEZIER
)))
return
ret
;
return
0
;
}
static
void
decompose_outline
(
FT_Outline
*
outline
,
D2D1_POINT_2F
offset
,
IDWriteGeometrySink
*
sink
)
static
int
decompose_outline
(
FT_Outline
*
ft_outline
,
struct
dwrite_outline
*
outline
)
{
static
const
FT_Outline_Funcs
decompose_funcs
=
{
static
const
FT_Outline_Funcs
decompose_funcs
=
{
decompose_move_to
,
decompose_line_to
,
decompose_conic_to
,
...
...
@@ -428,19 +445,17 @@ static void decompose_outline(FT_Outline *outline, D2D1_POINT_2F offset, IDWrite
0
,
0
};
struct
decompose_context
context
;
struct
decompose_context
context
=
{
0
};
int
ret
;
context
.
sink
=
sink
;
context
.
offset
=
offset
;
context
.
figure_started
=
FALSE
;
context
.
move_to
=
FALSE
;
context
.
origin
.
x
=
0
;
context
.
origin
.
y
=
0
;
context
.
outline
=
outline
;
pFT_Outline_Decompose
(
outline
,
&
decompose_funcs
,
&
context
);
ret
=
pFT_Outline_Decompose
(
ft_
outline
,
&
decompose_funcs
,
&
context
);
if
(
context
.
figure_started
)
ID2D1SimplifiedGeometrySink_EndFigure
(
sink
,
D2D1_FIGURE_END_CLOSED
);
if
(
!
ret
&&
context
.
figure_started
)
ret
=
dwrite_outline_push_tag
(
outline
,
OUTLINE_END_FIGURE
);
return
ret
;
}
static
void
embolden_glyph_outline
(
FT_Outline
*
outline
,
FLOAT
emsize
)
...
...
@@ -464,13 +479,13 @@ static void embolden_glyph(FT_Glyph glyph, FLOAT emsize)
embolden_glyph_outline
(
&
outline_glyph
->
outline
,
emsize
);
}
HRESULT
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
D2D1_POINT_2F
origin
,
IDWriteGeometrySink
*
sink
)
int
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
struct
dwrite_outline
*
outline
)
{
FTC_ScalerRec
scaler
;
USHORT
simulations
;
HRESULT
hr
=
S_OK
;
FT_Size
size
;
int
ret
;
simulations
=
IDWriteFontFace5_GetSimulations
(
fontface
);
...
...
@@ -482,31 +497,29 @@ HRESULT freetype_get_glyph_outline(IDWriteFontFace5 *fontface, float emSize, UIN
scaler
.
y_res
=
0
;
EnterCriticalSection
(
&
freetype_cs
);
if
(
pFTC_Manager_LookupSize
(
cache_manager
,
&
scaler
,
&
size
)
==
0
)
if
(
!
(
ret
=
pFTC_Manager_LookupSize
(
cache_manager
,
&
scaler
,
&
size
))
)
{
if
(
pFT_Load_Glyph
(
size
->
face
,
glyph
,
FT_LOAD_NO_BITMAP
)
==
0
)
{
FT_Outline
*
outline
=
&
size
->
face
->
glyph
->
outline
;
FT_Outline
*
ft_
outline
=
&
size
->
face
->
glyph
->
outline
;
FT_Matrix
m
;
if
(
simulations
&
DWRITE_FONT_SIMULATIONS_BOLD
)
embolden_glyph_outline
(
outline
,
emSize
);
embolden_glyph_outline
(
ft_
outline
,
emSize
);
m
.
xx
=
1
<<
16
;
m
.
xy
=
simulations
&
DWRITE_FONT_SIMULATIONS_OBLIQUE
?
(
1
<<
16
)
/
3
:
0
;
m
.
yx
=
0
;
m
.
yy
=
-
(
1
<<
16
);
/* flip Y axis */
pFT_Outline_Transform
(
outline
,
&
m
);
pFT_Outline_Transform
(
ft_
outline
,
&
m
);
decompose_outline
(
outline
,
origin
,
sink
);
ret
=
decompose_outline
(
ft_outline
,
outline
);
}
}
else
hr
=
E_FAIL
;
LeaveCriticalSection
(
&
freetype_cs
);
return
hr
;
return
ret
;
}
UINT16
freetype_get_glyphcount
(
IDWriteFontFace5
*
fontface
)
...
...
@@ -797,10 +810,10 @@ HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT
return
E_NOTIMPL
;
}
HRESULT
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
D2D1_POINT_2F
origin
,
IDWriteGeometrySink
*
sink
)
int
freetype_get_glyph_outline
(
IDWriteFontFace5
*
fontface
,
float
emSize
,
UINT16
glyph
,
struct
dwrite_outline
*
outline
)
{
return
E_NOTIMPL
;
return
1
;
}
UINT16
freetype_get_glyphcount
(
IDWriteFontFace5
*
fontface
)
...
...
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