Bug 1308113 - Account for letter- and word-spacing when resolving tab-size <number>. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D117331
This commit is contained in:
@@ -3419,15 +3419,17 @@ void nsTextFrame::PropertyProvider::GetSpacing(Range aRange,
|
|||||||
|
|
||||||
static bool CanAddSpacingAfter(const gfxTextRun* aTextRun, uint32_t aOffset,
|
static bool CanAddSpacingAfter(const gfxTextRun* aTextRun, uint32_t aOffset,
|
||||||
bool aNewlineIsSignificant) {
|
bool aNewlineIsSignificant) {
|
||||||
if (aOffset + 1 >= aTextRun->GetLength()) return true;
|
if (aOffset + 1 >= aTextRun->GetLength()) {
|
||||||
return aTextRun->IsClusterStart(aOffset + 1) &&
|
return true;
|
||||||
aTextRun->IsLigatureGroupStart(aOffset + 1) &&
|
}
|
||||||
!aTextRun->CharIsFormattingControl(aOffset) &&
|
const auto* g = aTextRun->GetCharacterGlyphs();
|
||||||
!(aNewlineIsSignificant && aTextRun->CharIsNewline(aOffset));
|
return g[aOffset + 1].IsClusterStart() &&
|
||||||
|
g[aOffset + 1].IsLigatureGroupStart() &&
|
||||||
|
!g[aOffset].CharIsFormattingControl() && !g[aOffset].CharIsTab() &&
|
||||||
|
!(aNewlineIsSignificant && g[aOffset].CharIsNewline());
|
||||||
}
|
}
|
||||||
|
|
||||||
static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame,
|
static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame) {
|
||||||
gfxTextRun* aTextRun) {
|
|
||||||
const auto& tabSize = aFrame->StyleText()->mMozTabSize;
|
const auto& tabSize = aFrame->StyleText()->mMozTabSize;
|
||||||
if (tabSize.IsLength()) {
|
if (tabSize.IsLength()) {
|
||||||
nscoord w = tabSize.length._0.ToAppUnits();
|
nscoord w = tabSize.length._0.ToAppUnits();
|
||||||
@@ -3439,13 +3441,17 @@ static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame,
|
|||||||
gfxFloat spaces = tabSize.number._0;
|
gfxFloat spaces = tabSize.number._0;
|
||||||
MOZ_ASSERT(spaces >= 0);
|
MOZ_ASSERT(spaces >= 0);
|
||||||
|
|
||||||
// Round the space width when converting to appunits the same way
|
const nsIFrame* cb = aFrame->GetContainingBlock(0, aFrame->StyleDisplay());
|
||||||
// textruns do.
|
const auto* styleText = cb->StyleText();
|
||||||
gfxFloat spaceWidthAppUnits = NS_round(
|
|
||||||
GetFirstFontMetrics(aTextRun->GetFontGroup(), aTextRun->IsVertical())
|
// Round the space width when converting to appunits the same way textruns do.
|
||||||
.spaceWidth *
|
RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForFrame(cb, 1.0f);
|
||||||
aTextRun->GetAppUnitsPerDevUnit());
|
bool vertical = cb->GetWritingMode().IsCentralBaseline();
|
||||||
return spaces * spaceWidthAppUnits;
|
nscoord spaceWidth = nscoord(NS_round(
|
||||||
|
GetFirstFontMetrics(fm->GetThebesFontGroup(), vertical).spaceWidth *
|
||||||
|
cb->PresContext()->AppUnitsPerDevPixel()));
|
||||||
|
return spaces * (spaceWidth + styleText->mLetterSpacing.ToAppUnits() +
|
||||||
|
styleText->mWordSpacing.Resolve(spaceWidth));
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
|
void nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
|
||||||
@@ -3498,7 +3504,7 @@ void nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
|
|||||||
|
|
||||||
// Now add tab spacing, if there is any
|
// Now add tab spacing, if there is any
|
||||||
if (!aIgnoreTabs) {
|
if (!aIgnoreTabs) {
|
||||||
gfxFloat tabWidth = ComputeTabWidthAppUnits(mFrame, mTextRun);
|
gfxFloat tabWidth = ComputeTabWidthAppUnits(mFrame);
|
||||||
if (tabWidth > 0) {
|
if (tabWidth > 0) {
|
||||||
CalcTabWidths(aRange, tabWidth);
|
CalcTabWidths(aRange, tabWidth);
|
||||||
if (mTabWidths) {
|
if (mTabWidths) {
|
||||||
@@ -8476,7 +8482,7 @@ void nsTextFrame::AddInlineMinISizeForFlow(gfxContext* aRenderingContext,
|
|||||||
provider.GetSpacing(Range(i, i + 1), &spacing);
|
provider.GetSpacing(Range(i, i + 1), &spacing);
|
||||||
aData->mCurrentLine += nscoord(spacing.mBefore);
|
aData->mCurrentLine += nscoord(spacing.mBefore);
|
||||||
if (tabWidth < 0) {
|
if (tabWidth < 0) {
|
||||||
tabWidth = ComputeTabWidthAppUnits(this, textRun);
|
tabWidth = ComputeTabWidthAppUnits(this);
|
||||||
}
|
}
|
||||||
gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, tabWidth,
|
gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, tabWidth,
|
||||||
provider.MinTabAdvance());
|
provider.MinTabAdvance());
|
||||||
@@ -8646,7 +8652,7 @@ void nsTextFrame::AddInlinePrefISizeForFlow(
|
|||||||
provider.GetSpacing(Range(i, i + 1), &spacing);
|
provider.GetSpacing(Range(i, i + 1), &spacing);
|
||||||
aData->mCurrentLine += nscoord(spacing.mBefore);
|
aData->mCurrentLine += nscoord(spacing.mBefore);
|
||||||
if (tabWidth < 0) {
|
if (tabWidth < 0) {
|
||||||
tabWidth = ComputeTabWidthAppUnits(this, textRun);
|
tabWidth = ComputeTabWidthAppUnits(this);
|
||||||
}
|
}
|
||||||
gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, tabWidth,
|
gfxFloat afterTab = AdvanceToNextTab(aData->mCurrentLine, tabWidth,
|
||||||
provider.MinTabAdvance());
|
provider.MinTabAdvance());
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
p { float:left; white-space:pre; border:1px solid black; clear:both; }
|
p { float:left; white-space:pre; border:1px solid black; clear:both; }
|
||||||
.space { padding:0 2px; }
|
.letterspace { letter-spacing:4px; }
|
||||||
|
.space { padding:0 4px 0 0; }
|
||||||
table { clear:both; }
|
table { clear:both; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -20,12 +21,12 @@ table { clear:both; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<span class="space">a</span>
|
<span class="letterspace"> </span><span class="space">a</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div style="width:0">
|
<div style="width:0">
|
||||||
<p class="letterspace">
|
<p>
|
||||||
<span class="space">a</span>
|
<span class="letterspace"> </span><span class="space">a</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
p { float:left; white-space:pre; border:1px solid black; clear:both; }
|
p { float:left; white-space:pre; border:1px solid black; clear:both; }
|
||||||
.letterspace { letter-spacing:2px; }
|
.letterspace { letter-spacing:4px; }
|
||||||
table { clear:both; }
|
table { clear:both; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -19,8 +19,9 @@ table { clear:both; }
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- there should be 1px of letter-spacing after the tab, 1px before the 'a' and 2px after
|
<!-- there should be no letter-spacing after the tab, because letter-spacing is
|
||||||
the a -->
|
already incorporated into the calculation of the tab position, but there
|
||||||
|
will be 4px after the a -->
|
||||||
<p class="letterspace">
|
<p class="letterspace">
|
||||||
a
|
a
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
span { display:inline-block; width:10em; }
|
span { display:inline-block; width:10ch; }
|
||||||
|
/* first tab-position will be at 2 * (space-width + word-spacing), i.e. 22ch,
|
||||||
|
so to advance there after the 3-ch word "tab" we need 19ch of added space */
|
||||||
|
span.tab { width: 19ch; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="width: 433px; height: 590px;">
|
<body style="font-family: monospace; width: 433px; height: 590px;">
|
||||||
|
|
||||||
<table border="1">
|
<table border="1">
|
||||||
<tr><td>space <span></span>.</td>
|
<tr><td>space <span></span>.</td>
|
||||||
@@ -23,7 +26,7 @@ span { display:inline-block; width:10em; }
|
|||||||
<tr><td>ideographic-space .</td>
|
<tr><td>ideographic-space .</td>
|
||||||
<tr><td>newline
|
<tr><td>newline
|
||||||
.</td>
|
.</td>
|
||||||
<tr><td>tab	.</td>
|
<tr><td>tab<span class=tab></span>.</td>
|
||||||
<tr><td>form-feed.</td>
|
<tr><td>form-feed.</td>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ span { display:inline-block; width:10em; }
|
|||||||
<tr><td>ideographic-space .</td>
|
<tr><td>ideographic-space .</td>
|
||||||
<tr><td>newline
|
<tr><td>newline
|
||||||
.</td>
|
.</td>
|
||||||
<tr><td>tab	.</td>
|
<tr><td>tab<span class=tab></span>.</td>
|
||||||
<tr><td>form-feed.</td>
|
<tr><td>form-feed.</td>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<body style="word-spacing:10em; width: 433px; height: 590px;">
|
<body style="font-family: monospace; word-spacing:10ch; -moz-tab-size: 2; width: 433px; height: 590px;">
|
||||||
|
|
||||||
<table border="1">
|
<table border="1">
|
||||||
<tr><td>space .</td>
|
<tr><td>space .</td>
|
||||||
|
|||||||
Reference in New Issue
Block a user