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