include/editeng/unoprnms.hxx                       |    1 
 include/svx/svddef.hxx                             |    3 -
 include/svx/unoshprp.hxx                           |    1 
 oox/inc/drawingml/textbodyproperties.hxx           |    2 
 oox/source/drawingml/shape.cxx                     |    5 --
 oox/source/drawingml/textbodypropertiescontext.cxx |   14 ++++++
 oox/source/export/drawingml.cxx                    |    5 ++
 oox/source/token/properties.txt                    |    1 
 svx/qa/unit/data/clip-vertical-overflow.pptx       |binary
 svx/qa/unit/svdraw.cxx                             |   44 +++++++++++++++++++++
 svx/source/svdraw/svdattr.cxx                      |    1 
 svx/source/svdraw/svdotextdecomposition.cxx        |   14 ++++--
 12 files changed, 80 insertions(+), 11 deletions(-)

New commits:
commit 60bce1af8aab2115d603781193bb659b35d1aedb
Author:     Sarper Akdemir <sarper.akde...@collabora.com>
AuthorDate: Thu Apr 6 13:01:02 2023 +0300
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Apr 10 08:52:51 2023 +0200

    pptx import/export: consider TextClipVerticalOverflow for vertOverflow
    
    Also adds a unit test that tests TextClipVerticalOverflow on
    4 different scenarios.
    
    Change-Id: I6232935765641c796046d90fe2207d67ae4b3eb5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150107
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/oox/inc/drawingml/textbodyproperties.hxx 
b/oox/inc/drawingml/textbodyproperties.hxx
index 1daa5d592a30..d935f940638d 100644
--- a/oox/inc/drawingml/textbodyproperties.hxx
+++ b/oox/inc/drawingml/textbodyproperties.hxx
@@ -51,7 +51,7 @@ struct TextBodyProperties
     /// Normal autofit: font scale (default: 100%).
     sal_Int32 mnFontScale = 100000;
     OUString msHorzOverflow;
-    OUString msVertOverflow;
+    std::optional< sal_Int32 > moVertOverflow{};
 
     std::array<std::optional<sal_Int32>, 4> maTextDistanceValues;
 
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index fbd3e79c5a6e..69f3bf5a4d60 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -1792,9 +1792,8 @@ Reference< XShape > const & Shape::createAndInsert(
                 auto sHorzOverflow = 
getTextBody()->getTextProperties().msHorzOverflow;
                 if (!sHorzOverflow.isEmpty())
                     putPropertyToGrabBag("horzOverflow", 
uno::Any(getTextBody()->getTextProperties().msHorzOverflow));
-                auto nVertOverflow = 
getTextBody()->getTextProperties().msVertOverflow;
-                if (!nVertOverflow.isEmpty())
-                    putPropertyToGrabBag("vertOverflow", 
uno::Any(getTextBody()->getTextProperties().msVertOverflow));
+                if (XML_ellipsis == 
getTextBody()->getTextProperties().moVertOverflow)
+                    putPropertyToGrabBag("vertOverflow", 
uno::Any(OUString{"ellipsis"}));
             }
 
             // Note that the script 
oox/source/drawingml/customshapes/generatePresetsData.pl looks
diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx 
b/oox/source/drawingml/textbodypropertiescontext.cxx
index 47ef04797c93..46576c069c8e 100644
--- a/oox/source/drawingml/textbodypropertiescontext.cxx
+++ b/oox/source/drawingml/textbodypropertiescontext.cxx
@@ -83,7 +83,19 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( 
ContextHandler2Helper cons
   // ST_TextHorzOverflowType
     mrTextBodyProp.msHorzOverflow = 
rAttribs.getStringDefaulted(XML_horzOverflow);
     // ST_TextVertOverflowType
-    mrTextBodyProp.msVertOverflow = 
rAttribs.getStringDefaulted(XML_vertOverflow);
+    if( rAttribs.hasAttribute(XML_vertOverflow) )
+    {
+        mrTextBodyProp.moVertOverflow = rAttribs.getToken(XML_vertOverflow);
+        switch( mrTextBodyProp.moVertOverflow.value_or(XML_overflow) )
+        {
+            case XML_ellipsis:
+            case XML_clip:
+                
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextClipVerticalOverflow, true);
+                break;
+            default:
+                break;
+        }
+    }
 
     // ST_TextColumnCount
     if (const sal_Int32 nColumns = rAttribs.getInteger(XML_numCol, 0); 
nColumns > 0)
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 59d67393bed5..270d961d6d5a 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3868,6 +3868,11 @@ void DrawingML::WriteText(const Reference<XInterface>& 
rXIface, bool bBodyPr, bo
             }
         }
 
