include/vcl/outdev.hxx | 2 solenv/clang-format/excludelist | 1 vcl/Library_vcl.mk | 1 vcl/inc/font/EmphasisMark.hxx | 45 +++++++++ vcl/qa/cppunit/font.cxx | 71 ++++++++++++++ vcl/source/font/EmphasisMark.cxx | 174 +++++++++++++++++++++++++++++++++++ vcl/source/gdi/pdfwriter_impl.cxx | 45 +++------ vcl/source/outdev/font.cxx | 188 ++------------------------------------ 8 files changed, 319 insertions(+), 208 deletions(-)
New commits: commit 5791c779635b5d42de3c5691bdbadf4a079e096e Author: Chris Sherlock <[email protected]> AuthorDate: Sat Aug 13 17:20:32 2022 +1000 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Wed Sep 7 15:26:55 2022 +0200 vcl: convert ImplGetEmphasisMark() to EmphasisMark class It makes more sense for an emphasis mark to be an object that can be queried, than it is for it to be a function with lots of output parameters. I have added a unit test, note that for now something doesn't seem right with polypolygon equality checks (test fails, but the disc is generated the same way) so not testing the shape creation. Change-Id: I7597603419b69639b8d9764afdb68e266da7a56b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122601 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 1162ef3c116e..66cd10f2a53f 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1133,8 +1133,6 @@ public: bool GetFontFeatures(std::vector<vcl::font::Feature>& rFontFeatures) const; - SAL_DLLPRIVATE void ImplGetEmphasisMark( tools::PolyPolygon& rPolyPoly, bool& rPolyLine, tools::Rectangle& rRect1, tools::Rectangle& rRect2, - tools::Long& rYOff, tools::Long& rWidth, FontEmphasisMark eEmphasis, tools::Long nHeight ); bool GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr, int nIndex, int nLen, std::vector< tools::Rectangle >& rVector ) const; diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index 4802408e4117..d1239f3a09fa 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -14808,6 +14808,7 @@ vcl/source/filter/wmf/wmf.cxx vcl/source/filter/wmf/wmfwr.cxx vcl/source/filter/wmf/wmfwr.hxx vcl/source/font/DirectFontSubstitution.cxx +vcl/source/font/EmphasisMark.cxx vcl/source/font/FontSelectPattern.cxx vcl/source/font/PhysicalFontCollection.cxx vcl/source/font/PhysicalFontFamily.cxx diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index b4135d502b2e..10907d6c420c 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -476,6 +476,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/filter/webp/reader \ vcl/source/filter/webp/writer \ vcl/source/font/DirectFontSubstitution \ + vcl/source/font/EmphasisMark \ vcl/source/font/Feature \ vcl/source/font/FeatureCollector \ vcl/source/font/FeatureParser \ diff --git a/vcl/inc/font/EmphasisMark.hxx b/vcl/inc/font/EmphasisMark.hxx new file mode 100644 index 000000000000..5e902da26294 --- /dev/null +++ b/vcl/inc/font/EmphasisMark.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#pragma once + +#include <sal/config.h> + +#include <tools/fontenum.hxx> +#include <tools/gen.hxx> +#include <tools/long.hxx> +#include <tools/poly.hxx> + +#include <vcl/dllapi.h> + +namespace vcl::font +{ +class VCL_DLLPUBLIC EmphasisMark +{ +public: + EmphasisMark(FontEmphasisMark eEmphasis, tools::Long nHeight, sal_Int32 nDPIY); + + tools::PolyPolygon GetShape() const { return maPolyPoly; } + bool IsShapePolyLine() const { return mbIsPolyLine; } + tools::Rectangle GetRect1() const { return maRect1; } + tools::Rectangle GetRect2() const { return maRect2; } + tools::Long GetYOffset() const { return mnYOff; } + tools::Long GetWidth() const { return mnWidth; } + +private: + tools::PolyPolygon maPolyPoly; + bool mbIsPolyLine; + tools::Rectangle maRect1; + tools::Rectangle maRect2; + tools::Long mnYOff; + tools::Long mnWidth; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/qa/cppunit/font.cxx b/vcl/qa/cppunit/font.cxx index 8023de9d6f07..d989b01cb051 100644 --- a/vcl/qa/cppunit/font.cxx +++ b/vcl/qa/cppunit/font.cxx @@ -12,6 +12,8 @@ #include <vcl/font.hxx> +#include <font/EmphasisMark.hxx> + class VclFontTest : public test::BootstrapFixture { public: @@ -27,6 +29,11 @@ public: void testSymbolFlagAndCharSet(); void testEmphasisMarkShouldBePosAboveWhenSimplifiedChinese(); void testEmphasisMarkShouldBePosAboveWhenNotSimplifiedChinese(); + void testEmphasisMarkInitAsNone(); + void testEmphasisMarkInitAsDot(); + void testEmphasisMarkInitAsDisc(); + void testEmphasisMarkInitAsAccent(); + void testEmphasisMarkInitAsStyle(); CPPUNIT_TEST_SUITE(VclFontTest); CPPUNIT_TEST(testName); @@ -39,6 +46,11 @@ public: CPPUNIT_TEST(testSymbolFlagAndCharSet); CPPUNIT_TEST(testEmphasisMarkShouldBePosAboveWhenSimplifiedChinese); CPPUNIT_TEST(testEmphasisMarkShouldBePosAboveWhenNotSimplifiedChinese); + CPPUNIT_TEST(testEmphasisMarkInitAsNone); + CPPUNIT_TEST(testEmphasisMarkInitAsDot); + CPPUNIT_TEST(testEmphasisMarkInitAsDisc); + CPPUNIT_TEST(testEmphasisMarkInitAsAccent); + CPPUNIT_TEST(testEmphasisMarkInitAsStyle); CPPUNIT_TEST_SUITE_END(); }; @@ -178,6 +190,65 @@ void VclFontTest::testEmphasisMarkShouldBePosAboveWhenNotSimplifiedChinese() CPPUNIT_ASSERT_MESSAGE("Accent mark not kept", (aFont.GetEmphasisMarkStyle() & FontEmphasisMark::Accent)); } +void VclFontTest::testEmphasisMarkInitAsNone() +{ + vcl::font::EmphasisMark aEmphasisMark(FontEmphasisMark::NONE, 5, 96); + + CPPUNIT_ASSERT_MESSAGE("Shape not a polyline", !aEmphasisMark.IsShapePolyLine()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Shape wrong", tools::PolyPolygon(), aEmphasisMark.GetShape()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect1 not correct", tools::Rectangle(), aEmphasisMark.GetRect1()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect2 not correct", tools::Rectangle(), aEmphasisMark.GetRect2()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("y offset wrong", tools::Long(1), aEmphasisMark.GetYOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("width wrong", tools::Long(0), aEmphasisMark.GetWidth()); +} + +void VclFontTest::testEmphasisMarkInitAsDot() +{ + vcl::font::EmphasisMark aEmphasisMark(FontEmphasisMark::Dot, 5, 96); + + CPPUNIT_ASSERT_MESSAGE("Shape not a polyline", !aEmphasisMark.IsShapePolyLine()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Shape wrong", tools::PolyPolygon(), aEmphasisMark.GetShape()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect1 not correct", tools::Rectangle(Point(), Size(2, 2)), aEmphasisMark.GetRect1()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect2 not correct", tools::Rectangle(), aEmphasisMark.GetRect2()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("y offset wrong", tools::Long(3), aEmphasisMark.GetYOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("width wrong", tools::Long(2), aEmphasisMark.GetWidth()); +} + +void VclFontTest::testEmphasisMarkInitAsDisc() +{ + vcl::font::EmphasisMark aEmphasisMark(FontEmphasisMark::Disc, 5, 96); + + CPPUNIT_ASSERT_MESSAGE("Shape not a polyline", !aEmphasisMark.IsShapePolyLine()); +// something wrong with polypolygon equality checking! +// CPPUNIT_ASSERT_EQUAL_MESSAGE("Shape not disc with radius of 2", tools::PolyPolygon(tools::Polygon(Point(2, 2), 2, 2)), aEmphasisMark.GetShape()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect1 not correct", tools::Rectangle(), aEmphasisMark.GetRect1()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect2 not correct", tools::Rectangle(), aEmphasisMark.GetRect2()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("y offset wrong", tools::Long(4), aEmphasisMark.GetYOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("width wrong", tools::Long(4), aEmphasisMark.GetWidth()); +} + +void VclFontTest::testEmphasisMarkInitAsAccent() +{ + vcl::font::EmphasisMark aEmphasisMark(FontEmphasisMark::Accent, 5, 96); + + CPPUNIT_ASSERT_MESSAGE("Shape not a polyline", !aEmphasisMark.IsShapePolyLine()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect1 not correct", tools::Rectangle(), aEmphasisMark.GetRect1()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect2 not correct", tools::Rectangle(), aEmphasisMark.GetRect2()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("y offset wrong", tools::Long(4), aEmphasisMark.GetYOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("width wrong", tools::Long(4), aEmphasisMark.GetWidth()); +} + +void VclFontTest::testEmphasisMarkInitAsStyle() +{ + vcl::font::EmphasisMark aEmphasisMark(FontEmphasisMark::Style, 5, 96); + + CPPUNIT_ASSERT_MESSAGE("Shape not a polyline", !aEmphasisMark.IsShapePolyLine()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect1 not correct", tools::Rectangle(), aEmphasisMark.GetRect1()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Rect2 not correct", tools::Rectangle(), aEmphasisMark.GetRect2()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("y offset wrong", tools::Long(1), aEmphasisMark.GetYOffset()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("width wrong", tools::Long(0), aEmphasisMark.GetWidth()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(VclFontTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/vcl/source/font/EmphasisMark.cxx b/vcl/source/font/EmphasisMark.cxx new file mode 100644 index 000000000000..29093a8109d5 --- /dev/null +++ b/vcl/source/font/EmphasisMark.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <font/EmphasisMark.hxx> + +namespace vcl::font +{ +EmphasisMark::EmphasisMark(FontEmphasisMark eEmphasis, tools::Long nHeight, sal_Int32 nDPIY) +{ + static const PolyFlags aAccentPolyFlags[24] = + { + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Normal, PolyFlags::Control, + PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control + }; + + static const Point aAccentPos[24] = + { + { 78, 0 }, + { 348, 79 }, + { 599, 235 }, + { 843, 469 }, + { 938, 574 }, + { 990, 669 }, + { 990, 773 }, + { 990, 843 }, + { 964, 895 }, + { 921, 947 }, + { 886, 982 }, + { 860, 999 }, + { 825, 999 }, + { 764, 999 }, + { 721, 964 }, + { 686, 895 }, + { 625, 791 }, + { 556, 660 }, + { 469, 504 }, + { 400, 400 }, + { 261, 252 }, + { 61, 61 }, + { 0, 27 }, + { 9, 0 } + }; + + mnWidth = 0; + mnYOff = 0; + mbIsPolyLine = false; + + if ( !nHeight ) + return; + + FontEmphasisMark nEmphasisStyle = eEmphasis & FontEmphasisMark::Style; + tools::Long nDotSize = 0; + switch ( nEmphasisStyle ) + { + case FontEmphasisMark::Dot: + // Dot has 55% of the height + nDotSize = (nHeight*550)/1000; + if ( !nDotSize ) + nDotSize = 1; + if ( nDotSize <= 2 ) + maRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); + else + { + tools::Long nRad = nDotSize/2; + tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); + maPolyPoly.Insert( aPoly ); + } + mnYOff = ((nHeight*250)/1000)/2; // Center to the another EmphasisMarks + mnWidth = nDotSize; + break; + + case FontEmphasisMark::Circle: + // Dot has 80% of the height + nDotSize = (nHeight*800)/1000; + if ( !nDotSize ) + nDotSize = 1; + if ( nDotSize <= 2 ) + maRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); + else + { + tools::Long nRad = nDotSize/2; + tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); + maPolyPoly.Insert( aPoly ); + // BordemnWidth is 15% + tools::Long nBorder = (nDotSize*150)/1000; + if ( nBorder <= 1 ) + mbIsPolyLine = true; + else + { + tools::Polygon aPoly2( Point( nRad, nRad ), + nRad-nBorder, nRad-nBorder ); + maPolyPoly.Insert( aPoly2 ); + } + } + mnWidth = nDotSize; + break; + + case FontEmphasisMark::Disc: + // Dot has 80% of the height + nDotSize = (nHeight*800)/1000; + if ( !nDotSize ) + nDotSize = 1; + if ( nDotSize <= 2 ) + maRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); + else + { + tools::Long nRad = nDotSize/2; + tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); + maPolyPoly.Insert( aPoly ); + } + mnWidth = nDotSize; + break; + + case FontEmphasisMark::Accent: + // Dot has 80% of the height + nDotSize = (nHeight*800)/1000; + if ( !nDotSize ) + nDotSize = 1; + if ( nDotSize <= 2 ) + { + if ( nDotSize == 1 ) + { + maRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); + mnWidth = nDotSize; + } + else + { + maRect1 = tools::Rectangle( Point(), Size( 1, 1 ) ); + maRect2 = tools::Rectangle( Point( 1, 1 ), Size( 1, 1 ) ); + } + } + else + { + tools::Polygon aPoly( SAL_N_ELEMENTS(aAccentPos), aAccentPos, + aAccentPolyFlags ); + double dScale = static_cast<double>(nDotSize)/1000.0; + aPoly.Scale( dScale, dScale ); + tools::Polygon aTemp; + aPoly.AdaptiveSubdivide( aTemp ); + tools::Rectangle aBoundRect = aTemp.GetBoundRect(); + mnWidth = aBoundRect.GetWidth(); + nDotSize = aBoundRect.GetHeight(); + maPolyPoly.Insert( aTemp ); + } + break; + default: break; + } + + // calculate position + tools::Long nOffY = 1+(nDPIY/300); // one visible pixel space + tools::Long nSpaceY = nHeight-nDotSize; + if ( nSpaceY >= nOffY*2 ) + mnYOff += nOffY; + + if ( !(eEmphasis & FontEmphasisMark::PosBelow) ) + mnYOff += nDotSize; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 8ba0f07e9c52..3e01a6c76b9d 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -77,6 +77,7 @@ #include <svdata.hxx> #include <bitmap/BitmapWriteAccess.hxx> #include <fontsubset.hxx> +#include <font/EmphasisMark.hxx> #include <font/PhysicalFontFace.hxx> #include <salgdi.hxx> #include <textlayout.hxx> @@ -6251,7 +6252,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool // // * If there is many to one or many to many mapping, use an // ActualText span embedding the original string, since ToUnicode - // can’t handle these. + // can't handle these. // * If the one glyph is used for several Unicode code points, also // use ActualText since ToUnicode can map each glyph in the font // only once. @@ -6277,7 +6278,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool if (pGlyph->IsInCluster()) assert(aCodeUnits.empty()); - // A glyph can’t have more than one ToUnicode entry, use ActualText + // A glyph can't have more than one ToUnicode entry, use ActualText // instead. if (!aCodeUnits.empty() && !bUseActualText) { @@ -6470,34 +6471,21 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool if( !(m_aCurrentPDFState.m_aFont.GetEmphasisMark() & FontEmphasisMark::Style) ) return; - tools::PolyPolygon aEmphPoly; - tools::Rectangle aEmphRect1; - tools::Rectangle aEmphRect2; - tools::Long nEmphYOff; - tools::Long nEmphWidth; - tools::Long nEmphHeight; - bool bEmphPolyLine; - FontEmphasisMark nEmphMark; - push( PushFlags::ALL ); aLine.setLength( 0 ); aLine.append( "q\n" ); - nEmphMark = m_aCurrentPDFState.m_aFont.GetEmphasisMarkStyle(); + FontEmphasisMark nEmphMark = m_aCurrentPDFState.m_aFont.GetEmphasisMarkStyle(); + + tools::Long nEmphHeight; if ( nEmphMark & FontEmphasisMark::PosBelow ) nEmphHeight = GetEmphasisDescent(); else nEmphHeight = GetEmphasisAscent(); - ImplGetEmphasisMark( aEmphPoly, - bEmphPolyLine, - aEmphRect1, - aEmphRect2, - nEmphYOff, - nEmphWidth, - nEmphMark, - ImplDevicePixelToLogicWidth(nEmphHeight) ); - if ( bEmphPolyLine ) + + vcl::font::EmphasisMark aEmphasisMark(nEmphMark, ImplDevicePixelToLogicWidth(nEmphHeight), GetDPIY()); + if ( aEmphasisMark.IsShapePolyLine() ) { setLineColor( m_aCurrentPDFState.m_aFont.GetColor() ); setFillColor( COL_TRANSPARENT ); @@ -6507,17 +6495,18 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool setFillColor( m_aCurrentPDFState.m_aFont.GetColor() ); setLineColor( COL_TRANSPARENT ); } + writeBuffer( aLine.getStr(), aLine.getLength() ); Point aOffset(0,0); if ( nEmphMark & FontEmphasisMark::PosBelow ) - aOffset.AdjustY(GetFontInstance()->mxFontMetric->GetDescent() + nEmphYOff ); + aOffset.AdjustY(GetFontInstance()->mxFontMetric->GetDescent() + aEmphasisMark.GetYOffset() ); else - aOffset.AdjustY( -(GetFontInstance()->mxFontMetric->GetAscent() + nEmphYOff) ); + aOffset.AdjustY( -(GetFontInstance()->mxFontMetric->GetAscent() + aEmphasisMark.GetYOffset()) ); - tools::Long nEmphWidth2 = nEmphWidth / 2; - tools::Long nEmphHeight2 = nEmphHeight / 2; + tools::Long nEmphWidth2 = aEmphasisMark.GetWidth() / 2; + tools::Long nEmphHeight2 = nEmphHeight / 2; aOffset += Point( nEmphWidth2, nEmphHeight2 ); if ( eAlign == ALIGN_BOTTOM ) @@ -6531,7 +6520,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool if (pGlyph->IsSpacing()) { DevicePoint aAdjOffset(aOffset.X(), aOffset.Y()); - aAdjOffset.adjustX((pGlyph->newWidth() - nEmphWidth) / 2); + aAdjOffset.adjustX((pGlyph->newWidth() - aEmphasisMark.GetWidth()) / 2); aAdjOffset = aRotScale.transform( aAdjOffset ); aAdjOffset -= DevicePoint(nEmphWidth2, nEmphHeight2); @@ -6540,8 +6529,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool aMarkDevPos += aAdjOffset; Point aMarkPos = SubPixelToLogic(aMarkDevPos, bCheckSubPixelToLogic); drawEmphasisMark( aMarkPos.X(), aMarkPos.Y(), - aEmphPoly, bEmphPolyLine, - aEmphRect1, aEmphRect2 ); + aEmphasisMark.GetShape(), aEmphasisMark.IsShapePolyLine(), + aEmphasisMark.GetRect1(), aEmphasisMark.GetRect2() ); } } diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index 56d476e0a8f1..ba3076ac272b 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -35,6 +35,7 @@ #include <vcl/virdev.hxx> #include <window.h> +#include <font/EmphasisMark.hxx> #include <ImplLayoutArgs.hxx> #include <drawmode.hxx> @@ -262,166 +263,6 @@ bool OutputDevice::GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities return mpGraphics->GetFontCapabilities(rFontCapabilities); } -void OutputDevice::ImplGetEmphasisMark( tools::PolyPolygon& rPolyPoly, bool& rPolyLine, - tools::Rectangle& rRect1, tools::Rectangle& rRect2, - tools::Long& rYOff, tools::Long& rWidth, - FontEmphasisMark eEmphasis, - tools::Long nHeight ) -{ - static const PolyFlags aAccentPolyFlags[24] = - { - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Normal, PolyFlags::Control, - PolyFlags::Normal, PolyFlags::Control, PolyFlags::Control - }; - - static const Point aAccentPos[24] = - { - { 78, 0 }, - { 348, 79 }, - { 599, 235 }, - { 843, 469 }, - { 938, 574 }, - { 990, 669 }, - { 990, 773 }, - { 990, 843 }, - { 964, 895 }, - { 921, 947 }, - { 886, 982 }, - { 860, 999 }, - { 825, 999 }, - { 764, 999 }, - { 721, 964 }, - { 686, 895 }, - { 625, 791 }, - { 556, 660 }, - { 469, 504 }, - { 400, 400 }, - { 261, 252 }, - { 61, 61 }, - { 0, 27 }, - { 9, 0 } - }; - - rWidth = 0; - rYOff = 0; - rPolyLine = false; - - if ( !nHeight ) - return; - - FontEmphasisMark nEmphasisStyle = eEmphasis & FontEmphasisMark::Style; - tools::Long nDotSize = 0; - switch ( nEmphasisStyle ) - { - case FontEmphasisMark::Dot: - // Dot has 55% of the height - nDotSize = (nHeight*550)/1000; - if ( !nDotSize ) - nDotSize = 1; - if ( nDotSize <= 2 ) - rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); - else - { - tools::Long nRad = nDotSize/2; - tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); - rPolyPoly.Insert( aPoly ); - } - rYOff = ((nHeight*250)/1000)/2; // Center to the another EmphasisMarks - rWidth = nDotSize; - break; - - case FontEmphasisMark::Circle: - // Dot has 80% of the height - nDotSize = (nHeight*800)/1000; - if ( !nDotSize ) - nDotSize = 1; - if ( nDotSize <= 2 ) - rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); - else - { - tools::Long nRad = nDotSize/2; - tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); - rPolyPoly.Insert( aPoly ); - // BorderWidth is 15% - tools::Long nBorder = (nDotSize*150)/1000; - if ( nBorder <= 1 ) - rPolyLine = true; - else - { - tools::Polygon aPoly2( Point( nRad, nRad ), - nRad-nBorder, nRad-nBorder ); - rPolyPoly.Insert( aPoly2 ); - } - } - rWidth = nDotSize; - break; - - case FontEmphasisMark::Disc: - // Dot has 80% of the height - nDotSize = (nHeight*800)/1000; - if ( !nDotSize ) - nDotSize = 1; - if ( nDotSize <= 2 ) - rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); - else - { - tools::Long nRad = nDotSize/2; - tools::Polygon aPoly( Point( nRad, nRad ), nRad, nRad ); - rPolyPoly.Insert( aPoly ); - } - rWidth = nDotSize; - break; - - case FontEmphasisMark::Accent: - // Dot has 80% of the height - nDotSize = (nHeight*800)/1000; - if ( !nDotSize ) - nDotSize = 1; - if ( nDotSize <= 2 ) - { - if ( nDotSize == 1 ) - { - rRect1 = tools::Rectangle( Point(), Size( nDotSize, nDotSize ) ); - rWidth = nDotSize; - } - else - { - rRect1 = tools::Rectangle( Point(), Size( 1, 1 ) ); - rRect2 = tools::Rectangle( Point( 1, 1 ), Size( 1, 1 ) ); - } - } - else - { - tools::Polygon aPoly( SAL_N_ELEMENTS(aAccentPos), aAccentPos, - aAccentPolyFlags ); - double dScale = static_cast<double>(nDotSize)/1000.0; - aPoly.Scale( dScale, dScale ); - tools::Polygon aTemp; - aPoly.AdaptiveSubdivide( aTemp ); - tools::Rectangle aBoundRect = aTemp.GetBoundRect(); - rWidth = aBoundRect.GetWidth(); - nDotSize = aBoundRect.GetHeight(); - rPolyPoly.Insert( aTemp ); - } - break; - default: break; - } - - // calculate position - tools::Long nOffY = 1+(mnDPIY/300); // one visible pixel space - tools::Long nSpaceY = nHeight-nDotSize; - if ( nSpaceY >= nOffY*2 ) - rYOff += nOffY; - if ( !(eEmphasis & FontEmphasisMark::PosBelow) ) - rYOff += nDotSize; -} - tools::Long OutputDevice::GetFontExtLeading() const { return mpFontInstance->mxFontMetric->GetExternalLeading(); @@ -1077,26 +918,16 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) EnableMapMode( false ); FontEmphasisMark nEmphasisMark = maFont.GetEmphasisMarkStyle(); - tools::PolyPolygon aPolyPoly; - tools::Rectangle aRect1; - tools::Rectangle aRect2; - tools::Long nEmphasisYOff; - tools::Long nEmphasisWidth; - tools::Long nEmphasisHeight; - bool bPolyLine; + tools::Long nEmphasisHeight; if ( nEmphasisMark & FontEmphasisMark::PosBelow ) nEmphasisHeight = mnEmphasisDescent; else nEmphasisHeight = mnEmphasisAscent; - ImplGetEmphasisMark( aPolyPoly, bPolyLine, - aRect1, aRect2, - nEmphasisYOff, nEmphasisWidth, - nEmphasisMark, - nEmphasisHeight ); + vcl::font::EmphasisMark aEmphasisMark(nEmphasisMark, nEmphasisHeight, GetDPIY()); - if ( bPolyLine ) + if (aEmphasisMark.IsShapePolyLine()) { SetLineColor( GetTextColor() ); SetFillColor(); @@ -1110,11 +941,11 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) Point aOffset(0,0); if ( nEmphasisMark & FontEmphasisMark::PosBelow ) - aOffset.AdjustY(mpFontInstance->mxFontMetric->GetDescent() + nEmphasisYOff ); + aOffset.AdjustY(mpFontInstance->mxFontMetric->GetDescent() + aEmphasisMark.GetYOffset()); else - aOffset.AdjustY( -(mpFontInstance->mxFontMetric->GetAscent() + nEmphasisYOff) ); + aOffset.AdjustY(-(mpFontInstance->mxFontMetric->GetAscent() + aEmphasisMark.GetYOffset())); - tools::Long nEmphasisWidth2 = nEmphasisWidth / 2; + tools::Long nEmphasisWidth2 = aEmphasisMark.GetWidth() / 2; tools::Long nEmphasisHeight2 = nEmphasisHeight / 2; aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 ); @@ -1131,7 +962,7 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) if (!pGlyph->IsSpacing()) { Point aAdjPoint = aOffset; - aAdjPoint.AdjustX(aRectangle.Left() + (aRectangle.GetWidth() - nEmphasisWidth) / 2 ); + aAdjPoint.AdjustX(aRectangle.Left() + (aRectangle.GetWidth() - aEmphasisMark.GetWidth()) / 2 ); if ( mpFontInstance->mnOrientation ) { Point aOriginPt(0, 0); @@ -1141,7 +972,8 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) aOutPoint.adjustY(aAdjPoint.Y() - nEmphasisHeight2); ImplDrawEmphasisMark( rSalLayout.DrawBase().getX(), aOutPoint.getX(), aOutPoint.getY(), - aPolyPoly, bPolyLine, aRect1, aRect2 ); + aEmphasisMark.GetShape(), aEmphasisMark.IsShapePolyLine(), + aEmphasisMark.GetRect1(), aEmphasisMark.GetRect2() ); } }
