Kaydet (Commit) a20e145c authored tarafından Vort's avatar Vort Kaydeden (comit) Caolán McNamara

fdo#45001 fdo#77105 PDF Import: rotated text fixes

1. Fix 180 degrees text rotation;
2. Make rotated text fully editable.

Change-Id: Ie937f29031bbd0146207ce83678db351b65d2f8d
Reviewed-on: https://gerrit.libreoffice.org/8890Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst f704d5a5
......@@ -222,6 +222,15 @@ void DrawXmlEmitter::fillFrameProps( DrawElement& rElem,
if( rElem.MirrorVertical )
fRotate += M_PI;
// 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)))
{
fRotate += M_PI;
}
// build transformation string
if( fShearX != 0.0 )
{
......
......@@ -127,11 +127,12 @@ namespace pdfi
{
protected:
GraphicalElement( Element* pParent, sal_Int32 nGCId )
: Element( pParent ), GCId( nGCId ), MirrorVertical( false ) {}
: Element( pParent ), GCId( nGCId ), MirrorVertical( false ), IsForText (false) {}
public:
sal_Int32 GCId;
bool MirrorVertical;
bool IsForText;
};
struct DrawElement : public GraphicalElement
......
......@@ -56,9 +56,7 @@ namespace pdfi
com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > xContext) :
m_xContext(xContext),
fYPrevTextPosition(-10000.0),
fXPrevTextPosition(0.0),
fPrevTextWidth(0.0),
prevCharWidth(0),
m_pElFactory( new ElementFactory() ),
m_pDocument( m_pElFactory->createDocumentElement() ),
m_pCurPage(0),
......@@ -224,9 +222,7 @@ void PDFIProcessor::processGlyphLine()
if ((ch == 0x20) || (ch == 0xa0))
{
double spaceWidth =
m_GlyphsList[i].getRect().X2 -
m_GlyphsList[i].getRect().X1;
double spaceWidth = m_GlyphsList[i].getWidth();
spaceDetectBoundary = spaceWidth * 0.5;
break;
}
......@@ -237,129 +233,89 @@ void PDFIProcessor::processGlyphLine()
{
double avgGlyphWidth = 0.0;
for (size_t i = 0; i < m_GlyphsList.size(); i++)
{
avgGlyphWidth +=
m_GlyphsList[i].getRect().X2 -
m_GlyphsList[i].getRect().X1;
}
avgGlyphWidth += m_GlyphsList[i].getWidth();
avgGlyphWidth /= m_GlyphsList.size();
spaceDetectBoundary = avgGlyphWidth * 0.2;
}
FrameElement* frame = m_pElFactory->createFrameElement(m_GlyphsList[0].getCurElement(),
getGCId(getTransformGlyphContext(m_GlyphsList[0])));
FrameElement* frame = m_pElFactory->createFrameElement(
m_GlyphsList[0].getCurElement(),
getGCId(m_GlyphsList[0].getGC()));
frame->ZOrder = m_nNextZOrder++;
frame->IsForText = true;
ParagraphElement* para = m_pElFactory->createParagraphElement(frame);
for (size_t i = 0; i < m_GlyphsList.size(); i++)
{
bool prependSpace = false;
if (i != 0)
TextElement* text = m_pElFactory->createTextElement(
para,
getGCId(m_GlyphsList[i].getGC()),
m_GlyphsList[i].getGC().FontId);
if (i == 0)
{
double spaceSize =
m_GlyphsList[i].getRect().X1 -
m_GlyphsList[i - 1].getRect().X2;
text->x = m_GlyphsList[0].getGC().Transformation.get(0, 2);
text->y = m_GlyphsList[0].getGC().Transformation.get(1, 2);
text->w = 0;
text->h = 0;
para->updateGeometryWith(text);
frame->updateGeometryWith(para);
}
else
{
double spaceSize = m_GlyphsList[i].getPrevSpaceWidth();
prependSpace = spaceSize > spaceDetectBoundary;
}
drawCharGlyphs(m_GlyphsList[i].getGlyph(),
m_GlyphsList[i].getRect(),
m_GlyphsList[i].getGC(),
para,
frame,
prependSpace);
if (prependSpace)
text->Text.append(" ");
text->Text.append(m_GlyphsList[i].getGlyph());
}
m_GlyphsList.clear();
}
void PDFIProcessor::drawGlyphLine( const OUString& rGlyphs,
const geometry::RealRectangle2D& rRect,
const geometry::Matrix2D& rFontMatrix )
void PDFIProcessor::drawGlyphs( const OUString& rGlyphs,
const geometry::RealRectangle2D& rRect,
const geometry::Matrix2D& rFontMatrix )
{
::basegfx::B2DPoint point1(rRect.X1, rRect.Y1);
::basegfx::B2DPoint point2(rRect.X2, rRect.Y2);
point1 *= getCurrentContext().Transformation;
point2 *= getCurrentContext().Transformation;
if ((fYPrevTextPosition != point1.getY()) ||
(fXPrevTextPosition > point2.getX()) ||
((fXPrevTextPosition + fPrevTextWidth * 1.3) < point1.getX()))
basegfx::B2DHomMatrix totalTextMatrix1(
rFontMatrix.m00, rFontMatrix.m01, rRect.X1,
rFontMatrix.m10, rFontMatrix.m11, rRect.Y1);
basegfx::B2DHomMatrix totalTextMatrix2(
rFontMatrix.m00, rFontMatrix.m01, rRect.X2,
rFontMatrix.m10, rFontMatrix.m11, rRect.Y2);
totalTextMatrix1 *= getCurrentContext().Transformation;
totalTextMatrix2 *= getCurrentContext().Transformation;
basegfx::B2DHomMatrix invMatrix(totalTextMatrix1);
basegfx::B2DHomMatrix invPrevMatrix(prevTextMatrix);
invMatrix.invert();
invPrevMatrix.invert();
basegfx::B2DHomMatrix offsetMatrix1(totalTextMatrix1);
basegfx::B2DHomMatrix offsetMatrix2(totalTextMatrix2);
offsetMatrix1 *= invPrevMatrix;
offsetMatrix2 *= invMatrix;
double charWidth = offsetMatrix2.get(0, 2);
double prevSpaceWidth = offsetMatrix1.get(0, 2) - prevCharWidth;
if ((totalTextMatrix1.get(0, 0) != prevTextMatrix.get(0, 0)) ||
(totalTextMatrix1.get(0, 1) != prevTextMatrix.get(0, 1)) ||
(totalTextMatrix1.get(1, 0) != prevTextMatrix.get(1, 0)) ||
(totalTextMatrix1.get(1, 1) != prevTextMatrix.get(1, 1)) ||
(offsetMatrix1.get(0, 2) < 0.0) ||
(prevSpaceWidth > prevCharWidth * 1.3) ||
(!basegfx::fTools::equalZero(offsetMatrix1.get(1, 2), 0.0001)))
{
processGlyphLine();
}
CharGlyph aGlyph(m_pCurElement, getCurrentContext(), rFontMatrix, rRect, rGlyphs);
getGCId(getCurrentContext());
CharGlyph aGlyph(m_pCurElement, getCurrentContext(), charWidth, prevSpaceWidth, rGlyphs);
aGlyph.getGC().Transformation = totalTextMatrix1;
m_GlyphsList.push_back(aGlyph);
fYPrevTextPosition = point1.getY();
fXPrevTextPosition = point2.getX();
fPrevTextWidth = point2.getX() - point1.getX();
}
GraphicsContext& PDFIProcessor::getTransformGlyphContext( CharGlyph& rGlyph )
{
geometry::RealRectangle2D rRect = rGlyph.getRect();
geometry::Matrix2D rFontMatrix = rGlyph.getFontMatrix();
basegfx::B2DHomMatrix aFontMatrix;
basegfx::unotools::homMatrixFromMatrix(
aFontMatrix,
rFontMatrix );
FontAttributes aFontAttrs = m_aIdToFont[ rGlyph.getGC().FontId ];
// add transformation to GC
basegfx::B2DHomMatrix aFontTransform(basegfx::tools::createTranslateB2DHomMatrix(-rRect.X1, -rRect.Y1));
aFontTransform *= aFontMatrix;
aFontTransform.translate( rRect.X1, rRect.Y1 );
rGlyph.getGC().Transformation = rGlyph.getGC().Transformation * aFontTransform;
getGCId(rGlyph.getGC());
return rGlyph.getGC();
}
void PDFIProcessor::drawCharGlyphs( OUString& rGlyphs,
geometry::RealRectangle2D& rRect,
const GraphicsContext& aGC,
ParagraphElement* pPara,
FrameElement* pFrame,
bool bSpaceFlag )
{
OUString tempStr( 32 );
// check whether there was a previous draw frame
TextElement* pText = m_pElFactory->createTextElement( pPara,
getGCId(aGC),
aGC.FontId );
if( bSpaceFlag )
pText->Text.append( tempStr );
pText->Text.append( rGlyphs );
::basegfx::B2DPoint point(rRect.X1, rRect.Y1);
point *= aGC.Transformation;
pText->x = point.getX();
pText->y = point.getY();
pText->w = 0.0001; // hack for solving of size auto-grow problem
pText->h = 0.0001;
pPara->updateGeometryWith( pText );
if( pFrame )
pFrame->updateGeometryWith( pPara );
}
void PDFIProcessor::drawGlyphs( const OUString& rGlyphs,
const geometry::RealRectangle2D& rRect,
const geometry::Matrix2D& rFontMatrix )
{
drawGlyphLine( rGlyphs, rRect, rFontMatrix );
prevCharWidth = charWidth;
prevTextMatrix = totalTextMatrix1;
}
void PDFIProcessor::endText()
......
......@@ -66,9 +66,8 @@ namespace pdfi
public:
com::sun::star::uno::Reference<
com::sun::star::uno::XComponentContext > m_xContext;
double fYPrevTextPosition;
double fXPrevTextPosition;
double fPrevTextWidth;
basegfx::B2DHomMatrix prevTextMatrix;
double prevCharWidth;
enum DocumentTextDirecion { LrTb, RlTb, TbLr };
explicit PDFIProcessor( const com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator >& xStat,
......@@ -103,19 +102,6 @@ namespace pdfi
private:
void processGlyphLine();
void drawGlyphLine( const OUString& rGlyphs,
const ::com::sun::star::geometry::RealRectangle2D& rRect,
const ::com::sun::star::geometry::Matrix2D& rFontMatrix );
void drawCharGlyphs( OUString& rGlyphs,
::com::sun::star::geometry::RealRectangle2D& rRect,
const GraphicsContext& aGC,
ParagraphElement* pPara,
FrameElement* pFrame,
bool bSpaceFlag );
GraphicsContext& getTransformGlyphContext( CharGlyph& rGlyph );
// ContentSink interface implementation
virtual void setPageNum( sal_Int32 nNumPages ) SAL_OVERRIDE;
......@@ -226,24 +212,24 @@ namespace pdfi
class CharGlyph
{
public:
CharGlyph(Element* pCurElement, const GraphicsContext& rCurrentContext, const com::sun::star::geometry::Matrix2D& rFontMatrix,
const com::sun::star::geometry::RealRectangle2D& rRect, const OUString& rGlyphs )
CharGlyph(Element* pCurElement, const GraphicsContext& rCurrentContext,
double width, double prevSpaceWidth, const OUString& rGlyphs )
: m_pCurElement(pCurElement), m_rCurrentContext(rCurrentContext),
m_rFontMatrix(rFontMatrix), m_rRect(rRect), m_rGlyphs(rGlyphs) {};
m_Width(width), m_PrevSpaceWidth(prevSpaceWidth), m_rGlyphs(rGlyphs) {};
virtual ~CharGlyph(){};
OUString& getGlyph(){ return m_rGlyphs; }
com::sun::star::geometry::RealRectangle2D& getRect(){ return m_rRect; }
com::sun::star::geometry::Matrix2D& getFontMatrix(){ return m_rFontMatrix; }
double getWidth(){ return m_Width; }
double getPrevSpaceWidth(){ return m_PrevSpaceWidth; }
GraphicsContext& getGC(){ return m_rCurrentContext; }
Element* getCurElement(){ return m_pCurElement; }
private:
Element* m_pCurElement ;
GraphicsContext m_rCurrentContext ;
com::sun::star::geometry::Matrix2D m_rFontMatrix ;
com::sun::star::geometry::RealRectangle2D m_rRect ;
OUString m_rGlyphs ;
double m_Width ;
double m_PrevSpaceWidth ;
OUString m_rGlyphs ;
};
}
......
......@@ -821,16 +821,13 @@ void PDFOutDev::drawChar(GfxState *state, double x, double y,
const double aPositionX(x-originX);
const double aPositionY(y-originY);
// TODO(F2): use leading here, when set
const double nWidth(dx != 0.0 ? dx : fFontSize);
const double nHeight(dy != 0.0 ? dy : fFontSize);
const double* pTextMat=state->getTextMat();
printf( "drawChar %f %f %f %f %f %f %f %f ",
normalize(aPositionX),
normalize(aPositionY),
normalize(aPositionX+nWidth),
normalize(aPositionY-nHeight),
normalize(aPositionX + dx),
normalize(aPositionY + dy),
normalize(pTextMat[0]),
normalize(pTextMat[2]),
normalize(pTextMat[1]),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment