Patch title: Release 94 bulk changes
Abstract:
File: /pliant/graphic/browser/naive/tag/text.pli
Key:
    Removed line
    Added line
   
module "/pliant/language/compiler.pli"
module "/pliant/language/stream.pli"
module "/pliant/graphic/browser/naive/core.pli"
module "/pliant/language/type/text/str32.pli"
module "/pliant/util/encoding/utf8.pli"
module "/pliant/graphic/vector/font.pli"
module "/pliant/math/transform.pli"
module "/pliant/graphic/misc/float.pli"
module "/pliant/math/curve.pli"

constant debug false


type TextArea
  field Int offset
  field BrowserArea2 area

function set_kerning a t kerning
  arg BrowserArea2 a ; arg Str32 t ; arg_w Address kerning
  kerning := null
  if a:space_extra_spacing<>0
    kerning := memory_allocate t:len*Float:size null
    for (var Int j) 0 t:len-1
      kerning map Float j := shunt j>0 and (t j-1)=" " a:space_extra_spacing 0.0
  
function drop_kerning kerning
  arg Address kerning
  if kerning<>null
    memory_free kerning

browser_tag_position text
  var Str32 text := utf8_decode attribute:""
  if (font "font" text (var Link:Font font) (var Float scale) (var Int color))=failure
    return
  var CBool tt := (query "para" "fold")="false"
  part control
    if (text search "[lf]" text:len-1)=text:len-1
      font bbox text null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
      if bx1-bx0<=area_x1-line_x or tt
        extra := memory_resize extra BrowserArea2:size addressof:node
        (extra map BrowserArea2) setup bx0 by0 bx1 by1
        addtoline node:area line_extend+line_adjust font scale text
        if query:"center"
          line_flags := line_flags .or. line_align_center
        if text:len>0 and (text text:len-1)="[lf]"
          newline false
        return
    area ; var Int n := 0
    var Int start := 0
    while start<text:len
      var Int stop
      if tt
        stop := start+((text start text:len) search "[lf]" text:len-start-1)+1
      else
        stop := start
        part cut
          var Int i := stop
          while i<text:len and text:i<>" " and text:i<>"[lf]"
            i += 1
          var Str32 t := text start i-start
          font bbox t null bx0 by0 bx1 by1 ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
          if bx1-bx0>area_x1-line_x
            leave cut
          if i<text:len and text:i="[lf]"
            stop := i+1 ; leave cut
          while i<text:len and text:i=" "
            i += 1
          stop := i
          if stop<text:len
            restart cut
        if stop=start
          if start=0 and line_x<>area_x0
            newline true
            restart control
          eif start=0
            var Str32 t := utf8_decode attribute:""
            font bbox t null bx0 by0 bx1 by1 ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
            extra := memory_resize extra BrowserArea2:size addressof:node
            (extra map BrowserArea2) setup bx0 by0 bx1 by1
            addtoline node:area line_extend+line_adjust font scale t
            return
          else
            stop := text len
      extra := memory_resize extra BrowserArea2:size+(n+1)*TextArea:size addressof:node
      var Pointer:TextArea a :> (extra translate BrowserArea2 1) map TextArea n
      a offset := stop
      var Str32 t := text start stop-start
      font bbox t null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
      a:area setup bx0 by0 bx1 by1
      addtoline ((addressof a:area) map BrowserArea) line_extend+line_adjust font scale t
      if query:"center"
        line_flags := line_flags .or. line_align_center
      if stop<text:len or stop>0 and (text stop-1)="[lf]"
        newline stop=0 or (text stop-1)<>"[lf]"
      start := stop
      n += 1
  area x0 := float_max
  area y0 := float_max
  area x1 := float_min
  area y1 := float_min
  for (var Int i) 0 n-1
    var Pointer:TextArea a :> (extra translate BrowserArea2 1) map TextArea i
    area x0 := min area:x0 a:area:x0
    area y0 := min area:y0 a:area:y0
    area x1 := max area:x1 a:area:x1
    area y1 := max area:y1 a:area:y1
  for (var Int i) 0 n-1
    var Pointer:TextArea a :> (extra translate BrowserArea2 1) map TextArea i
    a:area x0 -= area x0
    a:area y0 -= area y0
    a:area x1 -= area x0
    a:area y1 -= area y0

