Paint a focus ring for <area shape="default">. b=448987 r+sr=roc
authorMats Palmgren <mats.palmgren@bredband.net>
Thu, 07 Aug 2008 16:44:04 +0200
changeset 16486 d8f62778e9e4ee8b9abdfae1f6314e3152b8fa55
parent 16485 12893191012aa59933203622d3514032e223900b
child 16487 06820914768f2daa6793158cb1476022b9060df3
push id1073
push usermpalmgren@mozilla.com
push dateThu, 07 Aug 2008 14:45:25 +0000
treeherdermozilla-central@06820914768f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs448987
milestone1.9.1a2pre
Paint a focus ring for <area shape="default">. b=448987 r+sr=roc
layout/generic/nsImageFrame.cpp
layout/generic/nsImageMap.cpp
layout/generic/nsImageMap.h
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1127,17 +1127,17 @@ static void PaintDebugImageMap(nsIFrame*
      const nsRect& aDirtyRect, nsPoint aPt) {
   nsImageFrame* f = static_cast<nsImageFrame*>(aFrame);
   nsRect inner = f->GetInnerArea() + aPt;
   nsPresContext* pc = f->PresContext();
 
   aCtx->SetColor(NS_RGB(0, 0, 0));
   aCtx->PushState();
   aCtx->Translate(inner.x, inner.y);
-  f->GetImageMap(pc)->Draw(pc, *aCtx);
+  f->GetImageMap(pc)->Draw(aFrame, *aCtx);
   aCtx->PopState();
 }
 #endif
 
 /**
  * Note that nsDisplayImage does not receive events. However, an image element
  * is replaced content so its background will be z-adjacent to the
  * image itself, and hence receive events just as if the image itself
@@ -1184,17 +1184,17 @@ nsImageFrame::PaintImage(nsIRenderingCon
 
   nsPresContext* presContext = PresContext();
   nsImageMap* map = GetImageMap(presContext);
   if (nsnull != map) {
     aRenderingContext.PushState();
     aRenderingContext.SetColor(NS_RGB(0, 0, 0));
     aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
     aRenderingContext.Translate(inner.x, inner.y);
-    map->Draw(presContext, aRenderingContext);
+    map->Draw(this, aRenderingContext);
     aRenderingContext.PopState();
   }
 }
 
 NS_IMETHODIMP
 nsImageFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                const nsRect&           aDirtyRect,
                                const nsDisplayListSet& aLists)
--- a/layout/generic/nsImageMap.cpp
+++ b/layout/generic/nsImageMap.cpp
@@ -74,19 +74,18 @@ static NS_DEFINE_CID(kCStringBundleServi
 class Area {
 public:
   Area(nsIContent* aArea);
   virtual ~Area();
 
   virtual void ParseCoords(const nsAString& aSpec);
 
   virtual PRBool IsInside(nscoord x, nscoord y) const = 0;
-  virtual void Draw(nsPresContext* aCX,
-                    nsIRenderingContext& aRC) = 0;
-  virtual void GetRect(nsPresContext* aCX, nsRect& aRect) = 0;
+  virtual void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC) = 0;
+  virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) = 0;
 
   void HasFocus(PRBool aHasFocus);
 
   void GetHREF(nsAString& aHref) const;
   void GetArea(nsIContent** aArea) const;
 
   nsCOMPtr<nsIContent> mArea;
   nscoord* mCoords;
@@ -332,50 +331,64 @@ void Area::HasFocus(PRBool aHasFocus)
 
 //----------------------------------------------------------------------
 
 class DefaultArea : public Area {
 public:
   DefaultArea(nsIContent* aArea);
 
   virtual PRBool IsInside(nscoord x, nscoord y) const;
-  virtual void Draw(nsPresContext* aCX,
-                    nsIRenderingContext& aRC);
-  virtual void GetRect(nsPresContext* aCX, nsRect& aRect);
+  virtual void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC);
+  virtual void GetRect(nsIFrame* aFrame, nsRect& aRect);
 };
 
 DefaultArea::DefaultArea(nsIContent* aArea)
   : Area(aArea)
 {
 }
 
 PRBool DefaultArea::IsInside(nscoord x, nscoord y) const
 {
   return PR_TRUE;
 }
 
-void DefaultArea::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
+void DefaultArea::Draw(nsIFrame* aFrame, nsIRenderingContext& aRC)
 {
+  if (mHasFocus) {
+    nsRect r = aFrame->GetRect();
+    r.MoveTo(0, 0);
+    nscoord x1 = r.x;
+    nscoord y1 = r.y;
+    const nscoord kOnePixel = nsPresContext::CSSPixelsToAppUnits(1);
+    nscoord x2 = r.XMost() - kOnePixel;
+    nscoord y2 = r.YMost() - kOnePixel;
+    // XXX aRC.DrawRect(r) result is ugly, that's why we use DrawLine.
+    aRC.DrawLine(x1, y1, x1, y2);
+    aRC.DrawLine(x1, y2, x2, y2);
+    aRC.DrawLine(x1, y1, x2, y1);
+    aRC.DrawLine(x2, y1, x2, y2);
+  }
 }
 
-void DefaultArea::GetRect(nsPresContext* aCX, nsRect& aRect)
+void DefaultArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
 {
+  aRect = aFrame->GetRect();
+  aRect.MoveTo(0, 0);
 }
 
 //----------------------------------------------------------------------
 
 class RectArea : public Area {
 public:
   RectArea(nsIContent* aArea);
 
   virtual void ParseCoords(const nsAString& aSpec);
   virtual PRBool IsInside(nscoord x, nscoord y) const;
-  virtual void Draw(nsPresContext* aCX,
-                    nsIRenderingContext& aRC);
-  virtual void GetRect(nsPresContext* aCX, nsRect& aRect);
+  virtual void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC);
+  virtual void GetRect(nsIFrame* aFrame, nsRect& aRect);
 };
 
 RectArea::RectArea(nsIContent* aArea)
   : Area(aArea)
 {
 }
 
 void RectArea::ParseCoords(const nsAString& aSpec)
@@ -426,17 +439,17 @@ PRBool RectArea::IsInside(nscoord x, nsc
                  "Someone screwed up RectArea::ParseCoords");
     if ((x >= x1) && (x <= x2) && (y >= y1) && (y <= y2)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
-void RectArea::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
+void RectArea::Draw(nsIFrame* aFrame, nsIRenderingContext& aRC)
 {
   if (mHasFocus) {
     if (mNumCoords >= 4) {
       nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
       nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
       nscoord x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
       nscoord y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[3]);
       NS_ASSERTION(x1 <= x2 && y1 <= y2,
@@ -444,17 +457,17 @@ void RectArea::Draw(nsPresContext* aCX, 
       aRC.DrawLine(x1, y1, x1, y2);
       aRC.DrawLine(x1, y2, x2, y2);
       aRC.DrawLine(x1, y1, x2, y1);
       aRC.DrawLine(x2, y1, x2, y2);
     }
   }
 }
 
-void RectArea::GetRect(nsPresContext* aCX, nsRect& aRect)
+void RectArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
 {
   if (mNumCoords >= 4) {
     nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
     nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
     nscoord x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
     nscoord y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[3]);
     NS_ASSERTION(x1 <= x2 && y1 <= y2,
                  "Someone screwed up RectArea::ParseCoords");
@@ -466,19 +479,18 @@ void RectArea::GetRect(nsPresContext* aC
 //----------------------------------------------------------------------
 
 class PolyArea : public Area {
 public:
   PolyArea(nsIContent* aArea);
 
   virtual void ParseCoords(const nsAString& aSpec);
   virtual PRBool IsInside(nscoord x, nscoord y) const;
-  virtual void Draw(nsPresContext* aCX,
-                    nsIRenderingContext& aRC);
-  virtual void GetRect(nsPresContext* aCX, nsRect& aRect);
+  virtual void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC);
+  virtual void GetRect(nsIFrame* aFrame, nsRect& aRect);
 };
 
 PolyArea::PolyArea(nsIContent* aArea)
   : Area(aArea)
 {
 }
 
 void PolyArea::ParseCoords(const nsAString& aSpec)
@@ -557,17 +569,17 @@ PRBool PolyArea::IsInside(nscoord x, nsc
     }
     if ((intersects & 1) != 0) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
-void PolyArea::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
+void PolyArea::Draw(nsIFrame* aFrame, nsIRenderingContext& aRC)
 {
   if (mHasFocus) {
     if (mNumCoords >= 6) {
       nscoord x0 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
       nscoord y0 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
       nscoord x1, y1;
       for (PRInt32 i = 2; i < mNumCoords; i += 2) {
         x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[i]);
@@ -578,17 +590,17 @@ void PolyArea::Draw(nsPresContext* aCX, 
       }
       x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
       y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
       aRC.DrawLine(x0, y0, x1, y1);
     }
   }
 }
 
-void PolyArea::GetRect(nsPresContext* aCX, nsRect& aRect)
+void PolyArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
 {
   if (mNumCoords >= 6) {
     nscoord x1, x2, y1, y2, xtmp, ytmp;
     x1 = x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
     y1 = y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
     for (PRInt32 i = 2; i < mNumCoords; i += 2) {
       xtmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i]);
       ytmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i+1]);
@@ -605,19 +617,18 @@ void PolyArea::GetRect(nsPresContext* aC
 //----------------------------------------------------------------------
 
 class CircleArea : public Area {
 public:
   CircleArea(nsIContent* aArea);
 
   virtual void ParseCoords(const nsAString& aSpec);
   virtual PRBool IsInside(nscoord x, nscoord y) const;
-  virtual void Draw(nsPresContext* aCX,
-                    nsIRenderingContext& aRC);
-  virtual void GetRect(nsPresContext* aCX, nsRect& aRect);
+  virtual void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC);
+  virtual void GetRect(nsIFrame* aFrame, nsRect& aRect);
 };
 
 CircleArea::CircleArea(nsIContent* aArea)
   : Area(aArea)
 {
 }
 
 void CircleArea::ParseCoords(const nsAString& aSpec)
@@ -665,17 +676,17 @@ PRBool CircleArea::IsInside(nscoord x, n
     nscoord dist = (dx * dx) + (dy * dy);
     if (dist <= (radius * radius)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
-void CircleArea::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
+void CircleArea::Draw(nsIFrame* aFrame, nsIRenderingContext& aRC)
 {
   if (mHasFocus) {
     if (mNumCoords >= 3) {
       nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
       nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
       nscoord radius = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
       if (radius < 0) {
         return;
@@ -683,17 +694,17 @@ void CircleArea::Draw(nsPresContext* aCX
       nscoord x = x1 - radius;
       nscoord y = y1 - radius;
       nscoord w = 2 * radius;
       aRC.DrawEllipse(x, y, w, w);
     }
   }
 }
 
-void CircleArea::GetRect(nsPresContext* aCX, nsRect& aRect)
+void CircleArea::GetRect(nsIFrame* aFrame, nsRect& aRect)
 {
   if (mNumCoords >= 3) {
     nscoord x1 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]);
     nscoord y1 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]);
     nscoord radius = nsPresContext::CSSPixelsToAppUnits(mCoords[2]);
     if (radius < 0) {
       return;
     }
@@ -723,22 +734,31 @@ NS_IMPL_ISUPPORTS4(nsImageMap,
                    nsIDOMEventListener,
                    nsIImageMap)
 
 NS_IMETHODIMP
 nsImageMap::GetBoundsForAreaContent(nsIContent *aContent, 
                                    nsPresContext* aPresContext, 
                                    nsRect& aBounds)
 {
+  NS_ENSURE_TRUE(aContent && aPresContext, NS_ERROR_INVALID_ARG);
+
   // Find the Area struct associated with this content node, and return bounds
   PRInt32 i, n = mAreas.Count();
   for (i = 0; i < n; i++) {
     Area* area = (Area*) mAreas.ElementAt(i);
     if (area->mArea == aContent) {
-      area->GetRect(aPresContext, aBounds);
+      aBounds = nsRect();
+      nsIPresShell* shell = aPresContext->PresShell();
+      if (shell) {
+        nsIFrame* frame = shell->GetPrimaryFrameFor(aContent);
+        if (frame) {
+          area->GetRect(frame, aBounds);
+        }
+      }
       return NS_OK;
     }
   }
   return NS_ERROR_FAILURE;
 }
 
 void
 nsImageMap::FreeAreas()
@@ -900,22 +920,22 @@ nsImageMap::IsInside(nscoord aX, nscoord
       return PR_TRUE;
     }
   }
 
   return PR_FALSE;
 }
 
 void
-nsImageMap::Draw(nsPresContext* aCX, nsIRenderingContext& aRC)
+nsImageMap::Draw(nsIFrame* aFrame, nsIRenderingContext& aRC)
 {
   PRInt32 i, n = mAreas.Count();
   for (i = 0; i < n; i++) {
     Area* area = (Area*) mAreas.ElementAt(i);
-    area->Draw(aCX, aRC);
+    area->Draw(aFrame, aRC);
   }
 }
 
 void
 nsImageMap::MaybeUpdateAreas(nsIContent *aContent)
 {
   if (aContent == mMap || mContainsBlockContents) {
     UpdateAreas();
@@ -1001,22 +1021,19 @@ nsImageMap::ChangeFocus(nsIDOMEvent* aEv
           //Now invalidate the rect
           nsCOMPtr<nsIDocument> doc = targetContent->GetDocument();
           //This check is necessary to see if we're still attached to the doc
           if (doc) {
             nsIPresShell *presShell = doc->GetPrimaryShell();
             if (presShell) {
               nsIFrame* imgFrame = presShell->GetPrimaryFrameFor(targetContent);
               if (imgFrame) {
-                nsPresContext *presContext = presShell->GetPresContext();
-                if (presContext) {
-                  nsRect dmgRect;
-                  area->GetRect(presContext, dmgRect);
-                  imgFrame->Invalidate(dmgRect, PR_FALSE);
-                }
+                nsRect dmgRect;
+                area->GetRect(imgFrame, dmgRect);
+                imgFrame->Invalidate(dmgRect, PR_FALSE);
               }
             }
           }
           break;
         }
       }
     }
   }
--- a/layout/generic/nsImageMap.h
+++ b/layout/generic/nsImageMap.h
@@ -68,17 +68,17 @@ public:
    * See if the given aX,aY <b>pixel</b> coordinates are in the image
    * map. If they are then PR_TRUE is returned and aContent points to the
    * found area. If the coordinates are not in the map then PR_FALSE
    * is returned.
    */
   PRBool IsInside(nscoord aX, nscoord aY,
                   nsIContent** aContent) const;
 
-  void Draw(nsPresContext* aCX, nsIRenderingContext& aRC);
+  void Draw(nsIFrame* aFrame, nsIRenderingContext& aRC);
   
   /** 
    * Called just before the nsImageFrame releases us. 
    * Used to break the cycle caused by the DOM listener.
    */
   void Destroy(void);
   
   // nsISupports