bug 258377, make border collapsed tables to listen for dynamic border style changes r/sr=bzbarsky
authorBernd <bmlk@gmx.de>
Sun, 26 Oct 2008 11:11:34 +0100
changeset 20836 0dd32fac8d1a7776e8ac5914c7add5bb33ae239c
parent 20835 5b5d20d79a019ef96a29f502157b125a165c2fa8
child 20837 b0e2addff7c9fabf2c4e4c1fd532744aa8b0e7be
push idunknown
push userunknown
push dateunknown
bugs258377
milestone1.9.1b2pre
bug 258377, make border collapsed tables to listen for dynamic border style changes r/sr=bzbarsky
layout/generic/nsBulletFrame.cpp
layout/generic/nsBulletFrame.h
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsIFrame.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGGradientFrame.cpp
layout/svg/base/src/nsSVGGradientFrame.h
layout/svg/base/src/nsSVGLeafFrame.cpp
layout/svg/base/src/nsSVGPathGeometryFrame.cpp
layout/svg/base/src/nsSVGPathGeometryFrame.h
layout/svg/base/src/nsSVGPatternFrame.cpp
layout/svg/base/src/nsSVGPatternFrame.h
layout/svg/base/src/nsSVGStopFrame.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColFrame.cpp
layout/tables/nsTableColFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/xul/base/src/nsBoxFrame.cpp
layout/xul/base/src/nsBoxFrame.h
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/nsImageBoxFrame.h
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.h
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -128,19 +128,19 @@ nsBulletFrame::IsEmpty()
 
 PRBool
 nsBulletFrame::IsSelfEmpty() 
 {
   return GetStyleList()->mListStyleType == NS_STYLE_LIST_STYLE_NONE;
 }
 
 /* virtual */ void
