Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(369)

Side by Side Diff: third_party/WebKit/WebCore/rendering/RenderBoxModelObject.cpp

Issue 21184: WebKit merge 40722:40785 (part 1) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details. 12 * Library General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU Library General Public License 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 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, 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA. 17 * Boston, MA 02110-1301, USA.
18 * 18 *
19 */ 19 */
20 20
21 #include "config.h" 21 #include "config.h"
22 #include "RenderBoxModelObject.h" 22 #include "RenderBoxModelObject.h"
23 23
24 #include "GraphicsContext.h"
25 #include "HTMLElement.h"
26 #include "HTMLNames.h"
27 #include "ImageBuffer.h"
24 #include "RenderBlock.h" 28 #include "RenderBlock.h"
25 #include "RenderLayer.h" 29 #include "RenderLayer.h"
26 #include "RenderView.h" 30 #include "RenderView.h"
27 31
32 using namespace std;
33
28 namespace WebCore { 34 namespace WebCore {
29 35
36 using namespace HTMLNames;
37
30 bool RenderBoxModelObject::s_wasFloating = false; 38 bool RenderBoxModelObject::s_wasFloating = false;
31 39
32 RenderBoxModelObject::RenderBoxModelObject(Node* node) 40 RenderBoxModelObject::RenderBoxModelObject(Node* node)
33 : RenderObject(node) 41 : RenderObject(node)
34 , m_layer(0) 42 , m_layer(0)
35 { 43 {
36 } 44 }
37 45
38 RenderBoxModelObject::~RenderBoxModelObject() 46 RenderBoxModelObject::~RenderBoxModelObject()
39 { 47 {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 if (!style()->top().isAuto()) { 118 if (!style()->top().isAuto()) {
111 if (!style()->top().isPercent() || containingBlock()->style()->height(). isFixed()) 119 if (!style()->top().isPercent() || containingBlock()->style()->height(). isFixed())
112 return style()->top().calcValue(containingBlockHeight()); 120 return style()->top().calcValue(containingBlockHeight());
113 } else if (!style()->bottom().isAuto()) { 121 } else if (!style()->bottom().isAuto()) {
114 if (!style()->bottom().isPercent() || containingBlock()->style()->height ().isFixed()) 122 if (!style()->bottom().isPercent() || containingBlock()->style()->height ().isFixed())
115 return -style()->bottom().calcValue(containingBlockHeight()); 123 return -style()->bottom().calcValue(containingBlockHeight());
116 } 124 }
117 return 0; 125 return 0;
118 } 126 }
119 127
128 int RenderBoxModelObject::offsetLeft() const
129 {
130 RenderBoxModelObject* offsetPar = offsetParent();
131 if (!offsetPar)
132 return 0;
133 int xPos = (isBox() ? toRenderBox(this)->x() : 0);
134 if (offsetPar->isBox())
135 xPos -= toRenderBox(offsetPar)->borderLeft();
136 if (!isPositioned()) {
137 if (isRelPositioned())
138 xPos += relativePositionOffsetX();
139 RenderObject* curr = parent();
140 while (curr && curr != offsetPar) {
141 // FIXME: What are we supposed to do inside SVG content?
142 if (curr->isBox() && !curr->isTableRow())
143 xPos += toRenderBox(curr)->x();
144 curr = curr->parent();
145 }
146 if (offsetPar->isBox() && offsetPar->isBody() && !offsetPar->isRelPositi oned() && !offsetPar->isPositioned())
147 xPos += toRenderBox(offsetPar)->x();
148 }
149 return xPos;
150 }
151
152 int RenderBoxModelObject::offsetTop() const
153 {
154 RenderBoxModelObject* offsetPar = offsetParent();
155 if (!offsetPar)
156 return 0;
157 int yPos = (isBox() ? toRenderBox(this)->y() : 0);
158 if (offsetPar->isBox())
159 yPos -= toRenderBox(offsetPar)->borderTop();
160 if (!isPositioned()) {
161 if (isRelPositioned())
162 yPos += relativePositionOffsetY();
163 RenderObject* curr = parent();
164 while (curr && curr != offsetPar) {
165 // FIXME: What are we supposed to do inside SVG content?
166 if (curr->isBox() && !curr->isTableRow())
167 yPos += toRenderBox(curr)->y();
168 curr = curr->parent();
169 }
170 if (offsetPar->isBox() && offsetPar->isBody() && !offsetPar->isRelPositi oned() && !offsetPar->isPositioned())
171 yPos += toRenderBox(offsetPar)->y();
172 }
173 return yPos;
174 }
175
176 int RenderBoxModelObject::paddingTop(bool) const
177 {
178 int w = 0;
179 Length padding = style()->paddingTop();
180 if (padding.isPercent())
181 w = containingBlock()->availableWidth();
182 return padding.calcMinValue(w);
183 }
184
185 int RenderBoxModelObject::paddingBottom(bool) const
186 {
187 int w = 0;
188 Length padding = style()->paddingBottom();
189 if (padding.isPercent())
190 w = containingBlock()->availableWidth();
191 return padding.calcMinValue(w);
192 }
193
194 int RenderBoxModelObject::paddingLeft(bool) const
195 {
196 int w = 0;
197 Length padding = style()->paddingLeft();
198 if (padding.isPercent())
199 w = containingBlock()->availableWidth();
200 return padding.calcMinValue(w);
201 }
202
203 int RenderBoxModelObject::paddingRight(bool) const
204 {
205 int w = 0;
206 Length padding = style()->paddingRight();
207 if (padding.isPercent())
208 w = containingBlock()->availableWidth();
209 return padding.calcMinValue(w);
210 }
211
212
213 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co nst Color& c, const FillLayer* bgLayer, int clipY, int clipH,
214 int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op)
215 {
216 GraphicsContext* context = paintInfo.context;
217 bool includeLeftEdge = box ? box->includeLeftEdge() : true;
218 bool includeRightEdge = box ? box->includeRightEdge() : true;
219 int bLeft = includeLeftEdge ? borderLeft() : 0;
220 int bRight = includeRightEdge ? borderRight() : 0;
221 int pLeft = includeLeftEdge ? paddingLeft() : 0;
222 int pRight = includeRightEdge ? paddingRight() : 0;
223
224 bool clippedToBorderRadius = false;
225 if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) {
226 context->save();
227 context->addRoundedRectClip(IntRect(tx, ty, w, h),
228 includeLeftEdge ? style()->borderTopLeftRadius() : IntSize(),
229 includeRightEdge ? style()->borderTopRightRadius() : IntSize(),
230 includeLeftEdge ? style()->borderBottomLeftRadius() : IntSize(),
231 includeRightEdge ? style()->borderBottomRightRadius() : IntSize());
232 clippedToBorderRadius = true;
233 }
234
235 if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
236 // Clip to the padding or content boxes as necessary.
237 bool includePadding = bgLayer->clip() == ContentFillBox;
238 int x = tx + bLeft + (includePadding ? pLeft : 0);
239 int y = ty + borderTop() + (includePadding ? paddingTop() : 0);
240 int width = w - bLeft - bRight - (includePadding ? pLeft + pRight : 0);
241 int height = h - borderTop() - borderBottom() - (includePadding ? paddin gTop() + paddingBottom() : 0);
242 context->save();
243 context->clip(IntRect(x, y, width, height));
244 } else if (bgLayer->clip() == TextFillBox) {
245 // We have to draw our text into a mask that can then be used to clip ba ckground drawing.
246 // First figure out how big the mask has to be. It should be no bigger than what we need
247 // to actually render, so we should intersect the dirty rect with the bo rder box of the background.
248 IntRect maskRect(tx, ty, w, h);
249 maskRect.intersect(paintInfo.rect);
250
251 // Now create the mask.
252 auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), f alse);
253 if (!maskImage.get())
254 return;
255
256 GraphicsContext* maskImageContext = maskImage->context();
257 maskImageContext->translate(-maskRect.x(), -maskRect.y());
258
259 // Now add the text to the clip. We do this by painting using a special paint phase that signals to
260 // InlineTextBoxes that they should just add their contents to the clip.
261 PaintInfo info(maskImageContext, maskRect, PaintPhaseTextClip, true, 0, 0);
262 if (box)
263 box->paint(info, tx - box->xPos(), ty - box->yPos());
264 else
265 paint(info, tx, ty);
266
267 // The mask has been created. Now we just need to clip to it.
268 context->save();
269 context->clipToImageBuffer(maskRect, maskImage.get());
270 }
271
272 StyleImage* bg = bgLayer->image();
273 bool shouldPaintBackgroundImage = bg && bg->canRender(style()->effectiveZoom ());
274 Color bgColor = c;
275
276 // When this style flag is set, change existing background colors and images to a solid white background.
277 // If there's no bg color or image, leave it untouched to avoid affecting tr ansparency.
278 // We don't try to avoid loading the background images, because this style f lag is only set
279 // when printing, and at that point we've already loaded the background imag es anyway. (To avoid
280 // loading the background images we'd have to do this check when applying st yles rather than
281 // while rendering.)
282 if (style()->forceBackgroundsToWhite()) {
283 // Note that we can't reuse this variable below because the bgColor migh t be changed
284 bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha() > 0;
285 if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
286 bgColor = Color::white;
287 shouldPaintBackgroundImage = false;
288 }
289 }
290
291 // Only fill with a base color (e.g., white) if we're the root document, sin ce iframes/frames with
292 // no background in the child document should show the parent's background.
293 bool isTransparent = false;
294 if (!bgLayer->next() && isRoot() && !(bgColor.isValid() && bgColor.alpha() > 0) && view()->frameView()) {
295 Node* elt = document()->ownerElement();
296 if (elt) {
297 if (!elt->hasTagName(frameTag)) {
298 // Locate the <body> element using the DOM. This is easier than trying
299 // to crawl around a render tree with potential :before/:after c ontent and
300 // anonymous blocks created by inline <body> tags etc. We can l ocate the <body>
301 // render object very easily via the DOM.
302 HTMLElement* body = document()->body();
303 isTransparent = !body || !body->hasLocalName(framesetTag); // Ca n't scroll a frameset document anyway.
304 }
305 } else
306 isTransparent = view()->frameView()->isTransparent();
307
308 // FIXME: This needs to be dynamic. We should be able to go back to bli tting if we ever stop being transparent.
309 if (isTransparent)
310 view()->frameView()->setUseSlowRepaints(); // The parent must show b ehind the child.
311 }
312
313 // Paint the color first underneath all images.
314 if (!bgLayer->next()) {
315 IntRect rect(tx, clipY, w, clipH);
316 // If we have an alpha and we are painting the root element, go ahead an d blend with the base background color.
317 if (isRoot() && (!bgColor.isValid() || bgColor.alpha() < 0xFF) && !isTra nsparent) {
318 Color baseColor = view()->frameView()->baseBackgroundColor();
319 if (baseColor.alpha() > 0) {
320 context->save();
321 context->setCompositeOperation(CompositeCopy);
322 context->fillRect(rect, baseColor);
323 context->restore();
324 } else
325 context->clearRect(rect);
326 }
327
328 if (bgColor.isValid() && bgColor.alpha() > 0)
329 context->fillRect(rect, bgColor);
330 }
331
332 // no progressive loading of the background image
333 if (shouldPaintBackgroundImage) {
334 IntRect destRect;
335 IntPoint phase;
336 IntSize tileSize;
337
338 calculateBackgroundImageGeometry(bgLayer, tx, ty, w, h, destRect, phase, tileSize);
339 if (!destRect.isEmpty()) {
340 CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer- >composite() : op;
341 context->drawTiledImage(bg->image(this, tileSize), destRect, phase, tileSize, compositeOp);
342 }
343 }
344
345 if (bgLayer->clip() != BorderFillBox)
346 // Undo the background clip
347 context->restore();
348
349 if (clippedToBorderRadius)
350 // Undo the border radius clip
351 context->restore();
352 }
353
354 IntSize RenderBoxModelObject::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const
355 {
356 StyleImage* bg = bgLayer->image();
357 bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the bo x established by background-origin.
358
359 if (bgLayer->isSizeSet()) {
360 int w = scaledWidth;
361 int h = scaledHeight;
362 Length bgWidth = bgLayer->size().width();
363 Length bgHeight = bgLayer->size().height();
364
365 if (bgWidth.isFixed())
366 w = bgWidth.value();
367 else if (bgWidth.isPercent())
368 w = bgWidth.calcValue(scaledWidth);
369
370 if (bgHeight.isFixed())
371 h = bgHeight.value();
372 else if (bgHeight.isPercent())
373 h = bgHeight.calcValue(scaledHeight);
374
375 // If one of the values is auto we have to use the appropriate
376 // scale to maintain our aspect ratio.
377 if (bgWidth.isAuto() && !bgHeight.isAuto())
378 w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg-> imageSize(this, style()->effectiveZoom()).height();
379 else if (!bgWidth.isAuto() && bgHeight.isAuto())
380 h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg- >imageSize(this, style()->effectiveZoom()).width();
381 else if (bgWidth.isAuto() && bgHeight.isAuto()) {
382 // If both width and height are auto, we just want to use the image' s
383 // intrinsic size.
384 w = bg->imageSize(this, style()->effectiveZoom()).width();
385 h = bg->imageSize(this, style()->effectiveZoom()).height();
386 }
387
388 return IntSize(max(1, w), max(1, h));
389 } else
390 return bg->imageSize(this, style()->effectiveZoom());
391 }
392
393 void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL ayer, int tx, int ty, int w, int h,
394 IntRect& destRect, I ntPoint& phase, IntSize& tileSize)
395 {
396 int pw;
397 int ph;
398 int left = 0;
399 int right = 0;
400 int top = 0;
401 int bottom = 0;
402 int cx;
403 int cy;
404 int rw = 0;
405 int rh = 0;
406
407 // CSS2 chapter 14.2.1
408
409 if (bgLayer->attachment()) {
410 // Scroll
411 if (bgLayer->origin() != BorderFillBox) {
412 left = borderLeft();
413 right = borderRight();
414 top = borderTop();
415 bottom = borderBottom();
416 if (bgLayer->origin() == ContentFillBox) {
417 left += paddingLeft();
418 right += paddingRight();
419 top += paddingTop();
420 bottom += paddingBottom();
421 }
422 }
423
424 // The background of the box generated by the root element covers the en tire canvas including
425 // its margins. Since those were added in already, we have to factor th em out when computing the
426 // box used by background-origin/size/position.
427 if (isRoot()) {
428 rw = toRenderBox(this)->width() - left - right;
429 rh = toRenderBox(this)->height() - top - bottom;
430 left += marginLeft();
431 right += marginRight();
432 top += marginTop();
433 bottom += marginBottom();
434 }
435 cx = tx;
436 cy = ty;
437 pw = w - left - right;
438 ph = h - top - bottom;
439 } else {
440 // Fixed
441 IntRect vr = viewRect();
442 cx = vr.x();
443 cy = vr.y();
444 pw = vr.width();
445 ph = vr.height();
446 }
447
448 int sx = 0;
449 int sy = 0;
450 int cw;
451 int ch;
452
453 IntSize scaledImageSize;
454 if (isRoot() && bgLayer->attachment())
455 scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh);
456 else
457 scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph);
458
459 int scaledImageWidth = scaledImageSize.width();
460 int scaledImageHeight = scaledImageSize.height();
461
462 EFillRepeat backgroundRepeat = bgLayer->repeat();
463
464 int xPosition;
465 if (isRoot() && bgLayer->attachment())
466 xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, tru e);
467 else
468 xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, tru e);
469 if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) {
470 cw = pw + left + right;
471 sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledIm ageWidth : 0;
472 } else {
473 cx += max(xPosition + left, 0);
474 sx = -min(xPosition + left, 0);
475 cw = scaledImageWidth + min(xPosition + left, 0);
476 }
477
478 int yPosition;
479 if (isRoot() && bgLayer->attachment())
480 yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, tr ue);
481 else
482 yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, tr ue);
483 if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) {
484 ch = ph + top + bottom;
485 sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledI mageHeight : 0;
486 } else {
487 cy += max(yPosition + top, 0);
488 sy = -min(yPosition + top, 0);
489 ch = scaledImageHeight + min(yPosition + top, 0);
490 }
491
492 if (!bgLayer->attachment()) {
493 sx += max(tx - cx, 0);
494 sy += max(ty - cy, 0);
495 }
496
497 destRect = IntRect(cx, cy, cw, ch);
498 destRect.intersect(IntRect(tx, ty, w, h));
499 phase = IntPoint(sx, sy);
500 tileSize = IntSize(scaledImageWidth, scaledImageHeight);
501 }
502
120 } // namespace WebCore 503 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698