Bug 1083892 - Make CalculateBlockSideMargins work with logical coordinates. r=smontagu
authorJonathan Kew <jkew@mozilla.com>
Fri, 24 Oct 2014 12:24:39 +0100
changeset 212224 80ba33c7c54996482b8a35a09a9db9e10a08af4f
parent 212223 c0b74388316a431dcdb6f8f7d18333b07c244e58
child 212225 155f1e8a15787a475e9535843f5a2e790c0c8a4f
push id27702
push userkwierso@gmail.com
push dateFri, 24 Oct 2014 22:05:50 +0000
treeherdermozilla-central@c70f62375f7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmontagu
bugs1083892
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1083892 - Make CalculateBlockSideMargins work with logical coordinates. r=smontagu
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -2162,17 +2162,17 @@ nsHTMLReflowState::InitConstraints(nsPre
       NS_ASSERTION(ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
                    ComputedBSize() >= 0, "Bogus block-size");
 
       // Exclude inline tables and flex items from the block margin calculations
       if (isBlock &&
           !IsSideCaption(frame, mStyleDisplay) &&
           mStyleDisplay->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE &&
           !flexContainerFrame) {
-        CalculateBlockSideMargins(AvailableWidth(), ComputedWidth(), aFrameType);
+        CalculateBlockSideMargins(AvailableISize(), ComputedISize(), aFrameType);
       }
     }
   }
 }
 
 static void
 UpdateProp(FrameProperties& aProps,
            const FramePropertyDescriptor* aProperty,
@@ -2308,105 +2308,134 @@ nsCSSOffsetState::InitOffsets(nscoord aH
 // This code enforces section 10.3.3 of the CSS2 spec for this formula:
 //
 // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
 //   'padding-right' + 'border-right-width' + 'margin-right'
 //   = width of containing block 
 //
 // Note: the width unit is not auto when this is called
 void
-nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailWidth,
-                                             nscoord aComputedWidth,
+nsHTMLReflowState::CalculateBlockSideMargins(nscoord aAvailISize,
+                                             nscoord aComputedISize,
                                              nsIAtom* aFrameType)
 {
-  NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedWidth &&
-                   NS_UNCONSTRAINEDSIZE != aAvailWidth,
-                   "have unconstrained width; this should only result from "
-                   "very large sizes, not attempts at intrinsic width "
+  NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aComputedISize &&
+                   NS_UNCONSTRAINEDSIZE != aAvailISize,
+                   "have unconstrained inline-size; this should only result from "
+                   "very large sizes, not attempts at intrinsic inline-size "
                    "calculation");
 
-  nscoord sum = ComputedPhysicalMargin().left + ComputedPhysicalBorderPadding().left +
-    aComputedWidth + ComputedPhysicalBorderPadding().right + ComputedPhysicalMargin().right;
-  if (sum == aAvailWidth)
+  nscoord sum = ComputedLogicalMargin().IStartEnd(mWritingMode) +
+    ComputedLogicalBorderPadding().IStartEnd(mWritingMode) + aComputedISize;
+  if (sum == aAvailISize) {
     // The sum is already correct
     return;
+  }
 
-  // Determine the left and right margin values. The width value
+  // Determine the start and end margin values. The isize value
   // remains constant while we do this.
 
   // Calculate how much space is available for margins
-  nscoord availMarginSpace = aAvailWidth - sum;
+  nscoord availMarginSpace = aAvailISize - sum;
+
+  LogicalMargin margin = ComputedLogicalMargin();
 
   // If the available margin space is negative, then don't follow the
   // usual overconstraint rules.
   if (availMarginSpace < 0) {
     if (mCBReflowState &&
-        mCBReflowState->mStyleVisibility->mDirection == NS_STYLE_DIRECTION_RTL) {
-      ComputedPhysicalMargin().left += availMarginSpace;
+        mCBReflowState->GetWritingMode().IsBidiLTR() !=
+          mWritingMode.IsBidiLTR()) {
+      margin.IStart(mWritingMode) += availMarginSpace;
     } else {
-      ComputedPhysicalMargin().right += availMarginSpace;
+      margin.IEnd(mWritingMode) += availMarginSpace;
     }
+    SetComputedLogicalMargin(margin);
     return;
   }
 
   // The css2 spec clearly defines how block elements should behave
   // in section 10.3.3.
-  bool isAutoLeftMargin =
-    eStyleUnit_Auto == mStyleMargin->mMargin.GetLeftUnit();
-  bool isAutoRightMargin =
-    eStyleUnit_Auto == mStyleMargin->mMargin.GetRightUnit();
-  if (!isAutoLeftMargin && !isAutoRightMargin) {
+  bool isAutoStartMargin, isAutoEndMargin;
+  const nsStyleSides& styleSides = mStyleMargin->mMargin;
+  if (mWritingMode.IsVertical()) {
+    if (mWritingMode.IsBidiLTR()) {
+      isAutoStartMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
+      isAutoEndMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
+    } else {
+      isAutoStartMargin = eStyleUnit_Auto == styleSides.GetBottomUnit();
+      isAutoEndMargin = eStyleUnit_Auto == styleSides.GetTopUnit();
+    }
+  } else {
+    if (mWritingMode.IsBidiLTR()) {
+      isAutoStartMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
+      isAutoEndMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
+    } else {
+      isAutoStartMargin = eStyleUnit_Auto == styleSides.GetRightUnit();
+      isAutoEndMargin = eStyleUnit_Auto == styleSides.GetLeftUnit();
+    }
+  }
+  if (!isAutoStartMargin && !isAutoEndMargin) {
     // Neither margin is 'auto' so we're over constrained. Use the
     // 'direction' property of the parent to tell which margin to
     // ignore
     // First check if there is an HTML alignment that we should honor
     const nsHTMLReflowState* prs = parentReflowState;
     if (aFrameType == nsGkAtoms::tableFrame) {
       NS_ASSERTION(prs->frame->GetType() == nsGkAtoms::tableOuterFrame,
                    "table not inside outer table");
       // Center the table within the outer table based on the alignment
       // of the outer table's parent.
       prs = prs->parentReflowState;
     }
     if (prs &&
         (prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
          prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
          prs->mStyleText->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)) {
-      isAutoLeftMargin =
-        prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
-      isAutoRightMargin =
-        prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
+      if (prs->mWritingMode.IsBidiLTR()) {
+        isAutoStartMargin =
+          prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
+        isAutoEndMargin =
+          prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
+      } else {
+        isAutoStartMargin =
+          prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_RIGHT;
+        isAutoEndMargin =
+          prs->mStyleText->mTextAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT;
+      }
     }
     // Otherwise apply the CSS rules, and ignore one margin by forcing
     // it to 'auto', depending on 'direction'.
     else if (mCBReflowState &&
-             NS_STYLE_DIRECTION_RTL == mCBReflowState->mStyleVisibility->mDirection) {
-      isAutoLeftMargin = true;
+             mCBReflowState->GetWritingMode().IsBidiLTR() !=
+               mWritingMode.IsBidiLTR()) {
+      isAutoStartMargin = true;
     }
     else {
-      isAutoRightMargin = true;
+      isAutoEndMargin = true;
     }
   }
 
   // Logic which is common to blocks and tables
   // The computed margins need not be zero because the 'auto' could come from
   // overconstraint or from HTML alignment so values need to be accumulated
 
-  if (isAutoLeftMargin) {
-    if (isAutoRightMargin) {
+  if (isAutoStartMargin) {
+    if (isAutoEndMargin) {
       // Both margins are 'auto' so the computed addition should be equal
-      nscoord forLeft = availMarginSpace / 2;
-      ComputedPhysicalMargin().left  += forLeft;
-      ComputedPhysicalMargin().right += availMarginSpace - forLeft;
+      nscoord forStart = availMarginSpace / 2;
+      margin.IStart(mWritingMode) += forStart;
+      margin.IEnd(mWritingMode) += availMarginSpace - forStart;
     } else {
-      ComputedPhysicalMargin().left += availMarginSpace;
+      margin.IStart(mWritingMode) += availMarginSpace;
     }
-  } else if (isAutoRightMargin) {
-    ComputedPhysicalMargin().right += availMarginSpace;
+  } else if (isAutoEndMargin) {
+    margin.IEnd(mWritingMode) += availMarginSpace;
   }
+  SetComputedLogicalMargin(margin);
 }
 
 #define NORMAL_LINE_HEIGHT_FACTOR 1.2f    // in term of emHeight 
 // For "normal" we use the font's normal line height (em height + leading).
 // If both internal leading and  external leading specified by font itself
 // are zeros, we should compensate this by creating extra (external) leading 
 // in eCompensateLeading mode. This is necessary because without this 
 // compensation, normal line height might looks too tight. 
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -112,23 +112,30 @@ public:
   const nsMargin& ComputedPhysicalPadding() const { return mComputedPadding; }
 
   // We may need to eliminate the (few) users of these writable-reference accessors
   // as part of migrating to logical coordinates.
   nsMargin& ComputedPhysicalMargin() { return mComputedMargin; }
   nsMargin& ComputedPhysicalBorderPadding() { return mComputedBorderPadding; }
   nsMargin& ComputedPhysicalPadding() { return mComputedPadding; }
 
-  LogicalMargin ComputedLogicalMargin() const
+  const LogicalMargin ComputedLogicalMargin() const
     { return LogicalMargin(mWritingMode, mComputedMargin); }
-  LogicalMargin ComputedLogicalBorderPadding() const
+  const LogicalMargin ComputedLogicalBorderPadding() const
     { return LogicalMargin(mWritingMode, mComputedBorderPadding); }
-  LogicalMargin ComputedLogicalPadding() const
+  const LogicalMargin ComputedLogicalPadding() const
     { return LogicalMargin(mWritingMode, mComputedPadding); }
 
+  void SetComputedLogicalMargin(const LogicalMargin& aMargin)
+    { mComputedMargin = aMargin.GetPhysicalMargin(mWritingMode); }
+  void SetComputedLogicalBorderPadding(const LogicalMargin& aMargin)
+    { mComputedBorderPadding = aMargin.GetPhysicalMargin(mWritingMode); }
+  void SetComputedLogicalPadding(const LogicalMargin& aMargin)
+    { mComputedPadding = aMargin.GetPhysicalMargin(mWritingMode); }
+
   WritingMode GetWritingMode() const { return mWritingMode; }
 
 protected:
   // cached copy of the frame's writing-mode, for logical coordinates
   WritingMode      mWritingMode;
 
   // These are PHYSICAL coordinates (for now).
   // Will probably become logical in due course.
@@ -798,15 +805,15 @@ protected:
   void ComputeMinMaxValues(nscoord                  aContainingBlockWidth,
                            nscoord                  aContainingBlockHeight,
                            const nsHTMLReflowState* aContainingBlockRS);
 
   void CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth,
                                          nscoord* aInsideBoxSizing,
                                          nscoord* aOutsideBoxSizing);
 
-  void CalculateBlockSideMargins(nscoord aAvailWidth,
-                                 nscoord aComputedWidth,
+  void CalculateBlockSideMargins(nscoord aAvailISize,
+                                 nscoord aComputedISize,
                                  nsIAtom* aFrameType);
 };
 
 #endif /* nsHTMLReflowState_h___ */