Bug 1113684 - part 1 - Handle vertical writing modes when displaying alt-text alongside a broken-image icon. r=smontagu

This commit is contained in:
Jonathan Kew 2015-01-06 20:56:03 +00:00
Родитель b1289a8906
Коммит c6f6059f08
1 изменённых файлов: 78 добавлений и 29 удалений

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

@ -1100,14 +1100,23 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
nscoord maxAscent = fm->MaxAscent();
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
// use where to break the text given a maximum width. At a minimum we need
// to be able to get the break character...
const char16_t* str = aAltText.get();
int32_t strLen = aAltText.Length();
nscoord y = aRect.y;
int32_t strLen = aAltText.Length();
nsPoint pt = wm.IsVerticalRL() ? aRect.TopRight() - nsPoint(lineHeight, 0)
: aRect.TopLeft();
nscoord iSize = isVertical ? aRect.height : aRect.width;
if (!aPresContext->BidiEnabled() && HasRTLChars(aAltText)) {
aPresContext->SetBidiEnabled();
@ -1115,38 +1124,71 @@ nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
// Always show the first line, even if we have to clip it below
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
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);
// Display the text
nsresult rv = NS_ERROR_FAILURE;
if (aPresContext->BidiEnabled()) {
const nsStyleVisibility* vis = StyleVisibility();
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
aPresContext, aRenderingContext,
aRenderingContext, *fm,
aRect.XMost() - strWidth, y + maxAscent);
else
rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
aPresContext, aRenderingContext,
aRenderingContext, *fm,
aRect.x, y + maxAscent);
nsBidiDirection dir;
nscoord x, y;
if (isVertical) {
x = pt.x + maxDescent; // XXX will need update for sideways-left
if (wm.IsBidiLTR()) {
y = aRect.y;
dir = NSBIDI_LTR;
} else {
y = aRect.YMost() - strWidth;
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)) {
nsLayoutUtils::DrawUniDirString(str, maxFit,
nsPoint(aRect.x, y + maxAscent), *fm,
aRenderingContext);
isVertical
? nsPoint(pt.x + maxDescent, pt.y)
: nsPoint(pt.x, pt.y + maxAscent),
*fm, aRenderingContext);
}
// Move to the next line
str += maxFit;
strLen -= maxFit;
y += height;
if (wm.IsVerticalRL()) {
pt.x -= lineHeight;
} else if (wm.IsVerticalLR()) {
pt.x += lineHeight;
} else {
pt.y += lineHeight;
}
firstLine = false;
}
}
@ -1247,7 +1289,6 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
// Check if we should display image placeholders
if (gIconLoad->mPrefShowPlaceholders) {
const nsStyleVisibility* vis = StyleVisibility();
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
bool iconUsed = false;
@ -1260,6 +1301,9 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
mDisplayingIcon = true;
}
WritingMode wm = GetWritingMode();
bool flushRight =
(!wm.IsVertical() && !wm.IsBidiLTR()) || wm.IsVerticalRL();
// If the icon in question is loaded and decoded, draw it
uint32_t imageStatus = 0;
@ -1269,8 +1313,7 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
nsCOMPtr<imgIContainer> imgCon;
aRequest->GetImage(getter_AddRefs(imgCon));
MOZ_ASSERT(imgCon, "Load complete, but no image container?");
nsRect dest((vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
inner.XMost() - size : inner.x,
nsRect dest(flushRight ? inner.XMost() - size : inner.x,
inner.y, size, size);
nsLayoutUtils::DrawSingleImage(*gfx, PresContext(), imgCon,
nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
@ -1283,8 +1326,7 @@ nsImageFrame::DisplayAltFeedback(nsRenderingContext& aRenderingContext,
if (!iconUsed) {
ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 1.f)));
nscoord iconXPos = (vis->mDirection == NS_STYLE_DIRECTION_RTL) ?
inner.XMost() - size : inner.x;
nscoord iconXPos = flushRight ? inner.XMost() - size : inner.x;
// stroked rect:
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
// additional ICON_PADDING pixels for padding
int32_t iconWidth = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
if (vis->mDirection != NS_STYLE_DIRECTION_RTL)
inner.x += iconWidth;
inner.width -= iconWidth;
int32_t paddedIconSize =
nsPresContext::CSSPixelsToAppUnits(ICON_SIZE + ICON_PADDING);
if (wm.IsVertical()) {
inner.y += paddedIconSize;
inner.height -= paddedIconSize;
} else {
if (!flushRight) {
inner.x += paddedIconSize;
}
inner.width -= paddedIconSize;
}
}
// If there's still room, display the alt-text