зеркало из https://github.com/mozilla/gecko-dev.git
Display one hex box with six digits for non-BMP codepoints with no glyph. Bug 376532, r+sr+a=roc
This commit is contained in:
Родитель
372aa77573
Коммит
e011fa00ec
|
@ -1068,7 +1068,7 @@ public:
|
|||
*/
|
||||
void SetDetailedGlyphs(PRUint32 aCharIndex, const DetailedGlyph *aGlyphs,
|
||||
PRUint32 aNumGlyphs);
|
||||
void SetMissingGlyph(PRUint32 aCharIndex, PRUnichar aChar);
|
||||
void SetMissingGlyph(PRUint32 aCharIndex, PRUint32 aChar);
|
||||
void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, PRUint32 aCharIndex);
|
||||
|
||||
// API for access to the raw glyph data, needed by gfxFont::Draw
|
||||
|
|
|
@ -693,7 +693,8 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
Fixed *aBaselineDeltas, PRUint32 aAppUnitsPerDevUnit,
|
||||
gfxTextRun *aRun, PRUint32 aSegmentStart,
|
||||
const PRPackedBool *aUnmatched,
|
||||
const PRUnichar *aString)
|
||||
const PRUnichar *aString,
|
||||
const PRUint32 aLength)
|
||||
{
|
||||
NS_ASSERTION(aGlyphCount > 0, "Must set at least one glyph");
|
||||
PRUint32 firstOffset = aGlyphs[0].originalOffset;
|
||||
|
@ -727,7 +728,15 @@ SetGlyphsForCharacterGroup(ATSLayoutRecord *aGlyphs, PRUint32 aGlyphCount,
|
|||
if (!allMatched) {
|
||||
for (i = firstOffset; i <= lastOffset; ++i) {
|
||||
PRUint32 index = i/2;
|
||||
aRun->SetMissingGlyph(aSegmentStart + index, aString[index]);
|
||||
if (NS_IS_HIGH_SURROGATE(aString[index]) &&
|
||||
index + 1 < aLength &&
|
||||
NS_IS_LOW_SURROGATE(aString[index + 1])) {
|
||||
aRun->SetMissingGlyph(aSegmentStart + index,
|
||||
SURROGATE_TO_UCS4(aString[index],
|
||||
aString[index + 1]));
|
||||
} else {
|
||||
aRun->SetMissingGlyph(aSegmentStart + index, aString[index]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -888,12 +897,12 @@ PostLayoutCallback(ATSULineRef aLine, gfxTextRun *aRun,
|
|||
glyphCount,
|
||||
baselineDeltas ? baselineDeltas + numGlyphs - glyphCount : nsnull,
|
||||
appUnitsPerDevUnit, aRun, aSegmentStart,
|
||||
aUnmatched, aString);
|
||||
aUnmatched, aString, aSegmentLength);
|
||||
} else {
|
||||
SetGlyphsForCharacterGroup(glyphRecords,
|
||||
glyphCount, baselineDeltas,
|
||||
appUnitsPerDevUnit, aRun, aSegmentStart,
|
||||
aUnmatched, aString);
|
||||
aUnmatched, aString, aSegmentLength);
|
||||
glyphRecords += glyphCount;
|
||||
if (baselineDeltas) {
|
||||
baselineDeltas += glyphCount;
|
||||
|
|
|
@ -1559,7 +1559,7 @@ gfxTextRun::SetDetailedGlyphs(PRUint32 aIndex, const DetailedGlyph *aGlyphs,
|
|||
}
|
||||
|
||||
void
|
||||
gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUnichar aChar)
|
||||
gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUint32 aChar)
|
||||
{
|
||||
DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
|
||||
if (!details)
|
||||
|
@ -1569,7 +1569,7 @@ gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUnichar aChar)
|
|||
details->mGlyphID = aChar;
|
||||
GlyphRun *glyphRun = &mGlyphRuns[FindFirstGlyphRunContaining(aIndex)];
|
||||
gfxFloat width = PR_MAX(glyphRun->mFont->GetMetrics().aveCharWidth,
|
||||
gfxFontMissingGlyphs::GetDesiredMinWidth());
|
||||
gfxFontMissingGlyphs::GetDesiredMinWidth(aChar));
|
||||
details->mAdvance = PRUint32(width*GetAppUnitsPerDevUnit());
|
||||
details->mXOffset = 0;
|
||||
details->mYOffset = 0;
|
||||
|
|
|
@ -126,22 +126,25 @@ static const PRUint16 glyphMicroFont[16] = {
|
|||
};
|
||||
|
||||
/* Parameters that control the rendering of hexboxes. They look like this:
|
||||
|
||||
+---------+
|
||||
| |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| HHH HHH |
|
||||
| |
|
||||
+---------+
|
||||
|
||||
BMP codepoints non-BMP codepoints
|
||||
(U+0000 - U+FFFF) (U+10000 - U+10FFFF)
|
||||
|
||||
+---------+ +-------------+
|
||||
| | | |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| | | |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| HHH HHH | | HHH HHH HHH |
|
||||
| | | |
|
||||
+---------+ +-------------+
|
||||
*/
|
||||
|
||||
/** Width of a minifont glyph (see above) */
|
||||
|
@ -166,15 +169,6 @@ static const int BOX_BORDER_WIDTH = 1;
|
|||
* opacity being used to draw the text.
|
||||
*/
|
||||
static const gfxFloat BOX_BORDER_OPACITY = 0.5;
|
||||
/**
|
||||
* The minimum desired width for a missing-glyph glyph box. I've laid it out
|
||||
* like this so you can see what goes where.
|
||||
*/
|
||||
static const int MIN_DESIRED_WIDTH =
|
||||
BOX_HORIZONTAL_INSET + BOX_BORDER_WIDTH + HEX_CHAR_GAP +
|
||||
MINIFONT_WIDTH + HEX_CHAR_GAP + MINIFONT_WIDTH +
|
||||
HEX_CHAR_GAP + BOX_BORDER_WIDTH + BOX_HORIZONTAL_INSET;
|
||||
|
||||
/**
|
||||
* Draw a single hex character using the current color. A nice way to do this
|
||||
* would be to fill in an A8 image surface and then use it as a mask
|
||||
|
@ -201,7 +195,7 @@ DrawHexChar(gfxContext *aContext, const gfxPoint& aPt, PRUint32 aDigit)
|
|||
|
||||
void
|
||||
gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext *aContext, const gfxRect& aRect,
|
||||
PRUnichar aChar)
|
||||
PRUint32 aChar)
|
||||
{
|
||||
aContext->Save();
|
||||
|
||||
|
@ -233,29 +227,60 @@ gfxFontMissingGlyphs::DrawMissingGlyph(gfxContext *aContext, const gfxRect& aRec
|
|||
aContext->Stroke();
|
||||
}
|
||||
|
||||
if (aRect.Width() >= 2*MINIFONT_WIDTH + HEX_CHAR_GAP &&
|
||||
aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
|
||||
aContext->SetColor(currentColor);
|
||||
gfxPoint center(aRect.X() + aRect.Width()/2,
|
||||
aRect.Y() + aRect.Height()/2);
|
||||
gfxFloat halfGap = HEX_CHAR_GAP/2.0;
|
||||
gfxFloat left = -(MINIFONT_WIDTH + halfGap);
|
||||
gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(left, top), (aChar >> 12) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(halfGap, top), (aChar >> 8) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(left, halfGap), (aChar >> 4) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(halfGap, halfGap), aChar & 0xF);
|
||||
gfxPoint center(aRect.X() + aRect.Width()/2,
|
||||
aRect.Y() + aRect.Height()/2);
|
||||
gfxFloat halfGap = HEX_CHAR_GAP/2.0;
|
||||
gfxFloat top = -(MINIFONT_HEIGHT + halfGap);
|
||||
if (aChar < 0x10000) {
|
||||
if (aRect.Width() >= 2*MINIFONT_WIDTH + HEX_CHAR_GAP &&
|
||||
aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
|
||||
// Draw 4 digits for BMP
|
||||
aContext->SetColor(currentColor);
|
||||
gfxFloat left = -(MINIFONT_WIDTH + halfGap);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(left, top), (aChar >> 12) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(halfGap, top), (aChar >> 8) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(left, halfGap), (aChar >> 4) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(halfGap, halfGap), aChar & 0xF);
|
||||
}
|
||||
} else {
|
||||
if (aRect.Width() >= 3*MINIFONT_WIDTH + 2*HEX_CHAR_GAP &&
|
||||
aRect.Height() >= 2*MINIFONT_HEIGHT + HEX_CHAR_GAP) {
|
||||
// Draw 6 digits for non-BMP
|
||||
aContext->SetColor(currentColor);
|
||||
gfxFloat first = -(MINIFONT_WIDTH * 1.5 + HEX_CHAR_GAP);
|
||||
gfxFloat second = -(MINIFONT_WIDTH / 2.0);
|
||||
gfxFloat third = (MINIFONT_WIDTH / 2.0 + HEX_CHAR_GAP);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(first, top), (aChar >> 20) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(second, top), (aChar >> 16) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(third, top), (aChar >> 12) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(first, halfGap), (aChar >> 8) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(second, halfGap), (aChar >> 4) & 0xF);
|
||||
DrawHexChar(aContext,
|
||||
center + gfxPoint(third, halfGap), aChar & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
aContext->Restore();
|
||||
}
|
||||
|
||||
gfxFloat
|
||||
gfxFontMissingGlyphs::GetDesiredMinWidth()
|
||||
gfxFontMissingGlyphs::GetDesiredMinWidth(PRUint32 aChar)
|
||||
{
|
||||
return MIN_DESIRED_WIDTH;
|
||||
/**
|
||||
* The minimum desired width for a missing-glyph glyph box. I've laid it out
|
||||
* like this so you can see what goes where.
|
||||
*/
|
||||
return BOX_HORIZONTAL_INSET + BOX_BORDER_WIDTH + HEX_CHAR_GAP +
|
||||
MINIFONT_WIDTH + HEX_CHAR_GAP + MINIFONT_WIDTH +
|
||||
((aChar < 0x10000) ? 0 : HEX_CHAR_GAP + MINIFONT_WIDTH) +
|
||||
HEX_CHAR_GAP + BOX_BORDER_WIDTH + BOX_HORIZONTAL_INSET;
|
||||
}
|
||||
|
|
|
@ -56,12 +56,12 @@ public:
|
|||
* @param aChar the UTF16 codepoint for the character
|
||||
*/
|
||||
static void DrawMissingGlyph(gfxContext *aContext, const gfxRect& aRect,
|
||||
PRUnichar aChar);
|
||||
PRUint32 aChar);
|
||||
/**
|
||||
* @return the desired minimum width for a glyph-box that will allow
|
||||
* the hexboxes to be drawn reasonably.
|
||||
*/
|
||||
static gfxFloat GetDesiredMinWidth();
|
||||
static gfxFloat GetDesiredMinWidth(PRUint32 aChar);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -488,21 +488,6 @@ void gfxOS2FontGroup::InitTextRun(gfxTextRun *aTextRun, const PRUint8 *aUTF8Text
|
|||
aUTF8Length - aUTF8HeaderLength);
|
||||
}
|
||||
|
||||
static void SetMissingGlyphForUCS4(gfxTextRun *aTextRun, PRUint32 aIndex,
|
||||
PRUint32 aCh)
|
||||
{
|
||||
if (aCh < 0x10000) {
|
||||
aTextRun->SetMissingGlyph(aIndex, PRUnichar(aCh));
|
||||
return;
|
||||
}
|
||||
|
||||
// Display non-BMP characters as a surrogate pair
|
||||
aTextRun->SetMissingGlyph(aIndex, H_SURROGATE(aCh));
|
||||
if (aIndex + 1 < aTextRun->GetLength()) {
|
||||
aTextRun->SetMissingGlyph(aIndex + 1, L_SURROGATE(aCh));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to return the leading UTF-8 character in a char pointer
|
||||
// as 32bit number. Also sets the length of the current character (i.e. the
|
||||
// offset to the next one) in the second argument
|
||||
|
@ -587,7 +572,7 @@ void gfxOS2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun, const PRUint8 *aUT
|
|||
g.SetSimpleGlyph(advance, gid));
|
||||
} else if (gid == 0) {
|
||||
// gid = 0 only happens when the glyph is missing from the font
|
||||
SetMissingGlyphForUCS4(aTextRun, utf16Offset, ch);
|
||||
aTextRun->SetMissingGlyph(utf16Offset, ch);
|
||||
} else {
|
||||
gfxTextRun::DetailedGlyph details;
|
||||
details.mIsLastGlyph = PR_TRUE;
|
||||
|
|
|
@ -1002,21 +1002,6 @@ ConvertPangoToAppUnits(PRInt32 aCoordinate, PRUint32 aAppUnitsPerDevUnit)
|
|||
return PRInt32(v);
|
||||
}
|
||||
|
||||
static void
|
||||
SetMissingGlyphForUCS4(gfxTextRun *aTextRun, PRUint32 aIndex, gunichar aCh)
|
||||
{
|
||||
if (aCh < 0x10000) {
|
||||
aTextRun->SetMissingGlyph(aIndex, PRUnichar(aCh));
|
||||
return;
|
||||
}
|
||||
|
||||
// Display non-BMP characters as a surrogate pair
|
||||
aTextRun->SetMissingGlyph(aIndex, H_SURROGATE(aCh));
|
||||
if (aIndex + 1 < aTextRun->GetLength()) {
|
||||
aTextRun->SetMissingGlyph(aIndex + 1, L_SURROGATE(aCh));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a run of Pango glyphs that should be treated as a single
|
||||
* cluster/ligature, store them in the textrun at the appropriate character
|
||||
|
@ -1242,7 +1227,7 @@ gfxPangoFontGroup::SetMissingGlyphs(gfxTextRun *aTextRun,
|
|||
break;
|
||||
}
|
||||
gunichar ch = g_utf8_get_char(aUTF8 + index);
|
||||
SetMissingGlyphForUCS4(aTextRun, utf16Offset, ch);
|
||||
aTextRun->SetMissingGlyph(utf16Offset, ch);
|
||||
|
||||
++utf16Offset;
|
||||
NS_ASSERTION(!IS_SURROGATE(ch), "surrogates should not appear in UTF8");
|
||||
|
@ -1301,7 +1286,7 @@ gfxPangoFontGroup::CreateGlyphRunsXft(gfxTextRun *aTextRun,
|
|||
} else if (IS_MISSING_GLYPH(glyph)) {
|
||||
// Note that missing-glyph IDs are not simple glyph IDs, so we'll
|
||||
// always get here when a glyph is missing
|
||||
SetMissingGlyphForUCS4(aTextRun, utf16Offset, ch);
|
||||
aTextRun->SetMissingGlyph(utf16Offset, ch);
|
||||
} else {
|
||||
gfxTextRun::DetailedGlyph details;
|
||||
details.mIsLastGlyph = PR_TRUE;
|
||||
|
|
|
@ -1103,7 +1103,15 @@ public:
|
|||
NS_ASSERTION(!gfxFontGroup::IsInvalidChar(mRangeString[offset]),
|
||||
"invalid character detected");
|
||||
if (missing) {
|
||||
aRun->SetMissingGlyph(runOffset, mRangeString[offset]);
|
||||
if (NS_IS_HIGH_SURROGATE(mRangeString[offset]) &&
|
||||
offset + 1 < mRangeLength &&
|
||||
NS_IS_LOW_SURROGATE(mRangeString[offset + 1])) {
|
||||
aRun->SetMissingGlyph(runOffset,
|
||||
SURROGATE_TO_UCS4(mRangeString[offset],
|
||||
mRangeString[offset + 1]));
|
||||
} else {
|
||||
aRun->SetMissingGlyph(runOffset, mRangeString[offset]);
|
||||
}
|
||||
} else if (glyphCount == 1 && advance >= 0 &&
|
||||
mOffsets[k].dv == 0 && mOffsets[k].du == 0 &&
|
||||
gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче