зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1113684 - part 1 - Handle vertical writing modes when displaying alt-text alongside a broken-image icon. r=smontagu
This commit is contained in:
Родитель
b1289a8906
Коммит
c6f6059f08
|
@ -1100,14 +1100,23 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||||
|
|
||||||
nscoord maxAscent = fm->MaxAscent();
|
nscoord maxAscent = fm->MaxAscent();
|
||||||
nscoord maxDescent = fm->MaxDescent();
|
nscoord maxDescent = fm->MaxDescent();
|
||||||
nscoord height = fm->MaxHeight();
|
nscoord lineHeight = fm->MaxHeight(); // line-relative, so an x-coordinate
|
||||||
|
// length if writing mode is vertical
|
||||||
|
|
||||||
|
WritingMode wm = GetWritingMode();
|
||||||
|
bool isVertical = wm.IsVertical();
|
||||||
|
|
||||||
|
fm->SetVertical(isVertical);
|
||||||
|
fm->SetTextOrientation(StyleVisibility()->mTextOrientation);
|
||||||
|
|
||||||
// XXX It would be nice if there was a way to have the font metrics tell
|
// XXX It would be nice if there was a way to have the font metrics tell
|
||||||
// use where to break the text given a maximum width. At a minimum we need
|
// use where to break the text given a maximum width. At a minimum we need
|
||||||
// to be able to get the break character...
|
// to be able to get the break character...
|
||||||
const char16_t* str = aAltText.get();
|
const char16_t* str = aAltText.get();
|
||||||
int32_t strLen = aAltText.Length();
|
int32_t strLen = aAltText.Length();
|
||||||
nscoord y = aRect.y;
|
nsPoint pt = wm.IsVerticalRL() ? aRect.TopRight() - nsPoint(lineHeight, 0)
|
||||||
|
: aRect.TopLeft();
|
||||||
|
nscoord iSize = isVertical ? aRect.height : aRect.width;
|
||||||
|
|
||||||
if (!aPresContext->BidiEnabled() && HasRTLChars(aAltText)) {
|
if (!aPresContext->BidiEnabled() && HasRTLChars(aAltText)) {
|
||||||
aPresContext->SetBidiEnabled();
|
aPresContext->SetBidiEnabled();
|
||||||
|
@ -1115,38 +1124,71 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
|
||||||
|
|
||||||
// Always show the first line, even if we have to clip it below
|
// Always show the first line, even if we have to clip it below
|
||||||
bool firstLine = true;
|
bool firstLine = true;
|
||||||
while ((strLen > 0) && (firstLine || (y + maxDescent) < aRect.YMost())) {
|
while (strLen > 0) {
|
||||||
|
if (!firstLine) {
|
||||||
|
// If we've run out of space, break out of the loop
|
||||||
|
if ((!isVertical && (pt.y + maxDescent) >= aRect.YMost()) ||
|
||||||
|
(wm.IsVerticalRL() && (pt.x + maxDescent < aRect.x)) ||
|
||||||
|
(wm.IsVerticalLR() && (pt.x + maxDescent >= aRect.XMost()))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine how much of the text to display on this line
|
// Determine how much of the text to display on this line
|
||||||
uint32_t maxFit; // number of characters that fit
|
uint32_t maxFit; // number of characters that fit
|
||||||
nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
|
nscoord strWidth = MeasureString(str, strLen, iSize, maxFit,
|
||||||
aRenderingContext, *fm);
|
aRenderingContext, *fm);
|
||||||
|
|
||||||
// Display the text
|
// Display the text
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
|
|
||||||
if (aPresContext->BidiEnabled()) {
|
if (aPresContext->BidiEnabled()) {
|
||||||
const nsStyleVisibility* vis = StyleVisibility();
|
nsBidiDirection dir;
|
||||||
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
|
nscoord x, y;
|
||||||
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
|
|
||||||
aPresContext, aRenderingContext,
|
if (isVertical) {
|
||||||
aRenderingContext, *fm,
|
x = pt.x + maxDescent; // XXX will need update for sideways-left
|
||||||
aRect.XMost() - strWidth, y + maxAscent);
|
if (wm.IsBidiLTR()) {
|
||||||
else
|
y = aRect.y;
|
||||||
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
|
dir = NSBIDI_LTR;
|
||||||
aPresContext, aRenderingContext,
|
} else {
|
||||||
aRenderingContext, *fm,
|
y = aRect.YMost() - strWidth;
|
||||||
aRect.x, y + maxAscent);
|
dir = NSBIDI_RTL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
y = pt.y + maxAscent;
|
||||||
|
if (wm.IsBidiLTR()) {
|
||||||
|
x = aRect.x;
|
||||||
|
dir = NSBIDI_LTR;
|
||||||
|
} else {
|
||||||
|
x = aRect.XMost() - strWidth;
|
||||||
|
dir = NSBIDI_RTL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = nsBidiPresUtils::RenderText(str, maxFit, dir,
|
||||||
|
aPresContext, aRenderingContext,
|
||||||
|
aRenderingContext, *fm, x, y);
|
||||||
}
|
}
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
nsLayoutUtils::DrawUniDirString(str, maxFit,
|
nsLayoutUtils::DrawUniDirString(str, maxFit,
|
||||||
nsPoint(aRect.x, y + maxAscent), *fm,
|
isVertical
|
||||||
aRenderingContext);
|
? nsPoint(pt.x + maxDescent, pt.y)
|
||||||
|
: nsPoint(pt.x, pt.y + maxAscent),
|
||||||
|
*fm, aRenderingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next line
|
// Move to the next line
|
||||||
str += maxFit;
|
str += maxFit;
|
||||||
strLen -= maxFit;
|
strLen -= maxFit;
|
||||||
y += height;
|
if (wm.IsVerticalRL()) {
|
||||||
|
pt.x -= lineHeight;
|
||||||
|
} else if (wm.IsVerticalLR()) {
|
||||||
|
pt.x += lineHeight;
|
||||||
|
} else {
|
||||||
|
pt.y += lineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
firstLine = false;
|
firstLine = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1247,7 +1289,6 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
||||||
|
|
||||||
// Check if we should display image placeholders
|
// Check if we should display image placeholders
|
||||||
if (gIconLoad->mPrefShowPlaceholders) {
|
if (gIconLoad->mPrefShowPlaceholders) {
|
||||||
const nsStyleVisibility* vis = StyleVisibility();
|
|
||||||
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
|
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
|
||||||
|
|
||||||
bool iconUsed = false;
|
bool iconUsed = false;
|
||||||
|
@ -1260,6 +1301,9 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
||||||
mDisplayingIcon = true;
|
mDisplayingIcon = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WritingMode wm = GetWritingMode();
|
||||||
|
bool flushRight =
|
||||||
|
(!wm.IsVertical() && !wm.IsBidiLTR()) || wm.IsVerticalRL();
|
||||||
|
|
||||||
// If the icon in question is loaded and decoded, draw it
|
// If the icon in question is loaded and decoded, draw it
|
||||||
uint32_t imageStatus = 0;
|
uint32_t imageStatus = 0;
|
||||||
|
@ -1269,8 +1313,7 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
||||||
nsCOMPtr<imgIContainer> imgCon;
|
nsCOMPtr<imgIContainer> imgCon;
|
||||||
aRequest->GetImage(getter_AddRefs(imgCon));
|
aRequest->GetImage(getter_AddRefs(imgCon));
|
||||||
MOZ_ASSERT(imgCon, "Load complete, but no image container?");
|
MOZ_ASSERT(imgCon, "Load complete, but no image container?");
|
||||||
nsRect dest((vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
|
nsRect dest(flushRight ? inner.XMost() - size : inner.x,
|
||||||
inner.XMost() - size : inner.x,
|
|
||||||
inner.y, size, size);
|
inner.y, size, size);
|
||||||
nsLayoutUtils::DrawSingleImage(*gfx, PresContext(), imgCon,
|
nsLayoutUtils::DrawSingleImage(*gfx, PresContext(), imgCon,
|
||||||
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
|
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
|
||||||
|
@ -1283,8 +1326,7 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
||||||
if (!iconUsed) {
|
if (!iconUsed) {
|
||||||
ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
|
ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
|
||||||
|
|
||||||
nscoord iconXPos = (vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
|
nscoord iconXPos = flushRight ? inner.XMost() - size : inner.x;
|
||||||
inner.XMost() - size : inner.x;
|
|
||||||
|
|
||||||
// stroked rect:
|
// stroked rect:
|
||||||
nsRect rect(iconXPos, inner.y, size, size);
|
nsRect rect(iconXPos, inner.y, size, size);
|
||||||
|
@ -1306,10 +1348,17 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
|
||||||
|
|
||||||
// Reduce the inner rect by the width of the icon, and leave an
|
// Reduce the inner rect by the width of the icon, and leave an
|
||||||
// additional ICON_PADDING pixels for padding
|
// additional ICON_PADDING pixels for padding
|
||||||
int32_t iconWidth = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
|
int32_t paddedIconSize =
|
||||||
if (vis->mDirection != NS_STYLE_DIRECTION_RTL)
|
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
|
||||||
inner.x += iconWidth;
|
if (wm.IsVertical()) {
|
||||||
inner.width -= iconWidth;
|
inner.y += paddedIconSize;
|
||||||
|
inner.height -= paddedIconSize;
|
||||||
|
} else {
|
||||||
|
if (!flushRight) {
|
||||||
|
inner.x += paddedIconSize;
|
||||||
|
}
|
||||||
|
inner.width -= paddedIconSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's still room, display the alt-text
|
// If there's still room, display the alt-text
|
||||||
|
|
Загрузка…
Ссылка в новой задаче