1 /* 2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "InlineBox.h" 22 23 #include "HitTestResult.h" 24 #include "InlineFlowBox.h" 25 #include "RenderArena.h" 26 #include "RenderBox.h" 27 #include "RootInlineBox.h" 28 29 using namespace std; 30 31 namespace WebCore { 32 33 #ifndef NDEBUG 34 static bool inInlineBoxDetach; 35 #endif 36 37 #ifndef NDEBUG 38 39 InlineBox::~InlineBox() 40 { 41 if (!m_hasBadParent && m_parent) 42 m_parent->setHasBadChildList(); 43 } 44 45 #endif 46 47 void InlineBox::remove() 48 { 49 if (parent()) 50 parent()->removeChild(this); 51 } 52 53 void InlineBox::destroy(RenderArena* renderArena) 54 { 55 #ifndef NDEBUG 56 inInlineBoxDetach = true; 57 #endif 58 delete this; 59 #ifndef NDEBUG 60 inInlineBoxDetach = false; 61 #endif 62 63 // Recover the size left there for us by operator delete and free the memory. 64 renderArena->free(*(size_t *)this, this); 65 } 66 67 void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw() 68 { 69 return renderArena->allocate(sz); 70 } 71 72 void InlineBox::operator delete(void* ptr, size_t sz) 73 { 74 ASSERT(inInlineBoxDetach); 75 76 // Stash size where destroy can find it. 77 *(size_t *)ptr = sz; 78 } 79 80 #ifndef NDEBUG 81 void InlineBox::showTreeForThis() const 82 { 83 if (m_renderer) 84 m_renderer->showTreeForThis(); 85 } 86 #endif 87 88 int InlineBox::height() const 89 { 90 #if ENABLE(SVG) 91 if (hasVirtualHeight()) 92 return virtualHeight(); 93 #endif 94 95 if (renderer()->isText()) 96 return m_isText ? renderer()->style(m_firstLine)->font().height() : 0; 97 if (renderer()->isBox() && parent()) 98 return toRenderBox(m_renderer)->height(); 99 100 ASSERT(isInlineFlowBox()); 101 RenderBoxModelObject* flowObject = boxModelObject(); 102 const Font& font = renderer()->style(m_firstLine)->font(); 103 int result = font.height(); 104 if (parent()) 105 result += flowObject->borderTop() + flowObject->paddingTop() + flowObject->borderBottom() + flowObject->paddingBottom(); 106 return result; 107 } 108 109 int InlineBox::caretMinOffset() const 110 { 111 return m_renderer->caretMinOffset(); 112 } 113 114 int InlineBox::caretMaxOffset() const 115 { 116 return m_renderer->caretMaxOffset(); 117 } 118 119 unsigned InlineBox::caretMaxRenderedOffset() const 120 { 121 return 1; 122 } 123 124 void InlineBox::dirtyLineBoxes() 125 { 126 markDirty(); 127 for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent()) 128 curr->markDirty(); 129 } 130 131 void InlineBox::deleteLine(RenderArena* arena) 132 { 133 if (!m_extracted && m_renderer->isBox()) 134 toRenderBox(m_renderer)->setInlineBoxWrapper(0); 135 destroy(arena); 136 } 137 138 void InlineBox::extractLine() 139 { 140 m_extracted = true; 141 if (m_renderer->isBox()) 142 toRenderBox(m_renderer)->setInlineBoxWrapper(0); 143 } 144 145 void InlineBox::attachLine() 146 { 147 m_extracted = false; 148 if (m_renderer->isBox()) 149 toRenderBox(m_renderer)->setInlineBoxWrapper(this); 150 } 151 152 void InlineBox::adjustPosition(int dx, int dy) 153 { 154 m_x += dx; 155 m_y += dy; 156 if (m_renderer->isReplaced()) { 157 RenderBox* box = toRenderBox(m_renderer); 158 box->move(dx, dy); 159 } 160 } 161 162 void InlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty) 163 { 164 if (!renderer()->shouldPaintWithinRoot(paintInfo) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) 165 return; 166 167 // Paint all phases of replaced elements atomically, as though the replaced element established its 168 // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1 169 // specification.) 170 bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip; 171 RenderObject::PaintInfo info(paintInfo); 172 info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; 173 renderer()->paint(info, tx, ty); 174 if (!preservePhase) { 175 info.phase = PaintPhaseChildBlockBackgrounds; 176 renderer()->paint(info, tx, ty); 177 info.phase = PaintPhaseFloat; 178 renderer()->paint(info, tx, ty); 179 info.phase = PaintPhaseForeground; 180 renderer()->paint(info, tx, ty); 181 info.phase = PaintPhaseOutline; 182 renderer()->paint(info, tx, ty); 183 } 184 } 185 186 bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty) 187 { 188 // Hit test all phases of replaced elements atomically, as though the replaced element established its 189 // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1 190 // specification.) 191 return renderer()->hitTest(request, result, IntPoint(x, y), tx, ty); 192 } 193 194 const RootInlineBox* InlineBox::root() const 195 { 196 if (m_parent) 197 return m_parent->root(); 198 ASSERT(isRootInlineBox()); 199 return static_cast<const RootInlineBox*>(this); 200 } 201 202 RootInlineBox* InlineBox::root() 203 { 204 if (m_parent) 205 return m_parent->root(); 206 ASSERT(isRootInlineBox()); 207 return static_cast<RootInlineBox*>(this); 208 } 209 210 bool InlineBox::nextOnLineExists() const 211 { 212 if (!m_determinedIfNextOnLineExists) { 213 m_determinedIfNextOnLineExists = true; 214 215 if (!parent()) 216 m_nextOnLineExists = false; 217 else if (nextOnLine()) 218 m_nextOnLineExists = true; 219 else 220 m_nextOnLineExists = parent()->nextOnLineExists(); 221 } 222 return m_nextOnLineExists; 223 } 224 225 bool InlineBox::prevOnLineExists() const 226 { 227 if (!m_determinedIfPrevOnLineExists) { 228 m_determinedIfPrevOnLineExists = true; 229 230 if (!parent()) 231 m_prevOnLineExists = false; 232 else if (prevOnLine()) 233 m_prevOnLineExists = true; 234 else 235 m_prevOnLineExists = parent()->prevOnLineExists(); 236 } 237 return m_prevOnLineExists; 238 } 239 240 InlineBox* InlineBox::nextLeafChild() const 241 { 242 InlineBox* leaf = 0; 243 for (InlineBox* box = nextOnLine(); box && !leaf; box = box->nextOnLine()) 244 leaf = box->isLeaf() ? box : static_cast<InlineFlowBox*>(box)->firstLeafChild(); 245 if (!leaf && parent()) 246 leaf = parent()->nextLeafChild(); 247 return leaf; 248 } 249 250 InlineBox* InlineBox::prevLeafChild() const 251 { 252 InlineBox* leaf = 0; 253 for (InlineBox* box = prevOnLine(); box && !leaf; box = box->prevOnLine()) 254 leaf = box->isLeaf() ? box : static_cast<InlineFlowBox*>(box)->lastLeafChild(); 255 if (!leaf && parent()) 256 leaf = parent()->prevLeafChild(); 257 return leaf; 258 } 259 260 RenderObject::SelectionState InlineBox::selectionState() 261 { 262 return renderer()->selectionState(); 263 } 264 265 bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) 266 { 267 // Non-replaced elements can always accommodate an ellipsis. 268 if (!m_renderer || !m_renderer->isReplaced()) 269 return true; 270 271 IntRect boxRect(m_x, 0, m_width, 10); 272 IntRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10); 273 return !(boxRect.intersects(ellipsisRect)); 274 } 275 276 int InlineBox::placeEllipsisBox(bool, int, int, int, bool&) 277 { 278 // Use -1 to mean "we didn't set the position." 279 return -1; 280 } 281 282 } // namespace WebCore 283 284 #ifndef NDEBUG 285 286 void showTree(const WebCore::InlineBox* b) 287 { 288 if (b) 289 b->showTreeForThis(); 290 } 291 292 #endif 293