diff --git a/layout/mathml/nsMathMLmoFrame.cpp b/layout/mathml/nsMathMLmoFrame.cpp index 8aac2a812db0..99da363d9444 100644 --- a/layout/mathml/nsMathMLmoFrame.cpp +++ b/layout/mathml/nsMathMLmoFrame.cpp @@ -30,6 +30,7 @@ nsMathMLmoFrame::~nsMathMLmoFrame() { } +static const char16_t kInvisibleComma = char16_t(0x200B); // a.k.a. ZERO WIDTH SPACE static const char16_t kApplyFunction = char16_t(0x2061); static const char16_t kInvisibleTimes = char16_t(0x2062); static const char16_t kInvisibleSeparator = char16_t(0x2063); @@ -73,7 +74,8 @@ nsMathMLmoFrame::UseMathMLChar() { return (NS_MATHML_OPERATOR_GET_FORM(mFlags) && NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) || - NS_MATHML_OPERATOR_IS_CENTERED(mFlags); + NS_MATHML_OPERATOR_IS_CENTERED(mFlags) || + NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags); } void @@ -121,16 +123,18 @@ nsMathMLmoFrame::ProcessTextData() char16_t ch = (length == 0) ? char16_t('\0') : data[0]; if ((length == 1) && - (ch == kApplyFunction || + (ch == kInvisibleComma || + ch == kApplyFunction || ch == kInvisibleSeparator || ch == kInvisiblePlus || ch == kInvisibleTimes)) { mFlags |= NS_MATHML_OPERATOR_INVISIBLE; } - // don't bother doing anything special if we don't have a single child + // don't bother doing anything special if we don't have a + // single child with a visible text content nsPresContext* presContext = PresContext(); - if (mFrames.GetLength() != 1) { + if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags) || mFrames.GetLength() != 1) { data.Truncate(); // empty data to reset the char mMathMLChar.SetData(presContext, data); ResolveMathMLCharStyle(presContext, mContent, mStyleContext, &mMathMLChar, false); @@ -337,10 +341,17 @@ nsMathMLmoFrame::ProcessOperatorData() // thickmathspace = 5/18em float lspace = 5.0f/18.0f; float rspace = 5.0f/18.0f; - // lookup the operator dictionary - nsAutoString data; - mMathMLChar.GetData(data); - nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); + if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { + // mMathMLChar has been reset in ProcessTextData so we can not find it + // in the operator dictionary. The operator dictionary always uses + // lspace = rspace = 0 for invisible operators. + lspace = rspace = 0; + } else { + // lookup the operator dictionary + nsAutoString data; + mMathMLChar.GetData(data); + nsMathMLOperators::LookupOperator(data, form, &mFlags, &lspace, &rspace); + } if (lspace || rspace) { // Cache the default values of lspace and rspace. // since these values are relative to the 'em' unit, convert to twips now @@ -738,12 +749,15 @@ nsMathMLmoFrame::Stretch(nsRenderingContext& aRenderingContext, } } - // Place our children using the default method - // This will allow our child text frame to get its DidReflow() - nsresult rv = Place(aRenderingContext, true, aDesiredStretchSize); - if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) { - // Make sure the child frames get their DidReflow() calls. - DidReflowChildren(mFrames.FirstChild()); + // Child frames of invisble operators are not reflowed + if (!NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { + // Place our children using the default method + // This will allow our child text frame to get its DidReflow() + nsresult rv = Place(aRenderingContext, true, aDesiredStretchSize); + if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) { + // Make sure the child frames get their DidReflow() calls. + DidReflowChildren(mFrames.FirstChild()); + } } if (useMathMLChar) { @@ -933,6 +947,22 @@ nsMathMLmoFrame::Reflow(nsPresContext* aPresContext, // it is safer to just process the whole lot here ProcessOperatorData(); + // play safe by not passing invisible operators to the font subsystem because + // some platforms risk selecting strange glyphs for them and give bad inter-space + if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { + // return empty space for now, but this is not yet final since there + // can be lspace and rspace attributes that reclaim some room. + // These will be dealt with later in Stretch(). + aDesiredSize.Width() = 0; + aDesiredSize.Height() = 0; + aDesiredSize.SetTopAscent(0); + aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); + aStatus = NS_FRAME_COMPLETE; + + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); + return NS_OK; + } + return nsMathMLTokenFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } diff --git a/layout/reftests/mathml/mo-invisibleoperators-2-ref.html b/layout/reftests/mathml/mo-invisibleoperators-2-ref.html deleted file mode 100644 index d704aa2bc0e1..000000000000 --- a/layout/reftests/mathml/mo-invisibleoperators-2-ref.html +++ /dev/null @@ -1,27 +0,0 @@ - - -
- -
- -
- -
-
- - | -
- -
- -
- -
- -
- - | -