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

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: all working! Created 7 years, 1 month 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 2464 matching lines...) Expand 10 before | Expand all | Expand 10 after
2475 bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundCol or).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255; 2475 bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundCol or).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
2476 2476
2477 GraphicsContextStateSaver stateSaver(*context, false); 2477 GraphicsContextStateSaver stateSaver(*context, false);
2478 2478
2479 const ShadowList* shadowList = s->boxShadow(); 2479 const ShadowList* shadowList = s->boxShadow();
2480 for (size_t i = shadowList->shadows().size(); i--; ) { 2480 for (size_t i = shadowList->shadows().size(); i--; ) {
2481 const ShadowData& shadow = shadowList->shadows()[i]; 2481 const ShadowData& shadow = shadowList->shadows()[i];
2482 if (shadow.style() != shadowStyle) 2482 if (shadow.style() != shadowStyle)
2483 continue; 2483 continue;
2484 2484
2485 IntSize shadowOffset(shadow.x(), shadow.y()); 2485 LayoutSize shadowOffset(shadow.x(), shadow.y());
2486 int shadowBlur = shadow.blur(); 2486 LayoutUnit shadowBlur = shadow.blur();
2487 int shadowSpread = shadow.spread(); 2487 LayoutUnit shadowSpread = shadow.spread();
2488 2488
2489 if (shadowOffset.isZero() && !shadowBlur && !shadowSpread) 2489 if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
2490 continue; 2490 continue;
2491 2491
2492 const Color& shadowColor = resolveColor(shadow.color()); 2492 const Color& shadowColor = resolveColor(shadow.color());
2493 2493
2494 if (shadow.style() == Normal) { 2494 if (shadow.style() == Normal) {
2495 RoundedRect fillRect = border; 2495 FloatRect fillRect = border.rect();
2496 fillRect.inflate(shadowSpread); 2496 fillRect.inflate(shadowSpread);
2497 if (fillRect.isEmpty()) 2497 if (fillRect.isEmpty())
2498 continue; 2498 continue;
2499 2499
2500 IntRect shadowRect(border.rect()); 2500 LayoutRect shadowRect(border.rect());
2501 shadowRect.inflate(shadowBlur + shadowSpread); 2501 shadowRect.inflate(shadowBlur + shadowSpread);
2502 shadowRect.move(shadowOffset); 2502 shadowRect.move(shadowOffset);
2503 2503
2504 // Save the state and clip, if not already done. 2504 // Save the state and clip, if not already done.
2505 // The clip does not depend on any shadow-specific properties. 2505 // The clip does not depend on any shadow-specific properties.
2506 if (!stateSaver.saved()) { 2506 if (!stateSaver.saved()) {
2507 stateSaver.save(); 2507 stateSaver.save();
2508 if (hasBorderRadius) { 2508 if (hasBorderRadius) {
2509 RoundedRect rectToClipOut = border; 2509 RoundedRect rectToClipOut = border;
2510 2510
2511 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time 2511 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time
2512 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the 2512 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the
2513 // corners. Those are avoided by insetting the clipping path by one pixel. 2513 // corners. Those are avoided by insetting the clipping path by one pixel.
2514 if (hasOpaqueBackground) 2514 if (hasOpaqueBackground)
2515 rectToClipOut.inflateWithRadii(-1); 2515 rectToClipOut.inflateWithRadii(-1);
2516 2516
2517 if (!rectToClipOut.isEmpty()) { 2517 if (!rectToClipOut.isEmpty()) {
2518 context->clipOutRoundedRect(rectToClipOut); 2518 context->clipOutRoundedRect(rectToClipOut);
2519 } 2519 }
2520 } else { 2520 } else {
2521 // This IntRect is correct even with fractional shadows, bec ause it is used for the rectangle
2522 // of the box itself, which is always pixel-aligned.
2521 IntRect rectToClipOut = border.rect(); 2523 IntRect rectToClipOut = border.rect();
2522 2524
2523 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time 2525 // If the box is opaque, it is unnecessary to clip it out. H owever, doing so saves time
2524 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the 2526 // when painting the shadow. On the other hand, it introduce s subpixel gaps along the
2525 // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path 2527 // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path
2526 // by one pixel. 2528 // by one pixel.
2527 if (hasOpaqueBackground) { 2529 if (hasOpaqueBackground) {
2528 // FIXME: The function to decide on the policy based on the transform should be a named function. 2530 // FIXME: The function to decide on the policy based on the transform should be a named function.
2529 // FIXME: It's not clear if this check is right. What ab out integral scale factors? 2531 // FIXME: It's not clear if this check is right. What ab out integral scale factors?
2530 AffineTransform transform = context->getCTM(); 2532 AffineTransform transform = context->getCTM();
2531 if (transform.a() != 1 || (transform.d() != 1 && transfo rm.d() != -1) || transform.b() || transform.c()) 2533 if (transform.a() != 1 || (transform.d() != 1 && transfo rm.d() != -1) || transform.b() || transform.c())
2532 rectToClipOut.inflate(-1); 2534 rectToClipOut.inflate(-1);
2533 } 2535 }
2534 2536
2535 if (!rectToClipOut.isEmpty()) { 2537 if (!rectToClipOut.isEmpty()) {
2536 context->clipOut(rectToClipOut); 2538 context->clipOut(rectToClipOut);
2537 } 2539 }
2538 } 2540 }
2539 } 2541 }
2540 2542
2541 // Draw only the shadow. 2543 // Draw only the shadow.
2542 DrawLooper drawLooper; 2544 DrawLooper drawLooper;
2543 drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor, 2545 drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor,
2544 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresA lpha); 2546 DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresA lpha);
2545 context->setDrawLooper(drawLooper); 2547 context->setDrawLooper(drawLooper);
2546 2548
2547 if (hasBorderRadius) { 2549 if (hasBorderRadius) {
2548 RoundedRect influenceRect(shadowRect, border.radii()); 2550 // XXX is this IntRect conversion correct?
eae 2013/11/27 23:45:27 Why not use pixelSnappedIntRect instead?
cbiesinger 2013/12/18 02:09:12 Good idea, thanks.
2551 RoundedRect influenceRect(IntRect(shadowRect.pixelSnappedLocatio n(), shadowRect.pixelSnappedSize()), border.radii());
2549 influenceRect.expandRadii(2 * shadowBlur + shadowSpread); 2552 influenceRect.expandRadii(2 * shadowBlur + shadowSpread);
2550 if (allCornersClippedOut(influenceRect, info.rect)) 2553 if (allCornersClippedOut(influenceRect, info.rect))
2551 context->fillRect(fillRect.rect(), Color::black); 2554 context->fillRect(fillRect, Color::black);
2552 else { 2555 else {
2553 fillRect.expandRadii(shadowSpread); 2556 RoundedRect roundedFillRect = border;
2554 if (!fillRect.isRenderable()) 2557 roundedFillRect.inflate(shadowSpread);
2555 fillRect.adjustRadii(); 2558
2556 context->fillRoundedRect(fillRect, Color::black); 2559 roundedFillRect.expandRadii(shadowSpread);
2560 if (!roundedFillRect.isRenderable())
2561 roundedFillRect.adjustRadii();
2562 context->fillRoundedRect(roundedFillRect, Color::black);
2557 } 2563 }
2558 } else { 2564 } else {
2559 context->fillRect(fillRect.rect(), Color::black); 2565 context->fillRect(fillRect, Color::black);
2560 } 2566 }
2561 } else { 2567 } else {
2568 // inset shadow
eae 2013/11/27 23:45:27 Update comment to be more descriptive or remove it
cbiesinger 2013/12/18 02:09:12 Done.
2562 GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge; 2569 GraphicsContext::Edges clippedEdges = GraphicsContext::NoEdge;
2563 if (!includeLogicalLeftEdge) { 2570 if (!includeLogicalLeftEdge) {
2564 if (isHorizontal) 2571 if (isHorizontal)
2565 clippedEdges |= GraphicsContext::LeftEdge; 2572 clippedEdges |= GraphicsContext::LeftEdge;
2566 else 2573 else
2567 clippedEdges |= GraphicsContext::TopEdge; 2574 clippedEdges |= GraphicsContext::TopEdge;
2568 } 2575 }
2569 if (!includeLogicalRightEdge) { 2576 if (!includeLogicalRightEdge) {
2570 if (isHorizontal) 2577 if (isHorizontal)
2571 clippedEdges |= GraphicsContext::RightEdge; 2578 clippedEdges |= GraphicsContext::RightEdge;
2572 else 2579 else
2573 clippedEdges |= GraphicsContext::BottomEdge; 2580 clippedEdges |= GraphicsContext::BottomEdge;
2574 } 2581 }
2575 context->drawInnerShadow(border, shadowColor, shadowOffset, shadowBl ur, shadowSpread, clippedEdges); 2582 // TODO: support non-integer shadows
2583 context->drawInnerShadow(border, shadowColor, IntSize(shadowOffset.w idth(), shadowOffset.height()), shadowBlur, shadowSpread, clippedEdges);
eae 2013/11/27 23:45:27 do you want to floor or round the offset here? Use
cbiesinger 2013/12/18 02:09:12 Ah, thanks - done. Switched to floored because tha
2576 } 2584 }
2577 } 2585 }
2578 } 2586 }
2579 2587
2580 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const 2588 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
2581 { 2589 {
2582 return containingBlock()->availableLogicalWidth(); 2590 return containingBlock()->availableLogicalWidth();
2583 } 2591 }
2584 2592
2585 RenderBoxModelObject* RenderBoxModelObject::continuation() const 2593 RenderBoxModelObject* RenderBoxModelObject::continuation() const
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
2813 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent()); 2821 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
2814 for (RenderObject* child = startChild; child && child != endChild; ) { 2822 for (RenderObject* child = startChild; child && child != endChild; ) {
2815 // Save our next sibling as moveChildTo will clear it. 2823 // Save our next sibling as moveChildTo will clear it.
2816 RenderObject* nextSibling = child->nextSibling(); 2824 RenderObject* nextSibling = child->nextSibling();
2817 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert); 2825 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
2818 child = nextSibling; 2826 child = nextSibling;
2819 } 2827 }
2820 } 2828 }
2821 2829
2822 } // namespace WebCore 2830 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698