diff --git a/metainfo.xml b/metainfo.xml
index 02e3cc32d2..0356bde8cc 100644
--- a/metainfo.xml
+++ b/metainfo.xml
@@ -102,7 +102,7 @@
- - ...
+ - Fixes a problem with oversized glyphs being wrongly cut off (#821).
diff --git a/src/terminal_renderer/TextRenderer.cpp b/src/terminal_renderer/TextRenderer.cpp
index 6cb61451c8..c08ac8f955 100644
--- a/src/terminal_renderer/TextRenderer.cpp
+++ b/src/terminal_renderer/TextRenderer.cpp
@@ -368,14 +368,21 @@ void TextRenderer::restrictToTileSize(TextureAtlas::TileCreateData& tileCreateDa
auto const subSize = ImageSize { subWidth, tileCreateData.bitmapSize.height };
auto const subPitch = unbox(subSize.width) * colorComponentCount;
auto const xOffset = 0;
+ auto const sourcePitch = unbox(tileCreateData.bitmapSize.width) * colorComponentCount;
auto slicedBitmap = vector(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(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);
}
diff --git a/src/text_shaper/open_shaper.cpp b/src/text_shaper/open_shaper.cpp
index b3a43f1304..0c72fa88fd 100644
--- a/src/text_shaper/open_shaper.cpp
+++ b/src/text_shaper/open_shaper.cpp
@@ -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,
@@ -747,10 +745,13 @@ optional 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;
@@ -798,18 +799,34 @@ optional open_shaper::rasterize(glyph_key _glyph, render_mode
break;
}
case FT_PIXEL_MODE_LCD: {
- auto const width = static_cast(ftFace->glyph->bitmap.width);
- auto const height = static_cast(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(ftBitmap.width) * static_cast(ftBitmap.rows));
output.bitmapSize.width /= crispy::Width(3);
- auto const pitch = static_cast(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(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: {