Implementation of AXIsolatedObject::setSelectedVisiblePositionRange.
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / mathml / tools / operator-dictionary.py
1 #!/usr/bin/python
2
3 from lxml import etree
4 from utils.misc import downloadWithProgressBar, UnicodeXMLURL, InlineAxisOperatorsURL
5 import json, re
6 from utils import mathfont
7
8 NonBreakingSpace = 0x00A0
9
10 def parseHexaNumber(string):
11     return int("0x%s" % string, 16)
12
13 def parseHexaSequence(string):
14     return tuple(map(parseHexaNumber, string[1:].split("-")))
15
16 def parseSpaces(value, entry, names):
17     for name in names:
18         attributeValue = entry.get(name)
19         if attributeValue is not None:
20             value[name] = int(attributeValue)
21
22 def parseProperties(value, entry, names):
23     attributeValue = entry.get("properties")
24     if attributeValue is not None:
25         for name in names:
26             if attributeValue.find(name) >= 0:
27                 value[name] = True
28
29 def buildKeyAndValueFrom(characters, form):
30     # Concatenate characters and form to build the key.
31     key = ""
32     for c in characters:
33         key += unichr(c)
34     key += " " + form
35     # But save characters as an individual property for easier manipulation in
36     # this Python script.
37     value = {
38         "characters": characters,
39     }
40     return key, value
41
42 def createSizeVariants(aFont):
43     for size in (0, 1, 2, 3):
44         g = aFont.createChar(-1, "v%d" % size)
45         mathfont.drawRectangleGlyph(g, mathfont.em, (size + 1) * mathfont.em, 0)
46         g = aFont.createChar(-1, "h%d" % size)
47         mathfont.drawRectangleGlyph(g, (size + 1) * mathfont.em, mathfont.em, 0)
48
49 def createStretchy(aFont, codePoint, isHorizontal):
50     if isHorizontal:
51         aFont[codePoint].horizontalVariants = "h0 h1 h2 h3"
52         aFont[codePoint].horizontalComponents = \
53             (("h2", False, 0, mathfont.em, 3 * mathfont.em), \
54              ("h1", True, mathfont.em, mathfont.em, 2 * mathfont.em))
55     else:
56         aFont[codePoint].verticalVariants = "v0 v1 v2 v3"
57         aFont[codePoint].verticalComponents = \
58             (("v2", False, 0, mathfont.em, 3 * mathfont.em), \
59              ("v1", True, mathfont.em, mathfont.em, 2 * mathfont.em))
60
61 # Retrieve the spec files.
62 inlineAxisOperatorsTXT = downloadWithProgressBar(InlineAxisOperatorsURL)
63 unicodeXML = downloadWithProgressBar(UnicodeXMLURL)
64
65 # Extract the operator dictionary.
66 xsltTransform = etree.XSLT(etree.parse("./operator-dictionary.xsl"))
67
68 # Put the operator dictionary into a Python structure.
69 inlineAxisOperators = {}
70 with open(inlineAxisOperatorsTXT, mode="r") as f:
71     for line in f:
72         hexaString = re.match("^U\+([0-9A-F]+)", line).group(1)
73         inlineAxisOperators[parseHexaNumber(hexaString)] = True
74
75 operatorDictionary = {}
76 root = xsltTransform(etree.parse(unicodeXML)).getroot()
77 for entry in root:
78     characters = parseHexaSequence(entry.get("unicode"))
79     assert characters != (NonBreakingSpace)
80     key, value = buildKeyAndValueFrom(characters, entry.get("form"))
81     # There is no dictionary-specified minsize/maxsize values, so no need to
82     # parse them.
83     # The fence, separator and priority properties don't have any effect on math
84     # layout, so they are not added to the JSON file.
85     parseSpaces(value, entry, ["lspace", "rspace"])
86     parseProperties(value, entry, ["stretchy", "symmetric", "largeop",
87                                    "movablelimits", "accent"])
88     if (len(characters) == 1 and characters[0] in inlineAxisOperators):
89         value["horizontal"] = True
90     operatorDictionary[key] = value
91
92 # Create entries for the non-breaking space in all forms in order to test the
93 # default for operators outside the official dictionary.
94 for form in ["infix", "prefix", "suffix"]:
95     key, value = buildKeyAndValueFrom(tuple([NonBreakingSpace]), form)
96     operatorDictionary[key] = value
97
98 # Create a WOFF font with glyphs for all the operator strings.
99 font = mathfont.create("operators")
100
101 # Set parameters for largeop and stretchy tests.
102 font.math.DisplayOperatorMinHeight = 2 * mathfont.em
103 font.math.MinConnectorOverlap = mathfont.em / 2
104
105 # Set parameters for accent tests so that we only have large gap when
106 # overscript is an accent.
107 font.math.UpperLimitBaselineRiseMin = 0
108 font.math.StretchStackTopShiftUp = 0
109 font.math.AccentBaseHeight = 2 * mathfont.em
110 font.math.OverbarVerticalGap = 0
111
112 createSizeVariants(font)
113 for key in operatorDictionary:
114     value = operatorDictionary[key]
115     for c in value["characters"]:
116         if c in font:
117             continue
118         if c == NonBreakingSpace:
119             g = font.createChar(c)
120             mathfont.drawRectangleGlyph(g, mathfont.em, mathfont.em / 3, 0)
121         else:
122             mathfont.createSquareGlyph(font, c)
123         createStretchy(font, c, c in inlineAxisOperators)
124 mathfont.save(font)
125
126 # Generate the python file.
127 for key in operatorDictionary:
128     del operatorDictionary[key]["characters"] # Remove this temporary value.
129 JSON = {
130     "comment": "This file was automatically generated by operator-dictionary.py. Do not edit.",
131     "dictionary": operatorDictionary
132 }
133 with open('../support/operator-dictionary.json', 'w') as fp:
134     json.dump(JSON, fp, sort_keys=True, ensure_ascii=True)