📄 renderboxmodelobject.cpp
字号:
includeLeftEdge ? style()->borderBottomLeftRadius() : IntSize(), includeRightEdge ? style()->borderBottomRightRadius() : IntSize()); clippedToBorderRadius = true; } if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) { // Clip to the padding or content boxes as necessary. bool includePadding = bgLayer->clip() == ContentFillBox; int x = tx + bLeft + (includePadding ? pLeft : 0); int y = ty + borderTop() + (includePadding ? paddingTop() : 0); int width = w - bLeft - bRight - (includePadding ? pLeft + pRight : 0); int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0); context->save(); context->clip(IntRect(x, y, width, height)); } else if (bgLayer->clip() == TextFillBox) { // We have to draw our text into a mask that can then be used to clip background drawing. // First figure out how big the mask has to be. It should be no bigger than what we need // to actually render, so we should intersect the dirty rect with the border box of the background. IntRect maskRect(tx, ty, w, h); maskRect.intersect(paintInfo.rect); // Now create the mask. auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false); if (!maskImage.get()) return; GraphicsContext* maskImageContext = maskImage->context(); maskImageContext->translate(-maskRect.x(), -maskRect.y()); // Now add the text to the clip. We do this by painting using a special paint phase that signals to // InlineTextBoxes that they should just add their contents to the clip. PaintInfo info(maskImageContext, maskRect, PaintPhaseTextClip, true, 0, 0); if (box) box->paint(info, tx - box->x(), ty - box->y()); else paint(info, tx, ty); // The mask has been created. Now we just need to clip to it. context->save(); context->clipToImageBuffer(maskRect, maskImage.get()); } StyleImage* bg = bgLayer->image(); bool shouldPaintBackgroundImage = bg && bg->canRender(style()->effectiveZoom()); Color bgColor = c; // When this style flag is set, change existing background colors and images to a solid white background. // If there's no bg color or image, leave it untouched to avoid affecting transparency. // We don't try to avoid loading the background images, because this style flag is only set // when printing, and at that point we've already loaded the background images anyway. (To avoid // loading the background images we'd have to do this check when applying styles rather than // while rendering.) if (style()->forceBackgroundsToWhite()) { // Note that we can't reuse this variable below because the bgColor might be changed bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha() > 0; if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) { bgColor = Color::white; shouldPaintBackgroundImage = false; } } // Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with // no background in the child document should show the parent's background. bool isTransparent = false; if (!bgLayer->next() && isRoot() && !(bgColor.isValid() && bgColor.alpha() > 0) && view()->frameView()) { Node* elt = document()->ownerElement(); if (elt) { if (!elt->hasTagName(frameTag)) { // Locate the <body> element using the DOM. This is easier than trying // to crawl around a render tree with potential :before/:after content and // anonymous blocks created by inline <body> tags etc. We can locate the <body> // render object very easily via the DOM. HTMLElement* body = document()->body(); isTransparent = !body || !body->hasLocalName(framesetTag); // Can't scroll a frameset document anyway. } } else isTransparent = view()->frameView()->isTransparent(); // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent. if (isTransparent) view()->frameView()->setUseSlowRepaints(); // The parent must show behind the child. } // Paint the color first underneath all images. if (!bgLayer->next()) { IntRect rect(tx, clipY, w, clipH); // If we have an alpha and we are painting the root element, go ahead and blend with the base background color. if (isRoot() && (!bgColor.isValid() || bgColor.alpha() < 0xFF) && !isTransparent) { Color baseColor = view()->frameView()->baseBackgroundColor(); if (baseColor.alpha() > 0) { context->save(); context->setCompositeOperation(CompositeCopy); context->fillRect(rect, baseColor); context->restore(); } else context->clearRect(rect); } if (bgColor.isValid() && bgColor.alpha() > 0) context->fillRect(rect, bgColor); } // no progressive loading of the background image if (shouldPaintBackgroundImage) { IntRect destRect; IntPoint phase; IntSize tileSize; calculateBackgroundImageGeometry(bgLayer, tx, ty, w, h, destRect, phase, tileSize); IntPoint destOrigin = destRect.location(); destRect.intersect(paintInfo.rect); if (!destRect.isEmpty()) { phase += destRect.location() - destOrigin; CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op; context->drawTiledImage(bg->image(this, tileSize), destRect, phase, tileSize, compositeOp); } } if (bgLayer->clip() != BorderFillBox) // Undo the background clip context->restore(); if (clippedToBorderRadius) // Undo the border radius clip context->restore();}IntSize RenderBoxModelObject::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const{ StyleImage* bg = bgLayer->image(); bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the box established by background-origin. if (bgLayer->isSizeSet()) { int w = scaledWidth; int h = scaledHeight; Length bgWidth = bgLayer->size().width(); Length bgHeight = bgLayer->size().height(); if (bgWidth.isFixed()) w = bgWidth.value(); else if (bgWidth.isPercent()) w = bgWidth.calcValue(scaledWidth); if (bgHeight.isFixed()) h = bgHeight.value(); else if (bgHeight.isPercent()) h = bgHeight.calcValue(scaledHeight); // If one of the values is auto we have to use the appropriate // scale to maintain our aspect ratio. if (bgWidth.isAuto() && !bgHeight.isAuto()) w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg->imageSize(this, style()->effectiveZoom()).height(); else if (!bgWidth.isAuto() && bgHeight.isAuto()) h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg->imageSize(this, style()->effectiveZoom()).width(); else if (bgWidth.isAuto() && bgHeight.isAuto()) { // If both width and height are auto, we just want to use the image's // intrinsic size. w = bg->imageSize(this, style()->effectiveZoom()).width(); h = bg->imageSize(this, style()->effectiveZoom()).height(); } return IntSize(max(1, w), max(1, h)); } else return bg->imageSize(this, style()->effectiveZoom());}void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgLayer, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize){ int pw; int ph; int left = 0; int right = 0; int top = 0; int bottom = 0; int cx; int cy; int rw = 0; int rh = 0; // CSS2 chapter 14.2.1 if (bgLayer->attachment()) { // Scroll if (bgLayer->origin() != BorderFillBox) { left = borderLeft(); right = borderRight(); top = borderTop(); bottom = borderBottom(); if (bgLayer->origin() == ContentFillBox) { left += paddingLeft(); right += paddingRight(); top += paddingTop(); bottom += paddingBottom(); } } // The background of the box generated by the root element covers the entire canvas including // its margins. Since those were added in already, we have to factor them out when computing the // box used by background-origin/size/position. if (isRoot()) { rw = toRenderBox(this)->width() - left - right; rh = toRenderBox(this)->height() - top - bottom; left += marginLeft(); right += marginRight(); top += marginTop(); bottom += marginBottom(); } cx = tx; cy = ty; pw = w - left - right; ph = h - top - bottom; } else { // Fixed IntRect vr = viewRect(); cx = vr.x(); cy = vr.y(); pw = vr.width(); ph = vr.height(); } int sx = 0; int sy = 0; int cw; int ch; IntSize scaledImageSize; if (isRoot() && bgLayer->attachment()) scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh); else scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph); int scaledImageWidth = scaledImageSize.width(); int scaledImageHeight = scaledImageSize.height(); EFillRepeat backgroundRepeat = bgLayer->repeat(); int xPosition; if (isRoot() && bgLayer->attachment()) xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true); else xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true); if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) { cw = pw + left + right; sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledImageWidth : 0; } else { cx += max(xPosition + left, 0); sx = -min(xPosition + left, 0); cw = scaledImageWidth + min(xPosition + left, 0); } int yPosition; if (isRoot() && bgLayer->attachment()) yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true); else yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true); if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) { ch = ph + top + bottom; sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledImageHeight : 0; } else { cy += max(yPosition + top, 0); sy = -min(yPosition + top, 0); ch = scaledImageHeight + min(yPosition + top, 0); } if (!bgLayer->attachment()) { sx += max(tx - cx, 0); sy += max(ty - cy, 0); } destRect = IntRect(cx, cy, cw, ch); destRect.intersect(IntRect(tx, ty, w, h)); phase = IntPoint(sx, sy); tileSize = IntSize(scaledImageWidth, scaledImageHeight);}int RenderBoxModelObject::verticalPosition(bool firstLine) const{ // This method determines the vertical position for inline elements. ASSERT(isInline()); if (!isInline())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -