about summary refs log blame commit diff stats
path: root/src/layout/box.nim
blob: 9812a9cdf107fb0745d2319fb785e7efd0712fc3 (plain) (tree)
1
2
3
4
5
6
7
8
9
                    
                     
                 
                        

    

                            
 


                                            
 

                                        
                        
                                     

                          
                   

                           
               
                  
                      
                         

                  
 
                                   
                               
                   





                                 




                                    



                                             


                            

                   
               
 
                               

                                                                           
                           
 


                                                     
                              
                               

                                
                              



                                    
                                                   





                    
 




                                            
 
                               
                               
                   

                  
                                                
                                         


                                                   
                          



                                                       
 
                        
                               



                                
 




















                                                          
                                    



















                                                      
                                 
                                             
 


                                             


                                      
 



                                      










                                           



                                           
import css/cssvalues
import css/stylednode
import img/bitmap
import layout/layoutunit

type
  DimensionType* = enum
    dtHorizontal, dtVertical

  Offset* = array[DimensionType, LayoutUnit]

  Size* = array[DimensionType, LayoutUnit]

  Overflow* = array[DimensionType, Span]

  InlineAtomType* = enum
    iatWord, iatInlineBlock, iatImage

  InlineAtom* = ref object
    offset*: Offset
    size*: Size
    case t*: InlineAtomType
    of iatWord:
      str*: string
    of iatInlineBlock:
      innerbox*: BlockBox
    of iatImage:
      bmp*: Bitmap

  RootInlineFragmentState* = object
    # offset relative to parent
    offset*: Offset
    # padding size
    size*: Size
    # overflow relative to offset
    overflow*: Overflow
    # minimum content width
    xminwidth*: LayoutUnit
    # baseline of the first line box
    firstBaseline*: LayoutUnit
    # baseline of the last line box
    baseline*: LayoutUnit

  RootInlineFragment* = ref object
    fragment*: InlineFragment # root fragment
    state*: RootInlineFragmentState

  SplitType* = enum
    stSplitStart, stSplitEnd

  Area* = object
    offset*: Offset
    size*: Size

  InlineFragmentState* = object
    startOffset*: Offset # offset of the first word, for position: absolute
    areas*: seq[Area] # background that should be painted by fragment
    atoms*: seq[InlineAtom]

  InlineFragmentType* = enum
    iftParent, iftText, iftNewline, iftBitmap, iftBox

  InlineFragment* = ref object
    state*: InlineFragmentState
    computed*: CSSComputedValues
    node*: StyledNode
    splitType*: set[SplitType]
    case t*: InlineFragmentType
    of iftParent:
      children*: seq[InlineFragment]
    of iftText:
      text*: StyledNode # note: this has no parent.
    of iftNewline:
      discard
    of iftBitmap:
      bmp*: Bitmap
    of iftBox:
      box*: BlockBox

  Span* = object
    start*: LayoutUnit
    send*: LayoutUnit

  RelativeRect* = array[DimensionType, Span]

  BlockBoxLayoutState* = object
    # offset relative to parent
    offset*: Offset
    # padding size
    size*: Size
    margin*: RelativeRect #TODO get rid of this?
    positioned*: RelativeRect #TODO ditto
    # overflow relative to offset
    overflow*: Overflow
    # minimum content width (usually shortest word)
    xminwidth*: LayoutUnit
    # baseline of the first line box of all descendants
    firstBaseline*: LayoutUnit
    # baseline of the last line box of all descendants
    baseline*: LayoutUnit

  BlockBox* = ref object
    state*: BlockBoxLayoutState
    computed*: CSSComputedValues
    node*: StyledNode
    inline*: RootInlineFragment
    nested*: seq[BlockBox]

func offset*(x, y: LayoutUnit): Offset =
  return [dtHorizontal: x, dtVertical: y]

func x*(offset: Offset): LayoutUnit {.inline.} =
  return offset[dtHorizontal]

func x*(offset: var Offset): var LayoutUnit {.inline.} =
  return offset[dtHorizontal]

func `x=`*(offset: var Offset; x: LayoutUnit) {.inline.} =
  offset[dtHorizontal] = x

func y*(offset: Offset): LayoutUnit {.inline.} =
  return offset[dtVertical]

func y*(offset: var Offset): var LayoutUnit {.inline.} =
  return offset[dtVertical]

func `y=`*(offset: var Offset; y: LayoutUnit) {.inline.} =
  offset[dtVertical] = y

func size*(w, h: LayoutUnit): Size =
  return [dtHorizontal: w, dtVertical: h]

func w*(size: Size): LayoutUnit {.inline.} =
  return size[dtHorizontal]

func w*(size: var Size): var LayoutUnit {.inline.} =
  return size[dtHorizontal]

func `w=`*(size: var Size; w: LayoutUnit) {.inline.} =
  size[dtHorizontal] = w

func h*(size: Size): LayoutUnit {.inline.} =
  return size[dtVertical]

func h*(size: var Size): var LayoutUnit {.inline.} =
  return size[dtVertical]

func `h=`*(size: var Size; h: LayoutUnit) {.inline.} =
  size[dtVertical] = h

func `+`*(a, b: Offset): Offset =
  return offset(x = a.x + b.x, y = a.y + b.y)

func `-`*(a, b: Offset): Offset =
  return offset(x = a.x - b.x, y = a.y - b.y)

proc `+=`*(a: var Offset; b: Offset) =
  a.x += b.x
  a.y += b.y

proc `-=`*(a: var Offset; b: Offset) =
  a.x -= b.x
  a.y -= b.y

func left*(s: RelativeRect): LayoutUnit =
  return s[dtHorizontal].start

func right*(s: RelativeRect): LayoutUnit =
  return s[dtHorizontal].send

func top*(s: RelativeRect): LayoutUnit =
  return s[dtVertical].start

func bottom*(s: RelativeRect): LayoutUnit =
  return s[dtVertical].send

proc `+=`*(span: var Span; u: LayoutUnit) =
  span.start += u
  span.send += u