summaryrefslogtreecommitdiffstats
path: root/svgio/source/svgreader/svgcharacternode.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 11:48:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 11:48:25 +0000
commit9c0049cfae49c8e4ddef9125a69db2ad134c10c6 (patch)
tree812a86c0eee63dfc5ace12f2622ed3ce9cd3d680 /svgio/source/svgreader/svgcharacternode.cxx
parentReleasing progress-linux version 4:24.2.3-2~progress7.99u1. (diff)
downloadlibreoffice-9c0049cfae49c8e4ddef9125a69db2ad134c10c6.tar.xz
libreoffice-9c0049cfae49c8e4ddef9125a69db2ad134c10c6.zip
Merging upstream version 4:24.2.4.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'svgio/source/svgreader/svgcharacternode.cxx')
-rw-r--r--svgio/source/svgreader/svgcharacternode.cxx115
1 files changed, 74 insertions, 41 deletions
diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx
index 02bc3911a3..0aea1976c1 100644
--- a/svgio/source/svgreader/svgcharacternode.cxx
+++ b/svgio/source/svgreader/svgcharacternode.cxx
@@ -138,11 +138,11 @@ namespace svgio::svgreader
{
// prepare retval, index and length
rtl::Reference<BasePrimitive2D> pRetval;
- sal_uInt32 nLength(getText().getLength());
+ const sal_uInt32 nLength(getText().getLength());
if(nLength)
{
- sal_uInt32 nIndex(0);
+ const sal_uInt32 nIndex(0);
// prepare FontAttribute
const drawinglayer::attribute::FontAttribute aFontAttribute(getFontAttribute(rSvgStyleAttributes));
@@ -154,9 +154,12 @@ namespace svgio::svgreader
// prepare locale
css::lang::Locale aLocale;
- // prepare TextLayouterDevice
+ // prepare TextLayouterDevice; use a larger font size for more linear size
+ // calculations. Similar to nTextSizeFactor in sd/source/ui/view/sdview.cxx
+ // (ViewRedirector::createRedirectedPrimitive2DSequence).
+ const double sizeFactor = fFontHeight < 50000 ? 50000 / fFontHeight : 1.0;
TextLayouterDevice aTextLayouterDevice;
- aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale);
+ aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth * sizeFactor, fFontHeight * sizeFactor, aLocale);
// prepare TextArray
::std::vector< double > aTextArray(rSvgTextPosition.getX());
@@ -190,13 +193,13 @@ namespace svgio::svgreader
{
fComulativeDx += aDxArray[a];
}
- aTextArray.push_back(aExtendArray[a] + fStartX + fComulativeDx);
+ aTextArray.push_back(aExtendArray[a] / sizeFactor + fStartX + fComulativeDx);
}
}
// get current TextPosition and TextWidth in units
basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition());
- double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength));
+ double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength) / sizeFactor);
// check for user-given TextLength
if(0.0 != rSvgTextPosition.getTextLength()
@@ -209,7 +212,10 @@ namespace svgio::svgreader
// spacing, need to create and expand TextArray
if(aTextArray.empty())
{
- aTextArray = aTextLayouterDevice.getTextArray(getText(), nIndex, nLength);
+ auto aExtendArray(aTextLayouterDevice.getTextArray(getText(), nIndex, nLength));
+ aTextArray.reserve(aExtendArray.size());
+ for (auto n : aExtendArray)
+ aTextArray.push_back(n / sizeFactor);
}
for(auto &a : aTextArray)
@@ -289,12 +295,12 @@ namespace svgio::svgreader
case DominantBaseline::Middle:
case DominantBaseline::Central:
{
- aPosition.setY(aPosition.getY() - aRange.getCenterY());
+ aPosition.setY(aPosition.getY() - aRange.getCenterY() / sizeFactor);
break;
}
case DominantBaseline::Hanging:
{
- aPosition.setY(aPosition.getY() - aRange.getMinY());
+ aPosition.setY(aPosition.getY() - aRange.getMinY() / sizeFactor);
break;
}
default: // DominantBaseline::Auto
@@ -312,12 +318,12 @@ namespace svgio::svgreader
{
case BaselineShift::Sub:
{
- aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset());
+ aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset() / sizeFactor);
break;
}
case BaselineShift::Super:
{
- aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset());
+ aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset() / sizeFactor);
break;
}
case BaselineShift::Percentage:
@@ -480,53 +486,80 @@ namespace svgio::svgreader
}
}
- void SvgCharacterNode::whiteSpaceHandling()
+ SvgCharacterNode*
+ SvgCharacterNode::whiteSpaceHandling(SvgCharacterNode* pPreviousCharacterNode)
{
bool bIsDefault(XmlSpace::Default == getXmlSpace());
// if xml:space="default" then remove all newline characters, otherwise convert them to space
// convert tab to space too
- maText = maTextBeforeSpaceHandling = maText.replaceAll(u"\n", bIsDefault ? u"" : u" ").replaceAll(u"\t", u" ");
+ maText = maText.replaceAll(u"\n", bIsDefault ? u"" : u" ").replaceAll(u"\t", u" ");
- if(bIsDefault)
+ if (!bIsDefault)
{
- // strip of all leading and trailing spaces
- // and consolidate contiguous space
- maText = consolidateContiguousSpace(maText.trim());
- }
- }
+ if (maText.isEmpty())
+ {
+ // Ignore this empty node for the purpose of whitespace handling
+ return pPreviousCharacterNode;
+ }
- SvgCharacterNode* SvgCharacterNode::addGap(SvgCharacterNode* pPreviousCharacterNode)
- {
- // maText may have lost all text. If that's the case, ignore as invalid character node
- // Also ignore if maTextBeforeSpaceHandling just have spaces
- if(!maText.isEmpty() && !o3tl::trim(maTextBeforeSpaceHandling).empty())
- {
- if(pPreviousCharacterNode)
+ if (pPreviousCharacterNode && pPreviousCharacterNode->mbHadTrailingSpace)
{
- bool bAddGap(true);
+ // pPreviousCharacterNode->mbHadTrailingSpace implies its xml:space="default".
+ // Even if this xml:space="preserve" node is whitespace-only, the trailing space
+ // of the previous node is significant - restore it
+ pPreviousCharacterNode->maText += " ";
+ }
+
+ return this;
+ }
- // Do not add a gap if last node doesn't end with a space and
- // current note doesn't start with a space
- const sal_uInt32 nLastLength(pPreviousCharacterNode->maTextBeforeSpaceHandling.getLength());
- if(pPreviousCharacterNode->maTextBeforeSpaceHandling[nLastLength - 1] != ' ' && maTextBeforeSpaceHandling[0] != ' ')
- bAddGap = false;
+ bool bHadLeadingSpace = maText.startsWith(" ");
+ mbHadTrailingSpace = maText.endsWith(" "); // Only set for xml:space="default"
- // Do not add a gap if this node and last node are in different lines
- if(pPreviousCharacterNode->mpParentLine != mpParentLine)
- bAddGap = false;
+ // strip of all leading and trailing spaces
+ // and consolidate contiguous space
+ maText = consolidateContiguousSpace(maText.trim());
- // add in-between whitespace (single space) to the beginning of the current character node
- if(bAddGap)
+ if (pPreviousCharacterNode)
+ {
+ if (pPreviousCharacterNode->mbHadTrailingSpace)
+ {
+ // pPreviousCharacterNode->mbHadTrailingSpace implies its xml:space="default".
+ // The previous node already has a pending trailing space.
+ if (maText.isEmpty())
{
- maText = " " + maText;
+ // Leading spaces in this empty node are insignificant.
+ // Ignore this empty node for the purpose of whitespace handling
+ return pPreviousCharacterNode;
}
+ // The previous node's trailing space is significant - restore it. Note that
+ // it is incorrect to insert a space in this node instead: the spaces in
+ // different nodes may have different size
+ pPreviousCharacterNode->maText += " ";
+ return this;
}
- // this becomes the previous character node
- return this;
+ if (bHadLeadingSpace)
+ {
+ // This possibly whitespace-only xml:space="default" node goes after another
+ // node either having xml:space="default", but without a trailing space; or
+ // having xml:space="preserve" (in that case, it's irrelevant if that node had
+ // any trailing spaces).
+ if (!maText.isEmpty())
+ {
+ // The leading whitespace in this node is significant - restore it
+ maText = " " + maText;
+ }
+ // The trailing whitespace in this node may or may not be
+ // significant (it will be significant, if there will be more nodes). Keep it as
+ // it is (even empty), but return this, to participate in whitespace handling
+ return this;
+ }
}
- return pPreviousCharacterNode;
+ // No previous node, or no leading/trailing space on the previous node's boundary: if
+ // this is whitespace-only, its whitespace is never significant
+ return maText.isEmpty() ? pPreviousCharacterNode : this;
}
void SvgCharacterNode::concatenate(std::u16string_view rText)