Bug 335359. Make the caret thicker when it's at a Kanji character. r+sr=mrbkap,a=damon
authorroc+@cs.cmu.edu
Tue, 22 Apr 2008 20:13:55 -0700
changeset 14572 d194294ef81cee57e5601873e0380c6a18977e39
parent 14571 7d7d2811dfdaf442e9ed2d969f7a4dd3535061c1
child 14573 d58e41e7f526fe8e2e85a89cfbd45671147debd5
push id14
push userbsmedberg@mozilla.com
push dateTue, 29 Apr 2008 14:30:10 +0000
treeherdermozilla-central@78e482f2d4be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdamon
bugs335359
milestone1.9pre
Bug 335359. Make the caret thicker when it's at a Kanji character. r+sr=mrbkap,a=damon
layout/base/nsCaret.cpp
layout/base/nsCaret.h
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -66,16 +66,17 @@
 #include "nsILookAndFeel.h"
 #include "nsBlockFrame.h"
 #include "nsISelectionController.h"
 #include "nsDisplayList.h"
 #include "nsCaret.h"
 #include "nsTextFrame.h"
 #include "nsXULPopupManager.h"
 #include "nsMenuPopupFrame.h"
+#include "nsTextFragment.h"
 
 // The bidi indicator hangs off the caret to one side, to show which
 // direction the typing is in. It needs to be at least 2x2 to avoid looking like 
 // an insignificant dot
 static const PRInt32 kMinBidiIndicatorPixels = 2;
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
@@ -158,26 +159,42 @@ NS_IMETHODIMP nsCaret::Init(nsIPresShell
     rv = StartBlinking();
     if (NS_FAILED(rv))
       return rv;
   }
 
   return NS_OK;
 }
 
-nsCaret::Metrics nsCaret::ComputeMetrics(nsPresContext *aPresContext)
+static PRBool
+DrawCJKCaret(nsIFrame* aFrame, PRInt32 aOffset)
+{
+  nsIContent* content = aFrame->GetContent();
+  const nsTextFragment* frag = content->GetText();
+  if (!frag)
+    return PR_FALSE;
+  if (aOffset < 0 || aOffset >= frag->GetLength())
+    return PR_FALSE;
+  PRUnichar ch = frag->CharAt(aOffset);
+  return 0x2e80 <= ch && ch <= 0xd7ff;
+}
+
+nsCaret::Metrics nsCaret::ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset)
 {
   // Compute nominal sizes in appunits
   nscoord caretWidth = nsPresContext::CSSPixelsToAppUnits(mCaretWidthCSSPx);
+  if (DrawCJKCaret(aFrame, aOffset)) {
+    caretWidth += nsPresContext::CSSPixelsToAppUnits(1);
+  }
   nscoord bidiIndicatorSize = nsPresContext::CSSPixelsToAppUnits(kMinBidiIndicatorPixels);
   bidiIndicatorSize = PR_MAX(caretWidth, bidiIndicatorSize);
 
   // Round them to device pixels. Always round down, except that anything
   // between 0 and 1 goes up to 1 so we don't let the caret disappear.
-  PRUint32 tpp = aPresContext->AppUnitsPerDevPixel();
+  PRUint32 tpp = aFrame->PresContext()->AppUnitsPerDevPixel();
   Metrics result;
   result.mCaretWidth = NS_ROUND_BORDER_TO_PIXELS(caretWidth, tpp);
   result.mBidiIndicatorSize = NS_ROUND_BORDER_TO_PIXELS(bidiIndicatorSize, tpp);
   return result;
 }
 
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP nsCaret::Terminate()
@@ -345,17 +362,17 @@ NS_IMETHODIMP nsCaret::GetCaretCoordinat
     if (outView)
       *outView = drawingView;
   }
   // now add the frame offset to the view offset, and we're done
   viewOffset += framePos;
   outCoordinates->x = viewOffset.x;
   outCoordinates->y = viewOffset.y;
   outCoordinates->height = theFrame->GetSize().height;
-  outCoordinates->width = ComputeMetrics(theFrame->PresContext()).mCaretWidth;
+  outCoordinates->width = ComputeMetrics(theFrame, theFrameOffset).mCaretWidth;
   
   return NS_OK;
 }
 
 void nsCaret::DrawCaretAfterBriefDelay()
 {
   // Make sure readonly caret gets drawn again if it needs to be
   if (!mBlinkTimer) {
@@ -1154,17 +1171,17 @@ nsresult nsCaret::UpdateCaretRects(nsIFr
                                                        framePos);
   if (NS_FAILED(rv))
   {
     mCaretRect.Empty();
     return rv;
   }
 
   mCaretRect += framePos;
-  Metrics metrics = ComputeMetrics(presContext);
+  Metrics metrics = ComputeMetrics(aFrame, aFrameOffset);
   mCaretRect.width = metrics.mCaretWidth;
 
   // Clamp our 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)
   {
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -141,17 +141,17 @@ protected:
                                          nsFrameSelection::HINT aFrameHint,
                                          PRUint8 aBidiLevel,
                                          PRBool aInvalidate);
 
     struct Metrics {
       nscoord mBidiIndicatorSize; // width and height of bidi indicator
       nscoord mCaretWidth;        // full caret width including bidi indicator
     };
-    Metrics ComputeMetrics(nsPresContext *aPresContext);
+    Metrics ComputeMetrics(nsIFrame* aFrame, PRInt32 aOffset);
 
     // Returns true if the caret should be drawn. When |mDrawn| is true,
     // this returns true, so that we erase the drawn caret. If |aIgnoreDrawnState|
     // is true, we don't take into account whether the caret is currently
     // drawn or not. This can be used to determine if the caret is drawn when
     // it shouldn't be.
     PRBool        MustDrawCaret(PRBool aIgnoreDrawnState);