summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx51
-rw-r--r--include/vcl/outdev.hxx5
-rw-r--r--include/vcl/vcllayout.hxx6
-rw-r--r--sd/qa/unit/PNGExportTests.cxx61
-rw-r--r--sd/qa/unit/data/svg/tdf162259.svg15
-rw-r--r--sw/source/uibase/sidebar/QuickFindPanel.cxx2
-rw-r--r--vcl/inc/win/winlayout.hxx2
-rw-r--r--vcl/source/outdev/text.cxx1
-rw-r--r--vcl/win/gdi/DWriteTextRenderer.cxx21
-rw-r--r--vcl/win/gdi/winlayout.cxx8
10 files changed, 127 insertions, 45 deletions
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 3da588b1a096..718c725fc88f 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -397,6 +397,25 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
/ (aResultFontSize.Width() ? aResultFontSize.Width()
: aResultFontSize.Height());
+#ifdef _WIN32
+ if (aResultFontSize.Width()
+ && aResultFontSize.Width() != aResultFontSize.Height())
+ {
+ // See getVclFontFromFontAttribute in drawinglayer/source/primitive2d/textlayoutdevice.cxx
+ vcl::Font aUnscaledTest(aFont);
+ aUnscaledTest.SetFontSize({ 0, aResultFontSize.Height() });
+ const FontMetric aUnscaledFontMetric(
+ Application::GetDefaultDevice()->GetFontMetric(aUnscaledTest));
+ if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
+ {
+ double nExistingXScale = static_cast<double>(aResultFontSize.Width())
+ / aUnscaledFontMetric.GetAverageFontWidth();
+ nFontScalingFixX
+ = aFontScaling.getX() / aFontScaling.getY() / nExistingXScale;
+ }
+ }
+#endif
+
if (!rtl_math_approxEqual(nFontScalingFixY, 1.0)
|| !rtl_math_approxEqual(nFontScalingFixX, 1.0))
{
@@ -431,25 +450,21 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
mpOutputDevice->SetFont(aFont);
mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+ if (!aDXArray.empty())
{
- // For D2DWriteTextOutRenderer, we must pass a flag to not use font scaling
- auto guard = mpOutputDevice->ScopedNoFontScaling();
- if (!aDXArray.empty())
- {
- const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
- mpOutputDevice, rTextCandidate.getText(), rTextCandidate.getTextPosition(),
- rTextCandidate.getTextLength());
- mpOutputDevice->DrawTextArray(
- aStartPoint, rTextCandidate.getText(), aDXArray,
- rTextCandidate.getKashidaArray(), rTextCandidate.getTextPosition(),
- rTextCandidate.getTextLength(), SalLayoutFlags::NONE, pGlyphs);
- }
- else
- {
- mpOutputDevice->DrawText(aStartPoint, rTextCandidate.getText(),
- rTextCandidate.getTextPosition(),
- rTextCandidate.getTextLength());
- }
+ const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+ mpOutputDevice, rTextCandidate.getText(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
+ mpOutputDevice->DrawTextArray(
+ aStartPoint, rTextCandidate.getText(), aDXArray,
+ rTextCandidate.getKashidaArray(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength(), SalLayoutFlags::NONE, pGlyphs);
+ }
+ else
+ {
+ mpOutputDevice->DrawText(aStartPoint, rTextCandidate.getText(),
+ rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
}
// Restore previous layout mode
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 2fddb3c3f24a..e353acd2938e 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -21,7 +21,6 @@
#include <sal/config.h>
-#include <comphelper/flagguard.hxx>
#include <tools/gen.hxx>
#include <tools/ref.hxx>
#include <tools/solar.h>
@@ -267,8 +266,6 @@ private:
mutable bool mbRefPoint : 1;
mutable bool mbEnableRTL : 1;
- bool mbNoFontScaling = false; // Used only by D2DWriteTextOutRenderer
-
protected:
mutable std::shared_ptr<vcl::font::PhysicalFontCollection> mxFontCollection;
mutable std::shared_ptr<ImplFontCache> mxFontCache;
@@ -351,8 +348,6 @@ public:
/// request XSpriteCanvas render interface
css::uno::Reference< css::rendering::XSpriteCanvas > GetSpriteCanvas() const;
- auto ScopedNoFontScaling() { return comphelper::FlagRestorationGuard(mbNoFontScaling, true); }
-
protected:
/** Acquire a graphics device that the output device uses to draw on.
diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index 9370c69ded2e..dd0747eae3ec 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -22,7 +22,6 @@
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/range/b2drectangle.hxx>
-#include <comphelper/flagguard.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <tools/gen.hxx>
#include <tools/degree.hxx>
@@ -121,9 +120,6 @@ public:
virtual SalLayoutGlyphs GetGlyphs() const;
- auto ScopedFontScaling(bool v) { return comphelper::FlagRestorationGuard(mbScaleFont, v); }
- bool ScaleFont() const { return mbScaleFont; }
-
protected:
// used by layout engines
SalLayout();
@@ -132,8 +128,6 @@ private:
SalLayout(const SalLayout&) = delete;
SalLayout& operator=(const SalLayout&) = delete;
- bool mbScaleFont = true; // Used only by D2DWriteTextOutRenderer
-
protected:
int mnMinCharPos;
int mnEndCharPos;
diff --git a/sd/qa/unit/PNGExportTests.cxx b/sd/qa/unit/PNGExportTests.cxx
index c2af95329ca2..78135e3a5eba 100644
--- a/sd/qa/unit/PNGExportTests.cxx
+++ b/sd/qa/unit/PNGExportTests.cxx
@@ -941,4 +941,65 @@ CPPUNIT_TEST_FIXTURE(SdPNGExportTest, testTdf155048)
}
}
+CPPUNIT_TEST_FIXTURE(SdPNGExportTest, testTdf162259)
+{
+ // The top X in the SVG, having no skew, used a fast rendering path, and was output much wider
+ // than the bottom one, which has a skew. Test the rendered pixels inside the known boundaries.
+
+ loadFromFile(u"svg/tdf162259.svg");
+
+ auto xGraphicExporter = drawing::GraphicExportFilter::create(getComponentContext());
+ CPPUNIT_ASSERT(xGraphicExporter);
+
+ auto xSupplier = mxComponent.queryThrow<css::drawing::XDrawPagesSupplier>();
+ auto xPage = xSupplier->getDrawPages()->getByIndex(0).queryThrow<css::lang::XComponent>();
+ xGraphicExporter->setSourceDocument(xPage);
+
+ // 101 x 151 is current width x height ratio of the loaded SVG. FIXME: it should be 100 x 150.
+ css::uno::Sequence<css::beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue(u"PixelWidth"_ustr, sal_Int32(101)),
+ comphelper::makePropertyValue(u"PixelHeight"_ustr, sal_Int32(151)),
+ };
+
+ css::uno::Sequence<css::beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue(u"URL"_ustr, maTempFile.GetURL()),
+ comphelper::makePropertyValue(u"FilterName"_ustr, u"PNG"_ustr),
+ comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData)
+ };
+
+ xGraphicExporter->filter(aDescriptor);
+ BitmapEx bmp = vcl::PngImageReader(*maTempFile.GetStream(StreamMode::READ)).read();
+
+ tools::Rectangle topX(12, 21, 37, 60);
+ int topNonWhites = 0;
+ tools::Rectangle bottomX(13, 83, 37, 126);
+ int bottomNonWhites = 0;
+
+ // Check that there is nothing outside the X recrangles
+ for (tools::Long x = 0; x < bmp.GetSizePixel().Width(); ++x)
+ {
+ for (tools::Long y = 0; y < bmp.GetSizePixel().Height(); ++y)
+ {
+ if (topX.Contains(Point{ x, y }))
+ {
+ if (bmp.GetPixelColor(x, y) != COL_WHITE)
+ ++topNonWhites;
+ }
+ else if (bottomX.Contains(Point{ x, y }))
+ {
+ if (bmp.GetPixelColor(x, y) != COL_WHITE)
+ ++bottomNonWhites;
+ }
+ else
+ {
+ OString msg("Pixel: "_ostr + OString::number(x) + "," + OString::number(y));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), COL_WHITE, bmp.GetPixelColor(x, y));
+ }
+ }
+ }
+
+ CPPUNIT_ASSERT_GREATER(350, topNonWhites); // 399 in my testing
+ CPPUNIT_ASSERT_GREATER(350, bottomNonWhites); // 362 in my testing
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/qa/unit/data/svg/tdf162259.svg b/sd/qa/unit/data/svg/tdf162259.svg
new file mode 100644
index 000000000000..96e7bd930c8d
--- /dev/null
+++ b/sd/qa/unit/data/svg/tdf162259.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="150" viewBox="0 0 100 150">
+ <g>
+ <text style="font-size:5.9px;font-family:Liberation Serif"
+ transform="scale(6,10)"
+ x="2" y="6">
+ <tspan>X</tspan>
+ </text>
+ <text style="font-size:5.9px;font-family:Liberation Serif"
+ transform="scale(6,10) skewY(5)"
+ x="2" y="12">
+ <tspan>X</tspan>
+ </text>
+ </g>
+</svg>
diff --git a/sw/source/uibase/sidebar/QuickFindPanel.cxx b/sw/source/uibase/sidebar/QuickFindPanel.cxx
index 4da7639ca8c2..0df67a256742 100644
--- a/sw/source/uibase/sidebar/QuickFindPanel.cxx
+++ b/sw/source/uibase/sidebar/QuickFindPanel.cxx
@@ -10,6 +10,8 @@
#include "QuickFindPanel.hxx"
#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <comphelper/scopeguard.hxx>
#include <svl/srchitem.hxx>
#include <view.hxx>
#include <swmodule.hxx>
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 31066a7db28a..cfb36e825b54 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -36,6 +36,8 @@ class WinFontInstance : public LogicalFontInstance
public:
~WinFontInstance() override;
+ float getHScale() const;
+
void SetGraphics(WinSalGraphics*);
WinSalGraphics* GetGraphics() const { return m_pGraphics; }
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 2d41dd412888..8bbd12160bd1 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -449,7 +449,6 @@ void OutputDevice::ImplDrawSpecialText( SalLayout& rSalLayout )
void OutputDevice::ImplDrawText( SalLayout& rSalLayout )
{
- auto guard = rSalLayout.ScopedFontScaling(!mbNoFontScaling);
if( mbInitClipRegion )
InitClipRegion();
if( mbOutputClipped )
diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx
index 1731a1e4c379..f25fe80cd79d 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -99,7 +99,7 @@ HRESULT checkResult(HRESULT hr, const char* location)
class WinFontTransformGuard
{
public:
- WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget,
+ WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget, float hscale,
const GenericSalLayout& rLayout, const D2D1_POINT_2F& rBaseline,
bool bIsVertical);
~WinFontTransformGuard();
@@ -247,17 +247,18 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
{
mpRT->BeginDraw();
+ const float hscale = rWinFont.getHScale();
int nStart = 0;
basegfx::B2DPoint aPos;
const GlyphItem* pGlyph;
while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
{
UINT16 glyphIndices[] = { static_cast<UINT16>(pGlyph->glyphId()) };
- FLOAT glyphAdvances[] = { static_cast<FLOAT>(pGlyph->newWidth()) };
+ FLOAT glyphAdvances[] = { static_cast<FLOAT>(pGlyph->newWidth()) / hscale };
DWRITE_GLYPH_OFFSET glyphOffsets[] = { { 0.0f, 0.0f }, };
- D2D1_POINT_2F baseline = { static_cast<FLOAT>(aPos.getX() - bounds.Left()),
+ D2D1_POINT_2F baseline = { static_cast<FLOAT>(aPos.getX() - bounds.Left()) / hscale,
static_cast<FLOAT>(aPos.getY() - bounds.Top()) };
- WinFontTransformGuard aTransformGuard(mpRT, rLayout, baseline, pGlyph->IsVertical());
+ WinFontTransformGuard aTransformGuard(mpRT, hscale, rLayout, baseline, pGlyph->IsVertical());
DWRITE_GLYPH_RUN glyphs = {
pFontFace,
lfEmHeight,
@@ -305,22 +306,12 @@ IDWriteFontFace* D2DWriteTextOutRenderer::GetDWriteFace(const WinFontInstance& r
return pFontFace;
}
-WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget,
+WinFontTransformGuard::WinFontTransformGuard(ID2D1RenderTarget* pRenderTarget, float hscale,
const GenericSalLayout& rLayout,
const D2D1_POINT_2F& rBaseline,
bool bIsVertical)
: mpRenderTarget(pRenderTarget)
{
- const float hscale = [&rLayout]
- {
- if (!rLayout.ScaleFont())
- return 1.0;
- const auto& rPattern = rLayout.GetFont().GetFontSelectPattern();
- if (!rPattern.mnHeight || !rPattern.mnWidth)
- return 1.0;
- return rPattern.mnWidth * rLayout.GetFont().GetAverageWidthFactor() / rPattern.mnHeight;
- }();
-
Degree10 angle = rLayout.GetOrientation();
if (bIsVertical)
angle += 900_deg10;
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 0c64759e1ab8..19eaae2ecee7 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -146,6 +146,14 @@ WinFontInstance::~WinFontInstance()
::DeleteFont(m_hFont);
}
+float WinFontInstance::getHScale() const
+{
+ const vcl::font::FontSelectPattern& rPattern = GetFontSelectPattern();
+ if (!rPattern.mnHeight || !rPattern.mnWidth)
+ return 1.0;
+ return rPattern.mnWidth * GetAverageWidthFactor() / rPattern.mnHeight;
+}
+
void WinFontInstance::ImplInitHbFont(hb_font_t* /*pHbFont*/)
{
assert(m_pGraphics);