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

Side by Side Diff: Source/core/paint/BoxBorderPainter.cpp

Issue 1154213013: Stateful BoxBorderPainter (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: minor optimization Created 5 years, 6 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
« no previous file with comments | « Source/core/paint/BoxBorderPainter.h ('k') | Source/core/paint/BoxPainter.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "core/paint/BoxBorderPainter.h" 6 #include "core/paint/BoxBorderPainter.h"
7 7
8 #include "core/paint/BoxPainter.h" 8 #include "core/paint/BoxPainter.h"
9 #include "core/paint/PaintInfo.h" 9 #include "core/paint/PaintInfo.h"
10 #include "core/style/BorderEdge.h" 10 #include "core/style/BorderEdge.h"
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 if (maxRadii > newRect.width()) { 277 if (maxRadii > newRect.width()) {
278 newRect.move(newRect.width() - maxRadii, 0); 278 newRect.move(newRect.width() - maxRadii, 0);
279 newRect.setWidth(maxRadii); 279 newRect.setWidth(maxRadii);
280 } 280 }
281 break; 281 break;
282 } 282 }
283 283
284 return FloatRoundedRect(newRect, newRadii); 284 return FloatRoundedRect(newRect, newRadii);
285 } 285 }
286 286
287 struct BoxBorderInfo {
288 STACK_ALLOCATED();
289 public:
290 BoxBorderInfo(const ComputedStyle& style, BackgroundBleedAvoidance bleedAvoi dance,
291 bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
292 : style(style)
293 , bleedAvoidance(bleedAvoidance)
294 , includeLogicalLeftEdge(includeLogicalLeftEdge)
295 , includeLogicalRightEdge(includeLogicalRightEdge)
296 , visibleEdgeCount(0)
297 , firstVisibleEdge(0)
298 , visibleEdgeSet(0)
299 , isUniformStyle(true)
300 , isUniformWidth(true)
301 , isUniformColor(true)
302 , hasAlpha(false)
303 {
304
305 style.getBorderEdgeInfo(edges, includeLogicalLeftEdge, includeLogicalRig htEdge);
306
307 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(edges); ++i) {
308 const BorderEdge& edge = edges[i];
309
310 if (!edge.shouldRender()) {
311 if (edge.presentButInvisible()) {
312 isUniformWidth = false;
313 isUniformColor = false;
314 }
315
316 continue;
317 }
318
319 visibleEdgeCount++;
320 visibleEdgeSet |= edgeFlagForSide(static_cast<BoxSide>(i));
321
322 hasAlpha = hasAlpha || edge.color.hasAlpha();
323
324 if (visibleEdgeCount == 1) {
325 firstVisibleEdge = i;
326 continue;
327 }
328
329 isUniformStyle = isUniformStyle && (edge.borderStyle() == edges[firs tVisibleEdge].borderStyle());
330 isUniformWidth = isUniformWidth && (edge.width == edges[firstVisible Edge].width);
331 isUniformColor = isUniformColor && (edge.color == edges[firstVisible Edge].color);
332 }
333 }
334
335 const ComputedStyle& style;
336 const BackgroundBleedAvoidance bleedAvoidance;
337 const bool includeLogicalLeftEdge;
338 const bool includeLogicalRightEdge;
339
340 BorderEdge edges[4];
341
342 unsigned visibleEdgeCount;
343 unsigned firstVisibleEdge;
344 BorderEdgeFlags visibleEdgeSet;
345
346 bool isUniformStyle;
347 bool isUniformWidth;
348 bool isUniformColor;
349 bool hasAlpha;
350 };
351
352 LayoutRectOutsets doubleStripeInsets(const BorderEdge edges[], BorderEdge::Doubl eBorderStripe stripe) 287 LayoutRectOutsets doubleStripeInsets(const BorderEdge edges[], BorderEdge::Doubl eBorderStripe stripe)
353 { 288 {
354 // Insets are representes as negative outsets. 289 // Insets are representes as negative outsets.
355 return LayoutRectOutsets( 290 return LayoutRectOutsets(
356 -edges[BSTop].getDoubleBorderStripeWidth(stripe), 291 -edges[BSTop].getDoubleBorderStripeWidth(stripe),
357 -edges[BSRight].getDoubleBorderStripeWidth(stripe), 292 -edges[BSRight].getDoubleBorderStripeWidth(stripe),
358 -edges[BSBottom].getDoubleBorderStripeWidth(stripe), 293 -edges[BSBottom].getDoubleBorderStripeWidth(stripe),
359 -edges[BSLeft].getDoubleBorderStripeWidth(stripe)); 294 -edges[BSLeft].getDoubleBorderStripeWidth(stripe));
360 } 295 }
361 296
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 context->fillDRRect(adjustedOuter, inner, color); 348 context->fillDRRect(adjustedOuter, inner, color);
414 break; 349 break;
415 } 350 }
416 // fall through 351 // fall through
417 default: 352 default:
418 context->fillDRRect(outer, inner, color); 353 context->fillDRRect(outer, inner, color);
419 break; 354 break;
420 } 355 }
421 } 356 }
422 357
423 void drawDoubleBorder(GraphicsContext* context, const BoxBorderInfo& borderInfo, const LayoutRect& borderRect, 358 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance)
424 const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder)
425 { 359 {
426 ASSERT(borderInfo.isUniformColor); 360 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr oundBleedClipLayer;
427 ASSERT(borderInfo.isUniformStyle); 361 }
428 ASSERT(borderInfo.edges[borderInfo.firstVisibleEdge].borderStyle() == DOUBLE );
429 ASSERT(borderInfo.visibleEdgeSet == AllBorderEdges);
430 362
431 const Color color = borderInfo.edges[borderInfo.firstVisibleEdge].color; 363 } // anonymous namespace
364
365 void BoxBorderPainter::drawDoubleBorder(GraphicsContext* context, const LayoutRe ct& borderRect) const
366 {
367 ASSERT(m_isUniformColor);
368 ASSERT(m_isUniformStyle);
369 ASSERT(firstEdge().borderStyle() == DOUBLE);
370 ASSERT(m_visibleEdgeSet == AllBorderEdges);
371
372 const Color color = firstEdge().color;
432 373
433 // outer stripe 374 // outer stripe
434 const LayoutRectOutsets outerThirdInsets = 375 const LayoutRectOutsets outerThirdInsets =
435 doubleStripeInsets(borderInfo.edges, BorderEdge::DoubleBorderStripeOuter ); 376 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeOuter);
436 const FloatRoundedRect outerThirdRect = borderInfo.style.getRoundedInnerBord erFor(borderRect, 377 const FloatRoundedRect outerThirdRect = m_style.getRoundedInnerBorderFor(bor derRect,
437 outerThirdInsets, borderInfo.includeLogicalLeftEdge, borderInfo.includeL ogicalRightEdge); 378 outerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
438 drawBleedAdjustedDRRect(context, borderInfo.bleedAvoidance, outerBorder, out erThirdRect, color); 379 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, outerThirdRect, color);
439 380
440 // inner stripe 381 // inner stripe
441 const LayoutRectOutsets innerThirdInsets = 382 const LayoutRectOutsets innerThirdInsets =
442 doubleStripeInsets(borderInfo.edges, BorderEdge::DoubleBorderStripeInner ); 383 doubleStripeInsets(m_edges, BorderEdge::DoubleBorderStripeInner);
443 const FloatRoundedRect innerThirdRect = borderInfo.style.getRoundedInnerBord erFor(borderRect, 384 const FloatRoundedRect innerThirdRect = m_style.getRoundedInnerBorderFor(bor derRect,
444 innerThirdInsets, borderInfo.includeLogicalLeftEdge, borderInfo.includeL ogicalRightEdge); 385 innerThirdInsets, m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
445 context->fillDRRect(innerThirdRect, innerBorder, color); 386 context->fillDRRect(innerThirdRect, m_inner, color);
446 } 387 }
447 388
448 bool paintBorderFastPath(GraphicsContext* context, const BoxBorderInfo& info, 389 bool BoxBorderPainter::paintBorderFastPath(GraphicsContext* context, const Layou tRect& borderRect) const
449 const LayoutRect& borderRect, const FloatRoundedRect& outer, const FloatRoun dedRect& inner)
450 { 390 {
451 if (!info.isUniformColor || !info.isUniformStyle || !inner.isRenderable()) 391 if (!m_isUniformColor || !m_isUniformStyle || !m_inner.isRenderable())
452 return false; 392 return false;
453 393
454 const BorderEdge& firstEdge = info.edges[info.firstVisibleEdge]; 394 if (firstEdge().borderStyle() != SOLID && firstEdge().borderStyle() != DOUBL E)
455 if (firstEdge.borderStyle() != SOLID && firstEdge.borderStyle() != DOUBLE)
456 return false; 395 return false;
457 396
458 if (info.visibleEdgeSet == AllBorderEdges) { 397 if (m_visibleEdgeSet == AllBorderEdges) {
459 if (firstEdge.borderStyle() == SOLID) { 398 if (firstEdge().borderStyle() == SOLID) {
460 if (info.isUniformWidth && !outer.isRounded()) { 399 if (m_isUniformWidth && !m_outer.isRounded()) {
461 // 4-side, solid, uniform-width, rectangular border => one drawR ect() 400 // 4-side, solid, uniform-width, rectangular border => one drawR ect()
462 drawSolidBorderRect(context, outer.rect(), firstEdge.width, firs tEdge.color); 401 drawSolidBorderRect(context, m_outer.rect(), firstEdge().width, firstEdge().color);
463 } else { 402 } else {
464 // 4-side, solid border => one drawDRRect() 403 // 4-side, solid border => one drawDRRect()
465 drawBleedAdjustedDRRect(context, info.bleedAvoidance, outer, inn er, firstEdge.color); 404 drawBleedAdjustedDRRect(context, m_bleedAvoidance, m_outer, m_in ner, firstEdge().color);
466 } 405 }
467 } else { 406 } else {
468 // 4-side, double border => 2x drawDRRect() 407 // 4-side, double border => 2x drawDRRect()
469 ASSERT(firstEdge.borderStyle() == DOUBLE); 408 ASSERT(firstEdge().borderStyle() == DOUBLE);
470 drawDoubleBorder(context, info, borderRect, outer, inner); 409 drawDoubleBorder(context, borderRect);
471 } 410 }
472 411
473 return true; 412 return true;
474 } 413 }
475 414
476 // This is faster than the normal complex border path only if it avoids crea ting transparency 415 // This is faster than the normal complex border path only if it avoids crea ting transparency
477 // layers (when the border is translucent). 416 // layers (when the border is translucent).
478 if (firstEdge.borderStyle() == SOLID && !outer.isRounded() && info.hasAlpha) { 417 if (firstEdge().borderStyle() == SOLID && !m_outer.isRounded() && m_hasAlpha ) {
479 ASSERT(info.visibleEdgeSet != AllBorderEdges); 418 ASSERT(m_visibleEdgeSet != AllBorderEdges);
480 // solid, rectangular border => one drawPath() 419 // solid, rectangular border => one drawPath()
481 Path path; 420 Path path;
482 421
483 for (int i = BSTop; i <= BSLeft; ++i) { 422 for (int i = BSTop; i <= BSLeft; ++i) {
484 const BorderEdge& currEdge = info.edges[i]; 423 const BorderEdge& currEdge = m_edges[i];
485 if (currEdge.shouldRender()) 424 if (currEdge.shouldRender())
486 path.addRect(calculateSideRect(outer, currEdge, i)); 425 path.addRect(calculateSideRect(m_outer, currEdge, i));
487 } 426 }
488 427
489 context->setFillRule(RULE_NONZERO); 428 context->setFillRule(RULE_NONZERO);
490 context->setFillColor(firstEdge.color); 429 context->setFillColor(firstEdge().color);
491 context->fillPath(path); 430 context->fillPath(path);
492 431
493 return true; 432 return true;
494 } 433 }
495 434
496 return false; 435 return false;
497 } 436 }
498 437
499 bool bleedAvoidanceIsClipping(BackgroundBleedAvoidance bleedAvoidance) 438 BoxBorderPainter::BoxBorderPainter(const LayoutRect& borderRect, const ComputedS tyle& style,
439 const IntRect& clipRect, BackgroundBleedAvoidance bleedAvoidance,
440 bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
441 : m_style(style)
442 , m_bleedAvoidance(bleedAvoidance)
443 , m_includeLogicalLeftEdge(includeLogicalLeftEdge)
444 , m_includeLogicalRightEdge(includeLogicalRightEdge)
445 , m_visibleEdgeCount(0)
446 , m_firstVisibleEdge(0)
447 , m_visibleEdgeSet(0)
448 , m_isUniformStyle(true)
449 , m_isUniformWidth(true)
450 , m_isUniformColor(true)
451 , m_hasAlpha(false)
500 { 452 {
501 return bleedAvoidance == BackgroundBleedClipOnly || bleedAvoidance == Backgr oundBleedClipLayer; 453 style.getBorderEdgeInfo(m_edges, includeLogicalLeftEdge, includeLogicalRight Edge);
454
455 for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_edges); ++i) {
456 const BorderEdge& edge = m_edges[i];
457
458 if (!edge.shouldRender()) {
459 if (edge.presentButInvisible()) {
460 m_isUniformWidth = false;
461 m_isUniformColor = false;
462 }
463
464 continue;
465 }
466
467 m_visibleEdgeCount++;
468 m_visibleEdgeSet |= edgeFlagForSide(static_cast<BoxSide>(i));
469
470 m_hasAlpha |= edge.color.hasAlpha();
471
472 if (m_visibleEdgeCount == 1) {
473 m_firstVisibleEdge = i;
474 continue;
475 }
476
477 m_isUniformStyle &= edge.borderStyle() == m_edges[m_firstVisibleEdge].bo rderStyle();
478 m_isUniformWidth &= edge.width == m_edges[m_firstVisibleEdge].width;
479 m_isUniformColor &= edge.color == m_edges[m_firstVisibleEdge].color;
480 }
481
482 // No need to compute the rrects if we don't have any borders to draw.
483 if (!m_visibleEdgeSet)
484 return;
485
486 m_outer = style.getRoundedBorderFor(borderRect, includeLogicalLeftEdge, incl udeLogicalRightEdge);
487 m_inner = style.getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
488
489 // If no corner intersects the clip region, we can pretend the outer border is
490 // rectangular to improve performance.
491 // FIXME: why is this predicated on uniform style & solid edges?
492 if (m_isUniformStyle
493 && firstEdge().borderStyle() == SOLID
494 && m_outer.isRounded()
495 && BoxPainter::allCornersClippedOut(m_outer, clipRect))
496 m_outer.setRadii(FloatRoundedRect::Radii());
502 } 497 }
503 498
504 } // anonymous namespace 499 void BoxBorderPainter::paintBorder(const PaintInfo& info, const LayoutRect& rect ) const
505
506 void BoxBorderPainter::paintBorder(LayoutBoxModelObject& obj, const PaintInfo& i nfo,
507 const LayoutRect& rect, const ComputedStyle& style, BackgroundBleedAvoidance bleedAvoidance,
508 bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
509 { 500 {
510 GraphicsContext* graphicsContext = info.context; 501 if (!m_visibleEdgeCount || m_outer.rect().isEmpty())
511 // border-image is not affected by border-radius.
512 if (BoxPainter::paintNinePieceImage(obj, graphicsContext, rect, style, style .borderImage()))
513 return; 502 return;
514 503
515 const BoxBorderInfo borderInfo(style, bleedAvoidance, includeLogicalLeftEdge , includeLogicalRightEdge); 504 GraphicsContext* graphicsContext = info.context;
516 FloatRoundedRect outerBorder = style.getRoundedBorderFor(rect, includeLogica lLeftEdge, includeLogicalRightEdge);
517 FloatRoundedRect innerBorder = style.getRoundedInnerBorderFor(rect, includeL ogicalLeftEdge, includeLogicalRightEdge);
518 505
519 if (outerBorder.rect().isEmpty() || !borderInfo.visibleEdgeCount) 506 if (paintBorderFastPath(graphicsContext, rect))
520 return; 507 return;
521 508
522 const BorderEdge& firstEdge = borderInfo.edges[borderInfo.firstVisibleEdge]; 509 bool clipToOuterBorder = m_outer.isRounded();
523 bool haveAllSolidEdges = borderInfo.isUniformStyle && firstEdge.borderStyle( ) == SOLID;
524
525 // If no corner intersects the clip region, we can pretend outerBorder is
526 // rectangular to improve performance.
527 if (haveAllSolidEdges && outerBorder.isRounded() && BoxPainter::allCornersCl ippedOut(outerBorder, info.rect))
528 outerBorder.setRadii(FloatRoundedRect::Radii());
529
530 if (paintBorderFastPath(graphicsContext, borderInfo, rect, outerBorder, inne rBorder))
531 return;
532
533 bool clipToOuterBorder = outerBorder.isRounded();
534 GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder); 510 GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder);
535 if (clipToOuterBorder) { 511 if (clipToOuterBorder) {
536 // For BackgroundBleedClip{Only,Layer}, the outer rrect clip is already applied. 512 // For BackgroundBleedClip{Only,Layer}, the outer rrect clip is already applied.
537 if (!bleedAvoidanceIsClipping(bleedAvoidance)) 513 if (!bleedAvoidanceIsClipping(m_bleedAvoidance))
538 graphicsContext->clipRoundedRect(outerBorder); 514 graphicsContext->clipRoundedRect(m_outer);
539 515
540 // For BackgroundBleedBackgroundOverBorder, we're going to draw an opaqu e background over 516 // For BackgroundBleedBackgroundOverBorder, we're going to draw an opaqu e background over
541 // the inner rrect - so clipping is not needed (nor desirable due to bac kdrop bleeding). 517 // the inner rrect - so clipping is not needed (nor desirable due to bac kdrop bleeding).
542 if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && innerBorder .isRenderable() && !innerBorder.isEmpty()) 518 if (m_bleedAvoidance != BackgroundBleedBackgroundOverBorder && m_inner.i sRenderable() && !m_inner.isEmpty())
543 graphicsContext->clipOutRoundedRect(innerBorder); 519 graphicsContext->clipOutRoundedRect(m_inner);
544 } 520 }
545 521
546 // If only one edge visible antialiasing doesn't create seams 522 // If only one edge visible antialiasing doesn't create seams
547 bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext) || border Info.visibleEdgeCount == 1; 523 bool antialias = BoxPainter::shouldAntialiasLines(graphicsContext) || m_visi bleEdgeCount == 1;
548 if (borderInfo.hasAlpha) { 524 if (m_hasAlpha) {
549 paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBo rder, borderInfo.edges, 525 paintTranslucentBorderSides(graphicsContext, antialias);
550 borderInfo.visibleEdgeSet, bleedAvoidance, includeLogicalLeftEdge, inclu deLogicalRightEdge, antialias);
551 } else { 526 } else {
552 paintBorderSides(graphicsContext, style, outerBorder, innerBorder, borde rInfo.edges, 527 paintBorderSides(graphicsContext, m_visibleEdgeSet, antialias);
553 borderInfo.visibleEdgeSet, bleedAvoidance, includeLogicalLeftEdge, inclu deLogicalRightEdge, antialias);
554 } 528 }
555 } 529 }
556 530
557 void BoxBorderPainter::paintTranslucentBorderSides(GraphicsContext* graphicsCont ext, 531 void BoxBorderPainter::paintTranslucentBorderSides(GraphicsContext* graphicsCont ext,
558 const ComputedStyle& style, const FloatRoundedRect& outerBorder, const Float RoundedRect& innerBorder, 532 bool antialias) const
559 const BorderEdge edges[], BorderEdgeFlags edgesToDraw, BackgroundBleedAvoida nce bleedAvoidance,
560 bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
561 { 533 {
562 // willBeOverdrawn assumes that we draw in order: top, bottom, left, right. 534 // willBeOverdrawn assumes that we draw in order: top, bottom, left, right.
563 // This is different from BoxSide enum order. 535 // This is different from BoxSide enum order.
564 static const BoxSide paintOrder[] = { BSTop, BSBottom, BSLeft, BSRight }; 536 static const BoxSide paintOrder[] = { BSTop, BSBottom, BSLeft, BSRight };
565 537
538 BorderEdgeFlags edgesToDraw = m_visibleEdgeSet;
566 while (edgesToDraw) { 539 while (edgesToDraw) {
567 // Find undrawn edges sharing a color. 540 // Find undrawn edges sharing a color.
568 Color commonColor; 541 Color commonColor;
569 542
570 BorderEdgeFlags commonColorEdgeSet = 0; 543 BorderEdgeFlags commonColorEdgeSet = 0;
571 for (size_t i = 0; i < sizeof(paintOrder) / sizeof(paintOrder[0]); ++i) { 544 for (size_t i = 0; i < sizeof(paintOrder) / sizeof(paintOrder[0]); ++i) {
572 BoxSide currSide = paintOrder[i]; 545 BoxSide currSide = paintOrder[i];
573 if (!includesEdge(edgesToDraw, currSide)) 546 if (!includesEdge(edgesToDraw, currSide))
574 continue; 547 continue;
575 548
576 bool includeEdge; 549 bool includeEdge;
577 if (!commonColorEdgeSet) { 550 if (!commonColorEdgeSet) {
578 commonColor = edges[currSide].color; 551 commonColor = m_edges[currSide].color;
579 includeEdge = true; 552 includeEdge = true;
580 } else { 553 } else {
581 includeEdge = edges[currSide].color == commonColor; 554 includeEdge = m_edges[currSide].color == commonColor;
582 } 555 }
583 556
584 if (includeEdge) 557 if (includeEdge)
585 commonColorEdgeSet |= edgeFlagForSide(currSide); 558 commonColorEdgeSet |= edgeFlagForSide(currSide);
586 } 559 }
587 560
588 bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && commonColor.hasAlpha(); 561 bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && commonColor.hasAlpha();
589 if (useTransparencyLayer) { 562 if (useTransparencyLayer) {
590 graphicsContext->beginLayer(static_cast<float>(commonColor.alpha()) / 255); 563 graphicsContext->beginLayer(static_cast<float>(commonColor.alpha()) / 255);
591 commonColor = Color(commonColor.red(), commonColor.green(), commonCo lor.blue()); 564 commonColor = Color(commonColor.red(), commonColor.green(), commonCo lor.blue());
592 } 565 }
593 566
594 paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges , commonColorEdgeSet, 567 paintBorderSides(graphicsContext, commonColorEdgeSet, antialias, &common Color);
595 bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, ant ialias, &commonColor);
596 568
597 if (useTransparencyLayer) 569 if (useTransparencyLayer)
598 graphicsContext->endLayer(); 570 graphicsContext->endLayer();
599 571
600 edgesToDraw &= ~commonColorEdgeSet; 572 edgesToDraw &= ~commonColorEdgeSet;
601 } 573 }
602 } 574 }
603 575
604 void BoxBorderPainter::paintOneBorderSide(GraphicsContext* graphicsContext, cons t ComputedStyle& style, 576 void BoxBorderPainter::paintOneBorderSide(GraphicsContext* graphicsContext,
605 const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, co nst FloatRect& sideRect, 577 const FloatRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adja centSide2,
606 BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path, 578 const Path* path, bool antialias, const Color* overrideColor) const
607 BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool i ncludeLogicalRightEdge,
608 bool antialias, const Color* overrideColor)
609 { 579 {
610 const BorderEdge& edgeToRender = edges[side]; 580 const BorderEdge& edgeToRender = m_edges[side];
611 ASSERT(edgeToRender.width); 581 ASSERT(edgeToRender.width);
612 const BorderEdge& adjacentEdge1 = edges[adjacentSide1]; 582 const BorderEdge& adjacentEdge1 = m_edges[adjacentSide1];
613 const BorderEdge& adjacentEdge2 = edges[adjacentSide2]; 583 const BorderEdge& adjacentEdge2 = m_edges[adjacentSide2];
614
615 bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, edges, !ant ialias);
616 bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, edges, !ant ialias);
617
618 bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1, edg es);
619 bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2, edg es);
620 584
621 const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.co lor; 585 const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.co lor;
622 586
623 if (path) { 587 if (path) {
588 bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1, m_edges);
589 bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2, m_edges);
590
624 GraphicsContextStateSaver stateSaver(*graphicsContext); 591 GraphicsContextStateSaver stateSaver(*graphicsContext);
625 if (innerBorder.isRenderable()) 592 if (m_inner.isRenderable())
626 clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, sid e, adjacentSide1StylesMatch, adjacentSide2StylesMatch); 593 clipBorderSidePolygon(graphicsContext, side, adjacentSide1StylesMatc h, adjacentSide2StylesMatch);
627 else 594 else
628 clipBorderSideForComplexInnerPath(graphicsContext, outerBorder, inne rBorder, side, edges); 595 clipBorderSideForComplexInnerPath(graphicsContext, side);
629 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi dth), adjacentEdge2.width); 596 float thickness = std::max(std::max(edgeToRender.width, adjacentEdge1.wi dth), adjacentEdge2.width);
630 drawBoxSideFromPath(graphicsContext, LayoutRect(outerBorder.rect()), *pa th, edges, edgeToRender.width, thickness, side, style, 597 drawBoxSideFromPath(graphicsContext, LayoutRect(m_outer.rect()), *path, edgeToRender.width,
631 colorToPaint, edgeToRender.borderStyle(), bleedAvoidance, includeLog icalLeftEdge, includeLogicalRightEdge); 598 thickness, side, colorToPaint, edgeToRender.borderStyle());
632 } else { 599 } else {
633 bool clipForStyle = styleRequiresClipPolygon(edgeToRender.borderStyle()) && (mitreAdjacentSide1 || mitreAdjacentSide2); 600 bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, m_edges , !antialias);
634 bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSide1 , edges) && mitreAdjacentSide1; 601 bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, m_edges , !antialias);
635 bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSide2 , edges) && mitreAdjacentSide2; 602
603 bool clipForStyle = styleRequiresClipPolygon(edgeToRender.borderStyle())
604 && (mitreAdjacentSide1 || mitreAdjacentSide2);
605 bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSide1 , m_edges) && mitreAdjacentSide1;
606 bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSide2 , m_edges) && mitreAdjacentSide2;
636 bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2 ; 607 bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2 ;
637 608
638 GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip); 609 GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip);
639 if (shouldClip) { 610 if (shouldClip) {
640 bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitr eAdjacentSide1); 611 bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitr eAdjacentSide1);
641 bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitr eAdjacentSide2); 612 bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitr eAdjacentSide2);
642 clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, sid e, !aliasAdjacentSide1, !aliasAdjacentSide2); 613 clipBorderSidePolygon(graphicsContext, side, !aliasAdjacentSide1, !a liasAdjacentSide2);
643 // Since we clipped, no need to draw with a mitre. 614 // Since we clipped, no need to draw with a mitre.
644 mitreAdjacentSide1 = false; 615 mitreAdjacentSide1 = false;
645 mitreAdjacentSide2 = false; 616 mitreAdjacentSide2 = false;
646 } 617 }
647 618
648 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec t.y(), sideRect.maxX(), sideRect.maxY(), side, colorToPaint, edgeToRender.border Style(), 619 ObjectPainter::drawLineForBoxSide(graphicsContext, sideRect.x(), sideRec t.y(),
620 sideRect.maxX(), sideRect.maxY(), side, colorToPaint, edgeToRender.b orderStyle(),
649 mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? a djacentEdge2.width : 0, antialias); 621 mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? a djacentEdge2.width : 0, antialias);
650 } 622 }
651 } 623 }
652 624
653 void BoxBorderPainter::paintBorderSides(GraphicsContext* graphicsContext, const ComputedStyle& style, 625 void BoxBorderPainter::paintBorderSides(GraphicsContext* graphicsContext, Border EdgeFlags edgeSet,
654 const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, co nst BorderEdge edges[], 626 bool antialias, const Color* overrideColor) const
655 BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance, bool inclu deLogicalLeftEdge,
656 bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
657 { 627 {
658 bool renderRadii = outerBorder.isRounded(); 628 bool renderRadii = m_outer.isRounded();
659 629
660 Path roundedPath; 630 Path roundedPath;
661 if (renderRadii) 631 if (renderRadii)
662 roundedPath.addRoundedRect(outerBorder); 632 roundedPath.addRoundedRect(m_outer);
663 633
664 // The inner border adjustment for bleed avoidance mode BackgroundBleedBackg roundOverBorder 634 // The inner border adjustment for bleed avoidance mode BackgroundBleedBackg roundOverBorder
665 // is only applied to sideRect, which is okay since BackgroundBleedBackgroun dOverBorder 635 // is only applied to sideRect, which is okay since BackgroundBleedBackgroun dOverBorder
666 // is only to be used for solid borders and the shape of the border painted by drawBoxSideFromPath 636 // is only to be used for solid borders and the shape of the border painted by drawBoxSideFromPath
667 // only depends on sideRect when painting solid borders. 637 // only depends on sideRect when painting solid borders.
668 638
669 if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) { 639 if (includesEdge(edgeSet, BSTop)) {
670 FloatRect sideRect = outerBorder.rect(); 640 const BorderEdge& edge = m_edges[BSTop];
671 sideRect.setHeight(edges[BSTop].width); 641 ASSERT(edge.shouldRender());
672 642
673 bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].bo rderStyle()) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorde r.radii().topRight())); 643 FloatRect sideRect = m_outer.rect();
674 paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sid eRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance , includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 644 sideRect.setHeight(edge.width);
645
646 bool usePath = renderRadii && (borderStyleHasInnerDetail(edge.borderStyl e())
647 || borderWillArcInnerEdge(m_inner.radii().topLeft(), m_inner.radii() .topRight()));
648 paintOneBorderSide(graphicsContext, sideRect, BSTop, BSLeft, BSRight,
649 usePath ? &roundedPath : 0, antialias, overrideColor);
675 } 650 }
676 651
677 if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) { 652 if (includesEdge(edgeSet, BSBottom)) {
678 FloatRect sideRect = outerBorder.rect(); 653 const BorderEdge& edge = m_edges[BSBottom];
679 sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width); 654 ASSERT(edge.shouldRender());
680 655
681 bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom] .borderStyle()) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), inne rBorder.radii().bottomRight())); 656 FloatRect sideRect = m_outer.rect();
682 paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sid eRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoida nce, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 657 sideRect.shiftYEdgeTo(sideRect.maxY() - edge.width);
658
659 bool usePath = renderRadii && (borderStyleHasInnerDetail(edge.borderStyl e())
660 || borderWillArcInnerEdge(m_inner.radii().bottomLeft(), m_inner.radi i().bottomRight()));
661 paintOneBorderSide(graphicsContext, sideRect, BSBottom, BSLeft, BSRight,
662 usePath ? &roundedPath : 0, antialias, overrideColor);
683 } 663 }
684 664
685 if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) { 665 if (includesEdge(edgeSet, BSLeft)) {
686 FloatRect sideRect = outerBorder.rect(); 666 const BorderEdge& edge = m_edges[BSLeft];
687 sideRect.setWidth(edges[BSLeft].width); 667 ASSERT(edge.shouldRender());
688 668
689 bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].b orderStyle()) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerB order.radii().topLeft())); 669 FloatRect sideRect = m_outer.rect();
690 paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sid eRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidanc e, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 670 sideRect.setWidth(edge.width);
671
672 bool usePath = renderRadii && (borderStyleHasInnerDetail(edge.borderStyl e())
673 || borderWillArcInnerEdge(m_inner.radii().bottomLeft(), m_inner.radi i().topLeft()));
674 paintOneBorderSide(graphicsContext, sideRect, BSLeft, BSTop, BSBottom,
675 usePath ? &roundedPath : 0, antialias, overrideColor);
691 } 676 }
692 677
693 if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) { 678 if (includesEdge(edgeSet, BSRight)) {
694 FloatRect sideRect = outerBorder.rect(); 679 const BorderEdge& edge = m_edges[BSRight];
695 sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width); 680 ASSERT(edge.shouldRender());
696 681
697 bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight]. borderStyle()) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), inne rBorder.radii().topRight())); 682 FloatRect sideRect = m_outer.rect();
698 paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sid eRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidan ce, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor); 683 sideRect.shiftXEdgeTo(sideRect.maxX() - edge.width);
684
685 bool usePath = renderRadii && (borderStyleHasInnerDetail(edge.borderStyl e())
686 || borderWillArcInnerEdge(m_inner.radii().bottomRight(), m_inner.rad ii().topRight()));
687 paintOneBorderSide(graphicsContext, sideRect, BSRight, BSTop, BSBottom,
688 usePath ? &roundedPath : 0, antialias, overrideColor);
699 } 689 }
700 } 690 }
701 691
702 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext* graphicsContext, 692 void BoxBorderPainter::drawBoxSideFromPath(GraphicsContext* graphicsContext,
703 const LayoutRect& borderRect, const Path& borderPath, const BorderEdge edges [], float thickness, 693 const LayoutRect& borderRect, const Path& borderPath, float thickness, float drawThickness,
704 float drawThickness, BoxSide side, const ComputedStyle& style, Color color, EBorderStyle borderStyle, 694 BoxSide side, Color color, EBorderStyle borderStyle) const
705 BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool i ncludeLogicalRightEdge)
706 { 695 {
707 if (thickness <= 0) 696 if (thickness <= 0)
708 return; 697 return;
709 698
710 if (borderStyle == DOUBLE && thickness < 3) 699 if (borderStyle == DOUBLE && thickness < 3)
711 borderStyle = SOLID; 700 borderStyle = SOLID;
712 701
713 switch (borderStyle) { 702 switch (borderStyle) {
714 case BNONE: 703 case BNONE:
715 case BHIDDEN: 704 case BHIDDEN:
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 // FIXME: stroking the border path causes issues with tight corners: 741 // FIXME: stroking the border path causes issues with tight corners:
753 // https://bugs.webkit.org/show_bug.cgi?id=58711 742 // https://bugs.webkit.org/show_bug.cgi?id=58711
754 // Also, to get the best appearance we should stroke a path between the two borders. 743 // Also, to get the best appearance we should stroke a path between the two borders.
755 graphicsContext->strokePath(borderPath); 744 graphicsContext->strokePath(borderPath);
756 return; 745 return;
757 } 746 }
758 case DOUBLE: { 747 case DOUBLE: {
759 // Draw inner border line 748 // Draw inner border line
760 { 749 {
761 GraphicsContextStateSaver stateSaver(*graphicsContext); 750 GraphicsContextStateSaver stateSaver(*graphicsContext);
762 const LayoutRectOutsets innerInsets = doubleStripeInsets(edges, Bord erEdge::DoubleBorderStripeInner); 751 const LayoutRectOutsets innerInsets = doubleStripeInsets(m_edges, Bo rderEdge::DoubleBorderStripeInner);
763 FloatRoundedRect innerClip = style.getRoundedInnerBorderFor(borderRe ct, 752 FloatRoundedRect innerClip = m_style.getRoundedInnerBorderFor(border Rect, innerInsets,
764 innerInsets, includeLogicalLeftEdge, includeLogicalRightEdge); 753 m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
765 754
766 graphicsContext->clipRoundedRect(innerClip); 755 graphicsContext->clipRoundedRect(innerClip);
767 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogi calLeftEdge, includeLogicalRightEdge); 756 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne ss, drawThickness,
757 side, color, SOLID);
768 } 758 }
769 759
770 // Draw outer border line 760 // Draw outer border line
771 { 761 {
772 GraphicsContextStateSaver stateSaver(*graphicsContext); 762 GraphicsContextStateSaver stateSaver(*graphicsContext);
773 LayoutRect outerRect = borderRect; 763 LayoutRect outerRect = borderRect;
774 LayoutRectOutsets outerInsets = doubleStripeInsets(edges, BorderEdge ::DoubleBorderStripeOuter); 764 LayoutRectOutsets outerInsets = doubleStripeInsets(m_edges, BorderEd ge::DoubleBorderStripeOuter);
775 765
776 if (bleedAvoidanceIsClipping(bleedAvoidance)) { 766 if (bleedAvoidanceIsClipping(m_bleedAvoidance)) {
777 outerRect.inflate(1); 767 outerRect.inflate(1);
778 outerInsets.setTop(outerInsets.top() - 1); 768 outerInsets.setTop(outerInsets.top() - 1);
779 outerInsets.setRight(outerInsets.right() - 1); 769 outerInsets.setRight(outerInsets.right() - 1);
780 outerInsets.setBottom(outerInsets.bottom() - 1); 770 outerInsets.setBottom(outerInsets.bottom() - 1);
781 outerInsets.setLeft(outerInsets.left() - 1); 771 outerInsets.setLeft(outerInsets.left() - 1);
782 } 772 }
783 773
784 FloatRoundedRect outerClip = style.getRoundedInnerBorderFor(outerRec t, outerInsets, 774 FloatRoundedRect outerClip = m_style.getRoundedInnerBorderFor(outerR ect, outerInsets,
785 includeLogicalLeftEdge, includeLogicalRightEdge); 775 m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
786 graphicsContext->clipOutRoundedRect(outerClip); 776 graphicsContext->clipOutRoundedRect(outerClip);
787 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogi calLeftEdge, includeLogicalRightEdge); 777 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickne ss, drawThickness,
778 side, color, SOLID);
788 } 779 }
789 return; 780 return;
790 } 781 }
791 case RIDGE: 782 case RIDGE:
792 case GROOVE: 783 case GROOVE:
793 { 784 {
794 EBorderStyle s1; 785 EBorderStyle s1;
795 EBorderStyle s2; 786 EBorderStyle s2;
796 if (borderStyle == GROOVE) { 787 if (borderStyle == GROOVE) {
797 s1 = INSET; 788 s1 = INSET;
798 s2 = OUTSET; 789 s2 = OUTSET;
799 } else { 790 } else {
800 s1 = OUTSET; 791 s1 = OUTSET;
801 s2 = INSET; 792 s2 = INSET;
802 } 793 }
803 794
804 // Paint full border 795 // Paint full border
805 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thic kness, drawThickness, side, style, color, s1, bleedAvoidance, includeLogicalLeft Edge, includeLogicalRightEdge); 796 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness,
797 side, color, s1);
806 798
807 // Paint inner only 799 // Paint inner only
808 GraphicsContextStateSaver stateSaver(*graphicsContext); 800 GraphicsContextStateSaver stateSaver(*graphicsContext);
809 LayoutUnit topWidth = edges[BSTop].usedWidth() / 2; 801 LayoutUnit topWidth = m_edges[BSTop].usedWidth() / 2;
810 LayoutUnit bottomWidth = edges[BSBottom].usedWidth() / 2; 802 LayoutUnit bottomWidth = m_edges[BSBottom].usedWidth() / 2;
811 LayoutUnit leftWidth = edges[BSLeft].usedWidth() / 2; 803 LayoutUnit leftWidth = m_edges[BSLeft].usedWidth() / 2;
812 LayoutUnit rightWidth = edges[BSRight].usedWidth() / 2; 804 LayoutUnit rightWidth = m_edges[BSRight].usedWidth() / 2;
813 805
814 FloatRoundedRect clipRect = style.getRoundedInnerBorderFor(borderRect, 806 FloatRoundedRect clipRect = m_style.getRoundedInnerBorderFor(borderRect,
815 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth), 807 LayoutRectOutsets(-topWidth, -rightWidth, -bottomWidth, -leftWidth),
816 includeLogicalLeftEdge, includeLogicalRightEdge); 808 m_includeLogicalLeftEdge, m_includeLogicalRightEdge);
817 809
818 graphicsContext->clipRoundedRect(clipRect); 810 graphicsContext->clipRoundedRect(clipRect);
819 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thic kness, drawThickness, side, style, color, s2, bleedAvoidance, includeLogicalLeft Edge, includeLogicalRightEdge); 811 drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness,
812 side, color, s2);
820 return; 813 return;
821 } 814 }
822 case INSET: 815 case INSET:
823 if (side == BSTop || side == BSLeft) 816 if (side == BSTop || side == BSLeft)
824 color = color.dark(); 817 color = color.dark();
825 break; 818 break;
826 case OUTSET: 819 case OUTSET:
827 if (side == BSBottom || side == BSRight) 820 if (side == BSBottom || side == BSRight)
828 color = color.dark(); 821 color = color.dark();
829 break; 822 break;
830 default: 823 default:
831 break; 824 break;
832 } 825 }
833 826
834 graphicsContext->setStrokeStyle(NoStroke); 827 graphicsContext->setStrokeStyle(NoStroke);
835 graphicsContext->setFillColor(color); 828 graphicsContext->setFillColor(color);
836 graphicsContext->drawRect(pixelSnappedIntRect(borderRect)); 829 graphicsContext->drawRect(pixelSnappedIntRect(borderRect));
837 } 830 }
838 831
839 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext* graphi csContext, 832 void BoxBorderPainter::clipBorderSideForComplexInnerPath(GraphicsContext* graphi csContext,
840 const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, 833 BoxSide side) const
841 BoxSide side, const BorderEdge edges[])
842 { 834 {
843 graphicsContext->clip(calculateSideRectIncludingInner(outerBorder, edges, si de)); 835 graphicsContext->clip(calculateSideRectIncludingInner(m_outer, m_edges, side ));
844 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(innerBorde r, side); 836 FloatRoundedRect adjustedInnerRect = calculateAdjustedInnerBorder(m_inner, s ide);
845 if (!adjustedInnerRect.isEmpty()) 837 if (!adjustedInnerRect.isEmpty())
846 graphicsContext->clipOutRoundedRect(adjustedInnerRect); 838 graphicsContext->clipOutRoundedRect(adjustedInnerRect);
847 } 839 }
848 840
849 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext* graphicsContext, 841 void BoxBorderPainter::clipBorderSidePolygon(GraphicsContext* graphicsContext, B oxSide side,
850 const FloatRoundedRect& outerBorder, const FloatRoundedRect& innerBorder, Bo xSide side, 842 bool firstEdgeMatches, bool secondEdgeMatches) const
851 bool firstEdgeMatches, bool secondEdgeMatches)
852 { 843 {
853 FloatPoint quad[4]; 844 FloatPoint quad[4];
854 845
855 const LayoutRect outerRect(outerBorder.rect()); 846 const LayoutRect outerRect(m_outer.rect());
856 const LayoutRect innerRect(innerBorder.rect()); 847 const LayoutRect innerRect(m_inner.rect());
857
858 FloatPoint centerPoint(innerRect.location().x().toFloat() + innerRect.width( ).toFloat() / 2, innerRect.location().y().toFloat() + innerRect.height().toFloat () / 2);
859 848
860 // For each side, create a quad that encompasses all parts of that side that may draw, 849 // For each side, create a quad that encompasses all parts of that side that may draw,
861 // including areas inside the innerBorder. 850 // including areas inside the innerBorder.
862 // 851 //
863 // 0----------------3 852 // 0----------------3
864 // 0 \ / 0 853 // 0 \ / 0
865 // |\ 1----------- 2 /| 854 // |\ 1----------- 2 /|
866 // | 1 1 | 855 // | 1 1 |
867 // | | | | 856 // | | | |
868 // | | | | 857 // | | | |
869 // | 2 2 | 858 // | 2 2 |
870 // |/ 1------------2 \| 859 // |/ 1------------2 \|
871 // 3 / \ 3 860 // 3 / \ 3
872 // 0----------------3 861 // 0----------------3
873 // 862 //
874 switch (side) { 863 switch (side) {
875 case BSTop: 864 case BSTop:
876 quad[0] = FloatPoint(outerRect.minXMinYCorner()); 865 quad[0] = FloatPoint(outerRect.minXMinYCorner());
877 quad[1] = FloatPoint(innerRect.minXMinYCorner()); 866 quad[1] = FloatPoint(innerRect.minXMinYCorner());
878 quad[2] = FloatPoint(innerRect.maxXMinYCorner()); 867 quad[2] = FloatPoint(innerRect.maxXMinYCorner());
879 quad[3] = FloatPoint(outerRect.maxXMinYCorner()); 868 quad[3] = FloatPoint(outerRect.maxXMinYCorner());
880 869
881 if (!innerBorder.radii().topLeft().isZero()) { 870 if (!m_inner.radii().topLeft().isZero()) {
882 findIntersection(quad[0], quad[1], 871 findIntersection(quad[0], quad[1],
883 FloatPoint( 872 FloatPoint(
884 quad[1].x() + innerBorder.radii().topLeft().width(), 873 quad[1].x() + m_inner.radii().topLeft().width(),
885 quad[1].y()), 874 quad[1].y()),
886 FloatPoint( 875 FloatPoint(
887 quad[1].x(), 876 quad[1].x(),
888 quad[1].y() + innerBorder.radii().topLeft().height()), 877 quad[1].y() + m_inner.radii().topLeft().height()),
889 quad[1]); 878 quad[1]);
890 } 879 }
891 880
892 if (!innerBorder.radii().topRight().isZero()) { 881 if (!m_inner.radii().topRight().isZero()) {
893 findIntersection(quad[3], quad[2], 882 findIntersection(quad[3], quad[2],
894 FloatPoint( 883 FloatPoint(
895 quad[2].x() - innerBorder.radii().topRight().width(), 884 quad[2].x() - m_inner.radii().topRight().width(),
896 quad[2].y()), 885 quad[2].y()),
897 FloatPoint( 886 FloatPoint(
898 quad[2].x(), 887 quad[2].x(),
899 quad[2].y() + innerBorder.radii().topRight().height()), 888 quad[2].y() + m_inner.radii().topRight().height()),
900 quad[2]); 889 quad[2]);
901 } 890 }
902 break; 891 break;
903 892
904 case BSLeft: 893 case BSLeft:
905 quad[0] = FloatPoint(outerRect.minXMinYCorner()); 894 quad[0] = FloatPoint(outerRect.minXMinYCorner());
906 quad[1] = FloatPoint(innerRect.minXMinYCorner()); 895 quad[1] = FloatPoint(innerRect.minXMinYCorner());
907 quad[2] = FloatPoint(innerRect.minXMaxYCorner()); 896 quad[2] = FloatPoint(innerRect.minXMaxYCorner());
908 quad[3] = FloatPoint(outerRect.minXMaxYCorner()); 897 quad[3] = FloatPoint(outerRect.minXMaxYCorner());
909 898
910 if (!innerBorder.radii().topLeft().isZero()) { 899 if (!m_inner.radii().topLeft().isZero()) {
911 findIntersection(quad[0], quad[1], 900 findIntersection(quad[0], quad[1],
912 FloatPoint( 901 FloatPoint(
913 quad[1].x() + innerBorder.radii().topLeft().width(), 902 quad[1].x() + m_inner.radii().topLeft().width(),
914 quad[1].y()), 903 quad[1].y()),
915 FloatPoint( 904 FloatPoint(
916 quad[1].x(), 905 quad[1].x(),
917 quad[1].y() + innerBorder.radii().topLeft().height()), 906 quad[1].y() + m_inner.radii().topLeft().height()),
918 quad[1]); 907 quad[1]);
919 } 908 }
920 909
921 if (!innerBorder.radii().bottomLeft().isZero()) { 910 if (!m_inner.radii().bottomLeft().isZero()) {
922 findIntersection(quad[3], quad[2], 911 findIntersection(quad[3], quad[2],
923 FloatPoint( 912 FloatPoint(
924 quad[2].x() + innerBorder.radii().bottomLeft().width(), 913 quad[2].x() + m_inner.radii().bottomLeft().width(),
925 quad[2].y()), 914 quad[2].y()),
926 FloatPoint( 915 FloatPoint(
927 quad[2].x(), 916 quad[2].x(),
928 quad[2].y() - innerBorder.radii().bottomLeft().height()), 917 quad[2].y() - m_inner.radii().bottomLeft().height()),
929 quad[2]); 918 quad[2]);
930 } 919 }
931 break; 920 break;
932 921
933 case BSBottom: 922 case BSBottom:
934 quad[0] = FloatPoint(outerRect.minXMaxYCorner()); 923 quad[0] = FloatPoint(outerRect.minXMaxYCorner());
935 quad[1] = FloatPoint(innerRect.minXMaxYCorner()); 924 quad[1] = FloatPoint(innerRect.minXMaxYCorner());
936 quad[2] = FloatPoint(innerRect.maxXMaxYCorner()); 925 quad[2] = FloatPoint(innerRect.maxXMaxYCorner());
937 quad[3] = FloatPoint(outerRect.maxXMaxYCorner()); 926 quad[3] = FloatPoint(outerRect.maxXMaxYCorner());
938 927
939 if (!innerBorder.radii().bottomLeft().isZero()) { 928 if (!m_inner.radii().bottomLeft().isZero()) {
940 findIntersection(quad[0], quad[1], 929 findIntersection(quad[0], quad[1],
941 FloatPoint( 930 FloatPoint(
942 quad[1].x() + innerBorder.radii().bottomLeft().width(), 931 quad[1].x() + m_inner.radii().bottomLeft().width(),
943 quad[1].y()), 932 quad[1].y()),
944 FloatPoint( 933 FloatPoint(
945 quad[1].x(), 934 quad[1].x(),
946 quad[1].y() - innerBorder.radii().bottomLeft().height()), 935 quad[1].y() - m_inner.radii().bottomLeft().height()),
947 quad[1]); 936 quad[1]);
948 } 937 }
949 938
950 if (!innerBorder.radii().bottomRight().isZero()) { 939 if (!m_inner.radii().bottomRight().isZero()) {
951 findIntersection(quad[3], quad[2], 940 findIntersection(quad[3], quad[2],
952 FloatPoint( 941 FloatPoint(
953 quad[2].x() - innerBorder.radii().bottomRight().width(), 942 quad[2].x() - m_inner.radii().bottomRight().width(),
954 quad[2].y()), 943 quad[2].y()),
955 FloatPoint( 944 FloatPoint(
956 quad[2].x(), 945 quad[2].x(),
957 quad[2].y() - innerBorder.radii().bottomRight().height()), 946 quad[2].y() - m_inner.radii().bottomRight().height()),
958 quad[2]); 947 quad[2]);
959 } 948 }
960 break; 949 break;
961 950
962 case BSRight: 951 case BSRight:
963 quad[0] = FloatPoint(outerRect.maxXMinYCorner()); 952 quad[0] = FloatPoint(outerRect.maxXMinYCorner());
964 quad[1] = FloatPoint(innerRect.maxXMinYCorner()); 953 quad[1] = FloatPoint(innerRect.maxXMinYCorner());
965 quad[2] = FloatPoint(innerRect.maxXMaxYCorner()); 954 quad[2] = FloatPoint(innerRect.maxXMaxYCorner());
966 quad[3] = FloatPoint(outerRect.maxXMaxYCorner()); 955 quad[3] = FloatPoint(outerRect.maxXMaxYCorner());
967 956
968 if (!innerBorder.radii().topRight().isZero()) { 957 if (!m_inner.radii().topRight().isZero()) {
969 findIntersection(quad[0], quad[1], 958 findIntersection(quad[0], quad[1],
970 FloatPoint( 959 FloatPoint(
971 quad[1].x() - innerBorder.radii().topRight().width(), 960 quad[1].x() - m_inner.radii().topRight().width(),
972 quad[1].y()), 961 quad[1].y()),
973 FloatPoint( 962 FloatPoint(
974 quad[1].x(), 963 quad[1].x(),
975 quad[1].y() + innerBorder.radii().topRight().height()), 964 quad[1].y() + m_inner.radii().topRight().height()),
976 quad[1]); 965 quad[1]);
977 } 966 }
978 967
979 if (!innerBorder.radii().bottomRight().isZero()) { 968 if (!m_inner.radii().bottomRight().isZero()) {
980 findIntersection(quad[3], quad[2], 969 findIntersection(quad[3], quad[2],
981 FloatPoint( 970 FloatPoint(
982 quad[2].x() - innerBorder.radii().bottomRight().width(), 971 quad[2].x() - m_inner.radii().bottomRight().width(),
983 quad[2].y()), 972 quad[2].y()),
984 FloatPoint( 973 FloatPoint(
985 quad[2].x(), 974 quad[2].x(),
986 quad[2].y() - innerBorder.radii().bottomRight().height()), 975 quad[2].y() - m_inner.radii().bottomRight().height()),
987 quad[2]); 976 quad[2]);
988 } 977 }
989 break; 978 break;
990 } 979 }
991 980
992 // If the border matches both of its adjacent sides, don't anti-alias the cl ip, and 981 // If the border matches both of its adjacent sides, don't anti-alias the cl ip, and
993 // if neither side matches, anti-alias the clip. 982 // if neither side matches, anti-alias the clip.
994 if (firstEdgeMatches == secondEdgeMatches) { 983 if (firstEdgeMatches == secondEdgeMatches) {
995 graphicsContext->clipPolygon(4, quad, !firstEdgeMatches); 984 graphicsContext->clipPolygon(4, quad, !firstEdgeMatches);
996 return; 985 return;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 1017
1029 FloatPoint secondQuad[4]; 1018 FloatPoint secondQuad[4];
1030 secondQuad[0] = quad[0]; 1019 secondQuad[0] = quad[0];
1031 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy); 1020 secondQuad[1] = FloatPoint(quad[0].x() - r1 * cx, quad[0].y() - r1 * cy);
1032 secondQuad[2] = quad[2]; 1021 secondQuad[2] = quad[2];
1033 secondQuad[3] = quad[3]; 1022 secondQuad[3] = quad[3];
1034 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches); 1023 graphicsContext->clipPolygon(4, secondQuad, !secondEdgeMatches);
1035 } 1024 }
1036 1025
1037 } // namespace blink 1026 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/paint/BoxBorderPainter.h ('k') | Source/core/paint/BoxPainter.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698