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
8245b46e
Commit
8245b46e
authored
Mar 09, 2011
by
Dylan Smith
Committed by
Alexandre Julliard
Mar 10, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
d3dx9: Support triangulation of complex glyphs in D3DXCreateText.
parent
3eee5b74
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
350 additions
and
4 deletions
+350
-4
mesh.c
dlls/d3dx9_36/mesh.c
+350
-4
No files found.
dlls/d3dx9_36/mesh.c
View file @
8245b46e
...
...
@@ -1589,6 +1589,30 @@ struct glyphinfo
float
offset_x
;
};
/* is an dynamic_array */
struct
word_array
{
int
count
,
capacity
;
WORD
*
items
;
};
/* complex polygons are split into monotone polygons, which have
* at most 2 intersections with the vertical sweep line */
struct
triangulation
{
struct
word_array
vertex_stack
;
BOOL
last_on_top
,
merging
;
};
/* is an dynamic_array */
struct
triangulation_array
{
int
count
,
capacity
;
struct
triangulation
*
items
;
struct
glyphinfo
*
glyph
;
};
static
BOOL
reserve
(
struct
dynamic_array
*
array
,
int
count
,
int
itemsize
)
{
if
(
count
>
array
->
capacity
)
{
...
...
@@ -1633,6 +1657,32 @@ static struct outline *add_outline(struct outline_array *array)
return
item
;
}
static
inline
face
*
add_face
(
struct
face_array
*
array
)
{
return
&
array
->
items
[
array
->
count
++
];
}
static
struct
triangulation
*
add_triangulation
(
struct
triangulation_array
*
array
)
{
struct
triangulation
*
item
;
if
(
!
reserve
((
struct
dynamic_array
*
)
array
,
array
->
count
+
1
,
sizeof
(
array
->
items
[
0
])))
return
NULL
;
item
=
&
array
->
items
[
array
->
count
++
];
ZeroMemory
(
item
,
sizeof
(
*
item
));
return
item
;
}
static
HRESULT
add_vertex_index
(
struct
word_array
*
array
,
WORD
vertex_index
)
{
if
(
!
reserve
((
struct
dynamic_array
*
)
array
,
array
->
count
+
1
,
sizeof
(
array
->
items
[
0
])))
return
E_OUTOFMEMORY
;
array
->
items
[
array
->
count
++
]
=
vertex_index
;
return
S_OK
;
}
/* assume fixed point numbers can be converted to float point in place */
C_ASSERT
(
sizeof
(
FIXED
)
==
sizeof
(
float
));
C_ASSERT
(
sizeof
(
POINTFX
)
==
sizeof
(
D3DXVECTOR2
));
...
...
@@ -1889,6 +1939,21 @@ static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int da
return
S_OK
;
}
/* Get the y-distance from a line to a point */
static
float
get_line_to_point_y_distance
(
D3DXVECTOR2
*
line_pt1
,
D3DXVECTOR2
*
line_pt2
,
D3DXVECTOR2
*
point
)
{
D3DXVECTOR2
line_vec
=
{
0
,
0
};
float
line_pt_dx
;
float
line_y
;
D3DXVec2Subtract
(
&
line_vec
,
line_pt2
,
line_pt1
);
line_pt_dx
=
point
->
x
-
line_pt1
->
x
;
line_y
=
line_pt1
->
y
+
(
line_vec
.
y
*
line_pt_dx
)
/
line_vec
.
x
;
return
point
->
y
-
line_y
;
}
static
D3DXVECTOR2
*
get_indexed_point
(
struct
point2d_index
*
pt_idx
)
{
return
&
pt_idx
->
outline
->
items
[
pt_idx
->
vertex
].
pos
;
...
...
@@ -1899,8 +1964,126 @@ static D3DXVECTOR2 *get_ordered_vertex(struct glyphinfo *glyph, WORD index)
return
get_indexed_point
(
&
glyph
->
ordered_vertices
.
items
[
index
]);
}
static
HRESULT
triangulate
(
struct
glyphinfo
*
glyph
)
static
void
remove_triangulation
(
struct
triangulation_array
*
array
,
struct
triangulation
*
item
)
{
HeapFree
(
GetProcessHeap
(),
0
,
item
->
vertex_stack
.
items
);
MoveMemory
(
item
,
item
+
1
,
(
char
*
)
&
array
->
items
[
array
->
count
]
-
(
char
*
)(
item
+
1
));
array
->
count
--
;
}
static
HRESULT
triangulation_add_point
(
struct
triangulation
**
t_ptr
,
struct
triangulation_array
*
triangulations
,
WORD
vtx_idx
,
BOOL
to_top
)
{
struct
glyphinfo
*
glyph
=
triangulations
->
glyph
;
struct
triangulation
*
t
=
*
t_ptr
;
HRESULT
hr
;
face
*
face
;
int
f1
,
f2
;
if
(
t
->
last_on_top
)
{
f1
=
1
;
f2
=
2
;
}
else
{
f1
=
2
;
f2
=
1
;
}
if
(
t
->
last_on_top
!=
to_top
&&
t
->
vertex_stack
.
count
>
1
)
{
/* consume all vertices on the stack */
WORD
last_pt
=
t
->
vertex_stack
.
items
[
0
];
int
i
;
for
(
i
=
1
;
i
<
t
->
vertex_stack
.
count
;
i
++
)
{
face
=
add_face
(
&
glyph
->
faces
);
if
(
!
face
)
return
E_OUTOFMEMORY
;
(
*
face
)[
0
]
=
vtx_idx
;
(
*
face
)[
f1
]
=
last_pt
;
(
*
face
)[
f2
]
=
last_pt
=
t
->
vertex_stack
.
items
[
i
];
}
t
->
vertex_stack
.
items
[
0
]
=
last_pt
;
t
->
vertex_stack
.
count
=
1
;
}
else
if
(
t
->
vertex_stack
.
count
>
1
)
{
int
i
=
t
->
vertex_stack
.
count
-
1
;
D3DXVECTOR2
*
point
=
get_ordered_vertex
(
glyph
,
vtx_idx
);
WORD
top_idx
=
t
->
vertex_stack
.
items
[
i
--
];
D3DXVECTOR2
*
top_pt
=
get_ordered_vertex
(
glyph
,
top_idx
);
while
(
i
>=
0
)
{
WORD
prev_idx
=
t
->
vertex_stack
.
items
[
i
--
];
D3DXVECTOR2
*
prev_pt
=
get_ordered_vertex
(
glyph
,
prev_idx
);
if
(
prev_pt
->
x
!=
top_pt
->
x
&&
((
to_top
&&
get_line_to_point_y_distance
(
prev_pt
,
top_pt
,
point
)
>
0
)
||
(
!
to_top
&&
get_line_to_point_y_distance
(
prev_pt
,
top_pt
,
point
)
<
0
)))
break
;
face
=
add_face
(
&
glyph
->
faces
);
if
(
!
face
)
return
E_OUTOFMEMORY
;
(
*
face
)[
0
]
=
vtx_idx
;
(
*
face
)[
f1
]
=
prev_idx
;
(
*
face
)[
f2
]
=
top_idx
;
top_pt
=
prev_pt
;
top_idx
=
prev_idx
;
t
->
vertex_stack
.
count
--
;
}
}
t
->
last_on_top
=
to_top
;
hr
=
add_vertex_index
(
&
t
->
vertex_stack
,
vtx_idx
);
if
(
hr
==
S_OK
&&
t
->
merging
)
{
struct
triangulation
*
t2
;
t2
=
to_top
?
t
-
1
:
t
+
1
;
t2
->
merging
=
FALSE
;
hr
=
triangulation_add_point
(
&
t2
,
triangulations
,
vtx_idx
,
to_top
);
if
(
hr
!=
S_OK
)
return
hr
;
remove_triangulation
(
triangulations
,
t
);
if
(
t2
>
t
)
t2
--
;
*
t_ptr
=
t2
;
}
return
hr
;
}
/* check if the point is next on the outline for either the top or bottom */
static
D3DXVECTOR2
*
triangulation_get_next_point
(
struct
triangulation
*
t
,
struct
glyphinfo
*
glyph
,
BOOL
on_top
)
{
int
i
=
t
->
last_on_top
==
on_top
?
t
->
vertex_stack
.
count
-
1
:
0
;
WORD
idx
=
t
->
vertex_stack
.
items
[
i
];
struct
point2d_index
*
pt_idx
=
&
glyph
->
ordered_vertices
.
items
[
idx
];
struct
outline
*
outline
=
pt_idx
->
outline
;
if
(
on_top
)
i
=
(
pt_idx
->
vertex
+
outline
->
count
-
1
)
%
outline
->
count
;
else
i
=
(
pt_idx
->
vertex
+
1
)
%
outline
->
count
;
return
&
outline
->
items
[
i
].
pos
;
}
static
int
compare_vertex_indices
(
const
void
*
a
,
const
void
*
b
)
{
const
struct
point2d_index
*
idx1
=
a
,
*
idx2
=
b
;
const
D3DXVECTOR2
*
p1
=
&
idx1
->
outline
->
items
[
idx1
->
vertex
].
pos
;
const
D3DXVECTOR2
*
p2
=
&
idx2
->
outline
->
items
[
idx2
->
vertex
].
pos
;
float
diff
=
p1
->
x
-
p2
->
x
;
if
(
diff
==
0
.
0
f
)
diff
=
p1
->
y
-
p2
->
y
;
return
diff
==
0
.
0
f
?
0
:
(
diff
>
0
.
0
f
?
-
1
:
1
);
}
static
HRESULT
triangulate
(
struct
triangulation_array
*
triangulations
)
{
int
sweep_idx
;
HRESULT
hr
;
struct
glyphinfo
*
glyph
=
triangulations
->
glyph
;
int
nb_vertices
=
0
;
int
i
;
struct
point2d_index
*
idx_ptr
;
...
...
@@ -1972,9 +2155,160 @@ static HRESULT triangulate(struct glyphinfo *glyph)
}
}
FIXME
(
"triangulation of complex glyphs not yet implemented for D3DXCreateText.
\n
"
);
/* Perform 2D polygon triangulation for complex glyphs.
* Triangulation is performed using a sweep line concept, from right to left,
* by processing vertices in sorted order. Complex polygons are split into
* monotone polygons which are triangulated seperately. */
/* FIXME: The order of the faces is not consistent with the native implementation. */
return
E_NOTIMPL
;
/* Reserve space for maximum possible faces from triangulation.
* # faces for outer outlines = outline->count - 2
* # faces for inner outlines = outline->count + 2
* There must be at least 1 outer outline. */
glyph
->
faces
.
items
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
nb_vertices
+
glyph
->
outlines
.
count
*
2
-
4
)
*
sizeof
(
glyph
->
faces
.
items
[
0
]));
if
(
!
glyph
->
faces
.
items
)
return
E_OUTOFMEMORY
;
qsort
(
glyph
->
ordered_vertices
.
items
,
nb_vertices
,
sizeof
(
glyph
->
ordered_vertices
.
items
[
0
]),
compare_vertex_indices
);
for
(
sweep_idx
=
0
;
sweep_idx
<
glyph
->
ordered_vertices
.
count
;
sweep_idx
++
)
{
int
start
=
0
;
int
end
=
triangulations
->
count
;
while
(
start
<
end
)
{
D3DXVECTOR2
*
sweep_vtx
=
get_ordered_vertex
(
glyph
,
sweep_idx
);
int
current
=
(
start
+
end
)
/
2
;
struct
triangulation
*
t
=
&
triangulations
->
items
[
current
];
BOOL
on_top_outline
=
FALSE
;
D3DXVECTOR2
*
top_next
,
*
bottom_next
;
WORD
top_idx
,
bottom_idx
;
if
(
t
->
merging
&&
t
->
last_on_top
)
top_next
=
triangulation_get_next_point
(
t
+
1
,
glyph
,
TRUE
);
else
top_next
=
triangulation_get_next_point
(
t
,
glyph
,
TRUE
);
if
(
sweep_vtx
==
top_next
)
{
if
(
t
->
merging
&&
t
->
last_on_top
)
t
++
;
hr
=
triangulation_add_point
(
&
t
,
triangulations
,
sweep_idx
,
TRUE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
t
+
1
<
&
triangulations
->
items
[
triangulations
->
count
]
&&
triangulation_get_next_point
(
t
+
1
,
glyph
,
FALSE
)
==
sweep_vtx
)
{
/* point also on bottom outline of higher triangulation */
struct
triangulation
*
t2
=
t
+
1
;
hr
=
triangulation_add_point
(
&
t2
,
triangulations
,
sweep_idx
,
FALSE
);
if
(
hr
!=
S_OK
)
return
hr
;
t
->
merging
=
TRUE
;
t2
->
merging
=
TRUE
;
}
on_top_outline
=
TRUE
;
}
if
(
t
->
merging
&&
!
t
->
last_on_top
)
bottom_next
=
triangulation_get_next_point
(
t
-
1
,
glyph
,
FALSE
);
else
bottom_next
=
triangulation_get_next_point
(
t
,
glyph
,
FALSE
);
if
(
sweep_vtx
==
bottom_next
)
{
if
(
t
->
merging
&&
!
t
->
last_on_top
)
t
--
;
if
(
on_top_outline
)
{
/* outline finished */
remove_triangulation
(
triangulations
,
t
);
break
;
}
hr
=
triangulation_add_point
(
&
t
,
triangulations
,
sweep_idx
,
FALSE
);
if
(
hr
!=
S_OK
)
return
hr
;
if
(
t
>
triangulations
->
items
&&
triangulation_get_next_point
(
t
-
1
,
glyph
,
TRUE
)
==
sweep_vtx
)
{
struct
triangulation
*
t2
=
t
-
1
;
/* point also on top outline of lower triangulation */
hr
=
triangulation_add_point
(
&
t2
,
triangulations
,
sweep_idx
,
TRUE
);
if
(
hr
!=
S_OK
)
return
hr
;
t
=
t2
+
1
;
/* t may be invalidated by triangulation merging */
t
->
merging
=
TRUE
;
t2
->
merging
=
TRUE
;
}
break
;
}
if
(
on_top_outline
)
break
;
if
(
t
->
last_on_top
)
{
top_idx
=
t
->
vertex_stack
.
items
[
t
->
vertex_stack
.
count
-
1
];
bottom_idx
=
t
->
vertex_stack
.
items
[
0
];
}
else
{
top_idx
=
t
->
vertex_stack
.
items
[
0
];
bottom_idx
=
t
->
vertex_stack
.
items
[
t
->
vertex_stack
.
count
-
1
];
}
/* check if the point is inside or outside this polygon */
if
(
get_line_to_point_y_distance
(
get_ordered_vertex
(
glyph
,
top_idx
),
top_next
,
sweep_vtx
)
>
0
)
{
/* above */
start
=
current
+
1
;
}
else
if
(
get_line_to_point_y_distance
(
get_ordered_vertex
(
glyph
,
bottom_idx
),
bottom_next
,
sweep_vtx
)
<
0
)
{
/* below */
end
=
current
;
}
else
if
(
t
->
merging
)
{
/* inside, so cancel merging */
struct
triangulation
*
t2
=
t
->
last_on_top
?
t
+
1
:
t
-
1
;
t
->
merging
=
FALSE
;
t2
->
merging
=
FALSE
;
hr
=
triangulation_add_point
(
&
t
,
triangulations
,
sweep_idx
,
t
->
last_on_top
);
if
(
hr
!=
S_OK
)
return
hr
;
hr
=
triangulation_add_point
(
&
t2
,
triangulations
,
sweep_idx
,
t2
->
last_on_top
);
if
(
hr
!=
S_OK
)
return
hr
;
break
;
}
else
{
/* inside, so split polygon into two monotone parts */
struct
triangulation
*
t2
=
add_triangulation
(
triangulations
);
if
(
!
t2
)
return
E_OUTOFMEMORY
;
MoveMemory
(
t
+
1
,
t
,
(
char
*
)(
t2
+
1
)
-
(
char
*
)
t
);
if
(
t
->
last_on_top
)
{
t2
=
t
+
1
;
}
else
{
t2
=
t
;
t
++
;
}
ZeroMemory
(
&
t2
->
vertex_stack
,
sizeof
(
t2
->
vertex_stack
));
hr
=
add_vertex_index
(
&
t2
->
vertex_stack
,
t
->
vertex_stack
.
items
[
t
->
vertex_stack
.
count
-
1
]);
if
(
hr
!=
S_OK
)
return
hr
;
hr
=
add_vertex_index
(
&
t2
->
vertex_stack
,
sweep_idx
);
if
(
hr
!=
S_OK
)
return
hr
;
t2
->
last_on_top
=
!
t
->
last_on_top
;
hr
=
triangulation_add_point
(
&
t
,
triangulations
,
sweep_idx
,
t
->
last_on_top
);
if
(
hr
!=
S_OK
)
return
hr
;
break
;
}
}
if
(
start
>=
end
)
{
struct
triangulation
*
t
;
struct
triangulation
*
t2
=
add_triangulation
(
triangulations
);
if
(
!
t2
)
return
E_OUTOFMEMORY
;
t
=
&
triangulations
->
items
[
start
];
MoveMemory
(
t
+
1
,
t
,
(
char
*
)(
t2
+
1
)
-
(
char
*
)
t
);
ZeroMemory
(
t
,
sizeof
(
*
t
));
hr
=
add_vertex_index
(
&
t
->
vertex_stack
,
sweep_idx
);
if
(
hr
!=
S_OK
)
return
hr
;
}
}
return
S_OK
;
}
HRESULT
WINAPI
D3DXCreateTextW
(
LPDIRECT3DDEVICE9
device
,
...
...
@@ -1999,6 +2333,7 @@ HRESULT WINAPI D3DXCreateTextW(LPDIRECT3DDEVICE9 device,
int
bufsize
=
0
;
struct
glyphinfo
*
glyphs
=
NULL
;
GLYPHMETRICS
gm
;
struct
triangulation_array
triangulations
=
{
0
,
0
,
NULL
};
int
i
;
struct
vertex
*
vertex_ptr
;
face
*
face_ptr
;
...
...
@@ -2075,8 +2410,13 @@ HRESULT WINAPI D3DXCreateTextW(LPDIRECT3DDEVICE9 device,
max_deviation_sq
,
otm
.
otmEMSquare
,
&
cos_table
);
if
(
hr
!=
S_OK
)
goto
error
;
hr
=
triangulate
(
&
glyphs
[
i
]);
triangulations
.
glyph
=
&
glyphs
[
i
];
hr
=
triangulate
(
&
triangulations
);
if
(
hr
!=
S_OK
)
goto
error
;
if
(
triangulations
.
count
)
{
ERR
(
"%d incomplete triangulations of glyph (%u).
\n
"
,
triangulations
.
count
,
text
[
i
]);
triangulations
.
count
=
0
;
}
if
(
glyphmetrics
)
{
...
...
@@ -2302,6 +2642,12 @@ error:
}
HeapFree
(
GetProcessHeap
(),
0
,
glyphs
);
}
if
(
triangulations
.
items
)
{
int
i
;
for
(
i
=
0
;
i
<
triangulations
.
count
;
i
++
)
HeapFree
(
GetProcessHeap
(),
0
,
triangulations
.
items
[
i
].
vertex_stack
.
items
);
HeapFree
(
GetProcessHeap
(),
0
,
triangulations
.
items
);
}
HeapFree
(
GetProcessHeap
(),
0
,
raw_outline
);
if
(
oldfont
)
SelectObject
(
hdc
,
oldfont
);
if
(
font
)
DeleteObject
(
font
);
...
...
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