[graphics/drawy/gsoc2026] src: fix: Improve word wrapping and scaling text

Abdelhadi Wael <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit b99fd07d0a101a45ae8eaa3720da9c83a949795e by Abdelhadi Wael.
Committed on 21/07/2026 at 23:55.
Pushed by mlaurent into branch 'gsoc2026'.

fix: Improve word wrapping and scaling text
- don't cache text in horizontal resize
- makes scaling text more accuarte (avoid wrapping while scaling)

M  +26   -20   src/gui/item/text.cpp
M  +1    -0    src/gui/item/text.hpp
M  +1    -1    src/widgets/transformhandler/resizetransformhandler.cpp

https://invent.kde.org/graphics/drawy/-/commit/b99fd07d0a101a45ae8eaa3720da9c83a949795e

diff --git a/src/gui/item/text.cpp b/src/gui/item/text.cpp
index 6f4e0b6e..6f26f9a7 100644
--- a/src/gui/item/text.cpp
+++ b/src/gui/item/text.cpp
@@ -77,14 +77,10 @@ void TextItem::draw(QPainter &painter, const QPointF &offset)
     painter.translate(m_boundingBox.topLeft() - offset);
     painter.setOpacity(painter.opacity() * (property(Property::Type::Opacity).value<int>() / 255.0));
 
-    QTransform transform{m_transform};
-    const auto [scaleX, scaleY]{Common::Utils::Math::extractScale(transform)};
-
-    if (m_mode == Mode::Normal && qFuzzyCompare(1.0, scaleY) && !qFuzzyCompare(1.0, scaleX)) {
+    if (m_isHorizontalResize) {
+        QTransform transform{m_transform};
+        const auto [scaleX, scaleY]{Common::Utils::Math::extractScale(transform)};
         painter.scale(1.0 / scaleX, 1.0);
-        const qreal width = m_wrapWidth > 0 ? m_wrapWidth : m_boundingBox.width();
-        const qreal targetWidth = std::max(width * scaleX, minWrapWidth());
-        m_document.setTextWidth(targetWidth);
     }
 
     QAbstractTextDocumentLayout::PaintContext ctx;
@@ -126,12 +122,16 @@ void TextItem::resize(const QTransform operation)
     QTransform transform{m_transform};
     const auto [scaleX, scaleY]{Common::Utils::Math::extractScale(transform)};
 
-    if (m_mode == Mode::Normal && qFuzzyCompare(1.0, scaleY) && !qFuzzyCompare(1.0, scaleX)) {
+    m_isHorizontalResize = m_mode == Mode::Normal && qFuzzyCompare(1.0, scaleY) && !qFuzzyCompare(1.0, scaleX);
+
+    if (m_isHorizontalResize) {
         const qreal width = m_wrapWidth > 0 ? m_wrapWidth : m_boundingBox.width();
         const qreal targetWidth = std::max(width * scaleX, minWrapWidth());
 
-        m_document.setTextWidth(targetWidth);
-        m_boundingBox.setHeight(m_document.size().height());
+        if (qRound(m_document.textWidth()) != targetWidth) {
+            m_document.setTextWidth(targetWidth);
+            m_boundingBox.setHeight(m_document.size().height());
+        }
     }
 }
 
@@ -140,15 +140,9 @@ void TextItem::commitTransformation()
     const auto [scaleX, scaleY]{Common::Utils::Math::extractScale(m_transform)};
     const QTransform filtered{scaleX, 0, 0, scaleY, 0, 0};
 
-    if (!qFuzzyCompare(1.0, scaleX)) {
-        if (qFuzzyCompare(1.0, scaleY)) {
-            const qreal width = m_wrapWidth > 0 ? m_wrapWidth : m_boundingBox.width();
-            m_wrapWidth = std::max(width * scaleX, minWrapWidth());
-        } else {
-            if (m_wrapWidth > 0) {
-                m_wrapWidth = std::max(m_wrapWidth * scaleX, minWrapWidth());
-            }
-        }
+    if (m_isHorizontalResize) {
+        const qreal width = m_wrapWidth > 0 ? m_wrapWidth : m_boundingBox.width();
+        m_wrapWidth = std::max(width * scaleX, minWrapWidth());
     }
 
     m_boundingBox = filtered.map(m_boundingBox).boundingRect();
@@ -160,12 +154,17 @@ void TextItem::commitTransformation()
         Item::setProperty(Property::Type::FontSize, Property{newFontSize, Property::Type::FontSize});
     }
     updateBoundingBox();
+    m_isHorizontalResize = false;
 }
 
 void TextItem::scaleTextFragments(const qreal scaleY)
 {
+    const QSignalBlocker blocker{m_document};
     m_cursor.beginEditBlock();
 
+    m_document.setTextWidth(-1);
+    const qreal oldIdealWidth = m_document.idealWidth();
+
     QTextBlock block = m_document.firstBlock();
     while (block.isValid()) {
         for (auto it = block.begin(); !it.atEnd(); ++it) {
@@ -181,6 +180,13 @@ void TextItem::scaleTextFragments(const qreal scaleY)
         block = block.next();
     }
 
+    m_document.setTextWidth(-1);
+    const qreal newIdealWidth = m_document.idealWidth();
+    const qreal scale = newIdealWidth / oldIdealWidth;
+    if (m_wrapWidth > 0) {
+        m_wrapWidth = std::max(m_wrapWidth * scale, minWrapWidth());
+    }
+
     m_cursor.endEditBlock();
 }
 
@@ -552,7 +558,7 @@ void TextItem::deserialize(const QJsonObject &obj)
 
 bool TextItem::needsCaching() const
 {
-    return true;
+    return !m_isHorizontalResize;
 }
 
 QDebug operator<<(QDebug d, const TextItem &t)
diff --git a/src/gui/item/text.hpp b/src/gui/item/text.hpp
index 13ec2ddc..4240e6ef 100644
--- a/src/gui/item/text.hpp
+++ b/src/gui/item/text.hpp
@@ -90,5 +90,6 @@ private:
     int m_preeditCursorPos{0};
 
     qreal m_wrapWidth{-1};
+    bool m_isHorizontalResize{false};
 };
 LIBDRAWYGUI_EXPORT QDebug operator<<(QDebug d, const TextItem &t);
diff --git a/src/widgets/transformhandler/resizetransformhandler.cpp b/src/widgets/transformhandler/resizetransformhandler.cpp
index 1e5c2091..533c63a2 100644
--- a/src/widgets/transformhandler/resizetransformhandler.cpp
+++ b/src/widgets/transformhandler/resizetransformhandler.cpp
@@ -180,7 +180,7 @@ TransformHandler::State ResizeTransformHandler::mouseMoved(ApplicationContext *c
                 item->resize(transformUpdate);
             }
 
-            if (!item->needsCaching()) {
+            if (!item->needsCaching() && item->formType() != Item::FormType::Text) {
                 item->commitTransformation();
             }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.