filter/source/svg/presentation_engine.js |  125 +++++++++++++++++++------------
 filter/source/svg/svgexport.cxx          |    6 +
 2 files changed, 83 insertions(+), 48 deletions(-)

New commits:
commit 7019b492fa3057155528ac7aa6ef3f6fc9de4aff
Author:     Marco Cecchetti <marco.cecche...@collabora.com>
AuthorDate: Fri Feb 19 16:04:07 2021 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Feb 22 12:20:42 2021 +0100

    filter: svg: js engine: misplaced text: improving text field handling
    
    Change-Id: I8b5f9a39b3cd3fcfdae0d088eae0a875cf9404ee
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111065
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/filter/source/svg/presentation_engine.js 
b/filter/source/svg/presentation_engine.js
index 76bd4d41b12d..7f3cb48bcfbf 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -5589,68 +5589,99 @@ PlaceholderShape.prototype.isValid = function()
  */
 PlaceholderShape.prototype.init = function()
 {
-
     var aTextFieldElement = getElementByClassName( 
this.masterPage.backgroundObjects, this.className );
     if( aTextFieldElement )
     {
-        var aPlaceholderElement = getElementByClassName( aTextFieldElement, 
'PlaceholderText' );
-        if( aPlaceholderElement )
+        var aTextElem = getElementByClassName( aTextFieldElement, 
'SVGTextShape' );
+        if( aTextElem )
         {
-            // Each text field element has an invisible rectangle that can be
-            // regarded as the text field bounding box.
-            // We exploit such a feature and the exported text adjust attribute
-            // value in order to set up correctly the position and text
-            // adjustment for the placeholder element.
-            var aSVGRectElem = getElementByClassName( aTextFieldElement, 
'BoundingBox' );
-            if( aSVGRectElem )
+            var aPlaceholderElement = getElementByClassName(aTextElem, 
'PlaceholderText');
+            if( aPlaceholderElement )
             {
-                var aRect = new Rectangle( aSVGRectElem );
-                var sTextAdjust = getOOOAttribute( aTextFieldElement, 
aOOOAttrTextAdjust ) || 'left';
-                var sTextAnchor, sX;
-                if( sTextAdjust == 'left' )
-                {
-                    sTextAnchor = 'start';
-                    sX = String( aRect.left );
-                }
-                else if( sTextAdjust == 'right' )
-                {
-                    sTextAnchor = 'end';
-                    sX = String( aRect.right );
-                }
-                else if( sTextAdjust == 'center' )
+                // SVG 1.1 does not support text wrapping wrt a rectangle.
+                // When a text shape contains a placeholder, setting up the 
position
+                // of each text line doesn't work since the position is 
computed
+                // before replacing the placeholder text.
+                // Anyway each text shape has an invisible rectangle that can 
be
+                // regarded as the text shape bounding box.
+                // We exploit such a feature and the exported text adjust 
attribute
+                // value in order to set up correctly the position and text
+                // adjustment for the text shape content.
+                // We assume that once the real value has been substituted to
+                // the placeholder the resulting content is no more than a 
single line.
+                // So we remove from <tspan> elements used for setting up the
+                // position of text lines (class TextPosition) the 'x' and 'y' 
attribute.
+                // In the general case we would need to implement a function
+                // which is able to compute at which words the text shape 
content has
+                // to be wrapped.
+                var aSVGRectElem = getElementByClassName( aTextFieldElement, 
'BoundingBox' );
+                if( aSVGRectElem )
                 {
-                    sTextAnchor = 'middle';
-                    var nMiddle = ( aRect.left + aRect.right ) / 2;
-                    sX = String( parseInt( String( nMiddle ) ) );
+                    var aRect = new Rectangle( aSVGRectElem );
+                    var sTextAdjust = getOOOAttribute( aTextFieldElement, 
aOOOAttrTextAdjust );
+                    // the bbox of the text shape is indeed a bit larger, 
there is a bit of internal padding
+                    var nMargin = 250; // 1000th mm
+                    var sTextAnchor, sX;
+                    if( sTextAdjust == 'left' )
+                    {
+                        sTextAnchor = 'start';
+                        sX = String( Math.trunc( aRect.left + nMargin ) );
+                    }
+                    else if( sTextAdjust == 'right' )
+                    {
+                        sTextAnchor = 'end';
+                        sX = String( Math.trunc( aRect.right - nMargin ) );
+                    }
+                    else if( sTextAdjust == 'center' )
+                    {
+                        sTextAnchor = 'middle';
+                        var nMiddle = ( aRect.left + aRect.right ) / 2;
+                        sX = String( parseInt( String( nMiddle ) ) );
+                    }
+                    if( sTextAnchor )
+                    {
+                        aTextElem.setAttribute( 'text-anchor', sTextAnchor );
+                        if( sX )
+                            aTextElem.setAttribute( 'x', sX );
+
+                        var aTSpanElements = getElementsByClassName( 
aTextElem, 'TextPosition' );
+                        if( aTSpanElements )
+                        {
+                            var i = 0;
+                            for( ; i < aTSpanElements.length; ++i )
+                            {
+                                var aTSpanElem = aTSpanElements[i];
+                                aTSpanElem.removeAttribute( 'x' );
+                                if( i !== 0 )
+                                    aTSpanElem.removeAttribute( 'y' );
+                            }
+                        }
+                    }
                 }
-                if( sTextAnchor )
-                    aPlaceholderElement.setAttribute( 'text-anchor', 
sTextAnchor );
-                if( sX )
-                    aPlaceholderElement.setAttribute( 'x', sX );
-            }
 
-            // date/time fields were not exported correctly when positioned 
chars are used
-            if( this.masterPage.metaSlide.theMetaDoc.bIsUsePositionedChars )
-            {
-                // We remove all text lines but the first one used as 
placeholder.
-                var aTextLineGroupElem = 
aPlaceholderElement.parentNode.parentNode;
-                if( aTextLineGroupElem )
+                // date/time fields were not exported correctly when 
positioned chars are used
+                if( this.masterPage.metaSlide.theMetaDoc.bIsUsePositionedChars 
)
                 {
-                    // Just to be sure it is the element we are looking for.
-                    var sFontFamilyAttr = aTextLineGroupElem.getAttribute( 
'font-family' );
-                    if( sFontFamilyAttr )
+                    // We remove all text lines but the first one used as 
placeholder.
+                    var aTextLineGroupElem = 
aPlaceholderElement.parentNode.parentNode;
+                    if( aTextLineGroupElem )
                     {
-                        var aChildSet = getElementChildren( aTextLineGroupElem 
);
-                        if( aChildSet.length > 1  )
-                            var i = 1;
-                        for( ; i < aChildSet.length; ++i )
+                        // Just to be sure it is the element we are looking 
for.
+                        var sFontFamilyAttr = aTextLineGroupElem.getAttribute( 
'font-family' );
+                        if( sFontFamilyAttr )
                         {
-                            aTextLineGroupElem.removeChild( aChildSet[i] );
+                            var aChildSet = getElementChildren( 
aTextLineGroupElem );
+                            if( aChildSet.length > 1 )
+                                var i = 1;
+                            for( ; i < aChildSet.length; ++i )
+                            {
+                                aTextLineGroupElem.removeChild( aChildSet[i] );
+                            }
                         }
                     }
                 }
+                this.textElement = aPlaceholderElement;
             }
-            this.textElement = aPlaceholderElement;
         }
         this.element = aTextFieldElement;
     }
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
index ef13ab4884d9..ce12673b795d 100644
--- a/filter/source/svg/svgexport.cxx
+++ b/filter/source/svg/svgexport.cxx
@@ -2118,14 +2118,18 @@ bool SVGFilter::implExportShape( const Reference< 
css::drawing::XShape >& rxShap
                         bool bIsPageNumber  = ( aShapeClass == "Slide_Number" 
);
                         bool bIsFooter      = ( aShapeClass == "Footer" );
                         bool bIsDateTime    = ( aShapeClass == "Date/Time" );
-                        if( bIsPageNumber || bIsDateTime || bIsFooter )
+                        bool bTextField = bIsPageNumber || bIsFooter || 
bIsDateTime;
+                        if( bTextField )
                         {
                             // to notify to the 
SVGActionWriter::ImplWriteActions method
                             // that we are dealing with a placeholder shape
                             pElementId = &sPlaceholderTag;
 
                             mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, 
"visibility", "hidden" );
+                        }
 
+                        if( bTextField || ( aShapeClass == "TextShape" ) )
+                        {
                             sal_uInt16 nTextAdjust = 
sal_uInt16(ParagraphAdjust_LEFT);
                             OUString sTextAdjust;
                             xShapePropSet->getPropertyValue( "ParaAdjust" ) 
>>= nTextAdjust;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to