Skip to content

Commit

Permalink
Merge pull request #823 from contour-terminal/fix/lcd-pitch-issue
Browse files Browse the repository at this point in the history
Fixes issue for some oversized glyphs.
  • Loading branch information
christianparpart authored Sep 20, 2022
2 parents 89bc8b7 + e6fd4b3 commit 2caa86f
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 13 deletions.
2 changes: 1 addition & 1 deletion metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
<release version="0.3.5" urgency="medium" type="development">
<description>
<ul>
<li> ... </li>
<li>Fixes a problem with oversized glyphs being wrongly cut off (#821).</li>
</ul>
</description>
</release>
Expand Down
9 changes: 8 additions & 1 deletion src/terminal_renderer/TextRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,14 +368,21 @@ void TextRenderer::restrictToTileSize(TextureAtlas::TileCreateData& tileCreateDa
auto const subSize = ImageSize { subWidth, tileCreateData.bitmapSize.height };
auto const subPitch = unbox<uintptr_t>(subSize.width) * colorComponentCount;
auto const xOffset = 0;
auto const sourcePitch = unbox<uintptr_t>(tileCreateData.bitmapSize.width) * colorComponentCount;

auto slicedBitmap = vector<uint8_t>(subSize.area() * colorComponentCount);

if (RasterizerLog)
RasterizerLog()("Cutting off oversized {} tile from {} down to {}.",
tileCreateData.bitmapFormat,
tileCreateData.bitmapSize,
_textureAtlas->tileSize());

for (uintptr_t rowIndex = 0; rowIndex < unbox<uintptr_t>(subSize.height); ++rowIndex)
{
uint8_t* targetRow = slicedBitmap.data() + rowIndex * subPitch;
uint8_t const* sourceRow =
tileCreateData.bitmap.data() + rowIndex * subPitch + uintptr_t(xOffset) * colorComponentCount;
tileCreateData.bitmap.data() + rowIndex * sourcePitch + uintptr_t(xOffset) * colorComponentCount;
Require(sourceRow + subPitch <= tileCreateData.bitmap.data() + tileCreateData.bitmap.size());
std::memcpy(targetRow, sourceRow, subPitch);
}
Expand Down
39 changes: 28 additions & 11 deletions src/text_shaper/open_shaper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,10 +486,8 @@ struct open_shaper::Private // {{{
if (auto const ec = FT_Init_FreeType(&ft_); ec != FT_Err_Ok)
throw runtime_error { "freetype: Failed to initialize. "s + ftErrorStr(ec) };

#if defined(FT_LCD_FILTER_DEFAULT)
if (auto const ec = FT_Library_SetLcdFilter(ft_, FT_LCD_FILTER_DEFAULT); ec != FT_Err_Ok)
errorlog()("freetype: Failed to set LCD filter. {}", ftErrorStr(ec));
#endif
}

bool tryShapeWithFallback(font_key _font,
Expand Down Expand Up @@ -747,10 +745,13 @@ optional<rasterized_glyph> open_shaper::rasterize(glyph_key _glyph, render_mode
if (!FT_HAS_COLOR(ftFace))
{
if (FT_Render_Glyph(ftFace->glyph, ftRenderMode(_mode)) != FT_Err_Ok)
{
RasterizerLog()("Failed to rasterize glyph {}.", _glyph);
return nullopt;
}
}

rasterized_glyph output {};
auto output = rasterized_glyph {};
output.bitmapSize.width = crispy::Width::cast_from(ftFace->glyph->bitmap.width);
output.bitmapSize.height = crispy::Height::cast_from(ftFace->glyph->bitmap.rows);
output.position.x = ftFace->glyph->bitmap_left;
Expand Down Expand Up @@ -798,18 +799,34 @@ optional<rasterized_glyph> open_shaper::rasterize(glyph_key _glyph, render_mode
break;
}
case FT_PIXEL_MODE_LCD: {
auto const width = static_cast<size_t>(ftFace->glyph->bitmap.width);
auto const height = static_cast<size_t>(ftFace->glyph->bitmap.rows);
auto const& ftBitmap = ftFace->glyph->bitmap;
// RasterizerLog()("Rasterizing using pixel mode: {}, rows={}, width={}, pitch={}, mode={}",
// "lcd",
// ftBitmap.rows,
// ftBitmap.width,
// ftBitmap.pitch,
// ftBitmap.pixel_mode);

output.format = bitmap_format::rgb; // LCD
output.bitmap.resize(width * height);
output.bitmap.resize(static_cast<size_t>(ftBitmap.width) * static_cast<size_t>(ftBitmap.rows));
output.bitmapSize.width /= crispy::Width(3);

auto const pitch = static_cast<unsigned>(ftFace->glyph->bitmap.pitch);
auto const s = ftFace->glyph->bitmap.buffer;
for (auto const i: iota(0u, ftFace->glyph->bitmap.rows))
for (auto const j: iota(0u, ftFace->glyph->bitmap.width))
output.bitmap[i * width + j] = s[i * pitch + j];
auto s = ftBitmap.buffer;
auto t = output.bitmap.data();
if (ftBitmap.width == static_cast<unsigned>(std::abs(ftBitmap.pitch)))
{
std::copy_n(s, ftBitmap.width * ftBitmap.rows, t);
}
else
{
for (auto const _: iota(0u, ftBitmap.rows))
{
crispy::ignore_unused(_);
std::copy_n(s, ftBitmap.width, t);
s += ftBitmap.pitch;
t += ftBitmap.width;
}
}
break;
}
case FT_PIXEL_MODE_BGRA: {
Expand Down

0 comments on commit 2caa86f

Please sign in to comment.