bug 1057331 - add orientation flags to gfxShapedText/gfxTextRun and to glyph runs within the text run, and split glyph runs on orientation changes. r=jdaggett

This commit is contained in:
Jonathan Kew 2014-09-16 12:25:45 +01:00
parent b4f621c5f6
commit 5cadcfeab8
7 changed files with 207 additions and 81 deletions

View File

@ -2573,7 +2573,8 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext,
uint32_t flags = aTextRun->GetFlags();
flags &= (gfxTextRunFactory::TEXT_IS_RTL |
gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES |
gfxTextRunFactory::TEXT_USE_MATH_SCRIPT);
gfxTextRunFactory::TEXT_USE_MATH_SCRIPT |
gfxTextRunFactory::TEXT_ORIENT_MASK);
if (sizeof(T) == sizeof(uint8_t)) {
flags |= gfxTextRunFactory::TEXT_IS_8BIT;
}
@ -2642,8 +2643,13 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext,
if (boundary) {
// word was terminated by a space: add that to the textrun
uint16_t orientation = flags & gfxTextRunFactory::TEXT_ORIENT_MASK;
if (orientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED) {
orientation = gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
}
if (!aTextRun->SetSpaceGlyphIfSimple(this, aContext,
aRunStart + i, ch))
aRunStart + i, ch,
orientation))
{
static const uint8_t space = ' ';
gfxShapedWord *sw =
@ -2707,24 +2713,7 @@ gfxFont::SplitAndInitTextRun(gfxContext *aContext,
uint32_t aRunLength,
int32_t aRunScript);
bool
gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const uint8_t *aText,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper)
{
NS_ConvertASCIItoUTF16 unicodeString(reinterpret_cast<const char*>(aText),
aLength);
return InitFakeSmallCapsRun(aContext, aTextRun, unicodeString.get(),
aOffset, aLength, aMatchType, aScript,
aSyntheticLower, aSyntheticUpper);
}
template<>
bool
gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
@ -2732,6 +2721,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
uint16_t aOrientation,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper)
@ -2768,7 +2758,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
if (IsClusterExtender(ch)) {
chAction = runAction;
} else {
if (ch != ToUpperCase(ch) || mozilla::unicode::SpecialUpper(ch)) {
if (ch != ToUpperCase(ch) || SpecialUpper(ch)) {
// ch is lower case
chAction = (aSyntheticLower ? kUppercaseReduce : kNoChange);
} else if (ch != ToLowerCase(ch)) {
@ -2801,7 +2791,8 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
switch (runAction) {
case kNoChange:
// just use the current font and the existing string
aTextRun->AddGlyphRun(f, aMatchType, aOffset + runStart, true);
aTextRun->AddGlyphRun(f, aMatchType, aOffset + runStart, true,
aOrientation);
if (!f->SplitAndInitTextRun(aContext, aTextRun,
aText + runStart,
aOffset + runStart, runLength,
@ -2842,7 +2833,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
tempRun =
gfxTextRun::Create(&params, convertedString.Length(),
aTextRun->GetFontGroup(), 0);
tempRun->AddGlyphRun(f, aMatchType, 0, true);
tempRun->AddGlyphRun(f, aMatchType, 0, true, aOrientation);
if (!f->SplitAndInitTextRun(aContext, tempRun,
convertedString.BeginReading(),
0, convertedString.Length(),
@ -2861,7 +2852,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
}
} else {
aTextRun->AddGlyphRun(f, aMatchType, aOffset + runStart,
true);
true, aOrientation);
if (!f->SplitAndInitTextRun(aContext, aTextRun,
convertedString.BeginReading(),
aOffset + runStart, runLength,
@ -2884,6 +2875,26 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
return ok;
}
template<>
bool
gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const uint8_t *aText,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
uint16_t aOrientation,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper)
{
NS_ConvertASCIItoUTF16 unicodeString(reinterpret_cast<const char*>(aText),
aLength);
return InitFakeSmallCapsRun(aContext, aTextRun, unicodeString.get(),
aOffset, aLength, aMatchType, aOrientation,
aScript, aSyntheticLower, aSyntheticUpper);
}
already_AddRefed<gfxFont>
gfxFont::GetSmallCapsFont()
{

View File

@ -207,16 +207,19 @@ struct gfxTextRange {
kSystemFallback = 0x0004
};
gfxTextRange(uint32_t aStart, uint32_t aEnd,
gfxFont* aFont, uint8_t aMatchType)
gfxFont* aFont, uint8_t aMatchType,
uint16_t aOrientation)
: start(aStart),
end(aEnd),
font(aFont),
matchType(aMatchType)
matchType(aMatchType),
orientation(aOrientation)
{ }
uint32_t Length() const { return end - start; }
uint32_t start, end;
nsRefPtr<gfxFont> font;
uint8_t matchType;
uint16_t orientation;
};
@ -438,8 +441,7 @@ public:
enum {
CACHE_TEXT_FLAGS = 0xF0000000,
USER_TEXT_FLAGS = 0x0FFF0000,
PLATFORM_TEXT_FLAGS = 0x0000F000,
TEXTRUN_TEXT_FLAGS = 0x00000FFF,
TEXTRUN_TEXT_FLAGS = 0x0000FFFF,
SETTABLE_FLAGS = CACHE_TEXT_FLAGS | USER_TEXT_FLAGS,
/**
@ -503,6 +505,31 @@ public:
*/
TEXT_HIDE_CONTROL_CHARACTERS = 0x0400,
/**
* Field for orientation of the textrun and glyphs within it.
* Possible values of the TEXT_ORIENT_MASK field:
* TEXT_ORIENT_HORIZONTAL
* TEXT_ORIENT_VERTICAL_UPRIGHT
* TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT
* TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT
* TEXT_ORIENT_VERTICAL_MIXED
* For all VERTICAL settings, the x and y coordinates of glyph
* positions are exchanged, so that simple advances are vertical.
*
* The MIXED value indicates vertical textRuns for which the CSS
* text-orientation property is 'mixed', but is never used for
* individual glyphRuns; it will be resolved to either UPRIGHT
* or SIDEWAYS_RIGHT according to the UTR50 properties of the
* characters, and separate glyphRuns created for the resulting
* glyph orientations.
*/
TEXT_ORIENT_MASK = 0xF000,
TEXT_ORIENT_HORIZONTAL = 0x0000,
TEXT_ORIENT_VERTICAL_UPRIGHT = 0x1000,
TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT = 0x2000,
TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT = 0x4000,
TEXT_ORIENT_VERTICAL_MIXED = 0x8000,
/**
* nsTextFrameThebes sets these, but they're defined here rather than
* in nsTextFrameUtils.h because ShapedWord creation/caching also needs
@ -904,6 +931,11 @@ public:
return mFlags;
}
bool IsVertical() const {
return (GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK) !=
gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL;
}
bool IsRightToLeft() const {
return (GetFlags() & gfxTextRunFactory::TEXT_IS_RTL) != 0;
}
@ -1561,25 +1593,17 @@ public:
return mFontEntry->GetUVSGlyph(aCh, aVS);
}
bool InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const uint8_t *aText,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper);
bool InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const char16_t *aText,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper);
template<typename T>
bool InitFakeSmallCapsRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const T *aText,
uint32_t aOffset,
uint32_t aLength,
uint8_t aMatchType,
uint16_t aOrientation,
int32_t aScript,
bool aSyntheticLower,
bool aSyntheticUpper);
// call the (virtual) InitTextRun method to do glyph generation/shaping,
// limiting the length of text passed by processing the run in multiple

View File

@ -980,9 +980,12 @@ gfxTextRun::FindFirstGlyphRunContaining(uint32_t aOffset)
nsresult
gfxTextRun::AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
uint32_t aUTF16Offset, bool aForceNewRun)
uint32_t aUTF16Offset, bool aForceNewRun,
uint16_t aOrientation)
{
NS_ASSERTION(aFont, "adding glyph run for null font!");
NS_ASSERTION(aOrientation != gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED,
"mixed orientation should have been resolved");
if (!aFont) {
return NS_OK;
}
@ -995,7 +998,8 @@ gfxTextRun::AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
// Don't append a run if the font is already the one we want
if (lastGlyphRun->mFont == aFont &&
lastGlyphRun->mMatchType == aMatchType)
lastGlyphRun->mMatchType == aMatchType &&
lastGlyphRun->mOrientation == aOrientation)
{
return NS_OK;
}
@ -1009,7 +1013,8 @@ gfxTextRun::AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
// adjacent runs with the same font
if (numGlyphRuns > 1 &&
mGlyphRuns[numGlyphRuns - 2].mFont == aFont &&
mGlyphRuns[numGlyphRuns - 2].mMatchType == aMatchType)
mGlyphRuns[numGlyphRuns - 2].mMatchType == aMatchType &&
mGlyphRuns[numGlyphRuns - 2].mOrientation == aOrientation)
{
mGlyphRuns.TruncateLength(numGlyphRuns - 1);
return NS_OK;
@ -1017,6 +1022,7 @@ gfxTextRun::AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
lastGlyphRun->mFont = aFont;
lastGlyphRun->mMatchType = aMatchType;
lastGlyphRun->mOrientation = aOrientation;
return NS_OK;
}
}
@ -1030,6 +1036,7 @@ gfxTextRun::AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
glyphRun->mFont = aFont;
glyphRun->mCharacterOffset = aUTF16Offset;
glyphRun->mMatchType = aMatchType;
glyphRun->mOrientation = aOrientation;
return NS_OK;
}
@ -1047,9 +1054,10 @@ gfxTextRun::SortGlyphRuns()
mGlyphRuns.Clear();
uint32_t i, count = runs.Length();
for (i = 0; i < count; ++i) {
// a GlyphRun with the same font as the previous GlyphRun can just
// be skipped; the last GlyphRun will cover its character range.
if (i == 0 || runs[i].mFont != runs[i - 1].mFont) {
// a GlyphRun with the same font and orientation as the previous can
// just be skipped; the last GlyphRun will cover its character range.
if (i == 0 || runs[i].mFont != runs[i - 1].mFont ||
runs[i].mOrientation != runs[i - 1].mOrientation) {
mGlyphRuns.AppendElement(runs[i]);
// If two fonts have the same character offset, Sort() will have
// randomized the order.
@ -1201,7 +1209,8 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
"Ended font run in the middle of a cluster");
nsresult rv = AddGlyphRun(font, iter.GetGlyphRun()->mMatchType,
start - aStart + aDest, false);
start - aStart + aDest, false,
iter.GetGlyphRun()->mOrientation);
if (NS_FAILED(rv))
return;
}
@ -1218,32 +1227,37 @@ gfxTextRun::ClearGlyphsAndCharacters()
void
gfxTextRun::SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext,
uint32_t aCharIndex)
uint32_t aCharIndex, uint16_t aOrientation)
{
if (SetSpaceGlyphIfSimple(aFont, aContext, aCharIndex, ' ')) {
if (SetSpaceGlyphIfSimple(aFont, aContext, aCharIndex, ' ',
aOrientation)) {
return;
}
aFont->InitWordCache();
static const uint8_t space = ' ';
uint32_t flags = gfxTextRunFactory::TEXT_IS_8BIT |
gfxTextRunFactory::TEXT_IS_ASCII |
gfxTextRunFactory::TEXT_IS_PERSISTENT |
aOrientation;
gfxShapedWord *sw = aFont->GetShapedWord(aContext,
&space, 1,
gfxShapedWord::HashMix(0, ' '),
MOZ_SCRIPT_LATIN,
mAppUnitsPerDevUnit,
gfxTextRunFactory::TEXT_IS_8BIT |
gfxTextRunFactory::TEXT_IS_ASCII |
gfxTextRunFactory::TEXT_IS_PERSISTENT,
flags,
nullptr);
if (sw) {
AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false);
AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false,
aOrientation);
CopyGlyphDataFrom(sw, aCharIndex);
}
}
bool
gfxTextRun::SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext,
uint32_t aCharIndex, char16_t aSpaceChar)
uint32_t aCharIndex, char16_t aSpaceChar,
uint16_t aOrientation)
{
uint32_t spaceGlyph = aFont->GetSpaceGlyph();
if (!spaceGlyph || !CompressedGlyph::IsSimpleGlyphID(spaceGlyph)) {
@ -1256,7 +1270,8 @@ gfxTextRun::SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext,
return false;
}
AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false);
AddGlyphRun(aFont, gfxTextRange::kFontGroup, aCharIndex, false,
aOrientation);
CompressedGlyph g;
g.SetSimpleGlyph(spaceWidthAppUnits, spaceGlyph);
if (aSpaceChar == ' ') {
@ -1798,18 +1813,24 @@ gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags)
return nullptr;
}
uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
orientation = TEXT_ORIENT_VERTICAL_UPRIGHT;
}
gfxFont *font = GetFontAt(0);
if (MOZ_UNLIKELY(GetStyle()->size == 0)) {
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
// them, and always create at least size 1 fonts, i.e. they still
// render something for size 0 fonts.
textRun->AddGlyphRun(font, gfxTextRange::kFontGroup, 0, false);
textRun->AddGlyphRun(font, gfxTextRange::kFontGroup, 0, false,
orientation);
}
else {
if (font->GetSpaceGlyph()) {
// Normally, the font has a cached space glyph, so we can avoid
// the cost of calling FindFontForChar.
textRun->SetSpaceGlyph(font, aParams->mContext, 0);
textRun->SetSpaceGlyph(font, aParams->mContext, 0, orientation);
} else {
// In case the primary font doesn't have <space> (bug 970891),
// find one that does.
@ -1817,7 +1838,8 @@ gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, uint32_t aFlags)
nsRefPtr<gfxFont> spaceFont =
FindFontForChar(' ', 0, MOZ_SCRIPT_LATIN, nullptr, &matchType);
if (spaceFont) {
textRun->SetSpaceGlyph(spaceFont, aParams->mContext, 0);
textRun->SetSpaceGlyph(spaceFont, aParams->mContext, 0,
orientation);
}
}
}
@ -1838,7 +1860,12 @@ gfxFontGroup::MakeBlankTextRun(uint32_t aLength,
return nullptr;
}
textRun->AddGlyphRun(GetFontAt(0), gfxTextRange::kFontGroup, 0, false);
uint16_t orientation = aFlags & TEXT_ORIENT_MASK;
if (orientation == TEXT_ORIENT_VERTICAL_MIXED) {
orientation = TEXT_ORIENT_VERTICAL_UPRIGHT;
}
textRun->AddGlyphRun(GetFontAt(0), gfxTextRange::kFontGroup, 0, false,
orientation);
return textRun;
}
@ -2124,7 +2151,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
uint32_t runStart = 0;
nsAutoTArray<gfxTextRange,3> fontRanges;
ComputeRanges(fontRanges, aString, aLength, aRunScript);
ComputeRanges(fontRanges, aString, aLength, aRunScript,
aTextRun->GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK);
uint32_t numRanges = fontRanges.Length();
for (uint32_t r = 0; r < numRanges; r++) {
@ -2137,7 +2165,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
// common case - just do glyph layout and record the
// resulting positioned glyphs
aTextRun->AddGlyphRun(matchedFont, range.matchType,
aOffset + runStart, (matchedLength > 0));
aOffset + runStart, (matchedLength > 0),
range.orientation);
if (!matchedFont->SplitAndInitTextRun(aContext, aTextRun,
aString + runStart,
aOffset + runStart,
@ -2175,7 +2204,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
nsRefPtr<gfxFont> subSuperFont =
matchedFont->GetSubSuperscriptFont(aTextRun->GetAppUnitsPerDevUnit());
aTextRun->AddGlyphRun(subSuperFont, range.matchType,
aOffset + runStart, (matchedLength > 0));
aOffset + runStart, (matchedLength > 0),
range.orientation);
if (!subSuperFont->SplitAndInitTextRun(aContext, aTextRun,
aString + runStart,
aOffset + runStart,
@ -2197,6 +2227,7 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
aOffset + runStart,
matchedLength,
range.matchType,
range.orientation,
aRunScript,
syntheticLower,
syntheticUpper)) {
@ -2217,7 +2248,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
// do glyph layout and record the resulting positioned glyphs
aTextRun->AddGlyphRun(matchedFont, range.matchType,
aOffset + runStart, (matchedLength > 0));
aOffset + runStart, (matchedLength > 0),
range.orientation);
if (!matchedFont->SplitAndInitTextRun(aContext, aTextRun,
aString + runStart,
aOffset + runStart,
@ -2229,7 +2261,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
}
} else {
aTextRun->AddGlyphRun(mainFont, gfxTextRange::kFontGroup,
aOffset + runStart, (matchedLength > 0));
aOffset + runStart, (matchedLength > 0),
range.orientation);
}
if (!matchedFont) {
@ -2483,7 +2516,7 @@ gfxFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh,
template<typename T>
void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
const T *aString, uint32_t aLength,
int32_t aRunScript)
int32_t aRunScript, uint16_t aOrientation)
{
NS_ASSERTION(aRanges.Length() == 0, "aRanges must be initially empty");
NS_ASSERTION(aLength > 0, "don't call ComputeRanges for zero-length text");
@ -2536,19 +2569,36 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
prevCh = ch;
uint16_t orient = aOrientation;
if (aOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED) {
// For CSS text-orientation:mixed, we need to resolve orientation
// on a per-character basis using the UTR50 orientation property.
switch (GetVerticalOrientation(ch)) {
case VERTICAL_ORIENTATION_U:
case VERTICAL_ORIENTATION_Tr:
case VERTICAL_ORIENTATION_Tu:
orient = TEXT_ORIENT_VERTICAL_UPRIGHT;
break;
case VERTICAL_ORIENTATION_R:
orient = TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
break;
}
}
if (lastRangeIndex == -1) {
// first char ==> make a new range
aRanges.AppendElement(gfxTextRange(0, 1, font, matchType));
aRanges.AppendElement(gfxTextRange(0, 1, font, matchType, orient));
lastRangeIndex++;
prevFont = font;
} else {
// if font has changed, make a new range
gfxTextRange& prevRange = aRanges[lastRangeIndex];
if (prevRange.font != font || prevRange.matchType != matchType) {
if (prevRange.font != font || prevRange.matchType != matchType ||
prevRange.orientation != orient) {
// close out the previous range
prevRange.end = origI;
aRanges.AppendElement(gfxTextRange(origI, i + 1,
font, matchType));
font, matchType, orient));
lastRangeIndex++;
// update prevFont for the next match, *unless* we switched

View File

@ -411,6 +411,7 @@ public:
nsRefPtr<gfxFont> mFont; // never null
uint32_t mCharacterOffset; // into original UTF16 string
uint8_t mMatchType;
uint16_t mOrientation; // gfxTextRunFactory::TEXT_ORIENT_* value
};
class GlyphRunIterator {
@ -467,7 +468,8 @@ public:
* TextRun.
*/
nsresult AddGlyphRun(gfxFont *aFont, uint8_t aMatchType,
uint32_t aStartCharIndex, bool aForceNewRun);
uint32_t aStartCharIndex, bool aForceNewRun,
uint16_t aOrientation);
void ResetGlyphRuns() { mGlyphRuns.Clear(); }
void SortGlyphRuns();
void SanitizeGlyphRuns();
@ -480,7 +482,8 @@ public:
// clean out results from shaping in progress, used for fallback scenarios
void ClearGlyphsAndCharacters();
void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, uint32_t aCharIndex);
void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, uint32_t aCharIndex,
uint16_t aOrientation);
// Set the glyph data for the given character index to the font's
// space glyph, IF this can be done as a "simple" glyph record
@ -496,7 +499,8 @@ public:
// if it returns false, the caller needs to fall back to some other
// means to create the necessary (detailed) glyph data.
bool SetSpaceGlyphIfSimple(gfxFont *aFont, gfxContext *aContext,
uint32_t aCharIndex, char16_t aSpaceChar);
uint32_t aCharIndex, char16_t aSpaceChar,
uint16_t aOrientation);
// Record the positions of specific characters that layout may need to
// detect in the textrun, even though it doesn't have an explicit copy
@ -865,7 +869,7 @@ public:
template<typename T>
void ComputeRanges(nsTArray<gfxTextRange>& mRanges,
const T *aString, uint32_t aLength,
int32_t aRunScript);
int32_t aRunScript, uint16_t aOrientation);
gfxUserFontSet* GetUserFontSet();

View File

@ -5632,6 +5632,41 @@ nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
default:
break;
}
WritingMode wm(aStyleContext->StyleVisibility());
if (wm.IsVertical()) {
switch (aStyleText->mTextOrientation) {
case NS_STYLE_TEXT_ORIENTATION_MIXED:
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED;
break;
case NS_STYLE_TEXT_ORIENTATION_UPRIGHT:
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
break;
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS:
// This should depend on writing mode vertical-lr vs vertical-rl,
// but until we support SIDEWAYS_LEFT, we'll treat this the same
// as SIDEWAYS_RIGHT and simply fall through.
/*
if (wm.IsVerticalLR()) {
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT;
} else {
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
}
break;
*/
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_RIGHT:
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
break;
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_LEFT:
// Not yet supported, so fall through to the default (error) case.
/*
result |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT;
break;
*/
default:
NS_NOTREACHED("unknown text-orientation");
break;
}
}
return result;
}

View File

@ -133,7 +133,7 @@ MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
while (iter.NextRun()) {
gfxTextRun::GlyphRun* run = iter.GetGlyphRun();
nsresult rv = aDest->AddGlyphRun(run->mFont, run->mMatchType,
offset, false);
offset, false, run->mOrientation);
if (NS_FAILED(rv))
return;

View File

@ -553,7 +553,9 @@ nsOpenTypeTable::MakeTextRun(gfxContext* aThebesContext,
};
gfxTextRun* textRun = gfxTextRun::Create(&params, 1, aFontGroup, 0);
textRun->AddGlyphRun(aFontGroup->GetFontAt(0), gfxTextRange::kFontGroup, 0,
false);
false, gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL);
// We don't care about CSS writing mode here;
// math runs are assumed to be horizontal.
gfxTextRun::DetailedGlyph detailedGlyph;
detailedGlyph.mGlyphID = aGlyph.glyphID;
detailedGlyph.mAdvance =