-nsBulletFrame::DidSetStyleContext()
+nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsFrame::DidSetStyleContext();
+  nsFrame::DidSetStyleContext(aOldStyleContext);
 
   imgIRequest *newRequest = GetStyleList()->mListStyleImage;
 
   if (newRequest) {
 
     if (!mListener) {
       nsBulletListener *listener;
       NS_NEWXPCOM(listener, nsBulletListener);
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -57,17 +57,17 @@ public:
   virtual ~nsBulletFrame();
 
   // nsIFrame
   virtual void Destroy();
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
   virtual nsIAtom* GetType() const;
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   // nsIHTMLReflow
   NS_IMETHOD Reflow(nsPresContext* aPresContext,
                     nsHTMLReflowMetrics& aMetrics,
                     const nsHTMLReflowState& aReflowState,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -444,17 +444,17 @@ nsFrame::Init(nsIContent*      aContent,
                        NS_FRAME_GENERATED_CONTENT);
   }
   if (GetStyleDisplay()->HasTransform()) {
     // The frame gets reconstructed if we toggle the -moz-transform
     // property, so we can set this bit here and then ignore it.
     mState |= NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS;
   }
   
-  DidSetStyleContext();
+  DidSetStyleContext(nsnull);
 
   if (IsBoxWrapped())
     InitBoxMetrics(PR_FALSE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsFrame::SetInitialChildList(nsIAtom*        aListName,
@@ -548,17 +548,17 @@ nsFrame::GetOffsets(PRInt32 &aStart, PRI
 {
   aStart = 0;
   aEnd = 0;
   return NS_OK;
 }
 
 // Subclass hook for style post processing
 /* virtual */ void
-nsFrame::DidSetStyleContext()
+nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   // Ensure that this frame gets invalidates (and, in the case of some
   // 'border-image's, reflows) when images that affect it load.
   nsRefPtr<nsImageLoadNotifier> notifierChain;
 
   const nsStyleBackground *background = GetStyleBackground();
   imgIRequest *newBackgroundImage = background->mBackgroundImage;
   if (newBackgroundImage) {
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -552,17 +552,17 @@ protected:
    * which kind of content this is for
    */
   nsresult DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
       const nsDisplayListSet& aLists, PRUint16 aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
 
   PRInt16 DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn = PR_FALSE);
   
   // Style post processing hook
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
 public:
   //given a frame five me the first/last leaf available
   //XXX Robert O'Callahan wants to move these elsewhere
   static void GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
   static void GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame);
 
   // Return the line number of the aFrame, and (optionally) the containing block
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -605,40 +605,44 @@ public:
   /**
    * Get the style context associated with this frame.
    *
    */
   nsStyleContext* GetStyleContext() const { return mStyleContext; }
   void SetStyleContext(nsStyleContext* aContext)
   { 
     if (aContext != mStyleContext) {
-      if (mStyleContext)
-        mStyleContext->Release();
+      nsStyleContext* oldStyleContext = mStyleContext;
       mStyleContext = aContext;
       if (aContext) {
         aContext->AddRef();
-        DidSetStyleContext();
+        DidSetStyleContext(oldStyleContext);
       }
+      if (oldStyleContext)
+        oldStyleContext->Release();
     }
   }
   
   void SetStyleContextWithoutNotification(nsStyleContext* aContext)
   {
     if (aContext != mStyleContext) {
       if (mStyleContext)
         mStyleContext->Release();
       mStyleContext = aContext;
       if (aContext) {
         aContext->AddRef();
       }
     }
   }
 
   // Style post processing hook
-  virtual void DidSetStyleContext() = 0;
+  // Attention: the old style context is the one we're forgetting,
+  // and hence possibly completely bogus for GetStyle* purposes.
+  // Use PeekStyleData instead.
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
 
   /**
    * Get the style data associated with this frame.  This returns a
    * const style struct pointer that should never be modified.  See
    * |nsIStyleContext::GetStyleData| for more information.
    *
    * The use of the typesafe functions below is preferred to direct use
    * of this function.
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -620,29 +620,29 @@ nsObjectFrame::Destroy()
   // we need to finish with the plugin before native window is destroyed
   // doing this in the destructor is too late.
   StopPluginInternal(PR_TRUE);
   
   nsObjectFrameSuper::Destroy();
 }
 
 /* virtual */ void
-nsObjectFrame::DidSetStyleContext()
+nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (HasView()) {
     nsIView* view = GetView();
     nsIViewManager* vm = view->GetViewManager();
     if (vm) {
       nsViewVisibility visibility = 
         IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
       vm->SetViewVisibility(view, visibility);
     }
   }
 
-  nsObjectFrameSuper::DidSetStyleContext();
+  nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext);
 }
 
 nsIAtom*
 nsObjectFrame::GetType() const
 {
   return nsGkAtoms::objectFrame; 
 }
 
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -97,17 +97,17 @@ public:
   virtual nsresult CreateWidgetForView(nsIView* aView);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
   virtual void Destroy();
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD GetPluginInstance(nsIPluginInstance*& aPluginInstance);
   virtual nsresult Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener);
   virtual nsresult Instantiate(const char* aMimeType, nsIURI* aURI);
   virtual void TryNotifyContentObjectWrapper();
   virtual void StopPlugin();
 
   /*
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -85,17 +85,17 @@ public:
   
   NS_IMETHOD GetCursor(const nsPoint& aPoint,
                        nsIFrame::Cursor& aCursor);
   
   NS_IMETHOD CharacterDataChanged(nsPresContext* aPresContext,
                                   nsIContent*     aChild,
                                   PRBool          aAppend);
                                   
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
   
   virtual nsIFrame* GetNextContinuation() const {
     return mNextContinuation;
   }
   NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) {
     NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(),
                   "setting a next continuation with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this),
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -3620,19 +3620,19 @@ nsTextFrame::CharacterDataChanged(nsPres
   aPresContext->GetPresShell()->FrameNeedsReflow(targetTextFrame,
                                                  nsIPresShell::eStyleChange,
                                                  NS_FRAME_IS_DIRTY);
 
   return NS_OK;
 }
 
 /* virtual */ void
-nsTextFrame::DidSetStyleContext()
-{
-  nsFrame::DidSetStyleContext();
+nsTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  nsFrame::DidSetStyleContext(aOldStyleContext);
   ClearTextRun();
 } 
 
 class nsDisplayText : public nsDisplayItem {
 public:
   nsDisplayText(nsTextFrame* aFrame) : nsDisplayItem(aFrame) {
     MOZ_COUNT_CTOR(nsDisplayText);
   }
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -221,19 +221,19 @@ nsSVGGlyphFrame::CharacterDataChanged(ns
 }
 
 // Usable font size range in devpixels / user-units
 #define CLAMP_MIN_SIZE 8
 #define CLAMP_MAX_SIZE 200
 #define PRECISE_SIZE   200
 
 /* virtual */ void
-nsSVGGlyphFrame::DidSetStyleContext()
+nsSVGGlyphFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsSVGGlyphFrameBase::DidSetStyleContext();
+  nsSVGGlyphFrameBase::DidSetStyleContext(aOldStyleContext);
 
   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     ClearTextRun();
     NotifyGlyphMetricsChange();
   }
 }
 
 NS_IMETHODIMP
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -76,17 +76,17 @@ public:
   NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
   NS_IMETHOD_(nsrefcnt) Release() { return 1; }
 
   // nsIFrame interface:
   NS_IMETHOD  CharacterDataChanged(nsPresContext*  aPresContext,
                                    nsIContent*     aChild,
                                    PRBool          aAppend);
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD  SetSelected(nsPresContext* aPresContext,
                           nsIDOMRange*    aRange,
                           PRBool          aSelected,
                           nsSpread        aSpread,
                           SelectionType   aType);
   NS_IMETHOD  GetSelected(PRBool *aSelected) const;
   NS_IMETHOD  IsSelectable(PRBool* aIsSelectable, PRUint8* aSelectStyle) const;
