Bug 902762 pt 7 - Draw caret appropriately for vertical textruns. r=smontagu

This commit is contained in:
Jonathan Kew 2014-10-01 20:25:50 +01:00
parent 7746f0e276
commit e4d8d67d5c
2 changed files with 56 additions and 20 deletions

View File

@ -305,12 +305,18 @@ nsCaret::GetGeometryForFrame(nsIFrame* aFrame,
descent = fm->MaxDescent();
}
nscoord height = ascent + descent;
framePos.y = baseline - ascent;
bool vertical = aFrame->GetWritingMode().IsVertical();
if (vertical) {
framePos.x = baseline - ascent;
} else {
framePos.y = baseline - ascent;
}
Metrics caretMetrics = ComputeMetrics(aFrame, aFrameOffset, height);
rect = nsRect(framePos, nsSize(caretMetrics.mCaretWidth, height));
rect = nsRect(framePos, vertical ? nsSize(height, caretMetrics.mCaretWidth) :
nsSize(caretMetrics.mCaretWidth, height));
// Clamp the x-position to be within our scroll frame. If we don't, then it
// clips us, and we don't appear at all. See bug 335560.
// Clamp the inline-position to be within our scroll frame. If we don't, then
// it clips us, and we don't appear at all. See bug 335560.
nsIFrame *scrollFrame =
nsLayoutUtils::GetClosestFrameOfType(aFrame, nsGkAtoms::scrollFrame);
if (scrollFrame) {
@ -319,12 +325,20 @@ nsCaret::GetGeometryForFrame(nsIFrame* aFrame,
nsIFrame *scrolled = sf->GetScrolledFrame();
nsRect caretInScroll = rect + aFrame->GetOffsetTo(scrolled);
// Now see if thet caret extends beyond the view's bounds. If it does,
// Now see if the caret extends beyond the view's bounds. If it does,
// then snap it back, put it as close to the edge as it can.
nscoord overflow = caretInScroll.XMost() -
scrolled->GetVisualOverflowRectRelativeToSelf().width;
if (overflow > 0) {
rect.x -= overflow;
if (vertical) {
nscoord overflow = caretInScroll.YMost() -
scrolled->GetVisualOverflowRectRelativeToSelf().height;
if (overflow > 0) {
rect.y -= overflow;
}
} else {
nscoord overflow = caretInScroll.XMost() -
scrolled->GetVisualOverflowRectRelativeToSelf().width;
if (overflow > 0) {
rect.x -= overflow;
}
}
}
@ -822,13 +836,19 @@ nsCaret::ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
{
NS_ASSERTION(aFrame, "Should have a frame here");
bool isVertical = aFrame->GetWritingMode().IsVertical();
nscoord bidiIndicatorSize;
*aCaretRect = GetGeometryForFrame(aFrame, aFrameOffset, &bidiIndicatorSize);
// on RTL frames the right edge of mCaretRect must be equal to framePos
const nsStyleVisibility* vis = aFrame->StyleVisibility();
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
aCaretRect->x -= aCaretRect->width;
if (isVertical) {
aCaretRect->y -= aCaretRect->height;
} else {
aCaretRect->x -= aCaretRect->width;
}
}
// Simon -- make a hook to draw to the left or right of the caret to show keyboard language direction
@ -846,10 +866,19 @@ nsCaret::ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
// If keyboard language is RTL, draw the hook on the left; if LTR, to the right
// The height of the hook rectangle is the same as the width of the caret
// rectangle.
aHookRect->SetRect(aCaretRect->x + (isCaretRTL ? bidiIndicatorSize * -1 : aCaretRect->width),
aCaretRect->y + bidiIndicatorSize,
bidiIndicatorSize,
aCaretRect->width);
if (isVertical) {
aHookRect->SetRect(aCaretRect->XMost() - bidiIndicatorSize,
aCaretRect->y + (isCaretRTL ? bidiIndicatorSize * -1 :
aCaretRect->height),
aCaretRect->height,
bidiIndicatorSize);
} else {
aHookRect->SetRect(aCaretRect->x + (isCaretRTL ? bidiIndicatorSize * -1 :
aCaretRect->width),
aCaretRect->y + bidiIndicatorSize,
bidiIndicatorSize,
aCaretRect->width);
}
}
}

View File

@ -6529,18 +6529,25 @@ nsTextFrame::GetPointFromOffset(int32_t inOffset,
FindClusterStart(mTextRun, trimmedOffset, &iter);
}
gfxFloat advanceWidth =
gfxFloat advance =
mTextRun->GetAdvanceWidth(properties.GetStart().GetSkippedOffset(),
GetSkippedDistance(properties.GetStart(), iter),
&properties);
nscoord width = NSToCoordCeilClamped(advanceWidth);
nscoord iSize = NSToCoordCeilClamped(advance);
if (mTextRun->IsRightToLeft()) {
outPoint->x = mRect.width - width;
if (mTextRun->IsVertical()) {
if (mTextRun->IsRightToLeft()) {
outPoint->y = mRect.height - iSize;
} else {
outPoint->y = iSize;
}
} else {
outPoint->x = width;
if (mTextRun->IsRightToLeft()) {
outPoint->x = mRect.width - iSize;
} else {
outPoint->x = iSize;
}
}
outPoint->y = 0;
return NS_OK;
}