📄 render_object.cpp
字号:
for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
addLayers(curr, parentLayer, newObject, beforeChild);
}
void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
{
if (!parentLayer)
return;
RenderObject* object = newObject;
RenderLayer* beforeChild = 0;
::addLayers(this, parentLayer, object, beforeChild);
}
void RenderObject::removeLayers(RenderLayer* parentLayer)
{
if (!parentLayer)
return;
if (layer()) {
parentLayer->removeChild(layer());
return;
}
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
curr->removeLayers(parentLayer);
}
void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
{
if (!newParent)
return;
if (layer()) {
if (oldParent)
oldParent->removeChild(layer());
newParent->addChild(layer());
return;
}
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
curr->moveLayers(oldParent, newParent);
}
RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
bool checkParent)
{
// Error check the parent layer passed in. If it's null, we can't find anything.
if (!parentLayer)
return 0;
// Step 1: Descend into our siblings trying to find the next layer. If we do find
// a layer, and if its parent layer matches our desired parent layer, then we have
// a match.
for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
curr; curr = curr->nextSibling()) {
RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
if (nextLayer) {
if (nextLayer->parent() == parentLayer)
return nextLayer;
return 0;
}
}
// Step 2: If our layer is the desired parent layer, then we're finished. We didn't
// find anything.
RenderLayer* ourLayer = layer();
if (parentLayer == ourLayer)
return 0;
// Step 3: If we have a layer, then return that layer. It will be checked against
// the desired parent layer in the for loop above.
if (ourLayer)
return ourLayer;
// Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
// follow us to see if we can locate a layer.
if (checkParent && parent())
return parent()->findNextLayer(parentLayer, this, true);
return 0;
}
RenderLayer* RenderObject::enclosingLayer()
{
RenderObject* curr = this;
while (curr) {
RenderLayer *layer = curr->layer();
if (layer)
return layer;
curr = curr->parent();
}
return 0;
}
bool RenderObject::requiresLayer()
{
return isRoot() || isPositioned() || isRelPositioned() || style()->opacity() < 1.0f ||
m_hasOverflowClip;
}
RenderBlock* RenderObject::firstLineBlock() const
{
return 0;
}
void RenderObject::updateFirstLetter()
{}
int RenderObject::offsetLeft() const
{
int x = xPos();
if (!isPositioned()) {
if (isRelPositioned()) {
int y = 0;
((RenderBox*)this)->relativePositionOffset(x, y);
}
RenderObject* offsetPar = offsetParent();
RenderObject* curr = parent();
while (curr && curr != offsetPar) {
x += curr->xPos();
curr = curr->parent();
}
}
return x;
}
int RenderObject::offsetTop() const
{
int y = yPos();
if (!isPositioned()) {
if (isRelPositioned()) {
int x = 0;
((RenderBox*)this)->relativePositionOffset(x, y);
}
RenderObject* offsetPar = offsetParent();
RenderObject* curr = parent();
while (curr && curr != offsetPar) {
y += curr->yPos();
curr = curr->parent();
}
}
return y;
}
RenderObject* RenderObject::offsetParent() const
{
bool skipTables = isPositioned() || isRelPositioned();
RenderObject* curr = parent();
while (curr && !curr->isPositioned() && !curr->isRelPositioned() &&
!curr->isBody()) {
if (!skipTables && (curr->isTableCell() || curr->isTable()))
break;
curr = curr->parent();
}
return curr;
}
// More IE extensions. clientWidth and clientHeight represent the interior of an object
// excluding border and scrollbar.
int
RenderObject::clientWidth() const
{
return width() - borderLeft() - borderRight() -
(includeScrollbarSize() ? layer()->verticalScrollbarWidth() : 0);
}
int
RenderObject::clientHeight() const
{
return height() - borderTop() - borderBottom() -
(includeScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0);
}
// scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
// object has overflow:hidden/scroll/auto specified and also has overflow.
int
RenderObject::scrollWidth() const
{
return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
}
int
RenderObject::scrollHeight() const
{
return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
}
bool RenderObject::scroll(KWQScrollDirection direction, KWQScrollGranularity granularity, float multiplier)
{
RenderLayer *l = layer();
if (l != 0 && l->scroll(direction, granularity, multiplier)) {
return true;
}
RenderBlock *b = containingBlock();
if (b != 0 && !b->isCanvas()) {
return b->scroll(direction, granularity, multiplier);
}
return false;
}
bool
RenderObject::hasStaticX() const
{
return (style()->left().isVariable() && style()->right().isVariable()) ||
style()->left().isStatic() ||
style()->right().isStatic();
}
bool
RenderObject::hasStaticY() const
{
return (style()->top().isVariable() && style()->bottom().isVariable()) || style()->top().isStatic();
}
void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
{
}
void RenderObject::setNeedsLayout(bool b, bool markParents)
{
bool alreadyNeededLayout = m_needsLayout;
m_needsLayout = b;
if (b) {
if (!alreadyNeededLayout && markParents)
markContainingBlocksForLayout();
}
else {
m_posChildNeedsLayout = false;
m_normalChildNeedsLayout = false;
}
}
void RenderObject::setChildNeedsLayout(bool b, bool markParents)
{
bool alreadyNeededLayout = m_normalChildNeedsLayout;
m_normalChildNeedsLayout = b;
if (b) {
if (!alreadyNeededLayout && markParents)
markContainingBlocksForLayout();
}
else {
m_posChildNeedsLayout = false;
m_normalChildNeedsLayout = false;
}
}
void RenderObject::markContainingBlocksForLayout()
{
RenderObject *o = container();
RenderObject *last = this;
while (o) {
if (!last->isText() && (last->style()->position() == FIXED || last->style()->position() == ABSOLUTE)) {
if (o->m_posChildNeedsLayout)
return;
o->m_posChildNeedsLayout = true;
}
else {
if (o->m_normalChildNeedsLayout)
return;
o->m_normalChildNeedsLayout = true;
}
last = o;
o = o->container();
}
last->scheduleRelayout();
}
RenderBlock* RenderObject::containingBlock() const
{
if(isTableCell())
return static_cast<const RenderTableCell *>(this)->table();
if (isCanvas())
return (RenderBlock*)this;
RenderObject *o = parent();
if (!isText() && m_style->position() == FIXED) {
while ( o && !o->isCanvas() )
o = o->parent();
}
else if (!isText() && m_style->position() == ABSOLUTE) {
while (o && (o->style()->position() == STATIC || (o->isInline() && !o->isReplaced()))
&& !o->isRoot() && !o->isCanvas()) {
// For relpositioned inlines, we return the nearest enclosing block. We don't try
// to return the inline itself. This allows us to avoid having a positioned objects
// list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
// from this method. The container() method can actually be used to obtain the
// inline directly.
if (o->style()->position() == RELATIVE && o->isInline() && !o->isReplaced())
return o->containingBlock();
o = o->parent();
}
} else {
while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
|| o->isTableCol() || o->isFrameSet()))
o = o->parent();
}
if (!o || !o->isRenderBlock())
return 0; // Probably doesn't happen any more, but leave just in case. -dwh
return static_cast<RenderBlock*>(o);
}
int RenderObject::containingBlockWidth() const
{
// ###
return containingBlock()->contentWidth();
}
int RenderObject::containingBlockHeight() const
{
// ###
return containingBlock()->contentHeight();
}
bool RenderObject::sizesToMaxWidth() const
{
// Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
// but they allow text to sit on the same line as the marquee.
if (isFloating() || (isCompact() && isInline()) ||
(isInlineBlockOrInlineTable() && !isHTMLMarquee()) ||
(element() && (element()->id() == ID_BUTTON || element()->id() == ID_LEGEND)))
return true;
// Children of a horizontal marquee do not fill the container by default.
// FIXME: Need to deal with MAUTO value properly. It could be vertical.
if (parent()->style()->overflow() == OMARQUEE) {
EMarqueeDirection dir = parent()->style()->marqueeDirection();
if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
return true;
}
// Flexible horizontal boxes lay out children at their maxwidths. Also vertical boxes
// that don't stretch their kids lay out their children at their maxwidths.
if (parent()->isFlexibleBox() &&
(parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
return true;
return false;
}
void RenderObject::drawBorder(QPainter *p, int x1, int y1, int x2, int y2,
BorderSide s, QColor c, const QColor& textcolor, EBorderStyle style,
int adjbw1, int adjbw2, bool invalidisInvert)
{
int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
if(style == DOUBLE && width < 3)
style = SOLID;
if(!c.isValid()) {
if(invalidisInvert)
{
p->setRasterOp(Qt::XorROP);
c = Qt::white;
}
else {
if(style == INSET || style == OUTSET || style == RIDGE || style ==
GROOVE)
c.setRgb(238, 238, 238);
else
c = textcolor;
}
}
switch(style)
{
case BNONE:
case BHIDDEN:
// should not happen
if(invalidisInvert && p->rasterOp() == Qt::XorROP)
p->setRasterOp(Qt::CopyROP);
return;
case DOTTED:
p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DotLine));
/* nobreak; */
case DASHED:
if(style == DASHED)
p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DashLine));
if (width > 0)
switch(s)
{
case BSBottom:
case BSTop:
p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
break;
case BSRight:
case BSLeft:
p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
break;
}
break;
case DOUBLE:
{
int third = (width+1)/3;
if (adjbw1 == 0 && adjbw2 == 0)
{
p->setPen(Qt::NoPen);
p->setBrush(c);
switch(s)
{
case BSTop:
case BSBottom:
p->drawRect(x1, y1 , x2-x1, third);
p->drawRect(x1, y2-third, x2-x1, third);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -