Compare commits
13 Commits
b81f06e369
...
b7f2ef78b2
| Author | SHA1 | Date |
|---|---|---|
|
|
b7f2ef78b2 | |
|
|
2d9fa62941 | |
|
|
8b085a32a5 | |
|
|
604f4f5e44 | |
|
|
c37bb48e9c | |
|
|
609464bc9c | |
|
|
8a75d68421 | |
|
|
07d465cbaa | |
|
|
14cec11cc6 | |
|
|
9bc422a071 | |
|
|
2b0f0820e6 | |
|
|
0302cd69bd | |
|
|
cab53d0e75 |
|
|
@ -482,3 +482,6 @@ fn C.glTexImage2D()
|
|||
|
||||
// used by ios for println
|
||||
fn C.WrappedNSLog(str &u8)
|
||||
|
||||
// absolute value
|
||||
fn C.abs(number int) int
|
||||
|
|
|
|||
|
|
@ -578,3 +578,8 @@ pub fn (b u8) repeat(count int) string {
|
|||
}
|
||||
return unsafe { ret.vstring_with_len(new_len) }
|
||||
}
|
||||
|
||||
// for atomic ints, internal
|
||||
fn _Atomic__int_str(x int) string {
|
||||
return x.str()
|
||||
}
|
||||
|
|
|
|||
227
vlib/gg/draw.c.v
227
vlib/gg/draw.c.v
|
|
@ -211,66 +211,111 @@ pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) {
|
|||
sgl.end()
|
||||
}
|
||||
|
||||
// draw_rounded_rect_empty draws the outline of a rounded rectangle
|
||||
// draw_rounded_rect_empty draws the outline of a rounded rectangle with a thickness of 1 px.
|
||||
// `x`,`y` is the top-left corner of the rectangle.
|
||||
// `w` is the width, `h` is the height.
|
||||
// `radius` is the radius of the corner-rounding in pixels.
|
||||
// `c` is the color of the outline.
|
||||
pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
|
||||
mut theta := f32(0)
|
||||
mut xx := f32(0)
|
||||
mut yy := f32(0)
|
||||
r := radius * ctx.scale
|
||||
nx := x * ctx.scale
|
||||
ny := y * ctx.scale
|
||||
if w <= 0 || h <= 0 || radius < 0 {
|
||||
return
|
||||
}
|
||||
if c.a != 255 {
|
||||
sgl.load_pipeline(ctx.timage_pip)
|
||||
}
|
||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||
|
||||
mut new_radius := radius
|
||||
if w >= h && radius > h / 2 {
|
||||
new_radius = h / 2
|
||||
} else if radius > w / 2 {
|
||||
new_radius = w / 2
|
||||
}
|
||||
r := new_radius * ctx.scale
|
||||
sx := x * ctx.scale // start point x
|
||||
sy := y * ctx.scale
|
||||
width := w * ctx.scale
|
||||
height := h * ctx.scale
|
||||
segments := 2 * math.pi * r
|
||||
segdiv := segments / 4
|
||||
rb := 0
|
||||
lb := int(rb + segdiv)
|
||||
lt := int(lb + segdiv)
|
||||
rt := int(lt + segdiv)
|
||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||
// circle center coordinates
|
||||
ltx := sx + r
|
||||
lty := sy + r
|
||||
rtx := sx + width - r
|
||||
rty := lty
|
||||
rbx := rtx
|
||||
rby := sy + height - r
|
||||
lbx := ltx
|
||||
lby := rby
|
||||
|
||||
mut rad := f32(0)
|
||||
mut dx := f32(0)
|
||||
mut dy := f32(0)
|
||||
|
||||
// left top quarter
|
||||
sgl.begin_line_strip()
|
||||
// left top
|
||||
lx := nx + r
|
||||
ly := ny + r
|
||||
theta_coeff := 2 * f32(math.pi) / segments
|
||||
for i in lt .. rt {
|
||||
theta = theta_coeff * f32(i)
|
||||
xx = r * math.cosf(theta)
|
||||
yy = r * math.sinf(theta)
|
||||
sgl.v2f(xx + lx, yy + ly)
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
}
|
||||
// right top
|
||||
mut rx := nx + width - r
|
||||
mut ry := ny + r
|
||||
for i in rt .. int(segments) {
|
||||
theta = theta_coeff * f32(i)
|
||||
xx = r * math.cosf(theta)
|
||||
yy = r * math.sinf(theta)
|
||||
sgl.v2f(xx + rx, yy + ry)
|
||||
sgl.end()
|
||||
|
||||
// right top quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
}
|
||||
// right bottom
|
||||
mut rbx := rx
|
||||
mut rby := ny + height - r
|
||||
for i in rb .. lb {
|
||||
theta = theta_coeff * f32(i)
|
||||
xx = r * math.cosf(theta)
|
||||
yy = r * math.sinf(theta)
|
||||
sgl.v2f(xx + rbx, yy + rby)
|
||||
sgl.end()
|
||||
|
||||
// right bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
}
|
||||
// left bottom
|
||||
mut lbx := lx
|
||||
mut lby := ny + height - r
|
||||
for i in lb .. lt {
|
||||
theta = theta_coeff * f32(i)
|
||||
xx = r * math.cosf(theta)
|
||||
yy = r * math.sinf(theta)
|
||||
sgl.v2f(xx + lbx, yy + lby)
|
||||
sgl.end()
|
||||
|
||||
// left bottom quarter
|
||||
sgl.begin_line_strip()
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
}
|
||||
sgl.v2f(lx + xx, ly)
|
||||
sgl.end()
|
||||
|
||||
// Currently don't use 'gg.draw_line()' directly, it will repeatedly execute '*ctx.scale'.
|
||||
sgl.begin_lines()
|
||||
// top
|
||||
sgl.v2f(ltx, sy)
|
||||
sgl.v2f(rtx, sy)
|
||||
// right
|
||||
sgl.v2f(rtx + r, rty)
|
||||
sgl.v2f(rtx + r, rby)
|
||||
// bottom
|
||||
sgl.v2f(lbx, lby + r)
|
||||
sgl.v2f(rbx, rby + r)
|
||||
// left
|
||||
sgl.v2f(sx, lty)
|
||||
sgl.v2f(sx, lby)
|
||||
sgl.end()
|
||||
}
|
||||
|
||||
|
|
@ -280,87 +325,91 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
|
|||
// `radius` is the radius of the corner-rounding in pixels.
|
||||
// `c` is the color of the filled.
|
||||
pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
|
||||
assert w > 0 && h > 0 && radius >= 0
|
||||
if w <= 0 || h <= 0 || radius < 0 {
|
||||
return
|
||||
}
|
||||
if c.a != 255 {
|
||||
sgl.load_pipeline(ctx.timage_pip)
|
||||
}
|
||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||
mut xx := f32(0)
|
||||
mut yy := f32(0)
|
||||
mut radians := f32(0)
|
||||
|
||||
mut new_radius := radius
|
||||
if w >= h && radius > h / 2 {
|
||||
new_radius = h / 2
|
||||
} else if radius > w / 2 {
|
||||
new_radius = w / 2
|
||||
}
|
||||
|
||||
r := new_radius * ctx.scale
|
||||
nx := x * ctx.scale
|
||||
ny := y * ctx.scale
|
||||
sx := x * ctx.scale // start point x
|
||||
sy := y * ctx.scale
|
||||
width := w * ctx.scale
|
||||
height := h * ctx.scale
|
||||
// circle center coordinates
|
||||
ltx := sx + r
|
||||
lty := sy + r
|
||||
rtx := sx + width - r
|
||||
rty := lty
|
||||
rbx := rtx
|
||||
rby := sy + height - r
|
||||
lbx := ltx
|
||||
lby := rby
|
||||
|
||||
mut rad := f32(0)
|
||||
mut dx := f32(0)
|
||||
mut dy := f32(0)
|
||||
|
||||
// left top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
ltx := nx + r
|
||||
lty := ny + r
|
||||
for i in 0 .. 91 {
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
radians = f32(math.radians(i))
|
||||
xx = r * math.cosf(radians)
|
||||
yy = r * math.sinf(radians)
|
||||
sgl.v2f(ltx - xx, lty - yy)
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(ltx - dx, lty - dy)
|
||||
sgl.v2f(ltx, lty)
|
||||
}
|
||||
sgl.end()
|
||||
|
||||
// right top quarter
|
||||
sgl.begin_triangle_strip()
|
||||
rtx := nx + width - r
|
||||
rty := ny + r
|
||||
for i in 0 .. 91 {
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
radians = f32(math.radians(i))
|
||||
xx = r * math.cosf(radians)
|
||||
yy = r * math.sinf(radians)
|
||||
sgl.v2f(rtx + xx, rty - yy)
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rtx + dx, rty - dy)
|
||||
sgl.v2f(rtx, rty)
|
||||
}
|
||||
sgl.end()
|
||||
|
||||
// right bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
rbx := nx + width - r
|
||||
rby := ny + height - r
|
||||
for i in 0 .. 91 {
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
radians = f32(math.radians(i))
|
||||
xx = r * math.cosf(radians)
|
||||
yy = r * math.sinf(radians)
|
||||
sgl.v2f(rbx + xx, rby + yy)
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(rbx + dx, rby + dy)
|
||||
sgl.v2f(rbx, rby)
|
||||
}
|
||||
sgl.end()
|
||||
|
||||
// left bottom quarter
|
||||
sgl.begin_triangle_strip()
|
||||
lbx := nx + r
|
||||
lby := ny + height - r
|
||||
for i in 0 .. 91 {
|
||||
for i in 0 .. 31 {
|
||||
if r == 0 {
|
||||
break
|
||||
}
|
||||
radians = f32(math.radians(i))
|
||||
xx = r * math.cosf(radians)
|
||||
yy = r * math.sinf(radians)
|
||||
sgl.v2f(lbx - xx, lby + yy)
|
||||
rad = f32(math.radians(i * 3))
|
||||
dx = r * math.cosf(rad)
|
||||
dy = r * math.sinf(rad)
|
||||
sgl.v2f(lbx - dx, lby + dy)
|
||||
sgl.v2f(lbx, lby)
|
||||
}
|
||||
sgl.end()
|
||||
|
|
@ -368,24 +417,24 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
|
|||
// Separate drawing is to prevent transparent color overlap
|
||||
// top rectangle
|
||||
sgl.begin_quads()
|
||||
sgl.v2f(ltx, ny)
|
||||
sgl.v2f(rtx, ny)
|
||||
sgl.v2f(ltx, sy)
|
||||
sgl.v2f(rtx, sy)
|
||||
sgl.v2f(rtx, rty)
|
||||
sgl.v2f(ltx, lty)
|
||||
sgl.end()
|
||||
// middle rectangle
|
||||
sgl.begin_quads()
|
||||
sgl.v2f(nx, ny + r)
|
||||
sgl.v2f(sx, lty)
|
||||
sgl.v2f(rtx + r, rty)
|
||||
sgl.v2f(rbx + r, rby)
|
||||
sgl.v2f(nx, lby)
|
||||
sgl.v2f(sx, lby)
|
||||
sgl.end()
|
||||
// bottom rectangle
|
||||
sgl.begin_quads()
|
||||
sgl.v2f(lbx, lby)
|
||||
sgl.v2f(rbx, rby)
|
||||
sgl.v2f(rbx, ny + height)
|
||||
sgl.v2f(lbx, ny + height)
|
||||
sgl.v2f(rbx, rby + r)
|
||||
sgl.v2f(lbx, rby + r)
|
||||
sgl.end()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
module gg
|
||||
|
||||
import gx
|
||||
import sokol.sgl
|
||||
|
||||
// Stuff for ui from now for screenshot (that would be interesting for gg if screenshot is implemented also for gg)
|
||||
|
||||
// required for ui.DrawDevice interface (with &gg.Context as an instance)
|
||||
pub fn (ctx &Context) scissor_rect(x int, y int, w int, h int) {
|
||||
sgl.scissor_rect(int(dpi_scale() * x), int(dpi_scale() * y), int(dpi_scale() * w),
|
||||
int(dpi_scale() * h), true)
|
||||
}
|
||||
|
||||
pub fn (ctx &Context) has_text_style() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn (ctx &Context) set_text_style(font_name string, font_path string, size int, color gx.Color, align int, vertical_align int) {}
|
||||
|
||||
// default draw_text (draw_text_def but without set_cfg)
|
||||
pub fn (ctx &Context) draw_text_default(x int, y int, text string) {
|
||||
scale := if ctx.ft.scale == 0 { f32(1) } else { ctx.ft.scale }
|
||||
ctx.ft.fons.draw_text(x * scale, y * scale, text) // TODO: check offsets/alignment
|
||||
}
|
||||
|
|
@ -408,6 +408,16 @@ fn test_abs() {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_abs_zero() {
|
||||
ret1 := abs(0)
|
||||
println(ret1)
|
||||
assert '$ret1' == '0'
|
||||
|
||||
ret2 := abs(0.0)
|
||||
println(ret2)
|
||||
assert '$ret2' == '0'
|
||||
}
|
||||
|
||||
fn test_floor() {
|
||||
for i := 0; i < math.vf_.len; i++ {
|
||||
f := floor(math.vf_[i])
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@ pub fn max<T>(a T, b T) T {
|
|||
// abs returns the absolute value of `a`
|
||||
[inline]
|
||||
pub fn abs<T>(a T) T {
|
||||
return if a > 0 { a } else { -a }
|
||||
return if a < 0 { -a } else { a }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ pub const (
|
|||
#flag darwin -fobjc-arc
|
||||
#flag linux -lX11 -lGL -lXcursor -lXi -lpthread
|
||||
#flag freebsd -L/usr/local/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag openbsd -L/usr/X11R6/lib -lX11 -lGL -lXcursor -lXi
|
||||
#flag windows -lgdi32
|
||||
// METAL
|
||||
$if macos {
|
||||
|
|
@ -27,6 +28,7 @@ $if ios {
|
|||
// OPENGL
|
||||
#flag linux -DSOKOL_GLCORE33
|
||||
#flag freebsd -DSOKOL_GLCORE33
|
||||
#flag openbsd -DSOKOL_GLCORE33
|
||||
//#flag darwin -framework OpenGL -framework Cocoa -framework QuartzCore
|
||||
// D3D
|
||||
#flag windows -DSOKOL_GLCORE33
|
||||
|
|
@ -41,6 +43,7 @@ $if ios {
|
|||
#flag windows -DSOKOL_NO_ENTRY
|
||||
#flag windows -DSOKOL_WIN32_FORCE_MAIN
|
||||
#flag freebsd -DSOKOL_NO_ENTRY
|
||||
#flag openbsd -DSOKOL_NO_ENTRY
|
||||
#flag solaris -DSOKOL_NO_ENTRY
|
||||
// TODO end
|
||||
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
|
|||
// String Functions
|
||||
//=============================================================================
|
||||
|
||||
// f32_to_str return a string in scientific notation with max n_digit after the dot
|
||||
// f32_to_str returns a `string` in scientific notation with max `n_digit` after the dot.
|
||||
pub fn f32_to_str(f f32, n_digit int) string {
|
||||
mut u1 := Uf32{}
|
||||
u1.f = f
|
||||
|
|
@ -349,7 +349,7 @@ pub fn f32_to_str(f f32, n_digit int) string {
|
|||
return d.get_string_32(neg, n_digit, 0)
|
||||
}
|
||||
|
||||
// f32_to_str return a string in scientific notation with max n_digit after the dot
|
||||
// f32_to_str_pad returns a `string` in scientific notation with max `n_digit` after the dot.
|
||||
pub fn f32_to_str_pad(f f32, n_digit int) string {
|
||||
mut u1 := Uf32{}
|
||||
u1.f = f
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
|
|||
// String Functions
|
||||
//=============================================================================
|
||||
|
||||
// f64_to_str return a string in scientific notation with max n_digit after the dot
|
||||
// f64_to_str returns `f` as a `string` in scientific notation with max `n_digit` digits after the dot.
|
||||
pub fn f64_to_str(f f64, n_digit int) string {
|
||||
mut u1 := Uf64{}
|
||||
u1.f = f
|
||||
|
|
@ -356,7 +356,7 @@ pub fn f64_to_str(f f64, n_digit int) string {
|
|||
return d.get_string_64(neg, n_digit, 0)
|
||||
}
|
||||
|
||||
// f64_to_str return a string in scientific notation with max n_digit after the dot
|
||||
// f64_to_str returns `f` as a `string` in scientific notation with max `n_digit` digits after the dot.
|
||||
pub fn f64_to_str_pad(f f64, n_digit int) string {
|
||||
mut u1 := Uf64{}
|
||||
u1.f = f
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ pub mut:
|
|||
rm_tail_zero bool // remove the tail zeros from floats
|
||||
}
|
||||
|
||||
// format_str returns a `string` formatted according to the options set in `p`.
|
||||
[manualfree]
|
||||
pub fn format_str(s string, p BF_param) string {
|
||||
if p.len0 <= 0 {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module strconv
|
|||
|
||||
import strings
|
||||
|
||||
// strings.Builder version of format_str
|
||||
// format_str_sb is a `strings.Builder` version of `format_str`.
|
||||
pub fn format_str_sb(s string, p BF_param, mut sb strings.Builder) {
|
||||
if p.len0 <= 0 {
|
||||
sb.write_string(s)
|
||||
|
|
@ -40,7 +40,7 @@ const (
|
|||
digit_pairs = '00102030405060708090011121314151617181910212223242526272829203132333435363738393041424344454647484940515253545556575859506162636465666768696071727374757677787970818283848586878889809192939495969798999'
|
||||
)
|
||||
|
||||
// format_dec_sb format a u64
|
||||
// format_dec_sb formats an u64 using a `strings.Builder`.
|
||||
[direct_array_access]
|
||||
pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
|
||||
mut n_char := dec_digits(d)
|
||||
|
|
@ -135,8 +135,9 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
|
|||
return
|
||||
}
|
||||
|
||||
// f64_to_str_lnd1 formats a f64 to a `string` with `dec_digit` digits after the dot.
|
||||
[direct_array_access; manualfree]
|
||||
pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
|
||||
fn f64_to_str_lnd1(f f64, dec_digit int) string {
|
||||
unsafe {
|
||||
// we add the rounding value
|
||||
s := f64_to_str(f + dec_round[dec_digit], 18)
|
||||
|
|
@ -311,7 +312,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
|
|||
}
|
||||
}
|
||||
|
||||
// strings.Builder version of format_fl
|
||||
// format_fl is a `strings.Builder` version of format_fl.
|
||||
[direct_array_access; manualfree]
|
||||
pub fn format_fl(f f64, p BF_param) string {
|
||||
unsafe {
|
||||
|
|
@ -388,6 +389,7 @@ pub fn format_fl(f f64, p BF_param) string {
|
|||
}
|
||||
}
|
||||
|
||||
// format_es returns a f64 as a `string` formatted according to the options set in `p`.
|
||||
[direct_array_access; manualfree]
|
||||
pub fn format_es(f f64, p BF_param) string {
|
||||
unsafe {
|
||||
|
|
@ -458,6 +460,7 @@ pub fn format_es(f f64, p BF_param) string {
|
|||
}
|
||||
}
|
||||
|
||||
// remove_tail_zeros strips traling zeros from `s` and return the resulting `string`.
|
||||
[direct_array_access]
|
||||
pub fn remove_tail_zeros(s string) string {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -18,21 +18,33 @@ inspired by the Go version here:
|
|||
https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
|
||||
*/
|
||||
|
||||
// ftoa_64 returns a string in scientific notation with max 17 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.ftoa_64(123.1234567891011121) == '1.2312345678910111e+02'
|
||||
[inline]
|
||||
pub fn ftoa_64(f f64) string {
|
||||
return f64_to_str(f, 17)
|
||||
}
|
||||
|
||||
// ftoa_long_64 returns `f` as a `string` in decimal notation with a maximum of 17 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.f64_to_str_l(123.1234567891011121) == '123.12345678910111'
|
||||
[inline]
|
||||
pub fn ftoa_long_64(f f64) string {
|
||||
return f64_to_str_l(f)
|
||||
}
|
||||
|
||||
// ftoa_32 returns a `string` in scientific notation with max 8 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.ftoa_32(34.1234567) == '3.4123455e+01'
|
||||
[inline]
|
||||
pub fn ftoa_32(f f32) string {
|
||||
return f32_to_str(f, 8)
|
||||
}
|
||||
|
||||
// ftoa_long_32 returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.ftoa_long_32(34.1234567) == '34.12346'
|
||||
[inline]
|
||||
pub fn ftoa_long_32(f f32) string {
|
||||
return f32_to_str_l(f)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ f64 to string with string format
|
|||
*/
|
||||
|
||||
// TODO: Investigate precision issues
|
||||
// f32_to_str_l return a string with the f32 converted in a string in decimal notation
|
||||
// f32_to_str_l returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.f32_to_str_l(34.1234567) == '34.12346'
|
||||
[manualfree]
|
||||
pub fn f32_to_str_l(f f32) string {
|
||||
s := f32_to_str(f, 6)
|
||||
|
|
@ -34,6 +36,10 @@ pub fn f32_to_str_l(f f32) string {
|
|||
return res
|
||||
}
|
||||
|
||||
// f32_to_str_l_no_dot returns `f` as a `string` in decimal notation with a maximum of 6 digits after the dot.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
//
|
||||
// Example: assert strconv.f32_to_str_l_no_dot(34.) == '34'
|
||||
[manualfree]
|
||||
pub fn f32_to_str_l_no_dot(f f32) string {
|
||||
s := f32_to_str(f, 6)
|
||||
|
|
@ -42,6 +48,9 @@ pub fn f32_to_str_l_no_dot(f f32) string {
|
|||
return res
|
||||
}
|
||||
|
||||
// f64_to_str_l returns `f` as a `string` in decimal notation with a maximum of 18 digits after the dot.
|
||||
//
|
||||
// Example: assert strconv.f64_to_str_l(123.1234567891011121) == '123.12345678910111'
|
||||
[manualfree]
|
||||
pub fn f64_to_str_l(f f64) string {
|
||||
s := f64_to_str(f, 18)
|
||||
|
|
@ -50,6 +59,10 @@ pub fn f64_to_str_l(f f64) string {
|
|||
return res
|
||||
}
|
||||
|
||||
// f64_to_str_l_no_dot returns `f` as a `string` in decimal notation with a maximum of 18 digits after the dot.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
//
|
||||
// Example: assert strconv.f64_to_str_l_no_dot (34.) == '34'
|
||||
[manualfree]
|
||||
pub fn f64_to_str_l_no_dot(f f64) string {
|
||||
s := f64_to_str(f, 18)
|
||||
|
|
@ -58,7 +71,10 @@ pub fn f64_to_str_l_no_dot(f f64) string {
|
|||
return res
|
||||
}
|
||||
|
||||
// f64_to_str_l return a string with the f64 converted in a string in decimal notation
|
||||
// fxx_to_str_l_parse returns a `string` in decimal notation converted from a
|
||||
// floating-point `string` in scientific notation.
|
||||
//
|
||||
// Example: assert strconv.fxx_to_str_l_parse('34.22e+00') == '34.22'
|
||||
[manualfree]
|
||||
pub fn fxx_to_str_l_parse(s string) string {
|
||||
// check for +inf -inf Nan
|
||||
|
|
@ -181,7 +197,11 @@ pub fn fxx_to_str_l_parse(s string) string {
|
|||
return unsafe { tos(res.data, r_i) }
|
||||
}
|
||||
|
||||
// f64_to_str_l return a string with the f64 converted in a string in decimal notation
|
||||
// fxx_to_str_l_parse_no_dot returns a `string` in decimal notation converted from a
|
||||
// floating-point `string` in scientific notation.
|
||||
// The decimal digits after the dot can be omitted.
|
||||
//
|
||||
// Example: assert strconv.fxx_to_str_l_parse_no_dot ('34.e+01') == '340'
|
||||
[manualfree]
|
||||
pub fn fxx_to_str_l_parse_no_dot(s string) string {
|
||||
// check for +inf -inf Nan
|
||||
|
|
|
|||
|
|
@ -22,10 +22,18 @@ enum Char_parse_state {
|
|||
reset_params
|
||||
}
|
||||
|
||||
// v_printf prints a sprintf-like formated `string` to the terminal.
|
||||
pub fn v_printf(str string, pt ...voidptr) {
|
||||
print(v_sprintf(str, ...pt))
|
||||
}
|
||||
|
||||
// v_sprintf returns a sprintf-like formated `string`.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// x := 3.141516
|
||||
// assert strconv.v_sprintf('aaa %G', x) == 'aaa 3.141516'
|
||||
// ```
|
||||
[manualfree]
|
||||
pub fn v_sprintf(str string, pt ...voidptr) string {
|
||||
mut res := strings.new_builder(pt.len * 16)
|
||||
|
|
@ -628,7 +636,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
|
|||
}
|
||||
|
||||
[manualfree]
|
||||
pub fn format_es_old(f f64, p BF_param) string {
|
||||
fn format_es_old(f f64, p BF_param) string {
|
||||
unsafe {
|
||||
mut s := ''
|
||||
mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1)
|
||||
|
|
@ -692,7 +700,7 @@ pub fn format_es_old(f f64, p BF_param) string {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn remove_tail_zeros_old(s string) string {
|
||||
fn remove_tail_zeros_old(s string) string {
|
||||
mut i := 0
|
||||
mut last_zero_start := -1
|
||||
mut dot_pos := -1
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string)
|
|||
return none
|
||||
}
|
||||
mut fos := ''
|
||||
mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris']
|
||||
mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'openbsd', 'windows', 'mingw',
|
||||
'solaris']
|
||||
allowed_os_overrides << ctimedefines
|
||||
for os_override in allowed_os_overrides {
|
||||
if !flag.starts_with(os_override) {
|
||||
|
|
|
|||
|
|
@ -1156,7 +1156,7 @@ pub fn (mut t Table) find_or_register_multi_return(mr_typs []Type) int {
|
|||
mut name := '('
|
||||
mut cname := 'multi_return'
|
||||
for i, mr_typ in mr_typs {
|
||||
mr_type_sym := t.sym(mr_typ)
|
||||
mr_type_sym := t.sym(mktyp(mr_typ))
|
||||
ref, cref := if mr_typ.is_ptr() { '&', 'ref_' } else { '', '' }
|
||||
name += '$ref$mr_type_sym.name'
|
||||
cname += '_$cref$mr_type_sym.cname'
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ pub fn (t Type) atomic_typename() string {
|
|||
idx := t.idx()
|
||||
match idx {
|
||||
ast.u32_type_idx { return 'atomic_uint' }
|
||||
ast.int_type_idx { return 'atomic_int' }
|
||||
ast.int_type_idx { return '_Atomic int' }
|
||||
ast.u64_type_idx { return 'atomic_ullong' }
|
||||
ast.i64_type_idx { return 'atomic_llong' }
|
||||
else { return 'unknown_atomic' }
|
||||
|
|
@ -1161,6 +1161,10 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
|
|||
nr_muls--
|
||||
res = 'shared ' + res
|
||||
}
|
||||
if typ.has_flag(.atomic_f) {
|
||||
nr_muls--
|
||||
res = 'atomic ' + res
|
||||
}
|
||||
if nr_muls > 0 && !typ.has_flag(.variadic) {
|
||||
res = strings.repeat(`&`, nr_muls) + res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
|||
if expected == ast.voidptr_type {
|
||||
return true
|
||||
}
|
||||
if expected == ast.bool_type && (got.is_any_kind_of_pointer() || got.is_int()) {
|
||||
return true
|
||||
}
|
||||
|
||||
if expected.is_any_kind_of_pointer() { //&& !got.is_any_kind_of_pointer() {
|
||||
// Allow `int` as `&i8` etc in C code.
|
||||
deref := expected.deref()
|
||||
|
|
@ -244,6 +248,20 @@ pub fn (mut c Checker) check_basic(got ast.Type, expected ast.Type) bool {
|
|||
return true
|
||||
}
|
||||
got_sym, exp_sym := c.table.sym(got), c.table.sym(expected)
|
||||
// multi return
|
||||
if exp_sym.kind == .multi_return && got_sym.kind == .multi_return {
|
||||
exp_types := exp_sym.mr_info().types
|
||||
got_types := got_sym.mr_info().types.map(ast.mktyp(it))
|
||||
if exp_types.len != got_types.len {
|
||||
return false
|
||||
}
|
||||
for i in 0 .. exp_types.len {
|
||||
if !c.check_types(got_types[i], exp_types[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
// array/map as argument
|
||||
if got_sym.kind in [.array, .map, .array_fixed] && exp_sym.kind == got_sym.kind {
|
||||
if c.table.type_to_str(got) == c.table.type_to_str(expected).trim('&') {
|
||||
|
|
|
|||
|
|
@ -702,8 +702,13 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
&& c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive() {
|
||||
left_sym = c.table.sym((left_sym.info as ast.Alias).parent_type)
|
||||
}
|
||||
if c.pref.translated && node.op in [.plus, .minus, .mul]
|
||||
&& left_type.is_any_kind_of_pointer()
|
||||
&& (right_type.is_any_kind_of_pointer() || right_type.is_int()) {
|
||||
return_type = left_type
|
||||
}
|
||||
// Check if the alias type is not a primitive then allow using operator overloading for aliased `arrays` and `maps`
|
||||
if !c.pref.translated && left_sym.kind == .alias && left_sym.info is ast.Alias
|
||||
else if !c.pref.translated && left_sym.kind == .alias && left_sym.info is ast.Alias
|
||||
&& !(c.table.sym((left_sym.info as ast.Alias).parent_type).is_primitive()) {
|
||||
if left_sym.has_method(node.op.str()) {
|
||||
if method := left_sym.find_method(node.op.str()) {
|
||||
|
|
@ -3775,7 +3780,9 @@ fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_ty
|
|||
// if typ_sym.kind == .array && (!(ast.type_idx(index_type) in ast.number_type_idxs) &&
|
||||
// index_type_sym.kind != .enum_) {
|
||||
if typ_sym.kind in [.array, .array_fixed, .string] {
|
||||
if !(index_type.is_int() || index_type_sym.kind == .enum_) {
|
||||
if !(index_type.is_int() || index_type_sym.kind == .enum_
|
||||
|| (index_type_sym.kind == .alias
|
||||
&& (index_type_sym.info as ast.Alias).parent_type.is_int())) {
|
||||
type_str := if typ_sym.kind == .string {
|
||||
'non-integer string index `$index_type_sym.name`'
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
|||
if node.is_range {
|
||||
high_type := c.expr(node.high)
|
||||
high_type_idx := high_type.idx()
|
||||
if typ_idx in ast.integer_type_idxs && high_type_idx !in ast.integer_type_idxs {
|
||||
if typ_idx in ast.integer_type_idxs && high_type_idx !in ast.integer_type_idxs
|
||||
&& high_type_idx != ast.void_type_idx {
|
||||
c.error('range types do not match', node.cond.pos())
|
||||
} else if typ_idx in ast.float_type_idxs || high_type_idx in ast.float_type_idxs {
|
||||
c.error('range type can not be float', node.cond.pos())
|
||||
|
|
|
|||
|
|
@ -217,16 +217,6 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
if is_noreturn_callexpr(last_expr.expr) {
|
||||
continue
|
||||
}
|
||||
node_sym := c.table.sym(node.typ)
|
||||
last_sym := c.table.sym(last_expr.typ)
|
||||
if node_sym.kind == .multi_return && last_sym.kind == .multi_return {
|
||||
node_types := node_sym.mr_info().types
|
||||
last_types := last_sym.mr_info().types.map(ast.mktyp(it))
|
||||
if node_types == last_types {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`',
|
||||
node.pos)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,182 +22,165 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
|
|||
array_styp = g.typ(array_type.typ)
|
||||
g.write('HEAP($array_styp, ')
|
||||
}
|
||||
len := node.exprs.len
|
||||
if array_type.unaliased_sym.kind == .array_fixed {
|
||||
if node.has_it {
|
||||
g.inside_lambda = true
|
||||
tmp := g.new_tmp_var()
|
||||
mut s := g.go_before_stmt(0)
|
||||
s_ends_with_ln := s.ends_with('\n')
|
||||
s = s.trim_space()
|
||||
ret_typ := g.typ(node.typ)
|
||||
elem_typ := g.typ(node.elem_type)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp =')
|
||||
g.write('{')
|
||||
if node.has_val {
|
||||
for i, expr in node.exprs {
|
||||
if expr.is_auto_deref_var() {
|
||||
g.write('*')
|
||||
}
|
||||
g.write('0')
|
||||
if i != node.exprs.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
} else if node.has_default {
|
||||
g.write('0')
|
||||
info := array_type.unaliased_sym.info as ast.ArrayFixed
|
||||
for _ in 1 .. info.size {
|
||||
g.fixed_array_init(node, array_type)
|
||||
} else if len == 0 {
|
||||
// `[]int{len: 6, cap:10, init:22}`
|
||||
g.array_init_with_fields(node, elem_type, is_amp, shared_styp)
|
||||
} else {
|
||||
// `[1, 2, 3]`
|
||||
elem_styp := g.typ(elem_type.typ)
|
||||
noscan := g.check_noscan(elem_type.typ)
|
||||
if elem_type.unaliased_sym.kind == .function {
|
||||
g.write('new_array_from_c_array($len, $len, sizeof(voidptr), _MOV((voidptr[$len]){')
|
||||
} else if g.is_empty_struct(elem_type) {
|
||||
g.write('new_array_from_c_array${noscan}($len, $len, sizeof(voidptr), _MOV(($elem_styp[$len]){')
|
||||
} else {
|
||||
g.write('new_array_from_c_array${noscan}($len, $len, sizeof($elem_styp), _MOV(($elem_styp[$len]){')
|
||||
}
|
||||
if len > 8 {
|
||||
g.writeln('')
|
||||
g.write('\t\t')
|
||||
}
|
||||
for i, expr in node.exprs {
|
||||
if node.expr_types[i] == ast.string_type && expr !is ast.StringLiteral
|
||||
&& expr !is ast.StringInterLiteral {
|
||||
g.write('string_clone(')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.expr_with_cast(expr, node.expr_types[i], node.elem_type)
|
||||
}
|
||||
if i != len - 1 {
|
||||
if i > 0 && i & 7 == 0 { // i > 0 && i % 8 == 0
|
||||
g.writeln(',')
|
||||
g.write('\t\t')
|
||||
} else {
|
||||
g.write(', ')
|
||||
g.write('0')
|
||||
}
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
g.write('}')
|
||||
g.writeln(';')
|
||||
g.writeln('{')
|
||||
g.indent++
|
||||
g.writeln('$elem_typ* pelem = ($elem_typ*)$tmp;')
|
||||
g.writeln('int _len = (int)sizeof($tmp) / sizeof($elem_typ);')
|
||||
g.writeln('for(int it=0; it<_len; it++, pelem++) {')
|
||||
g.indent++
|
||||
g.write('*pelem = ')
|
||||
g.expr(node.default_expr)
|
||||
g.writeln(';')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
if s_ends_with_ln {
|
||||
g.writeln(s)
|
||||
} else {
|
||||
g.write(s)
|
||||
}
|
||||
g.write(tmp)
|
||||
g.inside_lambda = false
|
||||
return
|
||||
}
|
||||
need_tmp_var := g.inside_call && !g.inside_struct_init && node.exprs.len == 0
|
||||
mut stmt_str := ''
|
||||
mut tmp_var := ''
|
||||
if need_tmp_var {
|
||||
tmp_var = g.new_tmp_var()
|
||||
stmt_str = g.go_before_stmt(0)
|
||||
ret_typ := g.typ(node.typ)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp_var = ')
|
||||
g.write('}))')
|
||||
if g.is_shared {
|
||||
g.write('}, sizeof($shared_styp))')
|
||||
} else if is_amp {
|
||||
g.write(')')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) fixed_array_init(node ast.ArrayInit, array_type Type) {
|
||||
if node.has_it {
|
||||
g.inside_lambda = true
|
||||
tmp := g.new_tmp_var()
|
||||
mut s := g.go_before_stmt(0)
|
||||
s_ends_with_ln := s.ends_with('\n')
|
||||
s = s.trim_space()
|
||||
ret_typ := g.typ(node.typ)
|
||||
elem_typ := g.typ(node.elem_type)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp =')
|
||||
g.write('{')
|
||||
if node.has_val {
|
||||
for i, expr in node.exprs {
|
||||
if expr.is_auto_deref_var() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(expr)
|
||||
g.write('0')
|
||||
if i != node.exprs.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
} else if node.has_default {
|
||||
g.expr(node.default_expr)
|
||||
g.write('0')
|
||||
info := array_type.unaliased_sym.info as ast.ArrayFixed
|
||||
for _ in 1 .. info.size {
|
||||
g.write(', ')
|
||||
g.expr(node.default_expr)
|
||||
g.write('0')
|
||||
}
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
g.write('}')
|
||||
if need_tmp_var {
|
||||
g.writeln(';')
|
||||
g.write(stmt_str)
|
||||
g.write(tmp_var)
|
||||
g.writeln(';')
|
||||
g.writeln('{')
|
||||
g.indent++
|
||||
g.writeln('$elem_typ* pelem = ($elem_typ*)$tmp;')
|
||||
g.writeln('int _len = (int)sizeof($tmp) / sizeof($elem_typ);')
|
||||
g.writeln('for(int it=0; it<_len; it++, pelem++) {')
|
||||
g.indent++
|
||||
g.write('*pelem = ')
|
||||
g.expr(node.default_expr)
|
||||
g.writeln(';')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
if s_ends_with_ln {
|
||||
g.writeln(s)
|
||||
} else {
|
||||
g.write(s)
|
||||
}
|
||||
g.write(tmp)
|
||||
g.inside_lambda = false
|
||||
return
|
||||
}
|
||||
need_tmp_var := g.inside_call && !g.inside_struct_init && node.exprs.len == 0
|
||||
mut stmt_str := ''
|
||||
mut tmp_var := ''
|
||||
if need_tmp_var {
|
||||
tmp_var = g.new_tmp_var()
|
||||
stmt_str = g.go_before_stmt(0)
|
||||
ret_typ := g.typ(node.typ)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp_var = ')
|
||||
}
|
||||
g.write('{')
|
||||
if node.has_val {
|
||||
for i, expr in node.exprs {
|
||||
if expr.is_auto_deref_var() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(expr)
|
||||
if i != node.exprs.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
} else if node.has_default {
|
||||
g.expr(node.default_expr)
|
||||
info := array_type.unaliased_sym.info as ast.ArrayFixed
|
||||
for _ in 1 .. info.size {
|
||||
g.write(', ')
|
||||
g.expr(node.default_expr)
|
||||
}
|
||||
} else {
|
||||
g.write('0')
|
||||
}
|
||||
g.write('}')
|
||||
if need_tmp_var {
|
||||
g.writeln(';')
|
||||
g.write(stmt_str)
|
||||
g.write(tmp_var)
|
||||
}
|
||||
}
|
||||
|
||||
// `[]int{len: 6, cap: 10, init: it * it}`
|
||||
fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp bool, shared_styp string) {
|
||||
elem_styp := g.typ(elem_type.typ)
|
||||
noscan := g.check_noscan(elem_type.typ)
|
||||
if node.exprs.len == 0 {
|
||||
is_default_array := elem_type.unaliased_sym.kind == .array && node.has_default
|
||||
is_default_map := elem_type.unaliased_sym.kind == .map && node.has_default
|
||||
if node.has_it { // []int{len: 6, init: it * it} when variable it is used in init expression
|
||||
g.inside_lambda = true
|
||||
tmp := g.new_tmp_var()
|
||||
mut s := g.go_before_stmt(0)
|
||||
s_ends_with_ln := s.ends_with('\n')
|
||||
s = s.trim_space()
|
||||
ret_typ := g.typ(node.typ)
|
||||
elem_typ := g.typ(node.elem_type)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp =')
|
||||
if is_default_array {
|
||||
g.write('__new_array_with_array_default${noscan}(')
|
||||
} else if is_default_map {
|
||||
g.write('__new_array_with_map_default${noscan}(')
|
||||
} else {
|
||||
g.write('__new_array_with_default${noscan}(')
|
||||
}
|
||||
if node.has_len {
|
||||
g.expr(node.len_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
if node.has_cap {
|
||||
g.expr(node.cap_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
if elem_type.unaliased_sym.kind == .function || g.is_empty_struct(elem_type) {
|
||||
g.write('sizeof(voidptr), ')
|
||||
} else {
|
||||
g.write('sizeof($elem_styp), ')
|
||||
}
|
||||
if is_default_array {
|
||||
g.write('($elem_styp[]){')
|
||||
g.expr(node.default_expr)
|
||||
g.write('}[0])')
|
||||
} else if node.has_len && node.elem_type == ast.string_type {
|
||||
g.write('&($elem_styp[]){')
|
||||
g.write('_SLIT("")')
|
||||
g.write('})')
|
||||
} else if node.has_len && elem_type.unaliased_sym.kind in [.array, .map] {
|
||||
g.write('(voidptr)&($elem_styp[]){')
|
||||
g.write(g.type_default(node.elem_type))
|
||||
g.write('}[0])')
|
||||
} else {
|
||||
g.write('0)')
|
||||
}
|
||||
if g.is_shared {
|
||||
g.write('}, sizeof($shared_styp))')
|
||||
} else if is_amp {
|
||||
g.write(')')
|
||||
}
|
||||
g.writeln(';')
|
||||
g.writeln('{')
|
||||
g.indent++
|
||||
g.writeln('$elem_typ* pelem = ($elem_typ*)${tmp}.data;')
|
||||
g.writeln('for(int it=0; it<${tmp}.len; it++, pelem++) {')
|
||||
g.indent++
|
||||
g.write('*pelem = ')
|
||||
g.expr(node.default_expr)
|
||||
g.writeln(';')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
if s_ends_with_ln {
|
||||
g.writeln(s)
|
||||
} else {
|
||||
g.write(s)
|
||||
}
|
||||
g.write(tmp)
|
||||
g.inside_lambda = false
|
||||
return
|
||||
}
|
||||
is_default_array := elem_type.unaliased_sym.kind == .array && node.has_default
|
||||
is_default_map := elem_type.unaliased_sym.kind == .map && node.has_default
|
||||
if node.has_it { // []int{len: 6, init: it * it} when variable it is used in init expression
|
||||
g.inside_lambda = true
|
||||
tmp := g.new_tmp_var()
|
||||
mut s := g.go_before_stmt(0)
|
||||
s_ends_with_ln := s.ends_with('\n')
|
||||
s = s.trim_space()
|
||||
ret_typ := g.typ(node.typ)
|
||||
elem_typ := g.typ(node.elem_type)
|
||||
g.empty_line = true
|
||||
g.write('$ret_typ $tmp =')
|
||||
if is_default_array {
|
||||
g.write('__new_array_with_array_default${noscan}(')
|
||||
} else if is_default_map {
|
||||
|
|
@ -222,14 +205,10 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
|
|||
} else {
|
||||
g.write('sizeof($elem_styp), ')
|
||||
}
|
||||
if is_default_array || is_default_map {
|
||||
if is_default_array {
|
||||
g.write('($elem_styp[]){')
|
||||
g.expr(node.default_expr)
|
||||
g.write('}[0])')
|
||||
} else if node.has_default {
|
||||
g.write('&($elem_styp[]){')
|
||||
g.expr_with_cast(node.default_expr, node.default_type, node.elem_type)
|
||||
g.write('})')
|
||||
} else if node.has_len && node.elem_type == ast.string_type {
|
||||
g.write('&($elem_styp[]){')
|
||||
g.write('_SLIT("")')
|
||||
|
|
@ -246,39 +225,71 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
|
|||
} else if is_amp {
|
||||
g.write(')')
|
||||
}
|
||||
g.writeln(';')
|
||||
g.writeln('{')
|
||||
g.indent++
|
||||
g.writeln('$elem_typ* pelem = ($elem_typ*)${tmp}.data;')
|
||||
g.writeln('for(int it=0; it<${tmp}.len; it++, pelem++) {')
|
||||
g.indent++
|
||||
g.write('*pelem = ')
|
||||
g.expr(node.default_expr)
|
||||
g.writeln(';')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
if s_ends_with_ln {
|
||||
g.writeln(s)
|
||||
} else {
|
||||
g.write(s)
|
||||
}
|
||||
g.write(tmp)
|
||||
g.inside_lambda = false
|
||||
return
|
||||
}
|
||||
len := node.exprs.len
|
||||
if elem_type.unaliased_sym.kind == .function {
|
||||
g.write('new_array_from_c_array($len, $len, sizeof(voidptr), _MOV((voidptr[$len]){')
|
||||
} else if g.is_empty_struct(elem_type) {
|
||||
g.write('new_array_from_c_array${noscan}($len, $len, sizeof(voidptr), _MOV(($elem_styp[$len]){')
|
||||
if is_default_array {
|
||||
g.write('__new_array_with_array_default${noscan}(')
|
||||
} else if is_default_map {
|
||||
g.write('__new_array_with_map_default${noscan}(')
|
||||
} else {
|
||||
g.write('new_array_from_c_array${noscan}($len, $len, sizeof($elem_styp), _MOV(($elem_styp[$len]){')
|
||||
g.write('__new_array_with_default${noscan}(')
|
||||
}
|
||||
if len > 8 {
|
||||
g.writeln('')
|
||||
g.write('\t\t')
|
||||
if node.has_len {
|
||||
g.expr(node.len_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
for i, expr in node.exprs {
|
||||
if node.expr_types[i] == ast.string_type && expr !is ast.StringLiteral
|
||||
&& expr !is ast.StringInterLiteral {
|
||||
g.write('string_clone(')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.expr_with_cast(expr, node.expr_types[i], node.elem_type)
|
||||
}
|
||||
if i != len - 1 {
|
||||
if i > 0 && i & 7 == 0 { // i > 0 && i % 8 == 0
|
||||
g.writeln(',')
|
||||
g.write('\t\t')
|
||||
} else {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
if node.has_cap {
|
||||
g.expr(node.cap_expr)
|
||||
g.write(', ')
|
||||
} else {
|
||||
g.write('0, ')
|
||||
}
|
||||
if elem_type.unaliased_sym.kind == .function || g.is_empty_struct(elem_type) {
|
||||
g.write('sizeof(voidptr), ')
|
||||
} else {
|
||||
g.write('sizeof($elem_styp), ')
|
||||
}
|
||||
if is_default_array || is_default_map {
|
||||
g.write('($elem_styp[]){')
|
||||
g.expr(node.default_expr)
|
||||
g.write('}[0])')
|
||||
} else if node.has_default {
|
||||
g.write('&($elem_styp[]){')
|
||||
g.expr_with_cast(node.default_expr, node.default_type, node.elem_type)
|
||||
g.write('})')
|
||||
} else if node.has_len && node.elem_type == ast.string_type {
|
||||
g.write('&($elem_styp[]){')
|
||||
g.write('_SLIT("")')
|
||||
g.write('})')
|
||||
} else if node.has_len && elem_type.unaliased_sym.kind in [.array, .map] {
|
||||
g.write('(voidptr)&($elem_styp[]){')
|
||||
g.write(g.type_default(node.elem_type))
|
||||
g.write('}[0])')
|
||||
} else {
|
||||
g.write('0)')
|
||||
}
|
||||
g.write('}))')
|
||||
if g.is_shared {
|
||||
g.write('}, sizeof($shared_styp))')
|
||||
} else if is_amp {
|
||||
|
|
|
|||
|
|
@ -384,18 +384,18 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
|
|||
clean_interface_v_type_name = util.strip_main_name(clean_interface_v_type_name)
|
||||
fn_builder.writeln('static string indent_${str_fn_name}($styp x, int indent_count) { /* gen_str_for_interface */')
|
||||
for typ in info.types {
|
||||
subtype := g.table.sym(typ)
|
||||
sub_sym := g.table.sym(ast.mktyp(typ))
|
||||
mut func_name := g.get_str_fn(typ)
|
||||
sym_has_str_method, str_method_expects_ptr, _ := subtype.str_method_info()
|
||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sub_sym.str_method_info()
|
||||
if should_use_indent_func(sub_sym.kind) && !sym_has_str_method {
|
||||
func_name = 'indent_$func_name'
|
||||
}
|
||||
|
||||
// str_intp
|
||||
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' }
|
||||
if typ == ast.string_type {
|
||||
mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname'
|
||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
||||
mut val := '${func_name}(${deref}($sub_sym.cname*)x._$sub_sym.cname'
|
||||
if should_use_indent_func(sub_sym.kind) && !sym_has_str_method {
|
||||
val += ', indent_count'
|
||||
}
|
||||
val += ')'
|
||||
|
|
@ -403,11 +403,11 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
|
|||
{_SLIT("${clean_interface_v_type_name}(\'"), $c.si_s_code, {.d_s = $val}},
|
||||
{_SLIT("\')"), 0, {.d_c = 0 }}
|
||||
}))'
|
||||
fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
|
||||
fn_builder.write_string('\tif (x._typ == _${styp}_${sub_sym.cname}_index)')
|
||||
fn_builder.write_string(' return $res;')
|
||||
} else {
|
||||
mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname'
|
||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
||||
mut val := '${func_name}(${deref}($sub_sym.cname*)x._$sub_sym.cname'
|
||||
if should_use_indent_func(sub_sym.kind) && !sym_has_str_method {
|
||||
val += ', indent_count'
|
||||
}
|
||||
val += ')'
|
||||
|
|
@ -415,7 +415,7 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam
|
|||
{_SLIT("${clean_interface_v_type_name}("), $c.si_s_code, {.d_s = $val}},
|
||||
{_SLIT(")"), 0, {.d_c = 0 }}
|
||||
}))'
|
||||
fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
|
||||
fn_builder.write_string('\tif (x._typ == _${styp}_${sub_sym.cname}_index)')
|
||||
fn_builder.write_string(' return $res;\n')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ mut:
|
|||
referenced_fns shared map[string]bool // functions that have been referenced
|
||||
nr_closures int
|
||||
expected_cast_type ast.Type // for match expr of sumtypes
|
||||
or_expr_return_type ast.Type // or { 0, 1 } return type
|
||||
anon_fn bool
|
||||
tests_inited bool
|
||||
has_main bool
|
||||
|
|
@ -858,16 +859,16 @@ pub fn (mut g Gen) write_typeof_functions() {
|
|||
g.definitions.writeln('static char * v_typeof_interface_${sym.cname}(int sidx);')
|
||||
g.writeln('static char * v_typeof_interface_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||
for t in inter_info.types {
|
||||
subtype := g.table.sym(t)
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";')
|
||||
sub_sym := g.table.sym(ast.mktyp(t))
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return "${util.strip_main_name(sub_sym.name)}";')
|
||||
}
|
||||
g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";')
|
||||
g.writeln('}')
|
||||
g.writeln('')
|
||||
g.writeln('static int v_typeof_interface_idx_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||
for t in inter_info.types {
|
||||
subtype := g.table.sym(t)
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return ${int(t)};')
|
||||
sub_sym := g.table.sym(ast.mktyp(t))
|
||||
g.writeln('\tif (sidx == _${sym.cname}_${sub_sym.cname}_index) return ${int(t)};')
|
||||
}
|
||||
g.writeln('\treturn ${int(ityp)};')
|
||||
g.writeln('}')
|
||||
|
|
@ -1318,7 +1319,11 @@ pub fn (mut g Gen) write_interface_typesymbol_declaration(sym ast.TypeSymbol) {
|
|||
g.type_definitions.writeln('\tunion {')
|
||||
g.type_definitions.writeln('\t\tvoid* _object;')
|
||||
for variant in info.types {
|
||||
vcname := g.table.sym(variant).cname
|
||||
mk_typ := ast.mktyp(variant)
|
||||
if mk_typ != variant && mk_typ in info.types {
|
||||
continue
|
||||
}
|
||||
vcname := g.table.sym(mk_typ).cname
|
||||
g.type_definitions.writeln('\t\t$vcname* _$vcname;')
|
||||
}
|
||||
g.type_definitions.writeln('\t};')
|
||||
|
|
@ -2084,11 +2089,11 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||
g.expr(expr)
|
||||
return
|
||||
}
|
||||
if exp_sym.info is ast.Interface && got_type_raw.idx() != expected_type.idx()
|
||||
if exp_sym.info is ast.Interface && got_type.idx() != expected_type.idx()
|
||||
&& !expected_type.has_flag(.optional) {
|
||||
if expr is ast.StructInit && !got_type.is_ptr() {
|
||||
g.inside_cast_in_heap++
|
||||
got_styp := g.cc_type(got_type_raw.ref(), true)
|
||||
got_styp := g.cc_type(got_type.ref(), true)
|
||||
// TODO: why does cc_type even add this in the first place?
|
||||
exp_styp := exp_sym.cname
|
||||
mut fname := 'I_${got_styp}_to_Interface_$exp_styp'
|
||||
|
|
@ -2099,7 +2104,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
|||
got_styp)
|
||||
g.inside_cast_in_heap--
|
||||
} else {
|
||||
got_styp := g.cc_type(got_type_raw, true)
|
||||
got_styp := g.cc_type(got_type, true)
|
||||
got_is_shared := got_type.has_flag(.shared_f)
|
||||
exp_styp := if got_is_shared { '__shared__$exp_sym.cname' } else { exp_sym.cname }
|
||||
// If it's shared, we need to use the other caster:
|
||||
|
|
@ -3864,6 +3869,8 @@ fn (mut g Gen) concat_expr(node ast.ConcatExpr) {
|
|||
mut styp := g.typ(node.return_type)
|
||||
if g.inside_return {
|
||||
styp = g.typ(g.fn_decl.return_type)
|
||||
} else if g.inside_or_block {
|
||||
styp = g.typ(g.or_expr_return_type)
|
||||
}
|
||||
sym := g.table.sym(node.return_type)
|
||||
is_multi := sym.kind == .multi_return
|
||||
|
|
@ -4933,6 +4940,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
|
|||
g.writeln('if (${cvar_name}.state != 0) { /*or block*/ ')
|
||||
}
|
||||
if or_block.kind == .block {
|
||||
g.or_expr_return_type = return_type.clear_flag(.optional)
|
||||
if g.inside_or_block {
|
||||
g.writeln('\terr = ${cvar_name}.err;')
|
||||
} else {
|
||||
|
|
@ -4970,6 +4978,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
|
|||
g.writeln(';')
|
||||
}
|
||||
}
|
||||
g.or_expr_return_type = ast.void_type
|
||||
} else if or_block.kind == .propagate {
|
||||
if g.file.mod.name == 'main' && (isnil(g.fn_decl) || g.fn_decl.is_main) {
|
||||
// In main(), an `opt()?` call is sugar for `opt() or { panic(err) }`
|
||||
|
|
@ -5198,9 +5207,10 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
|||
// Make sure the sum type can be cast to this type (the types
|
||||
// are the same), otherwise panic.
|
||||
// g.insert_before('
|
||||
styp := g.typ(node.typ)
|
||||
sym := g.table.sym(node.typ)
|
||||
mut expr_type_sym := g.table.sym(node.expr_type)
|
||||
unwrapped_node_typ := g.unwrap_generic(node.typ)
|
||||
styp := g.typ(unwrapped_node_typ)
|
||||
sym := g.table.sym(unwrapped_node_typ)
|
||||
mut expr_type_sym := g.table.sym(g.unwrap_generic(node.expr_type))
|
||||
if mut expr_type_sym.info is ast.SumType {
|
||||
dot := if node.expr_type.is_ptr() { '->' } else { '.' }
|
||||
g.write('/* as */ *($styp*)__as_cast(')
|
||||
|
|
@ -5214,9 +5224,8 @@ fn (mut g Gen) as_cast(node ast.AsCast) {
|
|||
g.write(')')
|
||||
g.write(dot)
|
||||
// g.write('typ, /*expected:*/$node.typ)')
|
||||
sidx := g.type_sidx(node.typ)
|
||||
expected_sym := g.table.sym(node.typ)
|
||||
g.write('_typ, $sidx) /*expected idx: $sidx, name: $expected_sym.name */ ')
|
||||
sidx := g.type_sidx(unwrapped_node_typ)
|
||||
g.write('_typ, $sidx) /*expected idx: $sidx, name: $sym.name */ ')
|
||||
|
||||
// fill as cast name table
|
||||
for variant in expr_type_sym.info.variants {
|
||||
|
|
@ -5329,10 +5338,10 @@ fn (mut g Gen) interface_table() string {
|
|||
iinidx_minimum_base := 1000 // Note: NOT 0, to avoid map entries set to 0 later, so `if already_generated_mwrappers[name] > 0 {` works.
|
||||
mut current_iinidx := iinidx_minimum_base
|
||||
for st in inter_info.types {
|
||||
st_sym := g.table.sym(st)
|
||||
st_sym := g.table.sym(ast.mktyp(st))
|
||||
// cctype is the Cleaned Concrete Type name, *without ptr*,
|
||||
// i.e. cctype is always just Cat, not Cat_ptr:
|
||||
cctype := g.cc_type(st, true)
|
||||
cctype := g.cc_type(ast.mktyp(st), true)
|
||||
$if debug_interface_table ? {
|
||||
eprintln('>> interface name: $isym.name | concrete type: $st.debug() | st symname: $st_sym.name')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -401,10 +401,13 @@ pub fn (mut p Parser) parse_type() ast.Type {
|
|||
p.error_with_pos('cannot use `mut` on struct field type', p.tok.pos())
|
||||
}
|
||||
}
|
||||
if p.tok.kind == .key_mut || is_shared || is_atomic {
|
||||
if p.tok.kind == .key_mut || is_shared { // || is_atomic {
|
||||
nr_muls++
|
||||
p.next()
|
||||
}
|
||||
if is_atomic {
|
||||
p.next()
|
||||
}
|
||||
if p.tok.kind == .mul {
|
||||
p.error('use `&Type` instead of `*Type` when declaring references')
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import term
|
||||
import os
|
||||
import runtime
|
||||
import time
|
||||
|
||||
struct App {
|
||||
mut:
|
||||
idx atomic int
|
||||
}
|
||||
|
||||
fn test_atomic() {
|
||||
mut app := &App{}
|
||||
for i in 0 .. 10 {
|
||||
go app.run()
|
||||
}
|
||||
time.sleep(2 * time.second)
|
||||
println('idx=$app.idx')
|
||||
assert app.idx == 10
|
||||
}
|
||||
|
||||
fn (mut app App) run() {
|
||||
app.idx++
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
interface Any {}
|
||||
|
||||
fn thing(any Any) string {
|
||||
return match any {
|
||||
int { 'int${*any:17}' }
|
||||
f64 { 'f64${*any:20}' }
|
||||
else { 'literal type tag?${any:10}' }
|
||||
}
|
||||
}
|
||||
|
||||
fn test_cast_to_empty_interface() {
|
||||
mut ret_strings := []string{}
|
||||
mut arr := [Any(int(11)), int(22), Any(8888), 9999, Any(f64(1.11)), f64(2.22), Any(8.88), 9.99]
|
||||
|
||||
for i in arr {
|
||||
println(thing(i))
|
||||
ret_strings << thing(i)
|
||||
}
|
||||
|
||||
assert ret_strings.len == 8
|
||||
assert ret_strings[0] == 'int 11'
|
||||
assert ret_strings[1] == 'int 22'
|
||||
assert ret_strings[2] == 'int 8888'
|
||||
assert ret_strings[3] == 'int 9999'
|
||||
assert ret_strings[4] == 'f64 1.110'
|
||||
assert ret_strings[5] == 'f64 2.220'
|
||||
assert ret_strings[6] == 'f64 8.880'
|
||||
assert ret_strings[7] == 'f64 9.990'
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
module main
|
||||
|
||||
struct Empty {}
|
||||
|
||||
struct Node<T> {
|
||||
value T
|
||||
mut:
|
||||
next Tree<T>
|
||||
}
|
||||
|
||||
type Tree<T> = Empty | Node<T>
|
||||
|
||||
fn create<T>() Tree<T> {
|
||||
empty := Empty{}
|
||||
mut curr := Node<T>{10, empty}
|
||||
for _ in 0 .. 10 {
|
||||
curr.next = Node<T>{20, empty}
|
||||
}
|
||||
|
||||
return curr
|
||||
}
|
||||
|
||||
fn create_node<T>(args []T) Tree<T> {
|
||||
empty := Empty{}
|
||||
if args.len == 0 {
|
||||
return empty
|
||||
}
|
||||
|
||||
mut curr := Node<T>{args[0], empty}
|
||||
|
||||
for i := 1; i < args.len; i += 1 {
|
||||
curr.next = Node<T>{args[i], empty}
|
||||
curr = curr.next as Node<T>
|
||||
}
|
||||
|
||||
return curr
|
||||
}
|
||||
|
||||
fn merge_nodes<T>(head Tree<T>) Tree<T> {
|
||||
println('$head')
|
||||
|
||||
return Empty{}
|
||||
}
|
||||
|
||||
fn test_generic_sumtype_cast() {
|
||||
node := create_node<int>([0, 3, 1, 0, 4, 5, 2, 0])
|
||||
merge_nodes(node)
|
||||
create<int>()
|
||||
assert true
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
fn multi_return1() ?(int, int) {
|
||||
return 1, 2
|
||||
}
|
||||
|
||||
fn multi_return2() ?(i64, i64) {
|
||||
return 11, 22
|
||||
}
|
||||
|
||||
fn multi_return3() ?(int, i64) {
|
||||
return 11, 22
|
||||
}
|
||||
|
||||
fn test_multi_return_in_or_expr() {
|
||||
a1, b1 := multi_return1() or { 0, -1 }
|
||||
|
||||
println('$a1, $b1')
|
||||
assert a1 == 1
|
||||
assert b1 == 2
|
||||
|
||||
a2, b2 := multi_return2() or { 0, -1 }
|
||||
|
||||
println('$a2, $b2')
|
||||
assert a2 == 11
|
||||
assert b2 == 22
|
||||
|
||||
a3, b3 := multi_return3() or { 0, -1 }
|
||||
|
||||
println('$a3, $b3')
|
||||
assert a3 == 11
|
||||
assert b3 == 22
|
||||
}
|
||||
|
|
@ -59,13 +59,13 @@ pub fn (mut bmp BitMap) clear() {
|
|||
}
|
||||
|
||||
// transform matrix applied to the text
|
||||
fn (bmp &BitMap) trf_txt(p &Point) (int, int) {
|
||||
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
|
||||
fn (bmp &BitMap) trf_ch(p &Point) (int, int) {
|
||||
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])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub struct Text_block {
|
|||
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 {
|
||||
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 {
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -771,7 +771,7 @@ fn (mut tf TTF_File) read_cmap(offset u32) {
|
|||
* CMAPS 0/4
|
||||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) map_code(char_code int) u16 {
|
||||
pub fn (mut tf TTF_File) map_code(char_code int) u16 {
|
||||
mut index := 0
|
||||
for i in 0 .. tf.cmaps.len {
|
||||
mut cmap := tf.cmaps[i]
|
||||
|
|
@ -1006,13 +1006,13 @@ fn (mut tf TTF_File) read_kern_table() {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) reset_kern() {
|
||||
pub fn (mut tf TTF_File) reset_kern() {
|
||||
for i in 0 .. tf.kern.len {
|
||||
tf.kern[i].reset()
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) next_kern(glyph_index int) (int, int) {
|
||||
pub fn (mut tf TTF_File) next_kern(glyph_index int) (int, int) {
|
||||
mut x := 0
|
||||
mut y := 0
|
||||
for i in 0 .. tf.kern.len {
|
||||
|
|
|
|||
Loading…
Reference in New Issue