tdf#143377 Correct maximum Skew for TextOrientation in Calc
For zero or 180 degree text orinentation errors can happen in the Border visualization, theoretically also in the Text rendering. Ths has to do with sin(0) and sin(180) being zero and lead internal to numerical problems, e.g. a very huge Skew that when applied show the reported 'errors'. I limit this mechanism now to +/- 1/2 degree from the critical mentioned places, for Border and Text - to not risk to have different points of corrections. The UI only allows angles of 1 degree steps, but UNO API and pdf import may allow more. Change-Id: Idbc68f6a7beab84df0672165c2a813d96eeff84e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141999 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
This commit is contained in:
committed by
Armin Le Grand
parent
d3caee0a7a
commit
604f6fc8fe
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
||||
#include <basegfx/polygon/b2dpolygonclipper.hxx>
|
||||
// #include <basegfx/numeric/ftools.hxx>
|
||||
|
||||
//#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user