StripPortions: Move tooling closer to EditEngine/Outliner
EditEngine/Outliner::StripPortions is used with some lambda callbacks to convert Text to Primitives. The tooling for this is currently located in svx due to historical reasons (when I initially did that). An EditEngine/Outliner gets configured, this is dependent of the object type to handle (see TextBreakupHandler in svx and other places). Then the OutlinerParaObject gets set - the model data. EditEngine::StripPortions then initially uses ImpEditEngine::Paint which layouts all that and formats it. For all Text (or Graphics e.g. Bullets) those callbacks are used - if given. If not given it *still* does a direct paint to a given OutputDevice to stay compatible with legacy usages. Thus ImpEditEngine::Paint is currently kind of an hybrid: It needs to be capable of both: For Primitive creation it extracts data to DrawPortionInfo or DrawBulletInfo and calls the lambda callback where (e.g. in svx) the Primitives are created as needed based on that data. For Paint that data is used to Paint using the given OutputDevice. This means up to now for doing changes both had to be supported in that method which of course hosts the danger of getting unequal outputs when not being very careful. The DirectPaint is now rarely used (AFAIK only in some UI elements, e.g. WeldEditView stuff). The goal is to go in a direction where it would be possible to do those remaining Paint calls direcly inside ImpEditEngine using primitives, or - alternatively - change all remaining places to use a unified StripPortions method and send the result to a PrimitiveRenderer or buffer/resue it. This change is a 1st step to get the preconditions but does not change functionality yet. It moves that tooling to where it is used. Change-Id: I7225eab9a0dfd3d50cd3d1d8fe386dfb99ec42ef Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186045 Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com> Tested-by: Jenkins
This commit is contained in:
committed by
Armin Le Grand
parent
c4b3f7a6f9
commit
782131d3a3
@@ -29,6 +29,8 @@ $(eval $(call gb_CppunitTest_use_libraries,editeng_core, \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
docmodel \
|
||||
drawinglayercore \
|
||||
drawinglayer \
|
||||
i18nlangtag \
|
||||
i18nutil \
|
||||
lng \
|
||||
|
||||
@@ -23,6 +23,8 @@ $(eval $(call gb_CppunitTest_use_libraries,editeng_editeng, \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
docmodel \
|
||||
drawinglayercore \
|
||||
drawinglayer \
|
||||
i18nlangtag \
|
||||
i18nutil \
|
||||
lng \
|
||||
|
||||
@@ -73,6 +73,7 @@ $(eval $(call gb_Library_add_exception_objects,editeng,\
|
||||
editeng/source/editeng/impedit5 \
|
||||
editeng/source/editeng/misspellrange \
|
||||
editeng/source/editeng/section \
|
||||
editeng/source/editeng/StripPortionsHelper \
|
||||
editeng/source/editeng/textconv \
|
||||
editeng/source/editeng/TextPortionList \
|
||||
editeng/source/items/borderline \
|
||||
@@ -142,6 +143,8 @@ $(eval $(call gb_Library_use_libraries,editeng,\
|
||||
xo \
|
||||
basegfx \
|
||||
docmodel \
|
||||
drawinglayercore \
|
||||
drawinglayer \
|
||||
lng \
|
||||
svt \
|
||||
tk \
|
||||
|
||||
@@ -0,0 +1,569 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
#include <drawinglayer/attribute/fontattribute.hxx>
|
||||
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
|
||||
#include <editeng/escapementitem.hxx>
|
||||
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
|
||||
#include <editeng/smallcaps.hxx>
|
||||
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
|
||||
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
|
||||
|
||||
// anonymous helpers
|
||||
namespace
|
||||
{
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>
|
||||
CheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive,
|
||||
const DrawPortionInfo& rInfo)
|
||||
{
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> xRet = pPrimitive;
|
||||
if (rInfo.mpFieldData)
|
||||
{
|
||||
// Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D
|
||||
// which holds the field type and, if applicable, the URL
|
||||
const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(rInfo.mpFieldData);
|
||||
const SvxPageField* pPageField = dynamic_cast<const SvxPageField*>(rInfo.mpFieldData);
|
||||
|
||||
// embed current primitive to a sequence
|
||||
drawinglayer::primitive2d::Primitive2DContainer aSequence;
|
||||
|
||||
if (pPrimitive)
|
||||
{
|
||||
aSequence.resize(1);
|
||||
aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive);
|
||||
}
|
||||
|
||||
if (pURLField)
|
||||
{
|
||||
// extended this to hold more of the contents of the original
|
||||
// SvxURLField since that stuff is still used in HitTest and e.g. Calc
|
||||
std::vector<std::pair<OUString, OUString>> meValues;
|
||||
meValues.emplace_back("URL", pURLField->GetURL());
|
||||
meValues.emplace_back("Representation", pURLField->GetRepresentation());
|
||||
meValues.emplace_back("TargetFrame", pURLField->GetTargetFrame());
|
||||
meValues.emplace_back("AltText", pURLField->GetName());
|
||||
meValues.emplace_back(
|
||||
"SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat())));
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(
|
||||
std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues);
|
||||
}
|
||||
else if (pPageField)
|
||||
{
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(
|
||||
std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_PAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(
|
||||
std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_COMMON);
|
||||
}
|
||||
}
|
||||
|
||||
return xRet;
|
||||
}
|
||||
|
||||
class DoCapitalsDrawPortionInfo : public SvxDoCapitals
|
||||
{
|
||||
private:
|
||||
drawinglayer::primitive2d::Primitive2DContainer& mrTarget;
|
||||
const basegfx::B2DHomMatrix& mrNewTransformA;
|
||||
const basegfx::B2DHomMatrix& mrNewTransformB;
|
||||
const DrawPortionInfo& m_rInfo;
|
||||
SvxFont m_aFont;
|
||||
|
||||
public:
|
||||
DoCapitalsDrawPortionInfo(drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo)
|
||||
: SvxDoCapitals(rInfo.maText, rInfo.mnTextStart, rInfo.mnTextLen)
|
||||
, mrTarget(rTarget)
|
||||
, mrNewTransformA(rNewTransformA)
|
||||
, mrNewTransformB(rNewTransformB)
|
||||
, m_rInfo(rInfo)
|
||||
, m_aFont(rInfo.mrFont)
|
||||
{
|
||||
assert(!m_rInfo.mpDXArray.empty());
|
||||
|
||||
/* turn all these off as they are handled outside subportions for the whole portion */
|
||||
m_aFont.SetTransparent(false);
|
||||
m_aFont.SetUnderline(LINESTYLE_NONE);
|
||||
m_aFont.SetOverline(LINESTYLE_NONE);
|
||||
m_aFont.SetStrikeout(STRIKEOUT_NONE);
|
||||
|
||||
m_aFont.SetCaseMap(SvxCaseMap::NotMapped); /* otherwise this would call itself */
|
||||
}
|
||||
virtual void Do(const OUString& rSpanTxt, const sal_Int32 nSpanIdx, const sal_Int32 nSpanLen,
|
||||
const bool bUpper) override
|
||||
{
|
||||
sal_uInt8 nProp(0);
|
||||
if (!bUpper)
|
||||
{
|
||||
nProp = m_aFont.GetPropr();
|
||||
m_aFont.SetProprRel(SMALL_CAPS_PERCENTAGE);
|
||||
}
|
||||
|
||||
sal_Int32 nStartOffset = nSpanIdx - nIdx;
|
||||
double nStartX = nStartOffset ? m_rInfo.mpDXArray[nStartOffset - 1] : 0;
|
||||
|
||||
Point aStartPos(m_rInfo.mrStartPos.X() + nStartX, m_rInfo.mrStartPos.Y());
|
||||
|
||||
KernArray aDXArray;
|
||||
aDXArray.resize(nSpanLen);
|
||||
for (sal_Int32 i = 0; i < nSpanLen; ++i)
|
||||
aDXArray[i] = m_rInfo.mpDXArray[nStartOffset + i] - nStartX;
|
||||
|
||||
auto aKashidaArray = !m_rInfo.mpKashidaArray.empty()
|
||||
? std::span<const sal_Bool>(
|
||||
m_rInfo.mpKashidaArray.data() + nStartOffset, nSpanLen)
|
||||
: std::span<const sal_Bool>();
|
||||
|
||||
DrawPortionInfo aInfo(aStartPos, rSpanTxt, nSpanIdx, nSpanLen, aDXArray, aKashidaArray,
|
||||
m_aFont, m_rInfo.mnPara, m_rInfo.mnBiDiLevel,
|
||||
nullptr, /* no spelling in subportion, handled outside */
|
||||
nullptr, /* no field in subportion, handled outside */
|
||||
false, false, false, m_rInfo.mpLocale, m_rInfo.maOverlineColor,
|
||||
m_rInfo.maTextLineColor);
|
||||
|
||||
CreateTextPortionPrimitivesFromDrawPortionInfo(mrTarget, mrNewTransformA, mrNewTransformB,
|
||||
aInfo);
|
||||
|
||||
if (!bUpper)
|
||||
m_aFont.SetPropr(nProp);
|
||||
}
|
||||
};
|
||||
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D>
|
||||
buildTextPortionPrimitive(const DrawPortionInfo& rInfo, const OUString& rText,
|
||||
const drawinglayer::attribute::FontAttribute& rFontAttribute,
|
||||
const std::vector<double>& rDXArray,
|
||||
const basegfx::B2DHomMatrix& rNewTransform)
|
||||
{
|
||||
::std::vector<sal_Bool> aKashidaArray;
|
||||
|
||||
if (!rInfo.mpKashidaArray.empty() && rInfo.mnTextLen)
|
||||
{
|
||||
aKashidaArray.reserve(rInfo.mnTextLen);
|
||||
|
||||
for (sal_Int32 a = 0; a < rInfo.mnTextLen; a++)
|
||||
{
|
||||
aKashidaArray.push_back(rInfo.mpKashidaArray[a]);
|
||||
}
|
||||
}
|
||||
|
||||
// create complex text primitive and append
|
||||
const Color aFontColor(rInfo.mrFont.GetColor());
|
||||
const basegfx::BColor aBFontColor(aFontColor.getBColor());
|
||||
|
||||
const Color aTextFillColor(rInfo.mrFont.GetFillColor());
|
||||
|
||||
// prepare wordLineMode (for underline and strikeout)
|
||||
// NOT for bullet texts. It is set (this may be an error by itself), but needs to be suppressed to hinder e.g. '1)'
|
||||
// to be split which would not look like the original
|
||||
const bool bWordLineMode(rInfo.mrFont.IsWordLineMode() && !rInfo.mbEndOfBullet);
|
||||
|
||||
// prepare new primitive
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive;
|
||||
const bool bDecoratedIsNeeded(
|
||||
LINESTYLE_NONE != rInfo.mrFont.GetOverline()
|
||||
|| LINESTYLE_NONE != rInfo.mrFont.GetUnderline()
|
||||
|| STRIKEOUT_NONE != rInfo.mrFont.GetStrikeout()
|
||||
|| FontEmphasisMark::NONE != (rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::Style)
|
||||
|| FontRelief::NONE != rInfo.mrFont.GetRelief() || rInfo.mrFont.IsShadow()
|
||||
|| bWordLineMode);
|
||||
|
||||
if (bDecoratedIsNeeded)
|
||||
{
|
||||
// TextDecoratedPortionPrimitive2D needed, prepare some more data
|
||||
// get overline and underline color. If it's on automatic (0xffffffff) use FontColor instead
|
||||
const Color aUnderlineColor(rInfo.maTextLineColor);
|
||||
const basegfx::BColor aBUnderlineColor(
|
||||
(aUnderlineColor == COL_AUTO) ? aBFontColor : aUnderlineColor.getBColor());
|
||||
const Color aOverlineColor(rInfo.maOverlineColor);
|
||||
const basegfx::BColor aBOverlineColor(
|
||||
(aOverlineColor == COL_AUTO) ? aBFontColor : aOverlineColor.getBColor());
|
||||
|
||||
// prepare overline and underline data
|
||||
const drawinglayer::primitive2d::TextLine eFontOverline(
|
||||
drawinglayer::primitive2d::mapFontLineStyleToTextLine(rInfo.mrFont.GetOverline()));
|
||||
const drawinglayer::primitive2d::TextLine eFontLineStyle(
|
||||
drawinglayer::primitive2d::mapFontLineStyleToTextLine(rInfo.mrFont.GetUnderline()));
|
||||
|
||||
// check UnderlineAbove
|
||||
const bool bUnderlineAbove(drawinglayer::primitive2d::TEXT_LINE_NONE != eFontLineStyle
|
||||
&& rInfo.mrFont.IsUnderlineAbove());
|
||||
|
||||
// prepare strikeout data
|
||||
const drawinglayer::primitive2d::TextStrikeout eTextStrikeout(
|
||||
drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(
|
||||
rInfo.mrFont.GetStrikeout()));
|
||||
|
||||
// prepare emphasis mark data
|
||||
drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(
|
||||
drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_NONE);
|
||||
|
||||
switch (rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::Style)
|
||||
{
|
||||
case FontEmphasisMark::Dot:
|
||||
eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DOT;
|
||||
break;
|
||||
case FontEmphasisMark::Circle:
|
||||
eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_CIRCLE;
|
||||
break;
|
||||
case FontEmphasisMark::Disc:
|
||||
eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DISC;
|
||||
break;
|
||||
case FontEmphasisMark::Accent:
|
||||
eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_ACCENT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const bool bEmphasisMarkAbove(rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::PosAbove);
|
||||
const bool bEmphasisMarkBelow(rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::PosBelow);
|
||||
|
||||
// prepare font relief data
|
||||
drawinglayer::primitive2d::TextRelief eTextRelief(
|
||||
drawinglayer::primitive2d::TEXT_RELIEF_NONE);
|
||||
|
||||
switch (rInfo.mrFont.GetRelief())
|
||||
{
|
||||
case FontRelief::Embossed:
|
||||
eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED;
|
||||
break;
|
||||
case FontRelief::Engraved:
|
||||
eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED;
|
||||
break;
|
||||
default:
|
||||
break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE
|
||||
}
|
||||
|
||||
// prepare shadow/outline data
|
||||
const bool bShadow(rInfo.mrFont.IsShadow());
|
||||
|
||||
// TextDecoratedPortionPrimitive2D is needed, create one
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
|
||||
|
||||
// attributes for TextSimplePortionPrimitive2D
|
||||
rNewTransform, rText, rInfo.mnTextStart, rInfo.mnTextLen, std::vector(rDXArray),
|
||||
std::move(aKashidaArray), rFontAttribute,
|
||||
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(), aBFontColor, aTextFillColor,
|
||||
|
||||
// attributes for TextDecoratedPortionPrimitive2D
|
||||
aBOverlineColor, aBUnderlineColor, eFontOverline, eFontLineStyle, bUnderlineAbove,
|
||||
eTextStrikeout, bWordLineMode, eTextEmphasisMark, bEmphasisMarkAbove,
|
||||
bEmphasisMarkBelow, eTextRelief, bShadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TextSimplePortionPrimitive2D is enough
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
|
||||
rNewTransform, rText, rInfo.mnTextStart, rInfo.mnTextLen, std::vector(rDXArray),
|
||||
std::move(aKashidaArray), rFontAttribute,
|
||||
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(), aBFontColor, aTextFillColor);
|
||||
}
|
||||
|
||||
return pNewPrimitive;
|
||||
}
|
||||
} // end of anonymous namespace
|
||||
|
||||
// Outliner helpers
|
||||
void CreateTextPortionPrimitivesFromDrawPortionInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo)
|
||||
{
|
||||
if (rInfo.maText.isEmpty() || !rInfo.mnTextLen)
|
||||
return;
|
||||
|
||||
basegfx::B2DVector aFontScaling;
|
||||
drawinglayer::attribute::FontAttribute aFontAttribute(
|
||||
drawinglayer::primitive2d::getFontAttributeFromVclFont(aFontScaling, rInfo.mrFont,
|
||||
rInfo.IsRTL(), false));
|
||||
basegfx::B2DHomMatrix aNewTransform;
|
||||
|
||||
// add font scale to new transform
|
||||
aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY());
|
||||
|
||||
// look for proportional font scaling, if necessary, scale accordingly
|
||||
sal_Int8 nPropr(rInfo.mrFont.GetPropr());
|
||||
const double fPropFontFactor(nPropr / 100.0);
|
||||
if (100 != nPropr)
|
||||
aNewTransform.scale(fPropFontFactor, fPropFontFactor);
|
||||
|
||||
// apply font rotate
|
||||
if (rInfo.mrFont.GetOrientation())
|
||||
{
|
||||
aNewTransform.rotate(-toRadians(rInfo.mrFont.GetOrientation()));
|
||||
}
|
||||
|
||||
// look for escapement, if necessary, translate accordingly
|
||||
if (rInfo.mrFont.GetEscapement())
|
||||
{
|
||||
sal_Int16 nEsc(rInfo.mrFont.GetEscapement());
|
||||
|
||||
if (DFLT_ESC_AUTO_SUPER == nEsc)
|
||||
{
|
||||
nEsc = .8 * (100 - nPropr);
|
||||
assert(nEsc == DFLT_ESC_SUPER
|
||||
&& "I'm sure this formula needs to be changed, but how to confirm that???");
|
||||
nEsc = DFLT_ESC_SUPER;
|
||||
}
|
||||
else if (DFLT_ESC_AUTO_SUB == nEsc)
|
||||
{
|
||||
nEsc = .2 * -(100 - nPropr);
|
||||
assert(nEsc == -20
|
||||
&& "I'm sure this formula needs to be changed, but how to confirm that???");
|
||||
nEsc = -20;
|
||||
}
|
||||
|
||||
if (nEsc > MAX_ESC_POS)
|
||||
{
|
||||
nEsc = MAX_ESC_POS;
|
||||
}
|
||||
else if (nEsc < -MAX_ESC_POS)
|
||||
{
|
||||
nEsc = -MAX_ESC_POS;
|
||||
}
|
||||
|
||||
const double fEscapement(nEsc / -100.0);
|
||||
aNewTransform.translate(0.0, fEscapement * aFontScaling.getY());
|
||||
}
|
||||
|
||||
// apply transformA
|
||||
aNewTransform *= rNewTransformA;
|
||||
|
||||
// apply local offset
|
||||
aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y());
|
||||
|
||||
// also apply embedding object's transform
|
||||
aNewTransform *= rNewTransformB;
|
||||
|
||||
// prepare DXArray content. To make it independent from font size (and such from
|
||||
// the text transformation), scale it to unit coordinates
|
||||
::std::vector<double> aDXArray;
|
||||
|
||||
if (!rInfo.mpDXArray.empty())
|
||||
{
|
||||
aDXArray.reserve(rInfo.mnTextLen);
|
||||
for (sal_Int32 a = 0; a < rInfo.mnTextLen; a++)
|
||||
{
|
||||
aDXArray.push_back(rInfo.mpDXArray[a]);
|
||||
}
|
||||
}
|
||||
|
||||
OUString caseMappedText = rInfo.mrFont.CalcCaseMap(rInfo.maText);
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive(
|
||||
buildTextPortionPrimitive(rInfo, caseMappedText, aFontAttribute, aDXArray, aNewTransform));
|
||||
|
||||
bool bSmallCaps = rInfo.mrFont.IsCapital();
|
||||
if (bSmallCaps && rInfo.mpDXArray.empty())
|
||||
{
|
||||
SAL_WARN("svx", "SmallCaps requested with DXArray, abandoning");
|
||||
bSmallCaps = false;
|
||||
}
|
||||
if (bSmallCaps)
|
||||
{
|
||||
// rerun with each sub-portion
|
||||
DoCapitalsDrawPortionInfo aDoDrawPortionInfo(rTarget, rNewTransformA, rNewTransformB,
|
||||
rInfo);
|
||||
rInfo.mrFont.DoOnCapitals(aDoDrawPortionInfo);
|
||||
|
||||
// transfer collected primitives from rTarget to a new container
|
||||
drawinglayer::primitive2d::Primitive2DContainer aContainer = std::move(rTarget);
|
||||
|
||||
// Take any decoration for the whole formatted portion and keep it to get continuous over/under/strike-through
|
||||
if (pNewPrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
|
||||
{
|
||||
const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pTCPP
|
||||
= static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(
|
||||
pNewPrimitive.get());
|
||||
|
||||
if (pTCPP->getWordLineMode()) // single word mode: 'Individual words' in UI
|
||||
{
|
||||
// Split to single word primitives using TextBreakupHelper
|
||||
drawinglayer::primitive2d::TextBreakupHelper aTextBreakupHelper(*pTCPP);
|
||||
drawinglayer::primitive2d::Primitive2DContainer aBroken(
|
||||
aTextBreakupHelper.extractResult(drawinglayer::primitive2d::BreakupUnit::Word));
|
||||
for (auto& rPortion : aBroken)
|
||||
{
|
||||
assert(rPortion->getPrimitive2DID()
|
||||
== PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D
|
||||
&& "TextBreakupHelper generates same output primitive type as input");
|
||||
|
||||
const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pPortion
|
||||
= static_cast<
|
||||
const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(
|
||||
rPortion.get());
|
||||
|
||||
// create and add decoration
|
||||
const drawinglayer::primitive2d::Primitive2DContainer&
|
||||
rDecorationGeometryContent(pPortion->getOrCreateDecorationGeometryContent(
|
||||
pPortion->getTextTransform(), caseMappedText,
|
||||
pPortion->getTextPosition(), pPortion->getTextLength(),
|
||||
pPortion->getDXArray()));
|
||||
|
||||
aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(),
|
||||
rDecorationGeometryContent.end());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and add decoration
|
||||
const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent(
|
||||
pTCPP->getOrCreateDecorationGeometryContent(pTCPP->getTextTransform(),
|
||||
caseMappedText, rInfo.mnTextStart,
|
||||
rInfo.mnTextLen, aDXArray));
|
||||
|
||||
aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(),
|
||||
rDecorationGeometryContent.end());
|
||||
}
|
||||
}
|
||||
|
||||
pNewPrimitive = new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer));
|
||||
}
|
||||
|
||||
const Color aFontColor(rInfo.mrFont.GetColor());
|
||||
if (aFontColor.IsTransparent())
|
||||
{
|
||||
// Handle semi-transparent text for both the decorated and simple case here.
|
||||
pNewPrimitive = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
|
||||
drawinglayer::primitive2d::Primitive2DContainer{ pNewPrimitive },
|
||||
(255 - aFontColor.GetAlpha()) / 255.0);
|
||||
}
|
||||
|
||||
if (rInfo.mbEndOfBullet)
|
||||
{
|
||||
// embed in TextHierarchyBulletPrimitive2D
|
||||
drawinglayer::primitive2d::Primitive2DContainer aNewSequence{ pNewPrimitive };
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(
|
||||
std::move(aNewSequence));
|
||||
}
|
||||
|
||||
if (rInfo.mpFieldData)
|
||||
{
|
||||
pNewPrimitive = CheckFieldPrimitive(pNewPrimitive.get(), rInfo);
|
||||
}
|
||||
|
||||
rTarget.push_back(pNewPrimitive);
|
||||
|
||||
// support for WrongSpellVector. Create WrongSpellPrimitives as needed
|
||||
if (!rInfo.mpWrongSpellVector || aDXArray.empty())
|
||||
return;
|
||||
|
||||
const sal_Int32 nSize(rInfo.mpWrongSpellVector->size());
|
||||
const sal_Int32 nDXCount(aDXArray.size());
|
||||
const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded
|
||||
|
||||
for (sal_Int32 a(0); a < nSize; a++)
|
||||
{
|
||||
const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a];
|
||||
|
||||
if (rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart
|
||||
&& rCandidate.nEnd > rCandidate.nStart)
|
||||
{
|
||||
const sal_Int32 nStart(rCandidate.nStart - rInfo.mnTextStart);
|
||||
const sal_Int32 nEnd(rCandidate.nEnd - rInfo.mnTextStart);
|
||||
double fStart(0.0);
|
||||
double fEnd(0.0);
|
||||
|
||||
if (nStart > 0 && nStart - 1 < nDXCount)
|
||||
{
|
||||
fStart = aDXArray[nStart - 1];
|
||||
}
|
||||
|
||||
if (nEnd > 0 && nEnd - 1 < nDXCount)
|
||||
{
|
||||
fEnd = aDXArray[nEnd - 1];
|
||||
}
|
||||
|
||||
if (!basegfx::fTools::equal(fStart, fEnd))
|
||||
{
|
||||
if (rInfo.IsRTL())
|
||||
{
|
||||
// #i98523#
|
||||
// When the portion is RTL, mirror the redlining using the
|
||||
// full portion width
|
||||
const double fTextWidth(aDXArray[aDXArray.size() - 1]);
|
||||
|
||||
fStart = fTextWidth - fStart;
|
||||
fEnd = fTextWidth - fEnd;
|
||||
}
|
||||
|
||||
// need to take FontScaling out of values; it's already part of
|
||||
// aNewTransform and would be double applied
|
||||
const double fFontScaleX(aFontScaling.getX() * fPropFontFactor);
|
||||
|
||||
if (!basegfx::fTools::equal(fFontScaleX, 1.0)
|
||||
&& !basegfx::fTools::equalZero(fFontScaleX))
|
||||
{
|
||||
fStart /= fFontScaleX;
|
||||
fEnd /= fFontScaleX;
|
||||
}
|
||||
|
||||
rTarget.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D(
|
||||
aNewTransform, fStart, fEnd, aSpellColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDrawBulletPrimitivesFromDrawBulletInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawBulletInfo& rInfo)
|
||||
{
|
||||
basegfx::B2DHomMatrix aNewTransform;
|
||||
|
||||
// add size to new transform
|
||||
aNewTransform.scale(rInfo.maBulletSize.getWidth(), rInfo.maBulletSize.getHeight());
|
||||
|
||||
// apply transformA
|
||||
aNewTransform *= rNewTransformA;
|
||||
|
||||
// apply local offset
|
||||
aNewTransform.translate(rInfo.maBulletPosition.X(), rInfo.maBulletPosition.Y());
|
||||
|
||||
// also apply embedding object's transform
|
||||
aNewTransform *= rNewTransformB;
|
||||
|
||||
// prepare empty GraphicAttr
|
||||
const GraphicAttr aGraphicAttr;
|
||||
|
||||
// create GraphicPrimitive2D
|
||||
const drawinglayer::primitive2d::Primitive2DReference aNewReference(
|
||||
new drawinglayer::primitive2d::GraphicPrimitive2D(
|
||||
aNewTransform, rInfo.maBulletGraphicObject, aGraphicAttr));
|
||||
|
||||
// embed in TextHierarchyBulletPrimitive2D
|
||||
drawinglayer::primitive2d::Primitive2DContainer aNewSequence{ aNewReference };
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive
|
||||
= new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence));
|
||||
|
||||
// add to output
|
||||
rTarget.push_back(pNewPrimitive);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -47,8 +47,10 @@
|
||||
#include <editeng/scriptspaceitem.hxx>
|
||||
#include <editeng/charscaleitem.hxx>
|
||||
#include <editeng/numitem.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
#include <outleeng.hxx>
|
||||
#include <TextPortion.hxx>
|
||||
#include <tools/gen.hxx>
|
||||
|
||||
#include <svtools/colorcfg.hxx>
|
||||
#include <svl/ctloptions.hxx>
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <o3tl/string_view.hxx>
|
||||
#include <o3tl/temporary.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
|
||||
#include <memory>
|
||||
using std::advance;
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_EDITENG_STRIPPORTIONSHELPER_HXX
|
||||
#define INCLUDED_EDITENG_STRIPPORTIONSHELPER_HXX
|
||||
|
||||
#include <editeng/editengdllapi.h>
|
||||
|
||||
#include <tools/gen.hxx>
|
||||
#include <tools/color.hxx>
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <vcl/kernarray.hxx>
|
||||
#include <vcl/GraphicObject.hxx>
|
||||
#include <editeng/svxfont.hxx>
|
||||
#include <editeng/eedata.hxx>
|
||||
#include <editeng/flditem.hxx>
|
||||
|
||||
namespace com::sun::star::lang
|
||||
{
|
||||
struct Locale;
|
||||
}
|
||||
|
||||
class EDITENG_DLLPUBLIC DrawPortionInfo
|
||||
{
|
||||
public:
|
||||
const Point& mrStartPos;
|
||||
const OUString maText;
|
||||
sal_Int32 mnTextStart;
|
||||
sal_Int32 mnTextLen;
|
||||
KernArraySpan mpDXArray;
|
||||
std::span<const sal_Bool> mpKashidaArray;
|
||||
const SvxFont& mrFont;
|
||||
sal_Int32 mnPara;
|
||||
sal_uInt8 mnBiDiLevel;
|
||||
const EEngineData::WrongSpellVector* mpWrongSpellVector;
|
||||
const SvxFieldData* mpFieldData;
|
||||
bool mbEndOfLine : 1;
|
||||
bool mbEndOfParagraph : 1;
|
||||
bool mbEndOfBullet : 1;
|
||||
const com::sun::star::lang::Locale* mpLocale;
|
||||
const Color maOverlineColor;
|
||||
const Color maTextLineColor;
|
||||
|
||||
bool IsRTL() const { return mnBiDiLevel % 2 == 1; }
|
||||
|
||||
DrawPortionInfo(const Point& rPos, OUString aTxt, sal_Int32 nTxtStart, sal_Int32 nTxtLen,
|
||||
KernArraySpan pDXArr, std::span<const sal_Bool> pKashidaArr,
|
||||
const SvxFont& rFnt, sal_Int32 nPar, sal_uInt8 nBiDiLevel,
|
||||
const EEngineData::WrongSpellVector* pWrongSpellVector,
|
||||
const SvxFieldData* pFieldData, bool bEndOfLine, bool bEndOfParagraph,
|
||||
bool bEndOfBullet, const com::sun::star::lang::Locale* pLocale,
|
||||
const Color& rOverlineColor, const Color& rTextLineColor)
|
||||
: mrStartPos(rPos)
|
||||
, maText(std::move(aTxt))
|
||||
, mnTextStart(nTxtStart)
|
||||
, mnTextLen(nTxtLen)
|
||||
, mpDXArray(pDXArr)
|
||||
, mpKashidaArray(pKashidaArr)
|
||||
, mrFont(rFnt)
|
||||
, mnPara(nPar)
|
||||
, mnBiDiLevel(nBiDiLevel)
|
||||
, mpWrongSpellVector(pWrongSpellVector)
|
||||
, mpFieldData(pFieldData)
|
||||
, mbEndOfLine(bEndOfLine)
|
||||
, mbEndOfParagraph(bEndOfParagraph)
|
||||
, mbEndOfBullet(bEndOfBullet)
|
||||
, mpLocale(pLocale)
|
||||
, maOverlineColor(rOverlineColor)
|
||||
, maTextLineColor(rTextLineColor)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class EDITENG_DLLPUBLIC DrawBulletInfo
|
||||
{
|
||||
public:
|
||||
const GraphicObject maBulletGraphicObject;
|
||||
Point maBulletPosition;
|
||||
Size maBulletSize;
|
||||
|
||||
DrawBulletInfo(const GraphicObject& rBulletGraphicObject, const Point& rBulletPosition,
|
||||
const Size& rBulletSize)
|
||||
: maBulletGraphicObject(rBulletGraphicObject)
|
||||
, maBulletPosition(rBulletPosition)
|
||||
, maBulletSize(rBulletSize)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace drawinglayer::primitive2d
|
||||
{
|
||||
class Primitive2DContainer;
|
||||
}
|
||||
namespace basegfx
|
||||
{
|
||||
class B2DHomMatrix;
|
||||
}
|
||||
|
||||
void EDITENG_DLLPUBLIC CreateTextPortionPrimitivesFromDrawPortionInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo);
|
||||
void EDITENG_DLLPUBLIC CreateDrawBulletPrimitivesFromDrawBulletInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawBulletInfo& rInfo);
|
||||
|
||||
#endif // INCLUDED_EDITENG_STRIPPORTIONSHELPER_HXX
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -80,6 +80,8 @@ enum class PointerStyle;
|
||||
class SvxNumRule;
|
||||
enum class TextRotation;
|
||||
enum class SdrCompatibilityFlag;
|
||||
class DrawPortionInfo;
|
||||
class DrawBulletInfo;
|
||||
|
||||
namespace com::sun::star::linguistic2 {
|
||||
class XSpellChecker1;
|
||||
@@ -399,84 +401,6 @@ void EDITENG_DLLPUBLIC ReplaceTextWithSynonym( EditView &rEditView, const OUStr
|
||||
|
||||
typedef ::std::vector< OutlinerView* > ViewList;
|
||||
|
||||
class EDITENG_DLLPUBLIC DrawPortionInfo
|
||||
{
|
||||
public:
|
||||
const Point& mrStartPos;
|
||||
const OUString maText;
|
||||
sal_Int32 mnTextStart;
|
||||
sal_Int32 mnTextLen;
|
||||
KernArraySpan mpDXArray;
|
||||
std::span<const sal_Bool> mpKashidaArray;
|
||||
const SvxFont& mrFont;
|
||||
sal_Int32 mnPara;
|
||||
sal_uInt8 mnBiDiLevel;
|
||||
const EEngineData::WrongSpellVector* mpWrongSpellVector;
|
||||
const SvxFieldData* mpFieldData;
|
||||
bool mbEndOfLine : 1;
|
||||
bool mbEndOfParagraph : 1;
|
||||
bool mbEndOfBullet : 1;
|
||||
const css::lang::Locale* mpLocale;
|
||||
const Color maOverlineColor;
|
||||
const Color maTextLineColor;
|
||||
|
||||
bool IsRTL() const { return mnBiDiLevel % 2 == 1; }
|
||||
|
||||
DrawPortionInfo(
|
||||
const Point& rPos,
|
||||
OUString aTxt,
|
||||
sal_Int32 nTxtStart,
|
||||
sal_Int32 nTxtLen,
|
||||
KernArraySpan pDXArr,
|
||||
std::span<const sal_Bool> pKashidaArr,
|
||||
const SvxFont& rFnt,
|
||||
sal_Int32 nPar,
|
||||
sal_uInt8 nBiDiLevel,
|
||||
const EEngineData::WrongSpellVector* pWrongSpellVector,
|
||||
const SvxFieldData* pFieldData,
|
||||
bool bEndOfLine,
|
||||
bool bEndOfParagraph,
|
||||
bool bEndOfBullet,
|
||||
const css::lang::Locale* pLocale,
|
||||
const Color& rOverlineColor,
|
||||
const Color& rTextLineColor)
|
||||
: mrStartPos(rPos),
|
||||
maText(std::move(aTxt)),
|
||||
mnTextStart(nTxtStart),
|
||||
mnTextLen(nTxtLen),
|
||||
mpDXArray(pDXArr),
|
||||
mpKashidaArray(pKashidaArr),
|
||||
mrFont(rFnt),
|
||||
mnPara(nPar),
|
||||
mnBiDiLevel(nBiDiLevel),
|
||||
mpWrongSpellVector(pWrongSpellVector),
|
||||
mpFieldData(pFieldData),
|
||||
mbEndOfLine(bEndOfLine),
|
||||
mbEndOfParagraph(bEndOfParagraph),
|
||||
mbEndOfBullet(bEndOfBullet),
|
||||
mpLocale(pLocale),
|
||||
maOverlineColor(rOverlineColor),
|
||||
maTextLineColor(rTextLineColor)
|
||||
{}
|
||||
};
|
||||
|
||||
class EDITENG_DLLPUBLIC DrawBulletInfo
|
||||
{
|
||||
public:
|
||||
const GraphicObject maBulletGraphicObject;
|
||||
Point maBulletPosition;
|
||||
Size maBulletSize;
|
||||
|
||||
DrawBulletInfo(
|
||||
const GraphicObject& rBulletGraphicObject,
|
||||
const Point& rBulletPosition,
|
||||
const Size& rBulletSize)
|
||||
: maBulletGraphicObject(rBulletGraphicObject),
|
||||
maBulletPosition(rBulletPosition),
|
||||
maBulletSize(rBulletSize)
|
||||
{}
|
||||
};
|
||||
|
||||
struct EDITENG_DLLPUBLIC PaintFirstLineInfo
|
||||
{
|
||||
sal_Int32 mnPara;
|
||||
|
||||
@@ -116,19 +116,6 @@ namespace sdr::properties
|
||||
class CellProperties;
|
||||
}
|
||||
|
||||
class DrawPortionInfo;
|
||||
class DrawBulletInfo;
|
||||
void SVXCORE_DLLPUBLIC CreateTextPortionPrimitivesFromDrawPortionInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo);
|
||||
void SVXCORE_DLLPUBLIC CreateDrawBulletPrimitivesFromDrawBulletInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawBulletInfo& rInfo);
|
||||
|
||||
// SdrTextObj
|
||||
class SVXCORE_DLLPUBLIC SdrTextObj : public SdrAttrObj, public svx::ITextProvider
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <scitems.hxx>
|
||||
|
||||
#include <editeng/editview.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
#include <svx/fmshell.hxx>
|
||||
#include <svx/sdr/overlay/overlaymanager.hxx>
|
||||
#include <svx/svdoole2.hxx>
|
||||
|
||||
@@ -34,14 +34,11 @@
|
||||
#include <svx/xbtmpit.hxx>
|
||||
#include <basegfx/vector/b2dvector.hxx>
|
||||
#include <sdr/primitive2d/sdrtextprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textbreakuphelper.hxx>
|
||||
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
|
||||
#include <basegfx/range/b2drange.hxx>
|
||||
#include <editeng/eeitem.hxx>
|
||||
#include <editeng/editstat.hxx>
|
||||
#include <editeng/smallcaps.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
#include <tools/helpers.hxx>
|
||||
#include <svl/itemset.hxx>
|
||||
#include <drawinglayer/animation/animationtiming.hxx>
|
||||
@@ -52,10 +49,8 @@
|
||||
#include <editeng/flditem.hxx>
|
||||
#include <editeng/adjustitem.hxx>
|
||||
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
|
||||
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
|
||||
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
|
||||
#include <svx/unoapi.hxx>
|
||||
#include <drawinglayer/geometry/viewinformation2d.hxx>
|
||||
#include <editeng/outlobj.hxx>
|
||||
@@ -66,418 +61,6 @@
|
||||
|
||||
using namespace com::sun::star;
|
||||
|
||||
// helpers
|
||||
namespace
|
||||
{
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> buildTextPortionPrimitive(const DrawPortionInfo& rInfo, const OUString& rText,
|
||||
const drawinglayer::attribute::FontAttribute& rFontAttribute,
|
||||
const std::vector<double>& rDXArray,
|
||||
const basegfx::B2DHomMatrix& rNewTransform);
|
||||
|
||||
// static rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo);
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> CheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo)
|
||||
{
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> xRet = pPrimitive;
|
||||
if(rInfo.mpFieldData)
|
||||
{
|
||||
// Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D
|
||||
// which holds the field type and, if applicable, the URL
|
||||
const SvxURLField* pURLField = dynamic_cast< const SvxURLField* >(rInfo.mpFieldData);
|
||||
const SvxPageField* pPageField = dynamic_cast< const SvxPageField* >(rInfo.mpFieldData);
|
||||
|
||||
// embed current primitive to a sequence
|
||||
drawinglayer::primitive2d::Primitive2DContainer aSequence;
|
||||
|
||||
if(pPrimitive)
|
||||
{
|
||||
aSequence.resize(1);
|
||||
aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive);
|
||||
}
|
||||
|
||||
if(pURLField)
|
||||
{
|
||||
// extended this to hold more of the contents of the original
|
||||
// SvxURLField since that stuff is still used in HitTest and e.g. Calc
|
||||
std::vector< std::pair< OUString, OUString>> meValues;
|
||||
meValues.emplace_back("URL", pURLField->GetURL());
|
||||
meValues.emplace_back("Representation", pURLField->GetRepresentation());
|
||||
meValues.emplace_back("TargetFrame", pURLField->GetTargetFrame());
|
||||
meValues.emplace_back("AltText", pURLField->GetName());
|
||||
meValues.emplace_back("SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat())));
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues);
|
||||
}
|
||||
else if(pPageField)
|
||||
{
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_PAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_COMMON);
|
||||
}
|
||||
}
|
||||
|
||||
return xRet;
|
||||
}
|
||||
|
||||
class DoCapitalsDrawPortionInfo : public SvxDoCapitals
|
||||
{
|
||||
private:
|
||||
drawinglayer::primitive2d::Primitive2DContainer& mrTarget;
|
||||
const basegfx::B2DHomMatrix& mrNewTransformA;
|
||||
const basegfx::B2DHomMatrix& mrNewTransformB;
|
||||
const DrawPortionInfo& m_rInfo;
|
||||
SvxFont m_aFont;
|
||||
public:
|
||||
DoCapitalsDrawPortionInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo)
|
||||
: SvxDoCapitals(rInfo.maText, rInfo.mnTextStart, rInfo.mnTextLen)
|
||||
, mrTarget(rTarget)
|
||||
, mrNewTransformA(rNewTransformA)
|
||||
, mrNewTransformB(rNewTransformB)
|
||||
, m_rInfo(rInfo)
|
||||
, m_aFont(rInfo.mrFont)
|
||||
{
|
||||
assert(!m_rInfo.mpDXArray.empty());
|
||||
|
||||
/* turn all these off as they are handled outside subportions for the whole portion */
|
||||
m_aFont.SetTransparent(false);
|
||||
m_aFont.SetUnderline(LINESTYLE_NONE);
|
||||
m_aFont.SetOverline(LINESTYLE_NONE);
|
||||
m_aFont.SetStrikeout(STRIKEOUT_NONE);
|
||||
|
||||
m_aFont.SetCaseMap(SvxCaseMap::NotMapped); /* otherwise this would call itself */
|
||||
}
|
||||
virtual void Do( const OUString &rSpanTxt, const sal_Int32 nSpanIdx,
|
||||
const sal_Int32 nSpanLen, const bool bUpper ) override
|
||||
{
|
||||
sal_uInt8 nProp(0);
|
||||
if (!bUpper)
|
||||
{
|
||||
nProp = m_aFont.GetPropr();
|
||||
m_aFont.SetProprRel(SMALL_CAPS_PERCENTAGE);
|
||||
}
|
||||
|
||||
sal_Int32 nStartOffset = nSpanIdx - nIdx;
|
||||
double nStartX = nStartOffset ? m_rInfo.mpDXArray[nStartOffset - 1] : 0;
|
||||
|
||||
Point aStartPos(m_rInfo.mrStartPos.X() + nStartX, m_rInfo.mrStartPos.Y());
|
||||
|
||||
KernArray aDXArray;
|
||||
aDXArray.resize(nSpanLen);
|
||||
for (sal_Int32 i = 0; i < nSpanLen; ++i)
|
||||
aDXArray[i] = m_rInfo.mpDXArray[nStartOffset + i] - nStartX;
|
||||
|
||||
auto aKashidaArray = !m_rInfo.mpKashidaArray.empty() ?
|
||||
std::span<const sal_Bool>(m_rInfo.mpKashidaArray.data() + nStartOffset, nSpanLen) :
|
||||
std::span<const sal_Bool>();
|
||||
|
||||
DrawPortionInfo aInfo(aStartPos, rSpanTxt,
|
||||
nSpanIdx, nSpanLen,
|
||||
aDXArray, aKashidaArray,
|
||||
m_aFont, m_rInfo.mnPara,
|
||||
m_rInfo.mnBiDiLevel,
|
||||
nullptr, /* no spelling in subportion, handled outside */
|
||||
nullptr, /* no field in subportion, handled outside */
|
||||
false, false, false,
|
||||
m_rInfo.mpLocale, m_rInfo.maOverlineColor, m_rInfo.maTextLineColor);
|
||||
|
||||
CreateTextPortionPrimitivesFromDrawPortionInfo(
|
||||
mrTarget,
|
||||
mrNewTransformA,
|
||||
mrNewTransformB,
|
||||
aInfo);
|
||||
|
||||
if (!bUpper)
|
||||
m_aFont.SetPropr(nProp);
|
||||
}
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
void CreateTextPortionPrimitivesFromDrawPortionInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawPortionInfo& rInfo)
|
||||
{
|
||||
if(rInfo.maText.isEmpty() || !rInfo.mnTextLen)
|
||||
return;
|
||||
|
||||
basegfx::B2DVector aFontScaling;
|
||||
drawinglayer::attribute::FontAttribute aFontAttribute(
|
||||
drawinglayer::primitive2d::getFontAttributeFromVclFont(
|
||||
aFontScaling,
|
||||
rInfo.mrFont,
|
||||
rInfo.IsRTL(),
|
||||
false));
|
||||
basegfx::B2DHomMatrix aNewTransform;
|
||||
|
||||
// add font scale to new transform
|
||||
aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY());
|
||||
|
||||
// look for proportional font scaling, if necessary, scale accordingly
|
||||
sal_Int8 nPropr(rInfo.mrFont.GetPropr());
|
||||
const double fPropFontFactor(nPropr / 100.0);
|
||||
if (100 != nPropr)
|
||||
aNewTransform.scale(fPropFontFactor, fPropFontFactor);
|
||||
|
||||
// apply font rotate
|
||||
if(rInfo.mrFont.GetOrientation())
|
||||
{
|
||||
aNewTransform.rotate(-toRadians(rInfo.mrFont.GetOrientation()));
|
||||
}
|
||||
|
||||
// look for escapement, if necessary, translate accordingly
|
||||
if(rInfo.mrFont.GetEscapement())
|
||||
{
|
||||
sal_Int16 nEsc(rInfo.mrFont.GetEscapement());
|
||||
|
||||
if(DFLT_ESC_AUTO_SUPER == nEsc)
|
||||
{
|
||||
nEsc = .8 * (100 - nPropr);
|
||||
assert (nEsc == DFLT_ESC_SUPER && "I'm sure this formula needs to be changed, but how to confirm that???");
|
||||
nEsc = DFLT_ESC_SUPER;
|
||||
}
|
||||
else if(DFLT_ESC_AUTO_SUB == nEsc)
|
||||
{
|
||||
nEsc = .2 * -(100 - nPropr);
|
||||
assert (nEsc == -20 && "I'm sure this formula needs to be changed, but how to confirm that???");
|
||||
nEsc = -20;
|
||||
}
|
||||
|
||||
if(nEsc > MAX_ESC_POS)
|
||||
{
|
||||
nEsc = MAX_ESC_POS;
|
||||
}
|
||||
else if(nEsc < -MAX_ESC_POS)
|
||||
{
|
||||
nEsc = -MAX_ESC_POS;
|
||||
}
|
||||
|
||||
const double fEscapement(nEsc / -100.0);
|
||||
aNewTransform.translate(0.0, fEscapement * aFontScaling.getY());
|
||||
}
|
||||
|
||||
// apply transformA
|
||||
aNewTransform *= rNewTransformA;
|
||||
|
||||
// apply local offset
|
||||
aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y());
|
||||
|
||||
// also apply embedding object's transform
|
||||
aNewTransform *= rNewTransformB;
|
||||
|
||||
// prepare DXArray content. To make it independent from font size (and such from
|
||||
// the text transformation), scale it to unit coordinates
|
||||
::std::vector< double > aDXArray;
|
||||
|
||||
if (!rInfo.mpDXArray.empty())
|
||||
{
|
||||
aDXArray.reserve(rInfo.mnTextLen);
|
||||
for(sal_Int32 a=0; a < rInfo.mnTextLen; a++)
|
||||
{
|
||||
aDXArray.push_back(rInfo.mpDXArray[a]);
|
||||
}
|
||||
}
|
||||
|
||||
OUString caseMappedText = rInfo.mrFont.CalcCaseMap(rInfo.maText);
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive(buildTextPortionPrimitive(rInfo, caseMappedText,
|
||||
aFontAttribute,
|
||||
aDXArray, aNewTransform));
|
||||
|
||||
bool bSmallCaps = rInfo.mrFont.IsCapital();
|
||||
if (bSmallCaps && rInfo.mpDXArray.empty())
|
||||
{
|
||||
SAL_WARN("svx", "SmallCaps requested with DXArray, abandoning");
|
||||
bSmallCaps = false;
|
||||
}
|
||||
if (bSmallCaps)
|
||||
{
|
||||
// rerun with each sub-portion
|
||||
DoCapitalsDrawPortionInfo aDoDrawPortionInfo(
|
||||
rTarget,
|
||||
rNewTransformA,
|
||||
rNewTransformB,
|
||||
rInfo);
|
||||
rInfo.mrFont.DoOnCapitals(aDoDrawPortionInfo);
|
||||
|
||||
// transfer collected primitives from rTarget to a new container
|
||||
drawinglayer::primitive2d::Primitive2DContainer aContainer = std::move(rTarget);
|
||||
|
||||
// Take any decoration for the whole formatted portion and keep it to get continuous over/under/strike-through
|
||||
if (pNewPrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
|
||||
{
|
||||
const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
|
||||
static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(pNewPrimitive.get());
|
||||
|
||||
if (pTCPP->getWordLineMode()) // single word mode: 'Individual words' in UI
|
||||
{
|
||||
// Split to single word primitives using TextBreakupHelper
|
||||
drawinglayer::primitive2d::TextBreakupHelper aTextBreakupHelper(*pTCPP);
|
||||
drawinglayer::primitive2d::Primitive2DContainer aBroken(aTextBreakupHelper.extractResult(drawinglayer::primitive2d::BreakupUnit::Word));
|
||||
for (auto& rPortion : aBroken)
|
||||
{
|
||||
assert(rPortion->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D &&
|
||||
"TextBreakupHelper generates same output primitive type as input");
|
||||
|
||||
const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pPortion =
|
||||
static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(rPortion.get());
|
||||
|
||||
// create and add decoration
|
||||
const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent(
|
||||
pPortion->getOrCreateDecorationGeometryContent(
|
||||
pPortion->getTextTransform(),
|
||||
caseMappedText,
|
||||
pPortion->getTextPosition(),
|
||||
pPortion->getTextLength(),
|
||||
pPortion->getDXArray()));
|
||||
|
||||
aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// create and add decoration
|
||||
const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent(
|
||||
pTCPP->getOrCreateDecorationGeometryContent(
|
||||
pTCPP->getTextTransform(),
|
||||
caseMappedText,
|
||||
rInfo.mnTextStart,
|
||||
rInfo.mnTextLen,
|
||||
aDXArray));
|
||||
|
||||
aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end());
|
||||
}
|
||||
}
|
||||
|
||||
pNewPrimitive = new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer));
|
||||
}
|
||||
|
||||
const Color aFontColor(rInfo.mrFont.GetColor());
|
||||
if (aFontColor.IsTransparent())
|
||||
{
|
||||
// Handle semi-transparent text for both the decorated and simple case here.
|
||||
pNewPrimitive = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
|
||||
drawinglayer::primitive2d::Primitive2DContainer{ pNewPrimitive },
|
||||
(255 - aFontColor.GetAlpha()) / 255.0);
|
||||
}
|
||||
|
||||
if(rInfo.mbEndOfBullet)
|
||||
{
|
||||
// embed in TextHierarchyBulletPrimitive2D
|
||||
drawinglayer::primitive2d::Primitive2DContainer aNewSequence { pNewPrimitive };
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence));
|
||||
}
|
||||
|
||||
if(rInfo.mpFieldData)
|
||||
{
|
||||
pNewPrimitive = CheckFieldPrimitive(pNewPrimitive.get(), rInfo);
|
||||
}
|
||||
|
||||
rTarget.push_back(pNewPrimitive);
|
||||
|
||||
// support for WrongSpellVector. Create WrongSpellPrimitives as needed
|
||||
if(!rInfo.mpWrongSpellVector || aDXArray.empty())
|
||||
return;
|
||||
|
||||
const sal_Int32 nSize(rInfo.mpWrongSpellVector->size());
|
||||
const sal_Int32 nDXCount(aDXArray.size());
|
||||
const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded
|
||||
|
||||
for(sal_Int32 a(0); a < nSize; a++)
|
||||
{
|
||||
const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a];
|
||||
|
||||
if(rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart && rCandidate.nEnd > rCandidate.nStart)
|
||||
{
|
||||
const sal_Int32 nStart(rCandidate.nStart - rInfo.mnTextStart);
|
||||
const sal_Int32 nEnd(rCandidate.nEnd - rInfo.mnTextStart);
|
||||
double fStart(0.0);
|
||||
double fEnd(0.0);
|
||||
|
||||
if(nStart > 0 && nStart - 1 < nDXCount)
|
||||
{
|
||||
fStart = aDXArray[nStart - 1];
|
||||
}
|
||||
|
||||
if(nEnd > 0 && nEnd - 1 < nDXCount)
|
||||
{
|
||||
fEnd = aDXArray[nEnd - 1];
|
||||
}
|
||||
|
||||
if(!basegfx::fTools::equal(fStart, fEnd))
|
||||
{
|
||||
if(rInfo.IsRTL())
|
||||
{
|
||||
// #i98523#
|
||||
// When the portion is RTL, mirror the redlining using the
|
||||
// full portion width
|
||||
const double fTextWidth(aDXArray[aDXArray.size() - 1]);
|
||||
|
||||
fStart = fTextWidth - fStart;
|
||||
fEnd = fTextWidth - fEnd;
|
||||
}
|
||||
|
||||
// need to take FontScaling out of values; it's already part of
|
||||
// aNewTransform and would be double applied
|
||||
const double fFontScaleX(aFontScaling.getX() * fPropFontFactor);
|
||||
|
||||
if(!basegfx::fTools::equal(fFontScaleX, 1.0)
|
||||
&& !basegfx::fTools::equalZero(fFontScaleX))
|
||||
{
|
||||
fStart /= fFontScaleX;
|
||||
fEnd /= fFontScaleX;
|
||||
}
|
||||
|
||||
rTarget.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D(
|
||||
aNewTransform,
|
||||
fStart,
|
||||
fEnd,
|
||||
aSpellColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateDrawBulletPrimitivesFromDrawBulletInfo(
|
||||
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
|
||||
const basegfx::B2DHomMatrix& rNewTransformA,
|
||||
const basegfx::B2DHomMatrix& rNewTransformB,
|
||||
const DrawBulletInfo& rInfo)
|
||||
{
|
||||
basegfx::B2DHomMatrix aNewTransform;
|
||||
|
||||
// add size to new transform
|
||||
aNewTransform.scale(rInfo.maBulletSize.getWidth(), rInfo.maBulletSize.getHeight());
|
||||
|
||||
// apply transformA
|
||||
aNewTransform *= rNewTransformA;
|
||||
|
||||
// apply local offset
|
||||
aNewTransform.translate(rInfo.maBulletPosition.X(), rInfo.maBulletPosition.Y());
|
||||
|
||||
// also apply embedding object's transform
|
||||
aNewTransform *= rNewTransformB;
|
||||
|
||||
// prepare empty GraphicAttr
|
||||
const GraphicAttr aGraphicAttr;
|
||||
|
||||
// create GraphicPrimitive2D
|
||||
const drawinglayer::primitive2d::Primitive2DReference aNewReference(new drawinglayer::primitive2d::GraphicPrimitive2D(
|
||||
aNewTransform,
|
||||
rInfo.maBulletGraphicObject,
|
||||
aGraphicAttr));
|
||||
|
||||
// embed in TextHierarchyBulletPrimitive2D
|
||||
drawinglayer::primitive2d::Primitive2DContainer aNewSequence { aNewReference };
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence));
|
||||
|
||||
// add to output
|
||||
rTarget.push_back(pNewPrimitive);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class impTextBreakupHandler
|
||||
@@ -595,145 +178,6 @@ namespace
|
||||
drawinglayer::primitive2d::Primitive2DContainer extractPrimitive2DSequence();
|
||||
};
|
||||
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> buildTextPortionPrimitive(
|
||||
const DrawPortionInfo& rInfo, const OUString& rText,
|
||||
const drawinglayer::attribute::FontAttribute& rFontAttribute,
|
||||
const std::vector<double>& rDXArray,
|
||||
const basegfx::B2DHomMatrix& rNewTransform)
|
||||
{
|
||||
::std::vector< sal_Bool > aKashidaArray;
|
||||
|
||||
if(!rInfo.mpKashidaArray.empty() && rInfo.mnTextLen)
|
||||
{
|
||||
aKashidaArray.reserve(rInfo.mnTextLen);
|
||||
|
||||
for(sal_Int32 a=0; a < rInfo.mnTextLen; a++)
|
||||
{
|
||||
aKashidaArray.push_back(rInfo.mpKashidaArray[a]);
|
||||
}
|
||||
}
|
||||
|
||||
// create complex text primitive and append
|
||||
const Color aFontColor(rInfo.mrFont.GetColor());
|
||||
const basegfx::BColor aBFontColor(aFontColor.getBColor());
|
||||
|
||||
const Color aTextFillColor(rInfo.mrFont.GetFillColor());
|
||||
|
||||
// prepare wordLineMode (for underline and strikeout)
|
||||
// NOT for bullet texts. It is set (this may be an error by itself), but needs to be suppressed to hinder e.g. '1)'
|
||||
// to be split which would not look like the original
|
||||
const bool bWordLineMode(rInfo.mrFont.IsWordLineMode() && !rInfo.mbEndOfBullet);
|
||||
|
||||
// prepare new primitive
|
||||
rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive;
|
||||
const bool bDecoratedIsNeeded(
|
||||
LINESTYLE_NONE != rInfo.mrFont.GetOverline()
|
||||
|| LINESTYLE_NONE != rInfo.mrFont.GetUnderline()
|
||||
|| STRIKEOUT_NONE != rInfo.mrFont.GetStrikeout()
|
||||
|| FontEmphasisMark::NONE != (rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::Style)
|
||||
|| FontRelief::NONE != rInfo.mrFont.GetRelief()
|
||||
|| rInfo.mrFont.IsShadow()
|
||||
|| bWordLineMode);
|
||||
|
||||
if(bDecoratedIsNeeded)
|
||||
{
|
||||
// TextDecoratedPortionPrimitive2D needed, prepare some more data
|
||||
// get overline and underline color. If it's on automatic (0xffffffff) use FontColor instead
|
||||
const Color aUnderlineColor(rInfo.maTextLineColor);
|
||||
const basegfx::BColor aBUnderlineColor((aUnderlineColor == COL_AUTO) ? aBFontColor : aUnderlineColor.getBColor());
|
||||
const Color aOverlineColor(rInfo.maOverlineColor);
|
||||
const basegfx::BColor aBOverlineColor((aOverlineColor == COL_AUTO) ? aBFontColor : aOverlineColor.getBColor());
|
||||
|
||||
// prepare overline and underline data
|
||||
const drawinglayer::primitive2d::TextLine eFontOverline(
|
||||
drawinglayer::primitive2d::mapFontLineStyleToTextLine(rInfo.mrFont.GetOverline()));
|
||||
const drawinglayer::primitive2d::TextLine eFontLineStyle(
|
||||
drawinglayer::primitive2d::mapFontLineStyleToTextLine(rInfo.mrFont.GetUnderline()));
|
||||
|
||||
// check UnderlineAbove
|
||||
const bool bUnderlineAbove(
|
||||
drawinglayer::primitive2d::TEXT_LINE_NONE != eFontLineStyle && rInfo.mrFont.IsUnderlineAbove());
|
||||
|
||||
// prepare strikeout data
|
||||
const drawinglayer::primitive2d::TextStrikeout eTextStrikeout(
|
||||
drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rInfo.mrFont.GetStrikeout()));
|
||||
|
||||
// prepare emphasis mark data
|
||||
drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_NONE);
|
||||
|
||||
switch(rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::Style)
|
||||
{
|
||||
case FontEmphasisMark::Dot : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DOT; break;
|
||||
case FontEmphasisMark::Circle : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_CIRCLE; break;
|
||||
case FontEmphasisMark::Disc : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_DISC; break;
|
||||
case FontEmphasisMark::Accent : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_FONT_EMPHASIS_MARK_ACCENT; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
const bool bEmphasisMarkAbove(rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::PosAbove);
|
||||
const bool bEmphasisMarkBelow(rInfo.mrFont.GetEmphasisMark() & FontEmphasisMark::PosBelow);
|
||||
|
||||
// prepare font relief data
|
||||
drawinglayer::primitive2d::TextRelief eTextRelief(drawinglayer::primitive2d::TEXT_RELIEF_NONE);
|
||||
|
||||
switch(rInfo.mrFont.GetRelief())
|
||||
{
|
||||
case FontRelief::Embossed : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED; break;
|
||||
case FontRelief::Engraved : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED; break;
|
||||
default : break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE
|
||||
}
|
||||
|
||||
// prepare shadow/outline data
|
||||
const bool bShadow(rInfo.mrFont.IsShadow());
|
||||
|
||||
// TextDecoratedPortionPrimitive2D is needed, create one
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
|
||||
|
||||
// attributes for TextSimplePortionPrimitive2D
|
||||
rNewTransform,
|
||||
rText,
|
||||
rInfo.mnTextStart,
|
||||
rInfo.mnTextLen,
|
||||
std::vector(rDXArray),
|
||||
std::move(aKashidaArray),
|
||||
rFontAttribute,
|
||||
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(),
|
||||
aBFontColor,
|
||||
aTextFillColor,
|
||||
|
||||
// attributes for TextDecoratedPortionPrimitive2D
|
||||
aBOverlineColor,
|
||||
aBUnderlineColor,
|
||||
eFontOverline,
|
||||
eFontLineStyle,
|
||||
bUnderlineAbove,
|
||||
eTextStrikeout,
|
||||
bWordLineMode,
|
||||
eTextEmphasisMark,
|
||||
bEmphasisMarkAbove,
|
||||
bEmphasisMarkBelow,
|
||||
eTextRelief,
|
||||
bShadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TextSimplePortionPrimitive2D is enough
|
||||
pNewPrimitive = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
|
||||
rNewTransform,
|
||||
rText,
|
||||
rInfo.mnTextStart,
|
||||
rInfo.mnTextLen,
|
||||
std::vector(rDXArray),
|
||||
std::move(aKashidaArray),
|
||||
rFontAttribute,
|
||||
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(),
|
||||
aBFontColor,
|
||||
aTextFillColor);
|
||||
}
|
||||
|
||||
return pNewPrimitive;
|
||||
}
|
||||
|
||||
void impTextBreakupHandler::impFlushTextPortionPrimitivesToLinePrimitives()
|
||||
{
|
||||
// only create a line primitive when we had content; there is no need for
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
|
||||
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
|
||||
#include <basegfx/color/bcolor.hxx>
|
||||
#include <editeng/StripPortionsHelper.hxx>
|
||||
|
||||
// primitive decomposition helpers
|
||||
#include <drawinglayer/attribute/strokeattribute.hxx>
|
||||
|
||||
Reference in New Issue
Block a user