Skip to content
  • 0 Votes
    3 Posts
    666 Views
    I

    This is a pretty old post, but I recently tried to tackle this and wanted to write down some of my findings about this obscure corner of Qt. It is probable that not all of this correct, this is just my current understanding.

    The purpose of QAbstractTextDocumentLayout::draw is to paint all of the relevant text blocks in the document (typically by means of delegating to QTextLayout::draw which does the actual heavy lifting) as well as any additional decorations and elements that surround the actual text objects (e.g. frame borders, list bullets, etc). It is also responsible for drawing the text cursor marker if needed.

    The layout class operates in document coordinates, so the position or size of the viewport of the actual widget (if it is even a widget, it could be drawing to a printer) is of no concern. The given QPainter is already pre-configured to accept the document's coordinate system.

    What defines what elements the view wants painted is the context.clip rectangle. At least those elements that intersect with it should be painted, so a straightforward thing to do would be to iterate over all blocks in the document, and check if their bounding rectangle intersects with the clip rectangle. Given that all blocks should already have their layout in place by the time draw is called, this is relatively fast. Of course this can be further optimized based on the layout class' knowledge of how blocks are laid out, for example a plain-text-like layout that arranges blocks linearly can use some sort of binary search.

    It is allowed to draw more than the clip, so drawing all blocks every time is a valid approach, although inefficient. It is also possible that the given clip rectangle is invalid, in which case everything needs to be drawn anyway. Though, I haven't seen QTextEdit not provide a valid clip.

    Other members of the PaintContext:

    palette - if you want to use the view's palette pens and brushes to paint something, they are available through here, although most colors will be determined by the character format.

    selections - for the text editing widgets, those are the "extra selections". For each painted block, you'll want to check if any of the extra selections' cursor is relevant to that block, turn it into block-relative start and end positions, and collect into a list that will be provided to QTextLayout::draw.

    cursorPosition - position in characters (relative to the document) where the text cursor marker should be drawn. Straightforward implementation would figure out the relevant block containing that position, and if relevant to the draw call, delegate to its' layout's QTextLayout::drawCursor method. You can also paint your own cursor directly with the painter if you'd like something custom. It is -1 if no cursor is required. One thing I noticed is that QTextEdit repeatedly calls draw on the text cursor's immediate area on a timer, alternating cursorPosition between -1 and the actual position, so that' how it makes a blinking cursor. There is also something with additional negative values, that seems related to pre-edit text, which is something I don't fully understand yet.

  • 0 Votes
    1 Posts
    626 Views
    No one has replied