Changeset 18762 in webkit
- Timestamp:
- Jan 11, 2007, 4:21:22 AM (18 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r18760 r18762 1 2007-01-11 David Hyatt <hyatt@apple.com> 2 3 Fix two bugs in positionForCoordinates. (Make it work when you have a margin in between your border and 4 your first child block.) 5 6 Rewrite column rebalancing to have two modes: constrained and unconstrained. In unconstrained mode, 7 the system will dynamically rebalance as it loses space to breaks and compute a final intrinsic height 8 for the overall block. In constrained mode, columns flow into the fixed height block, and extra columns 9 spill out horizontally in the appropriate direction (RTL/LTR). 10 11 Make columns work properly with both LTR and RTL overflow blocks. 12 13 Initial column test suite coming soon now that the basic layout is right. 14 15 Reviewed by darin 16 17 * rendering/RenderBlock.cpp: 18 (WebCore:::RenderFlow): 19 (WebCore::RenderBlock::layoutBlock): 20 (WebCore::RenderBlock::paintColumns): 21 (WebCore::RenderBlock::lowestPosition): 22 (WebCore::RenderBlock::rightmostPosition): 23 (WebCore::RenderBlock::leftmostPosition): 24 (WebCore::RenderBlock::hitTestColumns): 25 (WebCore::RenderBlock::positionForCoordinates): 26 (WebCore::RenderBlock::availableWidth): 27 (WebCore::RenderBlock::calcColumnWidth): 28 (WebCore::RenderBlock::layoutColumns): 29 (WebCore::RenderBlock::adjustPointToColumnContents): 30 * rendering/RenderBlock.h: 31 (WebCore::RenderBlock::hasColumns): 32 1 33 2007-01-10 Rob Buis <buis@kde.org> 2 34 -
trunk/WebCore/rendering/RenderBlock.cpp
r18759 r18762 101 101 m_overflowLeft = m_overflowTop = 0; 102 102 m_tabWidth = -1; 103 m_ columnCount = 1;104 m_ columnWidth = 0;103 m_desiredColumnCount = 1; 104 m_desiredColumnWidth = 0; 105 105 m_columnRects = 0; 106 106 } … … 462 462 463 463 int oldWidth = m_width; 464 int oldColumnWidth = m_ columnWidth;464 int oldColumnWidth = m_desiredColumnWidth; 465 465 466 466 calcWidth(); … … 468 468 469 469 m_overflowWidth = m_width; 470 471 if (oldWidth != m_width || oldColumnWidth != m_columnWidth) 470 m_overflowLeft = 0; 471 472 if (oldWidth != m_width || oldColumnWidth != m_desiredColumnWidth) 472 473 relayoutChildren = true; 473 474 … … 525 526 // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as 526 527 // we adjust for clean column breaks. 527 layoutColumns();528 int singleColumnBottom = layoutColumns(); 528 529 529 530 // Calculate our new height. … … 531 532 calcHeight(); 532 533 if (oldHeight != m_height) { 534 // We have to rebalance columns to the new height. 535 layoutColumns(singleColumnBottom); 536 533 537 // If the block got expanded in size, then increase our overflowheight to match. 534 538 if (m_overflowHeight > m_height) … … 1309 1313 int currYOffset = 0; 1310 1314 int colGap = columnGap(); 1311 for (unsigned i = 0; i < m_column Count; i++) {1315 for (unsigned i = 0; i < m_columnRects->size(); i++) { 1312 1316 // For each rect, we clip to the rect, and then we adjust our coords. 1313 1317 IntRect colRect = m_columnRects->at(i); … … 2199 2203 } 2200 2204 2201 int 2202 RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const 2205 int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const 2203 2206 { 2204 2207 int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf); … … 2206 2209 return bottom; 2207 2210 2208 if (m_overflowHeight > m_height) 2209 bottom = max(m_overflowHeight, bottom); 2210 2211 if (m_floatingObjects && !hasColumns()) { 2212 FloatingObject* r; 2213 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2214 for ( ; (r = it.current()); ++it ) { 2215 if (!r->noPaint || r->node->layer()) { 2216 int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false); 2217 bottom = max(bottom, lp); 2218 } 2219 } 2220 } 2221 2211 if (includeSelf && m_overflowHeight > bottom) 2212 bottom = m_overflowHeight; 2213 2222 2214 if (m_positionedObjects) { 2223 2215 RenderObject* r; … … 2233 2225 } 2234 2226 2235 if (!includeSelf && lastLineBox() && !hasColumns()) { 2236 int lp = lastLineBox()->yPos() + lastLineBox()->height(); 2237 bottom = max(bottom, lp); 2238 } 2239 2240 return bottom; 2241 } 2242 2243 int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const 2244 { 2245 int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf); 2246 if (!includeOverflowInterior && hasOverflowClip()) 2247 return right; 2248 if (includeSelf && m_overflowWidth > right) 2249 right = m_overflowWidth; 2250 2251 if (m_floatingObjects && !hasColumns()) { 2227 if (hasColumns()) { 2228 for (unsigned i = 0; i < m_columnRects->size(); i++) 2229 bottom = max(bottom, m_columnRects->at(i).bottom()); 2230 return bottom; 2231 } 2232 2233 if (m_floatingObjects) { 2252 2234 FloatingObject* r; 2253 2235 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2254 2236 for ( ; (r = it.current()); ++it ) { 2255 2237 if (!r->noPaint || r->node->layer()) { 2256 int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false); 2257 right = max(right, rp); 2258 } 2259 } 2260 } 2238 int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false); 2239 bottom = max(bottom, lp); 2240 } 2241 } 2242 } 2243 2244 2245 if (!includeSelf && lastLineBox()) { 2246 int lp = lastLineBox()->yPos() + lastLineBox()->height(); 2247 bottom = max(bottom, lp); 2248 } 2249 2250 return bottom; 2251 } 2252 2253 int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const 2254 { 2255 int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf); 2256 if (!includeOverflowInterior && hasOverflowClip()) 2257 return right; 2258 2259 if (includeSelf && m_overflowWidth > right) 2260 right = m_overflowWidth; 2261 2261 2262 2262 if (m_positionedObjects) { … … 2273 2273 } 2274 2274 2275 if (!includeSelf && firstLineBox() && !hasColumns()) { 2275 if (hasColumns()) { 2276 // This only matters for LTR 2277 if (style()->direction() == LTR) 2278 right = max(m_columnRects->last().right(), right); 2279 return right; 2280 } 2281 2282 if (m_floatingObjects) { 2283 FloatingObject* r; 2284 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2285 for ( ; (r = it.current()); ++it ) { 2286 if (!r->noPaint || r->node->layer()) { 2287 int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false); 2288 right = max(right, rp); 2289 } 2290 } 2291 } 2292 2293 if (!includeSelf && firstLineBox()) { 2276 2294 for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) { 2277 2295 int rp = currBox->xPos() + currBox->width(); … … 2292 2310 if (!includeOverflowInterior && hasOverflowClip()) 2293 2311 return left; 2312 2294 2313 if (includeSelf && m_overflowLeft < left) 2295 2314 left = m_overflowLeft; 2296 2297 if (m_floatingObjects && !hasColumns()) { 2298 FloatingObject* r; 2299 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2300 for ( ; (r = it.current()); ++it ) { 2301 if (!r->noPaint || r->node->layer()) { 2302 int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false); 2303 left = min(left, lp); 2304 } 2305 } 2306 } 2307 2315 2308 2316 if (m_positionedObjects) { 2309 2317 RenderObject* r; … … 2318 2326 } 2319 2327 } 2320 2321 if (!includeSelf && firstLineBox() && !hasColumns()) { 2328 2329 if (hasColumns()) { 2330 // This only matters for RTL 2331 if (style()->direction() == RTL) 2332 left = min(m_columnRects->last().x(), left); 2333 return left; 2334 } 2335 2336 if (m_floatingObjects) { 2337 FloatingObject* r; 2338 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2339 for ( ; (r = it.current()); ++it ) { 2340 if (!r->noPaint || r->node->layer()) { 2341 int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false); 2342 left = min(left, lp); 2343 } 2344 } 2345 } 2346 2347 if (!includeSelf && firstLineBox()) { 2322 2348 for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) 2323 2349 left = min(left, (int)currBox->xPos()); … … 2690 2716 int currYOffset = 0; 2691 2717 int colGap = columnGap(); 2692 for (unsigned i = 0; i < m_column Count; i++) {2718 for (unsigned i = 0; i < m_columnRects->size(); i++) { 2693 2719 IntRect colRect = m_columnRects->at(i); 2694 2720 colRect.move(tx, ty); … … 2801 2827 2802 2828 // If we start inside the shadow tree, we will stay inside (even if the point is above or below). 2803 if (!(n && n->isShadowNode()) ) {2829 if (!(n && n->isShadowNode()) && !childrenInline()) { 2804 2830 // Don't return positions inside editable roots for coordinates outside those roots, except for coordinates outside 2805 2831 // a document that is entirely editable. … … 2872 2898 2873 2899 // See if any child blocks exist at this y coordinate. 2900 if (firstChild() && contentsY < firstChild()->yPos()) 2901 return VisiblePosition(n, 0, DOWNSTREAM); 2874 2902 for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) { 2875 2903 if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned()) … … 2892 2920 { 2893 2921 // If we have multiple columns, then the available width is reduced to our column width. 2894 if ( m_columnCount > 1)2895 return m_ columnWidth;2922 if (hasColumns()) 2923 return m_desiredColumnWidth; 2896 2924 return contentWidth(); 2897 2925 } … … 2907 2935 { 2908 2936 // Calculate our column width and column count. 2909 m_ columnCount = 1;2910 m_ columnWidth = contentWidth();2937 m_desiredColumnCount = 1; 2938 m_desiredColumnWidth = contentWidth(); 2911 2939 2912 2940 // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination. … … 2914 2942 return; 2915 2943 2916 int availWidth = m_ columnWidth;2944 int availWidth = m_desiredColumnWidth; 2917 2945 int colGap = columnGap(); 2918 2946 … … 2920 2948 int colCount = style()->columnCount(); 2921 2949 if ((colCount - 1) * colGap < availWidth) { 2922 m_ columnCount = colCount;2923 m_ columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount;2950 m_desiredColumnCount = colCount; 2951 m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount; 2924 2952 } else if (colGap < availWidth) { 2925 m_ columnCount = availWidth / colGap;2926 m_ columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount;2953 m_desiredColumnCount = availWidth / colGap; 2954 m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount; 2927 2955 } 2928 2956 } else if (style()->hasAutoColumnCount()) { 2929 2957 int colWidth = static_cast<int>(style()->columnWidth()); 2930 2958 if (colWidth < availWidth) { 2931 m_ columnCount = (availWidth + colGap) / (colWidth + colGap);2932 m_ columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount;2959 m_desiredColumnCount = (availWidth + colGap) / (colWidth + colGap); 2960 m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount; 2933 2961 } 2934 2962 } else { … … 2938 2966 2939 2967 if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) { 2940 m_ columnCount = colCount;2941 m_ columnWidth = colWidth;2968 m_desiredColumnCount = colCount; 2969 m_desiredColumnWidth = colWidth; 2942 2970 } else if (colWidth < availWidth) { 2943 m_ columnCount = (availWidth + colGap) / (colWidth + colGap);2944 m_ columnWidth = (availWidth - (m_columnCount - 1) * colGap) / m_columnCount;2945 } 2946 } 2947 } 2948 2949 void RenderBlock::layoutColumns()2971 m_desiredColumnCount = (availWidth + colGap) / (colWidth + colGap); 2972 m_desiredColumnWidth = (availWidth - (m_desiredColumnCount - 1) * colGap) / m_desiredColumnCount; 2973 } 2974 } 2975 } 2976 2977 int RenderBlock::layoutColumns(int endOfContent) 2950 2978 { 2951 2979 // Don't do anything if we have no columns 2952 2980 if (!hasColumns()) 2953 return; 2981 return -1; 2982 2983 bool computeIntrinsicHeight = (endOfContent == -1); 2954 2984 2955 2985 // Fill the columns in to the available height. Attempt to balance the height of the columns 2956 2986 int availableHeight = contentHeight(); 2957 int colHeight = availableHeight / m_columnCount + lineHeight(false) / 2; // Add in half our line-height to help with best-guess initial balancing. 2987 int colHeight = computeIntrinsicHeight ? availableHeight / m_desiredColumnCount : availableHeight; 2988 2989 // Add in half our line-height to help with best-guess initial balancing. 2990 int columnSlop = lineHeight(false) / 2; 2991 int remainingSlopSpace = columnSlop * m_desiredColumnCount; 2992 2993 if (computeIntrinsicHeight) 2994 colHeight += columnSlop; 2958 2995 2959 2996 int colGap = columnGap(); … … 2969 3006 int left = borderLeft() + paddingLeft(); 2970 3007 int top = borderTop() + paddingTop(); 2971 int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - m_ columnWidth;3008 int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - m_desiredColumnWidth; 2972 3009 int currY = top; 2973 int colCount = m_columnCount;3010 unsigned colCount = m_desiredColumnCount; 2974 3011 int maxColBottom = borderTop() + paddingTop(); 2975 for (unsigned i = 0; i < m_columnCount; i++) { 2976 // The last column just gets all the remaining space. 2977 if (i == m_columnCount - 1) 3012 int contentBottom = top + availableHeight; 3013 for (unsigned i = 0; i < colCount; i++) { 3014 // If we aren't constrained, then the last column can just get all the remaining space. 3015 if (computeIntrinsicHeight && i == colCount - 1) 2978 3016 colHeight = availableHeight; 2979 3017 2980 3018 // This represents the real column position. 2981 IntRect colRect(currX, top, m_ columnWidth, colHeight);3019 IntRect colRect(currX, top, m_desiredColumnWidth, colHeight); 2982 3020 2983 3021 // For the simulated paint, we pretend like everything is in one long strip. 2984 IntRect pageRect(left, currY, m_ columnWidth, colHeight);3022 IntRect pageRect(left, currY, m_desiredColumnWidth, colHeight); 2985 3023 v->setPrintRect(pageRect); 2986 3024 v->setTruncatedAt(currY + colHeight); 2987 3025 GraphicsContext context((PlatformGraphicsContext*)0); 2988 3026 RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0); 2989 m_columnCount = 1; 3027 3028 int oldColCount = m_desiredColumnCount; 3029 m_desiredColumnCount = 1; 2990 3030 paintObject(paintInfo, 0, 0); 2991 m_ columnCount = colCount;3031 m_desiredColumnCount = oldColCount; 2992 3032 2993 3033 int adjustedBottom = v->bestTruncatedAt(); … … 2997 3037 colRect.setHeight(adjustedBottom - currY); 2998 3038 3039 // Add in the lost space to the subsequent columns. 3040 // FIXME: This will create a "staircase" effect if there are enough columns, but the effect should be pretty subtle. 3041 if (computeIntrinsicHeight) { 3042 int lostSpace = colHeight - colRect.height(); 3043 if (lostSpace > remainingSlopSpace) { 3044 // Redestribute the space among the remaining columns. 3045 int spaceToRedistribute = lostSpace - remainingSlopSpace; 3046 int remainingColumns = colCount - i + 1; 3047 colHeight += spaceToRedistribute / remainingColumns; 3048 } 3049 remainingSlopSpace = max(0, remainingSlopSpace - lostSpace); 3050 } 3051 2999 3052 if (style()->direction() == LTR) 3000 currX += m_ columnWidth + colGap;3053 currX += m_desiredColumnWidth + colGap; 3001 3054 else 3002 currX -= (m_ columnWidth + colGap);3055 currX -= (m_desiredColumnWidth + colGap); 3003 3056 3004 3057 currY += colRect.height(); … … 3008 3061 3009 3062 m_columnRects->append(colRect); 3010 } 3063 3064 // Start adding in more columns as long as there's still content left. 3065 if (currY < endOfContent && i == colCount - 1) 3066 colCount++; 3067 } 3068 3069 m_overflowWidth = max(m_width, currX - colGap); 3070 m_overflowLeft = min(0, currX + m_desiredColumnWidth + colGap); 3011 3071 3012 3072 m_overflowHeight = maxColBottom; … … 3014 3074 if (includeHorizontalScrollbarSize()) 3015 3075 toAdd += m_layer->horizontalScrollbarHeight(); 3016 m_height = m_overflowHeight + toAdd; 3017 m_overflowWidth = m_width; 3076 3077 if (computeIntrinsicHeight) 3078 m_height = m_overflowHeight + toAdd; 3018 3079 3019 3080 v->setPrintRect(IntRect()); 3020 3081 v->setTruncatedAt(0); 3021 3082 3022 ASSERT(m_columnRects && m_columnCount == m_columnRects->size()); 3083 ASSERT(m_columnRects && colCount == m_columnRects->size()); 3084 3085 return contentBottom; 3023 3086 } 3024 3087 … … 3033 3096 int leftGap = colGap / 2; 3034 3097 IntPoint columnPoint(m_columnRects->at(0).location()); 3098 int yOffset = 0; 3035 3099 for (unsigned i = 0; i < m_columnRects->size(); i++) { 3036 3100 // Add in half the column gap to the left and right of the rect. … … 3038 3102 IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height()); 3039 3103 3040 if (gapAndColumnRect.contains(point)) 3104 if (gapAndColumnRect.contains(point)) { 3041 3105 // We're inside the column. Translate the x and y into our column coordinate space. 3042 point -= columnPoint - colRect.location(); 3106 point.move(columnPoint.x() - colRect.x(), yOffset); 3107 return; 3108 } 3043 3109 3044 3110 // Move to the next position. 3045 columnPoint.setY(columnPoint.y() + colRect.height());3111 yOffset += colRect.height(); 3046 3112 } 3047 3113 } -
trunk/WebCore/rendering/RenderBlock.h
r18758 r18762 281 281 void clearTruncation(); 282 282 283 virtual bool hasColumns() const { return m_ columnCount > 1; }283 virtual bool hasColumns() const { return m_desiredColumnCount > 1; } 284 284 void adjustRectForColumns(IntRect&) const; 285 285 private: … … 296 296 int columnGap() const; 297 297 void calcColumnWidth(); 298 void layoutColumns();298 int layoutColumns(int endOfContent = -1); 299 299 300 300 protected: … … 462 462 463 463 // Column information. 464 int m_ columnWidth;465 unsigned m_ columnCount;464 int m_desiredColumnWidth; 465 unsigned m_desiredColumnCount; 466 466 Vector<IntRect>* m_columnRects; 467 467 };
Note:
See TracChangeset
for help on using the changeset viewer.