diff --git a/metainfo.xml b/metainfo.xml index 02e3cc32d2..0356bde8cc 100644 --- a/metainfo.xml +++ b/metainfo.xml @@ -102,7 +102,7 @@ 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: {