~alcinnz/CatTrap

ref: 79c5cd4691c26d69867eee511802d356352aefd9 CatTrap/Graphics/Layout/Inline/CSS.hs -rw-r--r-- 4.7 KiB
79c5cd46 — Adrian Cochrane Implement unicode-bidi-property, attempted. Doesn't handle tree. 1 year, 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
{-# LANGUAGE OverloadedStrings, ViewPatterns #-}
-- | Infrastructure for parsing & desugaring text related CSS properties.
module Graphics.Layout.Inline.CSS(CSSInline(..), applyFontInline, applyBidi) where

import Data.CSS.Syntax.Tokens (Token(..))
import Stylist (PropertyParser(..))
import qualified Data.Text as Txt
import Data.Text (Text, cons, snoc)
import Data.Text.ParagraphLayout.Rich
import Data.Text.Glyphize (Direction(..))

import Graphics.Layout.CSS.Font (Font'(..), hbUnit)
import Data.Char (isSpace)
import Debug.Trace (trace) -- To report unexpected cases.

-- | Document text with Balkón styling options, CSS stylable.
data CSSInline = CSSInline Txt.Text TextOptions UnicodeBidi
-- | To what degree is the text direction isolated?
data UnicodeBidi = BdNormal | BdEmbed | BdOverride | BdIsolate
        | BdIsolateOverride | BdPlainText deriving (Eq, Ord, Enum, Read, Show)

instance PropertyParser CSSInline where
    temp = CSSInline "" (defaultTextOptions DirLTR) BdNormal
    inherit (CSSInline _ opts _) = CSSInline "" opts BdNormal
    priority _ = ["direction"] -- To inform logical spacing in caller!

    longhand _ (CSSInline _ opts bidi) "content" [Ident "initial"] =
        Just $ CSSInline "" opts bidi
    longhand _ (CSSInline _ opts bidi) "content" toks
        | all isString toks =
            Just $ CSSInline (Txt.concat [x | String x <- toks]) opts bidi
      where
        isString (String _) = True
        isString _ = False

    longhand _ (CSSInline t o b) "-argo-lang" [Ident kw]
        | kw `elem` ["initial", "auto"] = Just $ CSSInline t o {textLanguage=""} b
    longhand _ (CSSInline txt opts bidi) "-argo-lang" [String x] =
        Just $ CSSInline txt opts { textLanguage = Txt.unpack x } bidi

    longhand _ (CSSInline txt opts bidi) "direction" [Ident "ltr"] =
        Just $ CSSInline txt opts { textDirection = DirLTR } bidi
    longhand _ (CSSInline txt opts bidi) "direction" [Ident "rtl"] =
        Just $ CSSInline txt opts { textDirection = DirRTL } bidi
    longhand _ (CSSInline txt opts bidi) "direction" [Ident "initial"] =
        Just $ CSSInline txt opts { textDirection = DirLTR } bidi

    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "initial"] =
        Just $ CSSInline txt opts BdNormal
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "normal"] =
        Just $ CSSInline txt opts BdNormal
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "embed"] =
        Just $ CSSInline txt opts BdEmbed
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "isolate"] =
        Just $ CSSInline txt opts BdIsolate
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "bidi-override"] =
        Just $ CSSInline txt opts BdOverride
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "isolate-override"] =
        Just $ CSSInline txt opts BdIsolateOverride
    longhand _ (CSSInline txt opts _) "unicode-bidi" [Ident "plaintext"] =
        Just $ CSSInline txt opts BdPlainText
    longhand _ _ _ _ = Nothing

applyFontInline :: TextOptions -> Font' -> TextOptions
applyFontInline opts font = opts {
    textFont = hbFont font,
    textLineHeight = Absolute $ toEnum $ fromEnum $ lineheight font * hbUnit
  }
-- | Apply Bidi chars around the inline text. FIXME: Handle the tree!
applyBidi :: CSSInline -> Text
applyBidi (CSSInline txt _ BdNormal) = txt
applyBidi (CSSInline txt (textDirection -> DirLTR) BdEmbed) =
    chLREmbed `cons` txt `snoc` chPopDir
applyBidi (CSSInline txt (textDirection -> DirRTL) BdEmbed) =
    chRLEmbed `cons` txt `snoc` chPopDir
applyBidi (CSSInline txt (textDirection -> DirLTR) BdIsolate) =
    chLRIsolate `cons` txt `snoc` chPopDirIsolate
applyBidi (CSSInline txt (textDirection -> DirRTL) BdIsolate) =
    chRLIsolate `cons` txt `snoc` chPopDirIsolate
applyBidi (CSSInline txt (textDirection -> DirLTR) BdOverride) =
    chLROverride `cons` txt `snoc` chPopDir
applyBidi (CSSInline txt (textDirection -> DirRTL) BdOverride) =
    chRLOverride `cons` txt `snoc` chPopDir
applyBidi (CSSInline txt (textDirection -> DirLTR) BdIsolateOverride) =
    ch1stStrongIsolate `cons` chLROverride `cons` txt
        `snoc` chPopDir `snoc` chPopDirIsolate
applyBidi (CSSInline txt (textDirection -> DirRTL) BdIsolateOverride) =
    ch1stStrongIsolate `cons` chRLOverride `cons` txt
        `snoc` chPopDir `snoc` chPopDirIsolate
applyBidi (CSSInline txt _ BdPlainText) =
    ch1stStrongIsolate `cons` txt `snoc` chPopDirIsolate
applyBidi (CSSInline txt (textDirection -> dir) _) =
    trace ("Unexpected direction! " ++ show dir) txt

chLREmbed = '\x202A'
chRLEmbed = '\x202B'
chLROverride = '\x202D'
chRLOverride = '\x202E'
chPopDir = '\x202C'
chLRIsolate = '\x2066'
chRLIsolate = '\x2067'
ch1stStrongIsolate = '\x2068'
chPopDirIsolate = '\x2069'