diff --git a/vlib/x/ttf/common.v b/vlib/x/ttf/common.v index 3c5665c1b0..0e23fad33b 100644 --- a/vlib/x/ttf/common.v +++ b/vlib/x/ttf/common.v @@ -49,7 +49,7 @@ fn dprintln(txt string) { * Utility * ******************************************************************************/ -// transform the bitmap from one layer to color layers +// format_texture transforms the bitmap from one layer to color layers fn (mut bmp BitMap) format_texture() { r := u8(bmp.color >> 24) g := u8((bmp.color >> 16) & 0xFF) @@ -84,7 +84,7 @@ fn (mut bmp BitMap) format_texture() { } } -// write out a .ppm file +// save_as_ppm saves the `BitMap` data in .ppm file format to `file_name`. pub fn (mut bmp BitMap) save_as_ppm(file_name string) { tmp_buf := bmp.buf mut buf := unsafe { malloc_noscan(bmp.buf_size) } @@ -114,6 +114,7 @@ pub fn (mut bmp BitMap) save_as_ppm(file_name string) { bmp.buf = tmp_buf } +// get_raw_bytes returns the raw bytes of the bitmap. pub fn (mut bmp BitMap) get_raw_bytes() []u8 { mut f_buf := []u8{len: bmp.buf_size / 4} mut i := 0 @@ -126,6 +127,7 @@ pub fn (mut bmp BitMap) get_raw_bytes() []u8 { return f_buf } +// save_raw_data saves the raw data to `file_name`. pub fn (mut bmp BitMap) save_raw_data(file_name string) { os.write_file_array(file_name, bmp.get_raw_bytes()) or { panic(err) } } @@ -160,36 +162,39 @@ fn rfpart(x f32) f32 { * Colors * ******************************************************************************/ -/* -@[inline] -pub fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){ - if x < 0 || x >= dev.width || y < 0 || y >= dev.height { - return 0,0,0,0 - } - mut i := (x + y * dev.width)*dev.bp - unsafe{ - return dev.buf[i], dev.buf[i+1], dev.buf[i+2], dev.buf[i+3] - } -} -@[inline] -pub fn (mut dev BitMap) get_color_u32(x int, y int) u32{ - r, g, b, a := dev.get_color(x, y) - unsafe{ - return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a) - } -} -*/ +// @[inline] +// pub fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){ +// if x < 0 || x >= dev.width || y < 0 || y >= dev.height { +// return 0,0,0,0 +// } +// mut i := (x + y * dev.width)*dev.bp +// unsafe{ +// return dev.buf[i], dev.buf[i+1], dev.buf[i+2], dev.buf[i+3] +// } +// } + +// @[inline] +// pub fn (mut dev BitMap) get_color_u32(x int, y int) u32{ +// r, g, b, a := dev.get_color(x, y) +// unsafe{ +// return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a) +// } +// } + /****************************************************************************** * * Drawing * ******************************************************************************/ + +// color_multiply_alpha multiplies color `c`'s alpha channel with the `level` value. @[inline] pub fn color_multiply_alpha(c u32, level f32) u32 { return u32(f32(c & 0xFF) * level) } +// color_multiply multiplies R,G,B channels of color `c` with the `level` value. @[inline] pub fn color_multiply(c u32, level f32) u32 { mut r := (f32((c >> 24) & 0xFF) / 255.0) * level diff --git a/vlib/x/ttf/render_bmp.v b/vlib/x/ttf/render_bmp.v index 465fd47a30..ac089714c5 100644 --- a/vlib/x/ttf/render_bmp.v +++ b/vlib/x/ttf/render_bmp.v @@ -16,6 +16,8 @@ module ttf import encoding.utf8 import math +// BitMap represents a bitmap image of text rendered with the font supplied via +// the `tf` field. pub struct BitMap { pub mut: tf &TTF_File = unsafe { nil } @@ -50,7 +52,7 @@ pub mut: * Utility * ******************************************************************************/ -// clear clear the bitmap with 0 bytes +// clear clears the bitmap with 0 bytes. pub fn (mut bmp BitMap) clear() { mut sz := bmp.width * bmp.height * bmp.bp unsafe { @@ -58,25 +60,25 @@ pub fn (mut bmp BitMap) clear() { } } -// transform matrix applied to the text +// trf_txt returns the transform matrix applied to the text. pub fn (bmp &BitMap) trf_txt(p &Point) (int, int) { return int(p.x * bmp.tr_matrix[0] + p.y * bmp.tr_matrix[3] + bmp.tr_matrix[6]), int( p.x * bmp.tr_matrix[1] + p.y * bmp.tr_matrix[4] + bmp.tr_matrix[7]) } -// transform matrix applied to the char +// trf_ch returns the transform matrix applied to the char. pub fn (bmp &BitMap) trf_ch(p &Point) (int, int) { return int(p.x * bmp.ch_matrix[0] + p.y * bmp.ch_matrix[3] + bmp.ch_matrix[6]), int( p.x * bmp.ch_matrix[1] + p.y * bmp.ch_matrix[4] + bmp.ch_matrix[7]) } -// set draw position in the buffer +// set_pos sets the draw position in the buffer pub fn (mut bmp BitMap) set_pos(x f32, y f32) { bmp.tr_matrix[6] = x bmp.tr_matrix[7] = y } -// set the rotation angle in radiants +// set_rotation sets the rotation angle in radians `a` pub fn (mut bmp BitMap) set_rotation(a f32) { bmp.tr_matrix[0] = f32(math.cos(a)) // 1 bmp.tr_matrix[1] = f32(-math.sin(a)) // 0 @@ -89,6 +91,7 @@ pub fn (mut bmp BitMap) set_rotation(a f32) { * Filler functions * ******************************************************************************/ +// init_filler initializes the internal `filler` buffer. pub fn (mut bmp BitMap) init_filler() { h := bmp.height - bmp.filler.len if h < 1 { @@ -100,12 +103,14 @@ pub fn (mut bmp BitMap) init_filler() { // dprintln("Init filler: ${bmp.filler.len} rows") } +// clear_filler clears the internal `filler` buffer pub fn (mut bmp BitMap) clear_filler() { for i in 0 .. bmp.height { bmp.filler[i].clear() } } +// exec_filler plots the pixels of the `BitMap` to the internal buffer. pub fn (mut bmp BitMap) exec_filler() { for y in 0 .. bmp.height { if bmp.filler[y].len > 0 { @@ -131,6 +136,7 @@ pub fn (mut bmp BitMap) exec_filler() { } } +// fline populates the internal `filler` buffer with a line segment from `in_x0`,`in_y0` to `in_x1`,`in_y1`. pub fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) { mut x0 := f32(in_x0) mut x1 := f32(in_x1) @@ -187,6 +193,8 @@ pub fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) * Draw functions * ******************************************************************************/ + +// plot plots a pixel at `x`,`y` in color `c` in the internal bitmap buffer. @[inline] pub fn (mut bmp BitMap) plot(x int, y int, c u32) bool { if x < 0 || x >= bmp.width || y < 0 || y >= bmp.height { @@ -212,7 +220,7 @@ pub fn (mut bmp BitMap) plot(x int, y int, c u32) bool { * smooth draw functions * ******************************************************************************/ -// aline draw an aliased line on the bitmap +// aline draws an aliased line on the bitmap pub fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) { // mut c1 := c mut x0 := f32(in_x0) @@ -307,6 +315,7 @@ pub fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) * draw functions * ******************************************************************************/ +// line plots a line segment to the internal buffer from `in_x0`,`in_y0` to `in_x1`,`in_y1` in the color `c`. pub fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) { // outline with aliased borders if bmp.style == .outline_aliased { @@ -387,6 +396,7 @@ pub fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) } } +// box plots a (hollow) box to the internal buffer from top-left `in_x0`, `in_y0` to bottom right `in_x1`, `in_y1` in color `c`. pub fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) { bmp.line(in_x0, in_y0, in_x1, in_y0, c) bmp.line(in_x1, in_y0, in_x1, in_y1, c) @@ -394,6 +404,7 @@ pub fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) { bmp.line(in_x0, in_y0, in_x0, in_y1, c) } +// quadratic plots a quadratic Bezier curve in color `c`. pub fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx int, in_cy int, c u32) { /* x0 := int(in_x0 * bmp.scale) @@ -460,6 +471,7 @@ pub fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in * TTF Query functions * ******************************************************************************/ +// get_chars_bbox returns all characters found in bounding box of string `in_string`. pub fn (mut bmp BitMap) get_chars_bbox(in_string string) []int { mut res := []int{} mut w := 0 @@ -532,6 +544,7 @@ pub fn (mut bmp BitMap) get_chars_bbox(in_string string) []int { return res } +// get_bbox returns the bounding box (width and height) of text `in_string`. pub fn (mut bmp BitMap) get_bbox(in_string string) (int, int) { mut w := 0 @@ -627,6 +640,8 @@ fn (mut bmp BitMap) draw_notdef_glyph(in_x int, in_w int) { bmp.line(int(x - in_w), int(y), int(x), int(y - y_h), bmp.color) } +// draw_text plots the pixels of the text `in_string` to the internal buffer and +// returns the text bounding box. pub fn (mut bmp BitMap) draw_text(in_string string) (int, int) { mut w := 0 @@ -702,6 +717,8 @@ pub fn (mut bmp BitMap) draw_text(in_string string) (int, int) { return w, int(math.abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale) } +// draw_glyph plots the pixels of the glyph at `index` to the internal buffer and +// returns the `x_max` and `x_min` values. pub fn (mut bmp BitMap) draw_glyph(index u16) (int, int) { glyph := bmp.tf.read_glyph(index) diff --git a/vlib/x/ttf/render_sokol_cpu.v b/vlib/x/ttf/render_sokol_cpu.v index 250addbe7d..e14bbce4a3 100644 --- a/vlib/x/ttf/render_sokol_cpu.v +++ b/vlib/x/ttf/render_sokol_cpu.v @@ -17,6 +17,8 @@ import gg import sokol.sgl import sokol.gfx +// TTF_render_Sokol is a structure containing data for rendering a TTF font +// as a sokol texture pub struct TTF_render_Sokol { pub mut: bmp &BitMap = unsafe { nil } // Base bitmap render @@ -32,10 +34,12 @@ pub mut: * Render functions * ******************************************************************************/ +// format_texture formats the BMP (bitmap). pub fn (mut tf_skl TTF_render_Sokol) format_texture() { tf_skl.bmp.format_texture() } +// create_text prepares the text `in_txt` in size `in_font_size` as a sokol texture. pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32) { scale_reduct := tf_skl.scale_reduct device_dpi := tf_skl.device_dpi @@ -72,6 +76,7 @@ pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32 tf_skl.format_texture() } +// create_text_block prepares a block of text as a sokol texture. pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32) { scale_reduct := tf_skl.scale_reduct device_dpi := tf_skl.device_dpi @@ -116,6 +121,7 @@ pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, * Sokol Render functions * ******************************************************************************/ +// create_texture creates the sokol texture from the internal buffer state. pub fn (mut tf_skl TTF_render_Sokol) create_texture() { w := tf_skl.bmp.width h := tf_skl.bmp.height @@ -150,12 +156,14 @@ pub fn (mut tf_skl TTF_render_Sokol) create_texture() { tf_skl.sg_smp = ssmp } +// destroy_texture detroys the internal sokol texture. pub fn (tf_skl TTF_render_Sokol) destroy_texture() { gfx.destroy_image(tf_skl.sg_img) gfx.destroy_sampler(tf_skl.sg_smp) } -// Use only if usage: .dynamic +// update_text_texture updates the sokol texture with current internal state. +// NOTE: Only use if `.dynamic` is set. pub fn (mut tf_skl TTF_render_Sokol) update_text_texture() { sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp mut tmp_sbc := gfx.ImageData{} @@ -166,6 +174,7 @@ pub fn (mut tf_skl TTF_render_Sokol) update_text_texture() { gfx.update_image(tf_skl.sg_img, &tmp_sbc) } +// draw_text_bmp renders the internal state to the current sokol pipeline. pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) { // width := tf_skl.bmp.width >> 1 // height := tf_skl.bmp.height >> 1 diff --git a/vlib/x/ttf/text_block.v b/vlib/x/ttf/text_block.v index c20af1ec96..537a28f917 100644 --- a/vlib/x/ttf/text_block.v +++ b/vlib/x/ttf/text_block.v @@ -12,6 +12,7 @@ module ttf * * TODO: **********************************************************************/ +// Text_block represents a visual block of TTF text. pub struct Text_block { x int // x position of the left high corner y int // y position of the left high corner @@ -20,6 +21,7 @@ pub struct Text_block { cut_lines bool = true // force to cut the line if the length is over the text block width } +// get_justify_space_cw returns the space needed to justify `txt`. pub fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 { num_spaces := txt.count(' ') if num_spaces < 1 { @@ -33,7 +35,7 @@ pub fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, spa return res } -// write out a text +// draw_text_block renders out `text` in the `Text_block` `block`. pub fn (mut bmp BitMap) draw_text_block(text string, block Text_block) { mut x := block.x mut y := block.y diff --git a/vlib/x/ttf/ttf.v b/vlib/x/ttf/ttf.v index e84dd5b086..31ec1410ba 100644 --- a/vlib/x/ttf/ttf.v +++ b/vlib/x/ttf/ttf.v @@ -43,6 +43,11 @@ mut: * TTF_File structs * ******************************************************************************/ +// TTF_File represents the data contents of a complete `*.ttf` file. +// The struct is usually initialized by reading raw TTF data into the `buf` member field +// for example by doing: `ttf_font.buf = os.read_bytes("arial.ttf") or { panic(err) }`, +// and then run the `init/0` method, for example: `ttf_font.init()` + pub struct TTF_File { pub mut: buf []u8 @@ -96,6 +101,7 @@ pub mut: width_scale f32 = 1.0 } +// init initializes essential `TTF_File` fields from the contents of `buf`. pub fn (mut tf TTF_File) init() { tf.read_offset_tables() tf.read_head_table() @@ -117,6 +123,7 @@ pub fn (mut tf TTF_File) init() { * TTF_File Glyph Structs * ******************************************************************************/ +// Point represents a 2D point pub struct Point { pub mut: x int @@ -134,6 +141,7 @@ const g_type_simple = u16(1) // simple type const g_type_complex = u16(2) +// Glyph represents a single renderable unit ("a character") of the TTF. pub struct Glyph { pub mut: g_type u16 = g_type_simple @@ -153,6 +161,8 @@ pub mut: * TTF_File metrics and glyph * ******************************************************************************/ +// get_horizontal_metrics returns the horizontal metrics `advance_width` and `left_side_bearing` +// for the glyph at index `glyph_index`. pub fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) { assert 'hmtx' in tf.tables old_pos := tf.pos @@ -206,6 +216,7 @@ fn (mut tf TTF_File) get_glyph_offset(index u32) u32 { return offset + tf.tables['glyf'].offset } +// glyph_count returns the number of glyphs available in the TTF. pub fn (mut tf TTF_File) glyph_count() u16 { assert 'maxp' in tf.tables old_pos := tf.pos @@ -215,6 +226,7 @@ pub fn (mut tf TTF_File) glyph_count() u16 { return count } +// read_glyph_dim returns glyph dimension data in the form `x_min`, `x_max`, `y_min` and `y_max`. pub fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) { offset := tf.get_glyph_offset(index) // dprintln("offset: $offset") @@ -239,6 +251,7 @@ pub fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) { return x_min, x_max, y_min, y_max } +// get_ttf_widths returns all possible widths of the TTF. pub fn (mut tf TTF_File) get_ttf_widths() ([]int, int, int) { mut space_cw, _ := tf.get_horizontal_metrics(u16(` `)) // div_space_cw := int((f32(space_cw) * 0.3)) @@ -291,6 +304,7 @@ pub fn (mut tf TTF_File) get_ttf_widths() ([]int, int, int) { return widths, min_code, max_code } +// read_glyph returns `Glyph` data for the glyph at `index`. pub fn (mut tf TTF_File) read_glyph(index u16) Glyph { index_int := int(index) // index.str() if index_int in tf.glyph_cache { @@ -834,6 +848,8 @@ fn (mut tf TTF_File) read_cmap(offset u32) { * CMAPS 0/4 * ******************************************************************************/ +// map_code returns the glyph index for the `char_code` character code. +// map_code returns `0` if the character code could not be found. pub fn (mut tf TTF_File) map_code(char_code int) u16 { mut index := 0 for i in 0 .. tf.cmaps.len { @@ -1069,12 +1085,14 @@ fn (mut tf TTF_File) read_kern_table() { } } +// reset_kern resets the internal kerning table data. pub fn (mut tf TTF_File) reset_kern() { for i in 0 .. tf.kern.len { tf.kern[i].reset() } } +// next_kern returns the next `x`, `y` kerning for the glyph at index `glyph_index`. pub fn (mut tf TTF_File) next_kern(glyph_index int) (int, int) { mut x := 0 mut y := 0 @@ -1128,6 +1146,7 @@ fn (mut tf TTF_File) read_panose_table() { * TTF_File Utility * ******************************************************************************/ +// get_info_string returns a string with various information about the TTF. pub fn (tf TTF_File) get_info_string() string { txt := '----- Font Info ----- font_family : ${tf.font_family}