Bug 1790009, part 1: Refactor nsMathMLOperators::LookupOperator(s). r=emilio

nsMathMLOperators::LookupOperators(s) methods are currently use in three
places:

(1) In nsMathMLmoFrame::ProcessTextData(), where we need to check the
    flags for each form of the operator and take the bitwise-or of all
    of them, ignoring lspace/rspace.

(2) In nsMathMLOperators::GetStretchyDirection::ProcessTextData(), where
    we need to check the direction for each form of the operator (in any
    order) and return the first found, ignoring lspace/rspace.

(3) In nsMathMLmoFrame::ProcessOperatorData, where need to check the
    specified form, and try fallback forms in the order prefix, postfix,
    infix. When an entry is found, the code also clears the form bits of
    mFlags and bitwise-or the found flags.

This commit modifies nsMathMLOperators::LookupOperator to only check
one form at once and can be used to easily implement (1) and (2). This
removes the need for nsMathMLOperators::LookupOperators.

A new method nsMathMLOperators::LookupOperatorWithFallback is introduced
to preserve the fallback prefix/postfix/infix check that is needed for
(3). Undocumented bitwise logic is moved out of that method.

Differential Revision: https://phabricator.services.mozilla.com/D157705
This commit is contained in:
Frederic Wang 2022-09-22 12:04:07 +00:00
Родитель c538244252
Коммит a099935c6f
3 изменённых файлов: 73 добавлений и 90 удалений

Просмотреть файл

