ludic/packages/ludic.ui/draw_content.ludic

72 lines
3.1 KiB
Text

# draw_content.ludic - what is inside a box drawn: a text's lines, placed by text-align, each over its
# text-shadow, and a picture
# a text's lines (one, or the wrapped ones), each placed by text-align, the last cut by an ellipsis
function fr_text(ui_st: mut UiState, n: UiNode) -> void {
let lh = ly_line_h(n)
let y = n.y + n.pt + n.bt + (lh - n.rsize * 1.25) / 2.0
let a = n.rfg_a * ui_st.fr_ga
let sh = fr_text_shadow(n)
if n.lines == null {
var s = tf_fit(ui_st, n, n.text)
if n.ellipsis { s = ly_ellipsis(ui_st, s, ui_st.tf_size, n.cw - ly_hin(n)) }
fr_line(ui_st, n, sh, fr_line_x(ui_st, n, s, ui_st.tf_size), y, s, a, ui_st.tf_size)
return
}
for i in 0 .. len(n.lines) { fr_line(ui_st, n, sh, fr_line_x(ui_st, n, n.lines[i], n.rsize), y + float(i) * lh, n.lines[i], a, n.rsize) }
}
# one line, over its shadow when it has one
function fr_line(ui_st: UiState, n: UiNode, sh: UiNodeX, x: float, y: float, s: string, a: float, size: float) -> void {
if sh != null { ui_st.ui_be.text(x + sh.tsh_x, y + sh.tsh_y, s, size, sh.tsh_c, sh.tsh_a * ui_st.fr_ga) }
ui_st.ui_be.text(x, y, s, size, n.rfg, a)
}
# text-shadow is inherited: the nearest element that says it, or null (none)
function fr_text_shadow(n: UiNode) -> UiNodeX {
var at = n
while at != null {
if at.ex != null and at.ex.tsh_set {
if at.ex.tsh_c < 0 { return null }
return at.ex
}
at = at.parent
}
return null
}
# the opacity a native's draw is at: every group opacity around it, its own included
export function ui_opacity(ui_st: UiState) -> float { return ui_st.fr_ga }
# where a line starts: text-align within the room the box gives it
function fr_line_x(ui_st: UiState, n: UiNode, s: string, size: float) -> float {
let x = n.x + n.pl + n.bl
if n.talign == UI_START { return x }
let spare = n.cw - ly_hin(n) - ly_text_w(ui_st, s, size)
if n.talign == UI_CENTER { return x + spare / 2.0 }
return x + spare
}
# an <img>: a picture file drawn as it is, as a browser draws one (unless the img sets its own
# color); a cell of an atlas ("icon:tent") is a glyph, and takes the color around it as text does
function fr_image(ui_st: mut UiState, n: UiNode) -> void {
var c = 16777215
var a = ui_st.fr_ga
if n.fg != UI_INHERIT or fr_is_cell(n.src) {
c = n.rfg
a = ui_st.fr_ga * n.rfg_a
}
var nat_w = 0.0
var nat_h = 0.0
if ui_st.ui_be.image_w != null and ui_st.ui_be.image_h != null {
nat_w = ui_st.ui_be.image_w(n.src)
nat_h = ui_st.ui_be.image_h(n.src)
}
let r = ui_object_fit_into(ui_st.fit_out, n, nat_w, nat_h)
let clipped = ui_st.ui_be.clip != null and (r[2] > n.cw - ly_hin(n) or r[3] > n.ch - ly_vin(n))
if clipped { fr_clip_push(ui_st, n.x + n.pl + n.bl, n.y + n.pt + n.bt, n.cw - ly_hin(n), n.ch - ly_vin(n)) }
ui_st.ui_be.image(n.src, r[0], r[1], r[2], r[3], c, a)
if clipped { fr_clip_pop(ui_st) }
}
# prefix:name, and not a path (C:/... is a drive, not an atlas)
function fr_is_cell(src: string) -> bool {
for i in 0 .. len(src) {
if src[i] == 47 or src[i] == 92 { return false }
if src[i] == 58 { return i > 1 }
}
return false
}