+        if (!sVertOverflow && GetProperty(rXPropSet, 
"TextClipVerticalOverflow") && mAny.get<bool>())
+        {
+            sVertOverflow = "clip";
+        }
+
         mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), 
XML_bodyPr,
                                XML_numCol, 
sax_fastparser::UseIf(OString::number(nCols), nCols > 0),
                                XML_spcCol, 
sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nColSpacing)),
 nCols > 0 && nColSpacing >= 0),
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index edf799c2c8df..fd2c3a0c6497 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -547,6 +547,7 @@ TextAutoGrowHeight
 TextBox
 TextBreak
 TextCameraZRotateAngle
+TextClipVerticalOverflow
 TextColor
 TextColumns
 TextContourFrame
diff --git a/svx/qa/unit/data/clip-vertical-overflow.pptx 
b/svx/qa/unit/data/clip-vertical-overflow.pptx
new file mode 100644
index 000000000000..703f92e54b30
Binary files /dev/null and b/svx/qa/unit/data/clip-vertical-overflow.pptx differ
diff --git a/svx/qa/unit/svdraw.cxx b/svx/qa/unit/svdraw.cxx
index 0001a7f4d66a..de6ba067fe1f 100644
--- a/svx/qa/unit/svdraw.cxx
+++ b/svx/qa/unit/svdraw.cxx
@@ -669,6 +669,50 @@ CPPUNIT_TEST_FIXTURE(SvdrawTest, testRotatePoint)
         CPPUNIT_ASSERT_EQUAL(Point(300, 300), aPoint);
     }
 }
