OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) | 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) |
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
7 * Copyright (C) 2010 Google Inc. All rights reserved. | 7 * Copyright (C) 2010 Google Inc. All rights reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 | 140 |
141 RenderStyle* styleToUse = style(); | 141 RenderStyle* styleToUse = style(); |
142 setHasBoxDecorations(calculateHasBoxDecorations()); | 142 setHasBoxDecorations(calculateHasBoxDecorations()); |
143 setInline(styleToUse->isDisplayInlineType()); | 143 setInline(styleToUse->isDisplayInlineType()); |
144 setPositionState(styleToUse->position()); | 144 setPositionState(styleToUse->position()); |
145 setHorizontalWritingMode(styleToUse->isHorizontalWritingMode()); | 145 setHorizontalWritingMode(styleToUse->isHorizontalWritingMode()); |
146 } | 146 } |
147 | 147 |
148 static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child) | 148 static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child) |
149 { | 149 { |
150 if (!child->isAnonymousBlock() || !child->isInFlowPositioned()) | 150 if (!child->isAnonymousBlock() || !child->isRelPositioned()) |
151 return LayoutSize(); | 151 return LayoutSize(); |
152 LayoutSize offset; | 152 LayoutSize offset; |
153 RenderObject* p = toRenderBlock(child)->inlineElementContinuation(); | 153 RenderObject* p = toRenderBlock(child)->inlineElementContinuation(); |
154 while (p && p->isRenderInline()) { | 154 while (p && p->isRenderInline()) { |
155 if (p->isInFlowPositioned()) { | 155 if (p->isRelPositioned()) { |
156 RenderInline* renderInline = toRenderInline(p); | 156 RenderInline* renderInline = toRenderInline(p); |
157 offset += renderInline->offsetForInFlowPosition(); | 157 offset += renderInline->offsetForInFlowPosition(); |
158 } | 158 } |
159 p = p->parent(); | 159 p = p->parent(); |
160 } | 160 } |
161 return offset; | 161 return offset; |
162 } | 162 } |
163 | 163 |
164 bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const | 164 bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const |
165 { | 165 { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 Element* element = offsetParent(); | 253 Element* element = offsetParent(); |
254 if (!element) | 254 if (!element) |
255 return referencePoint; | 255 return referencePoint; |
256 | 256 |
257 if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject
()) { | 257 if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject
()) { |
258 if (offsetParent->isBox() && !offsetParent->isBody()) | 258 if (offsetParent->isBox() && !offsetParent->isBody()) |
259 referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRen
derBox(offsetParent)->borderTop()); | 259 referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRen
derBox(offsetParent)->borderTop()); |
260 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { | 260 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) { |
261 if (isRelPositioned()) | 261 if (isRelPositioned()) |
262 referencePoint.move(relativePositionOffset()); | 262 referencePoint.move(relativePositionOffset()); |
263 else if (isStickyPositioned()) | |
264 referencePoint.move(stickyPositionOffset()); | |
265 | 263 |
266 RenderObject* current; | 264 RenderObject* current; |
267 for (current = parent(); current != offsetParent && current->parent(
); current = current->parent()) { | 265 for (current = parent(); current != offsetParent && current->parent(
); current = current->parent()) { |
268 // FIXME: What are we supposed to do inside SVG content? | 266 // FIXME: What are we supposed to do inside SVG content? |
269 if (!isOutOfFlowPositioned()) { | 267 if (!isOutOfFlowPositioned()) { |
270 if (current->isBox() && !current->isTableRow()) | 268 if (current->isBox() && !current->isTableRow()) |
271 referencePoint.moveBy(toRenderBox(current)->topLeftLocat
ion()); | 269 referencePoint.moveBy(toRenderBox(current)->topLeftLocat
ion()); |
272 referencePoint.move(current->parent()->columnOffset(referenc
ePoint)); | 270 referencePoint.move(current->parent()->columnOffset(referenc
ePoint)); |
273 } | 271 } |
274 } | 272 } |
275 | 273 |
276 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent
->isPositioned()) | 274 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent
->isPositioned()) |
277 referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation
()); | 275 referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation
()); |
278 } | 276 } |
279 } | 277 } |
280 | 278 |
281 return referencePoint; | 279 return referencePoint; |
282 } | 280 } |
283 | 281 |
284 void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewpo
rtConstraints& constraints, const FloatRect& constrainingRect) const | |
285 { | |
286 RenderBlock* containingBlock = this->containingBlock(); | |
287 | |
288 LayoutRect containerContentRect = containingBlock->contentBoxRect(); | |
289 LayoutUnit maxWidth = containingBlock->availableLogicalWidth(); | |
290 | |
291 // Sticky positioned element ignore any override logical width on the contai
ning block (as they don't call | |
292 // containingBlockLogicalWidthForContent). It's unclear whether this is tota
lly fine. | |
293 LayoutBoxExtent minMargin(minimumValueForLength(style()->marginTop(), maxWid
th), | |
294 minimumValueForLength(style()->marginRight(), maxWidth), | |
295 minimumValueForLength(style()->marginBottom(), maxWidth), | |
296 minimumValueForLength(style()->marginLeft(), maxWidth)); | |
297 | |
298 // Compute the container-relative area within which the sticky element is al
lowed to move. | |
299 containerContentRect.contract(minMargin); | |
300 // Map to the view to avoid including page scale factor. | |
301 constraints.setAbsoluteContainingBlockRect(containingBlock->localToContainer
Quad(FloatRect(containerContentRect), view()).boundingBox()); | |
302 | |
303 LayoutRect stickyBoxRect = frameRectForStickyPositioning(); | |
304 LayoutRect flippedStickyBoxRect = stickyBoxRect; | |
305 containingBlock->flipForWritingMode(flippedStickyBoxRect); | |
306 LayoutPoint stickyLocation = flippedStickyBoxRect.location(); | |
307 | |
308 // FIXME: sucks to call localToAbsolute again, but we can't just offset from
the previously computed rect if there are transforms. | |
309 // Map to the view to avoid including page scale factor. | |
310 FloatRect absContainerFrame = containingBlock->localToContainerQuad(FloatRec
t(FloatPoint(), containingBlock->size()), view()).boundingBox(); | |
311 | |
312 if (containingBlock->hasOverflowClip()) { | |
313 IntSize scrollOffset = containingBlock->layer()->scrollableArea()->adjus
tedScrollOffset(); | |
314 stickyLocation -= scrollOffset; | |
315 } | |
316 | |
317 // We can't call localToAbsolute on |this| because that will recur. FIXME: F
or now, assume that |this| is not transformed. | |
318 FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocatio
n, flippedStickyBoxRect.size()); | |
319 constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect); | |
320 | |
321 float horizontalOffsets = constraints.rightOffset() + constraints.leftOffset
(); | |
322 bool skipRight = false; | |
323 bool skipLeft = false; | |
324 if (!style()->left().isAuto() && !style()->right().isAuto()) { | |
325 if (horizontalOffsets > containerContentRect.width().toFloat() | |
326 || horizontalOffsets + containerContentRect.width().toFloat() > cons
trainingRect.width()) { | |
327 skipRight = style()->isLeftToRightDirection(); | |
328 skipLeft = !skipRight; | |
329 } | |
330 } | |
331 | |
332 if (!style()->left().isAuto() && !skipLeft) { | |
333 constraints.setLeftOffset(floatValueForLength(style()->left(), constrain
ingRect.width())); | |
334 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft); | |
335 } | |
336 | |
337 if (!style()->right().isAuto() && !skipRight) { | |
338 constraints.setRightOffset(floatValueForLength(style()->right(), constra
iningRect.width())); | |
339 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight); | |
340 } | |
341 | |
342 bool skipBottom = false; | |
343 // FIXME(ostap): Exclude top or bottom edge offset depending on the writing
mode when related | |
344 // sections are fixed in spec: http://lists.w3.org/Archives/Public/www-style
/2014May/0286.html | |
345 float verticalOffsets = constraints.topOffset() + constraints.bottomOffset()
; | |
346 if (!style()->top().isAuto() && !style()->bottom().isAuto()) { | |
347 if (verticalOffsets > containerContentRect.height().toFloat() | |
348 || verticalOffsets + containerContentRect.height().toFloat() > const
rainingRect.height()) { | |
349 skipBottom = true; | |
350 } | |
351 } | |
352 | |
353 if (!style()->top().isAuto()) { | |
354 constraints.setTopOffset(floatValueForLength(style()->top(), constrainin
gRect.height())); | |
355 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop); | |
356 } | |
357 | |
358 if (!style()->bottom().isAuto() && !skipBottom) { | |
359 constraints.setBottomOffset(floatValueForLength(style()->bottom(), const
rainingRect.height())); | |
360 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom); | |
361 } | |
362 } | |
363 | |
364 LayoutSize RenderBoxModelObject::stickyPositionOffset() const | |
365 { | |
366 FloatRect constrainingRect; | |
367 | |
368 ASSERT(hasLayer()); | |
369 RenderLayer* enclosingClippingLayer = layer()->enclosingOverflowClipLayer(Ex
cludeSelf); | |
370 if (enclosingClippingLayer) { | |
371 RenderBox* enclosingClippingBox = toRenderBox(enclosingClippingLayer->re
nderer()); | |
372 LayoutRect clipRect = enclosingClippingBox->overflowClipRect(LayoutPoint
()); | |
373 clipRect.move(enclosingClippingBox->paddingLeft(), enclosingClippingBox-
>paddingTop()); | |
374 clipRect.contract(LayoutSize(enclosingClippingBox->paddingLeft() + enclo
singClippingBox->paddingRight(), | |
375 enclosingClippingBox->paddingTop() + enclosingClippingBox->paddingBo
ttom())); | |
376 constrainingRect = enclosingClippingBox->localToContainerQuad(FloatRect(
clipRect), view()).boundingBox(); | |
377 } else { | |
378 LayoutRect viewportRect = view()->frameView()->viewportConstrainedVisibl
eContentRect(); | |
379 constrainingRect = viewportRect; | |
380 } | |
381 | |
382 StickyPositionViewportConstraints constraints; | |
383 computeStickyPositionConstraints(constraints, constrainingRect); | |
384 | |
385 // The sticky offset is physical, so we can just return the delta computed i
n absolute coords (though it may be wrong with transforms). | |
386 return LayoutSize(constraints.computeStickyOffset(constrainingRect)); | |
387 } | |
388 | |
389 LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const | 282 LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const |
390 { | 283 { |
391 if (isRelPositioned()) | 284 return isRelPositioned() ? relativePositionOffset() : LayoutSize(); |
392 return relativePositionOffset(); | |
393 | |
394 if (isStickyPositioned()) | |
395 return stickyPositionOffset(); | |
396 | |
397 return LayoutSize(); | |
398 } | 285 } |
399 | 286 |
400 LayoutUnit RenderBoxModelObject::offsetLeft() const | 287 LayoutUnit RenderBoxModelObject::offsetLeft() const |
401 { | 288 { |
402 // Note that RenderInline and RenderBox override this to pass a different | 289 // Note that RenderInline and RenderBox override this to pass a different |
403 // startPoint to adjustedPositionRelativeToOffsetParent. | 290 // startPoint to adjustedPositionRelativeToOffsetParent. |
404 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); | 291 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x(); |
405 } | 292 } |
406 | 293 |
407 LayoutUnit RenderBoxModelObject::offsetTop() const | 294 LayoutUnit RenderBoxModelObject::offsetTop() const |
(...skipping 2433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2841 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); | 2728 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); |
2842 for (RenderObject* child = startChild; child && child != endChild; ) { | 2729 for (RenderObject* child = startChild; child && child != endChild; ) { |
2843 // Save our next sibling as moveChildTo will clear it. | 2730 // Save our next sibling as moveChildTo will clear it. |
2844 RenderObject* nextSibling = child->nextSibling(); | 2731 RenderObject* nextSibling = child->nextSibling(); |
2845 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); | 2732 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); |
2846 child = nextSibling; | 2733 child = nextSibling; |
2847 } | 2734 } |
2848 } | 2735 } |
2849 | 2736 |
2850 } // namespace WebCore | 2737 } // namespace WebCore |
OLD | NEW |