1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <qabstracttextdocumentlayout.h>
41#include <qtextformat.h>
42#include "qtextdocument_p.h"
43#include "qtextengine_p.h"
44#include "qtextlist.h"
45
46#include "qabstracttextdocumentlayout_p.h"
47
48QT_BEGIN_NAMESPACE
49
50QAbstractTextDocumentLayoutPrivate::~QAbstractTextDocumentLayoutPrivate()
51{
52}
53
54QTextObjectInterface::~QTextObjectInterface()
55{
56 // must be empty until ### Qt 6
57}
58
59/*!
60 \class QAbstractTextDocumentLayout
61 \reentrant
62
63 \brief The QAbstractTextDocumentLayout class is an abstract base
64 class used to implement custom layouts for QTextDocuments.
65 \inmodule QtGui
66
67 \ingroup richtext-processing
68
69 The standard layout provided by Qt can handle simple word processing
70 including inline images, lists and tables.
71
72 Some applications, e.g., a word processor or a DTP application might need
73 more features than the ones provided by Qt's layout engine, in which case
74 you can subclass QAbstractTextDocumentLayout to provide custom layout
75 behavior for your text documents.
76
77 An instance of the QAbstractTextDocumentLayout subclass can be installed
78 on a QTextDocument object with the
79 \l{QTextDocument::}{setDocumentLayout()} function.
80
81 You can insert custom objects into a QTextDocument; see the
82 QTextObjectInterface class description for details.
83
84 \sa QTextObjectInterface
85*/
86
87/*!
88 \class QTextObjectInterface
89 \brief The QTextObjectInterface class allows drawing of
90 custom text objects in \l{QTextDocument}s.
91 \since 4.5
92 \inmodule QtGui
93
94 A text object describes the structure of one or more elements in a
95 text document; for instance, images imported from HTML are
96 implemented using text objects. A text object knows how to lay out
97 and draw its elements when a document is being rendered.
98
99 Qt allows custom text objects to be inserted into a document by
100 registering a custom \l{QTextCharFormat::objectType()}{object
101 type} with QTextCharFormat. A QTextObjectInterface must also be
102 implemented for this type and be
103 \l{QAbstractTextDocumentLayout::registerHandler()}{registered}
104 with the QAbstractTextDocumentLayout of the document. When the
105 object type is encountered while rendering a QTextDocument, the
106 intrinsicSize() and drawObject() functions of the interface are
107 called.
108
109 The following list explains the required steps of inserting a
110 custom text object into a document:
111
112 \list
113 \li Choose an \a objectType. The \a objectType is an integer with a
114 value greater or equal to QTextFormat::UserObject.
115 \li Create a QTextCharFormat object and set the object type to the
116 chosen type using the setObjectType() function.
117 \li Implement the QTextObjectInterface class.
118 \li Call QAbstractTextDocumentLayout::registerHandler() with an instance of your
119 QTextObjectInterface subclass to register your object type.
120 \li Insert QChar::ObjectReplacementCharacter with the aforementioned
121 QTextCharFormat of the chosen object type into the document.
122 As mentioned, the functions of QTextObjectInterface
123 \l{QTextObjectInterface::}{intrinsicSize()} and
124 \l{QTextObjectInterface::}{drawObject()} will then be called with the
125 QTextFormat as parameter whenever the replacement character is
126 encountered.
127 \endlist
128
129 A class implementing a text object needs to inherit both QObject
130 and QTextObjectInterface. QObject must be the first class
131 inherited. For instance:
132
133 \snippet qtextobject/textobjectinterface.h 0
134
135 The data of a text object is usually stored in the QTextCharFormat
136 using QTextCharFormat::setProperty(), and then retrieved with
137 QTextCharFormat::property().
138
139 \warning Copy and Paste operations ignore custom text objects.
140
141 \sa {Text Object Example}, QTextCharFormat, QTextLayout
142*/
143
144/*!
145 \fn QTextObjectInterface::~QTextObjectInterface()
146
147 Destroys this QTextObjectInterface.
148*/
149
150/*!
151 \fn virtual QSizeF QTextObjectInterface::intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0
152
153 The intrinsicSize() function returns the size of the text object
154 represented by \a format in the given document (\a doc) at the
155 given position (\a posInDocument).
156
157 The size calculated will be used for subsequent calls to
158 drawObject() for this \a format.
159
160 \sa drawObject()
161*/
162
163/*!
164 \fn virtual void QTextObjectInterface::drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0
165
166 Draws this text object using the specified \a painter.
167
168 The size of the rectangle, \a rect, to draw in is the size
169 previously calculated by intrinsicSize(). The rectangles position
170 is relative to the \a painter.
171
172 You also get the document (\a doc) and the position (\a
173 posInDocument) of the \a format in that document.
174
175 \sa intrinsicSize()
176*/
177
178/*!
179 \fn void QAbstractTextDocumentLayout::update(const QRectF &rect)
180
181 This signal is emitted when the rectangle \a rect has been updated.
182
183 Subclasses of QAbstractTextDocumentLayout should emit this signal when
184 the layout of the contents change in order to repaint.
185*/
186
187/*!
188 \fn void QAbstractTextDocumentLayout::updateBlock(const QTextBlock &block)
189 \since 4.4
190
191 This signal is emitted when the specified \a block has been updated.
192
193 Subclasses of QAbstractTextDocumentLayout should emit this signal when
194 the layout of \a block has changed in order to repaint.
195*/
196
197/*!
198 \fn void QAbstractTextDocumentLayout::documentSizeChanged(const QSizeF &newSize)
199
200 This signal is emitted when the size of the document layout changes to
201 \a newSize.
202
203 Subclasses of QAbstractTextDocumentLayout should emit this signal when the
204 document's entire layout size changes. This signal is useful for widgets
205 that display text documents since it enables them to update their scroll
206 bars correctly.
207
208 \sa documentSize()
209*/
210
211/*!
212 \fn void QAbstractTextDocumentLayout::pageCountChanged(int newPages)
213
214 This signal is emitted when the number of pages in the layout changes;
215 \a newPages is the updated page count.
216
217 Subclasses of QAbstractTextDocumentLayout should emit this signal when
218 the number of pages in the layout has changed. Changes to the page count
219 are caused by changes to the layout or the document content itself.
220
221 \sa pageCount()
222*/
223
224/*!
225 \fn int QAbstractTextDocumentLayout::pageCount() const
226
227 Returns the number of pages contained in the layout.
228
229 \sa pageCountChanged()
230*/
231
232/*!
233 \fn QSizeF QAbstractTextDocumentLayout::documentSize() const
234
235 Returns the total size of the document's layout.
236
237 This information can be used by display widgets to update their scroll bars
238 correctly.
239
240 \sa documentSizeChanged(), QTextDocument::pageSize
241*/
242
243/*!
244 \fn void QAbstractTextDocumentLayout::draw(QPainter *painter, const PaintContext &context)
245
246 Draws the layout with the given \a painter using the given \a context.
247*/
248
249/*!
250 \fn int QAbstractTextDocumentLayout::hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const
251
252 Returns the cursor position for the given \a point with the specified
253 \a accuracy. Returns -1 if no valid cursor position was found.
254*/
255
256/*!
257 \fn void QAbstractTextDocumentLayout::documentChanged(int position, int charsRemoved, int charsAdded)
258
259 This function is called whenever the contents of the document change. A
260 change occurs when text is inserted, removed, or a combination of these
261 two. The change is specified by \a position, \a charsRemoved, and
262 \a charsAdded corresponding to the starting character position of the
263 change, the number of characters removed from the document, and the
264 number of characters added.
265
266 For example, when inserting the text "Hello" into an empty document,
267 \a charsRemoved would be 0 and \a charsAdded would be 5 (the length of
268 the string).
269
270 Replacing text is a combination of removing and inserting. For example, if
271 the text "Hello" gets replaced by "Hi", \a charsRemoved would be 5 and
272 \a charsAdded would be 2.
273
274 For subclasses of QAbstractTextDocumentLayout, this is the central function
275 where a large portion of the work to lay out and position document contents
276 is done.
277
278 For example, in a subclass that only arranges blocks of text, an
279 implementation of this function would have to do the following:
280
281 \list
282 \li Determine the list of changed \l{QTextBlock}(s) using the parameters
283 provided.
284 \li Each QTextBlock object's corresponding QTextLayout object needs to
285 be processed. You can access the \l{QTextBlock}'s layout using the
286 QTextBlock::layout() function. This processing should take the
287 document's page size into consideration.
288 \li If the total number of pages changed, the pageCountChanged() signal
289 should be emitted.
290 \li If the total size changed, the documentSizeChanged() signal should
291 be emitted.
292 \li The update() signal should be emitted to schedule a repaint of areas
293 in the layout that require repainting.
294 \endlist
295
296 \sa QTextLayout
297*/
298
299/*!
300 \class QAbstractTextDocumentLayout::PaintContext
301 \reentrant
302 \inmodule QtGui
303
304 \brief The QAbstractTextDocumentLayout::PaintContext class is a convenience
305 class defining the parameters used when painting a document's layout.
306
307 A paint context is used when rendering custom layouts for QTextDocuments
308 with the QAbstractTextDocumentLayout::draw() function. It is specified by
309 a \l {cursorPosition}{cursor position}, \l {palette}{default text color},
310 \l clip rectangle and a collection of \l selections.
311
312 \sa QAbstractTextDocumentLayout
313*/
314
315/*!
316 \fn QAbstractTextDocumentLayout::PaintContext::PaintContext()
317 \internal
318*/
319
320/*!
321 \variable QAbstractTextDocumentLayout::PaintContext::cursorPosition
322
323 \brief the position within the document, where the cursor line should be
324 drawn.
325
326 The default value is -1.
327*/
328
329/*!
330 \variable QAbstractTextDocumentLayout::PaintContext::palette
331
332 \brief the default color that is used for the text, when no color is
333 specified.
334
335 The default value is the application's default palette.
336*/
337
338/*!
339 \variable QAbstractTextDocumentLayout::PaintContext::clip
340
341 \brief a hint to the layout specifying the area around paragraphs, frames
342 or text require painting.
343
344 Everything outside of this rectangle does not need to be painted.
345
346 Specifying a clip rectangle can speed up drawing of large documents
347 significantly. Note that the clip rectangle is in document coordinates (not
348 in viewport coordinates). It is not a substitute for a clip region set on
349 the painter but merely a hint.
350
351 The default value is a null rectangle indicating everything needs to be
352 painted.
353*/
354
355/*!
356 \variable QAbstractTextDocumentLayout::PaintContext::selections
357
358 \brief the collection of selections that will be rendered when passing this
359 paint context to QAbstractTextDocumentLayout's draw() function.
360
361 The default value is an empty vector indicating no selection.
362*/
363
364/*!
365 \class QAbstractTextDocumentLayout::Selection
366 \reentrant
367 \inmodule QtGui
368
369 \brief The QAbstractTextDocumentLayout::Selection class is a convenience
370 class defining the parameters of a selection.
371
372 A selection can be used to specify a part of a document that should be
373 highlighted when drawing custom layouts for QTextDocuments with the
374 QAbstractTextDocumentLayout::draw() function. It is specified using
375 \l cursor and a \l format.
376
377 \sa QAbstractTextDocumentLayout, PaintContext
378*/
379
380/*!
381 \variable QAbstractTextDocumentLayout::Selection::format
382
383 \brief the format of the selection
384
385 The default value is QTextFormat::InvalidFormat.
386*/
387
388/*!
389 \variable QAbstractTextDocumentLayout::Selection::cursor
390 \brief the selection's cursor
391
392 The default value is a null cursor.
393*/
394
395/*!
396 Creates a new text document layout for the given \a document.
397*/
398QAbstractTextDocumentLayout::QAbstractTextDocumentLayout(QTextDocument *document)
399 : QObject(*new QAbstractTextDocumentLayoutPrivate, document)
400{
401 Q_D(QAbstractTextDocumentLayout);
402 d->setDocument(document);
403}
404
405/*!
406 \internal
407*/
408QAbstractTextDocumentLayout::QAbstractTextDocumentLayout(QAbstractTextDocumentLayoutPrivate &p, QTextDocument *document)
409 :QObject(p, document)
410{
411 Q_D(QAbstractTextDocumentLayout);
412 d->setDocument(document);
413}
414
415/*!
416 \internal
417*/
418QAbstractTextDocumentLayout::~QAbstractTextDocumentLayout()
419{
420}
421
422/*!
423 Registers the given \a component as a handler for items of the given \a objectType.
424
425 \note registerHandler() has to be called once for each object type. This
426 means that there is only one handler for multiple replacement characters
427 of the same object type.
428
429 The text document layout does not take ownership of \c component.
430*/
431void QAbstractTextDocumentLayout::registerHandler(int objectType, QObject *component)
432{
433 Q_D(QAbstractTextDocumentLayout);
434
435 QTextObjectInterface *iface = qobject_cast<QTextObjectInterface *>(object: component);
436 if (!iface)
437 return; // ### print error message on terminal?
438
439 connect(sender: component, SIGNAL(destroyed(QObject*)), receiver: this, SLOT(_q_handlerDestroyed(QObject*)));
440
441 QTextObjectHandler h;
442 h.iface = iface;
443 h.component = component;
444 d->handlers.insert(key: objectType, value: h);
445}
446
447/*!
448 \since 5.2
449
450 Unregisters the given \a component as a handler for items of the given \a objectType, or
451 any handler if the \a component is not specified.
452*/
453void QAbstractTextDocumentLayout::unregisterHandler(int objectType, QObject *component)
454{
455 Q_D(QAbstractTextDocumentLayout);
456
457 const auto it = d->handlers.constFind(key: objectType);
458 if (it != d->handlers.cend() && (!component || component == it->component)) {
459 if (component)
460 disconnect(sender: component, SIGNAL(destroyed(QObject*)), receiver: this, SLOT(_q_handlerDestroyed(QObject*)));
461 d->handlers.erase(it);
462 }
463}
464
465/*!
466 Returns a handler for objects of the given \a objectType.
467*/
468QTextObjectInterface *QAbstractTextDocumentLayout::handlerForObject(int objectType) const
469{
470 Q_D(const QAbstractTextDocumentLayout);
471
472 QTextObjectHandler handler = d->handlers.value(key: objectType);
473 if (!handler.component)
474 return nullptr;
475
476 return handler.iface;
477}
478
479/*!
480 Sets the size of the inline object \a item corresponding to the text
481 \a format.
482
483 \a posInDocument specifies the position of the object within the document.
484
485 The default implementation resizes the \a item to the size returned by
486 the object handler's intrinsicSize() function. This function is called only
487 within Qt. Subclasses can reimplement this function to customize the
488 resizing of inline objects.
489*/
490void QAbstractTextDocumentLayout::resizeInlineObject(QTextInlineObject item, int posInDocument, const QTextFormat &format)
491{
492 Q_D(QAbstractTextDocumentLayout);
493
494 QTextCharFormat f = format.toCharFormat();
495 Q_ASSERT(f.isValid());
496 QTextObjectHandler handler = d->handlers.value(key: f.objectType());
497 if (!handler.component)
498 return;
499
500 QSizeF s = handler.iface->intrinsicSize(doc: document(), posInDocument, format);
501 item.setWidth(s.width());
502 item.setAscent(s.height());
503 item.setDescent(0);
504}
505
506/*!
507 Lays out the inline object \a item using the given text \a format.
508
509 \a posInDocument specifies the position of the object within the document.
510
511 The default implementation does nothing. This function is called only
512 within Qt. Subclasses can reimplement this function to customize the
513 position of inline objects.
514
515 \sa drawInlineObject()
516*/
517void QAbstractTextDocumentLayout::positionInlineObject(QTextInlineObject item, int posInDocument, const QTextFormat &format)
518{
519 Q_UNUSED(item);
520 Q_UNUSED(posInDocument);
521 Q_UNUSED(format);
522}
523
524/*!
525 \fn void QAbstractTextDocumentLayout::drawInlineObject(QPainter *painter, const QRectF &rect, QTextInlineObject object, int posInDocument, const QTextFormat &format)
526
527 This function is called to draw the inline object, \a object, with the
528 given \a painter within the rectangle specified by \a rect using the
529 specified text \a format.
530
531 \a posInDocument specifies the position of the object within the document.
532
533 The default implementation calls drawObject() on the object handlers. This
534 function is called only within Qt. Subclasses can reimplement this function
535 to customize the drawing of inline objects.
536
537 \sa draw()
538*/
539void QAbstractTextDocumentLayout::drawInlineObject(QPainter *p, const QRectF &rect, QTextInlineObject item,
540 int posInDocument, const QTextFormat &format)
541{
542 Q_UNUSED(item);
543 Q_D(QAbstractTextDocumentLayout);
544
545 QTextCharFormat f = format.toCharFormat();
546 Q_ASSERT(f.isValid());
547 QTextObjectHandler handler = d->handlers.value(key: f.objectType());
548 if (!handler.component)
549 return;
550
551 handler.iface->drawObject(painter: p, rect, doc: document(), posInDocument, format);
552}
553
554void QAbstractTextDocumentLayoutPrivate::_q_handlerDestroyed(QObject *obj)
555{
556 HandlerHash::Iterator it = handlers.begin();
557 while (it != handlers.end())
558 if ((*it).component == obj)
559 it = handlers.erase(it);
560 else
561 ++it;
562}
563
564/*!
565 \internal
566
567 Returns the index of the format at position \a pos.
568*/
569int QAbstractTextDocumentLayout::formatIndex(int pos)
570{
571 QTextDocumentPrivate *pieceTable = qobject_cast<QTextDocument *>(object: parent())->docHandle();
572 return pieceTable->find(pos).value()->format;
573}
574
575/*!
576 \fn QTextCharFormat QAbstractTextDocumentLayout::format(int position)
577
578 Returns the character format that is applicable at the given \a position.
579*/
580QTextCharFormat QAbstractTextDocumentLayout::format(int pos)
581{
582 QTextDocumentPrivate *pieceTable = qobject_cast<QTextDocument *>(object: parent())->docHandle();
583 int idx = pieceTable->find(pos).value()->format;
584 return pieceTable->formatCollection()->charFormat(index: idx);
585}
586
587
588
589/*!
590 Returns the text document that this layout is operating on.
591*/
592QTextDocument *QAbstractTextDocumentLayout::document() const
593{
594 Q_D(const QAbstractTextDocumentLayout);
595 return d->document;
596}
597
598/*!
599 \fn QString QAbstractTextDocumentLayout::anchorAt(const QPointF &position) const
600
601 Returns the reference of the anchor the given \a position, or an empty
602 string if no anchor exists at that point.
603*/
604QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const
605{
606 QTextCharFormat fmt = formatAt(pos).toCharFormat();
607 return fmt.anchorHref();
608}
609
610/*!
611 \since 5.8
612
613 Returns the source of the image at the given position \a pos, or an empty
614 string if no image exists at that point.
615*/
616QString QAbstractTextDocumentLayout::imageAt(const QPointF &pos) const
617{
618 QTextImageFormat fmt = formatAt(pos).toImageFormat();
619 return fmt.name();
620}
621
622/*!
623 \since 5.8
624
625 Returns the text format at the given position \a pos.
626*/
627QTextFormat QAbstractTextDocumentLayout::formatAt(const QPointF &pos) const
628{
629 int cursorPos = hitTest(point: pos, accuracy: Qt::ExactHit);
630 if (cursorPos == -1)
631 return QTextFormat();
632
633 // compensate for preedit in the hit text block
634 QTextBlock block = document()->firstBlock();
635 while (block.isValid()) {
636 QRectF blockBr = blockBoundingRect(block);
637 if (blockBr.contains(p: pos)) {
638 QTextLayout *layout = block.layout();
639 int relativeCursorPos = cursorPos - block.position();
640 const int preeditLength = layout ? layout->preeditAreaText().length() : 0;
641 if (preeditLength > 0 && relativeCursorPos > layout->preeditAreaPosition())
642 cursorPos -= qMin(a: cursorPos - layout->preeditAreaPosition(), b: preeditLength);
643 break;
644 }
645 block = block.next();
646 }
647
648 QTextDocumentPrivate *pieceTable = qobject_cast<const QTextDocument *>(object: parent())->docHandle();
649 QTextDocumentPrivate::FragmentIterator it = pieceTable->find(pos: cursorPos);
650 return pieceTable->formatCollection()->format(idx: it->format);
651}
652
653/*!
654 \since 5.14
655
656 Returns the block (probably a list item) whose \l{QTextBlockFormat::marker()}{marker}
657 is found at the given position \a pos.
658*/
659QTextBlock QAbstractTextDocumentLayout::blockWithMarkerAt(const QPointF &pos) const
660{
661 QTextBlock block = document()->firstBlock();
662 while (block.isValid()) {
663 if (block.blockFormat().marker() != QTextBlockFormat::MarkerType::NoMarker) {
664 QRectF blockBr = blockBoundingRect(block);
665 QTextBlockFormat blockFmt = block.blockFormat();
666 QFontMetrics fm(block.charFormat().font());
667 qreal totalIndent = blockFmt.indent() + blockFmt.leftMargin() + blockFmt.textIndent();
668 if (block.textList())
669 totalIndent += block.textList()->format().indent() * 40;
670 QRectF adjustedBr = blockBr.adjusted(xp1: totalIndent - fm.height(), yp1: 0, xp2: totalIndent - blockBr.width(), yp2: fm.height() - blockBr.height());
671 if (adjustedBr.contains(p: pos)) {
672 //qDebug() << "hit block" << block.text() << blockBr << adjustedBr << "marker" << block.blockFormat().marker()
673 // << "font" << block.charFormat().font() << "adj" << lineHeight << totalIndent;
674 if (block.blockFormat().hasProperty(propertyId: QTextFormat::BlockMarker))
675 return block;
676 }
677 }
678 block = block.next();
679 }
680 return QTextBlock();
681}
682
683/*!
684 \fn QRectF QAbstractTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
685
686 Returns the bounding rectangle of \a frame.
687*/
688
689/*!
690 \fn QRectF QAbstractTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
691
692 Returns the bounding rectangle of \a block.
693*/
694
695/*!
696 Sets the paint device used for rendering the document's layout to the given
697 \a device.
698
699 \sa paintDevice()
700*/
701void QAbstractTextDocumentLayout::setPaintDevice(QPaintDevice *device)
702{
703 Q_D(QAbstractTextDocumentLayout);
704 d->paintDevice = device;
705}
706
707/*!
708 Returns the paint device used to render the document's layout.
709
710 \sa setPaintDevice()
711*/
712QPaintDevice *QAbstractTextDocumentLayout::paintDevice() const
713{
714 Q_D(const QAbstractTextDocumentLayout);
715 return d->paintDevice;
716}
717
718QT_END_NAMESPACE
719
720#include "moc_qabstracttextdocumentlayout.cpp"
721

source code of qtbase/src/gui/text/qabstracttextdocumentlayout.cpp