diff --git a/sdext/source/pdfimport/tree/drawtreevisiting.cxx b/sdext/source/pdfimport/tree/drawtreevisiting.cxx index d5ce02ad89bf..f7cd916b475b 100644 --- a/sdext/source/pdfimport/tree/drawtreevisiting.cxx +++ b/sdext/source/pdfimport/tree/drawtreevisiting.cxx @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -647,13 +648,47 @@ static bool isSpaces(TextElement* pTextElem) return true; } -static bool notTransformed(const GraphicsContext& GC) +static bool canConcatenate(const basegfx::B2DHomMatrix& rCurr, const basegfx::B2DHomMatrix& rNext) { - return - rtl::math::approxEqual(GC.Transformation.get(0,0), 100.00) && - GC.Transformation.get(1,0) == 0.00 && - GC.Transformation.get(0,1) == 0.00 && - rtl::math::approxEqual(GC.Transformation.get(1,1), -100.00); + // get FontHeight of both snippets + const double fHeightCurr((rCurr * basegfx::B2DVector(0.0, 1.0)).getLength()); + const double fHeightNext((rNext * basegfx::B2DVector(0.0, 1.0)).getLength()); + + // 1st compare FontHeight to detect FontHeight changes + if(!rtl::math::approxEqual(fHeightCurr, fHeightNext)) + return false; + + // we now need to check if the BottomLeft edge of next is parallel to + // the BaseLine of the current. We could do this by getting the vectors + // and start comparing, but we already have a nice tooling method for + // this, so use it + const basegfx::B2DPoint aBottomLeftNext(rNext * basegfx::B2DPoint(0.0, 1.0)); + const basegfx::B2DPoint aBottomLeftCurr(rCurr * basegfx::B2DPoint(0.0, 1.0)); + const basegfx::B2DPoint aBottomRightCurr(rCurr * basegfx::B2DPoint(1.0, 1.0)); + const basegfx::B2DVector aBaselineCurr(aBottomRightCurr - aBottomLeftCurr); + double fCut(0.0); + + if(!basegfx::utils::isPointOnEdge( + aBottomLeftNext, // point to check + aBottomLeftCurr, // edge start + aBaselineCurr, // edge vector + &fCut)) // return value for evtl. found cut in range ]0.0..1.0[ + { + // not on edge -> we are done, we expect it to be on the right part of the given edge, + // but not outside of it (farther away than EdgeLength) + return false; + } + + // point is on edge and we have the relative cut value for it in fCut. To check + // the distance relative to fontHeight we need to move it from unit coordinates + // to being relative to vector length by mulitplying it. To get immediately + // the distance from the right side, we first substract from 1.0 which would be + // the right edge end point + fCut = (1.0 - fCut) * aBaselineCurr.getLength(); + + // we need to set that in relation to the fontHeight, so e.g. accept as concatenation + // when the new part is more than half fontHeight away from current part. + return fCut < fHeightCurr * 0.5; } void DrawXmlOptimizer::optimizeTextElements(Element& rParent) @@ -693,8 +728,6 @@ void DrawXmlOptimizer::optimizeTextElements(Element& rParent) const GraphicsContext& rCurGC = m_rProcessor.getGraphicsContext( pCur->GCId ); const GraphicsContext& rNextGC = m_rProcessor.getGraphicsContext( pNext->GCId ); - // line and space optimization; works only in strictly horizontal mode - // concatenate consecutive text elements unless there is a // font or text color or matrix change, leave a new span in that case if( (pCur->FontId == pNext->FontId || isSpaces(pNext)) && @@ -702,7 +735,11 @@ void DrawXmlOptimizer::optimizeTextElements(Element& rParent) rCurGC.FillColor.Green == rNextGC.FillColor.Green && rCurGC.FillColor.Blue == rNextGC.FillColor.Blue && rCurGC.FillColor.Alpha == rNextGC.FillColor.Alpha && - (rCurGC.Transformation == rNextGC.Transformation || notTransformed(rNextGC)) + // check transformations; we need + // - same fontHeight + // - same baseLine + // - not too big distance/gap between + canConcatenate(rCurGC.Transformation, rNextGC.Transformation) ) { pCur->updateGeometryWith( pNext );