?? render_line.cpp
字號:
/**
* This file is part of the html renderer for KDE.
*
* Copyright (C) 2003 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
// -------------------------------------------------------------------------
#include <kdebug.h>
#include <assert.h>
#include <qpainter.h>
#include <kglobal.h>
#include "rendering/render_flow.h"
#include "rendering/render_text.h"
#include "rendering/render_table.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_docimpl.h"
#include "html/html_formimpl.h"
#include "render_inline.h"
#include "render_block.h"
#include "render_arena.h"
#include "render_line.h"
#include "khtmlview.h"
#include "htmltags.h"
using namespace DOM;
#ifndef NDEBUG
static bool inInlineBoxDetach;
#endif
namespace khtml {
class EllipsisBox : public InlineBox
{
public:
EllipsisBox(RenderObject* obj, const DOM::AtomicString& ellipsisStr, InlineFlowBox* p,
int w, int y, int h, int b, bool firstLine, InlineBox* markupBox)
:InlineBox(obj), m_str(ellipsisStr) {
m_parent = p;
m_width = w;
m_y = y;
m_height = h;
m_baseline = b;
m_firstLine = firstLine;
m_constructed = true;
m_markupBox = markupBox;
}
virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
virtual bool nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
private:
DOM::AtomicString m_str;
InlineBox* m_markupBox;
};
void InlineBox::remove()
{
if (parent())
parent()->removeChild(this);
}
void InlineBox::detach(RenderArena* renderArena)
{
#ifndef NDEBUG
inInlineBoxDetach = true;
#endif
delete this;
#ifndef NDEBUG
inInlineBoxDetach = false;
#endif
// Recover the size left there for us by operator delete and free the memory.
renderArena->free(*(size_t *)this, this);
}
void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw()
{
return renderArena->allocate(sz);
}
void InlineBox::operator delete(void* ptr, size_t sz)
{
assert(inInlineBoxDetach);
// Stash size where detach can find it.
*(size_t *)ptr = sz;
}
long InlineBox::caretMinOffset() const
{
return 0;
}
long InlineBox::caretMaxOffset() const
{
return 1;
}
unsigned long InlineBox::caretMaxRenderedOffset() const
{
return 1;
}
void InlineBox::dirtyLineBoxes()
{
markDirty();
for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent())
curr->markDirty();
}
void InlineBox::deleteLine(RenderArena* arena)
{
m_object->setInlineBoxWrapper(0);
detach(arena);
}
void InlineBox::extractLine()
{
m_extracted = true;
m_object->setInlineBoxWrapper(0);
}
void InlineBox::attachLine()
{
m_extracted = false;
m_object->setInlineBoxWrapper(this);
}
void InlineBox::adjustPosition(int dx, int dy)
{
m_x += dx;
m_y += dy;
if (m_object->isReplaced() || m_object->isBR())
m_object->setPos(m_object->xPos() + dx, m_object->yPos() + dy);
}
void InlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
{
if (!object()->shouldPaintWithinRoot(i) || i.phase == PaintActionOutline)
return;
// Paint all phases of replaced elements atomically, as though the replaced element established its
// own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
// specification.)
bool paintSelectionOnly = i.phase == PaintActionSelection;
RenderObject::PaintInfo info(i.p, i.r, paintSelectionOnly ? i.phase : PaintActionBlockBackground, i.paintingRoot);
object()->paint(info, tx, ty);
if (!paintSelectionOnly) {
info.phase = PaintActionChildBlockBackgrounds;
object()->paint(info, tx, ty);
info.phase = PaintActionFloat;
object()->paint(info, tx, ty);
info.phase = PaintActionForeground;
object()->paint(info, tx, ty);
info.phase = PaintActionOutline;
object()->paint(info, tx, ty);
}
}
bool InlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
{
// Hit test all phases of replaced elements atomically, as though the replaced element established its
// own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
// specification.)
return object()->hitTest(i, x, y, tx, ty);
}
RootInlineBox* InlineBox::root()
{
if (m_parent)
return m_parent->root();
return static_cast<RootInlineBox*>(this);
}
bool InlineBox::nextOnLineExists() const
{
if (!parent())
return false;
if (nextOnLine())
return true;
return parent()->nextOnLineExists();
}
bool InlineBox::prevOnLineExists() const
{
if (!parent())
return false;
if (prevOnLine())
return true;
return parent()->prevOnLineExists();
}
InlineBox* InlineBox::firstLeafChild()
{
return this;
}
InlineBox* InlineBox::lastLeafChild()
{
return this;
}
InlineBox* InlineBox::nextLeafChild()
{
return parent() ? parent()->firstLeafChildAfterBox(this) : 0;
}
InlineBox* InlineBox::prevLeafChild()
{
return parent() ? parent()->lastLeafChildBeforeBox(this) : 0;
}
RenderObject::SelectionState InlineBox::selectionState()
{
return object()->selectionState();
}
bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)
{
// Non-replaced elements can always accommodate an ellipsis.
if (!m_object || !m_object->isReplaced())
return true;
QRect boxRect(m_x, 0, m_width, 10);
QRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
return !(boxRect.intersects(ellipsisRect));
}
int InlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&)
{
// Use -1 to mean "we didn't set the position."
return -1;
}
RenderFlow* InlineFlowBox::flowObject()
{
return static_cast<RenderFlow*>(m_object);
}
int InlineFlowBox::marginLeft()
{
if (!includeLeftEdge())
return 0;
RenderStyle* cstyle = object()->style();
Length margin = cstyle->marginLeft();
if (margin.type != Variable)
return (margin.type == Fixed ? margin.value : object()->marginLeft());
return 0;
}
int InlineFlowBox::marginRight()
{
if (!includeRightEdge())
return 0;
RenderStyle* cstyle = object()->style();
Length margin = cstyle->marginRight();
if (margin.type != Variable)
return (margin.type == Fixed ? margin.value : object()->marginRight());
return 0;
}
int InlineFlowBox::marginBorderPaddingLeft()
{
return marginLeft() + borderLeft() + paddingLeft();
}
int InlineFlowBox::marginBorderPaddingRight()
{
return marginRight() + borderRight() + paddingRight();
}
int InlineFlowBox::getFlowSpacingWidth()
{
int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->isInlineFlowBox())
totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();
}
return totWidth;
}
void InlineFlowBox::addToLine(InlineBox* child) {
if (!m_firstChild)
m_firstChild = m_lastChild = child;
else {
m_lastChild->m_next = child;
child->m_prev = m_lastChild;
m_lastChild = child;
}
child->setFirstLineStyleBit(m_firstLine);
child->setParent(this);
if (child->isText())
m_hasTextChildren = true;
if (child->object()->selectionState() != RenderObject::SelectionNone)
root()->setHasSelectedChildren(true);
}
void InlineFlowBox::removeChild(InlineBox* child)
{
if (!m_dirty)
dirtyLineBoxes();
root()->childRemoved(child);
if (child == m_firstChild)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -