Bug 442637 - Apply ssty font feature setting to appropriate MathML elements. r=roc

--HG--
rename : layout/generic/MathVariantTextRunFactory.cpp => layout/generic/MathMLTextRunFactory.cpp
rename : layout/generic/MathVariantTextRunFactory.h => layout/generic/MathMLTextRunFactory.h
This commit is contained in:
James Kitchener 2014-01-15 09:49:20 -05:00
parent d1622128f3
commit 3a014bfa5f
5 changed files with 107 additions and 18 deletions

View File

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MathVariantTextRunFactory.h"
#include "MathMLTextRunFactory.h"
#include "mozilla/ArrayUtils.h"
@ -517,8 +517,8 @@ MathVariant(uint32_t aCh, uint8_t aMathVar)
}
void
nsMathVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
gfxContext* aRefContext)
MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
gfxContext* aRefContext)
{
gfxFontGroup* fontGroup = aTextRun->GetFontGroup();
gfxFontStyle fontStyle = *fontGroup->GetStyle();
@ -537,6 +537,56 @@ nsMathVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
const char16_t* str = aTextRun->mString.BeginReading();
nsRefPtr<nsStyleContext>* styles = aTextRun->mStyles.Elements();
if (mSSTYScriptLevel && length) {
bool found = false;
// We respect ssty settings explicitly set by the user
for (uint32_t i = 0; i < fontStyle.featureSettings.Length(); i++) {
if (fontStyle.featureSettings[i].mTag == TRUETYPE_TAG('s','s','t','y')) {
found = true;
break;
}
}
if (!found) {
uint8_t sstyLevel = 0;
float scriptScaling = pow(styles[0]->StyleFont()->mScriptSizeMultiplier,
mSSTYScriptLevel);
static_assert(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER < 1,
"Shouldn't it make things smaller?");
/*
An SSTY level of 2 is set if the scaling factor is less than or equal
to halfway between that for a scriptlevel of 1 (0.71) and that of a
scriptlevel of 2 (0.71^2), assuming the default script size multiplier.
An SSTY level of 1 is set if the script scaling factor is less than
or equal that for a scriptlevel of 1 assuming the default script size
multiplier.
User specified values of script size multiplier will change the scaling
factor which mSSTYScriptLevel values correspond to.
In the event that the script size multiplier actually makes things
larger, no change is made.
If the user doesn't want this to happen, all they need to do is set
style="-moz-font-feature-settings: 'ssty' 0"
*/
if (scriptScaling <= (NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER +
(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER*
NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER))/2) {
// Currently only the first two ssty settings are used, so two is large
// as we go
sstyLevel = 2;
} else if (scriptScaling <= NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER) {
sstyLevel = 1;
}
if (sstyLevel) {
gfxFontFeature settingSSTY;
settingSSTY.mTag = TRUETYPE_TAG('s','s','t','y');
settingSSTY.mValue = sstyLevel;
fontStyle.featureSettings.AppendElement(settingSSTY);
}
}
}
uint8_t mathVar;
bool doMathvariantStyling = true;
@ -613,8 +663,10 @@ nsMathVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
doMathvariantStyling) {
fontStyle.style = NS_FONT_STYLE_ITALIC;
fontStyle.weight = NS_FONT_WEIGHT_BOLD;
} else {
} else if (mathVar != NS_MATHML_MATHVARIANT_NONE) {
// Mathvariant overrides fontstyle and fontweight
// Need to check to see if mathvariant is actually applied as this function
// is used for other purposes.
fontStyle.style = NS_FONT_STYLE_NORMAL;
fontStyle.weight = NS_FONT_WEIGHT_NORMAL;
}

View File

@ -3,23 +3,26 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MATHVARIANTTEXTRUNFACTORY_H_
#define MATHVARIANTTEXTRUNFACTORY_H_
#ifndef MATHMLTEXTRUNFACTORY_H_
#define MATHMLTEXTRUNFACTORY_H_
#include "nsTextRunTransformations.h"
/**
* Builds textruns that render their text using a mathvariant
* Builds textruns that render their text with MathML specific renderings.
*/
class nsMathVariantTextRunFactory : public nsTransformingTextRunFactory {
class MathMLTextRunFactory : public nsTransformingTextRunFactory {
public:
nsMathVariantTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory)
: mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory) {}
MathMLTextRunFactory(nsTransformingTextRunFactory* aInnerTransformingTextRunFactory,
uint8_t aSSTYScriptLevel)
: mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory),
mSSTYScriptLevel(aSSTYScriptLevel) {}
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
gfxContext* aRefContext) MOZ_OVERRIDE;
protected:
nsAutoPtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory;
uint8_t mSSTYScriptLevel;
};
#endif /*MATHVARIANTTEXTRUNFACTORY_H_*/
#endif /*MATHMLTEXTRUNFACTORY_H_*/

