2022-10-19 11:20:19 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sal/config.h>
|
|
|
|
|
|
|
|
#include <test/bootstrapfixture.hxx>
|
|
|
|
#include <cppunit/TestAssert.h>
|
|
|
|
|
|
|
|
#include <vcl/virdev.hxx>
|
|
|
|
#include <vcl/font.hxx>
|
|
|
|
|
|
|
|
#include <font/LogicalFontInstance.hxx>
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
class VclLogicalFontInstanceTest : public test::BootstrapFixture
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VclLogicalFontInstanceTest()
|
|
|
|
: BootstrapFixture(true, false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void testglyphboundrect();
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE(VclLogicalFontInstanceTest);
|
|
|
|
CPPUNIT_TEST(testglyphboundrect);
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
};
|
|
|
|
|
|
|
|
void VclLogicalFontInstanceTest::testglyphboundrect()
|
|
|
|
{
|
2023-02-06 18:14:16 +02:00
|
|
|
ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
|
2022-10-19 11:20:19 +02:00
|
|
|
device->SetOutputSizePixel(Size(1000, 1000));
|
2024-05-10 13:19:35 +02:00
|
|
|
vcl::Font font(u"Liberation Sans"_ustr, Size(0, 110));
|
tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle
... 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 <quikee@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-03-29 20:15:06 +05:00
|
|
|
device->SetFont(font);
|
2022-10-19 11:20:19 +02:00
|
|
|
|
|
|
|
const LogicalFontInstance* pFontInstance = device->GetFontInstance();
|
|
|
|
|
tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle
... 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 <quikee@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-03-29 20:15:06 +05:00
|
|
|
basegfx::B2DRectangle aBoundRect;
|
2022-10-19 11:20:19 +02:00
|
|
|
const auto LATIN_SMALL_LETTER_B = 0x0062;
|
2024-03-31 00:45:25 +05:00
|
|
|
const auto SECTION_SIGN = 0x00A7; // UTR#50: Vertical_Orientation (vo) property value U
|
2022-10-19 11:20:19 +02:00
|
|
|
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(LATIN_SMALL_LETTER_B), aBoundRect,
|
|
|
|
false);
|
|
|
|
|
tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle
... 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 <quikee@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-03-29 20:15:06 +05:00
|
|
|
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);
|
2022-10-19 11:20:19 +02:00
|
|
|
|
2024-03-31 00:45:25 +05:00
|
|
|
// tdf#160436: test vertically oriented glyphs
|
|
|
|
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), aBoundRect, true);
|
|
|
|
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-79.7, aBoundRect.getMinX(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-55.0, aBoundRect.getMinY(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(88.9, aBoundRect.getWidth(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(48.8, aBoundRect.getHeight(), 0.05);
|
|
|
|
|
tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle
... 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 <quikee@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-03-29 20:15:06 +05:00
|
|
|
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);
|
|
|
|
|
2024-03-31 00:45:25 +05:00
|
|
|
// tdf#160436: test vertically oriented glyphs
|
|
|
|
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), aBoundRect, true);
|
|
|
|
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-55.0, aBoundRect.getMinX(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-9.2, aBoundRect.getMinY(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(48.8, aBoundRect.getWidth(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(88.9, aBoundRect.getHeight(), 0.05);
|
|
|
|
|
tdf#160430: Fix glyph bounds calculation, and use basegfx::B2DRectangle
... 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 <quikee@gmail.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-03-29 20:15:06 +05:00
|
|
|
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);
|
2024-03-31 00:45:25 +05:00
|
|
|
|
|
|
|
// tdf#160436: test vertically oriented glyphs
|
|
|
|
pFontInstance->GetGlyphBoundRect(pFontInstance->GetGlyphIndex(SECTION_SIGN), aBoundRect, true);
|
|
|
|
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-95.3, aBoundRect.getMinX(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(-45.4, aBoundRect.getMinY(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(97.4, aBoundRect.getWidth(), 0.05);
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(97.4, aBoundRect.getHeight(), 0.05);
|
2022-10-19 11:20:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(VclLogicalFontInstanceTest);
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|