| 1 | module ttf |
| 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 | **********************************************************************/ |
| 15 | // Text_block represents a visual block of TTF text. |
| 16 | pub struct Text_block { |
| 17 | pub: |
| 18 | x int // x position of the left high corner |
| 19 | y int // y position of the left high corner |
| 20 | w int // width of the text block |
| 21 | h int // height of the text block |
| 22 | cut_lines bool = true // force to cut the line if the length is over the text block width |
| 23 | } |
| 24 | |
| 25 | // get_justify_space_cw returns the space needed to justify `txt`. |
| 26 | pub fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 { |
| 27 | num_spaces := txt.count(' ') |
| 28 | if num_spaces < 1 { |
| 29 | return 0 |
| 30 | } |
| 31 | delta := block_w - w |
| 32 | // println("num spc: ${num_spaces}") |
| 33 | // println("delta: ${txt} w:${w} bw:${block_w} space_cw:${space_cw}") |
| 34 | res := f32(delta) / f32(num_spaces) / f32(space_cw) |
| 35 | // println("res: ${res}") |
| 36 | return res |
| 37 | } |
| 38 | |
| 39 | // draw_text_block renders out `text` in the `Text_block` `block`. |
| 40 | pub fn (mut bmp BitMap) draw_text_block(text string, block Text_block) { |
| 41 | mut x := block.x |
| 42 | mut y := block.y |
| 43 | mut y_base := int((bmp.tf.y_max - bmp.tf.y_min) * bmp.scale) |
| 44 | |
| 45 | // bmp.box(x, y, x + block.w, y + block.h, u32(0xFF00_0000)) |
| 46 | |
| 47 | // spaces data |
| 48 | mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `)) |
| 49 | space_cw = int(space_cw * bmp.scale) |
| 50 | |
| 51 | old_space_cw := bmp.space_cw |
| 52 | |
| 53 | mut offset_flag := f32(0) // default .left align |
| 54 | if bmp.align == .right { |
| 55 | offset_flag = 1 |
| 56 | } else if bmp.align == .center { |
| 57 | offset_flag = 0.5 |
| 58 | } |
| 59 | |
| 60 | for txt in text.split_into_lines() { |
| 61 | bmp.space_cw = old_space_cw |
| 62 | mut w, _ := bmp.get_bbox(txt) |
| 63 | if w <= block.w || block.cut_lines == false { |
| 64 | // println("Solid block!") |
| 65 | left_offset := int((block.w - w) * offset_flag) |
| 66 | if bmp.justify && (f32(w) / f32(block.w)) >= bmp.justify_fill_ratio { |
| 67 | bmp.space_cw = old_space_cw + bmp.get_justify_space_cw(txt, w, block.w, space_cw) |
| 68 | } |
| 69 | bmp.set_pos(x + left_offset, y + y_base) |
| 70 | bmp.draw_text(txt) |
| 71 | //---- DEBUG ---- |
| 72 | // mut txt_w , mut txt_h := bmp.draw_text(txt) |
| 73 | // bmp.box(x + left_offset,y+y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) ) |
| 74 | //--------------- |
| 75 | y += y_base |
| 76 | } else { |
| 77 | // println("to cut: ${txt}") |
| 78 | mut txt1 := txt.split(' ') |
| 79 | mut c := txt1.len |
| 80 | // mut done := false |
| 81 | for c > 0 { |
| 82 | tmp_str := txt1[0..c].join(' ') |
| 83 | // println("tmp_str: ${tmp_str}") |
| 84 | if tmp_str == '' { |
| 85 | break |
| 86 | } |
| 87 | |
| 88 | bmp.space_cw = old_space_cw |
| 89 | w, _ = bmp.get_bbox(tmp_str) |
| 90 | if w <= block.w { |
| 91 | mut left_offset := int((block.w - w) * offset_flag) |
| 92 | if bmp.justify && (f32(w) / f32(block.w)) >= bmp.justify_fill_ratio { |
| 93 | // println("cut phase!") |
| 94 | bmp.space_cw = 0.0 |
| 95 | w, _ = bmp.get_bbox(tmp_str) |
| 96 | left_offset = int((block.w - w) * offset_flag) |
| 97 | bmp.space_cw = bmp.get_justify_space_cw(tmp_str, w, block.w, space_cw) |
| 98 | } else { |
| 99 | bmp.space_cw = old_space_cw |
| 100 | } |
| 101 | bmp.set_pos(x + left_offset, y + y_base) |
| 102 | bmp.draw_text(tmp_str) |
| 103 | //---- DEBUG ---- |
| 104 | // txt_w , txt_h := bmp.draw_text(tmp_str) |
| 105 | // println("printing [${x},${y}] => '${tmp_str}' space_cw: ${bmp.space_cw}") |
| 106 | // bmp.box(x + left_offset,y + y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) ) |
| 107 | //--------------- |
| 108 | y += y_base |
| 109 | txt1 = unsafe { txt1[c..] } |
| 110 | c = txt1.len |
| 111 | //---- DEBUG ---- |
| 112 | // txt2 := txt1.join(' ') |
| 113 | // println("new string: ${txt2} len: ${c}") |
| 114 | //--------------- |
| 115 | } else { |
| 116 | c-- |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | bmp.space_cw = old_space_cw |
| 123 | } |
| 124 | |