1 /* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "LayoutState.h" 28 29 #include "ColumnInfo.h" 30 #include "RenderArena.h" 31 #include "RenderInline.h" 32 #include "RenderLayer.h" 33 #include "RenderView.h" 34 35 namespace WebCore { 36 37 LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo) 38 : m_columnInfo(columnInfo) 39 , m_next(prev) 40 #ifndef NDEBUG 41 , m_renderer(renderer) 42 #endif 43 { 44 ASSERT(m_next); 45 46 bool fixed = renderer->isPositioned() && renderer->style()->position() == FixedPosition; 47 if (fixed) { 48 // FIXME: This doesn't work correctly with transforms. 49 FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), true); 50 m_paintOffset = IntSize(fixedOffset.x(), fixedOffset.y()) + offset; 51 } else 52 m_paintOffset = prev->m_paintOffset + offset; 53 54 if (renderer->isPositioned() && !fixed) { 55 if (RenderObject* container = renderer->container()) { 56 if (container->isRelPositioned() && container->isRenderInline()) 57 m_paintOffset += toRenderInline(container)->relativePositionedInlineOffset(renderer); 58 } 59 } 60 61 m_layoutOffset = m_paintOffset; 62 63 if (renderer->isRelPositioned() && renderer->hasLayer()) 64 m_paintOffset += renderer->layer()->relativePositionOffset(); 65 66 m_clipped = !fixed && prev->m_clipped; 67 if (m_clipped) 68 m_clipRect = prev->m_clipRect; 69 70 if (renderer->hasOverflowClip()) { 71 RenderLayer* layer = renderer->layer(); 72 IntRect clipRect(toPoint(m_paintOffset) + renderer->view()->layoutDelta(), layer->size()); 73 if (m_clipped) 74 m_clipRect.intersect(clipRect); 75 else { 76 m_clipRect = clipRect; 77 m_clipped = true; 78 } 79 80 m_paintOffset -= layer->scrolledContentOffset(); 81 } 82 83 // If we establish a new page height, then cache the offset to the top of the first page. 84 // We can compare this later on to figure out what part of the page we're actually on, 85 if (pageLogicalHeight || m_columnInfo) { 86 m_pageLogicalHeight = pageLogicalHeight; 87 m_pageOffset = IntSize(m_layoutOffset.width() + renderer->borderLeft() + renderer->paddingLeft(), 88 m_layoutOffset.height() + renderer->borderTop() + renderer->paddingTop()); 89 m_pageLogicalHeightChanged = pageLogicalHeightChanged; 90 } else { 91 // If we don't establish a new page height, then propagate the old page height and offset down. 92 m_pageLogicalHeight = m_next->m_pageLogicalHeight; 93 m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged; 94 m_pageOffset = m_next->m_pageOffset; 95 96 // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto and inline blocks. 97 if (renderer->isReplaced() || renderer->scrollsOverflow()) 98 m_pageLogicalHeight = 0; 99 } 100 101 if (!m_columnInfo) 102 m_columnInfo = m_next->m_columnInfo; 103 104 m_layoutDelta = m_next->m_layoutDelta; 105 106 // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present. 107 } 108 109 LayoutState::LayoutState(RenderObject* root) 110 : m_clipped(false) 111 , m_pageLogicalHeight(0) 112 , m_pageLogicalHeightChanged(false) 113 , m_columnInfo(0) 114 , m_next(0) 115 #ifndef NDEBUG 116 , m_renderer(root) 117 #endif 118 { 119 RenderObject* container = root->container(); 120 FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), false, true); 121 m_paintOffset = IntSize(absContentPoint.x(), absContentPoint.y()); 122 123 if (container->hasOverflowClip()) { 124 RenderLayer* layer = toRenderBoxModelObject(container)->layer(); 125 m_clipped = true; 126 m_clipRect = IntRect(toPoint(m_paintOffset), layer->size()); 127 m_paintOffset -= layer->scrolledContentOffset(); 128 } 129 } 130 131 #ifndef NDEBUG 132 static bool inLayoutStateDestroy; 133 #endif 134 135 void LayoutState::destroy(RenderArena* renderArena) 136 { 137 #ifndef NDEBUG 138 inLayoutStateDestroy = true; 139 #endif 140 delete this; 141 #ifndef NDEBUG 142 inLayoutStateDestroy = false; 143 #endif 144 renderArena->free(*(size_t*)this, this); 145 } 146 147 void* LayoutState::operator new(size_t sz, RenderArena* renderArena) throw() 148 { 149 return renderArena->allocate(sz); 150 } 151 152 void LayoutState::operator delete(void* ptr, size_t sz) 153 { 154 ASSERT(inLayoutStateDestroy); 155 *(size_t*)ptr = sz; 156 } 157 158 void LayoutState::clearPaginationInformation() 159 { 160 m_pageLogicalHeight = m_next->m_pageLogicalHeight; 161 m_pageOffset = m_next->m_pageOffset; 162 m_columnInfo = m_next->m_columnInfo; 163 } 164 165 int LayoutState::pageLogicalOffset(int childLogicalOffset) const 166 { 167 return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height(); 168 } 169 170 void LayoutState::addForcedColumnBreak(int childLogicalOffset) 171 { 172 if (!m_columnInfo || m_columnInfo->columnHeight()) 173 return; 174 m_columnInfo->addForcedBreak(pageLogicalOffset(childLogicalOffset)); 175 } 176 177 } // namespace WebCore 178