--- a/layout/svg/base/src/nsSVGGradientFrame.cpp
+++ b/layout/svg/base/src/nsSVGGradientFrame.cpp
@@ -59,20 +59,20 @@ nsSVGGradientFrame::nsSVGGradientFrame(n
   mNoHRefURI(PR_FALSE)
 {
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods:
 
 /* virtual */ void
-nsSVGGradientFrame::DidSetStyleContext()
+nsSVGGradientFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   nsSVGEffects::InvalidateRenderingObservers(this);
-  nsSVGGradientFrameBase::DidSetStyleContext();
+  nsSVGGradientFrameBase::DidSetStyleContext(aOldStyleContext);
 }
 
 NS_IMETHODIMP
 nsSVGGradientFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      PRInt32         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
--- a/layout/svg/base/src/nsSVGGradientFrame.h
+++ b/layout/svg/base/src/nsSVGGradientFrame.h
@@ -60,17 +60,17 @@ protected:
 
 public:
   // nsSVGPaintServerFrame methods:
   virtual PRBool SetupPaintServer(gfxContext *aContext,
                                   nsSVGGeometryFrame *aSource,
                                   float aGraphicOpacity);
 
   // nsIFrame interface:
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
 
 #ifdef DEBUG
   // nsIFrameDebug interface:
   NS_IMETHOD GetFrameName(nsAString& aResult) const
--- a/layout/svg/base/src/nsSVGLeafFrame.cpp
+++ b/layout/svg/base/src/nsSVGLeafFrame.cpp
@@ -52,23 +52,23 @@ public:
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGLeaf"), aResult);
   }
 #endif
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 };
 
 nsIFrame*
 NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGLeafFrame(aContext);
 }
 
 /* virtual */ void
-nsSVGLeafFrame::DidSetStyleContext()
+nsSVGLeafFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsFrame::DidSetStyleContext();
+  nsFrame::DidSetStyleContext(aOldStyleContext);
   nsSVGEffects::InvalidateRenderingObservers(this);
 }
--- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp
@@ -79,19 +79,19 @@ nsSVGPathGeometryFrame::AttributeChanged
                   (mContent)->IsDependentAttribute(aAttribute) ||
        aAttribute == nsGkAtoms::transform))
     nsSVGUtils::UpdateGraphic(this);
 
   return NS_OK;
 }
 
 /* virtual */ void
-nsSVGPathGeometryFrame::DidSetStyleContext()
+nsSVGPathGeometryFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsSVGPathGeometryFrameBase::DidSetStyleContext();
+  nsSVGPathGeometryFrameBase::DidSetStyleContext(aOldStyleContext);
 
   nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(this);
   if (outerSVGFrame) {
     // invalidate here while we still have the filter information
     outerSVGFrame->InvalidateCoveredRegion(this);
   }
 
   // XXX: we'd like to use the style_hint mechanism and the
