27#define DEG2RAD(degree) degree/180.0*M_PI
74 qreal x = objectBound.left() + position.x() * objectBound.width();
75 qreal y = objectBound.top() + position.y() * objectBound.height();
81 qreal w = size.width() * objectBound.width();
82 qreal h = size.height() * objectBound.height();
89 if (objectBound.width() != 0)
90 x = (position.x() - objectBound.x()) / objectBound.width();
92 if (objectBound.height() != 0)
93 y = (position.y() - objectBound.y()) / objectBound.height();
99 qreal w = objectBound.width() != 0 ? size.width() / objectBound.width() : 0.0;
100 qreal h = objectBound.height() != 0 ? size.height() / objectBound.height() : 0.0;
106 if (transform.isIdentity())
109 if (transform.type() == QTransform::TxTranslate) {
110 return QString(
"translate(%1, %2)")
114 return QString(
"matrix(%1 %2 %3 %4 %5 %6)")
128 if (!
value.isEmpty()) {
134 const QRectF &elementBounds,
135 QRectF *_viewRect, QTransform *_viewTransform)
140 QString viewBoxStr = e.attribute(
"viewBox");
141 if (viewBoxStr.isEmpty())
return false;
149 viewBoxStr.remove(
"px");
151 QStringList points = viewBoxStr.replace(
',',
' ').simplified().split(
' ');
152 if (points.count() == 4) {
163 if (!result)
return false;
166 if (!
qFuzzyCompare(elementBounds.width(), viewBoxRect.width())) {
167 scaleX = elementBounds.width() / viewBoxRect.width();
170 if (!
qFuzzyCompare(elementBounds.height(), viewBoxRect.height())) {
171 scaleY = elementBounds.height() / viewBoxRect.height();
174 QTransform viewBoxTransform =
175 QTransform::fromTranslate(-viewBoxRect.x(), -viewBoxRect.y()) *
176 QTransform::fromScale(scaleX, scaleY) *
177 QTransform::fromTranslate(elementBounds.x(), elementBounds.y());
179 const QString aspectString = e.attribute(
"preserveAspectRatio");
184 *_viewRect = viewBoxRect;
185 *_viewTransform = viewBoxTransform;
192 if (
p.mode != Qt::IgnoreAspectRatio) {
193 QTransform viewBoxTransform = *_viewTransform;
195 const qreal tan1 = viewBoxRect.height() / viewBoxRect.width();
196 const qreal tan2 = elementBounds.height() / elementBounds.width();
198 const qreal uniformScale =
199 (
p.mode == Qt::KeepAspectRatioByExpanding) ^ (tan1 > tan2) ?
200 elementBounds.height() / viewBoxRect.height() :
201 elementBounds.width() / viewBoxRect.width();
204 QTransform::fromTranslate(-viewBoxRect.x(), -viewBoxRect.y()) *
205 QTransform::fromScale(uniformScale, uniformScale) *
206 QTransform::fromTranslate(elementBounds.x(), elementBounds.y());
208 const QPointF viewBoxAnchor = viewBoxTransform.map(
p.rectAnchorPoint(viewBoxRect));
209 const QPointF elementAnchor =
p.rectAnchorPoint(elementBounds);
210 const QPointF offset = elementAnchor - viewBoxAnchor;
212 viewBoxTransform = viewBoxTransform * QTransform::fromTranslate(offset.x(), offset.y());
214 *_viewTransform = viewBoxTransform;
222 QByteArray unitLatin1 = unit.toLatin1();
224 const char *start = unitLatin1.data();
250 QByteArray unitLatin1 = unit.trimmed().toLatin1();
252 const char *start = unitLatin1.data();
258 if (
int(end - start) < unit.length()) {
259 if (unit.right(2) == QLatin1String(
"px"))
261 else if (unit.right(2) == QLatin1String(
"pt"))
263 else if (unit.right(2) == QLatin1String(
"cm"))
265 else if (unit.right(2) == QLatin1String(
"pc"))
267 else if (unit.right(2) == QLatin1String(
"mm"))
269 else if (unit.right(2) == QLatin1String(
"in"))
271 else if (unit.right(2) == QLatin1String(
"em")) {
273 }
else if (unit.right(2) == QLatin1String(
"ex")) {
275 }
else if (unit.right(3) == QLatin1String(
"cap")) {
277 }
else if (unit.right(2) == QLatin1String(
"ch")) {
279 }
else if (unit.right(2) == QLatin1String(
"ic")) {
281 }
else if (unit.right(2) == QLatin1String(
"lh")) {
283 }
else if (unit.right(1) == QLatin1Char(
'%')) {
285 if (percentageViewBox) {
287 length.value = (
length.value / 100.0) * (sqrt(pow(bbox.width(), 2) + pow(bbox.height(), 2)) / sqrt(2.0));
338 if (unit.isEmpty())
return value;
339 QByteArray unitLatin1 = unit.toLower().toLatin1();
341 const char *start = unitLatin1.data();
342 if (!start)
return value;
346 if (
int(end - start) < unit.length()) {
347 if (unit.right(3) ==
"deg") {
349 }
else if (unit.right(4) ==
"grad") {
351 }
else if (unit.right(3) ==
"rad") {
367 if (
string.isEmpty())
return value;
368 QByteArray unitLatin1 =
string.toLatin1();
370 const char *start = unitLatin1.data();
371 if (!start)
return value;
380 int integer, exponent;
394 }
else if (*ptr ==
'-') {
400 while (*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
401 integer = (integer * 10) + *(ptr++) -
'0';
404 while (*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
405 decimal += (*(ptr++) -
'0') * (frac *= 0.1);
408 if (*ptr ==
'e' || *ptr ==
'E') {
414 }
else if (*ptr ==
'-') {
420 while (*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9') {
422 exponent += *ptr -
'0';
426 number = integer + decimal;
427 number *=
sign * pow((
double)10,
double(expsign * exponent));
434 QString result = tagName;
436 if (tagName ==
"path") {
437 QString kritaType = element.attribute(
"krita:type",
"");
438 QString sodipodiType = element.attribute(
"sodipodi:type",
"");
440 if (kritaType ==
"arc") {
441 result =
"krita:arc";
442 }
else if (sodipodiType ==
"arc") {
443 result =
"sodipodi:arc";
452 QString attribute = str;
453 attribute.replace(
',',
' ');
454 attribute.remove(
'\r');
455 attribute.remove(
'\n');
456 return attribute.simplified().split(
' ', Qt::SkipEmptyParts);
461 QRegExp rexp(
"(defer)?\\s*(none|(x(Min|Max|Mid)Y(Min|Max|Mid)))\\s*(meet|slice)?", Qt::CaseInsensitive);
462 int index = rexp.indexIn(str.toLower());
465 if (rexp.cap(1) ==
"defer") {
469 if (rexp.cap(2) !=
"none") {
472 mode = rexp.cap(6) ==
"slice" ?
473 Qt::KeepAspectRatioByExpanding : Qt::KeepAspectRatio;
480 return QPointF(alignedValue(rc.x(), rc.x() + rc.width(), xAlignment),
481 alignedValue(rc.y(), rc.y() + rc.height(), yAlignment));
489 xAlignment == Middle &&
490 yAlignment == Middle &&
491 mode == Qt::KeepAspectRatio) {
500 if (mode == Qt::IgnoreAspectRatio) {
503 result += QString(
"x%1Y%2")
504 .arg(alignmentToString(xAlignment))
505 .arg(alignmentToString(yAlignment));
507 if (mode == Qt::KeepAspectRatioByExpanding) {
518 str ==
"mid" ? Middle : Min;
524 alignment == Max ?
"Max" :
525 alignment == Min ?
"Min" :
539 result = 0.5 * (min + max);
qreal length(const QPointF &vec)
float value(const T *src, size_t ch)
constexpr qreal CM_TO_POINT(qreal cm)
constexpr qreal INCH_TO_POINT(qreal inch)
constexpr qreal PI_TO_POINT(qreal pi)
constexpr qreal MM_TO_POINT(qreal mm)
KoSvgText::FontMetrics metrics(const bool withResolvedLineHeight=true) const
metrics Return the metrics of the first available font.
KoSvgText::CssLengthPercentage fontSize() const
void addAttribute(const char *attrName, const QString &value)
QRectF currentBoundingBox
the current bound box used for bounding box units
qreal pixelsPerInch
controls the resolution of the image raster
bool forcePercentage
force parsing coordinates/length as percentages of currentBoundbox
static double toUserSpace(double value)
static qreal parseUnitX(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in x-direction
static double fromPercentage(QString s, bool *ok=nullptr)
static QString toPercentage(qreal value)
static qreal parseUnitAngular(SvgGraphicsContext *gc, const QString &unit)
parses angle, result in radians!
static bool parseViewBox(const QDomElement &e, const QRectF &elementBounds, QRectF *_viewRect, QTransform *_viewTransform)
Parses a viewbox attribute into an rectangle.
static const char * parseNumber(const char *ptr, qreal &number)
parses the number into parameter number
static QStringList simplifyList(const QString &str)
static QPointF objectToUserSpace(const QPointF &position, const QRectF &objectBound)
static QString transformToString(const QTransform &transform)
Converts specified transformation to a string.
static KoSvgText::CssLengthPercentage parseUnitStructImpl(SvgGraphicsContext *gc, QStringView, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF(), bool percentageViewBox=false)
Parse length attribute into struct.
static double ptToPx(SvgGraphicsContext *gc, double value)
static KoSvgText::CssLengthPercentage parseTextUnitStruct(SvgGraphicsContext *gc, QStringView unit)
Unit structs for text do not need the percentage to be resolved to viewport in most cases.
static qreal parseUnit(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, QStringView, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
Parses a length attribute.
static void parseAspectRatio(const PreserveAspectRatioParser &p, const QRectF &elementBounds, const QRectF &viewRect, QTransform *_viewTransform)
static double fromUserSpace(double value)
static QPointF userSpaceToObject(const QPointF &position, const QRectF &objectBound)
static qreal parseUnitXY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in xy-direction
static KoSvgText::CssLengthPercentage parseUnitStruct(SvgGraphicsContext *gc, QStringView unit, bool horiz=false, bool vert=false, const QRectF &bbox=QRectF())
Parse length attribute into a struct, always resolving the percentage to viewport.
static void writeTransformAttributeLazy(const QString &name, const QTransform &transform, KoXmlWriter &shapeWriter)
Writes a transform as an attribute name iff the transform is not empty.
static qreal parseUnitY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in y-direction
static QString mapExtendedShapeTag(const QString &tagName, const QDomElement &element)
static bool qFuzzyCompare(half p1, half p2)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
T kisDegreesToRadians(T degrees)
double toDouble(const QString &str, bool *ok=nullptr)
QString toString(const QString &value)
@ Cap
multiply by font-x-height.
@ Ch
multiply by font cap height
@ Lh
multiply by width of "U+6C34", represents average full width script advance.
@ Ex
multiply by Font-size
@ Ic
multiply by width of "0", represents average proportional script advance.
static qreal alignedValue(qreal min, qreal max, Alignment alignment)
Alignment alignmentFromString(const QString &str) const
QPointF rectAnchorPoint(const QRectF &rc) const
PreserveAspectRatioParser(const QString &str)
QString alignmentToString(Alignment alignment) const