perftest/
perftest.rs

1// Copyright 2018 The xi-editor Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15extern crate druid_win_shell;
16extern crate direct2d;
17extern crate directwrite;
18extern crate time;
19
20use std::any::Any;
21use std::cell::RefCell;
22
23use time::get_time;
24
25use direct2d::math::*;
26use direct2d::RenderTarget;
27use direct2d::brush::SolidColorBrush;
28use directwrite::TextFormat;
29
30use druid_win_shell::paint::PaintCtx;
31use druid_win_shell::util::default_text_options;
32use druid_win_shell::win_main;
33use druid_win_shell::window::{PresentStrategy, WindowBuilder, WindowHandle, WinHandler};
34
35struct PerfTest(RefCell<PerfState>);
36
37struct PerfState {
38    handle: WindowHandle,
39    last_time: f64,
40    dwrite_factory: directwrite::Factory,
41}
42
43impl WinHandler for PerfTest {
44    fn connect(&self, handle: &WindowHandle) {
45        self.0.borrow_mut().handle = handle.clone();
46    }
47
48    fn paint(&self, paint_ctx: &mut PaintCtx) -> bool {
49        let mut state = self.0.borrow_mut();
50        let rt = paint_ctx.render_target();
51        let size = rt.get_size();
52        let rect = RectF::from((0.0, 0.0, size.width, size.height));
53        let bg = SolidColorBrush::create(rt).with_color(0x272822).build().unwrap();
54        let fg = SolidColorBrush::create(rt).with_color(0xf0f0ea).build().unwrap();
55        rt.fill_rectangle(rect, &bg);
56
57        rt.draw_line((0.0, size.height), (size.width, 0.0), &fg, 1.0, None);
58
59        let th = ::std::f32::consts::PI * (get_time().nsec as f32) * 2e-9;
60        let dx = 100.0 * th.sin();
61        let dy = 100.0 * th.cos();
62        rt.draw_line((100.0, 100.0), (100.0 + dx, 100.0 - dy),
63            &fg, 1.0, None);
64
65        let text_format = TextFormat::create(&state.dwrite_factory)
66            .with_family("Consolas")
67            .with_size(15.0)
68            .build()
69            .unwrap();
70
71        let now = get_time();
72        let now = now.sec as f64 + 1e-9 * now.nsec as f64;
73        let msg = format!("{:3.1}ms", 1e3 * (now - state.last_time));
74        state.last_time = now;
75        rt.draw_text(
76            &msg,
77            &text_format,
78            (10.0, 210.0, 100.0, 300.0),
79            &fg,
80            default_text_options()
81        );
82
83        let msg = "Hello DWrite! This is a somewhat longer string of text intended to provoke slightly longer draw times.";
84        let dy = 15.0;
85        let x0 = 210.0;
86        let y0 = 10.0;
87        for i in 0..60 {
88            let y = y0 + (i as f32) * dy;
89            rt.draw_text(
90                msg,
91                &text_format,
92                (x0, y, x0 + 900.0, y + 80.0),
93                &fg,
94                default_text_options()
95            );
96        }
97
98    true
99    }
100
101    fn command(&self, id: u32) {
102        match id {
103            0x100 => self.0.borrow().handle.close(),
104            _ => println!("unexpected id {}", id),
105        }
106    }
107
108    fn char(&self, ch: u32, mods: u32) {
109        println!("got char 0x{:x} {:02x}", ch, mods);
110    }
111
112    fn keydown(&self, vk_code: i32, mods: u32) -> bool {
113        println!("got key code 0x{:x} {:02x}", vk_code, mods);
114        false
115    }
116
117    fn destroy(&self) {
118        win_main::request_quit();
119    }
120
121    fn as_any(&self) -> &Any { self }
122}
123
124fn main() {
125    druid_win_shell::init();
126
127    let mut run_loop = win_main::RunLoop::new();
128    let mut builder = WindowBuilder::new();
129    let perf_state = PerfState {
130        dwrite_factory: directwrite::Factory::new().unwrap(),
131        handle: Default::default(),
132        last_time: 0.0,
133    };
134    builder.set_handler(Box::new(PerfTest(RefCell::new(perf_state))));
135    builder.set_title("Performance tester");
136    // Note: experiment with changing this
137    builder.set_present_strategy(PresentStrategy::FlipRedirect);
138    let window = builder.build().unwrap();
139    window.show();
140    run_loop.run();
141}