summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dwrote/src/geometry_sink_impl.rs
blob: 2f2f7550a2aa083a8963e8444431ea7610ed7bf4 (plain)
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
#![allow(non_snake_case, non_upper_case_globals)]

use std::mem;
use std::slice;
use std::sync::atomic::AtomicUsize;
use winapi::shared::guiddef::REFIID;
use winapi::shared::minwindef::{UINT, ULONG};
use winapi::shared::winerror::S_OK;
use winapi::um::d2d1::{ID2D1SimplifiedGeometrySink, ID2D1SimplifiedGeometrySinkVtbl};
use winapi::um::d2d1::{D2D1_BEZIER_SEGMENT, D2D1_FIGURE_BEGIN, D2D1_FIGURE_END};
use winapi::um::d2d1::{D2D1_FIGURE_END_CLOSED, D2D1_FILL_MODE, D2D1_PATH_SEGMENT, D2D1_POINT_2F};
use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl};
use winapi::um::winnt::HRESULT;

use crate::com_helpers::Com;
use crate::outline_builder::OutlineBuilder;

static GEOMETRY_SINK_VTBL: ID2D1SimplifiedGeometrySinkVtbl = ID2D1SimplifiedGeometrySinkVtbl {
    parent: implement_iunknown!(static ID2D1SimplifiedGeometrySink, GeometrySinkImpl),
    BeginFigure: GeometrySinkImpl_BeginFigure,
    EndFigure: GeometrySinkImpl_EndFigure,
    AddLines: GeometrySinkImpl_AddLines,
    AddBeziers: GeometrySinkImpl_AddBeziers,
    Close: GeometrySinkImpl_Close,
    SetFillMode: GeometrySinkImpl_SetFillMode,
    SetSegmentFlags: GeometrySinkImpl_SetSegmentFlags,
};

#[repr(C)]
pub struct GeometrySinkImpl {
    // NB: This must be the first field.
    _refcount: AtomicUsize,
    outline_builder: Box<dyn OutlineBuilder>,
}

impl Com<ID2D1SimplifiedGeometrySink> for GeometrySinkImpl {
    type Vtbl = ID2D1SimplifiedGeometrySinkVtbl;
    #[inline]
    fn vtbl() -> &'static ID2D1SimplifiedGeometrySinkVtbl {
        &GEOMETRY_SINK_VTBL
    }
}

impl Com<IUnknown> for GeometrySinkImpl {
    type Vtbl = IUnknownVtbl;
    #[inline]
    fn vtbl() -> &'static IUnknownVtbl {
        &GEOMETRY_SINK_VTBL.parent
    }
}

impl GeometrySinkImpl {
    pub fn new(outline_builder: Box<dyn OutlineBuilder>) -> GeometrySinkImpl {
        GeometrySinkImpl {
            _refcount: AtomicUsize::new(1),
            outline_builder,
        }
    }
}

unsafe extern "system" fn GeometrySinkImpl_BeginFigure(
    this: *mut ID2D1SimplifiedGeometrySink,
    start_point: D2D1_POINT_2F,
    _: D2D1_FIGURE_BEGIN,
) {
    let this = GeometrySinkImpl::from_interface(this);
    (*this)
        .outline_builder
        .move_to(start_point.x, start_point.y)
}

unsafe extern "system" fn GeometrySinkImpl_EndFigure(
    this: *mut ID2D1SimplifiedGeometrySink,
    figure_end: D2D1_FIGURE_END,
) {
    let this = GeometrySinkImpl::from_interface(this);
    if figure_end == D2D1_FIGURE_END_CLOSED {
        (*this).outline_builder.close()
    }
}

unsafe extern "system" fn GeometrySinkImpl_AddLines(
    this: *mut ID2D1SimplifiedGeometrySink,
    points: *const D2D1_POINT_2F,
    points_count: UINT,
) {
    let this = GeometrySinkImpl::from_interface(this);
    let points = slice::from_raw_parts(points, points_count as usize);
    for point in points {
        (*this).outline_builder.line_to(point.x, point.y)
    }
}

unsafe extern "system" fn GeometrySinkImpl_AddBeziers(
    this: *mut ID2D1SimplifiedGeometrySink,
    beziers: *const D2D1_BEZIER_SEGMENT,
    beziers_count: UINT,
) {
    let this = GeometrySinkImpl::from_interface(this);
    let beziers = slice::from_raw_parts(beziers, beziers_count as usize);
    for bezier in beziers {
        (*this).outline_builder.curve_to(
            bezier.point1.x,
            bezier.point1.y,
            bezier.point2.x,
            bezier.point2.y,
            bezier.point3.x,
            bezier.point3.y,
        )
    }
}

unsafe extern "system" fn GeometrySinkImpl_Close(_: *mut ID2D1SimplifiedGeometrySink) -> HRESULT {
    S_OK
}

unsafe extern "system" fn GeometrySinkImpl_SetFillMode(
    _: *mut ID2D1SimplifiedGeometrySink,
    _: D2D1_FILL_MODE,
) {
}

unsafe extern "system" fn GeometrySinkImpl_SetSegmentFlags(
    _: *mut ID2D1SimplifiedGeometrySink,
    _: D2D1_PATH_SEGMENT,
) {
}