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);