Bug 1040668 part 8 - Setup text emphasis for text run. r=jfkthame

--HG--
extra : source : 4f5398b5953c0cf4d57ed0fce5788f1430a5b05d
This commit is contained in:
Xidorn Quan 2015-11-28 11:56:33 +11:00
Родитель d80f4dcc15
Коммит 376cdf821b
1 изменённых файлов: 69 добавлений и 0 удалений

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

@ -17,6 +17,7 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/TextEvents.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/IntegerRange.h"
#include "nsCOMPtr.h"
#include "nsBlockFrame.h"
@ -926,6 +927,7 @@ public:
void AssignTextRun(gfxTextRun* aTextRun, float aInflation);
nsTextFrame* GetNextBreakBeforeFrame(uint32_t* aIndex);
void SetupBreakSinksForTextRun(gfxTextRun* aTextRun, const void* aTextPtr);
void SetupTextEmphasisForTextRun(gfxTextRun* aTextRun, const void* aTextPtr);
struct FindBoundaryState {
nsIFrame* mStopAtFrame;
nsTextFrame* mFirstTextFrame;
@ -1900,6 +1902,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
const void* textPtr = aTextBuffer;
bool anyTextTransformStyle = false;
bool anyMathMLStyling = false;
bool anyTextEmphasis = false;
uint8_t sstyScriptLevel = 0;
uint32_t mathFlags = 0;
uint32_t textFlags = nsTextFrameUtils::TEXT_NO_BREAKS;
@ -1968,6 +1971,9 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) {
anyTextTransformStyle = true;
}
if (textStyle->HasTextEmphasis()) {
anyTextEmphasis = true;
}
textFlags |= GetSpacingFlags(f);
nsTextFrameUtils::CompressionMode compression =
GetCSSWhitespaceToCompressionMode(f, textStyle);
@ -2256,6 +2262,10 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
// making up the textrun, but I don't see a way to avoid this.
SetupBreakSinksForTextRun(textRun, textPtr);
if (anyTextEmphasis) {
SetupTextEmphasisForTextRun(textRun, textPtr);
}
if (mSkipIncompleteTextRuns) {
mSkipIncompleteTextRuns = !TextContainsLineBreakerWhiteSpace(textPtr,
transformedLength, mDoubleByteText);
@ -2489,6 +2499,65 @@ BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
}
}
static bool
MayCharacterHaveEmphasisMark(uint32_t aCh)
{
auto category = unicode::GetGeneralCategory(aCh);
// Comparing an unsigned variable against zero is a compile error,
// so we use static assert here to ensure we really don't need to
// compare it with the given constant.
static_assert(IsUnsigned<decltype(category)>::value &&
HB_UNICODE_GENERAL_CATEGORY_CONTROL == 0,
"if this constant is not zero, or category is signed, "
"we need to explicitly do the comparison below");
return !(category <= HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED ||
(category >= HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR &&
category <= HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR));
}
static bool
MayCharacterHaveEmphasisMark(uint8_t aCh)
{
// 0x00~0x1f and 0x7f~0x9f are in category Cc
// 0x20 and 0xa0 are in category Zs
bool result = !(aCh <= 0x20 || (aCh >= 0x7f && aCh <= 0xa0));
MOZ_ASSERT(result == MayCharacterHaveEmphasisMark(uint32_t(aCh)),
"result for uint8_t should match result for uint32_t");
return result;
}
void
BuildTextRunsScanner::SetupTextEmphasisForTextRun(gfxTextRun* aTextRun,
const void* aTextPtr)
{
if (!mDoubleByteText) {
auto text = reinterpret_cast<const uint8_t*>(aTextPtr);
for (auto i : MakeRange(aTextRun->GetLength())) {
if (!MayCharacterHaveEmphasisMark(text[i])) {
aTextRun->SetNoEmphasisMark(i);
}
}
} else {
auto text = reinterpret_cast<const char16_t*>(aTextPtr);
auto length = aTextRun->GetLength();
for (size_t i = 0; i < length; ++i) {
if (NS_IS_HIGH_SURROGATE(text[i]) && i + 1 < length &&
NS_IS_LOW_SURROGATE(text[i + 1])) {
uint32_t ch = SURROGATE_TO_UCS4(text[i], text[i + 1]);
if (!MayCharacterHaveEmphasisMark(ch)) {
aTextRun->SetNoEmphasisMark(i);
aTextRun->SetNoEmphasisMark(i + 1);
}
++i;
} else {
if (!MayCharacterHaveEmphasisMark(uint32_t(text[i]))) {
aTextRun->SetNoEmphasisMark(i);
}
}
}
}
}
// Find the flow corresponding to aContent in aUserData
static inline TextRunMappedFlow*
FindFlowForContent(TextRunUserData* aUserData, nsIContent* aContent)