📄 render_box.cpp
字号:
// Paint the color first underneath all images.
if (!bgLayer->next() && bgColor.isValid() && qAlpha(bgColor.rgb()) > 0) {
// If we have an alpha and we are painting the root element, go ahead and blend with our default
// background color (typically white).
if (qAlpha(bgColor.rgb()) < 0xFF && isRoot() && !canvas()->view()->isTransparent())
p->fillRect(_tx, clipy, w, cliph, canvas()->view()->palette().active().color(QColorGroup::Base));
p->fillRect(_tx, clipy, w, cliph, bgColor);
}
// no progressive loading of the background image
if (shouldPaintBackgroundImage) {
int sx = 0;
int sy = 0;
int cw,ch;
int cx,cy;
int vpab = bleft + bright;
int hpab = borderTop() + borderBottom();
// CSS2 chapter 14.2.1
if (bgLayer->backgroundAttachment())
{
//scroll
int pw = w - vpab;
int ph = h - hpab;
int pixw = bg->pixmap_size().width();
int pixh = bg->pixmap_size().height();
EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && w > pixw ) {
cw = pixw;
int xPosition = bgLayer->backgroundXPosition().minWidth(pw-pixw);
if (xPosition >= 0)
cx = _tx + xPosition;
else {
cx = _tx;
if (pixw == 0)
sx = 0;
else {
sx = -xPosition;
cw += xPosition;
}
}
cx += bleft;
} else {
cw = w;
cx = _tx;
if (pixw == 0)
sx = 0;
else {
sx = pixw - ((bgLayer->backgroundXPosition().minWidth(pw-pixw)) % pixw );
sx -= bleft % pixw;
}
}
if( (bgr == NO_REPEAT || bgr == REPEAT_X) && h > pixh ) {
ch = pixh;
int yPosition = bgLayer->backgroundYPosition().minWidth(ph-pixh);
if (yPosition >= 0)
cy = _ty + yPosition;
else {
cy = _ty;
if (pixh == 0)
sy = 0;
else {
sy = -yPosition;
ch += yPosition;
}
}
cy += borderTop();
} else {
ch = h;
cy = _ty;
if(pixh == 0){
sy = 0;
}else{
sy = pixh - ((bgLayer->backgroundYPosition().minWidth(ph-pixh)) % pixh );
sy -= borderTop() % pixh;
}
}
}
else
{
//fixed
QRect vr = viewRect();
int pw = vr.width();
int ph = vr.height();
int pixw = bg->pixmap_size().width();
int pixh = bg->pixmap_size().height();
EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && pw > pixw ) {
cw = pixw;
cx = vr.x() + bgLayer->backgroundXPosition().minWidth(pw-pixw);
} else {
cw = pw;
cx = vr.x();
if(pixw == 0){
sx = 0;
}else{
sx = pixw - ((bgLayer->backgroundXPosition().minWidth(pw-pixw)) % pixw );
}
}
if( (bgr == NO_REPEAT || bgr == REPEAT_X) && ph > pixh ) {
ch = pixh;
cy = vr.y() + bgLayer->backgroundYPosition().minWidth(ph-pixh);
} else {
ch = ph;
cy = vr.y();
if(pixh == 0){
sy = 0;
}else{
sy = pixh - ((bgLayer->backgroundYPosition().minWidth(ph-pixh)) % pixh );
}
}
QRect fix(cx,cy,cw,ch);
QRect ele(_tx,_ty,w,h);
QRect b = fix.intersect(ele);
sx+=b.x()-cx;
sy+=b.y()-cy;
cx=b.x();cy=b.y();cw=b.width();ch=b.height();
}
// kdDebug() << "cx="<<cx << " cy="<<cy<< " cw="<<cw << " ch="<<ch << " sx="<<sx << " sy="<<sy << endl;
if (cw>0 && ch>0)
p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c), sx, sy);
}
}
void RenderBox::outlineBox(QPainter *p, int _tx, int _ty, const char *color)
{
p->setPen(QPen(QColor(color), 1, Qt::DotLine));
p->setBrush( Qt::NoBrush );
p->drawRect(_tx, _ty, m_width, m_height);
}
QRect RenderBox::getOverflowClipRect(int tx, int ty)
{
// XXX When overflow-clip (CSS3) is implemented, we'll obtain the property
// here.
int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight();
int clipx = tx+bl;
int clipy = ty+bt;
int clipw = m_width-bl-br;
int cliph = m_height-bt-bb;
// Subtract out scrollbars if we have them.
if (m_layer) {
clipw -= m_layer->verticalScrollbarWidth();
cliph -= m_layer->horizontalScrollbarHeight();
}
return QRect(clipx,clipy,clipw,cliph);
}
QRect RenderBox::getClipRect(int tx, int ty)
{
int clipx = tx;
int clipy = ty;
int clipw = m_width;
int cliph = m_height;
if (!style()->clipLeft().isVariable())
{
int c=style()->clipLeft().width(m_width);
clipx+=c;
clipw-=c;
}
if (!style()->clipRight().isVariable())
{
int w = style()->clipRight().width(m_width);
clipw -= m_width - w;
}
if (!style()->clipTop().isVariable())
{
int c=style()->clipTop().width(m_height);
clipy+=c;
cliph-=c;
}
if (!style()->clipBottom().isVariable())
{
int h = style()->clipBottom().width(m_height);
cliph -= m_height - h;
}
//kdDebug( 6040 ) << "setting clip("<<clipx<<","<<clipy<<","<<clipw<<","<<cliph<<")"<<endl;
QRect cr(clipx,clipy,clipw,cliph);
return cr;
}
int RenderBox::containingBlockWidth() const
{
RenderBlock* cb = containingBlock();
if (!cb)
return 0;
if (usesLineWidth())
return cb->lineWidth(m_y);
else
return cb->contentWidth();
}
bool RenderBox::absolutePosition(int &xPos, int &yPos, bool f)
{
if (style()->position() == FIXED)
f = true;
RenderObject *o = container();
if (o && o->absolutePosition(xPos, yPos, f)) {
if (o->hasOverflowClip())
o->layer()->subtractScrollOffset(xPos, yPos);
if (!isInline() || isReplaced())
xPos += m_x, yPos += m_y;
if (isRelPositioned())
relativePositionOffset(xPos, yPos);
return true;
}
else {
xPos = yPos = 0;
return false;
}
}
void RenderBox::dirtyLineBoxes(bool fullLayout, bool)
{
if (m_inlineBoxWrapper) {
if (fullLayout) {
m_inlineBoxWrapper->detach(renderArena());
m_inlineBoxWrapper = 0;
}
else
m_inlineBoxWrapper->dirtyLineBoxes();
}
}
void RenderBox::position(InlineBox* box, int from, int len, bool reverse)
{
if (isPositioned()) {
// Cache the x position only if we were an INLINE type originally.
bool wasInline = style()->isOriginalDisplayInlineType();
if (wasInline && hasStaticX()) {
// The value is cached in the xPos of the box. We only need this value if
// our object was inline originally, since otherwise it would have ended up underneath
// the inlines.
m_staticX = box->xPos();
}
else if (!wasInline && hasStaticY())
// Our object was a block originally, so we make our normal flow position be
// just below the line box (as though all the inlines that came before us got
// wrapped in an anonymous block, which is what would have happened had we been
// in flow). This value was cached in the yPos() of the box.
m_staticY = box->yPos();
// Nuke the box.
box->remove();
box->detach(renderArena());
}
else if (isReplaced()) {
m_x = box->xPos();
m_y = box->yPos();
m_inlineBoxWrapper = box;
}
}
// For inline replaced elements, this function returns the inline box that owns us. Enables
// the replaced RenderObject to quickly determine what line it is contained on and to easily
// iterate over structures on the line.
InlineBox* RenderBox::inlineBoxWrapper() const
{
return m_inlineBoxWrapper;
}
void RenderBox::deleteLineBoxWrapper()
{
if (m_inlineBoxWrapper)
m_inlineBoxWrapper->detach(renderArena());
m_inlineBoxWrapper = 0;
}
void RenderBox::setInlineBoxWrapper(InlineBox* b)
{
m_inlineBoxWrapper = b;
}
QRect RenderBox::getAbsoluteRepaintRect()
{
int ow = style() ? style()->outlineSize() : 0;
QRect r(-ow, -ow, overflowWidth(false)+ow*2, overflowHeight(false)+ow*2);
computeAbsoluteRepaintRect(r);
return r;
}
void RenderBox::computeAbsoluteRepaintRect(QRect& r, bool f)
{
int x = r.x() + m_x;
int y = r.y() + m_y;
// Apply the relative position offset when invalidating a rectangle. The layer
// is translated, but the render box isn't, so we need to do this to get the
// right dirty rect. Since this is called from RenderObject::setStyle, the relative position
// flag on the RenderObject has been cleared, so use the one on the style().
if (style()->position() == RELATIVE && m_layer)
m_layer->relativePositionOffset(x,y);
if (style()->position()==FIXED)
f = true;
RenderObject* o = container();
if (o) {
// <body> may not have overflow, since it might be applying its overflow value to the
// scrollbars.
if (o->hasOverflowClip()) {
// o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
QRect boxRect(0, 0, o->layer()->width(), o->layer()->height());
o->layer()->subtractScrollOffset(x,y); // For overflow:auto/scroll/hidden.
QRect repaintRect(x, y, r.width(), r.height());
r = repaintRect.intersect(boxRect);
if (r.isEmpty())
return;
}
else {
r.setX(x);
r.setY(y);
}
o->computeAbsoluteRepaintRect(r, f);
}
}
void RenderBox::repaintDuringLayoutIfMoved(int oldX, int oldY)
{
int newX = m_x;
int newY = m_y;
if (oldX != newX || oldY != newY) {
// The child moved. Invalidate the object's old and new positions. We have to do this
// since the object may not have gotten a layout.
m_x = oldX; m_y = oldY;
repaint();
repaintFloatingDescendants();
m_x = newX; m_y = newY;
repaint();
repaintFloatingDescendants();
}
}
void RenderBox::relativePositionOffset(int &tx, int &ty)
{
if(!style()->left().isVariable())
tx += style()->left().width(containingBlockWidth());
else if(!style()->right().isVariable())
tx -= style()->right().width(containingBlockWidth());
if(!style()->top().isVariable())
{
if (!style()->top().isPercent()
|| containingBlock()->style()->height().isFixed())
ty += style()->top().width(containingBlockHeight());
}
else if(!style()->bottom().isVariable())
{
if (!style()->bottom().isPercent()
|| containingBlock()->style()->height().isFixed())
ty -= style()->bottom().width(containingBlockHeight());
}
}
void RenderBox::calcWidth()
{
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << "RenderBox("<<renderName()<<")::calcWidth()" << endl;
#endif
if (isPositioned())
{
calcAbsoluteHorizontal();
}
else
{
// The parent box is flexing us, so it has increased or decreased our width. Use the width
// from the style context.
if (m_overrideSize != -1 && parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
&& parent()->isFlexingChildren()) {
m_width = m_overrideSize;
return;
}
bool inVerticalBox = parent()->isFlexibleBox() && parent()->style()->boxOrient() == VERTICAL;
bool stretching = parent()->style()->boxAlign() == BSTRETCH;
bool treatAsReplaced = isReplaced() && !isInlineBlockOrInlineTable() &&
(!inVerticalBox || !stretching);
Length w;
if (treatAsReplaced)
w = Length( calcReplacedWidth(), Fixed );
else
w = style()->width();
Length ml = style()->marginLeft();
Length mr = style()->marginRight();
RenderBlock *cb = containingBlock();
int cw = containingBlockWidth();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -