include/vcl/outdev.hxx | 2 ++ vcl/inc/pdf/Matrix3.hxx | 2 ++ vcl/inc/pdf/pdfwriter_impl.hxx | 4 ++-- vcl/source/gdi/pdfwriter_impl.cxx | 31 ++++++++++++++----------------- vcl/source/outdev/map.cxx | 19 +++++++++++++++++++ vcl/source/pdf/Matrix3.cxx | 6 ++++++ 6 files changed, 45 insertions(+), 19 deletions(-)
New commits: commit 38a29acd7e305ec99c4eb1871b9f31f75a3ab80c Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Wed Aug 24 11:32:30 2022 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Thu Aug 25 09:51:12 2022 +0200 use DevicePoint and SubPixelToLogic to return to source coord system Change-Id: I1aeae6270feb6cb0a44b7850e1b3143e68ae780f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138770 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/pdf/Matrix3.hxx b/vcl/inc/pdf/Matrix3.hxx index 795b2af4be52..da88cc31399b 100644 --- a/vcl/inc/pdf/Matrix3.hxx +++ b/vcl/inc/pdf/Matrix3.hxx @@ -11,6 +11,7 @@ #pragma once #include <vcl/dllapi.h> +#include <vcl/devicecoordinate.hxx> #include <tools/gen.hxx> namespace vcl::pdf @@ -45,6 +46,7 @@ public: double get(size_t i) const { return f[i]; } Point transform(const Point& rPoint) const; + DevicePoint transform(const DevicePoint& rPoint) const; }; } diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 4ebddbe5edaf..9af21e81baee 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -579,14 +579,14 @@ struct PDFAddStream // helper structure for drawLayout and friends struct PDFGlyph { - Point const m_aPos; + DevicePoint const m_aPos; const GlyphItem* m_pGlyph; sal_Int32 const m_nNativeWidth; sal_Int32 const m_nMappedFontId; sal_uInt8 const m_nMappedGlyphId; int const m_nCharPos; - PDFGlyph( const Point& rPos, + PDFGlyph( const DevicePoint& rPos, const GlyphItem* pGlyph, sal_Int32 nNativeWidth, sal_Int32 nFontId, diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 48a8b472df03..74b7ccdbcf7d 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -5944,8 +5944,7 @@ void PDFWriterImpl::drawVerticalGlyphs( sal_Int32 nFontHeight ) { tools::Long nXOffset = 0; - Point aCurPos( rGlyphs[0].m_aPos ); - aCurPos = PixelToLogic( aCurPos ); + Point aCurPos(SubPixelToLogic(rGlyphs[0].m_aPos)); aCurPos += rAlignOffset; for( size_t i = 0; i < rGlyphs.size(); i++ ) { @@ -5969,9 +5968,9 @@ void PDFWriterImpl::drawVerticalGlyphs( if( i < rGlyphs.size()-1 ) // #i120627# the text on the Y axis is reversed when export ppt file to PDF format { - tools::Long nOffsetX = rGlyphs[i+1].m_aPos.X() - rGlyphs[i].m_aPos.X(); - tools::Long nOffsetY = rGlyphs[i+1].m_aPos.Y() - rGlyphs[i].m_aPos.Y(); - nXOffset += static_cast<int>(sqrt(double(nOffsetX*nOffsetX + nOffsetY*nOffsetY))); + double nOffsetX = rGlyphs[i+1].m_aPos.getX() - rGlyphs[i].m_aPos.getX(); + double nOffsetY = rGlyphs[i+1].m_aPos.getY() - rGlyphs[i].m_aPos.getY(); + nXOffset += static_cast<int>(sqrt(nOffsetX*nOffsetX + nOffsetY*nOffsetY)); } if (!rGlyphs[i].m_pGlyph->glyphId()) continue; @@ -6022,7 +6021,7 @@ void PDFWriterImpl::drawHorizontalGlyphs( for( size_t i = 1; i < rGlyphs.size(); i++ ) { if( rGlyphs[i].m_nMappedFontId != rGlyphs[i-1].m_nMappedFontId || - rGlyphs[i].m_aPos.Y() != rGlyphs[i-1].m_aPos.Y() ) + rGlyphs[i].m_aPos.getY() != rGlyphs[i-1].m_aPos.getY() ) { aRunEnds.push_back(i); } @@ -6034,10 +6033,8 @@ void PDFWriterImpl::drawHorizontalGlyphs( sal_uInt32 nBeginRun = 0; for( size_t nRun = 0; nRun < aRunEnds.size(); nRun++ ) { - // setup text matrix - Point aCurPos = rGlyphs[nBeginRun].m_aPos; - // back transformation to current coordinate system - aCurPos = PixelToLogic( aCurPos ); + // setup text matrix back transformed to current coordinate system + Point aCurPos(SubPixelToLogic(rGlyphs[nBeginRun].m_aPos)); aCurPos += rAlignOffset; // the first run can be set with "Td" operator // subsequent use of that operator would move @@ -6079,9 +6076,9 @@ void PDFWriterImpl::drawHorizontalGlyphs( { appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine ); // check if default glyph positioning is sufficient - const Point aThisPos = aMat.transform( rGlyphs[nPos].m_aPos ); - const Point aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos ); - double fAdvance = aThisPos.X() - aPrevPos.X(); + const DevicePoint aThisPos = aMat.transform( rGlyphs[nPos].m_aPos ); + const DevicePoint aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos ); + double fAdvance = aThisPos.getX() - aPrevPos.getX(); fAdvance *= 1000.0 / nPixelFontHeight; const double fAdjustment = rGlyphs[nPos-1].m_nNativeWidth - fAdvance + 0.5; SAL_WARN_IF( @@ -6320,7 +6317,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool if (bUseActualText || pGlyph->IsInCluster()) nCharPos = pGlyph->charPos(); - aGlyphs.emplace_back(Point(aPos.getX(), aPos.getY()), + aGlyphs.emplace_back(aPos, pGlyph, nGlyphWidth, nMappedFontObject, diff --git a/vcl/source/pdf/Matrix3.cxx b/vcl/source/pdf/Matrix3.cxx index 475f87d966df..7b225c3a68b4 100644 --- a/vcl/source/pdf/Matrix3.cxx +++ b/vcl/source/pdf/Matrix3.cxx @@ -30,6 +30,12 @@ Point Matrix3::transform(const Point& rOrig) const return Point(x * f[0] + y * f[2] + f[4], x * f[1] + y * f[3] + f[5]); } +DevicePoint Matrix3::transform(const DevicePoint& rOrig) const +{ + double x = rOrig.getX(), y = rOrig.getY(); + return DevicePoint(x * f[0] + y * f[2] + f[4], x * f[1] + y * f[3] + f[5]); +} + void Matrix3::skew(double alpha, double beta) { double fn[6]; commit 241ce1488b8354f6c203d4feaef8a9fed9a3f52c Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Tue Aug 23 17:27:42 2022 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Thu Aug 25 09:50:57 2022 +0200 retain accuracy when we have subpixels and convert back to Logic units Change-Id: If5a8624c1150919cc66f7b7d635edf112b480523 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138738 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 3f00d9dcde12..17d5d87289e9 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1720,6 +1720,8 @@ public: SAL_DLLPRIVATE tools::Long ImplLogicHeightToDevicePixel( tools::Long nHeight ) const; SAL_DLLPRIVATE double ImplLogicHeightToDeviceSubPixel(tools::Long nHeight) const; + SAL_DLLPRIVATE Point SubPixelToLogic(const DevicePoint& rDevicePt) const; + /** Convert device pixels to a width in logical units. To get the logical width, it must calculate the X-DPI of the device and the diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 1881562cc08f..48a8b472df03 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -6344,7 +6344,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool // ascent / descent to match the on-screen rendering. // This is the top left of the text without ascent / descent. DevicePoint aDrawPosition(rLayout.GetDrawPosition()); - tools::Rectangle aRectangle(PixelToLogic(Point(aDrawPosition.getX(), aDrawPosition.getY())), + tools::Rectangle aRectangle(SubPixelToLogic(aDrawPosition), Size(ImplDevicePixelToLogicWidth(rLayout.GetTextWidth()), 0)); aRectangle.AdjustTop(-aRefDevFontMetric.GetAscent()); // This includes ascent / descent. @@ -6355,7 +6355,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool { // Adapt rectangle for rotated text. tools::Polygon aPolygon(aRectangle); - aPolygon.Rotate(PixelToLogic(Point(aDrawPosition.getX(), aDrawPosition.getY())), pFontInstance->mnOrientation); + aPolygon.Rotate(SubPixelToLogic(aDrawPosition), pFontInstance->mnOrientation); drawPolygon(aPolygon); } else @@ -6476,7 +6476,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool { DevicePoint aStartPt = rLayout.GetDrawPosition(); int nWidth = rLayout.GetTextWidth() / rLayout.GetUnitsPerPixel(); - drawTextLine( PixelToLogic(Point(aStartPt.getX(), aStartPt.getY()) ), + drawTextLine( SubPixelToLogic(aStartPt), ImplDevicePixelToLogicWidth( nWidth ), eStrikeout, eUnderline, eOverline, bUnderlineAbove ); } diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index c184b255af2b..a073b1b029bf 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -278,6 +278,14 @@ static double ImplLogicToSubPixel(tools::Long n, tools::Long nDPI, tools::Long n return static_cast<double>(n) * nMapNum * nDPI / nMapDenom; } +static tools::Long ImplSubPixelToLogic(double n, tools::Long nDPI, tools::Long nMapNum, + tools::Long nMapDenom) +{ + assert(nDPI > 0); + assert(nMapNum != 0); + return std::round(n * nMapDenom / nMapNum / nDPI); +} + static tools::Long ImplPixelToLogic(tools::Long n, tools::Long nDPI, tools::Long nMapNum, tools::Long nMapDenom) { @@ -1165,6 +1173,17 @@ Point OutputDevice::PixelToLogic( const Point& rDevicePt ) const maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY ) - maMapRes.mnMapOfsY - mnOutOffLogicY ); } +Point OutputDevice::SubPixelToLogic(const DevicePoint& rDevicePt) const +{ + if (!mbMap) + return Point(rDevicePt.getX(), rDevicePt.getY()); + + return Point(ImplSubPixelToLogic(rDevicePt.getX(), mnDPIX, + maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX) - maMapRes.mnMapOfsX - mnOutOffLogicX, + ImplSubPixelToLogic(rDevicePt.getY(), mnDPIY, + maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY) - maMapRes.mnMapOfsY - mnOutOffLogicY); +} + Size OutputDevice::PixelToLogic( const Size& rDeviceSize ) const {