From 6f4a949c07eb06345df08c722f8e59e97888a499 Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Fri, 29 Mar 2024 20:15:06 +0500 Subject: tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... instead of tools::Rectangle. Several problems were there: 1. First, a horizontal bounding rectangle was calculated, with due rounding; and then the result was rotated, and after that, rounded again. That made the resulting rotated rectangle coordinates very imprecise. 2. Also, ceil/floor was applied without normalization; and in case of rotated font, that meant, that sometimes the range could be not expanded to cover partially covered pixels, but instead collapsed. 3. The rotation to angles other than 90 degree multiples was done incorrectly, resulting in cut off parts of characters. 4. For 90 degrees, the imprecise result of sin/cos converted 0.0 into values like 3e-16, which then could be ceil'ed up to 1. Using B2DRectangle and its transform allows to simplify and fix the calculations easily, and avoids premature rounding. Render of rotated text of small size is more stable with this change. Change-Id: Idffd74b9937feb2418ab76a8d325fdaf4ff841b7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165553 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl Reviewed-by: Mike Kaganski (cherry picked from commit 8962141a12c966b2d891829925e6203bf8d51852) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165619 Reviewed-by: Xisco Fauli --- vcl/qa/cppunit/logicalfontinstance.cxx | 43 +++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'vcl/qa/cppunit') diff --git a/vcl/qa/cppunit/logicalfontinstance.cxx b/vcl/qa/cppunit/logicalfontinstance.cxx index 6d5bbc4dafda..2a0e30d50c34 100644 --- a/vcl/qa/cppunit/logicalfontinstance.cxx +++ b/vcl/qa/cppunit/logicalfontinstance.cxx @@ -39,25 +39,46 @@ void VclLogicalFontInstanceTest::testglyphboundrect() { ScopedVclPtr device = VclPtr::Create(DeviceFormat::WITHOUT_ALPHA); device->SetOutputSizePixel(Size(1000, 1000)); - device->SetFont(vcl::Font("Liberation Sans", Size(0, 110))); + vcl::Font font("Liberation Sans", Size(0, 110)); + device->SetFont(font); const LogicalFontInstance* pFontInstance = device->GetFontInstance(); - tools::Rectangle aBoundRect; + basegfx::B2DRectangle aBoundRect; const auto LATIN_SMALL_LETTER_B = 0x0062; pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B), aBoundRect, false); - const tools::Long nExpectedX = 7; - const tools::Long nExpectedY = -80; - const tools::Long nExpectedWidth = 51; - const tools::Long nExpectedHeight = 83; + CPPUNIT_ASSERT_DOUBLES_EQUAL(7.1, aBoundRect.getMinX(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinY(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getWidth(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getHeight(), 0.05); - CPPUNIT_ASSERT_EQUAL_MESSAGE("x of glyph is wrong", nExpectedX, aBoundRect.getX()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("y of glyph is wrong", nExpectedY, aBoundRect.getY()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("height of glyph of wrong", nExpectedWidth, aBoundRect.GetWidth()); - CPPUNIT_ASSERT_EQUAL_MESSAGE("width of glyph of wrong", nExpectedHeight, - aBoundRect.GetHeight()); + font.SetOrientation(900_deg10); + device->SetFont(font); + + pFontInstance = device->GetFontInstance(); + + pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B), aBoundRect, + false); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinX(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-56.6, aBoundRect.getMinY(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(80.8, aBoundRect.getWidth(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(49.5, aBoundRect.getHeight(), 0.05); + + font.SetOrientation(450_deg10); + device->SetFont(font); + + pFontInstance = device->GetFontInstance(); + + pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B), aBoundRect, + false); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(-51.3, aBoundRect.getMinX(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-96.4, aBoundRect.getMinY(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getWidth(), 0.05); + CPPUNIT_ASSERT_DOUBLES_EQUAL(92.1, aBoundRect.getHeight(), 0.05); } CPPUNIT_TEST_SUITE_REGISTRATION(VclLogicalFontInstanceTest); -- cgit