on master help sign in
Improve space performance of text width functions
d64ff96Jonathan Daugherty
src/Graphics/Text/Width.hs+26−2
@@ -4,15 +4,29 @@
4module Graphics.Text.Width
4module Graphics.Text.Width
5 ( wcwidth
5 ( wcwidth
6 , wcswidth
6 , wcswidth
7+ , wctwidth
8+ , wctlwidth
7 , safeWcwidth
9 , safeWcwidth
8 , safeWcswidth
10 , safeWcswidth
11+ , safeWctwidth
12+ , safeWctlwidth
9 )
13 )
10where
14where
11
15
16+import Data.List (foldl')
17+import qualified Data.Text as T
18+import qualified Data.Text.Lazy as TL
19+
12foreign import ccall unsafe "vty_mk_wcwidth" wcwidth :: Char -> Int
20foreign import ccall unsafe "vty_mk_wcwidth" wcwidth :: Char -> Int
13
21
14wcswidth :: String -> Int
22wcswidth :: String -> Int
15−wcswidth = sum . map wcwidth
23+wcswidth = foldl' (\l c -> wcwidth c + l) 0
24+
25+wctwidth :: T.Text -> Int
26+wctwidth = T.foldl' (\l c -> wcwidth c + l) 0
27+
28+wctlwidth :: TL.Text -> Int
29+wctlwidth = TL.foldl' (\l c -> wcwidth c + l) 0
16
30
17-- XXX: Characters with unknown widths occupy 1 column?
31-- XXX: Characters with unknown widths occupy 1 column?
18--
32--
@@ -30,4 +44,14 @@ safeWcwidth = max 0 . wcwidth
30-- | Returns the display width of a string. Assumes all characters with
44-- | Returns the display width of a string. Assumes all characters with
31-- unknown widths are 0 width.
45-- unknown widths are 0 width.
32safeWcswidth :: String -> Int
46safeWcswidth :: String -> Int
33−safeWcswidth = sum . map safeWcwidth
47+safeWcswidth = foldl' (\l c -> safeWcwidth c + l) 0
48+
49+-- | Returns the display width of a text. Assumes all characters with
50+-- unknown widths are 0 width.
51+safeWctwidth :: T.Text -> Int
52+safeWctwidth = T.foldl' (\l c -> safeWcwidth c + l) 0
53+
54+-- | Returns the display width of a lazy text. Assumes all characters
55+-- with unknown widths are 0 width.
56+safeWctlwidth :: TL.Text -> Int
57+safeWctlwidth = TL.foldl' (\l c -> safeWcwidth c + l) 0
src/Graphics/Vty/Image.hs+6−2
@@ -46,8 +46,12 @@ module Graphics.Vty.Image
46 -- * Character width functions
46 -- * Character width functions
47 , safeWcwidth
47 , safeWcwidth
48 , safeWcswidth
48 , safeWcswidth
49+ , safeWctwidth
50+ , safeWctlwidth
49 , wcwidth
51 , wcwidth
50 , wcswidth
52 , wcswidth
53+ , wctwidth
54+ , wctlwidth
51 -- * Display Regions
55 -- * Display Regions
52 , DisplayText
56 , DisplayText
53 , DisplayRegion
57 , DisplayRegion
@@ -116,13 +120,13 @@ vertCat = foldr vertJoin EmptyImage
116-- | Make an 'Image' from a lazy text value. This function should not be
120-- | Make an 'Image' from a lazy text value. This function should not be
117-- given a text value containing escapes.
121-- given a text value containing escapes.
118text :: Attr -> TL.Text -> Image
122text :: Attr -> TL.Text -> Image
119−text a txt = let displayWidth = safeWcswidth (TL.unpack txt)
123+text a txt = let displayWidth = safeWctlwidth txt
120 in HorizText a txt displayWidth (fromIntegral $! TL.length txt)
124 in HorizText a txt displayWidth (fromIntegral $! TL.length txt)
121
125
122-- | Make an 'Image' from a text value. This function should not be
126-- | Make an 'Image' from a text value. This function should not be
123-- given a text value containing escapes.
127-- given a text value containing escapes.
124text' :: Attr -> T.Text -> Image
128text' :: Attr -> T.Text -> Image
125−text' a txt = let displayWidth = safeWcswidth (T.unpack txt)
129+text' a txt = let displayWidth = safeWctwidth txt
126 in HorizText a (TL.fromStrict txt) displayWidth (T.length txt)
130 in HorizText a (TL.fromStrict txt) displayWidth (T.length txt)
127
131
128-- | Make an image from a single character. This is a standard Haskell
132-- | Make an image from a single character. This is a standard Haskell
src/Graphics/Vty/PictureToSpans.hs+2−1
@@ -13,6 +13,7 @@ import Graphics.Vty.Image
13import Graphics.Vty.Image.Internal
13import Graphics.Vty.Image.Internal
14import Graphics.Vty.Picture
14import Graphics.Vty.Picture
15import Graphics.Vty.Span
15import Graphics.Vty.Span
16+import Graphics.Text.Width (wctlwidth)
16
17
17import Lens.Micro
18import Lens.Micro
18import Lens.Micro.Mtl
19import Lens.Micro.Mtl
@@ -323,7 +324,7 @@ addUnclippedText a txt = do
323 let op = TextSpan a usedDisplayColumns
324 let op = TextSpan a usedDisplayColumns
324 (fromIntegral $ TL.length txt)
325 (fromIntegral $ TL.length txt)
325 txt
326 txt
326− usedDisplayColumns = wcswidth $ TL.unpack txt
327+ usedDisplayColumns = wctlwidth txt
327 use rowOffset >>= snocOp op
328 use rowOffset >>= snocOp op
328
329
329addRowCompletion :: DisplayRegion -> Int -> BlitM s ()
330addRowCompletion :: DisplayRegion -> Int -> BlitM s ()
src/Graphics/Vty/Span.hs+2−2
@@ -14,6 +14,7 @@ module Graphics.Vty.Span where
14import Graphics.Vty.Attributes (Attr)
14import Graphics.Vty.Attributes (Attr)
15import Graphics.Vty.Image
15import Graphics.Vty.Image
16import Graphics.Vty.Image.Internal ( clipText )
16import Graphics.Vty.Image.Internal ( clipText )
17+import Graphics.Text.Width (wctlwidth)
17
18
18import qualified Data.Text.Lazy as TL
19import qualified Data.Text.Lazy as TL
19import Data.Vector (Vector)
20import Data.Vector (Vector)
@@ -126,7 +127,6 @@ spanOpHasWidth (RowEnd ow) = Just (ow,ow)
126-- span op.
127-- span op.
127columnsToCharOffset :: Int -> SpanOp -> Int
128columnsToCharOffset :: Int -> SpanOp -> Int
128columnsToCharOffset cx (TextSpan _ _ _ utf8Str) =
129columnsToCharOffset cx (TextSpan _ _ _ utf8Str) =
129− let str = TL.unpack utf8Str
130+ wctlwidth (TL.take (fromIntegral cx) utf8Str)
130− in wcswidth (take cx str)
131columnsToCharOffset cx (Skip _) = cx
131columnsToCharOffset cx (Skip _) = cx
132columnsToCharOffset cx (RowEnd _) = cx
132columnsToCharOffset cx (RowEnd _) = cx