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
b8e3fbe0
Commit
b8e3fbe0
authored
Jun 04, 2015
by
Nikolay Sivov
Committed by
Alexandre Julliard
Jun 05, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dwrite: Report strikethrough ranges to renderer.
parent
e31881a6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
127 additions
and
29 deletions
+127
-29
layout.c
dlls/dwrite/layout.c
+103
-28
layout.c
dlls/dwrite/tests/layout.c
+24
-1
No files found.
dlls/dwrite/layout.c
View file @
b8e3fbe0
...
...
@@ -176,6 +176,12 @@ struct layout_effective_inline {
BOOL
is_rtl
;
};
struct
layout_strikethrough
{
struct
list
entry
;
const
struct
layout_effective_run
*
run
;
DWRITE_STRIKETHROUGH
s
;
};
struct
layout_cluster
{
const
struct
layout_run
*
run
;
/* link to nominal run this cluster belongs to */
UINT32
position
;
/* relative to run, first cluster has 0 position */
...
...
@@ -206,6 +212,7 @@ struct dwrite_textlayout {
/* lists ready to use by Draw() */
struct
list
eruns
;
struct
list
inlineobjects
;
struct
list
strikethrough
;
USHORT
recompute
;
DWRITE_LINE_BREAKPOINT
*
nominal_breakpoints
;
...
...
@@ -355,6 +362,7 @@ static void free_layout_eruns(struct dwrite_textlayout *layout)
{
struct
layout_effective_inline
*
in
,
*
in2
;
struct
layout_effective_run
*
cur
,
*
cur2
;
struct
layout_strikethrough
*
s
,
*
s2
;
LIST_FOR_EACH_ENTRY_SAFE
(
cur
,
cur2
,
&
layout
->
eruns
,
struct
layout_effective_run
,
entry
)
{
list_remove
(
&
cur
->
entry
);
...
...
@@ -366,6 +374,11 @@ static void free_layout_eruns(struct dwrite_textlayout *layout)
list_remove
(
&
in
->
entry
);
heap_free
(
in
);
}
LIST_FOR_EACH_ENTRY_SAFE
(
s
,
s2
,
&
layout
->
strikethrough
,
struct
layout_strikethrough
,
entry
)
{
list_remove
(
&
s
->
entry
);
heap_free
(
s
);
}
}
/* Used to resolve break condition by forcing stronger condition over weaker. */
...
...
@@ -808,10 +821,18 @@ static HRESULT layout_compute(struct dwrite_textlayout *layout)
return
hr
;
}
static
inline
FLOAT
get_cluster_range_width
(
struct
dwrite_textlayout
*
layout
,
UINT32
start
,
UINT32
end
)
{
FLOAT
width
=
0
.
0
;
for
(;
start
<
end
;
start
++
)
width
+=
layout
->
clustermetrics
[
start
].
width
;
return
width
;
}
/* Effective run is built from consecutive clusters of a single nominal run, 'first_cluster' is 0 based cluster index,
'cluster_count' indicates how many clusters to add, including first one. */
static
HRESULT
layout_add_effective_run
(
struct
dwrite_textlayout
*
layout
,
const
struct
layout_run
*
r
,
UINT32
first_cluster
,
UINT32
cluster_count
,
FLOAT
origin_x
)
UINT32
cluster_count
,
FLOAT
origin_x
,
BOOL
strikethrough
)
{
UINT32
i
,
start
,
length
,
last_cluster
;
struct
layout_effective_run
*
run
;
...
...
@@ -839,9 +860,11 @@ static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const
if
(
!
run
)
return
E_OUTOFMEMORY
;
/* no need to iterate for that */
/* No need to iterate for that, use simple fact that:
<last cluster position> = first cluster position> + <sum of cluster lengths not including last one> */
last_cluster
=
first_cluster
+
cluster_count
-
1
;
length
=
layout
->
clusters
[
last_cluster
].
position
+
layout
->
clustermetrics
[
last_cluster
].
length
;
length
=
layout
->
clusters
[
last_cluster
].
position
-
layout
->
clusters
[
first_cluster
].
position
+
layout
->
clustermetrics
[
last_cluster
].
length
;
run
->
clustermap
=
heap_alloc
(
sizeof
(
UINT16
)
*
length
);
if
(
!
run
->
clustermap
)
{
...
...
@@ -870,6 +893,43 @@ static HRESULT layout_add_effective_run(struct dwrite_textlayout *layout, const
run
->
clustermap
[
i
]
=
r
->
u
.
regular
.
clustermap
[
start
]
-
start
;
list_add_tail
(
&
layout
->
eruns
,
&
run
->
entry
);
/* Strikethrough style is guaranteed to be consistent within effective run,
it's width equals to run width, thikness and offset are derived from
font metrics, rest of the values are from layout or run itself */
if
(
strikethrough
)
{
DWRITE_FONT_METRICS
metrics
=
{
0
};
struct
layout_strikethrough
*
s
;
s
=
heap_alloc
(
sizeof
(
*
s
));
if
(
!
s
)
return
E_OUTOFMEMORY
;
if
(
layout
->
gdicompatible
)
{
HRESULT
hr
=
IDWriteFontFace_GetGdiCompatibleMetrics
(
r
->
u
.
regular
.
run
.
fontFace
,
r
->
u
.
regular
.
run
.
fontEmSize
,
layout
->
pixels_per_dip
,
&
layout
->
transform
,
&
metrics
);
if
(
FAILED
(
hr
))
WARN
(
"failed to get font metrics, 0x%08x
\n
"
,
hr
);
}
else
IDWriteFontFace_GetMetrics
(
r
->
u
.
regular
.
run
.
fontFace
,
&
metrics
);
s
->
s
.
width
=
get_cluster_range_width
(
layout
,
first_cluster
,
first_cluster
+
cluster_count
);
s
->
s
.
thickness
=
metrics
.
strikethroughThickness
;
s
->
s
.
offset
=
metrics
.
strikethroughPosition
;
s
->
s
.
readingDirection
=
layout
->
format
.
readingdir
;
s
->
s
.
flowDirection
=
layout
->
format
.
flow
;
s
->
s
.
localeName
=
r
->
u
.
regular
.
descr
.
localeName
;
s
->
s
.
measuringMode
=
DWRITE_MEASURING_MODE_NATURAL
;
/* FIXME */
s
->
run
=
run
;
list_add_tail
(
&
layout
->
strikethrough
,
&
s
->
entry
);
}
return
S_OK
;
}
...
...
@@ -895,12 +955,23 @@ static HRESULT layout_set_line_metrics(struct dwrite_textlayout *layout, DWRITE_
return
S_OK
;
}
static
inline
FLOAT
get_cluster_range_width
(
struct
dwrite_textlayout
*
layout
,
UINT32
start
,
UINT32
end
)
static
struct
layout_range_header
*
get_layout_range_header_by_pos
(
struct
list
*
ranges
,
UINT32
pos
)
{
FLOAT
width
=
0
.
0
;
for
(;
start
<
end
;
start
++
)
width
+=
layout
->
clustermetrics
[
start
].
width
;
return
width
;
struct
layout_range_header
*
cur
;
LIST_FOR_EACH_ENTRY
(
cur
,
ranges
,
struct
layout_range_header
,
entry
)
{
DWRITE_TEXT_RANGE
*
r
=
&
cur
->
range
;
if
(
r
->
startPosition
<=
pos
&&
pos
<
r
->
startPosition
+
r
->
length
)
return
cur
;
}
return
NULL
;
}
static
inline
BOOL
layout_get_strikethrough_from_pos
(
struct
dwrite_textlayout
*
layout
,
UINT32
pos
)
{
struct
layout_range_header
*
h
=
get_layout_range_header_by_pos
(
&
layout
->
strike_ranges
,
pos
);
return
((
struct
layout_range_bool
*
)
h
)
->
value
;
}
static
HRESULT
layout_compute_effective_runs
(
struct
dwrite_textlayout
*
layout
)
...
...
@@ -908,8 +979,9 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
DWRITE_LINE_METRICS
metrics
;
const
struct
layout_run
*
run
;
FLOAT
width
,
origin_x
;
UINT32
i
,
start
,
line
;
UINT32
i
,
start
,
line
,
textpos
;
HRESULT
hr
;
BOOL
s
[
2
];
if
(
!
(
layout
->
recompute
&
RECOMPUTE_EFFECTIVE_RUNS
))
return
S_OK
;
...
...
@@ -923,17 +995,21 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
line
=
0
;
run
=
layout
->
clusters
[
0
].
run
;
memset
(
&
metrics
,
0
,
sizeof
(
metrics
));
s
[
0
]
=
s
[
1
]
=
layout_get_strikethrough_from_pos
(
layout
,
0
);
for
(
i
=
0
,
start
=
0
,
width
=
0
.
0
;
i
<
layout
->
cluster_count
;
i
++
)
{
for
(
i
=
0
,
start
=
0
,
textpos
=
0
,
width
=
0
.
0
;
i
<
layout
->
cluster_count
;
i
++
)
{
BOOL
can_wrap_after
=
layout
->
clustermetrics
[
i
].
canWrapLineAfter
;
s
[
1
]
=
layout_get_strikethrough_from_pos
(
layout
,
textpos
);
/* switched to next nominal run, at this point all previous pending clusters are already
checked for layout line overflow, so new effective run will fit in current line */
if
(
run
!=
layout
->
clusters
[
i
].
run
)
{
hr
=
layout_add_effective_run
(
layout
,
run
,
start
,
i
-
start
,
origin_x
);
if
(
run
!=
layout
->
clusters
[
i
].
run
||
s
[
0
]
!=
s
[
1
]
)
{
hr
=
layout_add_effective_run
(
layout
,
run
,
start
,
i
-
start
,
origin_x
,
s
[
0
]
);
if
(
FAILED
(
hr
))
return
hr
;
origin_x
+=
get_cluster_range_width
(
layout
,
start
,
i
);
run
=
layout
->
clusters
[
i
].
run
;
start
=
i
;
}
...
...
@@ -945,7 +1021,7 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
UINT32
strlength
=
metrics
.
length
,
index
=
i
;
if
(
i
>=
start
)
{
hr
=
layout_add_effective_run
(
layout
,
run
,
start
,
i
-
start
+
1
,
origin_x
);
hr
=
layout_add_effective_run
(
layout
,
run
,
start
,
i
-
start
+
1
,
origin_x
,
s
[
0
]
);
if
(
FAILED
(
hr
))
return
hr
;
/* we don't need to update origin for next run as we're going to wrap */
...
...
@@ -988,7 +1064,8 @@ static HRESULT layout_compute_effective_runs(struct dwrite_textlayout *layout)
width
+=
layout
->
clustermetrics
[
i
].
width
;
}
run
=
layout
->
clusters
[
i
].
run
;
s
[
0
]
=
s
[
1
];
textpos
+=
layout
->
clustermetrics
[
i
].
length
;
}
layout
->
line_count
=
line
;
...
...
@@ -1256,19 +1333,6 @@ static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *la
return
NULL
;
}
static
struct
layout_range_header
*
get_layout_range_header_by_pos
(
struct
list
*
ranges
,
UINT32
pos
)
{
struct
layout_range_header
*
cur
;
LIST_FOR_EACH_ENTRY
(
cur
,
ranges
,
struct
layout_range_header
,
entry
)
{
DWRITE_TEXT_RANGE
*
r
=
&
cur
->
range
;
if
(
r
->
startPosition
<=
pos
&&
pos
<
r
->
startPosition
+
r
->
length
)
return
cur
;
}
return
NULL
;
}
static
inline
BOOL
set_layout_range_iface_attr
(
IUnknown
**
dest
,
IUnknown
*
value
)
{
if
(
*
dest
==
value
)
return
FALSE
;
...
...
@@ -2193,6 +2257,7 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
struct
dwrite_textlayout
*
This
=
impl_from_IDWriteTextLayout2
(
iface
);
struct
layout_effective_inline
*
inlineobject
;
struct
layout_effective_run
*
run
;
struct
layout_strikethrough
*
s
;
HRESULT
hr
;
TRACE
(
"(%p)->(%p %p %.2f %.2f)
\n
"
,
This
,
context
,
renderer
,
origin_x
,
origin_y
);
...
...
@@ -2250,7 +2315,16 @@ static HRESULT WINAPI dwritetextlayout_Draw(IDWriteTextLayout2 *iface,
}
/* TODO: 3. Underlines */
/* TODO: 4. Strikethrough */
/* 4. Strikethrough */
LIST_FOR_EACH_ENTRY
(
s
,
&
This
->
strikethrough
,
struct
layout_strikethrough
,
entry
)
{
IDWriteTextRenderer_DrawStrikethrough
(
renderer
,
context
,
s
->
run
->
origin_x
,
s
->
run
->
origin_y
,
&
s
->
s
,
s
->
run
->
run
->
effect
);
}
return
S_OK
;
}
...
...
@@ -3206,6 +3280,7 @@ static HRESULT init_textlayout(const WCHAR *str, UINT32 len, IDWriteTextFormat *
layout
->
minwidth
=
0
.
0
;
list_init
(
&
layout
->
eruns
);
list_init
(
&
layout
->
inlineobjects
);
list_init
(
&
layout
->
strikethrough
);
list_init
(
&
layout
->
runs
);
list_init
(
&
layout
->
ranges
);
list_init
(
&
layout
->
strike_ranges
);
...
...
dlls/dwrite/tests/layout.c
View file @
b8e3fbe0
...
...
@@ -1156,6 +1156,14 @@ static const struct drawcall_entry draw_seq4[] = {
{
DRAW_LAST_KIND
}
};
static
const
struct
drawcall_entry
draw_seq5
[]
=
{
{
DRAW_GLYPHRUN
,
{
's'
,
't'
,
0
}
},
{
DRAW_GLYPHRUN
,
{
'r'
,
'i'
,
0
}
},
{
DRAW_GLYPHRUN
,
{
'n'
,
'g'
,
0
}
},
{
DRAW_STRIKETHROUGH
},
{
DRAW_LAST_KIND
}
};
static
void
test_Draw
(
void
)
{
static
const
WCHAR
strW
[]
=
{
's'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
0
};
...
...
@@ -1238,7 +1246,22 @@ static void test_Draw(void)
hr
=
IDWriteTextLayout_Draw
(
layout
,
NULL
,
&
testrenderer
,
0
.
0
,
0
.
0
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
ok_sequence
(
sequences
,
RENDERER_ID
,
draw_seq4
,
"draw test 4"
,
TRUE
);
ok_sequence
(
sequences
,
RENDERER_ID
,
draw_seq4
,
"draw test 4"
,
FALSE
);
IDWriteTextLayout_Release
(
layout
);
/* strikethrough somewhere in the middle */
hr
=
IDWriteFactory_CreateTextLayout
(
factory
,
strW
,
6
,
format
,
500
.
0
,
100
.
0
,
&
layout
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
flush_sequence
(
sequences
,
RENDERER_ID
);
range
.
startPosition
=
2
;
range
.
length
=
2
;
hr
=
IDWriteTextLayout_SetStrikethrough
(
layout
,
TRUE
,
range
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
hr
=
IDWriteTextLayout_Draw
(
layout
,
NULL
,
&
testrenderer
,
0
.
0
,
0
.
0
);
ok
(
hr
==
S_OK
,
"got 0x%08x
\n
"
,
hr
);
ok_sequence
(
sequences
,
RENDERER_ID
,
draw_seq5
,
"draw test 5"
,
FALSE
);
IDWriteTextLayout_Release
(
layout
);
IDWriteTextFormat_Release
(
format
);
...
...
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