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

Side by Side Diff: Source/core/rendering/RenderBoxModelObject.cpp

Issue 23241010: Support subpixel values for text-shadow and box-shadow (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: missed a virtual test Created 7 years 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) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved. 7 * Copyright (C) 2010 Google Inc. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after
2472 bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundCol or).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255; 2472 bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundCol or).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
2473 2473
2474 GraphicsContextStateSaver stateSaver(*context, false); 2474 GraphicsContextStateSaver stateSaver(*context, false);
2475 2475
2476 const ShadowList* shadowList = s->boxShadow(); 2476 const ShadowList* shadowList = s->boxShadow();
2477 for (size_t i = shadowList->shadows().size(); i--; ) { 2477 for (size_t i = shadowList->shadows().size(); i--; ) {
2478 const ShadowData& shadow = shadowList->shadows()[i]; 2478 const ShadowData& shadow = shadowList->shadows()[i];
2479 if (shadow.style() != shadowStyle) 2479 if (shadow.style() != shadowStyle)
2480 continue; 2480 continue;
2481 2481
2482 IntSize shadowOffset(shadow.x(), shadow.y()); 2482 FloatSize shadowOffset(shadow.x(), shadow.y());
2483 int shadowBlur = shadow.blur(); 2483 float shadowBlur = shadow.blur();
2484 int shadowSpread = shadow.spread(); 2484 float shadowSpread = shadow.spread();
2485 2485
2486 if (shadowOffset.isZero() && !shadowBlur && !shadowSpread) 2486 if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
2487 continue; 2487 continue;
2488 2488
2489 const Color& shadowColor = resolveColor(shadow.color()); 2489 const Color& shadowColor = resolveColor(shadow.color());
2490 2490
2491 if (shadow.style() == Normal) { 2491 if (shadow.style() == Normal) {
2492 RoundedRect fillRect = border; 2492 FloatRect fillRect = border.rect();
2493 fillRect.inflate(shadowSpread); 2493 fillRect.inflate(shadowSpread);
2494 if (fillRect.isEmpty()) 2494 if (fillRect.isEmpty())
2495 continue; 2495 continue;
2496 2496
2497 IntRect shadowRect(border.rect()); 2497 FloatRect shadowRect(border.rect());
2498 shadowRect.inflate(shadowBlur + shadowSpread); 2498 shadowRect.inflate(shadowBlur + shadowSpread);
2499 shadowRect.move(shadowOffset); 2499 shadowRect.move(shadowOffset);
2500 2500
2501 // Save the state and clip, if not already done. 2501 // Save the state and clip, if not already done.
2502 // The clip does not depend on any shadow-specific properties. 2502 // The clip does not depend on any shadow-specific properties.
2503 if (!stateSaver.saved()) { 2503 if (!stateSaver.saved()) {
2504 stateSaver.save(); 2504 stateSaver.save();
2505 if (hasBorderRadius) { 2505 if (hasBorderRadius) {
2506 RoundedRect rectToClipOut = border; 2506 RoundedRect rectToClipOut = border;
2507 2507
2508 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time 2508 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time
2509 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the 2509 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the
2510 // corners. Those are avoided by insetting the clipping path by one pixel. 2510 // corners. Those are avoided by insetting the clipping path by one pixel.
2511 if (hasOpaqueBackground) 2511 if (hasOpaqueBackground)
2512 rectToClipOut.inflateWithRadii(-1); 2512 rectToClipOut.inflateWithRadii(-1);
2513 2513
2514 if (!rectToClipOut.isEmpty()) { 2514 if (!rectToClipOut.isEmpty()) {
2515 context->clipOutRoundedRect(rectToClipOut); 2515 context->clipOutRoundedRect(rectToClipOut);
2516 } 2516 }
2517 } else { 2517 } else {
2518 // This IntRect is correct even with fractional shadows, bec ause it is used for the rectangle
2519 // of the box itself, which is always pixel-aligned.
2518 IntRect rectToClipOut = border.rect(); 2520 IntRect rectToClipOut = border.rect();
2519 2521
2520 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time 2522 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time
2521 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the 2523 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the
2522 // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path 2524 // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path
2523 // by one pixel. 2525 // by one pixel.
2524 if (hasOpaqueBackground) { 2526 if (hasOpaqueBackground) {
2525 // FIXME: The function to decide on the policy based on the transform should be a named function. 2527 // FIXME: The function to decide on the policy based on the transform should be a named function.
2526 // FIXME: It's not clear if this check is right. What ab out integral scale factors? 2528 // FIXME: It's not clear if this check is right. What ab out integral scale factors?
2527 AffineTransform transform = context->getCTM(); 2529 AffineTransform transform = context->getCTM();
2528 if (transform.a() != 1 || (transform.d() != 1 && transfo rm.d() != -1) || transform.b() || transform.c()) 2530 if (transform.a() != 1 || (transform.d() != 1 && transfo rm.d() != -1) || transform.b() || transform.c())
2529 rectToClipOut.inflate(-1); 2531 rectToClipOut.inflate(-1);
2530 } 2532 }
2531 2533
2532 if (!rectToClipOut.isEmpty()) { 2534 if (!rectToClipOut.isEmpty()) {
2533 context->clipOut(rectToClipOut); 2535 context->clipOut(rectToClipOut);
2534 } 2536 }
2535 } 2537 }
2536 } 2538 }
2537 2539
2538 // Draw only the shadow. 2540 // Draw only the shadow.
2539 DrawLooper drawLooper; 2541 DrawLooper drawLooper;
2540 drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor, 2542 drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor,
2541 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresA lpha); 2543 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresA lpha);
2542 context->setDrawLooper(drawLooper); 2544 context->setDrawLooper(drawLooper);
2543 2545
2544 if (hasBorderRadius) { 2546 if (hasBorderRadius) {
2545 RoundedRect influenceRect(shadowRect, border.radii()); 2547 RoundedRect influenceRect(pixelSnappedIntRect(LayoutRect(shadowR ect)), border.radii());
2546 influenceRect.expandRadii(2 * shadowBlur + shadowSpread); 2548 influenceRect.expandRadii(2 * shadowBlur + shadowSpread);
2547 if (allCornersClippedOut(influenceRect, info.rect)) 2549 if (allCornersClippedOut(influenceRect, info.rect))
2548 context->fillRect(fillRect.rect(), Color::black); 2550 context->fillRect(fillRect, Color::black);
2549 else { 2551 else {
2550 fillRect.expandRadii(shadowSpread); 2552 RoundedRect roundedFillRect = border;
2551 if (!fillRect.isRenderable()) 2553 roundedFillRect.inflate(shadowSpread);
2552 fillRect.adjustRadii(); 2554
2553 context->fillRoundedRect(fillRect, Color::black); 2555 roundedFillRect.expandRadii(shadowSpread);
2556 if (!roundedFillRect.isRenderable())
2557 roundedFillRect.adjustRadii();
2558 context->fillRoundedRect(roundedFillRect, Color::black);
2554 } 2559 }
2555 } else { 2560 } else {
2556 context->fillRect(fillRect.rect(), Color::black); 2561 context->fillRect(fillRect, Color::black);
2557 } 2562 }
2558 } else { 2563 } else {
2564 // The inset shadow case.
2559 GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge; 2565 GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge;
2560 if (!includeLogicalLeftEdge) { 2566 if (!includeLogicalLeftEdge) {
2561 if (isHorizontal) 2567 if (isHorizontal)
2562 clippedEdges |= GraphicsContext::LeftEdge; 2568 clippedEdges |= GraphicsContext::LeftEdge;
2563 else 2569 else
2564 clippedEdges |= GraphicsContext::TopEdge; 2570 clippedEdges |= GraphicsContext::TopEdge;
2565 } 2571 }
2566 if (!includeLogicalRightEdge) { 2572 if (!includeLogicalRightEdge) {
2567 if (isHorizontal) 2573 if (isHorizontal)
2568 clippedEdges |= GraphicsContext::RightEdge; 2574 clippedEdges |= GraphicsContext::RightEdge;
2569 else 2575 else
2570 clippedEdges |= GraphicsContext::BottomEdge; 2576 clippedEdges |= GraphicsContext::BottomEdge;
2571 } 2577 }
2572 context->drawInnerShadow(border, shadowColor, shadowOffset, shadowBl ur, shadowSpread, clippedEdges); 2578 // TODO: support non-integer shadows
leviw_travelin_and_unemployed 2014/01/14 22:28:35 Can we get a bug?
cbiesinger 2014/01/15 21:27:40 Done.
2579 context->drawInnerShadow(border, shadowColor, flooredIntSize(shadowO ffset), shadowBlur, shadowSpread, clippedEdges);
2573 } 2580 }
2574 } 2581 }
2575 } 2582 }
2576 2583
2577 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const 2584 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
2578 { 2585 {
2579 return containingBlock()->availableLogicalWidth(); 2586 return containingBlock()->availableLogicalWidth();
2580 } 2587 }
2581 2588
2582 RenderBoxModelObject* RenderBoxModelObject::continuation() const 2589 RenderBoxModelObject* RenderBoxModelObject::continuation() const
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
2810 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); 2817 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
2811 for (RenderObject* child = startChild; child && child != endChild; ) { 2818 for (RenderObject* child = startChild; child && child != endChild; ) {
2812 // Save our next sibling as moveChildTo will clear it. 2819 // Save our next sibling as moveChildTo will clear it.
2813 RenderObject* nextSibling = child->nextSibling(); 2820 RenderObject* nextSibling = child->nextSibling();
2814 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); 2821 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
2815 child = nextSibling; 2822 child = nextSibling;
2816 } 2823 }
2817 } 2824 }
2818 2825
2819 } // namespace WebCore 2826 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698