[orca] Add some speech generators for MathML content
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Add some speech generators for MathML content
- Date: Thu, 2 Jul 2015 06:18:35 +0000 (UTC)
commit e6509262722831371904bee9767519e9be0b22e1
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Thu Jul 2 02:18:13 2015 -0400
Add some speech generators for MathML content
src/orca/speech_generator.py | 333 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 333 insertions(+), 0 deletions(-)
---
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index 184914a..3c72b1e 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -1883,12 +1883,345 @@ class SpeechGenerator(generator.Generator):
result.extend(acss)
return result
+ # Math
+
+ def _generateMath(self, obj, **args):
+ result = []
+ children = [child for child in obj] or [obj]
+ for child in children:
+ if self._script.utilities.isMathLayoutOnly(child):
+ result.extend(self._generateMath(child))
+ continue
+
+ oldRole = self._getAlternativeRole(child)
+ self._overrideRole(oldRole, args)
+ result.extend(self.generate(child, role=oldRole))
+ self._restoreRole(oldRole, args)
+
+ return result
+
+ def _generateEnclosedBase(self, obj, **args):
+ return self._generateMath(obj, **args)
+
+ def _generateEnclosedEnclosures(self, obj, **args):
+ strings = []
+ enclosures = self._script.utilities.getMathEnclosures(obj)
+ if 'actuarial' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_ACTUARIAL)
+ if 'box' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_BOX)
+ if 'circle' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_CIRCLE)
+ if 'longdiv' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_LONGDIV)
+ if 'radical' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_RADICAL)
+ if 'roundedbox' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_ROUNDEDBOX)
+ if 'horizontalstrike' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_HORIZONTALSTRIKE)
+ if 'verticalstrike' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_VERTICALSTRIKE)
+ if 'downdiagonalstrike' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_DOWNDIAGONALSTRIKE)
+ if 'updiagonalstrike' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_UPDIAGONALSTRIKE)
+ if 'northeastarrow' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_NORTHEASTARROW)
+ if 'bottom' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_BOTTOM)
+ if 'left' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_LEFT)
+ if 'right' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_RIGHT)
+ if 'top' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_TOP)
+ if 'phasorangle' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_PHASOR_ANGLE)
+ if 'madruwb' in enclosures:
+ strings.append(messages.MATH_ENCLOSURE_MADRUWB)
+ if not strings:
+ msg = 'INFO: Could not get enclosure message for %s' % enclosures
+ debug.println(debug.LEVEL_INFO, msg)
+ return []
+
+ if len(strings) == 1:
+ result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % strings[0]]
+ else:
+ strings.insert(-1, messages.MATH_ENCLOSURE_AND)
+ if len(strings) == 3:
+ result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % " ".join(strings)]
+ else:
+ result = [messages.MATH_ENCLOSURE_ENCLOSED_BY % ", ".join(strings)]
+
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateFencedStart(self, obj, **args):
+ fenceStart, fenceEnd = self._script.utilities.getMathFences(obj)
+ if fenceStart:
+ result = [fenceStart]
+ result.extend(self.voice(DEFAULT))
+ return result
+
+ return []
+
+ def _generateFencedContents(self, obj, **args):
+ result = []
+ separators = self._script.utilities.getMathFencedSeparators(obj)
+ for x in range(len(separators), obj.childCount-1):
+ separators.append(separators[-1])
+ separators.append('')
+
+ for i, child in enumerate(obj):
+ result.extend(self._generateMath(child, **args))
+ result.extend(separators[i])
+ result.extend(self.voice(DEFAULT))
+
+ return result
+
+ def _generateFencedEnd(self, obj, **args):
+ fenceStart, fenceEnd = self._script.utilities.getMathFences(obj)
+ if fenceEnd:
+ result = [fenceEnd]
+ result.extend(self.voice(DEFAULT))
+ return result
+
+ return []
+
+ def _generateFractionStart(self, obj, **args):
+ if self._script.utilities.isMathFractionWithoutBar(obj):
+ result = [messages.MATH_FRACTION_WITHOUT_BAR_START]
+ else:
+ result = [messages.MATH_FRACTION_START]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateFractionNumerator(self, obj, **args):
+ numerator = self._script.utilities.getMathNumerator(obj)
+ oldRole = self._getAlternativeRole(numerator)
+ self._overrideRole(oldRole, args)
+ result = self.generate(numerator, role=oldRole)
+ self._restoreRole(oldRole, args)
+ return result
+
+ def _generateFractionDenominator(self, obj, **args):
+ denominator = self._script.utilities.getMathDenominator(obj)
+ oldRole = self._getAlternativeRole(denominator)
+ self._overrideRole(oldRole, args)
+ result = self.generate(denominator, role=oldRole)
+ self._restoreRole(oldRole, args)
+ return result
+
+ def _generateFractionLine(self, obj, **args):
+ result = [messages.MATH_FRACTION_LINE]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateFractionEnd(self, obj, **args):
+ result = [messages.MATH_FRACTION_END]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateRootStart(self, obj, **args):
+ result = []
+ if self._script.utilities.isMathSquareRoot(obj):
+ result = [messages.MATH_SQUARE_ROOT_OF]
+ else:
+ index = self._script.utilities.getMathRootIndex(obj)
+ string = self._script.utilities.displayedText(index)
+ if string == "2":
+ result = [messages.MATH_SQUARE_ROOT_OF]
+ elif string == "3":
+ result = [messages.MATH_CUBE_ROOT_OF]
+ elif string:
+ result = [string]
+ result.extend([messages.MATH_ROOT_OF])
+ elif self._script.utilities.isMathLayoutOnly(index):
+ result = self._generateMath(index)
+ result.extend([messages.MATH_ROOT_OF])
+ else:
+ oldRole = self._getAlternativeRole(index)
+ self._overrideRole(oldRole, args)
+ result.extend(self.generate(index, role=oldRole))
+ self._restoreRole(oldRole, args)
+ result.extend([messages.MATH_ROOT_OF])
+
+ if result:
+ result.extend(self.voice(SYSTEM))
+
+ return result
+
+ def _generateRootBase(self, obj, **args):
+ base = self._script.utilities.getMathRootBase(obj)
+ if not base:
+ return []
+
+ if self._script.utilities.isMathSquareRoot(obj) \
+ or self._script.utilities.isMathToken(base) \
+ or self._script.utilities.isMathLayoutOnly(base):
+ return self._generateMath(base)
+
+ result = [self._generatePause(obj, **args)]
+ oldRole = self._getAlternativeRole(base)
+ self._overrideRole(oldRole, args)
+ result.extend(self.generate(base, role=oldRole))
+ self._restoreRole(oldRole, args)
+
+ return result
+
+ def _generateRootEnd(self, obj, **args):
+ result = [messages.MATH_ROOT_END]
+ result.extend(self.voice(SYSTEM))
+ return result
+
+ def _generateScriptBase(self, obj, **args):
+ base = self._script.utilities.getMathScriptBase(obj)
+ if not base:
+ return []
+
+ return self._generateMath(base)
+
+ def _generateScriptScript(self, obj, **args):
+ oldRole = self._getAlternativeRole(obj)
+ self._overrideRole(oldRole, args)
+ result = self.generate(obj, role=oldRole)
+ self._restoreRole(oldRole, args)
+
+ return result
+
+ def _generateScriptSubscript(self, obj, **args):
+ subscript = self._script.utilities.getMathScriptSubscript(obj)
+ if not subscript:
+ return []
+
+ result = [messages.MATH_SUBSCRIPT]
+ result.extend(self.voice(SYSTEM))
+ result.extend(self._generateScriptScript(subscript))
+
+ return result
+
+ def _generateScriptSuperscript(self, obj, **args):
+ superscript = self._script.utilities.getMathScriptSuperscript(obj)
+ if not superscript:
+ return []
+
+ result = [messages.MATH_SUPERSCRIPT]
+ result.extend(self.voice(SYSTEM))
+ result.extend(self._generateScriptScript(superscript))
+
+ return result
+
+ def _generateScriptUnderscript(self, obj, **args):
+ underscript = self._script.utilities.getMathScriptUnderscript(obj)
+ if not underscript:
+ return []
+
+ result = [messages.MATH_UNDERSCRIPT]
+ result.extend(self.voice(SYSTEM))
+ result.extend(self._generateScriptScript(underscript))
+
+ return result
+
+ def _generateScriptOverscript(self, obj, **args):
+ overscript = self._script.utilities.getMathScriptOverscript(obj)
+ if not overscript:
+ return []
+
+ result = [messages.MATH_OVERSCRIPT]
+ result.extend(self.voice(SYSTEM))
+ result.extend(self._generateScriptScript(overscript))
+
+ return result
+
+ def _generateScriptPrescripts(self, obj, **args):
+ result = []
+ prescripts = self._script.utilities.getMathPrescripts(obj)
+ for i, script in enumerate(prescripts):
+ if i % 2:
+ rv = [messages.MATH_PRE_SUPERSCRIPT]
+ else:
+ rv = [messages.MATH_PRE_SUBSCRIPT]
+ rv.extend(self.voice(SYSTEM))
+ rv.extend(self._generateScriptScript(script))
+ result.append(rv)
+
+ return result
+
+ def _generateScriptPostscripts(self, obj, **args):
+ result = []
+ postscripts = self._script.utilities.getMathPostscripts(obj)
+ for i, script in enumerate(postscripts):
+ if i % 2:
+ rv = [messages.MATH_POST_SUPERSCRIPT]
+ else:
+ rv = [messages.MATH_POST_SUBSCRIPT]
+ rv.extend(self.voice(SYSTEM))
+ rv.extend(self._generateScriptScript(script))
+ result.append(rv)
+
+ return result
+
+ def _generateMathTable(self, obj, **args):
+ try:
+ table = obj.queryTable()
+ except:
+ return []
+
+ result = []
+ if not _settingsManager.getSetting('onlySpeakDisplayedText'):
+ result.append(messages.mathTableSize(table.nRows, table.nColumns))
+ result.extend(self.voice(SYSTEM))
+
+ result.extend(self._generatePause(obj, **args))
+ result.extend(self._generateMathRow(obj[0]))
+ return result
+
+ def _generateMathRow(self, obj, **args):
+ result = []
+ if not _settingsManager.getSetting('onlySpeakDisplayedText'):
+ result.append(messages.TABLE_ROW % (obj.getIndexInParent() + 1))
+ result.extend(self.voice(SYSTEM))
+
+ for child in obj:
+ result.extend(self._generatePause(child, **args))
+ result.extend(self._generateMath(child))
+
+ return result
+
#####################################################################
# #
# Other things for prosody and voice selection #
# #
#####################################################################
+ def _getAlternativeRole(self, obj, **args):
+ if self._script.utilities.isMath(obj):
+ if self._script.utilities.isMathTopLevel(obj):
+ return 'ROLE_MATH'
+ if self._script.utilities.isMathFraction(obj):
+ return 'ROLE_MATH_FRACTION'
+ if self._script.utilities.isMathRoot(obj):
+ return 'ROLE_MATH_ROOT'
+ if self._script.utilities.isMathSubOrSuperScript(obj):
+ return 'ROLE_MATH_SCRIPT_SUBSUPER'
+ if self._script.utilities.isMathUnderOrOverScript(obj):
+ return 'ROLE_MATH_SCRIPT_UNDEROVER'
+ if self._script.utilities.isMathMultiScript(obj):
+ return 'ROLE_MATH_MULTISCRIPT'
+ if self._script.utilities.isMathEnclose(obj):
+ return 'ROLE_MATH_ENCLOSED'
+ if self._script.utilities.isMathFenced(obj):
+ return 'ROLE_MATH_FENCED'
+ if self._script.utilities.isMathTable(obj):
+ return 'ROLE_MATH_TABLE'
+ if self._script.utilities.isMathTableRow(obj):
+ return 'ROLE_MATH_TABLE_ROW'
+ if self._script.utilities.isStatic(obj):
+ return 'ROLE_STATIC'
+
+ return args.get('role', obj.getRole())
+
def _generatePause(self, obj, **args):
if args.get('eliminatePauses', False):
return []
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]