OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |