@@ -619,38 +619,52 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
619619 const auto cellCenter = row->lineRendition == LineRendition::DoubleHeightTop ? rowBottom : rowTop;
620620 const auto scaleHorizontal = row->lineRendition != LineRendition::SingleWidth ? 0 .5f : 1 .0f ;
621621 const auto scaledCellWidth = cellWidth * scaleHorizontal;
622+ const auto horizontalShift = static_cast <u8 >(row->lineRendition != LineRendition::SingleWidth);
622623
623624 const auto appendVerticalLines = [&](const GridLineRange& r, FontDecorationPosition pos) {
624625 const auto from = r.from * scaledCellWidth;
625626 const auto to = r.to * scaledCellWidth;
626627 auto x = from + pos.position ;
627628
629+ const auto colors = &p.foregroundBitmap [p.colorBitmapRowStride * y];
630+
628631 D2D1_POINT_2F point0{ 0 , cellCenter };
629632 D2D1_POINT_2F point1{ 0 , cellCenter + cellHeight };
630- const auto brush = _brushWithColor (r.gridlineColor );
631633 const f32 w = pos.height ;
632634 const f32 hw = w * 0 .5f ;
633635
634- for (; x < to; x += cellWidth)
636+ auto c = r.from ;
637+ for (; x < to; x += cellWidth, c += 1 << horizontalShift)
635638 {
639+ const auto brush = _brushWithColor (colors[c]);
636640 const auto centerX = x + hw;
637641 point0.x = centerX;
638642 point1.x = centerX;
639643 _renderTarget->DrawLine (point0, point1, brush, w, nullptr );
640644 }
641645 };
642- const auto appendHorizontalLine = [&](const GridLineRange& r, FontDecorationPosition pos, ID2D1StrokeStyle* strokeStyle, const u32 color) {
643- const auto from = r.from * scaledCellWidth;
644- const auto to = r.to * scaledCellWidth;
646+ const auto appendHorizontalLine = [&](const GridLineRange& r, FontDecorationPosition pos, ID2D1StrokeStyle* strokeStyle, const std::span<const u32 >& colorBitmap) {
647+ const auto colors = &colorBitmap[p.colorBitmapRowStride * y];
645648
646- const auto brush = _brushWithColor (color);
647649 const f32 w = pos.height ;
648650 const f32 centerY = cellCenter + pos.position + w * 0 .5f ;
649- const D2D1_POINT_2F point0{ from, centerY };
650- const D2D1_POINT_2F point1{ to, centerY };
651- _renderTarget->DrawLine (point0, point1, brush, w, strokeStyle);
651+
652+ for (auto from = r.from ; from < r.to ;)
653+ {
654+ const auto start = colors[from];
655+ u16 run = 1u ;
656+ for (; colors[from + run] == start && run < (r.to - from); ++run)
657+ ;
658+
659+ const auto brush = _brushWithColor (start);
660+ const D2D1_POINT_2F point0{ from * scaledCellWidth, centerY };
661+ const D2D1_POINT_2F point1{ (from + run) * scaledCellWidth, centerY };
662+ _renderTarget->DrawLine (point0, point1, brush, w, strokeStyle);
663+
664+ from += run;
665+ }
652666 };
653- const auto appendCurlyLine = [&](const GridLineRange& r) {
667+ const auto appendCurlyLine = [&](const GridLineRange& r, const std::span< const u32 >& colorBitmap ) {
654668 const auto & font = *p.s ->font ;
655669
656670 const auto duTop = static_cast <f32 >(font.doubleUnderline [0 ].position );
@@ -672,11 +686,16 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
672686 const auto step = roundf (0 .5f * height);
673687 const auto period = 4 .0f * step;
674688
675- const auto from = r.from * scaledCellWidth;
676- const auto to = r.to * scaledCellWidth;
689+ const auto colors = &colorBitmap[p.colorBitmapRowStride * y];
690+
691+ // Calculate the wave over the entire region to be underlined, even if
692+ // it has multiple colors in it. That way, when we clip it to render each
693+ // color, it is seamless.
694+ const auto fullSpanFrom = r.from * scaledCellWidth;
695+ const auto fullSpanTo = r.to * scaledCellWidth;
677696 // Align the start of the wave to the nearest preceding period boundary.
678697 // This ensures that the wave is continuous across color and cell changes.
679- auto x = floorf (from / period) * period;
698+ auto x = floorf (fullSpanFrom / period) * period;
680699
681700 wil::com_ptr<ID2D1PathGeometry> geometry;
682701 THROW_IF_FAILED (p.d2dFactory ->CreatePathGeometry (geometry.addressof ()));
@@ -686,7 +705,7 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
686705
687706 // This adds complete periods of the wave until we reach the end of the range.
688707 sink->BeginFigure ({ x, center }, D2D1_FIGURE_BEGIN_HOLLOW);
689- for (D2D1_QUADRATIC_BEZIER_SEGMENT segment; x < to ;)
708+ for (D2D1_QUADRATIC_BEZIER_SEGMENT segment; x < fullSpanTo ;)
690709 {
691710 x += step;
692711 segment.point1 .x = x;
@@ -708,11 +727,21 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
708727
709728 THROW_IF_FAILED (sink->Close ());
710729
711- const auto brush = _brushWithColor (r.underlineColor );
712- const D2D1_RECT_F clipRect{ from, rowTop, to, rowBottom };
713- _renderTarget->PushAxisAlignedClip (&clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
714- _renderTarget->DrawGeometry (geometry.get (), brush, duHeight, nullptr );
715- _renderTarget->PopAxisAlignedClip ();
730+ for (auto from = r.from ; from < r.to ;)
731+ {
732+ const auto start = colors[from];
733+ u16 run = 1u ;
734+ for (; colors[from + run] == start && run < (r.to - from); ++run)
735+ ;
736+
737+ const auto brush = _brushWithColor (start);
738+ const D2D1_RECT_F clipRect{ (from * scaledCellWidth), rowTop, (from + run) * scaledCellWidth, rowBottom };
739+ _renderTarget->PushAxisAlignedClip (&clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
740+ _renderTarget->DrawGeometry (geometry.get (), brush, duHeight, nullptr );
741+ _renderTarget->PopAxisAlignedClip ();
742+
743+ from += run;
744+ }
716745 };
717746
718747 for (const auto & r : row->gridLineRanges )
@@ -730,20 +759,20 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
730759 }
731760 if (r.lines .test (GridLines::Top))
732761 {
733- appendHorizontalLine (r, p.s ->font ->gridTop , nullptr , r. gridlineColor );
762+ appendHorizontalLine (r, p.s ->font ->gridTop , nullptr , p. foregroundBitmap );
734763 }
735764 if (r.lines .test (GridLines::Bottom))
736765 {
737- appendHorizontalLine (r, p.s ->font ->gridBottom , nullptr , r. gridlineColor );
766+ appendHorizontalLine (r, p.s ->font ->gridBottom , nullptr , p. foregroundBitmap );
738767 }
739768 if (r.lines .test (GridLines::Strikethrough))
740769 {
741- appendHorizontalLine (r, p.s ->font ->strikethrough , nullptr , r. gridlineColor );
770+ appendHorizontalLine (r, p.s ->font ->strikethrough , nullptr , p. foregroundBitmap );
742771 }
743772
744773 if (r.lines .test (GridLines::Underline))
745774 {
746- appendHorizontalLine (r, p.s ->font ->underline , nullptr , r. underlineColor );
775+ appendHorizontalLine (r, p.s ->font ->underline , nullptr , p. underlineBitmap );
747776 }
748777 else if (r.lines .any (GridLines::DottedUnderline, GridLines::HyperlinkUnderline))
749778 {
@@ -753,7 +782,7 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
753782 static constexpr FLOAT dashes[2 ]{ 1 , 1 };
754783 THROW_IF_FAILED (p.d2dFactory ->CreateStrokeStyle (&props, &dashes[0 ], 2 , _dottedStrokeStyle.addressof ()));
755784 }
756- appendHorizontalLine (r, p.s ->font ->underline , _dottedStrokeStyle.get (), r. underlineColor );
785+ appendHorizontalLine (r, p.s ->font ->underline , _dottedStrokeStyle.get (), p. underlineBitmap );
757786 }
758787 else if (r.lines .test (GridLines::DashedUnderline))
759788 {
@@ -763,17 +792,17 @@ void BackendD2D::_drawGridlineRow(const RenderingPayload& p, const ShapedRow* ro
763792 static constexpr FLOAT dashes[2 ]{ 2 , 2 };
764793 THROW_IF_FAILED (p.d2dFactory ->CreateStrokeStyle (&props, &dashes[0 ], 2 , _dashedStrokeStyle.addressof ()));
765794 }
766- appendHorizontalLine (r, p.s ->font ->underline , _dashedStrokeStyle.get (), r. underlineColor );
795+ appendHorizontalLine (r, p.s ->font ->underline , _dashedStrokeStyle.get (), p. underlineBitmap );
767796 }
768797 else if (r.lines .test (GridLines::CurlyUnderline))
769798 {
770- appendCurlyLine (r);
799+ appendCurlyLine (r, p. underlineBitmap );
771800 }
772801 else if (r.lines .test (GridLines::DoubleUnderline))
773802 {
774803 for (const auto pos : p.s ->font ->doubleUnderline )
775804 {
776- appendHorizontalLine (r, pos, nullptr , r. underlineColor );
805+ appendHorizontalLine (r, pos, nullptr , p. underlineBitmap );
777806 }
778807 }
779808 }
0 commit comments