Repository: microsoft/terminal
File: src/renderer/atlas/BackendD2D.cpp (C++)

Code before:
    _miscGeneration = p.s->misc.generation();
    _viewportCellCount = p.s->viewportCellCount;
}

void BackendD2D::_drawBackground(const RenderingPayload& p)
{
    if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
    {
        const D2D1_RECT_U rect{
            1u,
            1u,
            1u + p.s->viewportCellCount.x,
            1u + p.s->viewportCellCount.y,
        };
        THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(&rect, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32))));
        _backgroundBitmapGeneration = p.colorBitmapGenerations[0];
    }

    // If the terminal was 120x30 cells and 1200x600 pixels large, this would draw the
    // background by upscaling a 122x32 pixel bitmap to fill the entire render target,
    // with some overhang on all four sides to paint the gutters.
    const D2D1_RECT_F rect{
        static_cast<f32>(-(p.s->font->cellSize.x)),
        static_cast<f32>(-(p.s->font->cellSize.y)),
        static_cast<f32>(p.s->targetSize.x + (2 * p.s->font->cellSize.x)),
        static_cast<f32>(p.s->targetSize.y + (2 * p.s->font->cellSize.y))
    };
    _renderTarget->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
    _renderTarget->FillRectangle(&rect, _backgroundBrush.get());
    _renderTarget->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_SOURCE_OVER);
}

void BackendD2D::_drawText(RenderingPayload& p)
{
    til::CoordType dirtyTop = til::CoordTypeMax;
    til::CoordType dirtyBottom = til::CoordTypeMin;

    // It is possible to create a "_foregroundBrush" similar to how the `_backgroundBrush` is created and
    // use that as the brush for text rendering below. That way we wouldn't have to search `row->colors` for color
    // changes and could draw entire lines of text in a single call. Unfortunately Direct2D is not particularly
    // smart if you do this and chooses to draw the given text into a way too small offscreen texture first and
    // then blends it on the screen with the given bitmap brush. While this roughly doubles the performance
    // when drawing lots of colors, the extra latency drops performance by >10x when drawing fewer colors.
    // Since fewer colors are more common, I've chosen to go with regular solid-color brushes.
    u16 y = 0;
    for (const auto row : p.rows)
    {
        auto baselineX = 0.0f;
        auto baselineY = static_cast<f32>(p.s->font->cellSize.y * y + p.s->font->baseline);

        if (row->lineRendition != LineRendition::SingleWidth)

Review comment (suggestion):
This isn't quite correct if the `targetSize` is not a multiple of the `cellSize`. I think this should be `(cellCount + 1) * cellSize`.

Code after:
    _cursorGeneration = p.s->cursor.generation();
    _miscGeneration = p.s->misc.generation();
    _viewportCellCount = p.s->viewportCellCount;
}

void BackendD2D::_drawBackground(const RenderingPayload& p)
{
    if (_backgroundBitmapGeneration != p.colorBitmapGenerations[0])
    {
        const D2D1_RECT_U rect{
            1u,
            1u,
            1u + p.s->viewportCellCount.x,
            1u + p.s->viewportCellCount.y,
        };
        THROW_IF_FAILED(_backgroundBitmap->CopyFromMemory(&rect, p.backgroundBitmap.data(), gsl::narrow_cast<UINT32>(p.colorBitmapRowStride * sizeof(u32))));
        _backgroundBitmapGeneration = p.colorBitmapGenerations[0];
    }

    // If the terminal was 120x30 cells and 1200x600 pixels large, this would draw the
    // background by upscaling a 120x30 pixel bitmap to fill the entire render target.
    const D2D1_RECT_F rect{ 0, 0, static_cast<f32>(p.s->targetSize.x), static_cast<f32>(p.s->targetSize.y) };
    _renderTarget->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY);
    _renderTarget->FillRectangle(&rect, _backgroundBrush.get());
    _renderTarget->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_SOURCE_OVER);
}

void BackendD2D::_drawText(RenderingPayload& p)
{
    til::CoordType dirtyTop = til::CoordTypeMax;
    til::CoordType dirtyBottom = til::CoordTypeMin;

    // It is possible to create a "_foregroundBrush" similar to how the `_backgroundBrush` is created and
    // use that as the brush for text rendering below. That way we wouldn't have to search `row->colors` for color
    // changes and could draw entire lines of text in a single call. Unfortunately Direct2D is not particularly
    // smart if you do this and chooses to draw the given text into a way too small offscreen texture first and
    // then blends it on the screen with the given bitmap brush. While this roughly doubles the performance
    // when drawing lots of colors, the extra latency drops performance by >10x when drawing fewer colors.
    // Since fewer colors are more common, I've chosen to go with regular solid-color brushes.
    u16 y = 0;
    for (const auto row : p.rows)
    {
        auto baselineX = 0.0f;
        auto baselineY = static_cast<f32>(p.s->font->cellSize.y * y + p.s->font->baseline);

        if (row->lineRendition != LineRendition::SingleWidth)
        {
            baselineY = _drawTextPrepareLineRendition(p, row, baselineY);
        }

        for (const auto& m : row->mappings)