Skip to content

Commit

Permalink
Improve correctness of Sixel background fill
Browse files Browse the repository at this point in the history
  • Loading branch information
j4james committed Nov 28, 2024
1 parent 9243104 commit 877bfe7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 15 deletions.
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

0 comments on commit 877bfe7

Please sign in to comment.