Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve correctness of Sixel background fill #18260

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions src/terminal/adapter/SixelParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,11 @@ void SixelParser::_initRasterAttributes(const VTInt macroParameter, const Dispat

// By default, the filled area will cover the maximum extent allowed.
_backgroundSize = { til::CoordTypeMax, til::CoordTypeMax };

// If the requested background area can not initially be filled, we'll
// handle the rest of it on demand when the image is resized. But this
// will be determined later in the _fillImageBackground method.
_resizeFillRequired = false;
}

void SixelParser::_updateRasterAttributes(const VTParameters& rasterAttributes)
Expand Down Expand Up @@ -647,6 +652,10 @@ void SixelParser::_resizeImageBuffer(const til::CoordType requiredHeight)
{
static constexpr auto transparentPixel = IndexedPixel{ .transparent = true };
_imageBuffer.resize(requiredSize, transparentPixel);
if (_resizeFillRequired)
{
_fillImageBackground(requiredHeight);
}
}
}

Expand All @@ -656,25 +665,30 @@ void SixelParser::_fillImageBackground()
{
_backgroundFillRequired = false;

const auto backgroundHeight = std::min(_backgroundSize.height, _availablePixelHeight);
const auto backgroundWidth = std::min(_backgroundSize.width, _availablePixelWidth);
_resizeImageBuffer(backgroundHeight);

// When a background fill is requested, we prefill the buffer with the 0
// color index, up to the boundaries set by the raster attributes (or if
// none were given, up to the page boundaries). The actual image output
// isn't limited by the background dimensions though.
static constexpr auto backgroundPixel = IndexedPixel{};
const auto backgroundOffset = _imageCursor.y * _imageMaxWidth;
auto dst = std::next(_imageBuffer.begin(), backgroundOffset);
for (auto i = 0; i < backgroundHeight; i++)
{
std::fill_n(dst, backgroundWidth, backgroundPixel);
std::advance(dst, _imageMaxWidth);
}
// none were given, up to the page boundaries). If the requested height
// is more than the available height, we'll continue filling the rest of
// it on demand when the image is resized (see above).
const auto backgroundHeight = std::min(_backgroundSize.height, _availablePixelHeight);
_resizeImageBuffer(backgroundHeight);
_fillImageBackground(backgroundHeight);
_resizeFillRequired = _backgroundSize.height > _availablePixelHeight;
}
}

_imageWidth = std::max(_imageWidth, backgroundWidth);
void SixelParser::_fillImageBackground(const int backgroundHeight)
{
static constexpr auto backgroundPixel = IndexedPixel{};
const auto backgroundWidth = std::min(_backgroundSize.width, _availablePixelWidth);
const auto backgroundOffset = _imageCursor.y * _imageMaxWidth;
auto dst = std::next(_imageBuffer.begin(), backgroundOffset);
for (auto i = 0; i < backgroundHeight; i++)
{
std::fill_n(dst, backgroundWidth, backgroundPixel);
std::advance(dst, _imageMaxWidth);
}
_imageWidth = std::max(_imageWidth, backgroundWidth);
}

void SixelParser::_writeToImageBuffer(int sixelValue, int repeatCount)
Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/SixelParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ namespace Microsoft::Console::VirtualTerminal
til::CoordType _pendingTextScrollCount = 0;
til::size _backgroundSize;
bool _backgroundFillRequired = false;
bool _resizeFillRequired = false;

void _initColorMap(const VTParameter backgroundColor);
void _defineColor(const VTParameters& colorParameters);
Expand All @@ -109,6 +110,7 @@ namespace Microsoft::Console::VirtualTerminal
void _initImageBuffer();
void _resizeImageBuffer(const til::CoordType requiredHeight);
void _fillImageBackground();
void _fillImageBackground(const int backgroundHeight);
void _writeToImageBuffer(const int sixelValue, const int repeatCount);
void _eraseImageBufferRows(const int rowCount, const til::CoordType startRow = 0) noexcept;
void _maybeFlushImageBuffer(const bool endOfSequence = false);
Expand Down
Loading