Adjust the caret y-position for zero-height inlines. b=503531 r=roc
authorMats Palmgren <matspal@gmail.com>
Tue, 29 Sep 2009 23:07:05 +0200
changeset 33278 1e2e64a82a171356688747dc4f06b3a13adfbbd2
parent 33277 d6be20db5b51b9dd99131ac8a68b8b621f460d67
child 33279 cbbc962fcc69e5ae6a4a31a56f4fefa68d5bae1d
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs503531
milestone1.9.3a1pre
Adjust the caret y-position for zero-height inlines. b=503531 r=roc
layout/base/nsCaret.cpp
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -1122,48 +1122,62 @@ void nsCaret::DrawCaret(PRBool aInvalida
     hint = mLastHint;
     bidiLevel = mLastBidiLevel;
   }
 
   DrawAtPositionWithHint(node, offset, hint, bidiLevel, aInvalidate);
   ToggleDrawnStatus();
 }
 
+static PRBool
+FramesOnSameLineHaveZeroHeight(nsIFrame* aFrame)
+{
+  nsLineBox* line = FindContainingLine(aFrame);
+  if (!line)
+    return aFrame->GetRect().height == 0;
+  PRInt32 count = line->GetChildCount();
+  for (nsIFrame* f = line->mFirstChild; count > 0; --count, f = f->GetNextSibling())
+  {
+   if (f->GetRect().height != 0)
+     return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
 nsresult nsCaret::UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset)
 {
   NS_ASSERTION(aFrame, "Should have a frame here");
 
   nsRect frameRect = aFrame->GetRect();
   frameRect.x = 0;
   frameRect.y = 0;
 
   nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
   if (!presShell) return NS_ERROR_FAILURE;
 
-  nsPresContext *presContext = presShell->GetPresContext();
-
   // If we got a zero-height frame we should figure out a height. We have to do
   // this after we've got an RC.
   if (frameRect.height == 0)
   {
     nsCOMPtr<nsIFontMetrics> fm;
     nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
 
     if (fm)
     {
       nscoord ascent, descent;
       fm->GetMaxAscent(ascent);
       fm->GetMaxDescent(descent);
       frameRect.height = ascent + descent;
 
-      // If it's a BR frame then it's probably at the end of a non-empty line
-      // (see BRFrame::Reflow). BR frames sit on the baseline of the text, so we
-      // need to subtract the ascent to account for the frame height.
-      if (aFrame->GetType() == nsGkAtoms::brFrame)
-          frameRect.y -= ascent;
+      // Place the caret on the baseline for inline frames, except when there is
+      // a frame on the line with non-zero height.  XXXmats why the exception? --
+      // I don't know but it seems to be necessary, see bug 503531.
+      if (aFrame->GetStyleDisplay()->IsInlineOutside() &&
+          !FramesOnSameLineHaveZeroHeight(aFrame))
+        frameRect.y -= ascent;
     }
   }
 
   mCaretRect = frameRect;
   nsCOMPtr<nsISelection> domSelection = do_QueryReferent(mDomSelectionWeak);
   nsCOMPtr<nsISelectionPrivate> privateSelection = do_QueryInterface(domSelection);
 
   nsPoint framePos;
@@ -1208,17 +1222,17 @@ nsresult nsCaret::UpdateCaretRects(nsIFr
       mCaretRect.x -= overflow;
   }
 
   // on RTL frames the right edge of mCaretRect must be equal to framePos
   const nsStyleVisibility* vis = aFrame->GetStyleVisibility();
   if (NS_STYLE_DIRECTION_RTL == vis->mDirection)
     mCaretRect.x -= mCaretRect.width;
 
-  return UpdateHookRect(presContext, metrics);
+  return UpdateHookRect(presShell->GetPresContext(), metrics);
 }
 
 nsresult nsCaret::UpdateHookRect(nsPresContext* aPresContext,
                                  const Metrics& aMetrics)
 {
   mHookRect.Empty();
 
 #ifdef IBMBIDI