--- a/layout/svg/base/src/nsSVGPathGeometryFrame.h
+++ b/layout/svg/base/src/nsSVGPathGeometryFrame.h
@@ -75,17 +75,17 @@ private:
   NS_IMETHOD_(nsrefcnt) Release() { return 1; }
 
 public:
   // nsIFrame interface:
   NS_IMETHOD  AttributeChanged(PRInt32         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                PRInt32         aModType);
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::svgPathGeometryFrame
    */
   virtual nsIAtom* GetType() const;
 
--- a/layout/svg/base/src/nsSVGPatternFrame.cpp
+++ b/layout/svg/base/src/nsSVGPatternFrame.cpp
@@ -72,20 +72,20 @@ nsSVGPatternFrame::nsSVGPatternFrame(nsS
   mNoHRefURI(PR_FALSE)
 {
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods:
 
 /* virtual */ void
-nsSVGPatternFrame::DidSetStyleContext()
+nsSVGPatternFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   nsSVGEffects::InvalidateRenderingObservers(this);
-  nsSVGPatternFrameBase::DidSetStyleContext();
+  nsSVGPatternFrameBase::DidSetStyleContext(aOldStyleContext);
 }
 
 NS_IMETHODIMP
 nsSVGPatternFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     PRInt32         aModType)
 {
   if (aNameSpaceID == kNameSpaceID_None &&
--- a/layout/svg/base/src/nsSVGPatternFrame.h
+++ b/layout/svg/base/src/nsSVGPatternFrame.h
@@ -75,17 +75,17 @@ public:
                                   nsSVGGeometryFrame *aSource,
                                   float aGraphicOpacity);
 
 public:
   // nsSVGContainerFrame methods:
   virtual already_AddRefed<nsIDOMSVGMatrix> GetCanvasTM();
 
   // nsIFrame interface:
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
 
   /**
    * Get the "type" of the frame
    *
--- a/layout/svg/base/src/nsSVGStopFrame.cpp
+++ b/layout/svg/base/src/nsSVGStopFrame.cpp
@@ -53,17 +53,17 @@ class nsSVGStopFrame : public nsSVGStopF
   friend nsIFrame*
   NS_NewSVGStopFrame(nsIPresShell*   aPresShell, nsIContent*     aContent,
                      nsIFrame*       aParentFrame, nsStyleContext* aContext);
 protected:
   nsSVGStopFrame(nsStyleContext* aContext) : nsSVGStopFrameBase(aContext) {}
 
 public:
   // nsIFrame interface:
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AttributeChanged(PRInt32         aNameSpaceID,
                               nsIAtom*        aAttribute,
                               PRInt32         aModType);
 
   /**
    * Get the "type" of the frame
    *
@@ -87,19 +87,19 @@ public:
 
 //----------------------------------------------------------------------
 // Implementation
 
 //----------------------------------------------------------------------
 // nsIFrame methods:
 
 /* virtual */ void
-nsSVGStopFrame::DidSetStyleContext()
+nsSVGStopFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsSVGStopFrameBase::DidSetStyleContext();
+  nsSVGStopFrameBase::DidSetStyleContext(aOldStyleContext);
   nsSVGEffects::InvalidateRenderingObservers(this);
 }
 
 nsIAtom *
 nsSVGStopFrame::GetType() const
 {
   return nsGkAtoms::svgStopFrame;
 }
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -232,16 +232,35 @@ nsTableCellFrame::AttributeChanged(PRInt
   // let the table frame decide what to do
   nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
   if (tableFrame) {
     tableFrame->AttributeChangedFor(this, mContent, aAttribute); 
   }
   return NS_OK;
 }
 