@ -309,7 +309,7 @@ static OperatorData* GetOperatorData(const nsString& aOperator,
return gOperatorTable->Get(key);
}
void nsMathMLOperators::LookupOperator(const nsString& aOperator,
bool nsMathMLOperators::LookupOperator(const nsString& aOperator,
const uint8_t aForm,
nsOperatorFlags* aFlags,
float* aLeadingSpace,
@ -321,66 +321,39 @@ void nsMathMLOperators::LookupOperator(const nsString& aOperator,
InitOperatorGlobals();
}
if (gOperatorTable) {
// The MathML REC says:
// If the operator does not occur in the dictionary with the specified form,
// the renderer should use one of the forms which is available there, in the
// order of preference: infix, postfix, prefix.
OperatorData* found;
if (!(found = GetOperatorData(aOperator, aForm))) {
for (const auto& form :
{NS_MATHML_OPERATOR_FORM_INFIX, NS_MATHML_OPERATOR_FORM_POSTFIX,
NS_MATHML_OPERATOR_FORM_PREFIX}) {
if (form == aForm) {
// This form was tried above, skip it.
continue;
}
if ((found = GetOperatorData(aOperator, form))) {
break;
}
}
}
if (found) {
NS_ASSERTION(found->mStr.Equals(aOperator), "bad setup");
*aLeadingSpace = found->mLeadingSpace;
*aTrailingSpace = found->mTrailingSpace;
*aFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the form bits
*aFlags |= found->mFlags; // just add bits without overwriting
if (OperatorData* data = GetOperatorData(aOperator, aForm)) {
NS_ASSERTION(data->mStr.Equals(aOperator), "bad setup");
*aFlags = data->mFlags;
*aLeadingSpace = data->mLeadingSpace;
*aTrailingSpace = data->mTrailingSpace;
return true;
}
}
return false;
}
void nsMathMLOperators::LookupOperators(const nsString& aOperator,
nsOperatorFlags* aFlags,
float* aLeadingSpace,
float* aTrailingSpace) {
if (!gGlobalsInitialized) {
InitOperatorGlobals();
bool nsMathMLOperators::LookupOperatorWithFallback(const nsString& aOperator,
const uint8_t aForm,
nsOperatorFlags* aFlags,
float* aLeadingSpace,
float* aTrailingSpace) {
if (LookupOperator(aOperator, aForm, aFlags, aLeadingSpace, aTrailingSpace)) {
return true;
}
aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = 0;
aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0;
aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = 0;
aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
if (gOperatorTable) {
for (const auto& form :
{NS_MATHML_OPERATOR_FORM_INFIX, NS_MATHML_OPERATOR_FORM_POSTFIX,
NS_MATHML_OPERATOR_FORM_PREFIX}) {
if (OperatorData* found = GetOperatorData(aOperator, form)) {
aFlags[form] = found->mFlags;
aLeadingSpace[form] = found->mLeadingSpace;
aTrailingSpace[form] = found->mTrailingSpace;
}
for (const auto& form :
{NS_MATHML_OPERATOR_FORM_INFIX, NS_MATHML_OPERATOR_FORM_POSTFIX,
NS_MATHML_OPERATOR_FORM_PREFIX}) {
if (form == aForm) {
// This form was tried above, skip it.
continue;
}
if (LookupOperator(aOperator, form, aFlags, aLeadingSpace,
aTrailingSpace)) {
return true;
}
}
return false;
}
/* static */
@ -403,19 +376,22 @@ bool nsMathMLOperators::IsIntegralOperator(const nsString& aOperator) {
/* static */
nsStretchDirection nsMathMLOperators::GetStretchyDirection(
const nsString& aOperator) {
// LookupOperator will search infix, postfix and prefix forms of aOperator and
// return the first form found. It is assumed that all these forms have same
// direction.
nsOperatorFlags flags = 0;
float dummy;
nsMathMLOperators::LookupOperator(aOperator, NS_MATHML_OPERATOR_FORM_INFIX,
&flags, &dummy, &dummy);
if (NS_MATHML_OPERATOR_IS_DIRECTION_VERTICAL(flags)) {
return NS_STRETCH_DIRECTION_VERTICAL;
} else if (NS_MATHML_OPERATOR_IS_DIRECTION_HORIZONTAL(flags)) {
return NS_STRETCH_DIRECTION_HORIZONTAL;
} else {
return NS_STRETCH_DIRECTION_UNSUPPORTED;
// Search any entry for that operator and return the corresponding direction.
// It is assumed that all the forms have same direction.
for (const auto& form :
{NS_MATHML_OPERATOR_FORM_INFIX, NS_MATHML_OPERATOR_FORM_POSTFIX,
NS_MATHML_OPERATOR_FORM_PREFIX}) {
nsOperatorFlags flags;
float dummy;
if (nsMathMLOperators::LookupOperator(aOperator, form, &flags, &dummy,
&dummy)) {
if (NS_MATHML_OPERATOR_IS_DIRECTION_VERTICAL(flags)) {
return NS_STRETCH_DIRECTION_VERTICAL;
}
if (NS_MATHML_OPERATOR_IS_DIRECTION_HORIZONTAL(flags)) {
return NS_STRETCH_DIRECTION_HORIZONTAL;
}
}
}
return NS_STRETCH_DIRECTION_UNSUPPORTED;
}

Просмотреть файл

@ -66,24 +66,21 @@ class nsMathMLOperators {
// LookupOperator:
// Given the string value of an operator and its form (last two bits of
// flags), this method returns attributes of the operator in the output
// parameters. If the operator is not found under the supplied form, then the
// other forms are tried in the following order: infix, postfix, prefix. The
// caller can test the output parameter aFlags to know exactly under which
// form the operator was found in the Operator Dictionary.
static void LookupOperator(const nsString& aOperator, const uint8_t aForm,
// parameters. The return value indicates whether an entry was found.
static bool LookupOperator(const nsString& aOperator, const uint8_t aForm,
nsOperatorFlags* aFlags, float* aLeadingSpace,
float* aTrailingSpace);
// LookupOperators:
// Helper to return all the forms under which an operator is listed in the
// Operator Dictionary. The caller must pass arrays of size 4, and use
// aFlags[NS_MATHML_OPERATOR_FORM_{INFIX|POSTFIX|PREFIX}],
// aLeadingSpace[], etc, to access the attributes of the operator under a
// particular form. If the operator wasn't found under a form, its entry
// aFlags[form] is set to zero.
static void LookupOperators(const nsString& aOperator,
nsOperatorFlags* aFlags, float* aLeadingSpace,
float* aTrailingSpace);
// LookupOperatorWithFallback:
// Same as LookupOperator but if the operator is not found under the supplied
// form, then the other forms are tried in the following order: infix, postfix
// prefix. The caller can test the output parameter aFlags to know exactly
// under which form the operator was found in the Operator Dictionary.
static bool LookupOperatorWithFallback(const nsString& aOperator,
const uint8_t aForm,
nsOperatorFlags* aFlags,
float* aLeadingSpace,
float* aTrailingSpace);
// Helper functions used by the nsMathMLChar class.
static bool IsMirrorableOperator(const nsString& aOperator);

Просмотреть файл

@ -131,12 +131,16 @@ void nsMathMLmoFrame::ProcessTextData() {
// lookup all the forms under which the operator is listed in the dictionary,
// and record whether the operator has accent="true" or movablelimits="true"
nsOperatorFlags flags[4];
float lspace[4], rspace[4];
nsMathMLOperators::LookupOperators(data, flags, lspace, rspace);
nsOperatorFlags allFlags = flags[NS_MATHML_OPERATOR_FORM_INFIX] |
flags[NS_MATHML_OPERATOR_FORM_POSTFIX] |
flags[NS_MATHML_OPERATOR_FORM_PREFIX];
nsOperatorFlags allFlags = 0;
for (const auto& form :
{NS_MATHML_OPERATOR_FORM_INFIX, NS_MATHML_OPERATOR_FORM_POSTFIX,
NS_MATHML_OPERATOR_FORM_PREFIX}) {
nsOperatorFlags flags = 0;
float dummy;
if (nsMathMLOperators::LookupOperator(data, form, &flags, &dummy, &dummy)) {
allFlags |= flags;
}
}
mFlags |= allFlags & NS_MATHML_OPERATOR_ACCENT;
mFlags |= allFlags & NS_MATHML_OPERATOR_MOVABLELIMITS;
@ -327,7 +331,13 @@ void nsMathMLmoFrame::ProcessOperatorData() {
// lookup the operator dictionary
nsAutoString data;
mMathMLChar.GetData(data);
nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace);
nsOperatorFlags flags = 0;
if (nsMathMLOperators::LookupOperatorWithFallback(data, form, &flags,
&lspace, &rspace)) {
mFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the form bits
mFlags |= flags; // just add bits without overwriting
}
// Spacing is zero if our outermost embellished operator is not in an
// inferred mrow.
if (!NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags) &&