Skip to content

Commit d7c86a3

Browse files
authored
Merge 7cafa6e into cb7258a
2 parents cb7258a + 7cafa6e commit d7c86a3

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

source/NVDAObjects/IAccessible/adobeAcrobat.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,36 @@ def _isEqual(self, other):
120120
return super(AcrobatNode, self)._isEqual(other)
121121

122122
def _getNodeMathMl(self, node):
123+
"""Traverse the MathML tree and return an XML string representing the math"""
124+
125+
def getMathMLAttributes(node, attrList: list) -> str:
126+
attrValues = ""
127+
# log.info(f"\nstart getMathMLAttributes -- looking for: {attrList}")
128+
for attr in attrList:
129+
val = node.GetAttribute(attr, "NSO")
130+
if val:
131+
attrValues += f' {attr}="{val}"'
132+
# log.info(f"getMathMLAttributes: found attrValues={attrValues}")
133+
return attrValues
134+
123135
tag = node.GetTagName()
136+
# log.info(f"_getNodeMathMl: mathml tag={tag}")
124137
yield "<%s" % tag
125-
# Output relevant attributes.
126-
if tag == "mfenced":
127-
for attr in "open", "close", "separators":
128-
val = node.GetAttribute(attr, "XML-1.00")
129-
if val:
130-
yield ' %s="%s"' % (attr, val)
138+
# Output relevant attributes
139+
id = node.GetID()
140+
if id:
141+
yield f' id="{id}"'
142+
yield getMathMLAttributes(node, ["intent", "arg"])
143+
if tag == "mi" or tag == "mn" or tag == "mo" or tag == "mtext":
144+
yield getMathMLAttributes(node, ["mathvariant"])
145+
elif tag == "mfenced":
146+
yield getMathMLAttributes(node, ["open", "close", "separators"])
147+
elif tag == "menclose":
148+
yield getMathMLAttributes(node, ["notation"])
149+
elif tag == "annotation-xml" or tag == "annotation":
150+
yield getMathMLAttributes(node, ["encoding"])
151+
elif tag == "ms":
152+
yield getMathMLAttributes(node, ["open", "close"])
131153
yield ">"
132154
val = node.GetValue()
133155
if val:
@@ -144,9 +166,28 @@ def _getNodeMathMl(self, node):
144166

145167
def _get_mathMl(self) -> str:
146168
"""Return the MathML associated with a Formula tag"""
169+
# There are two ways that MathML can be represented in a PDF:
170+
# 1. As a series of nested tags, each with a MathML element as the value.
171+
# 2. As a Formula tag with MathML as the value (comes from MathML in an Associated File)
147172
if self.pdDomNode is None:
148173
log.debugWarning("_get_mathMl: self.pdDomNode is None!")
149174
raise LookupError
175+
176+
# see if it is MathML tagging is used
177+
for childNum in range(self.pdDomNode.GetChildCount()):
178+
try:
179+
child = self.pdDomNode.GetChild(childNum).QueryInterface(IPDDomElement)
180+
except COMError:
181+
log.debugWarning(f"COMError trying to get childNum={childNum}")
182+
continue
183+
if log.isEnabledFor(log.DEBUG):
184+
log.debug(f"\t(PDF) get_mathMl: tag={child.GetTagName()}")
185+
if child.GetTagName() == "math":
186+
answer = "".join(self._getNodeMathMl(child))
187+
if log.isEnabledFor(log.DEBUG):
188+
log.debug(f"_get_mathMl: found MathML = {answer}")
189+
return answer
190+
150191
mathMl = self.pdDomNode.GetValue()
151192
if log.isEnabledFor(log.DEBUG):
152193
log.debug(
@@ -159,21 +200,11 @@ def _get_mathMl(self) -> str:
159200
# this test and the replacement doesn't work if someone uses a namespace tag (which they shouldn't, but..)
160201
if mathMl.startswith("<math"):
161202
return mathMl.replace('xmlns:mml="http://www.w3.org/1998/Math/MathML"', "")
162-
# Alternative for tagging: all the sub expressions are tagged -- gather up the MathML
163-
for childNum in range(self.pdDomNode.GetChildCount()):
164-
try:
165-
child = self.pdDomNode.GetChild(childNum).QueryInterface(IPDDomElement)
166-
except COMError:
167-
log.debugWarning(f"COMError trying to get childNum={childNum}")
168-
continue
169-
if log.isEnabledFor(log.DEBUG):
170-
log.debug(f"\tget_mathMl: tag={child.GetTagName()}")
171-
if child.GetTagName() == "math":
172-
return "".join(self._getNodeMathMl(child))
173-
# fall back to return the contents, which is hopefully alt text
203+
204+
# not MathML -- fall back to return the contents, which is hopefully alt text, inside an <mtext>
174205
if log.isEnabledFor(log.DEBUG):
175206
log.debug("_get_mathMl: didn't find MathML -- returning value as mtext")
176-
return f"<math><mtext>{self.pdDomNode.GetValue()}</mtext></math>"
207+
return f"<math><mtext>{mathMl}</mtext></math>"
177208

178209

179210
class RootNode(AcrobatNode):

user_docs/en/changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
### Bug Fixes
1212

13+
* MathML attributes were not being picked up when MathML was in the tag tree in PDF. This might result in poor or wrong speech and braille. (#17980)
1314
* In WinUI 3 apps including Microsoft Copilot and parts of Windows 11 File Explorer, NVDA will no longer fail to announce controls when using mouse and touch interaction. (#17407, #17771, @josephsl)
1415
* Fixed some rare cases where NVDA playing sounds could result in unexpected errors. (#17918, @LeonarddeR)
1516
* In Microsoft Word, when UIA is enabled, NVDA will no longer braille redundant table end markers when the cursor is in a table cell. (#15828, @LeonarddeR)

0 commit comments

Comments
 (0)