+/* virtual */ void
+nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  if (!aOldStyleContext) //avoid this on init
+    return;
+     
+  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    
+  if (tableFrame->IsBorderCollapse() &&
+      tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+    PRInt32 colIndex, rowIndex;
+    GetColIndex(colIndex);
+    GetRowIndex(rowIndex);
+    nsRect damageArea(colIndex, rowIndex, GetColSpan(), GetRowSpan());
+    tableFrame->SetBCDamageArea(damageArea);
+  }
+}
+
+     
 NS_IMETHODIMP
 nsTableCellFrame::AppendFrames(nsIAtom*        aListName,
                                nsIFrame*       aFrameList)
 {
   NS_PRECONDITION(PR_FALSE, "unsupported operation");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -87,16 +87,19 @@ public:
 #ifdef ACCESSIBILITY
   NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
 #endif
 
   NS_IMETHOD  AttributeChanged(PRInt32         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                PRInt32         aModType);
 
+  /** @see nsIFrame::DidSetStyleContext */
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+  
   // table cells contain an area frame which does most of the work, and
   // so these functions should never be called. They assert and return
   // NS_ERROR_NOT_IMPLEMENTED
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
--- a/layout/tables/nsTableColFrame.cpp
+++ b/layout/tables/nsTableColFrame.cpp
@@ -78,16 +78,32 @@ nsTableColFrame::SetColType(nsTableColTy
                (GetPrevContinuation() &&
                 GetPrevContinuation()->GetNextContinuation() == this &&
                 GetPrevContinuation()->GetNextSibling() == this),
                "spanned content cols must be continuations");
   PRUint32 type = aType - eColContent;
   mState |= (type << COL_TYPE_OFFSET);
 }
 
+/* virtual */ void
+nsTableColFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  if (!aOldStyleContext) //avoid this on init
+    return;
+     
+  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    
+  if (tableFrame->IsBorderCollapse() &&
+      tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+    nsRect damageArea = nsRect(GetColIndex(), 0, 1, tableFrame->GetRowCount());
+    tableFrame->SetBCDamageArea(damageArea);
+  }
+  return;
+}
+
 void nsTableColFrame::SetContinuousBCBorderWidth(PRUint8     aForSide,
                                                  BCPixelSize aPixelValue)
 {
   switch (aForSide) {
     case NS_SIDE_TOP:
       mTopContBorderWidth = aPixelValue;
       return;
     case NS_SIDE_RIGHT:
--- a/layout/tables/nsTableColFrame.h
+++ b/layout/tables/nsTableColFrame.h
@@ -64,17 +64,19 @@ public:
 
   /** instantiate a new instance of nsTableRowFrame.
     * @param aPresShell the pres shell for this frame
     *
     * @return           the frame that was created
     */
   friend nsTableColFrame* NS_NewTableColFrame(nsIPresShell* aPresShell,
                                               nsStyleContext*  aContext);
-
+  /** @see nsIFrame::DidSetStyleContext */
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+  
   PRInt32 GetColIndex() const;
   
   void SetColIndex (PRInt32 aColIndex);
 
   nsTableColFrame* GetNextCol() const;
 
   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
                     nsHTMLReflowMetrics&     aDesiredSize,
--- a/layout/tables/nsTableColGroupFrame.cpp
+++ b/layout/tables/nsTableColGroupFrame.cpp
@@ -200,16 +200,33 @@ nsTableColGroupFrame::SetInitialChildLis
     }
     return NS_OK; 
   }
 
   mFrames.AppendFrames(this, aChildList);
   return NS_OK;
 }
 
+/* virtual */ void
+nsTableColGroupFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  if (!aOldStyleContext) //avoid this on init
+    return;
+     
+  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    
+  if (tableFrame->IsBorderCollapse() &&
+      tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+    nsRect damageArea(GetFirstColumn()->GetColIndex(), 0, GetColCount(),
+                      tableFrame->GetRowCount());
+    tableFrame->SetBCDamageArea(damageArea);
+  }
+  return;
+}
+
 NS_IMETHODIMP
 nsTableColGroupFrame::AppendFrames(nsIAtom*        aListName,
                                    nsIFrame*       aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   nsTableColFrame* col = GetFirstColumn();
   nsTableColFrame* nextCol;
--- a/layout/tables/nsTableColGroupFrame.h
+++ b/layout/tables/nsTableColGroupFrame.h
@@ -104,16 +104,19 @@ public:
     * column and colgroup are not considered real here.
     * @param aTableFrame - the table parent of the colgroups
     * @param aLastColgroup - the last real colgroup
     * @return  is false if there is a non real colgroup at the end
     */
   static PRBool GetLastRealColGroup(nsTableFrame* aTableFrame, 
                                     nsIFrame**    aLastColGroup);
 
+  /** @see nsIFrame::DidSetStyleContext */
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+
   /** @see nsIFrame::AppendFrames, InsertFrames, RemoveFrame
     */
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -270,16 +270,17 @@ nsTableFrame::~nsTableFrame()
 
 void
 nsTableFrame::Destroy()
 {
   mColGroups.DestroyFrames();
   nsHTMLContainerFrame::Destroy();
 }
 
+
 // Make sure any views are positioned properly
 void
 nsTableFrame::RePositionViews(nsIFrame* aFrame)
 {
   nsContainerFrame::PositionFrameView(aFrame);
   nsContainerFrame::PositionChildViews(aFrame);
 }
 
@@ -2221,19 +2222,29 @@ nsTableFrame::GetCollapsedWidth(nsMargin
             width += cellSpacingX;
         }
       }
     }
   }
   return width;
 }
 