View File

@ -44,7 +44,7 @@ EXPORTS.mozilla.layout += [
UNIFIED_SOURCES += [
'FrameChildList.cpp',
'MathVariantTextRunFactory.cpp',
'MathMLTextRunFactory.cpp',
'nsAbsoluteContainingBlock.cpp',
'nsBlockFrame.cpp',
'nsBlockReflowContext.cpp',

View File

@ -338,6 +338,10 @@ typedef uint64_t nsFrameState;
// Frame has a LayerActivityProperty property
#define NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY NS_FRAME_STATE_BIT(54)
// Set for all descendants of MathML sub/supscript elements (other than the
// base frame) to indicate that the SSTY font feature should be used.
#define NS_FRAME_MATHML_SCRIPT_DESCENDANT NS_FRAME_STATE_BIT(58)
// Box layout bits
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)

View File

@ -38,10 +38,11 @@
#include "nsLayoutUtils.h"
#include "nsDisplayList.h"
#include "nsFrame.h"
#include "nsIMathMLFrame.h"
#include "nsPlaceholderFrame.h"
#include "nsTextFrameUtils.h"
#include "nsTextRunTransformations.h"
#include "MathVariantTextRunFactory.h"
#include "MathMLTextRunFactory.h"
#include "nsExpirationTracker.h"
#include "nsUnicodeProperties.h"
@ -1329,6 +1330,9 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame,
if (aForFrame && aForFrame->HasAnyStateBits(TEXT_IS_IN_SINGLE_CHAR_MI)) {
aLineContainer->AddStateBits(TEXT_IS_IN_SINGLE_CHAR_MI);
}
if (aForFrame && aForFrame->HasAnyStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT)) {
aLineContainer->AddStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT);
}
nsPresContext* presContext = aLineContainer->PresContext();
BuildTextRunsScanner scanner(presContext, aContext, aLineContainer,
@ -1893,7 +1897,8 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
const void* textPtr = aTextBuffer;
bool anySmallcapsStyle = false;
bool anyTextTransformStyle = false;
bool anyMathVariantStyle = false;
bool anyMathMLStyling = false;
uint8_t sstyScriptLevel = 0;
uint32_t textFlags = nsTextFrameUtils::TEXT_NO_BREAKS;
if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {
@ -1972,10 +1977,35 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
anySmallcapsStyle = true;
}
if (NS_MATHML_MATHVARIANT_NONE != fontStyle->mMathVariant) {
anyMathVariantStyle = true;
anyMathMLStyling = true;
} else if (mLineContainer->GetStateBits() & TEXT_IS_IN_SINGLE_CHAR_MI) {
textFlags |= nsTextFrameUtils::TEXT_IS_SINGLE_CHAR_MI;
anyMathVariantStyle = true;
anyMathMLStyling = true;
}
nsIFrame* parent = mLineContainer->GetParent();
nsIFrame* child = mLineContainer;
uint8_t oldScriptLevel = 0;
while (parent &&
child->HasAnyStateBits(NS_FRAME_MATHML_SCRIPT_DESCENDANT)) {
// Reconstruct the script level ignoring any user overrides. It is
// calculated this way instead of using scriptlevel to ensure the
// correct ssty font feature setting is used even if the user sets a
// different (especially negative) scriptlevel.
nsIMathMLFrame* mathFrame= do_QueryFrame(parent);
if (mathFrame) {
sstyScriptLevel += mathFrame->ScriptIncrement(child);
}
if (sstyScriptLevel < oldScriptLevel) {
// overflow
sstyScriptLevel = UINT8_MAX;
break;
}
child = parent;
parent = parent->GetParent();
oldScriptLevel = sstyScriptLevel;
}
if (sstyScriptLevel) {
anyMathMLStyling = true;
}
// Figure out what content is included in this flow.
@ -2110,9 +2140,9 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
transformingFactory =
new nsCaseTransformTextRunFactory(transformingFactory.forget());
}
if (anyMathVariantStyle) {
if (anyMathMLStyling) {
transformingFactory =
new nsMathVariantTextRunFactory(transformingFactory.forget());
new MathMLTextRunFactory(transformingFactory.forget(), sstyScriptLevel);
}
nsTArray<nsStyleContext*> styles;
if (transformingFactory) {