v2 / vlib / x / ttf / render_sokol / cpu.v
229 lines · 201 sloc · 6.16 KB · 2332ecff4811b8c97dfda8e825170e9397962519
Raw
1module render_sokol
2
3/**********************************************************************
4*
5* BMP render module utility functions
6*
7* Copyright (c) 2021 Dario Deledda. All rights reserved.
8* Use of this source code is governed by an MIT license
9* that can be found in the LICENSE file.
10*
11* Note:
12*
13* TODO:
14**********************************************************************/
15import math
16import gg
17import sokol.sgl
18import sokol.gfx
19import x.ttf
20
21// TTF_render_Sokol is a structure containing data for rendering a TTF font as a sokol texture.
22pub struct TTF_render_Sokol {
23pub mut:
24 bmp &ttf.BitMap = unsafe { nil } // Base bitmap render
25 // rendering fields
26 sg_img gfx.Image // sokol image
27 sg_smp gfx.Sampler // sokol sampler
28 scale_reduct f32 = 2.0 // scale of the cpu texture for filtering
29 device_dpi int = 72 // device DPI
30}
31
32/******************************************************************************
33*
34* Render functions
35*
36******************************************************************************/
37// format_texture formats the BMP (bitmap).
38pub fn (mut tf_skl TTF_render_Sokol) format_texture() {
39 tf_skl.bmp.format_texture()
40}
41
42// create_text prepares the text `in_txt` in size `in_font_size` as a sokol texture.
43pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32) {
44 scale_reduct := tf_skl.scale_reduct
45 device_dpi := tf_skl.device_dpi
46 font_size := in_font_size //* scale_reduct
47
48 // Formula: (font_size * device dpi) / (72dpi * em_unit)
49 // scale := ((1.0 * device_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
50 scale := f32(font_size * device_dpi) / f32(72 * int(tf_skl.bmp.tf.units_per_em))
51 // ttf.dprintln("Scale: ${scale}")
52
53 tf_skl.bmp.scale = scale * scale_reduct
54 w, h := tf_skl.bmp.get_bbox(in_txt)
55 tf_skl.bmp.width = int(w)
56 tf_skl.bmp.height = int(h + 8)
57 sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
58
59 // RAM buffer
60 if sz > tf_skl.bmp.buf_size {
61 if sz > 0 {
62 unsafe { free(tf_skl.bmp.buf) }
63 }
64 ttf.dprintln('create_text Alloc: ${sz} bytes')
65 tf_skl.bmp.buf = unsafe { malloc_noscan(sz) }
66 tf_skl.bmp.buf_size = sz
67 }
68
69 tf_skl.bmp.init_filler()
70
71 // draw the text
72 mut y_base := int((tf_skl.bmp.tf.y_max - tf_skl.bmp.tf.y_min) * tf_skl.bmp.scale)
73 tf_skl.bmp.set_pos(0, y_base)
74 tf_skl.bmp.clear()
75 tf_skl.bmp.draw_text(in_txt)
76 tf_skl.format_texture()
77}
78
79// create_text_block prepares a block of text as a sokol texture.
80pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32) {
81 scale_reduct := tf_skl.scale_reduct
82 device_dpi := tf_skl.device_dpi
83 font_size := in_font_size //* scale_reduct
84 // Formula: (font_size * device dpi) / (72dpi * em_unit)
85 // scale := ((1.0 * device_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
86 scale := f32(font_size * device_dpi) / f32(72 * int(tf_skl.bmp.tf.units_per_em))
87 // ttf.dprintln("Scale: ${scale}")
88
89 tf_skl.bmp.scale = scale * scale_reduct
90 w := in_w
91 h := in_h
92 tf_skl.bmp.width = int(w * scale_reduct + 0.5)
93 tf_skl.bmp.height = int((h + 2) * scale_reduct + 0.5)
94 sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
95
96 // if true { return }
97
98 // RAM buffer
99 if sz > tf_skl.bmp.buf_size {
100 if sz > 0 {
101 unsafe { free(tf_skl.bmp.buf) }
102 }
103 ttf.dprintln('Alloc: ${sz} bytes')
104 tf_skl.bmp.buf = unsafe { malloc_noscan(sz) }
105 tf_skl.bmp.buf_size = sz
106 }
107
108 tf_skl.bmp.init_filler()
109
110 // draw the text
111 mut y_base := int((tf_skl.bmp.tf.y_max - tf_skl.bmp.tf.y_min) * tf_skl.bmp.scale)
112 tf_skl.bmp.set_pos(0, y_base)
113 tf_skl.bmp.clear()
114
115 tf_skl.bmp.draw_text_block(in_txt, x: 0, y: 0, w: w, h: h)
116 tf_skl.format_texture()
117}
118
119/******************************************************************************
120*
121* Sokol Render functions
122*
123******************************************************************************/
124// create_texture creates the sokol texture from the internal buffer state.
125pub fn (mut tf_skl TTF_render_Sokol) create_texture() {
126 w := tf_skl.bmp.width
127 h := tf_skl.bmp.height
128 sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
129 mut img_desc := gfx.ImageDesc{
130 width: w
131 height: h
132 num_mipmaps: 0
133 // usage: .dynamic
134 label: &char(unsafe { nil })
135 d3d11_texture: 0
136 }
137 // comment for dynamic
138 img_desc.data.subimage[0][0] = gfx.Range{
139 ptr: tf_skl.bmp.buf
140 size: usize(sz)
141 }
142
143 simg := gfx.make_image(&img_desc)
144 // free(tf_skl.bmp.buf) // DONT FREE IF Dynamic
145
146 mut smp_desc := gfx.SamplerDesc{
147 min_filter: .linear
148 mag_filter: .linear
149 wrap_u: .clamp_to_edge
150 wrap_v: .clamp_to_edge
151 }
152
153 ssmp := gfx.make_sampler(&smp_desc)
154
155 tf_skl.sg_img = simg
156 tf_skl.sg_smp = ssmp
157}
158
159// destroy_texture detroys the internal sokol texture.
160pub fn (tf_skl TTF_render_Sokol) destroy_texture() {
161 gfx.destroy_image(tf_skl.sg_img)
162 gfx.destroy_sampler(tf_skl.sg_smp)
163}
164
165// update_text_texture updates the sokol texture with current internal state.
166// NOTE: Only use if `.dynamic` is set.
167pub fn (mut tf_skl TTF_render_Sokol) update_text_texture() {
168 sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
169 mut tmp_sbc := gfx.ImageData{}
170 tmp_sbc.subimage[0][0] = gfx.Range{
171 ptr: tf_skl.bmp.buf
172 size: usize(sz)
173 }
174 gfx.update_image(tf_skl.sg_img, &tmp_sbc)
175}
176
177// draw_text_bmp renders the internal state to the current sokol pipeline.
178pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
179 // width := tf_skl.bmp.width >> 1
180 // height := tf_skl.bmp.height >> 1
181 sgl.push_matrix()
182
183 width := tf_skl.bmp.width / (tf_skl.scale_reduct)
184 height := tf_skl.bmp.height / (tf_skl.scale_reduct)
185
186 u0 := f32(0.0)
187 v0 := f32(0.0)
188 u1 := f32(1.0)
189 v1 := f32(1.0)
190 x0 := f32(0)
191 y0 := f32(0)
192 x1 := f32(width) * ctx.scale
193 y1 := f32(height) * ctx.scale
194
195 ca := f32(math.cos(tf_skl.bmp.angle))
196 sa := f32(math.sin(tf_skl.bmp.angle))
197 m := [
198 f32(ca),
199 -sa,
200 0,
201 0,
202 sa,
203 ca,
204 0,
205 0,
206 0,
207 0,
208 1,
209 0,
210 x * ctx.scale,
211 y * ctx.scale,
212 0,
213 1,
214 ]
215 sgl.mult_matrix(m)
216
217 sgl.load_pipeline(ctx.pipeline.alpha)
218 sgl.enable_texture()
219 sgl.texture(tf_skl.sg_img, tf_skl.sg_smp)
220 sgl.begin_quads()
221 sgl.c4b(255, 255, 255, 255)
222 sgl.v2f_t2f(x0, y0, u0, v0)
223 sgl.v2f_t2f(x1, y0, u1, v0)
224 sgl.v2f_t2f(x1, y1, u1, v1)
225 sgl.v2f_t2f(x0, y1, u0, v1)
226 sgl.end()
227 sgl.disable_texture()
228 sgl.pop_matrix()
229}
230