-/* virtual */ void
-nsTableFrame::DidSetStyleContext()
-{
+
+   /* virtual */ void
+nsTableFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+   if (!aOldStyleContext) //avoid this on init
+     return;
+   
+   if (IsBorderCollapse() &&
+       BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+     nsRect damageArea(0, 0, GetColCount(), GetRowCount());
+     SetBCDamageArea(damageArea);
+   }
+
    //avoid this on init or nextinflow
    if (!mTableLayoutStrategy || GetPrevInFlow())
      return;
      
    PRBool isAuto = IsAutoLayout();
    if (isAuto != (LayoutStrategy()->GetType() == nsITableLayoutStrategy::Auto)) {
      nsITableLayoutStrategy* temp;
      if (isAuto)
@@ -4673,18 +4684,72 @@ GetColorAndStyle(const nsIFrame*  aFrame
     }
     else if (NS_SIDE_LEFT == aSide) {
       aSide = NS_SIDE_RIGHT;
     }
   }
   width = styleData->GetActualBorderWidth(aSide);
   aWidth = nsPresContext::AppUnitsToIntCSSPixels(width);
 }
- 
- 
+
+class nsDelayedCalcBCBorders : public nsRunnable {
+public:
+  nsDelayedCalcBCBorders(nsIFrame* aFrame) :
+    mFrame(aFrame) {}
+
+  NS_IMETHOD Run() {
+    if (mFrame) {
+      nsTableFrame* tableFrame = static_cast <nsTableFrame*>(mFrame.GetFrame());
+      if (tableFrame) {
+        if (tableFrame->NeedToCalcBCBorders()) {
+          tableFrame->CalcBCBorders();
+        }
+      }
+    }
+    return NS_OK;
+  }
+private:
+  nsWeakFrame mFrame;
+};
+  
+PRBool
+nsTableFrame::BCRecalcNeeded(nsStyleContext* aOldStyleContext,
+                             nsStyleContext* aNewStyleContext)
+{
+   // Attention: the old style context is the one we're forgetting,
+   // and hence possibly completely bogus for GetStyle* purposes.
+   // We use PeekStyleData instead.
+   
+  const nsStyleBorder* oldStyleData = static_cast<const nsStyleBorder*>
+                       (aOldStyleContext->PeekStyleData(eStyleStruct_Border));
+  if (!oldStyleData)
+    return PR_FALSE;
+  
+  const nsStyleBorder* newStyleData = aNewStyleContext->GetStyleBorder();
+  nsChangeHint change = newStyleData->CalcDifference(*oldStyleData);
+  if (change == NS_STYLE_HINT_NONE)
+    return PR_FALSE;
+  if (change == NS_STYLE_HINT_REFLOW)
+    return PR_TRUE; // the caller only needs to mark the bc damage area
+  if (change == NS_STYLE_HINT_VISUAL) {
+    NS_FOR_CSS_SIDES(side) {
+      if (newStyleData->GetBorderStyle(side) !=
+          oldStyleData->GetBorderStyle(side)) {
+        // we need to recompute the borders and the caller needs to mark
+        // the bc damage area
+        nsCOMPtr<nsIRunnable> evt = new nsDelayedCalcBCBorders(this);
+        if (evt)
+          NS_DispatchToCurrentThread(evt);
+        return PR_TRUE;
+      }
+    }
+  }
+  return PR_FALSE;
+}
+
 /* BCCellBorder represents a border segment which can be either a horizontal
  * or a vertical segment. For each segment we need to know the color, width,
  * style, who owns it and how long it is in cellmap coordinates.
  * Ownership of these segments is  important to calculate which corners should
  * be bevelled. This structure has dual use, its used first to compute the
  * dominant border for horizontal and vertical segments and to store the
  * preliminary computed border results in the BCCellBorders structure.
  * This temporary storage is not symmetric with respect to horizontal and
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -193,17 +193,17 @@ public:
   void AttributeChangedFor(nsIFrame*       aFrame,
                            nsIContent*     aContent, 
                            nsIAtom*        aAttribute); 
 
   /** @see nsIFrame::Destroy */
   virtual void Destroy();
   
   /** @see nsIFrame::DidSetStyleContext */
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
@@ -302,19 +302,21 @@ public:
 
   /** Get width of table + colgroup + col collapse: elements that
    *  continue along the length of the whole left side.
    *  see nsTablePainter about continuous borders
    *  @param aPixelsToTwips - conversion factor
    *  @param aGetInner - get only inner half of border width
    */
   nscoord GetContinuousLeftBCBorderWidth() const;
