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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutTableCell.cpp

Issue 2846563002: Optimize collapsed border calculation (step 1) (Closed)
Patch Set: - Created 3 years, 7 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1997 Martin Jones (mjones@kde.org) 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org) 3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org) 4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org) 5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) 6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc.
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * This library is free software; you can redistribute it and/or 10 * This library is free software; you can redistribute it and/or
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 52
53 static_assert(sizeof(LayoutTableCell) == sizeof(SameSizeAsLayoutTableCell), 53 static_assert(sizeof(LayoutTableCell) == sizeof(SameSizeAsLayoutTableCell),
54 "LayoutTableCell should stay small"); 54 "LayoutTableCell should stay small");
55 static_assert(sizeof(CollapsedBorderValue) == 8, 55 static_assert(sizeof(CollapsedBorderValue) == 8,
56 "CollapsedBorderValue should stay small"); 56 "CollapsedBorderValue should stay small");
57 57
58 LayoutTableCell::LayoutTableCell(Element* element) 58 LayoutTableCell::LayoutTableCell(Element* element)
59 : LayoutBlockFlow(element), 59 : LayoutBlockFlow(element),
60 absolute_column_index_(kUnsetColumnIndex), 60 absolute_column_index_(kUnsetColumnIndex),
61 cell_width_changed_(false), 61 cell_width_changed_(false),
62 collapsed_border_values_valid_(false),
63 collapsed_borders_visually_changed_(false),
62 intrinsic_padding_before_(0), 64 intrinsic_padding_before_(0),
63 intrinsic_padding_after_(0) { 65 intrinsic_padding_after_(0) {
64 // We only update the flags when notified of DOM changes in 66 // We only update the flags when notified of DOM changes in
65 // colSpanOrRowSpanChanged() so we need to set their initial values here in 67 // colSpanOrRowSpanChanged() so we need to set their initial values here in
66 // case something asks for colSpan()/rowSpan() before then. 68 // case something asks for colSpan()/rowSpan() before then.
67 UpdateColAndRowSpanFlags(); 69 UpdateColAndRowSpanFlags();
68 } 70 }
69 71
70 LayoutTableCell::CollapsedBorderValues::CollapsedBorderValues( 72 LayoutTableCell::CollapsedBorderValues::CollapsedBorderValues(
71 const LayoutTableCell& layout_table_cell, 73 const LayoutTableCell& layout_table_cell,
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 return HasSameDirectionAs(Table()) ? IsInStartColumn() : IsInEndColumn(); 591 return HasSameDirectionAs(Table()) ? IsInStartColumn() : IsInEndColumn();
590 } 592 }
591 593
592 bool LayoutTableCell::HasEndBorderAdjoiningTable() const { 594 bool LayoutTableCell::HasEndBorderAdjoiningTable() const {
593 // The table direction determines the row direction. In mixed directionality, 595 // The table direction determines the row direction. In mixed directionality,
594 // we cannot guarantee that we have a common border with the table (think a 596 // we cannot guarantee that we have a common border with the table (think a
595 // ltr table with ltr end cell). 597 // ltr table with ltr end cell).
596 return HasSameDirectionAs(Table()) ? IsInEndColumn() : IsInStartColumn(); 598 return HasSameDirectionAs(Table()) ? IsInEndColumn() : IsInStartColumn();
597 } 599 }
598 600
599 CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder( 601 CSSPropertyID LayoutTableCell::ResolveBorderProperty(
600 IncludeBorderColorOrNot include_color) const { 602 CSSPropertyID property) const {
603 return CSSProperty::ResolveDirectionAwareProperty(
604 property, StyleForCellFlow().Direction(),
605 StyleForCellFlow().GetWritingMode());
606 }
607
608 CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder() const {
601 LayoutTable* table = this->Table(); 609 LayoutTable* table = this->Table();
610 LayoutTableCell* cell_before = table->CellBefore(this);
611 // We can use the border shared with |cell_before| if it is valid.
612 if (cell_before && cell_before->collapsed_border_values_valid_ &&
613 cell_before->RowIndex() == RowIndex()) {
614 return cell_before->GetCollapsedBorderValues()
615 ? cell_before->GetCollapsedBorderValues()->EndBorder()
616 : CollapsedBorderValue();
617 }
602 618
603 // For the start border, we need to check, in order of precedence: 619 // For the start border, we need to check, in order of precedence:
604 // (1) Our start border. 620 // (1) Our start border.
605 int start_color_property = include_color 621 int start_color_property =
606 ? CSSProperty::ResolveDirectionAwareProperty( 622 ResolveBorderProperty(CSSPropertyWebkitBorderStartColor);
607 CSSPropertyWebkitBorderStartColor,
608 StyleForCellFlow().Direction(),
609 StyleForCellFlow().GetWritingMode())
610 : 0;
611 int end_color_property = 623 int end_color_property =
612 include_color 624 ResolveBorderProperty(CSSPropertyWebkitBorderEndColor);
613 ? CSSProperty::ResolveDirectionAwareProperty( 625 CollapsedBorderValue result(Style()->BorderStart(),
614 CSSPropertyWebkitBorderEndColor, StyleForCellFlow().Direction(), 626 ResolveColor(start_color_property),
615 StyleForCellFlow().GetWritingMode()) 627 kBorderPrecedenceCell);
616 : 0;
617 CollapsedBorderValue result(
618 Style()->BorderStart(),
619 include_color ? ResolveColor(start_color_property) : Color(),
620 kBorderPrecedenceCell);
621 628
622 // (2) The end border of the preceding cell. 629 // (2) The end border of the preceding cell.
623 LayoutTableCell* cell_before = table->CellBefore(this);
624 if (cell_before) { 630 if (cell_before) {
625 CollapsedBorderValue cell_before_adjoining_border = CollapsedBorderValue( 631 CollapsedBorderValue cell_before_adjoining_border = CollapsedBorderValue(
626 cell_before->BorderAdjoiningCellAfter(this), 632 cell_before->BorderAdjoiningCellAfter(this),
627 include_color ? cell_before->ResolveColor(end_color_property) : Color(), 633 cell_before->ResolveColor(end_color_property), kBorderPrecedenceCell);
628 kBorderPrecedenceCell);
629 // |result| should be the 2nd argument as |cellBefore| should win in case of 634 // |result| should be the 2nd argument as |cellBefore| should win in case of
630 // equality per CSS 2.1 (Border conflict resolution, point 4). 635 // equality per CSS 2.1 (Border conflict resolution, point 4).
631 result = ChooseBorder(cell_before_adjoining_border, result); 636 result = ChooseBorder(cell_before_adjoining_border, result);
632 if (!result.Exists()) 637 if (!result.Exists())
633 return result; 638 return result;
634 } 639 }
635 640
636 bool start_border_adjoins_table = HasStartBorderAdjoiningTable(); 641 bool start_border_adjoins_table = HasStartBorderAdjoiningTable();
637 if (start_border_adjoins_table) { 642 if (start_border_adjoins_table) {
638 // (3) Our row's start border. 643 // (3) Our row's start border.
639 result = ChooseBorder( 644 result = ChooseBorder(
640 result, CollapsedBorderValue( 645 result,
641 Row()->BorderAdjoiningStartCell(this), 646 CollapsedBorderValue(Row()->BorderAdjoiningStartCell(this),
642 include_color ? Parent()->ResolveColor(start_color_property) 647 Parent()->ResolveColor(start_color_property),
643 : Color(), 648 kBorderPrecedenceRow));
644 kBorderPrecedenceRow));
645 if (!result.Exists()) 649 if (!result.Exists())
646 return result; 650 return result;
647 651
648 // (4) Our row group's start border. 652 // (4) Our row group's start border.
649 result = ChooseBorder( 653 result = ChooseBorder(
650 result, CollapsedBorderValue(Section()->BorderAdjoiningStartCell(this), 654 result,
651 include_color ? Section()->ResolveColor( 655 CollapsedBorderValue(Section()->BorderAdjoiningStartCell(this),
652 start_color_property) 656 Section()->ResolveColor(start_color_property),
653 : Color(), 657 kBorderPrecedenceRowGroup));
654 kBorderPrecedenceRowGroup));
655 if (!result.Exists()) 658 if (!result.Exists())
656 return result; 659 return result;
657 } 660 }
658 661
659 // (5) Our column and column group's start borders. 662 // (5) Our column and column group's start borders.
660 LayoutTable::ColAndColGroup col_and_col_group = 663 LayoutTable::ColAndColGroup col_and_col_group =
661 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()); 664 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex());
662 if (col_and_col_group.colgroup && 665 if (col_and_col_group.colgroup &&
663 col_and_col_group.adjoins_start_border_of_col_group) { 666 col_and_col_group.adjoins_start_border_of_col_group) {
664 // Only apply the colgroup's border if this cell touches the colgroup edge. 667 // Only apply the colgroup's border if this cell touches the colgroup edge.
665 result = ChooseBorder( 668 result = ChooseBorder(
666 result, 669 result,
667 CollapsedBorderValue( 670 CollapsedBorderValue(
668 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), 671 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this),
669 include_color 672 col_and_col_group.colgroup->ResolveColor(start_color_property),
670 ? col_and_col_group.colgroup->ResolveColor(start_color_property)
671 : Color(),
672 kBorderPrecedenceColumnGroup)); 673 kBorderPrecedenceColumnGroup));
673 if (!result.Exists()) 674 if (!result.Exists())
674 return result; 675 return result;
675 } 676 }
676 if (col_and_col_group.col) { 677 if (col_and_col_group.col) {
677 // Always apply the col's border irrespective of whether this cell touches 678 // Always apply the col's border irrespective of whether this cell touches
678 // it. This is per HTML5: "For the purposes of the CSS table model, the col 679 // it. This is per HTML5: "For the purposes of the CSS table model, the col
679 // element is expected to be treated as if it "was present as many times as 680 // element is expected to be treated as if it "was present as many times as
680 // its span attribute specifies". 681 // its span attribute specifies".
681 result = ChooseBorder( 682 result = ChooseBorder(
682 result, CollapsedBorderValue( 683 result, CollapsedBorderValue(
683 col_and_col_group.col->BorderAdjoiningCellStartBorder(this), 684 col_and_col_group.col->BorderAdjoiningCellStartBorder(this),
684 include_color ? col_and_col_group.col->ResolveColor( 685 col_and_col_group.col->ResolveColor(start_color_property),
685 start_color_property)
686 : Color(),
687 kBorderPrecedenceColumn)); 686 kBorderPrecedenceColumn));
688 if (!result.Exists()) 687 if (!result.Exists())
689 return result; 688 return result;
690 } 689 }
691 690
692 // (6) The end border of the preceding column. 691 // (6) The end border of the preceding column.
693 if (cell_before) { 692 if (cell_before) {
694 LayoutTable::ColAndColGroup col_and_col_group = 693 LayoutTable::ColAndColGroup col_and_col_group =
695 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() - 1); 694 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() - 1);
696 // Only apply the colgroup's border if this cell touches the colgroup edge. 695 // Only apply the colgroup's border if this cell touches the colgroup edge.
697 if (col_and_col_group.colgroup && 696 if (col_and_col_group.colgroup &&
698 col_and_col_group.adjoins_end_border_of_col_group) { 697 col_and_col_group.adjoins_end_border_of_col_group) {
699 result = ChooseBorder( 698 result = ChooseBorder(
700 CollapsedBorderValue( 699 CollapsedBorderValue(
701 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), 700 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this),
702 include_color 701 col_and_col_group.colgroup->ResolveColor(end_color_property),
703 ? col_and_col_group.colgroup->ResolveColor(end_color_property)
704 : Color(),
705 kBorderPrecedenceColumnGroup), 702 kBorderPrecedenceColumnGroup),
706 result); 703 result);
707 if (!result.Exists()) 704 if (!result.Exists())
708 return result; 705 return result;
709 } 706 }
710 // Always apply the col's border irrespective of whether this cell touches 707 // Always apply the col's border irrespective of whether this cell touches
711 // it. This is per HTML5: "For the purposes of the CSS table model, the col 708 // it. This is per HTML5: "For the purposes of the CSS table model, the col
712 // element is expected to be treated as if it "was present as many times as 709 // element is expected to be treated as if it "was present as many times as
713 // its span attribute specifies". 710 // its span attribute specifies".
714 if (col_and_col_group.col) { 711 if (col_and_col_group.col) {
715 result = ChooseBorder( 712 result = ChooseBorder(
716 CollapsedBorderValue( 713 CollapsedBorderValue(
717 col_and_col_group.col->BorderAdjoiningCellAfter(this), 714 col_and_col_group.col->BorderAdjoiningCellAfter(this),
718 include_color 715 col_and_col_group.col->ResolveColor(end_color_property),
719 ? col_and_col_group.col->ResolveColor(end_color_property)
720 : Color(),
721 kBorderPrecedenceColumn), 716 kBorderPrecedenceColumn),
722 result); 717 result);
723 if (!result.Exists()) 718 if (!result.Exists())
724 return result; 719 return result;
725 } 720 }
726 } 721 }
727 722
728 if (start_border_adjoins_table) { 723 if (start_border_adjoins_table) {
729 // (7) The table's start border. 724 // (7) The table's start border.
730 result = ChooseBorder( 725 result = ChooseBorder(
731 result, 726 result, CollapsedBorderValue(table->TableStartBorderAdjoiningCell(this),
732 CollapsedBorderValue( 727 table->ResolveColor(start_color_property),
733 table->TableStartBorderAdjoiningCell(this), 728 kBorderPrecedenceTable));
734 include_color ? table->ResolveColor(start_color_property) : Color(),
735 kBorderPrecedenceTable));
736 if (!result.Exists()) 729 if (!result.Exists())
737 return result; 730 return result;
738 } 731 }
739 732
740 return result; 733 return result;
741 } 734 }
742 735
743 CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder( 736 CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder() const {
744 IncludeBorderColorOrNot include_color) const {
745 LayoutTable* table = this->Table(); 737 LayoutTable* table = this->Table();
746 // Note: We have to use the effective column information instead of whether we 738 // Note: We have to use the effective column information instead of whether we
747 // have a cell after as a table doesn't have to be regular (any row can have 739 // have a cell after as a table doesn't have to be regular (any row can have
748 // less cells than the total cell count). 740 // less cells than the total cell count).
749 bool is_end_column = table->AbsoluteColumnToEffectiveColumn( 741 bool is_end_column = IsInEndColumn();
750 AbsoluteColumnIndex() + ColSpan() - 1) == 742 LayoutTableCell* cell_after =
751 table->NumEffectiveColumns() - 1; 743 is_end_column ? nullptr : table->CellAfter(this);
744 // We can use the border shared with |cell_after| if it is valid.
745 if (cell_after && cell_after->collapsed_border_values_valid_ &&
746 cell_after->RowIndex() == RowIndex()) {
747 return cell_after->GetCollapsedBorderValues()
748 ? cell_after->GetCollapsedBorderValues()->StartBorder()
749 : CollapsedBorderValue();
750 }
752 751
753 // For end border, we need to check, in order of precedence: 752 // For end border, we need to check, in order of precedence:
754 // (1) Our end border. 753 // (1) Our end border.
755 int start_color_property = include_color 754 int start_color_property =
756 ? CSSProperty::ResolveDirectionAwareProperty( 755 ResolveBorderProperty(CSSPropertyWebkitBorderStartColor);
757 CSSPropertyWebkitBorderStartColor,
758 StyleForCellFlow().Direction(),
759 StyleForCellFlow().GetWritingMode())
760 : 0;
761 int end_color_property = 756 int end_color_property =
762 include_color 757 ResolveBorderProperty(CSSPropertyWebkitBorderEndColor);
763 ? CSSProperty::ResolveDirectionAwareProperty(
764 CSSPropertyWebkitBorderEndColor, StyleForCellFlow().Direction(),
765 StyleForCellFlow().GetWritingMode())
766 : 0;
767 CollapsedBorderValue result = CollapsedBorderValue( 758 CollapsedBorderValue result = CollapsedBorderValue(
768 Style()->BorderEnd(), 759 Style()->BorderEnd(), ResolveColor(end_color_property),
769 include_color ? ResolveColor(end_color_property) : Color(),
770 kBorderPrecedenceCell); 760 kBorderPrecedenceCell);
771 761
772 // (2) The start border of the following cell. 762 // (2) The start border of the following cell.
773 if (!is_end_column) { 763 if (cell_after) {
774 if (LayoutTableCell* cell_after = table->CellAfter(this)) { 764 CollapsedBorderValue cell_after_adjoining_border = CollapsedBorderValue(
775 CollapsedBorderValue cell_after_adjoining_border = CollapsedBorderValue( 765 cell_after->BorderAdjoiningCellBefore(this),
776 cell_after->BorderAdjoiningCellBefore(this), 766 cell_after->ResolveColor(start_color_property), kBorderPrecedenceCell);
777 include_color ? cell_after->ResolveColor(start_color_property) 767 result = ChooseBorder(result, cell_after_adjoining_border);
778 : Color(), 768 if (!result.Exists())
779 kBorderPrecedenceCell); 769 return result;
780 result = ChooseBorder(result, cell_after_adjoining_border);
781 if (!result.Exists())
782 return result;
783 }
784 } 770 }
785 771
786 bool end_border_adjoins_table = HasEndBorderAdjoiningTable(); 772 bool end_border_adjoins_table = HasEndBorderAdjoiningTable();
787 if (end_border_adjoins_table) { 773 if (end_border_adjoins_table) {
788 // (3) Our row's end border. 774 // (3) Our row's end border.
789 result = ChooseBorder( 775 result = ChooseBorder(
790 result, CollapsedBorderValue( 776 result, CollapsedBorderValue(Row()->BorderAdjoiningEndCell(this),
791 Row()->BorderAdjoiningEndCell(this), 777 Parent()->ResolveColor(end_color_property),
792 include_color ? Parent()->ResolveColor(end_color_property) 778 kBorderPrecedenceRow));
793 : Color(),
794 kBorderPrecedenceRow));
795 if (!result.Exists()) 779 if (!result.Exists())
796 return result; 780 return result;
797 781
798 // (4) Our row group's end border. 782 // (4) Our row group's end border.
799 result = ChooseBorder( 783 result = ChooseBorder(
800 result, CollapsedBorderValue( 784 result,
801 Section()->BorderAdjoiningEndCell(this), 785 CollapsedBorderValue(Section()->BorderAdjoiningEndCell(this),
802 include_color ? Section()->ResolveColor(end_color_property) 786 Section()->ResolveColor(end_color_property),
803 : Color(), 787 kBorderPrecedenceRowGroup));
804 kBorderPrecedenceRowGroup));
805 if (!result.Exists()) 788 if (!result.Exists())
806 return result; 789 return result;
807 } 790 }
808 791
809 // (5) Our column and column group's end borders. 792 // (5) Our column and column group's end borders.
810 LayoutTable::ColAndColGroup col_and_col_group = 793 LayoutTable::ColAndColGroup col_and_col_group =
811 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan() - 1); 794 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan() - 1);
812 if (col_and_col_group.colgroup && 795 if (col_and_col_group.colgroup &&
813 col_and_col_group.adjoins_end_border_of_col_group) { 796 col_and_col_group.adjoins_end_border_of_col_group) {
814 // Only apply the colgroup's border if this cell touches the colgroup edge. 797 // Only apply the colgroup's border if this cell touches the colgroup edge.
815 result = ChooseBorder( 798 result = ChooseBorder(
816 result, 799 result,
817 CollapsedBorderValue( 800 CollapsedBorderValue(
818 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this), 801 col_and_col_group.colgroup->BorderAdjoiningCellEndBorder(this),
819 include_color 802 col_and_col_group.colgroup->ResolveColor(end_color_property),
820 ? col_and_col_group.colgroup->ResolveColor(end_color_property)
821 : Color(),
822 kBorderPrecedenceColumnGroup)); 803 kBorderPrecedenceColumnGroup));
823 if (!result.Exists()) 804 if (!result.Exists())
824 return result; 805 return result;
825 } 806 }
826 if (col_and_col_group.col) { 807 if (col_and_col_group.col) {
827 // Always apply the col's border irrespective of whether this cell touches 808 // Always apply the col's border irrespective of whether this cell touches
828 // it. This is per HTML5: "For the purposes of the CSS table model, the col 809 // it. This is per HTML5: "For the purposes of the CSS table model, the col
829 // element is expected to be treated as if it "was present as many times as 810 // element is expected to be treated as if it "was present as many times as
830 // its span attribute specifies". 811 // its span attribute specifies".
831 result = ChooseBorder( 812 result = ChooseBorder(
832 result, CollapsedBorderValue( 813 result, CollapsedBorderValue(
833 col_and_col_group.col->BorderAdjoiningCellEndBorder(this), 814 col_and_col_group.col->BorderAdjoiningCellEndBorder(this),
834 include_color ? col_and_col_group.col->ResolveColor( 815 col_and_col_group.col->ResolveColor(end_color_property),
835 end_color_property)
836 : Color(),
837 kBorderPrecedenceColumn)); 816 kBorderPrecedenceColumn));
838 if (!result.Exists()) 817 if (!result.Exists())
839 return result; 818 return result;
840 } 819 }
841 820
842 // (6) The start border of the next column. 821 // (6) The start border of the next column.
843 if (!is_end_column) { 822 if (!is_end_column) {
844 LayoutTable::ColAndColGroup col_and_col_group = 823 LayoutTable::ColAndColGroup col_and_col_group =
845 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan()); 824 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex() + ColSpan());
846 if (col_and_col_group.colgroup && 825 if (col_and_col_group.colgroup &&
847 col_and_col_group.adjoins_start_border_of_col_group) { 826 col_and_col_group.adjoins_start_border_of_col_group) {
848 // Only apply the colgroup's border if this cell touches the colgroup 827 // Only apply the colgroup's border if this cell touches the colgroup
849 // edge. 828 // edge.
850 result = ChooseBorder( 829 result = ChooseBorder(
851 result, 830 result,
852 CollapsedBorderValue( 831 CollapsedBorderValue(
853 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this), 832 col_and_col_group.colgroup->BorderAdjoiningCellStartBorder(this),
854 include_color ? col_and_col_group.colgroup->ResolveColor( 833 col_and_col_group.colgroup->ResolveColor(start_color_property),
855 start_color_property)
856 : Color(),
857 kBorderPrecedenceColumnGroup)); 834 kBorderPrecedenceColumnGroup));
858 if (!result.Exists()) 835 if (!result.Exists())
859 return result; 836 return result;
860 } 837 }
861 if (col_and_col_group.col) { 838 if (col_and_col_group.col) {
862 // Always apply the col's border irrespective of whether this cell touches 839 // Always apply the col's border irrespective of whether this cell touches
863 // it. This is per HTML5: "For the purposes of the CSS table model, the 840 // it. This is per HTML5: "For the purposes of the CSS table model, the
864 // col element is expected to be treated as if it "was present as many 841 // col element is expected to be treated as if it "was present as many
865 // times as its span attribute specifies". 842 // times as its span attribute specifies".
866 result = ChooseBorder( 843 result = ChooseBorder(
867 result, CollapsedBorderValue( 844 result, CollapsedBorderValue(
868 col_and_col_group.col->BorderAdjoiningCellBefore(this), 845 col_and_col_group.col->BorderAdjoiningCellBefore(this),
869 include_color ? col_and_col_group.col->ResolveColor( 846 col_and_col_group.col->ResolveColor(start_color_property),
870 start_color_property)
871 : Color(),
872 kBorderPrecedenceColumn)); 847 kBorderPrecedenceColumn));
873 if (!result.Exists()) 848 if (!result.Exists())
874 return result; 849 return result;
875 } 850 }
876 } 851 }
877 852
878 if (end_border_adjoins_table) { 853 if (end_border_adjoins_table) {
879 // (7) The table's end border. 854 // (7) The table's end border.
880 result = ChooseBorder( 855 result = ChooseBorder(
881 result, 856 result, CollapsedBorderValue(table->TableEndBorderAdjoiningCell(this),
882 CollapsedBorderValue( 857 table->ResolveColor(end_color_property),
883 table->TableEndBorderAdjoiningCell(this), 858 kBorderPrecedenceTable));
884 include_color ? table->ResolveColor(end_color_property) : Color(),
885 kBorderPrecedenceTable));
886 if (!result.Exists()) 859 if (!result.Exists())
887 return result; 860 return result;
888 } 861 }
889 862
890 return result; 863 return result;
891 } 864 }
892 865
893 CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder( 866 CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder() const {
894 IncludeBorderColorOrNot include_color) const {
895 LayoutTable* table = this->Table(); 867 LayoutTable* table = this->Table();
868 LayoutTableCell* prev_cell = table->CellAbove(this);
869 // We can use the border shared with |prev_cell| if it is valid.
870 if (prev_cell && prev_cell->collapsed_border_values_valid_ &&
871 prev_cell->AbsoluteColumnIndex() == AbsoluteColumnIndex()) {
872 return prev_cell->GetCollapsedBorderValues()
873 ? prev_cell->GetCollapsedBorderValues()->AfterBorder()
874 : CollapsedBorderValue();
875 }
896 876
897 // For before border, we need to check, in order of precedence: 877 // For before border, we need to check, in order of precedence:
898 // (1) Our before border. 878 // (1) Our before border.
899 int before_color_property = include_color 879 int before_color_property =
900 ? CSSProperty::ResolveDirectionAwareProperty( 880 ResolveBorderProperty(CSSPropertyWebkitBorderBeforeColor);
901 CSSPropertyWebkitBorderBeforeColor, 881 int after_color_property =
902 StyleForCellFlow().Direction(), 882 ResolveBorderProperty(CSSPropertyWebkitBorderAfterColor);
903 StyleForCellFlow().GetWritingMode())
904 : 0;
905 int after_color_property = include_color
906 ? CSSProperty::ResolveDirectionAwareProperty(
907 CSSPropertyWebkitBorderAfterColor,
908 StyleForCellFlow().Direction(),
909 StyleForCellFlow().GetWritingMode())
910 : 0;
911 CollapsedBorderValue result = CollapsedBorderValue( 883 CollapsedBorderValue result = CollapsedBorderValue(
912 Style()->BorderBefore(), 884 Style()->BorderBefore(), ResolveColor(before_color_property),
913 include_color ? ResolveColor(before_color_property) : Color(),
914 kBorderPrecedenceCell); 885 kBorderPrecedenceCell);
915 886
916 LayoutTableCell* prev_cell = table->CellAbove(this);
917 if (prev_cell) { 887 if (prev_cell) {
918 // (2) A before cell's after border. 888 // (2) A before cell's after border.
919 result = ChooseBorder( 889 result = ChooseBorder(
920 CollapsedBorderValue(prev_cell->Style()->BorderAfter(), 890 CollapsedBorderValue(prev_cell->Style()->BorderAfter(),
921 include_color 891 prev_cell->ResolveColor(after_color_property),
922 ? prev_cell->ResolveColor(after_color_property)
923 : Color(),
924 kBorderPrecedenceCell), 892 kBorderPrecedenceCell),
925 result); 893 result);
926 if (!result.Exists()) 894 if (!result.Exists())
927 return result; 895 return result;
928 } 896 }
929 897
930 // (3) Our row's before border. 898 // (3) Our row's before border.
931 result = ChooseBorder( 899 result = ChooseBorder(
932 result, CollapsedBorderValue( 900 result,
933 Parent()->Style()->BorderBefore(), 901 CollapsedBorderValue(Parent()->Style()->BorderBefore(),
934 include_color ? Parent()->ResolveColor(before_color_property) 902 Parent()->ResolveColor(before_color_property),
935 : Color(), 903 kBorderPrecedenceRow));
936 kBorderPrecedenceRow));
937 if (!result.Exists()) 904 if (!result.Exists())
938 return result; 905 return result;
939 906
940 // (4) The previous row's after border. 907 // (4) The previous row's after border.
941 if (prev_cell) { 908 if (prev_cell) {
942 LayoutObject* prev_row = nullptr; 909 LayoutObject* prev_row = nullptr;
943 if (prev_cell->Section() == Section()) 910 if (prev_cell->Section() == Section())
944 prev_row = Parent()->PreviousSibling(); 911 prev_row = Parent()->PreviousSibling();
945 else 912 else
946 prev_row = prev_cell->Section()->LastRow(); 913 prev_row = prev_cell->Section()->LastRow();
947 914
948 if (prev_row) { 915 if (prev_row) {
949 result = ChooseBorder( 916 result = ChooseBorder(
950 CollapsedBorderValue( 917 CollapsedBorderValue(prev_row->Style()->BorderAfter(),
951 prev_row->Style()->BorderAfter(), 918 prev_row->ResolveColor(after_color_property),
952 include_color ? prev_row->ResolveColor(after_color_property) 919 kBorderPrecedenceRow),
953 : Color(),
954 kBorderPrecedenceRow),
955 result); 920 result);
956 if (!result.Exists()) 921 if (!result.Exists())
957 return result; 922 return result;
958 } 923 }
959 } 924 }
960 925
961 // Now check row groups. 926 // Now check row groups.
962 LayoutTableSection* curr_section = Section(); 927 LayoutTableSection* curr_section = Section();
963 if (!RowIndex()) { 928 if (!RowIndex()) {
964 // (5) Our row group's before border. 929 // (5) Our row group's before border.
965 result = ChooseBorder( 930 result = ChooseBorder(
966 result, CollapsedBorderValue(curr_section->Style()->BorderBefore(), 931 result,
967 include_color ? curr_section->ResolveColor( 932 CollapsedBorderValue(curr_section->Style()->BorderBefore(),
968 before_color_property) 933 curr_section->ResolveColor(before_color_property),
969 : Color(), 934 kBorderPrecedenceRowGroup));
970 kBorderPrecedenceRowGroup));
971 if (!result.Exists()) 935 if (!result.Exists())
972 return result; 936 return result;
973 937
974 // (6) Previous row group's after border. 938 // (6) Previous row group's after border.
975 curr_section = table->SectionAbove(curr_section, kSkipEmptySections); 939 curr_section = table->SectionAbove(curr_section, kSkipEmptySections);
976 if (curr_section) { 940 if (curr_section) {
977 result = ChooseBorder( 941 result = ChooseBorder(
978 CollapsedBorderValue( 942 CollapsedBorderValue(curr_section->Style()->BorderAfter(),
979 curr_section->Style()->BorderAfter(), 943 curr_section->ResolveColor(after_color_property),
980 include_color ? curr_section->ResolveColor(after_color_property) 944 kBorderPrecedenceRowGroup),
981 : Color(),
982 kBorderPrecedenceRowGroup),
983 result); 945 result);
984 if (!result.Exists()) 946 if (!result.Exists())
985 return result; 947 return result;
986 } 948 }
987 } 949 }
988 950
989 if (!curr_section) { 951 if (!curr_section) {
990 // (8) Our column and column group's before borders. 952 // (8) Our column and column group's before borders.
991 LayoutTableCol* col_elt = 953 LayoutTableCol* col_elt =
992 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) 954 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
993 .InnermostColOrColGroup(); 955 .InnermostColOrColGroup();
994 if (col_elt) { 956 if (col_elt) {
995 result = ChooseBorder( 957 result = ChooseBorder(
996 result, 958 result,
997 CollapsedBorderValue( 959 CollapsedBorderValue(col_elt->Style()->BorderBefore(),
998 col_elt->Style()->BorderBefore(), 960 col_elt->ResolveColor(before_color_property),
999 include_color ? col_elt->ResolveColor(before_color_property) 961 kBorderPrecedenceColumn));
1000 : Color(),
1001 kBorderPrecedenceColumn));
1002 if (!result.Exists()) 962 if (!result.Exists())
1003 return result; 963 return result;
1004 if (LayoutTableCol* enclosing_column_group = 964 if (LayoutTableCol* enclosing_column_group =
1005 col_elt->EnclosingColumnGroup()) { 965 col_elt->EnclosingColumnGroup()) {
1006 result = ChooseBorder( 966 result = ChooseBorder(
1007 result, CollapsedBorderValue( 967 result,
1008 enclosing_column_group->Style()->BorderBefore(), 968 CollapsedBorderValue(
1009 include_color ? enclosing_column_group->ResolveColor( 969 enclosing_column_group->Style()->BorderBefore(),
1010 before_color_property) 970 enclosing_column_group->ResolveColor(before_color_property),
1011 : Color(), 971 kBorderPrecedenceColumnGroup));
1012 kBorderPrecedenceColumnGroup));
1013 if (!result.Exists()) 972 if (!result.Exists())
1014 return result; 973 return result;
1015 } 974 }
1016 } 975 }
1017 976
1018 // (9) The table's before border. 977 // (9) The table's before border.
1019 result = ChooseBorder( 978 result = ChooseBorder(
1020 result, CollapsedBorderValue( 979 result, CollapsedBorderValue(table->Style()->BorderBefore(),
1021 table->Style()->BorderBefore(), 980 table->ResolveColor(before_color_property),
1022 include_color ? table->ResolveColor(before_color_property) 981 kBorderPrecedenceTable));
1023 : Color(),
1024 kBorderPrecedenceTable));
1025 if (!result.Exists()) 982 if (!result.Exists())
1026 return result; 983 return result;
1027 } 984 }
1028 985
1029 return result; 986 return result;
1030 } 987 }
1031 988
1032 CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder( 989 CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder() const {
1033 IncludeBorderColorOrNot include_color) const {
1034 LayoutTable* table = this->Table(); 990 LayoutTable* table = this->Table();
991 LayoutTableCell* next_cell = table->CellBelow(this);
992 // We can use the border shared with |next_cell| if it is valid.
993 if (next_cell && next_cell->collapsed_border_values_valid_ &&
994 next_cell->AbsoluteColumnIndex() == AbsoluteColumnIndex()) {
995 return next_cell->GetCollapsedBorderValues()
996 ? next_cell->GetCollapsedBorderValues()->BeforeBorder()
997 : CollapsedBorderValue();
998 }
1035 999
1036 // For after border, we need to check, in order of precedence: 1000 // For after border, we need to check, in order of precedence:
1037 // (1) Our after border. 1001 // (1) Our after border.
1038 int before_color_property = include_color 1002 int before_color_property =
1039 ? CSSProperty::ResolveDirectionAwareProperty( 1003 ResolveBorderProperty(CSSPropertyWebkitBorderBeforeColor);
1040 CSSPropertyWebkitBorderBeforeColor, 1004 int after_color_property =
1041 StyleForCellFlow().Direction(), 1005 ResolveBorderProperty(CSSPropertyWebkitBorderAfterColor);
1042 StyleForCellFlow().GetWritingMode())
1043 : 0;
1044 int after_color_property = include_color
1045 ? CSSProperty::ResolveDirectionAwareProperty(
1046 CSSPropertyWebkitBorderAfterColor,
1047 StyleForCellFlow().Direction(),
1048 StyleForCellFlow().GetWritingMode())
1049 : 0;
1050 CollapsedBorderValue result = CollapsedBorderValue( 1006 CollapsedBorderValue result = CollapsedBorderValue(
1051 Style()->BorderAfter(), 1007 Style()->BorderAfter(), ResolveColor(after_color_property),
1052 include_color ? ResolveColor(after_color_property) : Color(),
1053 kBorderPrecedenceCell); 1008 kBorderPrecedenceCell);
1054 1009
1055 LayoutTableCell* next_cell = table->CellBelow(this);
1056 if (next_cell) { 1010 if (next_cell) {
1057 // (2) An after cell's before border. 1011 // (2) An after cell's before border.
1058 result = ChooseBorder( 1012 result = ChooseBorder(
1059 result, CollapsedBorderValue(next_cell->Style()->BorderBefore(), 1013 result,
1060 include_color ? next_cell->ResolveColor( 1014 CollapsedBorderValue(next_cell->Style()->BorderBefore(),
1061 before_color_property) 1015 next_cell->ResolveColor(before_color_property),
1062 : Color(), 1016 kBorderPrecedenceCell));
1063 kBorderPrecedenceCell));
1064 if (!result.Exists()) 1017 if (!result.Exists())
1065 return result; 1018 return result;
1066 } 1019 }
1067 1020
1068 // (3) Our row's after border. (FIXME: Deal with rowspan!) 1021 // (3) Our row's after border. (FIXME: Deal with rowspan!)
1069 result = ChooseBorder( 1022 result = ChooseBorder(
1070 result, CollapsedBorderValue( 1023 result, CollapsedBorderValue(Parent()->Style()->BorderAfter(),
1071 Parent()->Style()->BorderAfter(), 1024 Parent()->ResolveColor(after_color_property),
1072 include_color ? Parent()->ResolveColor(after_color_property) 1025 kBorderPrecedenceRow));
1073 : Color(),
1074 kBorderPrecedenceRow));
1075 if (!result.Exists()) 1026 if (!result.Exists())
1076 return result; 1027 return result;
1077 1028
1078 // (4) The next row's before border. 1029 // (4) The next row's before border.
1079 if (next_cell) { 1030 if (next_cell) {
1080 result = ChooseBorder( 1031 result = ChooseBorder(
1081 result, 1032 result, CollapsedBorderValue(
1082 CollapsedBorderValue(next_cell->Parent()->Style()->BorderBefore(), 1033 next_cell->Parent()->Style()->BorderBefore(),
1083 include_color ? next_cell->Parent()->ResolveColor( 1034 next_cell->Parent()->ResolveColor(before_color_property),
1084 before_color_property) 1035 kBorderPrecedenceRow));
1085 : Color(),
1086 kBorderPrecedenceRow));
1087 if (!result.Exists()) 1036 if (!result.Exists())
1088 return result; 1037 return result;
1089 } 1038 }
1090 1039
1091 // Now check row groups. 1040 // Now check row groups.
1092 LayoutTableSection* curr_section = Section(); 1041 LayoutTableSection* curr_section = Section();
1093 if (RowIndex() + RowSpan() >= curr_section->NumRows()) { 1042 if (RowIndex() + RowSpan() >= curr_section->NumRows()) {
1094 // (5) Our row group's after border. 1043 // (5) Our row group's after border.
1095 result = ChooseBorder( 1044 result = ChooseBorder(
1096 result, CollapsedBorderValue(curr_section->Style()->BorderAfter(), 1045 result,
1097 include_color ? curr_section->ResolveColor( 1046 CollapsedBorderValue(curr_section->Style()->BorderAfter(),
1098 after_color_property) 1047 curr_section->ResolveColor(after_color_property),
1099 : Color(), 1048 kBorderPrecedenceRowGroup));
1100 kBorderPrecedenceRowGroup));
1101 if (!result.Exists()) 1049 if (!result.Exists())
1102 return result; 1050 return result;
1103 1051
1104 // (6) Following row group's before border. 1052 // (6) Following row group's before border.
1105 curr_section = table->SectionBelow(curr_section, kSkipEmptySections); 1053 curr_section = table->SectionBelow(curr_section, kSkipEmptySections);
1106 if (curr_section) { 1054 if (curr_section) {
1107 result = ChooseBorder( 1055 result = ChooseBorder(
1108 result, 1056 result, CollapsedBorderValue(
1109 CollapsedBorderValue( 1057 curr_section->Style()->BorderBefore(),
1110 curr_section->Style()->BorderBefore(), 1058 curr_section->ResolveColor(before_color_property),
1111 include_color ? curr_section->ResolveColor(before_color_property) 1059 kBorderPrecedenceRowGroup));
1112 : Color(),
1113 kBorderPrecedenceRowGroup));
1114 if (!result.Exists()) 1060 if (!result.Exists())
1115 return result; 1061 return result;
1116 } 1062 }
1117 } 1063 }
1118 1064
1119 if (!curr_section) { 1065 if (!curr_section) {
1120 // (8) Our column and column group's after borders. 1066 // (8) Our column and column group's after borders.
1121 LayoutTableCol* col_elt = 1067 LayoutTableCol* col_elt =
1122 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex()) 1068 table->ColElementAtAbsoluteColumn(AbsoluteColumnIndex())
1123 .InnermostColOrColGroup(); 1069 .InnermostColOrColGroup();
1124 if (col_elt) { 1070 if (col_elt) {
1125 result = ChooseBorder( 1071 result = ChooseBorder(
1126 result, CollapsedBorderValue(col_elt->Style()->BorderAfter(), 1072 result,
1127 include_color ? col_elt->ResolveColor( 1073 CollapsedBorderValue(col_elt->Style()->BorderAfter(),
1128 after_color_property) 1074 col_elt->ResolveColor(after_color_property),
1129 : Color(), 1075 kBorderPrecedenceColumn));
1130 kBorderPrecedenceColumn));
1131 if (!result.Exists()) 1076 if (!result.Exists())
1132 return result; 1077 return result;
1133 if (LayoutTableCol* enclosing_column_group = 1078 if (LayoutTableCol* enclosing_column_group =
1134 col_elt->EnclosingColumnGroup()) { 1079 col_elt->EnclosingColumnGroup()) {
1135 result = ChooseBorder( 1080 result = ChooseBorder(
1136 result, CollapsedBorderValue( 1081 result,
1137 enclosing_column_group->Style()->BorderAfter(), 1082 CollapsedBorderValue(
1138 include_color ? enclosing_column_group->ResolveColor( 1083 enclosing_column_group->Style()->BorderAfter(),
1139 after_color_property) 1084 enclosing_column_group->ResolveColor(after_color_property),
1140 : Color(), 1085 kBorderPrecedenceColumnGroup));
1141 kBorderPrecedenceColumnGroup));
1142 if (!result.Exists()) 1086 if (!result.Exists())
1143 return result; 1087 return result;
1144 } 1088 }
1145 } 1089 }
1146 1090
1147 // (9) The table's after border. 1091 // (9) The table's after border.
1148 result = ChooseBorder( 1092 result = ChooseBorder(
1149 result, 1093 result, CollapsedBorderValue(table->Style()->BorderAfter(),
1150 CollapsedBorderValue( 1094 table->ResolveColor(after_color_property),
1151 table->Style()->BorderAfter(), 1095 kBorderPrecedenceTable));
1152 include_color ? table->ResolveColor(after_color_property) : Color(),
1153 kBorderPrecedenceTable));
1154 if (!result.Exists()) 1096 if (!result.Exists())
1155 return result; 1097 return result;
1156 } 1098 }
1157 1099
1158 return result; 1100 return result;
1159 } 1101 }
1160 1102
1161 LayoutUnit LayoutTableCell::BorderLeft() const { 1103 LayoutUnit LayoutTableCell::BorderLeft() const {
1162 return Table()->CollapseBorders() ? CollapsedBorderHalfLeft(false) 1104 return Table()->CollapseBorders() ? CollapsedBorderHalfLeft(false)
1163 : LayoutBlockFlow::BorderLeft(); 1105 : LayoutBlockFlow::BorderLeft();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1243 return style_for_cell_flow.IsFlippedBlocksWritingMode() 1185 return style_for_cell_flow.IsFlippedBlocksWritingMode()
1244 ? CollapsedBorderHalfBefore(outer) 1186 ? CollapsedBorderHalfBefore(outer)
1245 : CollapsedBorderHalfAfter(outer); 1187 : CollapsedBorderHalfAfter(outer);
1246 } 1188 }
1247 return style_for_cell_flow.IsLeftToRightDirection() 1189 return style_for_cell_flow.IsLeftToRightDirection()
1248 ? CollapsedBorderHalfEnd(outer) 1190 ? CollapsedBorderHalfEnd(outer)
1249 : CollapsedBorderHalfStart(outer); 1191 : CollapsedBorderHalfStart(outer);
1250 } 1192 }
1251 1193
1252 LayoutUnit LayoutTableCell::CollapsedBorderHalfStart(bool outer) const { 1194 LayoutUnit LayoutTableCell::CollapsedBorderHalfStart(bool outer) const {
1253 CollapsedBorderValue border = 1195 UpdateCollapsedBorderValues();
1254 ComputeCollapsedStartBorder(kDoNotIncludeBorderColor); 1196 const auto* collapsed_border_values = this->GetCollapsedBorderValues();
1197 if (!collapsed_border_values)
1198 return LayoutUnit();
1199
1200 const auto& border = collapsed_border_values->StartBorder();
1255 if (border.Exists()) { 1201 if (border.Exists()) {
1256 return LayoutUnit( 1202 return LayoutUnit(
1257 (border.Width() + 1203 (border.Width() +
1258 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 1 : 0)) / 1204 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 1 : 0)) /
1259 2); // Give the extra pixel to top and left. 1205 2); // Give the extra pixel to top and left.
1260 } 1206 }
1261 return LayoutUnit(); 1207 return LayoutUnit();
1262 } 1208 }
1263 1209
1264 LayoutUnit LayoutTableCell::CollapsedBorderHalfEnd(bool outer) const { 1210 LayoutUnit LayoutTableCell::CollapsedBorderHalfEnd(bool outer) const {
1265 CollapsedBorderValue border = 1211 UpdateCollapsedBorderValues();
1266 ComputeCollapsedEndBorder(kDoNotIncludeBorderColor); 1212 const auto* collapsed_border_values = this->GetCollapsedBorderValues();
1213 if (!collapsed_border_values)
1214 return LayoutUnit();
1215
1216 const auto& border = collapsed_border_values->EndBorder();
1267 if (border.Exists()) { 1217 if (border.Exists()) {
1268 return LayoutUnit( 1218 return LayoutUnit(
1269 (border.Width() + 1219 (border.Width() +
1270 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 0 : 1)) / 1220 ((StyleForCellFlow().IsLeftToRightDirection() ^ outer) ? 0 : 1)) /
1271 2); 1221 2);
1272 } 1222 }
1273 return LayoutUnit(); 1223 return LayoutUnit();
1274 } 1224 }
1275 1225
1276 LayoutUnit LayoutTableCell::CollapsedBorderHalfBefore(bool outer) const { 1226 LayoutUnit LayoutTableCell::CollapsedBorderHalfBefore(bool outer) const {
1277 CollapsedBorderValue border = 1227 UpdateCollapsedBorderValues();
1278 ComputeCollapsedBeforeBorder(kDoNotIncludeBorderColor); 1228 const auto* collapsed_border_values = this->GetCollapsedBorderValues();
1229 if (!collapsed_border_values)
1230 return LayoutUnit();
1231
1232 const auto& border = collapsed_border_values->BeforeBorder();
1279 if (border.Exists()) { 1233 if (border.Exists()) {
1280 return LayoutUnit( 1234 return LayoutUnit(
1281 (border.Width() + 1235 (border.Width() +
1282 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / 1236 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) /
1283 2); // Give the extra pixel to top and left. 1237 2); // Give the extra pixel to top and left.
1284 } 1238 }
1285 return LayoutUnit(); 1239 return LayoutUnit();
1286 } 1240 }
1287 1241
1288 LayoutUnit LayoutTableCell::CollapsedBorderHalfAfter(bool outer) const { 1242 LayoutUnit LayoutTableCell::CollapsedBorderHalfAfter(bool outer) const {
1289 CollapsedBorderValue border = 1243 UpdateCollapsedBorderValues();
1290 ComputeCollapsedAfterBorder(kDoNotIncludeBorderColor); 1244 const auto* collapsed_border_values = this->GetCollapsedBorderValues();
1245 if (!collapsed_border_values)
1246 return LayoutUnit();
1247
1248 const auto& border = collapsed_border_values->AfterBorder();
1291 if (border.Exists()) { 1249 if (border.Exists()) {
1292 return LayoutUnit( 1250 return LayoutUnit(
1293 (border.Width() + 1251 (border.Width() +
1294 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / 1252 ((StyleForCellFlow().IsFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) /
1295 2); 1253 2);
1296 } 1254 }
1297 return LayoutUnit(); 1255 return LayoutUnit();
1298 } 1256 }
1299 1257
1300 void LayoutTableCell::Paint(const PaintInfo& paint_info, 1258 void LayoutTableCell::Paint(const PaintInfo& paint_info,
1301 const LayoutPoint& paint_offset) const { 1259 const LayoutPoint& paint_offset) const {
1302 TableCellPainter(*this).Paint(paint_info, paint_offset); 1260 TableCellPainter(*this).Paint(paint_info, paint_offset);
1303 } 1261 }
1304 1262
1263 void LayoutTableCell::UpdateCollapsedBorderValues() const {
1264 Table()->InvalidateCollapsedBordersForAllCellsIfNeeded();
1265 if (collapsed_border_values_valid_)
1266 return;
1267
1268 collapsed_border_values_valid_ = true;
1269
1270 if (!Table()->CollapseBorders()) {
1271 if (collapsed_border_values_) {
1272 collapsed_borders_visually_changed_ = true;
1273 collapsed_border_values_ = nullptr;
1274 }
1275 return;
1276 }
1277
1278 CollapsedBorderValues new_values(
1279 *this, ComputeCollapsedStartBorder(), ComputeCollapsedEndBorder(),
1280 ComputeCollapsedBeforeBorder(), ComputeCollapsedAfterBorder());
1281
1282 // We need to save collapsed border if has a non-zero width even if it's
1283 // invisible because the width affects table layout.
1284 if (!new_values.StartBorder().Width() && !new_values.EndBorder().Width() &&
1285 !new_values.BeforeBorder().Width() && !new_values.AfterBorder().Width()) {
1286 if (collapsed_border_values_) {
1287 collapsed_borders_visually_changed_ = true;
1288 collapsed_border_values_ = nullptr;
1289 }
1290 return;
1291 }
1292
1293 if (!collapsed_border_values_) {
1294 collapsed_borders_visually_changed_ = true;
1295 collapsed_border_values_ = WTF::WrapUnique(new CollapsedBorderValues(
1296 *this, new_values.StartBorder(), new_values.EndBorder(),
1297 new_values.BeforeBorder(), new_values.AfterBorder()));
1298 return;
1299 }
1300
1301 // We check VisuallyEquals so that the table cell is invalidated only if a
1302 // changed collapsed border is visible in the first place.
1303 if (!collapsed_border_values_->StartBorder().VisuallyEquals(
1304 new_values.StartBorder()) ||
1305 !collapsed_border_values_->EndBorder().VisuallyEquals(
1306 new_values.EndBorder()) ||
1307 !collapsed_border_values_->BeforeBorder().VisuallyEquals(
1308 new_values.BeforeBorder()) ||
1309 !collapsed_border_values_->AfterBorder().VisuallyEquals(
1310 new_values.AfterBorder())) {
1311 collapsed_border_values_->SetCollapsedBorderValues(new_values);
1312 collapsed_borders_visually_changed_ = true;
1313 }
1314 }
1315
1305 static void AddBorderStyle(LayoutTable::CollapsedBorderValues& border_values, 1316 static void AddBorderStyle(LayoutTable::CollapsedBorderValues& border_values,
1306 CollapsedBorderValue border_value) { 1317 CollapsedBorderValue border_value) {
1307 if (!border_value.IsVisible()) 1318 if (!border_value.IsVisible())
1308 return; 1319 return;
1309 size_t count = border_values.size(); 1320 size_t count = border_values.size();
1310 for (size_t i = 0; i < count; ++i) { 1321 for (size_t i = 0; i < count; ++i) {
1311 if (border_values[i].IsSameIgnoringColor(border_value)) 1322 if (border_values[i].IsSameIgnoringColor(border_value))
1312 return; 1323 return;
1313 } 1324 }
1314 border_values.push_back(border_value); 1325 border_values.push_back(border_value);
1315 } 1326 }
1316 1327
1317 void LayoutTableCell::CollectCollapsedBorderValues( 1328 void LayoutTableCell::CollectCollapsedBorderValues(
1318 LayoutTable::CollapsedBorderValues& border_values) { 1329 LayoutTable::CollapsedBorderValues& border_values) {
1319 CollapsedBorderValues new_values( 1330 UpdateCollapsedBorderValues();
1320 *this, ComputeCollapsedStartBorder(), ComputeCollapsedEndBorder(),
1321 ComputeCollapsedBeforeBorder(), ComputeCollapsedAfterBorder());
1322
1323 bool changed = false;
1324 if (!new_values.StartBorder().IsVisible() &&
1325 !new_values.EndBorder().IsVisible() &&
1326 !new_values.BeforeBorder().IsVisible() &&
1327 !new_values.AfterBorder().IsVisible()) {
1328 changed = !!collapsed_border_values_;
1329 collapsed_border_values_ = nullptr;
1330 } else if (!collapsed_border_values_) {
1331 changed = true;
1332 collapsed_border_values_ = WTF::WrapUnique(new CollapsedBorderValues(
1333 *this, new_values.StartBorder(), new_values.EndBorder(),
1334 new_values.BeforeBorder(), new_values.AfterBorder()));
1335 } else {
1336 // We check visuallyEquals so that the table cell is invalidated only if a
1337 // changed collapsed border is visible in the first place.
1338 changed = !collapsed_border_values_->StartBorder().VisuallyEquals(
1339 new_values.StartBorder()) ||
1340 !collapsed_border_values_->EndBorder().VisuallyEquals(
1341 new_values.EndBorder()) ||
1342 !collapsed_border_values_->BeforeBorder().VisuallyEquals(
1343 new_values.BeforeBorder()) ||
1344 !collapsed_border_values_->AfterBorder().VisuallyEquals(
1345 new_values.AfterBorder());
1346 if (changed)
1347 collapsed_border_values_->SetCollapsedBorderValues(new_values);
1348 }
1349 1331
1350 // If collapsed borders changed, invalidate the cell's display item client on 1332 // If collapsed borders changed, invalidate the cell's display item client on
1351 // the table's backing. 1333 // the table's backing.
1352 // TODO(crbug.com/451090#c5): Need a way to invalidate/repaint the borders 1334 // TODO(crbug.com/451090#c5): Need a way to invalidate/repaint the borders
1353 // only. 1335 // only.
1354 if (changed) { 1336 if (collapsed_borders_visually_changed_) {
1355 ObjectPaintInvalidator(*Table()) 1337 ObjectPaintInvalidator(*Table())
1356 .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient( 1338 .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
1357 *this, kPaintInvalidationStyleChange); 1339 *this, kPaintInvalidationStyleChange);
1340 collapsed_borders_visually_changed_ = false;
1358 } 1341 }
1359 1342
1360 AddBorderStyle(border_values, new_values.StartBorder()); 1343 if (!collapsed_border_values_)
1361 AddBorderStyle(border_values, new_values.EndBorder()); 1344 return;
1362 AddBorderStyle(border_values, new_values.BeforeBorder()); 1345
1363 AddBorderStyle(border_values, new_values.AfterBorder()); 1346 AddBorderStyle(border_values, collapsed_border_values_->StartBorder());
1347 AddBorderStyle(border_values, collapsed_border_values_->EndBorder());
1348 AddBorderStyle(border_values, collapsed_border_values_->BeforeBorder());
1349 AddBorderStyle(border_values, collapsed_border_values_->AfterBorder());
1364 } 1350 }
1365 1351
1366 void LayoutTableCell::SortCollapsedBorderValues( 1352 void LayoutTableCell::SortCollapsedBorderValues(
1367 LayoutTable::CollapsedBorderValues& border_values) { 1353 LayoutTable::CollapsedBorderValues& border_values) {
1368 std::sort(border_values.begin(), border_values.end(), CompareBorders); 1354 std::sort(border_values.begin(), border_values.end(), CompareBorders);
1369 } 1355 }
1370 1356
1371 void LayoutTableCell::PaintBoxDecorationBackground( 1357 void LayoutTableCell::PaintBoxDecorationBackground(
1372 const PaintInfo& paint_info, 1358 const PaintInfo& paint_info,
1373 const LayoutPoint& paint_offset) const { 1359 const LayoutPoint& paint_offset) const {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1485 } 1471 }
1486 1472
1487 bool LayoutTableCell::HasLineIfEmpty() const { 1473 bool LayoutTableCell::HasLineIfEmpty() const {
1488 if (GetNode() && HasEditableStyle(*GetNode())) 1474 if (GetNode() && HasEditableStyle(*GetNode()))
1489 return true; 1475 return true;
1490 1476
1491 return LayoutBlock::HasLineIfEmpty(); 1477 return LayoutBlock::HasLineIfEmpty();
1492 } 1478 }
1493 1479
1494 } // namespace blink 1480 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutTableCell.h ('k') | third_party/WebKit/Source/core/layout/LayoutTableCellTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698