void StaffText::layout() { if (autoplace()) setUserOff(QPointF()); QPointF p(textStyle().offset(spatium())); if (placement() == Element::Placement::BELOW) p.ry() = - p.ry() + lineHeight(); setPos(p); Text::layout1(); if (!parent()) // palette & clone trick return; if (autoplace() && segment()) { qreal minDistance = score()->styleP(StyleIdx::dynamicsMinDistance); // TODO Shape s1 = segment()->staffShape(staffIdx()).translated(segment()->pos()); Shape s2 = shape().translated(segment()->pos()); if (placement() == Element::Placement::ABOVE) { qreal d = s2.minVerticalDistance(s1); if (d > -minDistance) rUserYoffset() = -d - minDistance; } else { qreal d = s1.minVerticalDistance(s2); if (d > -minDistance) rUserYoffset() = d + minDistance; } } adjustReadPos(); }
short RenderListMarker::baselinePosition(bool, bool) const { if (!isImage()) { const Font& font = style()->font(); return font.ascent() + (lineHeight(false) - font.height())/2; } return height(); }
void SimpleText::layout() { int n = _text.size(); if (!n) { setPos(QPointF()); setbbox(QRectF()); return; } QFontMetricsF fm(_textStyle.fontPx(spatium())); QPointF o(_textStyle.offset(spatium())); QRectF bb; qreal lh = lineHeight(); qreal ly = .0; for (int i = 0; i < n; ++i) { TLine* t = &_text[i]; QRectF r(fm.tightBoundingRect(t->text)); t->pos.ry() = ly; if (align() & ALIGN_BOTTOM) t->pos.ry() += -r.bottom(); else if (align() & ALIGN_VCENTER) t->pos.ry() += -(r.top() + r.bottom()) * .5; else if (align() & ALIGN_BASELINE) ; else // ALIGN_TOP t->pos.ry() += -r.top(); if (align() & ALIGN_RIGHT) t->pos.rx() = -r.right(); else if (align() & ALIGN_HCENTER) t->pos.rx() = -(r.left() + r.right()) * .5; else // ALIGN_LEFT t->pos.rx() = -r.left(); bb |= r.translated(t->pos); ly += lh; } setPos(o); setbbox(bb); }
LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset) { ASSERT(!slowFirstChild()); // FIXME: This does not take into account either :first-line or :first-letter // However, as soon as some content is entered, the line boxes will be // constructed and this kludge is not called any more. So only the caret size // of an empty :first-line'd block is wrong. I think we can live with that. RenderStyle* currentStyle = firstLineStyle(); enum CaretAlignment { alignLeft, alignRight, alignCenter }; CaretAlignment alignment = alignLeft; switch (currentStyle->textAlign()) { case LEFT: case WEBKIT_LEFT: break; case CENTER: case WEBKIT_CENTER: alignment = alignCenter; break; case RIGHT: case WEBKIT_RIGHT: alignment = alignRight; break; case JUSTIFY: case TASTART: if (!currentStyle->isLeftToRightDirection()) alignment = alignRight; break; case TAEND: if (currentStyle->isLeftToRightDirection()) alignment = alignRight; break; } LayoutUnit x = borderLeft() + paddingLeft(); LayoutUnit maxX = width - borderRight() - paddingRight(); switch (alignment) { case alignLeft: if (currentStyle->isLeftToRightDirection()) x += textIndentOffset; break; case alignCenter: x = (x + maxX) / 2; if (currentStyle->isLeftToRightDirection()) x += textIndentOffset / 2; else x -= textIndentOffset / 2; break; case alignRight: x = maxX - caretWidth; if (!currentStyle->isLeftToRightDirection()) x -= textIndentOffset; break; } x = std::min(x, std::max<LayoutUnit>(maxX - caretWidth, 0)); LayoutUnit height = style()->fontMetrics().height(); LayoutUnit verticalSpace = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes) - height; LayoutUnit y = paddingTop() + borderTop() + (verticalSpace / 2); return currentStyle->isHorizontalWritingMode() ? LayoutRect(x, y, caretWidth, height) : LayoutRect(y, x, height, caretWidth); }
int QDeclarativeText::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QDeclarativeImplicitSizeItem::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { if (_id < 17) qt_static_metacall(this, _c, _id, _a); _id -= 17; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< QString*>(_v) = text(); break; case 1: *reinterpret_cast< QFont*>(_v) = font(); break; case 2: *reinterpret_cast< QColor*>(_v) = color(); break; case 3: *reinterpret_cast< TextStyle*>(_v) = style(); break; case 4: *reinterpret_cast< QColor*>(_v) = styleColor(); break; case 5: *reinterpret_cast< HAlignment*>(_v) = hAlign(); break; case 6: *reinterpret_cast< VAlignment*>(_v) = vAlign(); break; case 7: *reinterpret_cast< WrapMode*>(_v) = wrapMode(); break; case 8: *reinterpret_cast< int*>(_v) = lineCount(); break; case 9: *reinterpret_cast< bool*>(_v) = truncated(); break; case 10: *reinterpret_cast< int*>(_v) = maximumLineCount(); break; case 11: *reinterpret_cast< TextFormat*>(_v) = textFormat(); break; case 12: *reinterpret_cast< TextElideMode*>(_v) = elideMode(); break; case 13: *reinterpret_cast< qreal*>(_v) = paintedWidth(); break; case 14: *reinterpret_cast< qreal*>(_v) = paintedHeight(); break; case 15: *reinterpret_cast< qreal*>(_v) = lineHeight(); break; case 16: *reinterpret_cast< LineHeightMode*>(_v) = lineHeightMode(); break; } _id -= 17; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setText(*reinterpret_cast< QString*>(_v)); break; case 1: setFont(*reinterpret_cast< QFont*>(_v)); break; case 2: setColor(*reinterpret_cast< QColor*>(_v)); break; case 3: setStyle(*reinterpret_cast< TextStyle*>(_v)); break; case 4: setStyleColor(*reinterpret_cast< QColor*>(_v)); break; case 5: setHAlign(*reinterpret_cast< HAlignment*>(_v)); break; case 6: setVAlign(*reinterpret_cast< VAlignment*>(_v)); break; case 7: setWrapMode(*reinterpret_cast< WrapMode*>(_v)); break; case 10: setMaximumLineCount(*reinterpret_cast< int*>(_v)); break; case 11: setTextFormat(*reinterpret_cast< TextFormat*>(_v)); break; case 12: setElideMode(*reinterpret_cast< TextElideMode*>(_v)); break; case 15: setLineHeight(*reinterpret_cast< qreal*>(_v)); break; case 16: setLineHeightMode(*reinterpret_cast< LineHeightMode*>(_v)); break; } _id -= 17; } else if (_c == QMetaObject::ResetProperty) { switch (_id) { case 5: resetHAlign(); break; case 10: resetMaximumLineCount(); break; } _id -= 17; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 17; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 17; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 17; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 17; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 17; } #endif // QT_NO_PROPERTIES return _id; }
/* The ultimate line painting function. Currently missing features: - draw indent lines */ void KateRenderer::paintTextLine(QPainter& paint, KateLineLayoutPtr range, int xStart, int xEnd, const KTextEditor::Cursor* cursor) { Q_ASSERT(range->isValid()); // kDebug( 13033 )<<"KateRenderer::paintTextLine"; // font data const QFontMetricsF &fm = config()->fontMetrics(); int currentViewLine = -1; if (cursor && cursor->line() == range->line()) currentViewLine = range->viewLineForColumn(cursor->column()); paintTextLineBackground(paint, range, currentViewLine, xStart, xEnd); if (range->layout()) { bool drawSelection = m_view->selection() && showSelections() && m_view->selectionRange().overlapsLine(range->line()); // Draw selection in block selecton mode. We need 2 kinds of selections that QTextLayout::draw can't render: // - past-end-of-line selection and // - 0-column-wide selection (used to indicate where text will be typed) if (drawSelection && m_view->blockSelection()) { int selectionStartColumn = m_doc->fromVirtualColumn(range->line(), m_doc->toVirtualColumn(m_view->selectionRange().start())); int selectionEndColumn = m_doc->fromVirtualColumn(range->line(), m_doc->toVirtualColumn(m_view->selectionRange().end())); QBrush selectionBrush = config()->selectionColor(); if (selectionStartColumn != selectionEndColumn) { KateTextLayout lastLine = range->viewLine(range->viewLineCount() - 1); if (selectionEndColumn > lastLine.startCol()) { int selectionStartX = (selectionStartColumn > lastLine.startCol()) ? cursorToX(lastLine, selectionStartColumn, true) : 0; int selectionEndX = cursorToX(lastLine, selectionEndColumn, true); paint.fillRect(QRect(selectionStartX - xStart, (int)lastLine.lineLayout().y(), selectionEndX - selectionStartX, lineHeight()), selectionBrush); } } else { const int selectStickWidth = 2; KateTextLayout selectionLine = range->viewLine(range->viewLineForColumn(selectionStartColumn)); int selectionX = cursorToX(selectionLine, selectionStartColumn, true); paint.fillRect(QRect(selectionX - xStart, (int)selectionLine.lineLayout().y(), selectStickWidth, lineHeight()), selectionBrush); } } QVector<QTextLayout::FormatRange> additionalFormats; if (range->length() > 0) { // We may have changed the pen, be absolutely sure it gets set back to // normal foreground color before drawing text for text that does not // set the pen color paint.setPen(attribute(KTextEditor::HighlightInterface::dsNormal)->foreground().color()); // Draw the text :) if (drawSelection) { // FIXME toVector() may be a performance issue additionalFormats = decorationsForLine(range->textLine(), range->line(), true).toVector(); range->layout()->draw(&paint, QPoint(-xStart,0), additionalFormats); } else { range->layout()->draw(&paint, QPoint(-xStart,0)); } } QBrush backgroundBrush; bool backgroundBrushSet = false; // Loop each individual line for additional text decoration etc. QListIterator<QTextLayout::FormatRange> it = range->layout()->additionalFormats(); QVectorIterator<QTextLayout::FormatRange> it2 = additionalFormats; for (int i = 0; i < range->viewLineCount(); ++i) { KateTextLayout line = range->viewLine(i); // Determine the background to use, if any, for the end of this view line backgroundBrushSet = false; while (it2.hasNext()) { const QTextLayout::FormatRange& fr = it2.peekNext(); if (fr.start > line.endCol()) break; if (fr.start + fr.length > line.endCol()) { if (fr.format.hasProperty(QTextFormat::BackgroundBrush)) { backgroundBrushSet = true; backgroundBrush = fr.format.background(); } goto backgroundDetermined; } it2.next(); } while (it.hasNext()) { const QTextLayout::FormatRange& fr = it.peekNext(); if (fr.start > line.endCol()) break; if (fr.start + fr.length > line.endCol()) { if (fr.format.hasProperty(QTextFormat::BackgroundBrush)) { backgroundBrushSet = true; backgroundBrush = fr.format.background(); } break; } it.next(); } backgroundDetermined: // Draw selection or background color outside of areas where text is rendered if (!m_printerFriendly ) { bool draw = false; QBrush drawBrush; if (m_view->selection() && !m_view->blockSelection() && m_view->lineEndSelected(line.end(true))) { draw = true; drawBrush = config()->selectionColor(); } else if (backgroundBrushSet && !m_view->blockSelection()) { draw = true; drawBrush = backgroundBrush; } if (draw) { int fillStartX = line.endX() - line.startX() + line.xOffset() - xStart; int fillStartY = lineHeight() * i; int width= xEnd - xStart - fillStartX; int height= lineHeight(); // reverse X for right-aligned lines if (range->layout()->textOption().alignment() == Qt::AlignRight) fillStartX = 0; if (width > 0) { QRect area(fillStartX, fillStartY, width, height); paint.fillRect(area, drawBrush); } } } // Draw indent lines if (showIndentLines() && i == 0) { const qreal w = spaceWidth(); const int lastIndentColumn = range->textLine()->indentDepth(m_tabWidth); for (int x = m_indentWidth; x < lastIndentColumn; x += m_indentWidth) { paintIndentMarker(paint, x * w + 1 - xStart, range->line()); } } // draw an open box to mark non-breaking spaces const QString& text = range->textLine()->string(); int y = lineHeight() * i + fm.ascent() - fm.strikeOutPos(); int nbSpaceIndex = text.indexOf(nbSpaceChar, line.lineLayout().xToCursor(xStart)); while (nbSpaceIndex != -1 && nbSpaceIndex < line.endCol()) { int x = line.lineLayout().cursorToX(nbSpaceIndex); if (x > xEnd) break; paintNonBreakSpace(paint, x - xStart, y); nbSpaceIndex = text.indexOf(nbSpaceChar, nbSpaceIndex + 1); } // draw tab stop indicators if (showTabs()) { int tabIndex = text.indexOf(tabChar, line.lineLayout().xToCursor(xStart)); while (tabIndex != -1 && tabIndex < line.endCol()) { int x = line.lineLayout().cursorToX(tabIndex); if (x > xEnd) break; paintTabstop(paint, x - xStart + spaceWidth()/2.0, y); tabIndex = text.indexOf(tabChar, tabIndex + 1); } } // draw trailing spaces if (showTrailingSpaces()) { int spaceIndex = line.endCol() - 1; int trailingPos = range->textLine()->lastChar(); if (trailingPos < 0) trailingPos = 0; if (spaceIndex >= trailingPos) { while (spaceIndex >= line.startCol() && text.at(spaceIndex).isSpace()) { if (text.at(spaceIndex) != '\t' || !showTabs()) paintTrailingSpace(paint, line.lineLayout().cursorToX(spaceIndex) - xStart + spaceWidth()/2.0, y); --spaceIndex; } } } } // draw word-wrap-honor-indent filling if ( (range->viewLineCount() > 1) && range->shiftX() && (range->shiftX() > xStart) ) { if (backgroundBrushSet) paint.fillRect(0, lineHeight(), range->shiftX() - xStart, lineHeight() * (range->viewLineCount() - 1), backgroundBrush); paint.fillRect(0, lineHeight(), range->shiftX() - xStart, lineHeight() * (range->viewLineCount() - 1), QBrush(config()->wordWrapMarkerColor(), Qt::Dense4Pattern)); } // Draw caret if (drawCaret() && cursor && range->includesCursor(*cursor)) { int caretWidth, lineWidth = 2; QColor color; QTextLine line = range->layout()->lineForTextPosition(qMin(cursor->column(), range->length())); // Determine the caret's style caretStyles style = caretStyle(); // Make the caret the desired width if (style == Line) { caretWidth = lineWidth; } else if (line.isValid() && cursor->column() < range->length()) { caretWidth = int(line.cursorToX(cursor->column() + 1) - line.cursorToX(cursor->column())); if (caretWidth < 0) { caretWidth = -caretWidth; } } else { caretWidth = spaceWidth(); } // Determine the color if (m_caretOverrideColor.isValid()) { // Could actually use the real highlighting system for this... // would be slower, but more accurate for corner cases color = m_caretOverrideColor; } else { // search for the FormatRange that includes the cursor foreach (const QTextLayout::FormatRange &r, range->layout()->additionalFormats()) { if ((r.start <= cursor->column() ) && ( (r.start + r.length) > cursor->column())) { // check for Qt::NoBrush, as the returned color is black() and no invalid QColor QBrush foregroundBrush = r.format.foreground(); if (foregroundBrush != Qt::NoBrush) { color = r.format.foreground().color(); } break; } } // still no color found, fall back to default style if (!color.isValid()) color = attribute(KTextEditor::HighlightInterface::dsNormal)->foreground().color(); } // Clip the caret - Qt's caret has a habit of intruding onto other lines. paint.save(); paint.setClipRect(0, line.lineNumber() * lineHeight(), xEnd - xStart, lineHeight()); switch(style) { case Line : paint.setPen(QPen(color, caretWidth)); break; case Block : // use a gray caret so it's possible to see the character color.setAlpha(128); paint.setPen(QPen(color, caretWidth)); break; case Underline : paint.setClipRect(0, lineHeight() - lineWidth, xEnd - xStart, lineWidth); break; case Half : color.setAlpha(128); paint.setPen(QPen(color, caretWidth)); paint.setClipRect(0, lineHeight() / 2, xEnd - xStart, lineHeight() / 2); break; } if (cursor->column() <= range->length()) { range->layout()->drawCursor(&paint, QPoint(-xStart,0), cursor->column(), caretWidth); } else { // Off the end of the line... must be block mode. Draw the caret ourselves. const KateTextLayout& lastLine = range->viewLine(range->viewLineCount() - 1); int x = cursorToX(lastLine, KTextEditor::Cursor(range->line(), cursor->column()), true); if ((x >= xStart) && (x <= xEnd)) { paint.fillRect(x - xStart, (int)lastLine.lineLayout().y(), caretWidth, lineHeight(), color); } } paint.restore(); }
void KateRenderer::paintTextLineBackground(QPainter& paint, KateLineLayoutPtr layout, int currentViewLine, int xStart, int xEnd) { if (isPrinterFriendly()) return; // Normal background color QColor backgroundColor( config()->backgroundColor() ); // paint the current line background if we're on the current line QColor currentLineColor = config()->highlightedLineColor(); // Check for mark background int markRed = 0, markGreen = 0, markBlue = 0, markCount = 0; // Retrieve marks for this line uint mrk = m_doc->mark( layout->line() ); if (mrk) { for (uint bit = 0; bit < 32; bit++) { KTextEditor::MarkInterface::MarkTypes markType = (KTextEditor::MarkInterface::MarkTypes)(1<<bit); if (mrk & markType) { QColor markColor = config()->lineMarkerColor(markType); if (markColor.isValid()) { markCount++; markRed += markColor.red(); markGreen += markColor.green(); markBlue += markColor.blue(); } } } // for } // Marks if (markCount) { markRed /= markCount; markGreen /= markCount; markBlue /= markCount; backgroundColor.setRgb( int((backgroundColor.red() * 0.9) + (markRed * 0.1)), int((backgroundColor.green() * 0.9) + (markGreen * 0.1)), int((backgroundColor.blue() * 0.9) + (markBlue * 0.1)) ); } // Draw line background paint.fillRect(0, 0, xEnd - xStart, lineHeight() * layout->viewLineCount(), backgroundColor); // paint the current line background if we're on the current line if (currentViewLine != -1) { if (markCount) { markRed /= markCount; markGreen /= markCount; markBlue /= markCount; currentLineColor.setRgb( int((currentLineColor.red() * 0.9) + (markRed * 0.1)), int((currentLineColor.green() * 0.9) + (markGreen * 0.1)), int((currentLineColor.blue() * 0.9) + (markBlue * 0.1)) ); } paint.fillRect(0, lineHeight() * currentViewLine, xEnd - xStart, lineHeight(), currentLineColor); } }
int RenderLineBreak::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const { const RenderStyle& style = firstLine ? firstLineStyle() : this->style(); const FontMetrics& fontMetrics = style.fontMetrics(); return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2; }
/** * @brief Calculates preferable editor height for specified number of lines */ int ScriptWidget::editorHeight(int lines) { return lines * lineHeight() + 8; }
static void drawChar(unsigned char ch, int posX, int posY, font_t* font, int alignFlags, short /*textFlags*/) { float x = (float) posX, y = (float) posY; Point2Raw coords[4]; RectRaw geometry; if(alignFlags & ALIGN_RIGHT) x -= Fonts_CharWidth(font, ch); else if(!(alignFlags & ALIGN_LEFT)) x -= Fonts_CharWidth(font, ch) / 2; if(alignFlags & ALIGN_BOTTOM) y -= topToAscent(font) + lineHeight(font, ch); else if(!(alignFlags & ALIGN_TOP)) y -= (topToAscent(font) + lineHeight(font, ch))/2; glMatrixMode(GL_MODELVIEW); glTranslatef(x, y, 0); switch(Font_Type(font)) { case FT_BITMAP: /// @todo Filtering should be determined at a higher level. /// @todo We should not need to re-bind this texture here. GL_BindTextureUnmanaged(BitmapFont_GLTextureName(font), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, filterUI? GL_LINEAR : GL_NEAREST); std::memcpy(&geometry, BitmapFont_CharGeometry(font, ch), sizeof(geometry)); BitmapFont_CharCoords(font, ch, coords); break; case FT_BITMAPCOMPOSITE: { uint8_t const border = BitmapCompositeFont_CharBorder(font, ch); GL_BindTexture(BitmapCompositeFont_CharTexture(font, ch)); std::memcpy(&geometry, BitmapCompositeFont_CharGeometry(font, ch), sizeof(geometry)); if(border) { geometry.origin.x -= border; geometry.origin.y -= border; geometry.size.width += border*2; geometry.size.height += border*2; } BitmapCompositeFont_CharCoords(font, ch, coords); break; } default: Con_Error("FR_DrawChar: Invalid font type %i.", (int) Font_Type(font)); exit(1); // Unreachable. } if(font->_marginWidth) { geometry.origin.x -= font->_marginWidth; geometry.size.width += font->_marginWidth*2; } if(font->_marginHeight) { geometry.origin.y -= font->_marginHeight; geometry.size.height += font->_marginHeight*2; } GL_DrawRectWithCoords(&geometry, coords); if(Font_Type(font) == FT_BITMAPCOMPOSITE) { GL_SetNoTexture(); } glMatrixMode(GL_MODELVIEW); glTranslatef(-x, -y, 0); }