mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-24 21:58:06 +00:00
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:
parent
b4f621c5f6
commit
5cadcfeab8
@ -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(¶ms, 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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -553,7 +553,9 @@ nsOpenTypeTable::MakeTextRun(gfxContext* aThebesContext,
|
||||
};
|
||||
gfxTextRun* textRun = gfxTextRun::Create(¶ms, 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 =
|
||||
|
Loading…
x
Reference in New Issue
Block a user