about summary refs log tree commit diff stats
path: root/src/utils
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-03 23:10:44 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-03 23:18:25 +0100
commit15d5ad451bdc456e80e7468a76fb2eac6feb4a4e (patch)
tree941481cc2795e1dd191b928737a323362e298b16 /src/utils
parentfb04a7e96ff68b4516ea483ca4fbe9c4976bb7d2 (diff)
downloadchawan-15d5ad451bdc456e80e7468a76fb2eac6feb4a4e.tar.gz
strwidth, renderdocument: small refactoring
* put attrs pointer in state
* simplify width()
* use unsigned int as ptint to avoid UB
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/proptable.nim14
-rw-r--r--src/utils/strwidth.nim57
2 files changed, 26 insertions, 45 deletions
diff --git a/src/utils/proptable.nim b/src/utils/proptable.nim
index a34459a8..0087dd80 100644
--- a/src/utils/proptable.nim
+++ b/src/utils/proptable.nim
@@ -1,12 +1,10 @@
-import std/unicode
-
 # Lookup tables for characters on the BMP. This "only" takes up 8k of space
 # per table, as opposed to the 135k that storing all characters would require.
 # The downside is obviously that we need a binary search fallback for non-bmp.
 # We do not store a lookup table of ambiguous ranges, either.
 
 type
-  ptint* = int32
+  ptint* = uint32
   PropertyTable* = array[0x10000 div (sizeof(ptint) * 8), ptint]
   RangeMap* = openArray[(uint32, uint32)]
 
@@ -32,9 +30,9 @@ func makePropertyTable*(ranges: RangeMap, skip: RangeMap = @[]): PropertyTable =
     inc ucs
 
 {.push boundChecks:off.}
-func contains*(props: PropertyTable, r: Rune): bool =
-  let u = ptint(r)
-  let i = u div (sizeof(ptint) * 8)
-  let m = u mod (sizeof(ptint) * 8)
-  return (props[i] and (1 shl m)) != 0
+func contains*(props: PropertyTable, u: ptint): bool {.inline.} =
+  const isz = sizeof(ptint) * 8
+  let i = u div isz
+  let m = u mod isz
+  return (props[i] and (1u32 shl m)) != 0
 {.pop.}
diff --git a/src/utils/strwidth.nim b/src/utils/strwidth.nim
index 5ce2ba52..9cb115cc 100644
--- a/src/utils/strwidth.nim
+++ b/src/utils/strwidth.nim
@@ -7,48 +7,31 @@ import utils/map
 
 include res/map/charwidth_gen
 
-func isDoubleWidthHigh(r: Rune): bool =
-  return DoubleWidthRanges.isInRange(uint32(r))
-
-func isDoubleWidthAmbiguousHigh(r: Rune): bool =
-  # binary search in table of non-spacing characters
-  if DoubleWidthAmbiguousRanges.isInRange(uint32(r)):
-    return true
-  return r.isDoubleWidthHigh()
-
-func isCombining(r: Rune): bool =
-  return Combining.isInRange(uint32(r))
-
 # One of the few global variables in the code. Honestly, it should not exist.
-var is_cjk_ambiguous = false
+var isCJKAmbiguous = false
 proc set_cjk_ambiguous*(b: bool) =
-  is_cjk_ambiguous = b
+  isCJKAmbiguous = b
 
 # Warning: this shouldn't be called without normalization.
-# We could make this function more efficient in edge cases, but it's already
-# too complex for my taste.
 func width*(r: Rune): int =
-  {.cast(noSideEffect).}:
-    let u = uint32(r)
-    if u <= 0xFFFF:
-      if r in CombiningTable:
-        return 0
-      if not is_cjk_ambiguous:
-        if r in DoubleWidthTable:
-          return 2
-      else:
-        if r in DoubleWidthTable or DoubleWidthAmbiguousRanges.isInRange(u):
-          return 2
-    else:
-      if r.isCombining():
-        return 0
-      if not is_cjk_ambiguous:
-        if r.isDoubleWidthHigh():
-          return 2
-      else:
-        if r.isDoubleWidthAmbiguousHigh():
-          return 2
-    return 1
+  let u = uint32(r)
+  if u <= 0xFFFF: # fast path for BMP
+    if u in CombiningTable:
+      return 0
+    if u in DoubleWidthTable:
+      return 2
+    {.cast(noSideEffect).}:
+      if isCJKAmbiguous and DoubleWidthAmbiguousRanges.isInRange(u):
+        return 2
+  else:
+    if Combining.isInRange(u):
+      return 0
+    if DoubleWidthRanges.isInRange(u):
+      return 2
+    {.cast(noSideEffect).}:
+      if isCJKAmbiguous and DoubleWidthAmbiguousRanges.isInRange(u):
+        return 2
+  return 1
 
 # Width, but also works with tabs.
 # Needs the column width of the text so far.