-
+  friend class nsDelayedCalcBCBorders;
+  
   void SetBCDamageArea(const nsRect& aValue);
-
+  PRBool BCRecalcNeeded(nsStyleContext* aOldStyleContext,
+                        nsStyleContext* aNewStyleContext);
   void PaintBCBorders(nsIRenderingContext& aRenderingContext,
                       const nsRect&        aDirtyRect);
 
   /** nsIFrame method overridden to handle table specifics
   */
   NS_IMETHOD SetSelected(nsPresContext* aPresContext,
                          nsIDOMRange *aRange,
                          PRBool aSelected,
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -172,16 +172,31 @@ nsTableRowFrame::Init(nsIContent*      a
     nsTableRowFrame* rowFrame = (nsTableRowFrame*)aPrevInFlow;
     
     SetRowIndex(rowFrame->GetRowIndex());
   }
 
   return rv;
 }
 
+/* virtual */ void
+nsTableRowFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  if (!aOldStyleContext) //avoid this on init
+    return;
+     
+  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    
+  if (tableFrame->IsBorderCollapse() &&
+      tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+    nsRect damageArea(0, GetRowIndex(), tableFrame->GetColCount(), 1);
+    tableFrame->SetBCDamageArea(damageArea);
+  }
+  return;
+}
 
 NS_IMETHODIMP
 nsTableRowFrame::AppendFrames(nsIAtom*        aListName,
                               nsIFrame*       aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   // Append the frames
--- a/layout/tables/nsTableRowFrame.h
+++ b/layout/tables/nsTableRowFrame.h
@@ -67,17 +67,19 @@ struct nsTableCellReflowState;
 class nsTableRowFrame : public nsHTMLContainerFrame
 {
 public:
   virtual ~nsTableRowFrame();
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
-
+  /** @see nsIFrame::DidSetStyleContext */
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+  
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
                          nsIFrame*       aOldFrame);
 
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -1390,16 +1390,33 @@ nsTableRowGroupFrame::Reflow(nsPresConte
     CheckInvalidateSizeChange(aDesiredSize);
   }
   
   FinishAndStoreOverflow(&aDesiredSize);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return rv;
 }
 
+/* virtual */ void
+nsTableRowGroupFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
+{
+  if (!aOldStyleContext) //avoid this on init
+    return;
+     
+  nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
+    
+  if (tableFrame->IsBorderCollapse() &&
+      tableFrame->BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
+    nsRect damageArea(0, GetStartRowIndex(), tableFrame->GetColCount(),
+                      GetRowCount());
+    tableFrame->SetBCDamageArea(damageArea);
+  }
+  return;
+}
+
 NS_IMETHODIMP
 nsTableRowGroupFrame::AppendFrames(nsIAtom*        aListName,
                                    nsIFrame*       aFrameList)
 {
   NS_ASSERTION(!aListName, "unexpected child list");
 
   ClearRowCursor();
 
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -104,17 +104,19 @@ public:
 
   /** instantiate a new instance of nsTableRowFrame.
     * @param aPresShell the pres shell for this frame
     *
     * @return           the frame that was created
     */
   friend nsIFrame* NS_NewTableRowGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
   virtual ~nsTableRowGroupFrame();
-
+  /** @see nsIFrame::DidSetStyleContext */
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
+  
   NS_IMETHOD AppendFrames(nsIAtom*        aListName,
                           nsIFrame*       aFrameList);
   
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
                           nsIFrame*       aPrevFrame,
                           nsIFrame*       aFrameList);
 
   NS_IMETHOD RemoveFrame(nsIAtom*        aListName,
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -175,19 +175,19 @@ nsBoxFrame::SetInitialChildList(nsIAtom*
   } else {
     NS_WARNING("Warning add child failed!!\n");
   }
 
   return r;
 }
 
 /* virtual */ void
