1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use crate::effects::ClientEffect;
use crate::enums::BreakCondition;
use crate::error::DWResult;
use crate::factory::Factory;
use crate::inline_object::custom::CustomInlineObject;
use crate::metrics::overhang::OverhangMetrics;
use crate::metrics::InlineObjectMetrics;
use crate::text_format::TextFormat;
use crate::text_renderer::DrawContext;
use crate::text_renderer::TextRenderer;
use checked_enum::UncheckedEnum;
use com_wrapper::ComWrapper;
use dcommon::helpers::unwrap_opt_com;
use math2d::Point2f;
use winapi::shared::winerror::SUCCEEDED;
use winapi::um::dwrite::IDWriteInlineObject;
use wio::com::ComPtr;
pub mod custom;
#[repr(transparent)]
#[derive(Clone, ComWrapper)]
#[com(send, sync)]
pub struct InlineObject {
ptr: ComPtr<IDWriteInlineObject>,
}
impl InlineObject {
pub fn create_custom(object: impl CustomInlineObject) -> InlineObject {
let ptr = custom::com_obj::ComInlineObject::new(object);
unsafe { InlineObject::from_ptr(ptr) }
}
pub fn create_trimming_ellipsis(
factory: &Factory,
format: &TextFormat,
) -> DWResult<InlineObject> {
unsafe {
let mut ptr = std::ptr::null_mut();
let hr = (*factory.get_raw()).CreateEllipsisTrimmingSign(format.get_raw(), &mut ptr);
if SUCCEEDED(hr) {
Ok(InlineObject::from_raw(ptr))
} else {
Err(hr.into())
}
}
}
pub fn metrics(&self) -> InlineObjectMetrics {
unsafe {
let mut metrics = std::mem::zeroed();
self.ptr.GetMetrics(&mut metrics);
metrics.into()
}
}
pub fn overhang_metrics(&self) -> OverhangMetrics {
unsafe {
let mut metrics = std::mem::zeroed();
self.ptr.GetOverhangMetrics(&mut metrics);
metrics.into()
}
}
pub fn break_conditions(&self) -> BreakConditions {
unsafe {
let (mut before, mut after) = std::mem::zeroed();
self.ptr.GetBreakConditions(&mut before, &mut after);
BreakConditions {
preceding: before.into(),
following: after.into(),
}
}
}
pub fn draw(&self, context: &DrawingContext) -> DWResult<()> {
unsafe {
let hr = self.ptr.Draw(
context.client_context.ptr(),
context.renderer.get_raw(),
context.origin.x,
context.origin.y,
context.is_sideways as i32,
context.is_right_to_left as i32,
unwrap_opt_com(context.client_effect),
);
if SUCCEEDED(hr) {
Ok(())
} else {
Err(hr.into())
}
}
}
}
pub struct BreakConditions {
pub preceding: UncheckedEnum<BreakCondition>,
pub following: UncheckedEnum<BreakCondition>,
}
pub struct DrawingContext<'a> {
pub client_context: DrawContext,
pub renderer: &'a mut TextRenderer,
pub origin: Point2f,
pub is_sideways: bool,
pub is_right_to_left: bool,
pub client_effect: Option<&'a ClientEffect>,
}