+
+CPPUNIT_TEST_FIXTURE(SvdrawTest, testClipVerticalTextOverflow)
+{
+    // File contains a slide with 4 rectangle shapes with text inside
+    // each have <a:bodyPr vertOverflow="clip">
+    // 1-) Text overflowing the rectangle
+    // 2-) Text not overflowing the rectangle
+    // 3-) (Vertical text) Text overflowing the rectangle
+    // 4-) (Vertical text) Text not overflowing the rectangle
+    loadFromURL(u"clip-vertical-overflow.pptx");
+
+    SdrPage* pSdrPage = getFirstDrawPageWithAssert();
+    xmlDocUniquePtr pDocument = 
lcl_dumpAndParseFirstObjectWithAssert(pSdrPage);
+
+    // Test vertically overflowing text
+    // Without the accompanying fix in place, this test would have failed with:
+    // equality assertion failed
+    // - Expected: 6
+    // - Actual  : 13
+    // - In <>, XPath contents of child does not match
+    // i.e. the vertically overflowing text wasn't clipped & overflowing text
+    // was drawn anyways.
+    assertXPathContent(pDocument, 
"count((//sdrblocktext)[4]//textsimpleportion)", "6");
+
+    // make sure text is aligned correctly after the overflowing text is 
clipped
+    assertXPath(pDocument, "((//sdrblocktext)[4]//textsimpleportion)[1]", "y", 
"3749");
+    assertXPath(pDocument, "((//sdrblocktext)[4]//textsimpleportion)[6]", "y", 
"7559");
+
+    // make sure the text that isn't overflowing is still aligned properly
+    assertXPathContent(pDocument, 
"count((//sdrblocktext)[5]//textsimpleportion)", "3");
+    assertXPath(pDocument, "((//sdrblocktext)[5]//textsimpleportion)[1]", "y", 
"5073");
+    assertXPath(pDocument, "((//sdrblocktext)[5]//textsimpleportion)[3]", "y", 
"6597");
+
+    // Test vertically overflowing text, with vertical text direction
+    assertXPathContent(pDocument, 
"count((//sdrblocktext)[6]//textsimpleportion)", "12");
+    // make sure text is aligned correctly after the overflowing text is 
clipped
+    assertXPath(pDocument, "((//sdrblocktext)[6]//textsimpleportion)[1]", "x", 
"13093");
+    assertXPath(pDocument, "((//sdrblocktext)[6]//textsimpleportion)[12]", 
"x", "4711");
+
+    // make sure the text that isn't overflowing is still aligned properly
+    assertXPathContent(pDocument, 
"count((//sdrblocktext)[7]//textsimpleportion)", "3");
+    assertXPath(pDocument, "((//sdrblocktext)[7]//textsimpleportion)[1]", "x", 
"25417");
+    assertXPath(pDocument, "((//sdrblocktext)[7]//textsimpleportion)[3]", "x", 
"23893");
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 1934698260222f6727ac43118933094fa84dcdea
Author:     Sarper Akdemir <sarper.akde...@collabora.com>
AuthorDate: Thu Apr 6 13:00:53 2023 +0300
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Apr 10 08:52:42 2023 +0200

    editeng, svx: introduce ability to clip vertical text overflow
    
    Introduces editeng text property TextClipVerticalOverflow.
    
    Which when set causes vertical text that is overflown out of a
    frame/shape truncated. (Only when text isn't being edited)
    
    This is implemented as two steps:
    (if text overflows)
      1 - Vertical adjust is forced to top.
        (Forcing vert adjust to top isn't the desired behavior normally,
        but good enough for a first cut I'd say.)
           -> The desired behavior would be after the overflown text is
           truncated, doing a vertical adjust (of center/bottom/top) on
           that piece of text.
    
      2 - ClipRange is set to the height of the frame/shape.
    
    This appears to work with different text directions too (vertical
    etc.).
    
    Change-Id: I697715a7d28bde94a6650609b16505ffab92173f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150106
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/include/editeng/unoprnms.hxx b/include/editeng/unoprnms.hxx
index a321e54e5a73..1ca19c3f5121 100644
--- a/include/editeng/unoprnms.hxx
+++ b/include/editeng/unoprnms.hxx
@@ -124,6 +124,7 @@ inline constexpr OUStringLiteral UNO_NAME_TEXT_WRITINGMODE 
= u"TextWritingMode";
 inline constexpr OUStringLiteral UNO_NAME_TEXT_FONTINDEPENDENTLINESPACING = 
u"FontIndependentLineSpacing";
 inline constexpr OUStringLiteral UNO_NAME_TEXT_WORDWRAP = u"TextWordWrap";
 inline constexpr OUStringLiteral UNO_NAME_TEXT_CHAINNEXTNAME = 
u"TextChainNextName";
+inline constexpr OUStringLiteral UNO_NAME_TEXT_CLIPVERTOVERFLOW = 
u"TextClipVerticalOverflow";
 
 inline constexpr OUStringLiteral UNO_NAME_MEASUREKIND = u"MeasureKind";
 inline constexpr OUStringLiteral UNO_NAME_MEASURETEXTHPOS = 
u"MeasureTextHorizontalPosition";
diff --git a/include/svx/svddef.hxx b/include/svx/svddef.hxx
index 059c461721b4..85a72e5b713d 100644
--- a/include/svx/svddef.hxx
+++ b/include/svx/svddef.hxx
@@ -232,7 +232,8 @@ constexpr TypedWhichId<SvXMLAttrContainerItem>     
SDRATTR_XMLATTRIBUTES
 constexpr TypedWhichId<SdrTextFixedCellHeightItem> 
SDRATTR_TEXT_USEFIXEDCELLHEIGHT (SDRATTR_MISC_FIRST +23);     /*   1121 */ /*   
1121 */ /*   1104 */             /* Pool V2 */
 constexpr TypedWhichId<SdrOnOffItem>               SDRATTR_TEXT_WORDWRAP       
    (SDRATTR_MISC_FIRST +24);     /*   1122 */ /*   1122 */ /*   1105 */        
     /* Pool V2 */
 constexpr TypedWhichId<SfxStringItem>              SDRATTR_TEXT_CHAINNEXTNAME  
    (SDRATTR_MISC_FIRST +25);     /*   1123 */ /*   1123 */ /*   1106 */        
     /* Pool V2 */
-constexpr sal_uInt16                               SDRATTR_MISC_LAST           
    (SDRATTR_TEXT_CHAINNEXTNAME); /* 1125   */ /* 1125   */ /* 1108   */ /* 
Pool V1: 1056 */
+constexpr TypedWhichId<SdrOnOffItem>               
SDRATTR_TEXT_CLIPVERTOVERFLOW   (SDRATTR_MISC_FIRST +26);
+constexpr sal_uInt16                               SDRATTR_MISC_LAST           
    (SDRATTR_TEXT_CLIPVERTOVERFLOW); /* 1126   */ /* 1125   */ /* 1108   */ /* 
Pool V1: 1056 */
 
 constexpr sal_uInt16                              SDRATTR_EDGE_FIRST         
(SDRATTR_MISC_LAST + 1);    /* 1127   */ /* Pool V4 */
 constexpr TypedWhichId<SdrEdgeKindItem>           SDRATTR_EDGEKIND           
(SDRATTR_EDGE_FIRST + 0);   /*   1127 */ /* Pool V4 */
diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx
index 8a6302659702..a1fa9412afc9 100644
--- a/include/svx/unoshprp.hxx
+++ b/include/svx/unoshprp.hxx
@@ -327,6 +327,7 @@
     { UNO_NAME_TEXT_VERTADJUST,       SDRATTR_TEXT_VERTADJUST,        
cppu::UnoType<css::drawing::TextVerticalAdjust>::get(),    0,      0},\
     { UNO_NAME_TEXT_WORDWRAP,         SDRATTR_TEXT_WORDWRAP,          
cppu::UnoType<bool>::get(),        0,      0}, \
     { UNO_NAME_TEXT_CHAINNEXTNAME,    SDRATTR_TEXT_CHAINNEXTNAME,     
::cppu::UnoType<OUString>::get(),        0,      0}, \
+    { UNO_NAME_TEXT_CLIPVERTOVERFLOW, SDRATTR_TEXT_CLIPVERTOVERFLOW,  
cppu::UnoType<bool>::get(),              0,      0}, \
     { u"TextColumns",                     OWN_ATTR_TEXTCOLUMNS,           
cppu::UnoType<css::text::XTextColumns>::get(), 0, 0 }, \
     SVX_UNOEDIT_CHAR_PROPERTIES, \
     SVX_UNOEDIT_PARA_PROPERTIES,
diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx
index 3503fae4f6ce..5af9956fc45d 100644
--- a/svx/source/svdraw/svdattr.cxx
+++ b/svx/source/svdraw/svdattr.cxx
@@ -171,6 +171,7 @@ SdrItemPool::SdrItemPool(
     rPoolDefaults[SDRATTR_TEXT_CHAINNEXTNAME    -SDRATTR_START]=new 
SfxStringItem(SDRATTR_TEXT_CHAINNEXTNAME, "");
     rPoolDefaults[SDRATTR_TEXT_USEFIXEDCELLHEIGHT -SDRATTR_START]=new 
SdrTextFixedCellHeightItem;
     rPoolDefaults[SDRATTR_TEXT_WORDWRAP         -SDRATTR_START]=new 
SdrOnOffItem(SDRATTR_TEXT_WORDWRAP, true);
+    rPoolDefaults[SDRATTR_TEXT_CLIPVERTOVERFLOW-SDRATTR_START]=new 
SdrOnOffItem(SDRATTR_TEXT_CLIPVERTOVERFLOW, false);
     rPoolDefaults[SDRATTR_EDGEKIND         -SDRATTR_START]=new SdrEdgeKindItem;
     rPoolDefaults[SDRATTR_EDGENODE1HORZDIST-SDRATTR_START]=new 
SdrEdgeNode1HorzDistItem(nDefEdgeDist);
     rPoolDefaults[SDRATTR_EDGENODE1VERTDIST-SDRATTR_START]=new 
SdrEdgeNode1VertDistItem(nDefEdgeDist);
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx 
b/svx/source/svdraw/svdotextdecomposition.cxx
index ddbc6bfe540a..138b709e9769 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -1103,19 +1103,21 @@ void SdrTextObj::impDecomposeBlockTextPrimitive(
         }
     }
 
+    const double fFreeVerticalSpace(aAnchorTextRange.getHeight() - 
aOutlinerScale.getY());
+    bool bClipVerticalTextOverflow = fFreeVerticalSpace < 0
+                                     && 
GetObjectItemSet().Get(SDRATTR_TEXT_CLIPVERTOVERFLOW).GetValue();
     // correct vertical translation using the now known text size
-    if(SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj)
+    if((SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj)
+       && !bClipVerticalTextOverflow)
     {
-        const double fFree(aAnchorTextRange.getHeight() - 
aOutlinerScale.getY());
-
         if(SDRTEXTVERTADJUST_CENTER == eVAdj)
         {
-            aAdjustTranslate.setY(fFree / 2.0);
+            aAdjustTranslate.setY(fFreeVerticalSpace / 2.0);
         }
 
         if(SDRTEXTVERTADJUST_BOTTOM == eVAdj)
         {
-            aAdjustTranslate.setY(fFree);
+            aAdjustTranslate.setY(fFreeVerticalSpace);
         }
     }
 
@@ -1159,6 +1161,8 @@ void SdrTextObj::impDecomposeBlockTextPrimitive(
 
     // create ClipRange (if needed)
     basegfx::B2DRange aClipRange;
+    if(bClipVerticalTextOverflow)
+        aClipRange = {0, 0, std::numeric_limits<double>::max(), 
aAnchorTextRange.getHeight()};
 
     // now break up text primitives.
     impTextBreakupHandler aConverter(rOutliner);

Reply via email to