diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx index 4f1bc1680000..1e7f0a34e71c 100644 --- a/include/basegfx/numeric/ftools.hxx +++ b/include/basegfx/numeric/ftools.hxx @@ -109,7 +109,7 @@ namespace basegfx /** Snap v to the range [0.0 .. fWidth] using modulo */ - double snapToZeroRange(double v, double fWidth); + BASEGFX_DLLPUBLIC double snapToZeroRange(double v, double fWidth); /** Snap v to the range [fLow .. fHigh] using modulo */ diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index a7efd3dbb088..abee5a2e8756 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -4689,15 +4689,25 @@ void ScOutputData::DrawRotated(bool bPixelToLogic) { eRotMode = pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet).GetValue(); - if ( nAttrRotate == 18000_deg100 ) + // tdf#143377 To use the same limits to avoid too big Skew + // with TextOrientation in Calc, use 1/2 degree here, too. + // This equals '50' in the notation here + const bool bForbidSkew( + nAttrRotate < Degree100(50) || // range [0..50] + nAttrRotate > Degree100(36000 - 50) || // range [35950..36000[ + (nAttrRotate > Degree100(18000 - 50) && (nAttrRotate < Degree100(18000 + 50)))); // range 50 around 18000 + + if ( bForbidSkew ) + { eRotMode = SVX_ROTATE_MODE_STANDARD; // no overflow + } if ( bLayoutRTL ) nAttrRotate = -nAttrRotate; double nRealOrient = toRadians(nAttrRotate); // 1/100 degree nCos = cos( nRealOrient ); - nSin = sin( nRealOrient ); + nSin = bForbidSkew ? 0 : sin( nRealOrient ); } } diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx index aabce64ba78e..755b86e59f28 100644 --- a/svx/source/dialog/framelinkarray.cxx +++ b/svx/source/dialog/framelinkarray.cxx @@ -29,6 +29,7 @@ #include #include #include +// #include //#define OPTICAL_CHECK_CLIPRANGE_FOR_MERGED_CELL #ifdef OPTICAL_CHECK_CLIPRANGE_FOR_MERGED_CELL @@ -110,27 +111,47 @@ basegfx::B2DHomMatrix Cell::HelperCreateB2DHomMatrixFromB2DRange( if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode ) { - // when rotated, adapt values. Get Skew (cos/sin == 1/tan) - const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation))); + // tdf#143377 We need to limit applying Skew to geometry since the closer + // we get to 0.0 or PI the more sin(mfOrientation) will get to zero and the + // huger the Skew effect will be. For that, use an epsilon-radius of 1/2 + // degree around the dangerous points 0.0 and PI. - switch (meRotMode) + // Snap to modulo to [0.0 .. 2PI[ to make compare easier + const double fSnapped(::basegfx::snapToZeroRange(mfOrientation, M_PI * 2.0)); + + // As a compromize, allow up to 1/2 degree + static const double fMinAng(M_PI/360.0); + + // Check if Skew makes sense or would be too huge + const bool bForbidSkew( + fSnapped < fMinAng || // range [0.0 .. fMinAng] + fSnapped > (M_PI * 2.0) - fMinAng || // range [PI-fMinAng .. 2PI[ + fabs(fSnapped - M_PI) < fMinAng); // range [PI-fMinAng .. PI+fMinAng] + + if(!bForbidSkew) { - case SvxRotateMode::SVX_ROTATE_MODE_TOP: - // shear Y-Axis - aY.setX(-fSkew); - break; - case SvxRotateMode::SVX_ROTATE_MODE_CENTER: - // shear origin half, Y full - aOrigin.setX(aOrigin.getX() + (fSkew * 0.5)); - aY.setX(-fSkew); - break; - case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM: - // shear origin full, Y full - aOrigin.setX(aOrigin.getX() + fSkew); - aY.setX(-fSkew); - break; - default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above - break; + // when rotated, adapt values. Get Skew (cos/sin == 1/tan) + const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation))); + + switch (meRotMode) + { + case SvxRotateMode::SVX_ROTATE_MODE_TOP: + // shear Y-Axis + aY.setX(-fSkew); + break; + case SvxRotateMode::SVX_ROTATE_MODE_CENTER: + // shear origin half, Y full + aOrigin.setX(aOrigin.getX() + (fSkew * 0.5)); + aY.setX(-fSkew); + break; + case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM: + // shear origin full, Y full + aOrigin.setX(aOrigin.getX() + fSkew); + aY.setX(-fSkew); + break; + default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above + break; + } } }