30#include <com/sun/star/i18n/BreakIterator.hpp>
32#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
52 class impPathTextPortion
56 sal_Int32 mnTextStart;
57 sal_Int32 mnTextLength;
58 sal_Int32 mnParagraph;
60 ::std::vector< double > maDblDXArray;
61 ::std::vector< sal_Bool > maKashidaArray;
62 lang::Locale maLocale;
68 : maOffset(rInfo.mrStartPos.
X(), rInfo.mrStartPos.
Y()),
70 mnTextStart(rInfo.mnTextStart),
71 mnTextLength(rInfo.mnTextLen),
72 mnParagraph(rInfo.mnPara),
74 maKashidaArray(rInfo.mpKashidaArray.
begin(), rInfo.mpKashidaArray.
end()),
75 maLocale(rInfo.mpLocale ? *rInfo.mpLocale : lang::
Locale()),
76 mbRTL(!rInfo.mrFont.IsVertical() && rInfo.IsRTL())
80 maDblDXArray.reserve(mnTextLength);
82 for(sal_Int32 a=0;
a < mnTextLength;
a++)
84 maDblDXArray.push_back(
static_cast<double>(rInfo.
mpDXArray[a]));
90 bool operator<(
const impPathTextPortion& rComp)
const
92 if(mnParagraph < rComp.mnParagraph)
97 if(maOffset.
getX() < rComp.maOffset.getX())
102 return (maOffset.
getY() < rComp.maOffset.getY());
105 const OUString& getText()
const {
return maText; }
106 sal_Int32 getTextStart()
const {
return mnTextStart; }
107 sal_Int32 getTextLength()
const {
return mnTextLength; }
108 sal_Int32 getParagraph()
const {
return mnParagraph; }
109 const SvxFont& getFont()
const {
return maFont; }
110 bool isRTL()
const {
return mbRTL; }
111 const ::std::vector< double >& getDoubleDXArray()
const {
return maDblDXArray; }
112 const ::std::vector< sal_Bool >& getKashidaArray()
const {
return maKashidaArray; }
113 const lang::Locale&
getLocale()
const {
return maLocale; }
115 sal_Int32 getPortionIndex(sal_Int32 nIndex, sal_Int32 nLength)
const
119 return (mnTextStart + (mnTextLength - (nIndex + nLength)));
123 return (mnTextStart + nIndex);
127 double getDisplayLength(sal_Int32 nIndex, sal_Int32 nLength)
const
132 if(maFont.IsVertical())
151 class impTextBreakupHandler
154 ::std::vector< impPathTextPortion > maPathTextPortions;
159 explicit impTextBreakupHandler(
SdrOutliner& rOutliner)
160 : mrOutliner(rOutliner)
164 const ::std::vector< impPathTextPortion >& decompositionPathTextPrimitive()
170 if(!maPathTextPortions.empty())
173 ::std::sort(maPathTextPortions.begin(), maPathTextPortions.end());
176 return maPathTextPortions;
182 maPathTextPortions.emplace_back(*pInfo);
191 class impPolygonParagraphHandler
196 uno::Reference<i18n::XBreakIterator> mxBreak;
198 static double getParagraphTextLength(const ::std::vector< const impPathTextPortion* >& rTextPortions)
203 for(
const impPathTextPortion* pCandidate : rTextPortions)
205 if(pCandidate && pCandidate->getTextLength())
207 aTextLayouter.
setFont(pCandidate->getFont());
208 fRetval += pCandidate->getDisplayLength(0, pCandidate->getTextLength());
215 sal_Int32 getNextGlyphLen(
const impPathTextPortion* pCandidate, sal_Int32 nPosition,
const lang::Locale& rFontLocale)
217 sal_Int32 nNextGlyphLen(1);
222 nNextGlyphLen = mxBreak->nextCharacters(pCandidate->getText(), nPosition,
223 rFontLocale, i18n::CharacterIteratorMode::SKIPCELL, 1, nDone) - nPosition;
226 return nNextGlyphLen;
230 impPolygonParagraphHandler(
234 : maSdrFormTextAttribute(
std::move(aSdrFormTextAttribute)),
235 mrDecomposition(rDecomposition),
236 mrShadowDecomposition(rShadowDecomposition)
239 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
240 mxBreak = i18n::BreakIterator::create(xContext);
243 void HandlePair(
const basegfx::B2DPolygon& rPolygonCandidate, const ::std::vector< const impPathTextPortion* >& rTextPortions)
248 double fPolyEnd(fPolyLength);
249 double fPolyStart(0.0);
250 double fAutosizeScaleFactor(1.0);
251 bool bAutosizeScale(
false);
255 aPolygonCandidate.flip();
266 if(fPolyStart > fPolyEnd)
268 fPolyStart = fPolyEnd;
275 if(fPolyEnd < fPolyStart)
277 fPolyEnd = fPolyStart;
285 const double fParagraphTextLength(getParagraphTextLength(rTextPortions));
289 const bool bTextTooLong(fParagraphTextLength > (fPolyEnd - fPolyStart));
296 fPolyStart += ((fPolyEnd - fPolyStart) - fParagraphTextLength);
304 fPolyStart += ((fPolyEnd - fPolyStart) - fParagraphTextLength) / 2.0;
310 if(0.0 != fParagraphTextLength)
312 fAutosizeScaleFactor = (fPolyEnd - fPolyStart) / fParagraphTextLength;
313 bAutosizeScale =
true;
319 for(
auto a = rTextPortions.begin();
a != rTextPortions.end() && fPolyStart < fPolyEnd; ++
a)
321 const impPathTextPortion* pCandidate = *
a;
324 if(pCandidate && pCandidate->getTextLength())
329 pCandidate->getFont(),
334 aTextLayouter.
setFont(pCandidate->getFont());
335 sal_Int32 nUsedTextLength(0);
337 while(nUsedTextLength < pCandidate->getTextLength() && fPolyStart < fPolyEnd)
339 sal_Int32 nNextGlyphLen(getNextGlyphLen(pCandidate, pCandidate->getTextStart() + nUsedTextLength, pCandidate->getLocale()));
342 double fPortionLength(pCandidate->getDisplayLength(nUsedTextLength, nNextGlyphLen));
347 fPortionLength *= fAutosizeScaleFactor;
356 aNewTransformA.
scale(aFontScaling.
getX(), aFontScaling.
getY());
362 aNewTransformA.
scale(fAutosizeScaleFactor, fAutosizeScaleFactor);
381 aNewShadowTransform.
scale(1.0, fScaleValue);
382 aNewShadowTransform.
shearX(sin(fShearValue));
383 aNewShadowTransform.
scale(1.0, cos(fShearValue));
394 aNewTransformB.
translate(aStartPos.getX(), aStartPos.getY());
400 aNewTransformB.
translate(aStartPos.getX() - (fPortionLength / 2.0), aStartPos.getY());
409 const double fSin(sin(fShearValue));
410 const double fCos(cos(fShearValue));
412 aNewTransformB.
shearX(-fSin);
417 aNewTransformB.
scale(1.0, fCos);
418 aNewTransformB.
translate(aStartPos.getX() - (fPortionLength / 2.0), aStartPos.getY());
427 const double fCos(cos(fShearValue));
428 const double fTan(tan(fShearValue));
431 aNewTransformB.
shearY(fTan);
435 aNewTransformA.
scale(fCos, 1.0);
437 aNewTransformB.
translate(aStartPos.getX(), aStartPos.getY());
447 if(aEndPos.equal(aStartPos))
456 aNewTransformB.
translate(aPerpendicular.getX(), aPerpendicular.getY());
459 if(!pCandidate->getText().isEmpty() && nNextGlyphLen)
461 const sal_Int32 nPortionIndex(pCandidate->getPortionIndex(nUsedTextLength, nNextGlyphLen));
462 ::std::vector< double > aNewDXArray;
464 if(nNextGlyphLen > 1 && !pCandidate->getDoubleDXArray().empty())
469 pCandidate->getDoubleDXArray().begin() + nPortionIndex,
470 pCandidate->getDoubleDXArray().begin() + (nPortionIndex + nNextGlyphLen));
472 if(nPortionIndex > 0)
475 double fDXOffset= *(pCandidate->getDoubleDXArray().begin() + (nPortionIndex - 1));
477 aNewDXArray.begin(), aNewDXArray.end(),
478 aNewDXArray.begin(), [fDXOffset](
double x) { return x - fDXOffset; });
485 aNewDXArray.begin(), aNewDXArray.end(),
486 aNewDXArray.begin(), [fAutosizeScaleFactor](
double x) { return x * fAutosizeScaleFactor; });
496 mrShadowDecomposition.push_back(
498 aNewTransformB * aNewShadowTransform * aNewTransformA,
499 pCandidate->getText(),
502 std::vector(aNewDXArray),
503 std::vector(pCandidate->getKashidaArray()),
504 aCandidateFontAttribute,
505 pCandidate->getLocale(),
511 const Color aColor(pCandidate->getFont().GetColor());
514 mrDecomposition.push_back(
516 aNewTransformB * aNewTransformA,
517 pCandidate->getText(),
520 std::move(aNewDXArray),
521 std::vector(pCandidate->getKashidaArray()),
522 aCandidateFontAttribute,
523 pCandidate->getLocale(),
529 nUsedTextLength += nNextGlyphLen;
532 fPolyStart += fPortionLength;
545 void impAddPolygonStrokePrimitives(
552 for(
const auto& rB2DPolyPolygon : rB2DPolyPolyVector)
558 for(
auto const& rPolygon : std::as_const(aB2DPolyPolygon))
563 rPolygon, rLineAttribute, rStrokeAttribute) );
586 if(!aB2DPolyPolyVector.empty())
590 impAddPolygonStrokePrimitives(
596 const sal_uInt32 nStrokeCount(aStrokePrimitives.size());
603 aNewPrimitives.push_back(
605 std::move(aStrokePrimitives),
611 aNewPrimitives.
append( std::move(aStrokePrimitives) );
618 return aNewPrimitives;
644 impTextBreakupHandler aConverter(rOutliner);
645 const ::std::vector< impPathTextPortion > rPathTextPortions = aConverter.decompositionPathTextPrimitive();
647 if(!rPathTextPortions.empty())
654 sal_uInt32 nLoopCount(rPathPolyPolygon.
count());
666 impPolygonParagraphHandler aPolygonParagraphHandler(
668 aRegularDecomposition,
669 aShadowDecomposition);
672 for(
a = 0;
a < nLoopCount;
a++)
675 ::std::vector< const impPathTextPortion* > aParagraphTextPortions;
677 for(
const auto & rCandidate : rPathTextPortions)
679 if(
static_cast<sal_uInt32
>(rCandidate.getParagraph()) ==
a)
681 aParagraphTextPortions.push_back(&rCandidate);
686 if(!aParagraphTextPortions.empty())
688 aPolygonParagraphHandler.HandlePair(rPathPolyPolygon.
getB2DPolygon(
a), aParagraphTextPortions);
692 const sal_uInt32 nShadowCount(aShadowDecomposition.size());
693 const sal_uInt32 nRegularCount(aRegularDecomposition.size());
703 aRetvalA = aShadowDecomposition;
705 impAddPathTextOutlines(
706 aShadowDecomposition,
709 aRetvalA.
append(aOutlines);
712 aRetvalA = std::move(aShadowDecomposition);
723 aRetvalB = aRegularDecomposition;
725 impAddPathTextOutlines(
726 aRegularDecomposition,
729 aRetvalB.
append(aOutlines);
732 aRetvalB = std::move(aRegularDecomposition);
743 rTarget.append(std::move(aRetvalA));
744 rTarget.append(std::move(aRetvalB));
IMPL_LINK(MaskData, PipetteHdl, const OUString &, rId, void)
o3tl::span< const sal_Int32 > mpDXArray
void SetText(const OutlinerParaObject &)
void SetDrawPortionHdl(const Link< DrawPortionInfo *, void > &rLink)
void SetPaperSize(const Size &rSize)
bool SetUpdateLayout(bool bUpdate)
sal_Int32 GetParagraphCount() const
void setVisualizedPage(const SdrPage *pPage)
SdrOutliner & ImpGetDrawOutliner() const
void impDecomposePathTextPrimitive(drawinglayer::primitive2d::Primitive2DContainer &rTarget, const drawinglayer::primitive2d::SdrPathTextPrimitive2D &rSdrPathTextPrimitive, const drawinglayer::geometry::ViewInformation2D &aViewInformation) const
void rotate(double fRadiant)
void translate(double fX, double fY)
void scale(double fX, double fY)
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void transform(const basegfx::B2DHomMatrix &rMatrix)
sal_Int32 getFormTextShdwXVal() const
XFormTextAdjust getFormTextAdjust() const
sal_Int32 getFormTextStart() const
Color const & getFormTextShdwColor() const
sal_Int32 getFormTextDistance() const
sal_Int32 getFormTextShdwYVal() const
bool getFormTextOutline() const
XFormTextStyle getFormTextStyle() const
const SdrFormTextOutlineAttribute & getShadowOutline() const
bool getFormTextMirror() const
XFormTextShadow getFormTextShadow() const
const SdrFormTextOutlineAttribute & getOutline() const
const LineAttribute & getLineAttribute() const
const StrokeAttribute & getStrokeAttribute() const
sal_uInt8 getTransparence() const
void append(const Primitive2DReference &)
const basegfx::B2DPolyPolygon & getPathPolyPolygon() const
const attribute::SdrFormTextAttribute & getSdrFormTextAttribute() const
const OutlinerParaObject & getOutlinerParaObject() const
double getTextWidth(const OUString &rText, sal_uInt32 nIndex, sal_uInt32 nLength) const
void setFont(const vcl::Font &rFont)
double getTextHeight() const
void getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector &rTarget, basegfx::B2DHomMatrix &rTransformation) const
constexpr bool empty() const noexcept
DECL_LINK(CheckNameHdl, SvxNameDialog &, bool)
#define LINK(Instance, Class, Member)
double getLength(const B2DPolygon &rCandidate)
B2DPoint getPositionAbsolute(const B2DPolygon &rCandidate, double fDistance, double fLength)
B2DVector getNormalizedPerpendicular(const B2DVector &rVec)
::std::vector< B2DPolyPolygon > B2DPolyPolygonVector
const LanguageTag & getLocale()
attribute::FontAttribute getFontAttributeFromVclFont(basegfx::B2DVector &o_rSize, const vcl::Font &rFont, bool bRTL, bool bBiDiStrong)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
enumrange< T >::Iterator begin(enumrange< T >)
css::drawing::Direction3D aDirection
bool operator<(const Subset &rLHS, const Subset &rRHS)
SdrPage * GetSdrPageFromXDrawPage(const uno::Reference< drawing::XDrawPage > &xDrawPage) noexcept
returns the SdrObject from the given StarOffice API wrapper