browser_tag_draw text
  if node:extra=null
    void
  eif { var Int n := (memory_size:extra-BrowserArea2:size)\TextArea:size ; n=0 }
    if (font "font" attribute:"" (var Link:Font font) (var Float scale) (var Int color))=failure
      return
    var Str32 text := utf8_decode attribute:""
    if debug
      var Int c := 0FF0000h ; rectangle area:x0 area:y0 area:x1 area:y1 addressof:c
      var Int c := 0FFFFFFh ; rectangle area:x0+0.3 area:y0+0.3 area:x1-0.3 area:y1-0.3 addressof:c
    set_kerning (addressof:area map BrowserArea2) text (var Address kerning)
    font bbox text null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
    text text font kerning (transform area:x0-bx0 area:y0-by0 scale scale 0 0) addressof:color
    drop_kerning kerning
  else
    if debug
      var Int c := 0FFh ; rectangle area:x0 area:y0 area:x0+1 area:y0+1 addressof:c
    if (font "font" attribute:"" (var Link:Font font) (var Float scale) (var Int color))=failure
      return
    var Str32 text := utf8_decode attribute:""
    var Int start := 0
    for (var Int i) 0 n-1
      var Pointer:TextArea a :> (extra translate BrowserArea2 1) map TextArea i
      if debug
        var Int c := 0FF0000h ; rectangle area:x0+a:area:x0 area:y0+a:area:y0 area:x0+a:area:x1 area:y0+a:area:y1 addressof:c
        var Int c := 0FFFFFFh ; rectangle area:x0+a:area:x0+0.3 area:y0+a:area:y0+0.3 area:x0+a:area:x1-0.3 area:y0+a:area:y1-0.3 addressof:c
      var Int stop := a offset
      var Str32 t := text start stop-start
      set_kerning a:area t (var Address kerning)
      font bbox t null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
      text t font kerning (transform area:x0+a:area:x0-bx0 area:y0+a:area:y0-by0 scale scale 0 0) addressof:color
      drop_kerning kerning
      start := stop
  draw_recurse node
  focus_draw node font:vector

browser_tag_split text
  if node:extra=null
    void
  eif { var Int n := (memory_size:extra-BrowserArea2:size)\TextArea:size ; n=0 }
    if (font "font" attribute:"" (var Link:Font font) (var Float scale) (var Int color))=failure
      return
    var Str32 text := utf8_decode attribute:""
    set_kerning (addressof:area map BrowserArea2) text (var Address kerning)
    font bbox text null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
    var Vector2 v := vector area:x0-bx0 area:y0-by0
    boxes size := text len
    for (var Int i) 0 text:len-1
      if kerning<>null
        v x += (kerning map Float i)*scale*font:vector:x ; v y += (kerning map Float i)*scale*font:vector:y
      font bbox (text i 1) null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
      var Pointer:BrowserArea ba :> boxes i ; ba x0 := bx0+v:x ; ba y0 := by0+v:y ; ba x1 := bx1+v:x ; ba y1 := by1+v:y
      if extend and i=text:len-1
        if font:vector:x>0
          ba x1 := max ba:x1 area:x1
      var Vector2 w := font vector (text i 1) null
      v x += scale*w:x ; v y += scale*w:y
    drop_kerning kerning
    if extend and boxes:size=0
      boxes += area
  else
    if (font "font" attribute:"" (var Link:Font font) (var Float scale) (var Int color))=failure
      return
    var Str32 text := utf8_decode attribute:""
    boxes size := text len
    var Int start := 0
    for (var Int i) 0 n-1
      var Pointer:TextArea a :> (extra translate BrowserArea2 1) map TextArea i
      var Int stop := a offset
      var Str32 t := text start stop-start
      set_kerning a:area t (var Address kerning)
      font bbox t null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
      var Vector2 v := vector area:x0+a:area:x0-bx0 area:y0+a:area:y0-by0
      for (var Int j) 0 t:len-1
        if kerning<>null
          v x += (kerning map Float j)*scale*font:vector:x ; v y += (kerning map Float j)*scale*font:vector:y
        font bbox (t j 1) null (var Float bx0) (var Float by0) (var Float bx1) (var Float by1) ; bx0 *= scale ; by0 *= scale ; bx1 *= scale ; by1 *= scale
        var Pointer:BrowserArea ba :> boxes start+j ; ba x0 := bx0+v:x ; ba y0 := by0+v:y ; ba x1 := bx1+v:x ; ba y1 := by1+v:y
        if extend and j=t:len-1
          if font:vector:x>0
            ba x1 := max ba:x1 area:x0+a:area:x1
        var Vector2 w := font vector (t j 1) null
        v x += scale*w:x ; v y += scale*w:y
      drop_kerning kerning
      start := stop
  if (query "text" "h_extend")<>"" or (query "text" "v_extend")<>"" 
    boxes += area

browser_tag_event text
  if event<>"focus" or key<>"set"
    event_auto_focus node
  event_auto_target node


browser_tag_position eol
  if not ((query "eol" "spacing") parse (var Float spacing))
    spacing := 6/72*25.4
  if line_x=area_x0
    area_y0 += spacing
  newline false


browser_tag_position para
  if not ((query "para" "spacing") parse (var Float spacing))
    spacing := 6/72*25.4
  area_y0 += spacing
  newline false
  each sub node
    position sub
  area_y0 += spacing
  newline false


browser_tag_position section
  position_recurse node
  position_container node