optimized VStyle representation
This commit is contained in:
parent
74c07f0634
commit
4bfe66edd6
2 changed files with 72 additions and 32 deletions
|
|
@ -11,3 +11,12 @@ proc contains*[K, V](d: JDict[K, V], k: K): bool {.importcpp: "#.hasOwnProperty(
|
||||||
|
|
||||||
proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".}
|
proc del*[K, V](d: JDict[K, V], k: K) {.importcpp: "delete #[#]".}
|
||||||
|
|
||||||
|
type
|
||||||
|
JSeq*[T] = ref object
|
||||||
|
|
||||||
|
proc `[]`*[T](s: JSeq[T], i: int): T {.importcpp: "#[#]", noSideEffect.}
|
||||||
|
proc `[]=`*[T](s: JSeq[T], i: int, v: T) {.importcpp: "#[#] = #", noSideEffect.}
|
||||||
|
|
||||||
|
proc newJSeq*[T](): JSeq[T] {.importcpp: "[@]".}
|
||||||
|
proc len*[T](s: JSeq[T]): int {.importcpp: "#.length", noSideEffect.}
|
||||||
|
proc add*[T](s: JSeq[T]; x: T) {.importcpp: "#.push(#)", noSideEffect.}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import kdom, macros
|
import kdom, macros, jdict
|
||||||
|
|
||||||
type
|
type
|
||||||
StyleAttr* {.pure.} = enum
|
StyleAttr* {.pure.} = enum
|
||||||
|
|
@ -208,62 +208,93 @@ macro buildLookupTables(): untyped =
|
||||||
|
|
||||||
buildLookupTables()
|
buildLookupTables()
|
||||||
|
|
||||||
type
|
# I optimized the heck out of this representation since profiling showed
|
||||||
VStyle* = ref object
|
# it's relevant.
|
||||||
attrs: array[StyleAttr, cstring]
|
# even index: key, odd index: value; done this way for memory efficiency:
|
||||||
mask: set[StyleAttr]
|
|
||||||
|
|
||||||
proc kout[T](x: T) {.importc: "console.log", varargs.}
|
type
|
||||||
|
VStyle* = JSeq[cstring]
|
||||||
|
|
||||||
proc eq*(a, b: VStyle): bool =
|
proc eq*(a, b: VStyle): bool =
|
||||||
if a.isNil:
|
if a.isNil:
|
||||||
if b.isNil: return true
|
if b.isNil: return true
|
||||||
else: return false
|
else: return false
|
||||||
elif b.isNil: return false
|
elif b.isNil: return false
|
||||||
if a.mask != b.mask: return false
|
if a.len != b.len: return false
|
||||||
for x in a.mask:
|
for i in 0..<a.len:
|
||||||
if a.attrs[x] != b.attrs[x]: return false
|
if a[i] != b[i]: return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc setAttr*(s: VStyle; attr: StyleAttr, value: cstring) =
|
proc kout[T](x: T) {.importc: "console.log", varargs.}
|
||||||
|
|
||||||
|
proc setAttr(s: VStyle; a, value: cstring) {.noSideEffect.} =
|
||||||
|
var i = 0
|
||||||
|
while i < s.len:
|
||||||
|
if s[i] == a:
|
||||||
|
s[i+1] = value
|
||||||
|
return
|
||||||
|
elif s[i] > a:
|
||||||
|
s.add nil
|
||||||
|
s.add nil
|
||||||
|
# insertion point here:
|
||||||
|
for j in countdown(s.len-1, i, 2):
|
||||||
|
s[j] = s[j-2]
|
||||||
|
s[j-1] = s[j-3]
|
||||||
|
s[i] = a
|
||||||
|
s[i+1] = value
|
||||||
|
return
|
||||||
|
inc i, 2
|
||||||
|
s.add a
|
||||||
|
s.add value
|
||||||
|
|
||||||
|
proc setAttr*(s: VStyle; attr: StyleAttr, value: cstring) {.noSideEffect.} =
|
||||||
assert value != nil, "value must not be nil"
|
assert value != nil, "value must not be nil"
|
||||||
s.attrs[attr] = value
|
setAttr(s, toStyleAttrName[attr], value)
|
||||||
incl(s.mask, attr)
|
|
||||||
|
|
||||||
proc getAttr*(s: VStyle; attr: StyleAttr): cstring =
|
proc getAttr*(s: VStyle; attr: StyleAttr): cstring {.noSideEffect.} =
|
||||||
## returns 'nil' if the attribute has not been set.
|
## returns 'nil' if the attribute has not been set.
|
||||||
result = s.attrs[attr]
|
var i = 0
|
||||||
|
let a = toStyleAttrName[attr]
|
||||||
|
while i < s.len:
|
||||||
|
if s[i] == a:
|
||||||
|
return s[i+1]
|
||||||
|
elif s[i] > a:
|
||||||
|
return nil
|
||||||
|
inc i, 2
|
||||||
|
|
||||||
proc style*(pairs: varargs[(StyleAttr, cstring)]): VStyle =
|
proc style*(pairs: varargs[(StyleAttr, cstring)]): VStyle {.noSideEffect.} =
|
||||||
## constructs a VStyle object from a list of (attribute, value)-pairs.
|
## constructs a VStyle object from a list of (attribute, value)-pairs.
|
||||||
result = VStyle(mask: {})
|
result = newJSeq[cstring]()
|
||||||
for x in pairs:
|
for x in pairs:
|
||||||
result.setAttr x[0], x[1]
|
result.setAttr x[0], x[1]
|
||||||
|
|
||||||
proc style*(a: StyleAttr; val: cstring): VStyle =
|
proc style*(a: StyleAttr; val: cstring): VStyle {.noSideEffect.} =
|
||||||
## constructs a VStyle object from a single (attribute, value)-pair.
|
## constructs a VStyle object from a single (attribute, value)-pair.
|
||||||
result = VStyle(mask: {})
|
result = newJSeq[cstring]()
|
||||||
result.setAttr a, val
|
result.setAttr a, val
|
||||||
|
|
||||||
proc setStyle(d: Style; key, val: cstring) {.importcpp: "#[#] = #".}
|
proc setStyle(d: Style; key, val: cstring) {.importcpp: "#[#] = #", noSideEffect.}
|
||||||
|
|
||||||
proc merge*(a, b: VStyle): VStyle =
|
proc merge*(a, b: VStyle): VStyle {.noSideEffect.} =
|
||||||
## merges two styles. ``b`` takes precedence over ``a``.
|
## merges two styles. ``b`` takes precedence over ``a``.
|
||||||
result = VStyle(mask: {})
|
result = newJSeq[cstring]()
|
||||||
for i in low(StyleAttr)..high(StyleAttr):
|
for i in 0..<a.len:
|
||||||
result.attrs[i] = if b.attrs[i].isNil: a.attrs[i] else: b.attrs[i]
|
result.add a[i]
|
||||||
if result.attrs[i] != nil: incl(result.mask, i)
|
for i in countup(0, b.len-1, 2):
|
||||||
|
setAttr(result, b[i], b[i+1])
|
||||||
|
|
||||||
proc applyStyle*(n: Node; s: VStyle) =
|
proc applyStyle*(n: Node; s: VStyle) {.noSideEffect.} =
|
||||||
## apply the style to the real DOM node ``n``.
|
## apply the style to the real DOM node ``n``.
|
||||||
n.style = Style()
|
|
||||||
for x in s.mask:
|
|
||||||
n.style.setStyle(toStyleAttrName[x], s.attrs[x])
|
|
||||||
|
|
||||||
iterator pairs*(v: VStyle): (cstring, cstring) =
|
#n.style = Style() # optimized, this is a hotspot:
|
||||||
if v != nil:
|
{.emit: "`n`.style = {};".}
|
||||||
for x in v.mask:
|
for i in countup(0, s.len-1, 2):
|
||||||
yield (toStyleAttrName[x], v.attrs[x])
|
n.style.setStyle(s[i], s[i+1])
|
||||||
|
|
||||||
|
iterator pairs*(s: VStyle): (cstring, cstring) {.noSideEffect.} =
|
||||||
|
if s != nil:
|
||||||
|
for i in countup(0, s.len-1, 2):
|
||||||
|
yield (s[i], s[i+1])
|
||||||
|
|
||||||
import jstrutils
|
import jstrutils
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue