x.ttf: add README, some improvements (#8157)
parent
5ae55731b9
commit
ee9f9c9d81
|
@ -0,0 +1,310 @@
|
||||||
|
# TTF font utility
|
||||||
|
## introduction
|
||||||
|
This module is designed to perform two main task
|
||||||
|
- Load the font file
|
||||||
|
- Render text using a TTF font
|
||||||
|
|
||||||
|
The render system can be single or multiple, for example it is possible to have a bitmap
|
||||||
|
render and a HW accelerated render.
|
||||||
|
|
||||||
|
## TTF loader
|
||||||
|
This part of the module do a simple task, load a TTF file and preprocess all the loaded data
|
||||||
|
in order to simplify the rendering phase.
|
||||||
|
|
||||||
|
Let's start with a simple snippet of code that load a font from the disk:
|
||||||
|
```v ignore
|
||||||
|
mut ttf_font := ttf.TTF_File{}
|
||||||
|
ttf_font.buf = os.read_bytes("arial.ttf") or { panic(err) }
|
||||||
|
ttf_font.init()
|
||||||
|
```
|
||||||
|
*Note: the font must be passed to the `TTF_file` as RAM buffer.*
|
||||||
|
At this point the font "arial" is loaded and parsed and if it is a valid TTF font it is
|
||||||
|
ready for the rendering.
|
||||||
|
We can get some quick info on the font as string using the `get_info_string` function:
|
||||||
|
|
||||||
|
```v ignore
|
||||||
|
println(ttf_font.get_info_string())
|
||||||
|
```
|
||||||
|
that give an outpul like this:
|
||||||
|
```
|
||||||
|
----- Font Info -----
|
||||||
|
font_family : Arial
|
||||||
|
font_sub_family : Normal
|
||||||
|
full_name : Arial
|
||||||
|
postscript_name : ArialMT
|
||||||
|
version : 1
|
||||||
|
font_revision : 5.06
|
||||||
|
magic_number : 5f0f3cf5
|
||||||
|
flags : 81b
|
||||||
|
created unixTS : 649950890
|
||||||
|
modified unixTS : 1282151447
|
||||||
|
units_per_em : 2048
|
||||||
|
box : [x_min:-1361, y_min:-665, x_Max:4096, y_Max:2060]
|
||||||
|
mac_style : 0
|
||||||
|
-----------------------
|
||||||
|
```
|
||||||
|
|
||||||
|
Once loaded a font the `TTF_File` struct is filled with the font data and texts can be rendered.
|
||||||
|
At high level no more action are required to use the loaded font.
|
||||||
|
Multiple fonts can be loaded without problems at the same time.
|
||||||
|
|
||||||
|
## TTF Bitmap render
|
||||||
|
In this modue it is possible to have different renders running at the same time.
|
||||||
|
At the present time all the rendering are made on the CPU, sokol is used only to draw the
|
||||||
|
rendered text to the screen.
|
||||||
|
Let's start with a simple snippet of code:
|
||||||
|
```v ignore
|
||||||
|
import os
|
||||||
|
import x.ttf
|
||||||
|
[console]
|
||||||
|
fn main(){
|
||||||
|
mut ttf_font := ttf.TTF_File{}
|
||||||
|
ttf_font.buf = os.read_bytes("arial.ttf") or { panic(err) }
|
||||||
|
ttf_font.init()
|
||||||
|
// print font info
|
||||||
|
println(ttf_font.get_info_string())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This simple code load a TTF font and display its basic informations.
|
||||||
|
|
||||||
|
### draw_text
|
||||||
|
The draw text function draw simple strings without indentation or other imagination tasks.
|
||||||
|
At this point we can render a simple text:
|
||||||
|
```v ignore
|
||||||
|
import os
|
||||||
|
import x.ttf
|
||||||
|
|
||||||
|
[console]
|
||||||
|
fn main(){
|
||||||
|
mut ttf_font := ttf.TTF_File{}
|
||||||
|
ttf_font.buf = os.read_bytes("arial.ttf") or { panic(err) }
|
||||||
|
ttf_font.init()
|
||||||
|
// print font info
|
||||||
|
println(ttf_font.get_info_string())
|
||||||
|
|
||||||
|
bmp_width := 200
|
||||||
|
bmp_heigth := 64
|
||||||
|
bmp_layers := 4 // number of planes for an RGBA buffer
|
||||||
|
// memory size of the buffer
|
||||||
|
bmp_size := bmp_width * bmp_heigth * bmp_layers
|
||||||
|
|
||||||
|
font_size := 32 // font size in points
|
||||||
|
device_dpi := 72 // default screen DPI
|
||||||
|
// Formula for scale calculation
|
||||||
|
// scaler := (font_size * device dpi) / (72dpi * em_unit)
|
||||||
|
scale := f32(font_size * device_dpi) / f32(72 * ttf_font.units_per_em)
|
||||||
|
// height of the font to use in the buffer to separate the lines
|
||||||
|
y_base := int((ttf_font.y_max - ttf_font.y_min) * scale)
|
||||||
|
|
||||||
|
// declare the bitmap struct
|
||||||
|
mut bmp:= ttf.BitMap{
|
||||||
|
tf : &ttf_font
|
||||||
|
buf : malloc(bmp_size)
|
||||||
|
buf_size : bmp_size
|
||||||
|
width : bmp_width
|
||||||
|
height : bmp_heigth
|
||||||
|
bp : bmp_layers
|
||||||
|
color : 0x000000_FF // RGBA black
|
||||||
|
scale : scale
|
||||||
|
}
|
||||||
|
bmp.init_filler()
|
||||||
|
bmp.clear()
|
||||||
|
bmp.set_pos(10,y_base)
|
||||||
|
bmp.draw_text("Test Text!")
|
||||||
|
bmp.save_as_ppm("test.ppm")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This is the low level render that draw ther text on a bitmap and save the bitmap on a disk as
|
||||||
|
`.ppm` file.
|
||||||
|
*Note: The render in this case is a raw rendering without any postfiltering or other processing.*
|
||||||
|
|
||||||
|
Using the low level rendering you need to manage all the amenities like allocate and release
|
||||||
|
memory and other tasks like calc the character dimensions.
|
||||||
|
|
||||||
|
You can specify the style for the text rendering in the `BitMap` struct::
|
||||||
|
```v ignore
|
||||||
|
enum Style {
|
||||||
|
outline
|
||||||
|
outline_aliased
|
||||||
|
filled // default syle
|
||||||
|
raw
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Use this level only if you want achieve particular result on text rendering.
|
||||||
|
|
||||||
|
### draw_text_block
|
||||||
|
Draw text block draw a justified and indented block of multiline text in the bitmap.
|
||||||
|
```v ignore
|
||||||
|
import os
|
||||||
|
import x.ttf
|
||||||
|
|
||||||
|
[console]
|
||||||
|
fn main(){
|
||||||
|
mut ttf_font := ttf.TTF_File{}
|
||||||
|
ttf_font.buf = os.read_bytes("arial.ttf") or { panic(err) }
|
||||||
|
ttf_font.init()
|
||||||
|
// print font info
|
||||||
|
println(ttf_font.get_info_string())
|
||||||
|
|
||||||
|
bmp_width := 200
|
||||||
|
bmp_heigth := 200
|
||||||
|
bmp_layers := 4 // number of planes for an RGBA buffer
|
||||||
|
// memory size of the buffer
|
||||||
|
bmp_size := bmp_width * bmp_heigth * bmp_layers
|
||||||
|
|
||||||
|
font_size := 32 // font size in points
|
||||||
|
device_dpi := 72 // default screen DPI
|
||||||
|
// Formula for scale calculation
|
||||||
|
// scaler := (font_size * device dpi) / (72dpi * em_unit)
|
||||||
|
scale := f32(font_size * device_dpi) / f32(72 * ttf_font.units_per_em)
|
||||||
|
// height of the font to use in the buffer to separate the lines
|
||||||
|
y_base := int((ttf_font.y_max - ttf_font.y_min) * scale)
|
||||||
|
|
||||||
|
text := "Today it is a good day!
|
||||||
|
Tomorrow I'm not so sure :(
|
||||||
|
But Vwill prevail for sure, V is the way!!
|
||||||
|
òàèì@ò!£$%&
|
||||||
|
"
|
||||||
|
// declare the bitmap struct
|
||||||
|
mut bmp:= ttf.BitMap{
|
||||||
|
tf : &ttf_font
|
||||||
|
buf : malloc(bmp_size)
|
||||||
|
buf_size : bmp_size
|
||||||
|
width : bmp_width
|
||||||
|
height : bmp_heigth
|
||||||
|
bp : bmp_layers
|
||||||
|
color : 0x000000_FF // RGBA black
|
||||||
|
scale : scale
|
||||||
|
}
|
||||||
|
bmp.init_filler()
|
||||||
|
bmp.clear()
|
||||||
|
bmp.justify = true
|
||||||
|
bmp.align = .left
|
||||||
|
bmp.draw_text_block(text, {x: 0, y:0, w: bmp_width-20, h: bmp_heigth})
|
||||||
|
bmp.save_as_ppm("test.ppm")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This is the low level render that draw text block on the bitmap.
|
||||||
|
A text block is defined from a `Text_block` struct:
|
||||||
|
```v ignore
|
||||||
|
struct Text_block {
|
||||||
|
x int // x postion of the left high corner
|
||||||
|
y int // y postion of the left high corner
|
||||||
|
w int // width of the text block
|
||||||
|
h int // heigth of the text block
|
||||||
|
cut_lines bool = true // force to cut the line if the length is over the text block width
|
||||||
|
}
|
||||||
|
```
|
||||||
|
and use the following bitmap fields:
|
||||||
|
```v ignore
|
||||||
|
style Style = .filled // default syle
|
||||||
|
align Text_align = .left // default text align
|
||||||
|
justify bool // justify text flag, default deactivated
|
||||||
|
justify_fill_ratio f32 = 0.5 // justify fill ratio, if the ratio of the filled row is >= of this then justify the text
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possible to modify these parameters to obtain the desired effect on the text rendering.
|
||||||
|
|
||||||
|
## TTF Sokol render
|
||||||
|
The sokol render use the bitmap render to create the text and the `gg` functions to render
|
||||||
|
the text to the screen.
|
||||||
|
It is mor esimpel to use in a `gg app` that the raw bitmap render.
|
||||||
|
Each single text rendered need its own reder to be declared, after you can modify it.
|
||||||
|
Here a simple example of the usage:
|
||||||
|
```v ignore
|
||||||
|
import gg
|
||||||
|
import gx
|
||||||
|
import sokol.sapp
|
||||||
|
import sokol.sgl
|
||||||
|
|
||||||
|
import x.ttf
|
||||||
|
import os
|
||||||
|
|
||||||
|
const (
|
||||||
|
win_width = 600
|
||||||
|
win_height = 700
|
||||||
|
bg_color = gx.white
|
||||||
|
font_paths = [
|
||||||
|
"arial.ttf"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
struct App_data {
|
||||||
|
pub mut:
|
||||||
|
gg &gg.Context
|
||||||
|
sg_img C.sg_image
|
||||||
|
init_flag bool
|
||||||
|
frame_c int
|
||||||
|
|
||||||
|
tf []ttf.TTF_File
|
||||||
|
ttf_render []ttf.TTF_render_Sokol
|
||||||
|
}
|
||||||
|
|
||||||
|
fn my_init(mut app App_data) {
|
||||||
|
app.init_flag = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_frame(mut app &App_data) {
|
||||||
|
cframe_txt := "Current Frame: $app.frame_c"
|
||||||
|
|
||||||
|
app.gg.begin()
|
||||||
|
|
||||||
|
sgl.defaults()
|
||||||
|
sgl.matrix_mode_projection()
|
||||||
|
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
||||||
|
|
||||||
|
// draw text only if the app is already initialized
|
||||||
|
if app.init_flag == true {
|
||||||
|
// update the text
|
||||||
|
mut txt1 := &app.ttf_render[0]
|
||||||
|
txt1.destroy_texture()
|
||||||
|
txt1.create_text(cframe_txt ,43)
|
||||||
|
txt1.create_texture()
|
||||||
|
txt1.draw_text_bmp(app.gg, 30, 60)
|
||||||
|
}
|
||||||
|
app.frame_c++
|
||||||
|
app.gg.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
[console]
|
||||||
|
fn main(){
|
||||||
|
mut app := &App_data{
|
||||||
|
gg: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
app.gg = gg.new_context({
|
||||||
|
width: win_width
|
||||||
|
height: win_height
|
||||||
|
use_ortho: true // This is needed for 2D drawing
|
||||||
|
create_window: true
|
||||||
|
window_title: 'Test TTF module'
|
||||||
|
user_data: app
|
||||||
|
bg_color: bg_color
|
||||||
|
frame_fn: draw_frame
|
||||||
|
init_fn: my_init
|
||||||
|
})
|
||||||
|
|
||||||
|
// load TTF fonts
|
||||||
|
for font_path in font_paths {
|
||||||
|
mut tf := ttf.TTF_File{}
|
||||||
|
tf.buf = os.read_bytes(font_path) or { panic(err) }
|
||||||
|
println("TrueTypeFont file [$font_path] len: ${tf.buf.len}")
|
||||||
|
tf.init()
|
||||||
|
println(tf.get_info_string())
|
||||||
|
app.tf << tf
|
||||||
|
}
|
||||||
|
|
||||||
|
// TTF render 0 Frame counter
|
||||||
|
app.ttf_render << &ttf.TTF_render_Sokol {
|
||||||
|
bmp: &ttf.BitMap{
|
||||||
|
tf: &(app.tf[0])
|
||||||
|
buf: malloc(32000000)
|
||||||
|
buf_size: (32000000)
|
||||||
|
color : 0xFF0000FF
|
||||||
|
//style: .raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.gg.run()
|
||||||
|
}
|
||||||
|
```
|
|
@ -49,9 +49,50 @@ fn dprintln(txt string){
|
||||||
* Utility
|
* Utility
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
// transform the bitmap from one layer to color layers
|
||||||
|
fn (mut bmp BitMap) format_texture(){
|
||||||
|
r := byte(bmp.color >> 24)
|
||||||
|
g := byte((bmp.color >> 16) & 0xFF)
|
||||||
|
b := byte((bmp.color >> 8 ) & 0xFF)
|
||||||
|
a := byte(bmp.color & 0xFF)
|
||||||
|
|
||||||
|
b_r := byte(bmp.bg_color >> 24)
|
||||||
|
b_g := byte((bmp.bg_color >> 16) & 0xFF)
|
||||||
|
b_b := byte((bmp.bg_color >> 8 ) & 0xFF)
|
||||||
|
b_a := byte(bmp.bg_color & 0xFF)
|
||||||
|
|
||||||
|
// trasform buffer in a texture
|
||||||
|
x := byteptr(bmp.buf)
|
||||||
|
unsafe{
|
||||||
|
mut i := 0
|
||||||
|
for i<bmp.buf_size {
|
||||||
|
data := x[i]
|
||||||
|
if data > 0 {
|
||||||
|
x[i+0] = r
|
||||||
|
x[i+1] = g
|
||||||
|
x[i+2] = b
|
||||||
|
// alpha
|
||||||
|
x[i+3] = byte((a * data) >> 8)
|
||||||
|
} else {
|
||||||
|
x[i+0] = b_r
|
||||||
|
x[i+1] = b_g
|
||||||
|
x[i+2] = b_b
|
||||||
|
x[i+3] = b_a
|
||||||
|
}
|
||||||
|
i += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// write out a .ppm file
|
// write out a .ppm file
|
||||||
pub
|
pub
|
||||||
fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||||
|
tmp_buf := bmp.buf
|
||||||
|
mut buf := malloc(bmp.buf_size)
|
||||||
|
unsafe { C.memcpy(buf, tmp_buf, bmp.buf_size) }
|
||||||
|
bmp.buf = buf
|
||||||
|
|
||||||
|
bmp.format_texture()
|
||||||
npixels := bmp.width * bmp.height
|
npixels := bmp.width * bmp.height
|
||||||
mut f_out := os.create(file_name) or { panic(err) }
|
mut f_out := os.create(file_name) or { panic(err) }
|
||||||
f_out.writeln('P3')
|
f_out.writeln('P3')
|
||||||
|
@ -60,14 +101,17 @@ fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||||
for i in 0..npixels {
|
for i in 0..npixels {
|
||||||
pos := i * bmp.bp
|
pos := i * bmp.bp
|
||||||
unsafe {
|
unsafe {
|
||||||
c_r := 0xFF - bmp.buf[pos]
|
c_r := bmp.buf[pos]
|
||||||
c_g := 0xFF - bmp.buf[pos +1 ]
|
c_g := bmp.buf[pos +1 ]
|
||||||
c_b := 0xFF - bmp.buf[pos + 2]
|
c_b := bmp.buf[pos + 2]
|
||||||
f_out.write_str('${c_r} ${c_g} ${c_b} ')
|
f_out.write_str('${c_r} ${c_g} ${c_b} ')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
f_out.close()
|
f_out.close()
|
||||||
|
|
||||||
|
free(buf)
|
||||||
|
bmp.buf = tmp_buf
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub
|
||||||
|
|
|
@ -32,37 +32,7 @@ pub mut:
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
fn (mut tf_skl TTF_render_Sokol) format_texture(){
|
fn (mut tf_skl TTF_render_Sokol) format_texture(){
|
||||||
r := byte(tf_skl.bmp.color >> 24)
|
tf_skl.bmp.format_texture()
|
||||||
g := byte((tf_skl.bmp.color >> 16) & 0xFF)
|
|
||||||
b := byte((tf_skl.bmp.color >> 8 ) & 0xFF)
|
|
||||||
a := byte(tf_skl.bmp.color & 0xFF)
|
|
||||||
|
|
||||||
b_r := byte(tf_skl.bmp.bg_color >> 24)
|
|
||||||
b_g := byte((tf_skl.bmp.bg_color >> 16) & 0xFF)
|
|
||||||
b_b := byte((tf_skl.bmp.bg_color >> 8 ) & 0xFF)
|
|
||||||
b_a := byte(tf_skl.bmp.bg_color & 0xFF)
|
|
||||||
|
|
||||||
// trasform buffer in a texture
|
|
||||||
x := byteptr(tf_skl.bmp.buf)
|
|
||||||
unsafe{
|
|
||||||
mut i := 0
|
|
||||||
for i<tf_skl.bmp.buf_size {
|
|
||||||
data := x[i]
|
|
||||||
if data > 0 {
|
|
||||||
x[i+0] = r
|
|
||||||
x[i+1] = g
|
|
||||||
x[i+2] = b
|
|
||||||
// alpha
|
|
||||||
x[i+3] = byte((a * data) >> 8)
|
|
||||||
} else {
|
|
||||||
x[i+0] = b_r
|
|
||||||
x[i+1] = b_g
|
|
||||||
x[i+2] = b_b
|
|
||||||
x[i+3] = b_a
|
|
||||||
}
|
|
||||||
i += 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub
|
||||||
|
|
|
@ -13,14 +13,13 @@ module ttf
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
pub
|
pub
|
||||||
struct Text_block {
|
struct Text_block {
|
||||||
x int
|
x int // x postion of the left high corner
|
||||||
y int
|
y int // y postion of the left high corner
|
||||||
w int // width of the text block
|
w int // width of the text block
|
||||||
h int // heigth of the text block
|
h int // heigth of the text block
|
||||||
cut_lines bool = true
|
cut_lines bool = true // force to cut the line if the length is over the text block width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 {
|
fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 {
|
||||||
num_spaces := txt.count(" ")
|
num_spaces := txt.count(" ")
|
||||||
if num_spaces < 1 {
|
if num_spaces < 1 {
|
||||||
|
|
|
@ -558,9 +558,9 @@ fn (mut tf TTF_File) get_fixed() f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) get_string(length int) string {
|
fn (mut tf TTF_File) get_string(length int) string {
|
||||||
tmp_pos := tf.pos
|
tmp_pos := u64(tf.pos)
|
||||||
tf.pos += u32(length)
|
tf.pos += u32(length)
|
||||||
return unsafe{ tos(byteptr(u64(tf.buf.data)+u64(tmp_pos)), length) }
|
return unsafe{ tos(byteptr(u64(tf.buf.data)+tmp_pos), length) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) get_unicode_string(length int) string {
|
fn (mut tf TTF_File) get_unicode_string(length int) string {
|
||||||
|
@ -586,12 +586,10 @@ fn (mut tf TTF_File) get_unicode_string(length int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) get_date() u64 {
|
fn (mut tf TTF_File) get_date() u64 {
|
||||||
// var macTime = this.getUint32() * 0x100000000 + this.getUint32();
|
// get mac time and covert it to unix timestamp
|
||||||
// utcTime = macTime * 1000 + Date.UTC(1904, 1, 1);
|
mac_time := (u64(tf.get_u32()) << 32) + u64(tf.get_u32())
|
||||||
// return new Date(utcTime);
|
utc_time := mac_time - u64(2082844800)
|
||||||
|
return utc_time
|
||||||
mac_time := u64( (tf.get_u32()) << 32) + u64(tf.get_u32())
|
|
||||||
return mac_time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) calc_checksum(offset u32, length u32) u32 {
|
fn (mut tf TTF_File) calc_checksum(offset u32, length u32) u32 {
|
||||||
|
@ -1053,23 +1051,25 @@ fn (mut tf TTF_File) next_kern(glyph_index int) (int, int){
|
||||||
* TTF_File Utility
|
* TTF_File Utility
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/*
|
pub
|
||||||
fn (tf TTF_File) get_info_string() string{
|
fn (tf TTF_File) get_info_string() string{
|
||||||
txt := "----- Font Info -----
|
txt := "----- Font Info -----
|
||||||
version: $tf.version
|
font_family : $tf.font_family
|
||||||
font_revision: $tf.font_revision
|
font_sub_family : $tf.font_sub_family
|
||||||
|
full_name : $tf.full_name
|
||||||
|
postscript_name : $tf.postscript_name
|
||||||
|
version : $tf.version
|
||||||
|
font_revision : $tf.font_revision
|
||||||
magic_number : ${tf.magic_number.hex()}
|
magic_number : ${tf.magic_number.hex()}
|
||||||
flags : ${tf.flags.hex()}
|
flags : ${tf.flags.hex()}
|
||||||
created : ${tf.created}
|
created unixTS : ${tf.created}
|
||||||
modified : ${tf.modified}
|
modified unixTS : ${tf.modified}
|
||||||
box : [xm:${tf.x_min}, ym:${tf.y_min}, xM:${tf.x_max}, yM:${tf.y_max}]
|
box : [x_min:${tf.x_min}, y_min:${tf.y_min}, x_Max:${tf.x_max}, y_Max:${tf.y_max}]
|
||||||
mac_style : ${tf.mac_style}
|
mac_style : ${tf.mac_style}
|
||||||
-----------------------
|
-----------------------
|
||||||
"
|
"
|
||||||
return txt
|
return txt
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue