From ee21771db0292315ff3e1b87ff58294335106bd3 Mon Sep 17 00:00:00 2001 From: Vort Date: Fri, 16 Jan 2015 18:29:40 +0200 Subject: fdo#88465 PDF Import: fix scale and rotate image transformations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I64bb088320099303b0da6d272c3cd6a9ba954f87 Reviewed-on: https://gerrit.libreoffice.org/13957 Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara --- sdext/source/pdfimport/tree/drawtreevisiting.cxx | 85 +++++++++-------------- sdext/source/pdfimport/tree/pdfiprocessor.cxx | 88 +++++++----------------- 2 files changed, 56 insertions(+), 117 deletions(-) (limited to 'sdext/source') diff --git a/sdext/source/pdfimport/tree/drawtreevisiting.cxx b/sdext/source/pdfimport/tree/drawtreevisiting.cxx index 2194ad726972..67f491283ff7 100644 --- a/sdext/source/pdfimport/tree/drawtreevisiting.cxx +++ b/sdext/source/pdfimport/tree/drawtreevisiting.cxx @@ -190,74 +190,55 @@ void DrawXmlEmitter::fillFrameProps( DrawElement& rElem, bool bWasTransformed ) { - double rel_x = rElem.x, rel_y = rElem.y; - rProps[ "draw:z-index" ] = OUString::number( rElem.ZOrder ); rProps[ "draw:style-name"] = rEmitContext.rStyles.getStyleName( rElem.StyleId ); - rProps[ "svg:width" ] = convertPixelToUnitString( rElem.w ); - rProps[ "svg:height" ] = convertPixelToUnitString( rElem.h ); if (rElem.IsForText) rProps["draw:text-style-name"] = rEmitContext.rStyles.getStyleName(rElem.TextStyleId); const GraphicsContext& rGC = rEmitContext.rProcessor.getGraphicsContext( rElem.GCId ); - if( rGC.Transformation.isIdentity() || bWasTransformed ) + + if (bWasTransformed) { - rProps[ "svg:x" ] = convertPixelToUnitString( rel_x ); - rProps[ "svg:y" ] = convertPixelToUnitString( rel_y ); + rProps[ "svg:x" ] = convertPixelToUnitString(rElem.x); + rProps[ "svg:y" ] = convertPixelToUnitString(rElem.y); + rProps[ "svg:width" ] = convertPixelToUnitString(rElem.w); + rProps[ "svg:height" ] = convertPixelToUnitString(rElem.h); } else { - basegfx::B2DTuple aScale, aTranslation; - double fRotate, fShearX; - - rGC.Transformation.decompose( aScale, aTranslation, fRotate, fShearX ); - - OUStringBuffer aBuf( 256 ); - - // TODO(F2): general transformation case missing; if implemented, note - // that ODF rotation is oriented the other way + OUStringBuffer aBuf(256); - // vertical mirroring is done by horizontally mirroring and rotaing 180 degree - // quaint ! - if( rElem.MirrorVertical ) - fRotate += M_PI; + basegfx::B2DHomMatrix mat(rGC.Transformation); - // First check here is to skip image frame case - if (rElem.IsForText && - (aScale.getX() < 0) && - (aScale.getY() > 0) && - (basegfx::fTools::equalZero(aScale.getX() + aScale.getY(), 0.0001))) + if (rElem.MirrorVertical) { - fRotate += M_PI; + basegfx::B2DHomMatrix mat2; + mat2.translate(-0.5, -0.5); + mat2.scale(-1, -1); + mat2.translate(0.5, 0.5); + mat = mat * mat2; } - // build transformation string - if( fShearX != 0.0 ) - { - aBuf.appendAscii( "skewX( " ); - aBuf.append( fShearX ); - aBuf.appendAscii( " )" ); - } - if( fRotate != 0.0 ) - { - if( !aBuf.isEmpty() ) - aBuf.append( ' ' ); - aBuf.appendAscii( "rotate( " ); - aBuf.append( -fRotate ); - aBuf.appendAscii( " )" ); - - } - if( !aBuf.isEmpty() ) - aBuf.append( ' ' ); - aBuf.appendAscii( "translate( " ); - aBuf.append( convertPixelToUnitString( rel_x ) ); - aBuf.append( ' ' ); - aBuf.append( convertPixelToUnitString( rel_y ) ); - aBuf.appendAscii( " )" ); - - rProps[ "draw:transform" ] = aBuf.makeStringAndClear(); + double scale = convPx2mm(100); + mat.scale(scale, scale); + + aBuf.appendAscii("matrix("); + aBuf.append(mat.get(0, 0)); + aBuf.append(' '); + aBuf.append(mat.get(1, 0)); + aBuf.append(' '); + aBuf.append(mat.get(0, 1)); + aBuf.append(' '); + aBuf.append(mat.get(1, 1)); + aBuf.append(' '); + aBuf.append(mat.get(0, 2)); + aBuf.append(' '); + aBuf.append(mat.get(1, 2)); + aBuf.appendAscii(")"); + + rProps["draw:transform"] = aBuf.makeStringAndClear(); } } @@ -905,7 +886,7 @@ void DrawXmlFinalizer::visit( TextElement& elem, const std::list< Element* >::co double fRotate, fShearX; basegfx::B2DTuple aScale, aTranslation; rGC.Transformation.decompose(aScale, aTranslation, fRotate, fShearX); - double textScale = -100 * aScale.getX() / aScale.getY(); + double textScale = 100 * aScale.getX() / aScale.getY(); if (((textScale >= 1) && (textScale <= 99)) || ((textScale >= 101) && (textScale <= 999))) { diff --git a/sdext/source/pdfimport/tree/pdfiprocessor.cxx b/sdext/source/pdfimport/tree/pdfiprocessor.cxx index 37f412631013..87eda4e36929 100644 --- a/sdext/source/pdfimport/tree/pdfiprocessor.cxx +++ b/sdext/source/pdfimport/tree/pdfiprocessor.cxx @@ -282,15 +282,22 @@ void PDFIProcessor::drawGlyphs( const OUString& rGlyphs, { double ascent = getFont(getCurrentContext().FontId).ascent; - double ascentdx = rFontMatrix.m01 * ascent * fontSize; - double ascentdy = rFontMatrix.m11 * ascent * fontSize; - - basegfx::B2DHomMatrix totalTextMatrix1( - rFontMatrix.m00, rFontMatrix.m01, rRect.X1 + ascentdx, - rFontMatrix.m10, rFontMatrix.m11, rRect.Y1 + ascentdy); - basegfx::B2DHomMatrix totalTextMatrix2( - rFontMatrix.m00, rFontMatrix.m01, rRect.X2 + ascentdx, - rFontMatrix.m10, rFontMatrix.m11, rRect.Y2 + ascentdy); + basegfx::B2DHomMatrix fontMatrix( + rFontMatrix.m00, rFontMatrix.m01, 0.0, + rFontMatrix.m10, rFontMatrix.m11, 0.0); + fontMatrix.scale(fontSize, fontSize); + + basegfx::B2DHomMatrix totalTextMatrix1(fontMatrix); + basegfx::B2DHomMatrix totalTextMatrix2(fontMatrix); + totalTextMatrix1.translate(rRect.X1, rRect.Y1); + totalTextMatrix2.translate(rRect.X2, rRect.Y2); + + basegfx::B2DHomMatrix corrMatrix; + corrMatrix.scale(1.0, -1.0); + corrMatrix.translate(0.0, ascent); + totalTextMatrix1 = totalTextMatrix1 * corrMatrix; + totalTextMatrix2 = totalTextMatrix2 * corrMatrix; + totalTextMatrix1 *= getCurrentContext().Transformation; totalTextMatrix2 *= getCurrentContext().Transformation; @@ -334,72 +341,23 @@ void PDFIProcessor::endText() void PDFIProcessor::setupImage(ImageId nImage) { - const GraphicsContext& rGC( getCurrentContext() ); - - basegfx::B2DHomMatrix aTrans( rGC.Transformation ); + const GraphicsContext& rGC(getCurrentContext()); - // check for rotation, which is the other way around in ODF basegfx::B2DTuple aScale, aTranslation; double fRotate, fShearX; - rGC.Transformation.decompose( aScale, aTranslation, fRotate, fShearX ); - // TODDO(F4): correcting rotation when fShearX != 0 ? - if( fRotate != 0.0 ) - { - - // try to create a Transformation that corrects for the wrong rotation - aTrans.identity(); - aTrans.scale( aScale.getX(), aScale.getY() ); - aTrans.rotate( -fRotate ); - - basegfx::B2DRange aRect( 0, 0, 1, 1 ); - aRect.transform( aTrans ); - - // TODO(F3) treat translation correctly - // the corrections below work for multiples of 90 degree - // which is a common case (landscape/portrait/seascape) - // we need a general solution here; however this needs to - // work in sync with DrawXmlEmitter::fillFrameProps and WriterXmlEmitter::fillFrameProps - // admittedly this is a lame workaround and fails for arbitrary rotation - double fQuadrant = fmod( fRotate, 2.0*M_PI ) / M_PI_2; - int nQuadrant = (int)fQuadrant; - if( nQuadrant < 0 ) - nQuadrant += 4; - if( nQuadrant == 1 ) - { - aTranslation.setX( aTranslation.getX() + aRect.getHeight() + aRect.getWidth()); - aTranslation.setY( aTranslation.getY() + aRect.getHeight() ); - } - if( nQuadrant == 3 ) - aTranslation.setX( aTranslation.getX() - aRect.getHeight() ); + rGC.Transformation.decompose(aScale, aTranslation, fRotate, fShearX); - aTrans.translate( aTranslation.getX(), - aTranslation.getY() ); - } - - bool bMirrorVertical = aScale.getY() > 0; - - // transform unit rect to determine view box - basegfx::B2DRange aRect( 0, 0, 1, 1 ); - aRect.transform( aTrans ); - - // TODO(F3): Handle clip const sal_Int32 nGCId = getGCId(rGC); FrameElement* pFrame = m_pElFactory->createFrameElement( m_pCurElement, nGCId ); ImageElement* pImageElement = m_pElFactory->createImageElement( pFrame, nGCId, nImage ); - pFrame->x = pImageElement->x = aRect.getMinX(); - pFrame->y = pImageElement->y = aRect.getMinY(); - pFrame->w = pImageElement->w = aRect.getWidth(); - pFrame->h = pImageElement->h = aRect.getHeight(); + pFrame->x = pImageElement->x = aTranslation.getX(); + pFrame->y = pImageElement->y = aTranslation.getY(); + pFrame->w = pImageElement->w = aScale.getX(); + pFrame->h = pImageElement->h = aScale.getY(); pFrame->ZOrder = m_nNextZOrder++; - if( bMirrorVertical ) - { + if (aScale.getY() > 0) pFrame->MirrorVertical = pImageElement->MirrorVertical = true; - pFrame->x += aRect.getWidth(); - pImageElement->x += aRect.getWidth(); - pFrame->y += aRect.getHeight(); - pImageElement->y += aRect.getHeight(); - } } void PDFIProcessor::drawMask(const uno::Sequence& xBitmap, -- cgit