bug 418975 - support soft hyphen when calculating min width for table and fieldset. r=roc
☠☠ backed out by 5c844a79e5c1 ☠ ☠
authorJonathan Kew <jfkthame@gmail.com>
Thu, 24 Mar 2011 15:22:37 +0000
changeset 63816 25beb9ced8d26872adae91fcfaa5765fcd74377a
parent 63815 e8b657b37602f48d79726d03db2b04c574ebaf64
child 63817 03070beac9e721f211bf8361861a052151e8e5cb
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs418975
milestone2.2a1pre
bug 418975 - support soft hyphen when calculating min width for table and fieldset. r=roc
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsTextFrameThebes.cpp
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3179,27 +3179,29 @@ nsIFrame::InlineMinWidthData::ForceBreak
       prevLines = float_min;
   }
   floats.Clear();
   trailingTextFrame = nsnull;
   skipWhitespace = PR_TRUE;
 }
 
 void
-nsIFrame::InlineMinWidthData::OptionallyBreak(nsIRenderingContext *aRenderingContext)
+nsIFrame::InlineMinWidthData::OptionallyBreak(nsIRenderingContext *aRenderingContext,
+                                              nscoord aHyphenWidth)
 {
   trailingTextFrame = nsnull;
 
   // If we can fit more content into a smaller width by staying on this
   // line (because we're still at a negative offset due to negative
   // text-indent or negative margin), don't break.  Otherwise, do the
   // same as ForceBreak.  it doesn't really matter when we accumulate
   // floats.
-  if (currentLine < 0 || atStartOfLine)
+  if (currentLine + aHyphenWidth < 0 || atStartOfLine)
     return;
+  currentLine += aHyphenWidth;
   ForceBreak(aRenderingContext);
 }
 
 void
 nsIFrame::InlinePrefWidthData::ForceBreak(nsIRenderingContext *aRenderingContext)
 {
   if (floats.Length() != 0) {
             // preferred widths accumulated for floats that have already
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1460,17 +1460,21 @@ public:
       , atStartOfLine(PR_TRUE)
     {}
 
     // We need to distinguish forced and optional breaks for cases where the
     // current line total is negative.  When it is, we need to ignore
     // optional breaks to prevent min-width from ending up bigger than
     // pref-width.
     void ForceBreak(nsIRenderingContext *aRenderingContext);
-    void OptionallyBreak(nsIRenderingContext *aRenderingContext);
+
+    // If the break here is actually taken, aHyphenWidth must be added to the
+    // width of the current line.
+    void OptionallyBreak(nsIRenderingContext *aRenderingContext,
+                         nscoord aHyphenWidth = 0);
 
     // The last text frame processed so far in the current line, when
     // the last characters in that text frame are relevant for line
     // break opportunities.
     nsIFrame *trailingTextFrame;
 
     // Whether we're currently at the start of the line.  If we are, we
     // can't break (for example, between the text-indent and the first
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -6067,38 +6067,61 @@ nsTextFrame::AddInlineMinWidthForFlow(ns
     EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   const nsStyleText* textStyle = GetStyleText();
   const nsTextFragment* frag = mContent->GetText();
+
+  // If we're hyphenating, the PropertyProvider needs the actual length;
+  // otherwise we can just pass PR_INT32_MAX to mean "all the text"
+  PRInt32 len = PR_INT32_MAX;
+  PRBool hyphenating =
+    (mTextRun->GetFlags() & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0;
+  if (hyphenating) {
+    gfxSkipCharsIterator tmp(iter);
+    len =
+      tmp.ConvertSkippedToOriginal(flowEndInTextRun) - iter.GetOriginalOffset();
+  }
   PropertyProvider provider(mTextRun, textStyle, frag, this,
-                            iter, PR_INT32_MAX, nsnull, 0);
+                            iter, len, nsnull, 0);
 
   PRBool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
   PRBool preformatNewlines = textStyle->NewlineIsSignificant();
   PRBool preformatTabs = textStyle->WhiteSpaceIsSignificant();
   gfxFloat tabWidth = -1;
   PRUint32 start =
     FindStartAfterSkippingWhitespace(&provider, aData, textStyle, &iter, flowEndInTextRun);
 
-  // XXX Should we consider hyphenation here?
+  nsAutoTArray<PRPackedBool,BIG_TEXT_NODE_SIZE> hyphBuffer;
+  PRPackedBool *hyphBreakBefore = nsnull;
+  if (hyphenating) {
+    hyphBreakBefore = hyphBuffer.AppendElements(flowEndInTextRun - start);
+    if (hyphBreakBefore) {
+      provider.GetHyphenationBreaks(start, flowEndInTextRun - start,
+                                    hyphBreakBefore);
+    }
+  }
+
   for (PRUint32 i = start, wordStart = start; i <= flowEndInTextRun; ++i) {
     PRBool preformattedNewline = PR_FALSE;
     PRBool preformattedTab = PR_FALSE;
     if (i < flowEndInTextRun) {
       // XXXldb Shouldn't we be including the newline as part of the
       // segment that it ends rather than part of the segment that it
       // starts?
       preformattedNewline = preformatNewlines && mTextRun->GetChar(i) == '\n';
       preformattedTab = preformatTabs && mTextRun->GetChar(i) == '\t';
-      if (!mTextRun->CanBreakLineBefore(i) && !preformattedNewline &&
-          !preformattedTab) {
+      if (!mTextRun->CanBreakLineBefore(i) &&
+          !preformattedNewline &&
+          !preformattedTab &&
+          (!hyphBreakBefore || !hyphBreakBefore[i - start]))
+      {
         // we can't break here (and it's not the end of the flow)
         continue;
       }
     }
 
     if (i > wordStart) {
       nscoord width =
         NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(wordStart, i - wordStart, &provider));
@@ -6130,16 +6153,18 @@ nsTextFrame::AddInlineMinWidthForFlow(ns
                          mTextRun, &tabWidth);
       aData->currentLine = nscoord(afterTab + spacing.mAfter);
       wordStart = i + 1;
     } else if (i < flowEndInTextRun ||
         (i == mTextRun->GetLength() &&
          (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) {
       if (preformattedNewline) {
         aData->ForceBreak(aRenderingContext);
+      } else if (hyphBreakBefore && hyphBreakBefore[i - start]) {
+        aData->OptionallyBreak(aRenderingContext, provider.GetHyphenWidth());
       } else {
         aData->OptionallyBreak(aRenderingContext);
       }
       wordStart = i;
     }
   }
 
   if (start < flowEndInTextRun) {