18#include <QRegularExpression>
26void appendLazy(
QVector<qreal> *list, boost::optional<qreal>
value,
int iteration,
bool hasDefault =
true, qreal defaultValue = 0.0)
29 if (
value && *
value == defaultValue && hasDefault ==
true && list->isEmpty())
return;
31 while (list->size() < iteration) {
32 list->append(defaultValue);
41 for (
int i = 0; i < localTransformations.size(); i++) {
43 appendLazy(xPos, t.
xPos, i,
false);
44 appendLazy(yPos, t.
yPos, i,
false);
45 appendLazy(dxPos, t.
dxPos, i);
46 appendLazy(dyPos, t.
dyPos, i);
47 appendLazy(rotate, t.
rotate, i);
58 Q_FOREACH (
const QString &str, list) {
70 Q_FOREACH (
const QString &str, list) {
82 Q_FOREACH (
const QString &str, list) {
92 Q_FOREACH (qreal
value, values) {
96 return stringValues.join(
',');
101 const QString
value = convertListAttribute(values);
102 if (!
value.isEmpty()) {
108#include <ksharedconfig.h>
109#include <kconfiggroup.h>
119int forcedDpiForQtFontBugWorkaround() {
120 KConfigGroup cfg(KSharedConfig::openConfig(),
"");
138 const int forcedFontDPI = forcedDpiForQtFontBugWorkaround();
145 fontSize *= qreal(forcedFontDPI) / 72.0;
176 for (
int i = 0; i <
generic.size(); i++) {
177 auto id =
generic[i];
187 QVector<qreal> xPos = parseListAttributeX(e.attribute(
"x",
""), context);
188 QVector<qreal> yPos = parseListAttributeY(e.attribute(
"y",
""), context);
189 QVector<qreal> dxPos = parseListAttributeX(e.attribute(
"dx",
""), context);
190 QVector<qreal> dyPos = parseListAttributeY(e.attribute(
"dy",
""), context);
191 QVector<qreal> rotate = parseListAttributeAngular(e.attribute(
"rotate",
""), context);
193 const int numLocalTransformations =
194 std::max({xPos.size(), yPos.size(),
195 dxPos.size(), dyPos.size(),
199 for (
int i = 0; i < numLocalTransformations; i++) {
200 if (i < xPos.size()) {
203 if (i < yPos.size()) {
206 if (i < dxPos.size() && dxPos[i] != 0.0) {
209 if (i < dyPos.size() && dyPos[i] != 0.0) {
212 if (i < rotate.size()) {
217 if (e.tagName() ==
"textPath") {
224 if (e.hasAttribute(
"startOffset")) {
225 QString offset = e.attribute(
"startOffset",
"0");
226 if (offset.endsWith(
"%")) {
238 QString resolution = e.attribute(
TEXT_STYLE_RES.toLatin1().data()).toLower();
239 if (resolution.endsWith(
"dpi")) {
259 static const QRegularExpression s_regexCrlf(R
"==((?:\r\n|\r(?!\n)))==");
260 QString content = text.data();
261 content.replace(s_regexCrlf, QStringLiteral("\n"));
263 this->text = std::move(content);
271 QMap<QString, QString> shapeSpecificAttributes)
280 context.
shapeWriter().addAttribute(
"xlink:href",
"#" +
id);
288 context.
shapeWriter().addAttribute(
"startOffset", offset);
311 for (
int i = 0; i < rotate.size(); i++) {
315 writeTextListAttribute(
"x", xPos, context.
shapeWriter());
316 writeTextListAttribute(
"y", yPos, context.
shapeWriter());
317 writeTextListAttribute(
"dx", dxPos, context.
shapeWriter());
318 writeTextListAttribute(
"dy", dyPos, context.
shapeWriter());
319 writeTextListAttribute(
"rotate", rotate, context.
shapeWriter());
326 context.
shapeWriter().addAttribute(
"lengthAdjust",
"spacingAndGlyphs");
332 ownProperties = adjustPropertiesForFontSizeWorkaround(ownProperties);
339 this->associatedOutline.boundingRect(),
354 for (
auto it = shapeSpecificAttributes.constBegin(); it != shapeSpecificAttributes.constEnd(); ++it) {
355 styleString.append(it.key().toLatin1().data()).append(
": ").append(it.value()).append(
";");
357 for (
auto it = attributes.constBegin(); it != attributes.constEnd(); ++it) {
358 if (allowedAttributes.contains(it.key())) {
359 context.
shapeWriter().addAttribute(it.key().toLatin1().data(), it.value());
361 styleString.append(it.key().toLatin1().data()).append(
": ").append(it.value()).append(
";");
364 if (!styleString.isEmpty()) {
365 context.
shapeWriter().addAttribute(
"style", styleString);
391 for (
int i = 0; i < text.size(); i++) {
392 positions.append(QPair<int, int>(i, i));
420 result =
text.size();
427 if (start >=
text.size()) {
qreal length(const QPointF &vec)
float value(const T *src, size_t ch)
Q_GUI_EXPORT int qt_defaultDpi()
const QString TEXT_STYLE_RES
static QString transformText(QString text, KoSvgText::TextTransformInfo textTransformInfo, const QString &lang, QVector< QPair< int, int > > &positions)
const QString TEXT_STYLE_TYPE
static QString transformTextFullSizeKana(const QString &text)
transformTextFullSizeKana This function will take 'small' Kana (Japanese phonetic script) and transfo...
static QString transformTextCapitalize(const QString &text, QString langCode, QVector< QPair< int, int > > &positions)
transformTextToUpperCase This function splits the text into graphemes, and then uses QLocale::toUpper...
static QString transformTextToUpperCase(const QString &text, const QString &langCode, QVector< QPair< int, int > > &positions)
transformTextToUpperCase convenience function that creates a QLocale and uses it's 'toUpper' function...
static QString transformTextToLowerCase(const QString &text, const QString &langCode, QVector< QPair< int, int > > &positions)
transformTextToUpperCase convenience function that creates a QLocale and uses it's 'toLower' function...
static QString getBidiClosing(KoSvgText::UnicodeBidi bidi)
getBidiClosing Returns the bidi closing string associated with the given Css unicode-bidi value.
static void removeText(QString &text, int &start, int length)
removeText Special removal of text that takes a text, start and length and will modify these values s...
static QString transformTextFullWidth(const QString &text)
transformTextFullWidth This function will transform 'narrow' or 'halfwidth' characters to their norma...
static QString getBidiOpening(bool ltr, KoSvgText::UnicodeBidi bidi)
getBidiOpening Get the bidi opening string associated with the given Css unicode-bidi value and direc...
@ Visiblity
Bool, CSS visibility.
@ UnicodeBidiId
KoSvgText::UnicodeBidi.
@ PaintOrder
QVector<KoShape::PaintOrder>
@ KraTextStyleResolution
Int, used to scale style presets to be pixel-relative.
@ KraTextVersionId
Int, used for handling incorrectly saved files.
@ Opacity
Double, SVG shape opacity.
@ KraTextStyleType
string, used to identify the style preset type (character or paragraph).
@ FontSizeAdjustId
KoSvgText::AutoValue.
@ StrokeId
KoSvgText::StrokeProperty.
@ TextTransformId
KoSvgText::TextTransformInfo Struct.
@ FillId
KoSvgText::BackgroundProperty.
@ DirectionId
KoSvgText::Direction.
@ TextLanguage
a language string.
QSharedPointer< KoShapeBackground > background() const
KoShapeStrokeModelSP stroke() const
QMap< QString, QString > convertToSvgTextAttributes() const
QVariant property(PropertyId id, const QVariant &defaultValue=QVariant()) const
static const KoSvgTextProperties & defaultProperties()
bool hasProperty(PropertyId id) const
void setFontSize(const KoSvgText::CssLengthPercentage length)
void setProperty(PropertyId id, const QVariant &value)
KoSvgTextProperties ownProperties(const KoSvgTextProperties &parentProperties, bool keepFontSize=false) const
static QStringList supportedXmlAttributes()
QVariant propertyOrDefault(PropertyId id) const
KoSvgText::CssLengthPercentage fontSize() const
void addAttribute(const char *attrName, const QString &value)
KoSvgTextProperties textProperties
Stores textProperties.
Contains data used for loading svg.
SvgGraphicsContext * currentGC() const
Returns the current graphics context.
KoSvgTextProperties resolvedProperties() const
These are the text properties, completely resolved, ensuring that everything is inherited and the siz...
Context for saving svg files.
QScopedPointer< KoXmlWriter > shapeWriter
static void saveSvgFill(QSharedPointer< KoShapeBackground > background, const bool fillRuleEvenOdd, const QRectF outlineRect, const QSizeF size, const QTransform absoluteTransform, SvgSavingContext &context)
Saves fill style of specified shape.
static QString embedShape(const KoShape *shape, SvgSavingContext &context)
static void saveSvgStroke(KoShapeStrokeModelSP, SvgSavingContext &context)
Saves stroke style of specified shape.
static qreal parseUnitX(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in x-direction
static qreal parseUnitAngular(SvgGraphicsContext *gc, const QString &unit)
parses angle, result in radians!
static const char * parseNumber(const char *ptr, qreal &number)
parses the number into parameter number
static QStringList simplifyList(const QString &str)
static qreal parseUnit(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, QStringView, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
Parses a length attribute.
static qreal parseUnitY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in y-direction
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
T kisRadiansToDegrees(T radians)
int toInt(const QString &str, bool *ok=nullptr)
QString toString(const QString &value)
QString writeTextPathSide(TextPathSide value)
TextPathSide parseTextPathSide(const QString &value)
TextPathSpacing parseTextPathSpacing(const QString &value)
@ LengthAdjustSpacingAndGlyphs
Stretches the glyphs as well.
LengthAdjust parseLengthAdjust(const QString &value)
Direction
Base direction used by Bidi algorithm.
QString writeTextPathMethod(TextPathMethod value)
QVariant fromAutoValue(const KoSvgText::AutoValue &value)
AutoValue parseAutoValueXY(const QString &value, const SvgLoadingContext &context, const QString &autoKeyword)
QString writeTextPathSpacing(TextPathSpacing value)
TextPathMethod parseTextPathMethod(const QString &value)
@ TextTransformCapitalize
@ TextTransformUppercase
Convert all bicarmel text to upper-case, locale dependant.
@ TextTransformLowercase
Convert all bicarmel text to lower-case, locale dependant.
@ TextPathAlign
Only align position and rotation of glyphs to the path.
void removeText(int &start, int length)
removeText removes text,
KoSvgText::AutoValue textLength
the value 'textLength' attribute of the associated dom element
bool saveSvg(SvgSavingContext &context, bool rootText, bool saveText, QMap< QString, QString > shapeSpecificAttributes)
KoSvgTextContentElement()
QVector< KoSvgText::CharTransformation > localTransformations
Local SVG char transforms.
QString getTransformedString(QVector< QPair< int, int > > &positions, KoSvgTextProperties resolvedProps=KoSvgTextProperties()) const
bool loadSvg(const QDomElement &element, SvgLoadingContext &context, bool rootNode=false)
loadSvg load SVG style data into the current content element.
KoSvgTextProperties properties
The textProperties. This includes.
QPainterPath associatedOutline
The associated outline. Currently only a bounding box.
QString text
Plain text of the current node. Use insertText and removeText to manipulate it.
QScopedPointer< KoShape > textPath
The textpath, if any. Defaults to null.
bool loadSvgTextNode(const QDomText &text, SvgLoadingContext &context)
KoSvgText::LengthAdjust lengthAdjust
the value 'lengthAdjust' attribute of the associated dom element
int numChars(bool withControls=false, KoSvgTextProperties resolvedProps=KoSvgTextProperties()) const
KoSvgText::TextOnPathInfo textPathInfo
Text path info for the text-on-path algorithm.
void insertText(int start, QString insertText)
insertText
boost::optional< qreal > yPos
boost::optional< qreal > dxPos
boost::optional< qreal > dyPos
boost::optional< qreal > rotate
boost::optional< qreal > xPos
bool startOffsetIsPercentage
TextTransform capitals
Text transform upper/lower/capitalize.