--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1095,63 +1095,105 @@ nsImageFrame::DisplayAltText(nsPresConte
nsRefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(this));
// Format the text to display within the formatting rect
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();
}
// 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;
}
}
struct nsRecessedBorder : public nsStyleBorder {
nsRecessedBorder(nscoord aBorderWidth, nsPresContext* aPresContext)
: nsStyleBorder(aPresContext)
{
@@ -1242,54 +1284,54 @@ nsImageFrame::DisplayAltFeedback(nsRende
// Clip so we don't render outside the inner rect
gfx->Save();
gfx->Clip(NSRectToSnappedRect(inner, PresContext()->AppUnitsPerDevPixel(),
*drawTarget));
// Check if we should display image placeholders
if (gIconLoad->mPrefShowPlaceholders) {
- const nsStyleVisibility* vis = StyleVisibility();
nscoord size = nsPresContext::CSSPixelsToAppUnits(ICON_SIZE);
bool iconUsed = false;
// If we weren't previously displaying an icon, register ourselves
// as an observer for load and animation updates and flag that we're
// doing so now.
if (aRequest && !mDisplayingIcon) {
gIconLoad->AddIconObserver(this);
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;
if (aRequest)
aRequest->GetImageStatus(&imageStatus);
if (imageStatus & imgIRequest::STATUS_LOAD_COMPLETE) {
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,
nullptr, imgIContainer::FLAG_SYNC_DECODE);
iconUsed = true;
}
// if we could not draw the icon, flag that we're waiting for it and
// just draw some graffiti in the mean time
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);
Rect devPxRect =
ToRect(nsLayoutUtils::RectToGfxRect(rect, PresContext()->AppUnitsPerDevPixel()));
drawTarget->StrokeRect(devPxRect, color);
// filled circle in bottom right quadrant of stroked rect:
@@ -1301,20 +1343,27 @@ nsImageFrame::DisplayAltFeedback(nsRende
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder();
AppendEllipseToPath(builder, devPxRect.Center(), devPxRect.Size());
RefPtr<Path> ellipse = builder->Finish();
drawTarget->Fill(ellipse, color);
}
// 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
if (!inner.IsEmpty()) {
nsIContent* content = GetContent();
if (content) {
nsXPIDLString altText;
nsCSSFrameConstructor::GetAlternateTextFor(content, content->Tag(),