1 | import sokol |
2 | import sokol.sapp |
3 | import sokol.gfx |
4 | import sokol.sgl |
5 | import fontstash |
6 | import sokol.sfons |
7 | import os |
8 | |
9 | struct AppState { |
10 | mut: |
11 | pass_action gfx.PassAction |
12 | font_context &fontstash.Context |
13 | font_normal int |
14 | } |
15 | |
16 | fn main() { |
17 | mut color_action := gfx.ColorAttachmentAction{ |
18 | action: .clear |
19 | value: gfx.Color{ |
20 | r: 0.3 |
21 | g: 0.3 |
22 | b: 0.32 |
23 | a: 1.0 |
24 | } |
25 | } |
26 | mut pass_action := gfx.PassAction{} |
27 | pass_action.colors[0] = color_action |
28 | state := &AppState{ |
29 | pass_action: pass_action |
30 | font_context: unsafe { nil } // &fontstash.Context(0) |
31 | } |
32 | title := 'V Metal/GL Text Rendering' |
33 | desc := sapp.Desc{ |
34 | user_data: state |
35 | init_userdata_cb: init |
36 | frame_userdata_cb: frame |
37 | window_title: title.str |
38 | html5_canvas_name: title.str |
39 | } |
40 | sapp.run(&desc) |
41 | } |
42 | |
43 | fn init(mut state AppState) { |
44 | desc := sapp.create_desc() |
45 | gfx.setup(&desc) |
46 | s := &sgl.Desc{} |
47 | sgl.setup(s) |
48 | state.font_context = sfons.create(512, 512, 1) |
49 | // or use DroidSerif-Regular.ttf |
50 | if bytes := os.read_bytes(os.resource_abs_path(os.join_path('..', 'assets', 'fonts', |
51 | 'RobotoMono-Regular.ttf'))) |
52 | { |
53 | println('loaded font: ${bytes.len}') |
54 | state.font_normal = state.font_context.add_font_mem('sans', bytes, false) |
55 | } |
56 | } |
57 | |
58 | fn frame(mut state AppState) { |
59 | state.render_font() |
60 | gfx.begin_default_pass(&state.pass_action, sapp.width(), sapp.height()) |
61 | sgl.draw() |
62 | gfx.end_pass() |
63 | gfx.commit() |
64 | } |
65 | |
66 | fn (state &AppState) render_font() { |
67 | mut sx := f32(0.0) |
68 | mut sy := f32(0.0) |
69 | mut dx := f32(0.0) |
70 | mut dy := f32(0.0) |
71 | lh := f32(0.0) |
72 | white := sfons.rgba(255, 255, 255, 255) |
73 | black := sfons.rgba(0, 0, 0, 255) |
74 | brown := sfons.rgba(192, 128, 0, 128) |
75 | blue := sfons.rgba(0, 192, 255, 255) |
76 | |
77 | font_context := state.font_context |
78 | font_context.clear_state() |
79 | sgl.defaults() |
80 | sgl.matrix_mode_projection() |
81 | sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0) |
82 | sx = 0 |
83 | sy = 50 |
84 | dx = sx |
85 | dy = sy |
86 | font_context.set_font(state.font_normal) |
87 | font_context.set_size(100.0) |
88 | ascender := f32(0.0) |
89 | descender := f32(0.0) |
90 | font_context.vert_metrics(&ascender, &descender, &lh) |
91 | dx = sx |
92 | dy += lh |
93 | font_context.set_color(white) |
94 | dx = font_context.draw_text(dx, dy, 'The quick ') |
95 | font_context.set_font(state.font_normal) |
96 | font_context.set_size(48.0) |
97 | font_context.set_color(brown) |
98 | dx = font_context.draw_text(dx, dy, 'brown ') |
99 | font_context.set_font(state.font_normal) |
100 | font_context.set_size(24.0) |
101 | font_context.set_color(white) |
102 | dx = font_context.draw_text(dx, dy, 'fox ') |
103 | dx = sx |
104 | dy += lh * 1.2 |
105 | font_context.set_size(20.0) |
106 | font_context.set_font(state.font_normal) |
107 | font_context.set_color(blue) |
108 | font_context.draw_text(dx, dy, 'Now is the time for all good men to come to the aid of the party.') |
109 | dx = 300 |
110 | dy = 350 |
111 | font_context.set_alignment(.left | .baseline) |
112 | font_context.set_size(60.0) |
113 | font_context.set_font(state.font_normal) |
114 | font_context.set_color(white) |
115 | font_context.set_spacing(5.0) |
116 | font_context.set_blur(6.0) |
117 | font_context.draw_text(dx, dy, 'Blurry...') |
118 | dx = 300 |
119 | dy += 50.0 |
120 | font_context.set_size(28.0) |
121 | font_context.set_font(state.font_normal) |
122 | font_context.set_color(white) |
123 | font_context.set_spacing(0.0) |
124 | font_context.set_blur(3.0) |
125 | font_context.draw_text(dx, dy + 2, 'DROP SHADOW') |
126 | font_context.set_color(black) |
127 | font_context.set_blur(0) |
128 | font_context.draw_text(dx, dy, 'DROP SHADOW') |
129 | font_context.set_size(18.0) |
130 | font_context.set_font(state.font_normal) |
131 | font_context.set_color(white) |
132 | dx = 50 |
133 | dy = 350 |
134 | line(f32(dx - 10), f32(dy), f32(dx + 250), f32(dy)) |
135 | font_context.set_alignment(.left | .top) |
136 | dx = font_context.draw_text(dx, dy, 'Top') |
137 | dx += 10 |
138 | font_context.set_alignment(.left | .middle) |
139 | dx = font_context.draw_text(dx, dy, 'Middle') |
140 | dx += 10 |
141 | font_context.set_alignment(.left | .baseline) |
142 | dx = font_context.draw_text(dx, dy, 'Baseline') |
143 | dx += 10 |
144 | font_context.set_alignment(.left | .bottom) |
145 | font_context.draw_text(dx, dy, 'Bottom') |
146 | dx = 150 |
147 | dy = 400 |
148 | line(f32(dx), f32(dy - 30), f32(dx), f32(dy + 80.0)) |
149 | font_context.set_alignment(.left | .baseline) |
150 | font_context.draw_text(dx, dy, 'Left') |
151 | dy += 30 |
152 | font_context.set_alignment(.center | .baseline) |
153 | font_context.draw_text(dx, dy, 'Center') |
154 | dy += 30 |
155 | font_context.set_alignment(.right | .baseline) |
156 | font_context.draw_text(dx, dy, 'Right') |
157 | sfons.flush(font_context) |
158 | } |
159 | |
160 | fn line(sx f32, sy f32, ex f32, ey f32) { |
161 | sgl.begin_lines() |
162 | sgl.c4b(255, 255, 0, 128) |
163 | sgl.v2f(sx, sy) |
164 | sgl.v2f(ex, ey) |
165 | sgl.end() |
166 | } |