-nsBoxFrame::DidSetStyleContext()
+nsBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsContainerFrame::DidSetStyleContext();
+  nsContainerFrame::DidSetStyleContext(aOldStyleContext);
 
   // The values that CacheAttributes() computes depend on our style,
   // so we need to recompute them here...
   CacheAttributes();
 }
 
 /**
  * Initialize us. This is a good time to get the alignment of the box
--- a/layout/xul/base/src/nsBoxFrame.h
+++ b/layout/xul/base/src/nsBoxFrame.h
@@ -134,17 +134,17 @@ public:
   NS_IMETHOD  RemoveFrame(nsIAtom*        aListName,
                           nsIFrame*       aOldFrame);
 
   virtual nsIFrame* GetContentInsertionFrame();
 
   NS_IMETHOD  SetInitialChildList(nsIAtom*        aListName,
                                   nsIFrame*       aChildList);
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   virtual nsIAtom* GetType() const;
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     // record that children that are ignorable whitespace should be excluded 
     // (When content was loaded via the XUL content sink, it's already
     // been excluded, but we need this for when the XUL namespace is used
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -385,19 +385,19 @@ nsImageBoxFrame::PaintImage(nsIRendering
 
 
 //
 // DidSetStyleContext
 //
 // When the style context changes, make sure that all of our image is up to date.
 //
 /* virtual */ void
-nsImageBoxFrame::DidSetStyleContext()
+nsImageBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsLeafBoxFrame::DidSetStyleContext();
+  nsLeafBoxFrame::DidSetStyleContext(aOldStyleContext);
 
   // Fetch our subrect.
   const nsStyleList* myList = GetStyleList();
   mSubRect = myList->mImageRegion; // before |mSuppressStyleCheck| test!
 
   if (mUseSrcAttr || mSuppressStyleCheck)
     return; // No more work required, since the image isn't specified by style.
 
--- a/layout/xul/base/src/nsImageBoxFrame.h
+++ b/layout/xul/base/src/nsImageBoxFrame.h
@@ -85,17 +85,17 @@ public:
   NS_IMETHOD  Init(nsIContent*      aContent,
                    nsIFrame*        aParent,
                    nsIFrame*        asPrevInFlow);
 
   NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
                               nsIAtom* aAttribute,
                               PRInt32 aModType);
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   virtual void Destroy();
 
   virtual nsIAtom* GetType() const;
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -4214,19 +4214,19 @@ nsTreeBodyFrame::ClearStyleAndImageCache
 {
   mStyleCache.Clear();
   mImageCache.EnumerateRead(CancelImageRequest, nsnull);
   mImageCache.Clear();
   return NS_OK;
 }
 
 /* virtual */ void
-nsTreeBodyFrame::DidSetStyleContext()
+nsTreeBodyFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
-  nsLeafBoxFrame::DidSetStyleContext();
+  nsLeafBoxFrame::DidSetStyleContext(aOldStyleContext);
 
   // Clear the style cache; the pointers are no longer even valid
   mStyleCache.Clear();
   // XXX The following is hacky, but it's not incorrect,
   // and appears to fix a few bugs with style changes, like text zoom and
   // dpi changes
   mIndentation = GetIndentation();
   mRowHeight = GetRowHeight();
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h
@@ -116,17 +116,17 @@ public:
   NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
                          nsGUIEvent* aEvent,
                          nsEventStatus* aEventStatus);
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
-  virtual void DidSetStyleContext();
+  virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
 
   friend nsIFrame* NS_NewTreeBodyFrame(nsIPresShell* aPresShell);
   friend class nsTreeColumn;
 
   struct ScrollParts {
     nsIScrollbarFrame* mVScrollbar;
     nsIContent*        mVScrollbarContent;
     nsIScrollbarFrame* mHScrollbar;