void TextTools::setVCenterAlign() { Align align = (_textElement->align() & ~ALIGN_VMASK) | ALIGN_VCENTER; _textElement->setAlign(align); updateTools(); layoutText(); }
void TextTools::setTopAlign() { Align align = (_textElement->align() & ~ALIGN_VMASK) | ALIGN_TOP; _textElement->setAlign(align); updateTools(); layoutText(); }
void YTDelegate::layoutText(QTextLayout& textLayout, QString text, QSize constraint) const { QTextOption textOption(Qt::AlignJustify); textLayout.setTextOption(textOption); textLayout.setText(text); textLayout.beginLayout(); int lHeight = 0; while(true){ QTextLine line = textLayout.createLine(); if(!line.isValid()) break; line.setLineWidth(constraint.width()); line.setPosition(QPointF(0, lHeight)); if(lHeight + line.height() > constraint.height()) { QTextLine lastLine = textLayout.lineAt(textLayout.lineCount() - 2); QString lastString = text.mid(lastLine.textStart()); QFontMetrics fm(textLayout.font()); text.chop(lastString.length()); text += fm.elidedText(lastString, Qt::ElideRight, constraint.width()-1); textLayout.endLayout(); layoutText(textLayout, text, constraint); return; } lHeight += line.height(); lHeight += line.leading(); } textLayout.endLayout(); }
void TextTools::setBottomAlign() { Align align = (_textElement->align() & ~ALIGN_VMASK) | ALIGN_BOTTOM; _textElement->setAlign(align); updateTools(); layoutText(); }
void TextTools::updateText() { if (_textElement->type() == Element::LYRICS) { _textElement->score()->setLayoutAll(true); _textElement->score()->end(); } else layoutText(); }
bool TextStyleBuilder::prepareLabel(TextStyle::Parameters& _params, Label::Type _type) { if (_params.text.empty() || _params.fontSize <= 0.f) { LOGD("invalid params: '%s' %f", _params.text.c_str(), _params.fontSize); return false; } // Apply text transforms const std::string* renderText; std::string text; if (_params.transform == TextLabelProperty::Transform::none) { renderText = &_params.text; } else { text = applyTextTransform(_params, _params.text); renderText = &text; } // Scale factor by which the texture glyphs are scaled to match fontSize _params.fontScale = _params.fontSize / _params.font->size(); // Stroke width is normalized by the distance of the SDF spread, then // scaled to 255 and packed into the "alpha" channel of stroke. // Maximal strokeWidth is 3px, attribute is normalized to 0-1 range. auto ctx = m_style.context(); uint32_t strokeAttrib = std::max(_params.strokeWidth / ctx->maxStrokeWidth() * 255.f, 0.f); if (strokeAttrib > 255) { LOGN("stroke_width too large: %f / %f", _params.strokeWidth, strokeAttrib/255.f); strokeAttrib = 255; } m_attributes.stroke = (_params.strokeColor & 0x00ffffff) + (strokeAttrib << 24); m_attributes.fill = _params.fill; m_attributes.fontScale = _params.fontScale * 64.f; if (m_attributes.fontScale > 255) { LOGN("Too large font scale %f, maximal scale is 4", _params.fontScale); m_attributes.fontScale = 255; } m_attributes.quadsStart = m_quads.size(); m_attributes.textRanges = TextRange{}; glm::vec2 bbox(0); if (ctx->layoutText(_params, *renderText, m_quads, m_atlasRefs, bbox, m_attributes.textRanges)) { m_attributes.width = bbox.x; m_attributes.height = bbox.y; return true; } return false; }
QSize QmlConsoleItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget); int level = 0; QModelIndex idx(index); while (idx.parent() != QModelIndex()) { idx = idx.parent(); level++; } int width = view->width() - level * view->indentation() - view->verticalScrollBar()->width(); const bool selected = (view->selectionModel()->currentIndex() == index); if (!selected && option.font == m_cachedFont && m_cachedHeight > 0) return QSize(width, m_cachedHeight); ConsoleItem::ItemType type = (ConsoleItem::ItemType)index.data( ConsoleItem::TypeRole).toInt(); bool showTypeIcon = index.parent() == QModelIndex(); bool showExpandableIcon = type == ConsoleItem::DefaultType; QRect rect(level * view->indentation(), 0, width, 0); ConsoleItemPositions positions(rect, opt.font, showTypeIcon, showExpandableIcon); QFontMetrics fm(option.font); qreal height = fm.height(); if (selected) { QString str = index.data(Qt::DisplayRole).toString(); QTextLayout tl(str, option.font); height = layoutText(tl, positions.textAreaWidth()); } height += 2 * ConsoleItemPositions::ITEM_PADDING; if (height < positions.minimumHeight()) height = positions.minimumHeight(); if (!selected) { m_cachedHeight = height; m_cachedFont = option.font; } return QSize(width, height); }
QSize StatusEventItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { int iconHeight, iconWidth; int textWidth, textHeight; QFontMetrics fontMetrics = option.fontMetrics; QPixmap icon = index.data(StatusEventItem::IconRole).value<QPixmap>(); QString text = index.data(StatusEventItem::DescriptionRole).toString(); QTime tstamp = index.data(StatusEventItem::TimestampRole).toTime(); iconHeight = icon.height() + fontMetrics.lineSpacing() + 16; iconWidth = qMax(fontMetrics.width(tstamp.toString()), icon.width()) + 16; textWidth = option.rect.width() - iconWidth; if (option.state & QStyle::State_Selected) layoutText(text, option.font, textWidth, 6, &textHeight); else layoutText(text, option.font, textWidth, 3, &textHeight); textHeight += 8 + fontMetrics.leading() + fontMetrics.lineSpacing(); return QSize(option.rect.width(), qMax(iconHeight, textHeight)); }
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { if (standard) { return QStyledItemDelegate::sizeHint(option, index); } if (!index.isValid()) { return QSize(0, 0); } const QString text = index.model()->data(index, Qt::DisplayRole).toString(); const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>(); const QPixmap pixmap = icon.pixmap(iconSize, iconSize); QFontMetrics fm = option.fontMetrics; int gap = fm.height(); #if QT_VERSION >= 0x050100 QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); #else QSize layoutSize = pixmap.size(); #endif if (layoutSize.height() == 0) { /** * No pixmap loaded yet, we'll use the default icon size in this case. */ layoutSize=QSize(iconSize, iconSize); } QTextLayout iconTextLayout(text, option.font); int wt = layoutText(&iconTextLayout, qMax(3 * layoutSize.width(), 8 * fm.height())); int ht = iconTextLayout.boundingRect().height(); int width, height; if (text.isEmpty()) { height = layoutSize.height(); } else { height = layoutSize.height() + ht + 10; } width = qMax(wt, layoutSize.width()) + gap; return QSize(width, height); }
void TextTools::setHalign(QAction* a) { QTextBlockFormat bformat; Qt::Alignment qa = bformat.alignment() & ~Qt::AlignHorizontal_Mask; switch(a->data().toInt()) { case ALIGN_HCENTER: qa |= Qt::AlignHCenter; break; case ALIGN_RIGHT: qa |= Qt::AlignRight; break; case ALIGN_LEFT: qa |= Qt::AlignLeft; break; } bformat.setAlignment(qa); cursor()->mergeBlockFormat(bformat); _textElement->setAlign((_textElement->align() & ~ ALIGN_HMASK) | Align(a->data().toInt())); updateTools(); layoutText(); }
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return QSize(0, 0); } const QString text = index.model()->data(index, Qt::DisplayRole).toString(); const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>(); const QPixmap pixmap = icon.pixmap(iconSize, iconSize); QFontMetrics fm = option.fontMetrics; int gap = fm.height(); int wp = pixmap.width(); int hp = pixmap.height(); if (hp == 0) { /** * No pixmap loaded yet, we'll use the default icon size in this case. */ hp = iconSize; wp = iconSize; } QTextLayout iconTextLayout(text, option.font); int wt = layoutText(&iconTextLayout, qMax(3 * wp, 8 * fm.height())); int ht = iconTextLayout.boundingRect().height(); int width, height; if (text.isEmpty()) { height = hp; } else { height = hp + ht + 10; } width = qMax(wt, wp) + gap; return QSize(width, height); }
void FontSupport::drawText(const WFont& font, const WRectF& rect, const WTransform& transform, Bitmap& bitmap, WFlags<AlignmentFlag> flags, const WString& text) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; PangoMatrix matrix; matrix.xx = transform.m11(); matrix.xy = transform.m21(); matrix.yx = transform.m12(); matrix.yy = transform.m22(); matrix.x0 = transform.dx(); matrix.y0 = transform.dy(); std::string utf8 = text.toUTF8(); std::vector<PangoGlyphString *> glyphs; int width; pango_context_set_matrix(context_, &matrix); /* * Oh my god, somebody explain me why we need to do this... */ WFont f = font; f.setSize(font.sizeLength().toPixels() / pango_matrix_get_font_scale_factor(&matrix)); GList *items = layoutText(f, utf8, glyphs, width); pango_context_set_matrix(context_, nullptr); AlignmentFlag hAlign = flags & AlignHorizontalMask; /* FIXME handle bidi ! */ double x; switch (hAlign) { case AlignmentFlag::Left: x = rect.left(); break; case AlignmentFlag::Right: x = rect.right() - pangoUnitsToDouble(width); break; case AlignmentFlag::Center: x = rect.center().x() - pangoUnitsToDouble(width/2); break; default: x = 0; } AlignmentFlag vAlign = flags & AlignVerticalMask; PangoFont *pangoFont = matchFont(font).pangoFont(); PangoFontMetrics *metrics = pango_font_get_metrics(pangoFont, nullptr); double ascent = pangoUnitsToDouble(pango_font_metrics_get_ascent(metrics)); double descent = pangoUnitsToDouble(pango_font_metrics_get_descent(metrics)); pango_font_metrics_unref(metrics); double baseline = ascent; double height = ascent + descent; double y; switch (vAlign) { case AlignmentFlag::Top: y = rect.top() + baseline; break; case AlignmentFlag::Middle: y = rect.center().y() - height / 2 + baseline; break; case AlignmentFlag::Bottom: y = rect.bottom() - height + baseline; break; default: y = 0; } FT_Bitmap bmp; bmp.buffer = bitmap.buffer(); bmp.width = bitmap.width(); bmp.rows = bitmap.height(); bmp.pitch = bitmap.pitch(); bmp.pixel_mode = FT_PIXEL_MODE_GRAY; bmp.num_grays = 16; // ??? GList *elem; unsigned i = 0; for (elem = items; elem; elem = elem->next) { PangoItem *item = (PangoItem *)elem->data; PangoAnalysis *analysis = &item->analysis; PangoGlyphString *gl = glyphs[i++]; pango_ft2_render_transformed(&bmp, &matrix, analysis->font, gl, pangoUnitsFromDouble(x), pangoUnitsFromDouble(y)); x += pangoUnitsToDouble(pango_glyph_string_get_width(gl)); pango_glyph_string_free(gl); pango_item_free(item); } g_list_free(items); }
void TextTools::setValign(QAction* a) { _textElement->setAlign((_textElement->align() & ~ALIGN_VMASK) | Align(a->data().toInt())); updateTools(); layoutText(); }
void TextTools::setHalign(QAction* a) { _textElement->setCurHalign(a->data().toInt()); updateTools(); layoutText(); }
void TextTools::updateText() { if (!text) return; layoutText(); }
void QmlConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); painter->save(); // Set Colors QColor textColor; QIcon taskIcon; ConsoleItem::ItemType type = (ConsoleItem::ItemType)index.data( ConsoleItem::TypeRole).toInt(); switch (type) { case ConsoleItem::DebugType: textColor = QColor(CONSOLE_LOG_TEXT_COLOR); taskIcon = m_logIcon; break; case ConsoleItem::WarningType: textColor = QColor(CONSOLE_WARNING_TEXT_COLOR); taskIcon = m_warningIcon; break; case ConsoleItem::ErrorType: textColor = QColor(CONSOLE_ERROR_TEXT_COLOR); taskIcon = m_errorIcon; break; case ConsoleItem::InputType: textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR); taskIcon = m_prompt; break; default: textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR); break; } // Paint background QColor backgroundColor = drawBackground(painter, opt.rect, index, bool(opt.state & QStyle::State_Selected)); // Calculate positions const QTreeView *view = qobject_cast<const QTreeView *>(opt.widget); int level = 0; QModelIndex idx(index); while (idx.parent() != QModelIndex()) { idx = idx.parent(); level++; } int width = view->width() - level * view->indentation() - view->verticalScrollBar()->width(); bool showTypeIcon = index.parent() == QModelIndex(); bool showExpandableIcon = type == ConsoleItem::DefaultType; QRect rect(opt.rect.x(), opt.rect.top(), width, opt.rect.height()); ConsoleItemPositions positions(rect, opt.font, showTypeIcon, showExpandableIcon); // Paint TaskIconArea: if (showTypeIcon) painter->drawPixmap(positions.adjustedLeft(), positions.adjustedTop(), taskIcon.pixmap(positions.typeIconWidth(), positions.typeIconHeight())); // Set Text Color painter->setPen(textColor); // Paint TextArea: // Layout the description QString str = index.data(Qt::DisplayRole).toString(); bool showFileLineInfo = true; // show complete text if selected if (view->selectionModel()->currentIndex() == index) { QTextLayout tl(str, opt.font); layoutText(tl, positions.textAreaWidth(), &showFileLineInfo); tl.draw(painter, QPoint(positions.textAreaLeft(), positions.adjustedTop())); } else { QFontMetrics fm(opt.font); painter->drawText(positions.textArea(), fm.elidedText(str, Qt::ElideRight, positions.textAreaWidth())); } // skip if area is editable if (showExpandableIcon) { // Paint ExpandableIconArea: QIcon expandCollapseIcon; if (index.model()->rowCount(index) || index.model()->canFetchMore(index)) { if (view->isExpanded(index)) expandCollapseIcon = m_collapseIcon; else expandCollapseIcon = m_expandIcon; } painter->drawPixmap(positions.expandCollapseIconLeft(), positions.adjustedTop(), expandCollapseIcon.pixmap(positions.expandCollapseIconWidth(), positions.expandCollapseIconHeight())); } if (showFileLineInfo) { // Check for file info QString file = index.data(ConsoleItem::FileRole).toString(); const QUrl fileUrl = QUrl(file); if (fileUrl.isLocalFile()) file = fileUrl.toLocalFile(); if (!file.isEmpty()) { QFontMetrics fm(option.font); // Paint FileArea const int pos = file.lastIndexOf(QLatin1Char('/')); if (pos != -1) file = file.mid(pos +1); const int realFileWidth = fm.width(file); painter->setClipRect(positions.fileArea()); painter->drawText(positions.fileAreaLeft(), positions.adjustedTop() + fm.ascent(), file); if (realFileWidth > positions.fileAreaWidth()) { // draw a gradient to mask the text int gradientStart = positions.fileAreaLeft() - 1; QLinearGradient lg(gradientStart + ELLIPSIS_GRADIENT_WIDTH, 0, gradientStart, 0); lg.setColorAt(0, Qt::transparent); lg.setColorAt(1, backgroundColor); painter->fillRect(gradientStart, positions.adjustedTop(), ELLIPSIS_GRADIENT_WIDTH, positions.lineHeight(), lg); } // Paint LineArea QString lineText = index.data(ConsoleItem::LineRole).toString(); painter->setClipRect(positions.lineArea()); const int realLineWidth = fm.width(lineText); painter->drawText(positions.lineAreaRight() - realLineWidth, positions.adjustedTop() + fm.ascent(), lineText); } } painter->setClipRect(opt.rect); painter->restore(); }
void Font::drawText(std::vector<GraphicsBase> * vGraphicsBase, const char* text, float r, float g, float b, float a, TextLayoutParameters *layout, bool hasSample, float minx, float miny, TextLayout &l) { size_t size = utf8_to_wchar(text, strlen(text), NULL, 0, 0); if (size == 0) { return; } if (!(l.styleFlags&TEXTSTYLEFLAG_SKIPLAYOUT)) l = layoutText(text, layout); int gfx = vGraphicsBase->size(); vGraphicsBase->resize(gfx+1); GraphicsBase *graphicsBase = &((*vGraphicsBase)[gfx]); graphicsBase->data = data_; if (fontInfo_.isSetTextColorAvailable) { if (l.styleFlags&TEXTSTYLEFLAG_COLOR) { graphicsBase->colors.resize(size * 16); graphicsBase->colors.Update(); } else graphicsBase->setColor(r, g, b, a); } else { graphicsBase->setColor(1, 1, 1, 1); l.styleFlags&=(~TEXTSTYLEFLAG_COLOR); } graphicsBase->vertices.resize(size * 4); graphicsBase->texcoords.resize(size * 4); graphicsBase->indices.resize(size * 6); graphicsBase->vertices.Update(); graphicsBase->texcoords.Update(); graphicsBase->indices.Update(); size_t gi=0; for (int pn = 0; pn < l.parts.size(); pn++) { ChunkLayout c = l.parts[pn]; unsigned char rgba[4]; if (l.styleFlags&TEXTSTYLEFLAG_COLOR) { float ca=(c.styleFlags&TEXTSTYLEFLAG_COLOR)?(1.0/255)*((c.color>>24)&0xFF):a; rgba[0]=(unsigned char)(ca*((c.styleFlags&TEXTSTYLEFLAG_COLOR)?(c.color>>16)&0xFF:r*255)); rgba[1]=(unsigned char)(ca*((c.styleFlags&TEXTSTYLEFLAG_COLOR)?(c.color>>8)&0xFF:g*255)); rgba[2]=(unsigned char)(ca*((c.styleFlags&TEXTSTYLEFLAG_COLOR)?(c.color>>0)&0xFF:b*255)); rgba[3]=(unsigned char)(ca*255); } std::basic_string<wchar32_t> wtext; size_t wsize = utf8_to_wchar(c.text.c_str(), c.text.size(), NULL, 0, 0); wtext.resize(wsize); utf8_to_wchar(c.text.c_str(), c.text.size(), &wtext[0], wsize, 0); float x = (c.dx-minx)/sizescalex_, y = (c.dy-miny)/sizescaley_; /* if (hasSample) { std::map<wchar32_t, TextureGlyph>::const_iterator iter = fontInfo_.textureGlyphs.find(text[0]); const TextureGlyph &textureGlyph = iter->second; x = c.dx/sizescalex_-textureGlyph.left; //FIXME: is this needed ? }*/ wchar32_t prev = 0; for (int i = 0; i < wsize; ++i) { std::map<wchar32_t, TextureGlyph>::const_iterator iter = fontInfo_.textureGlyphs.find(wtext[i]); if (iter == fontInfo_.textureGlyphs.end()) continue; const TextureGlyph &textureGlyph = iter->second; int width = textureGlyph.width; int height = textureGlyph.height; int left = textureGlyph.left; int top = textureGlyph.top; x += kerning(prev, wtext[i]) >> 6; prev = wtext[i]; float x0 = x + left; float y0 = y - top; float x1 = x + left + width; float y1 = y - top + height; graphicsBase->vertices[gi * 4 + 0] = Point2f(sizescalex_ * x0, sizescaley_ * y0); graphicsBase->vertices[gi * 4 + 1] = Point2f(sizescalex_ * x1, sizescaley_ * y0); graphicsBase->vertices[gi * 4 + 2] = Point2f(sizescalex_ * x1, sizescaley_ * y1); graphicsBase->vertices[gi * 4 + 3] = Point2f(sizescalex_ * x0, sizescaley_ * y1); float u0 = (float) textureGlyph.x / (float) data_->exwidth; float v0 = (float) textureGlyph.y / (float) data_->exheight; float u1 = (float) (textureGlyph.x + width) / (float) data_->exwidth; float v1 = (float) (textureGlyph.y + height) / (float) data_->exheight; u0 *= uvscalex_; v0 *= uvscaley_; u1 *= uvscalex_; v1 *= uvscaley_; graphicsBase->texcoords[gi * 4 + 0] = Point2f(u0, v0); graphicsBase->texcoords[gi * 4 + 1] = Point2f(u1, v0); graphicsBase->texcoords[gi * 4 + 2] = Point2f(u1, v1); graphicsBase->texcoords[gi * 4 + 3] = Point2f(u0, v1); if (l.styleFlags&TEXTSTYLEFLAG_COLOR) { for (int v=0;v<16;v+=4) { graphicsBase->colors[gi * 16 + 0 + v] = rgba[0]; graphicsBase->colors[gi * 16 + 1 + v] = rgba[1]; graphicsBase->colors[gi * 16 + 2 + v] = rgba[2]; graphicsBase->colors[gi * 16 + 3 + v] = rgba[3]; } } graphicsBase->indices[gi * 6 + 0] = gi * 4 + 0; graphicsBase->indices[gi * 6 + 1] = gi * 4 + 1; graphicsBase->indices[gi * 6 + 2] = gi * 4 + 2; graphicsBase->indices[gi * 6 + 3] = gi * 4 + 0; graphicsBase->indices[gi * 6 + 4] = gi * 4 + 2; graphicsBase->indices[gi * 6 + 5] = gi * 4 + 3; x += textureGlyph.advancex >> 6; x += layout->letterSpacing / sizescalex_; gi++; } }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return; } bool mouseOver=option.state&QStyle::State_MouseOver; bool selected=option.state&QStyle::State_Selected; if (standard) { if (GtkStyle::isActive()) { bool mouseOver=option.state&QStyle::State_MouseOver; QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); if (!underMouse) { mouseOver=false; } if (mouseOver) { opt.showDecorationSelected=true; GtkStyle::drawSelection(option, painter, selected ? 0.75 : 0.25); opt.showDecorationSelected=false; opt.state&=~(QStyle::State_MouseOver|QStyle::State_Selected); opt.backgroundBrush=QBrush(Qt::transparent); if (selected) { opt.palette.setBrush(QPalette::Text, opt.palette.highlightedText()); } } QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); } else { QStyledItemDelegate::paint(painter, option, index); } return; } bool gtk=mouseOver && GtkStyle::isActive(); bool drawBgnd=true; if (!underMouse) { if (mouseOver && !selected) { drawBgnd=false; } mouseOver=false; } const QString text = index.model()->data(index, Qt::DisplayRole).toString(); const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>(); const QPixmap pixmap = icon.pixmap(iconSize, iconSize); QFontMetrics fm = painter->fontMetrics(); #if QT_VERSION >= 0x050100 QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); #else QSize layoutSize = pixmap.size(); #endif QTextLayout iconTextLayout(text, option.font); QTextOption textOption(Qt::AlignHCenter); iconTextLayout.setTextOption(textOption); int maxWidth = qMax(3 * layoutSize.width(), 8 * fm.height()); layoutText(&iconTextLayout, maxWidth); QPen pen = painter->pen(); QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { cg = QPalette::Inactive; } QStyleOptionViewItemV4 opt(option); opt.showDecorationSelected = true; QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); if (drawBgnd) { if (mouseOver && gtk) { GtkStyle::drawSelection(opt, painter, selected ? 0.75 : 0.25); } else { style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); } } #ifndef Q_OS_WIN if (selected) { painter->setPen(option.palette.color(cg, QPalette::HighlightedText)); } else #endif { painter->setPen(option.palette.color(cg, QPalette::Text)); } painter->drawPixmap(option.rect.x() + (option.rect.width()/2)-(layoutSize.width()/2), option.rect.y() + 5, pixmap); if (!text.isEmpty()) { iconTextLayout.draw(painter, QPoint(option.rect.x() + (option.rect.width()/2)-(maxWidth/2), option.rect.y() + layoutSize.height()+7)); } painter->setPen(pen); drawFocus(painter, option, option.rect); }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return; } bool mouseOver = option.state & QStyle::State_MouseOver; bool gtk = mouseOver && qApp->style()->inherits("QGtkStyle"); bool selected = option.state & QStyle::State_Selected; bool drawBgnd = true; if (!underMouse) { if (mouseOver && !selected) { drawBgnd = false; } mouseOver = false; } const QString text = index.model()->data(index, Qt::DisplayRole).toString(); const QIcon icon = index.model()->data(index, Qt::DecorationRole).value<QIcon>(); const QPixmap pixmap = icon.pixmap(iconSize, iconSize); QFontMetrics fm = painter->fontMetrics(); int wp = pixmap.width(); int hp = pixmap.height(); QTextLayout iconTextLayout(text, option.font); QTextOption textOption(Qt::AlignHCenter); iconTextLayout.setTextOption(textOption); int maxWidth = qMax(3 * wp, 8 * fm.height()); layoutText(&iconTextLayout, maxWidth); QPen pen = painter->pen(); QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { cg = QPalette::Inactive; } QStyleOptionViewItem opt(option); opt.showDecorationSelected = true; QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); if (drawBgnd) { if (mouseOver && gtk) { painter->save(); opt.state |= QStyle::State_Selected; painter->setOpacity(selected ? 0.75 : 0.25); } style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); if (mouseOver && gtk) { painter->restore(); } } if (selected) { painter->setPen(option.palette.color(cg, QPalette::HighlightedText)); } else { painter->setPen(option.palette.color(cg, QPalette::Text)); } painter->drawPixmap(option.rect.x() + (option.rect.width() / 2) - (wp / 2), option.rect.y() + 5, pixmap); if (!text.isEmpty()) { iconTextLayout.draw(painter, QPoint(option.rect.x() + (option.rect.width() / 2) - (maxWidth / 2), option.rect.y() + hp + 7)); } painter->setPen(pen); drawFocus(painter, option, option.rect); }
void StatusEventItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QItemDelegate::paint(painter, option, index); painter->save(); if (option.state & QStyle::State_Selected) painter->setPen(option.palette.highlightedText().color()); QPixmap icon = index.data(StatusEventItem::IconRole).value<QPixmap>(); QTime tstamp = index.data(StatusEventItem::TimestampRole).toTime(); QString title = index.data(StatusEventItem::TitleRole).toString(); QString text = index.data(StatusEventItem::DescriptionRole).toString(); QFont font = option.font; QFontMetrics fm = option.fontMetrics; /* XXX: Handle right-to-left layouts here. */ QRect iconRect(option.rect.x(), option.rect.y(), qMax(fm.width(tstamp.toString()), icon.width()) + 16, option.rect.height()); QRect textRect(iconRect.topRight(), option.rect.bottomRight()); // Draw the status icon QPoint center = iconRect.center(); int x = center.x() - qRound(icon.width() / 2.0); int y = center.y() - qRound((icon.height() + fm.lineSpacing()) / 2.0); painter->drawPixmap(x, y, icon); // Draw the timestamp text underneath the status icon x = iconRect.x(); y = y + icon.height(); painter->drawText(x, y, iconRect.width(), fm.lineSpacing(), Qt::AlignCenter, tstamp.toString()); // Draw the event's title in a bold font. If the current item has an // associated help URL, draw the little "?" icon to the right of the // title text font.setBold(true); painter->setFont(font); if (! index.data(StatusEventItem::HelpUrlRole).isNull()) { // Draw the little "?" icon in the corner of the list item and // account for it when eliding the title title = fm.elidedText(title, Qt::ElideRight, textRect.width() - _helpIcon.width() - 24); x = textRect.topRight().x() - _helpIcon.width() - 8; y = textRect.y() + 8; painter->drawPixmap(x, y, _helpIcon); } else { title = fm.elidedText(title, Qt::ElideRight, textRect.width() - 16); } painter->drawText(textRect.x(), textRect.y() + 8, textRect.width(), fm.lineSpacing(), Qt::AlignVCenter | Qt::AlignLeft, title); // Draw the rest of the event text, up to a maximum of 2 lines for // unselected items or 5 lines for selected items. Any extra text will // be elided. font.setBold(false); painter->setFont(font); if (option.state & QStyle::State_Selected) text = layoutText(text, font, textRect.width(), 6).join("\n"); else text = layoutText(text, font, textRect.width(), 3).join("\n"); x = textRect.x(); y = textRect.y() + 8 + fm.leading() + fm.lineSpacing(); painter->drawText(x, y, textRect.width(), textRect.height() - (y - textRect.y()), Qt::AlignTop | Qt::AlignLeft, text); painter->restore(); }
WTextItem FontSupport::measureText(const WFont& font, const WString& text, double maxWidth, bool wordWrap) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; /* * Note: accurate measuring on a bitmap requires that the transformation * is applied, because hinting may push chars to boundaries e.g. when * rotated (or scaled too?) */ std::string utf8 = text.toUTF8(); const char *s = utf8.c_str(); if (wordWrap) { int utflen = g_utf8_strlen(s, -1); PangoLogAttr *attrs = new PangoLogAttr[utflen + 1]; PangoLanguage *language = pango_language_from_string("en-US"); pango_get_log_attrs(s, utf8.length(), -1, language, attrs, utflen + 1); double w = 0, nextW = -1; int current = 0; int measured = 0; int end = 0; bool maxWidthReached = false; for (int i = 0; i < utflen + 1; ++i) { if (i == utflen || attrs[i].is_line_break) { int cend = g_utf8_offset_to_pointer(s, end) - s; WTextItem ti = measureText(font, WString::fromUTF8(utf8.substr(measured, cend - measured)), -1, false); if (isEpsilonMore(w + ti.width(), maxWidth)) { nextW = ti.width(); maxWidthReached = true; break; } else { measured = cend; current = g_utf8_offset_to_pointer(s, i) - s; w += ti.width(); if (i == utflen) { w += measureText(font, WString::fromUTF8(utf8.substr(measured)), -1, false).width(); measured = utf8.length(); } } } if (!attrs[i].is_white) end = i + 1; } delete[] attrs; if (maxWidthReached) { return WTextItem(WString::fromUTF8(utf8.substr(0, current)), w, nextW); } else { /* * For some reason, the sum of the individual widths is a bit less * (for longer stretches of text), so we re-measure it ! */ w = measureText(font, WString::fromUTF8(utf8.substr(0, measured)), -1, false).width(); return WTextItem(text, w); } } else { std::vector<PangoGlyphString *> glyphs; int width; GList *items = layoutText(font, utf8, glyphs, width); double w = pangoUnitsToDouble(width); for (unsigned i = 0; i < glyphs.size(); ++i) pango_glyph_string_free(glyphs[i]); g_list_foreach(items, (GFunc) pango_item_free, nullptr); g_list_free(items); return WTextItem(text, w); } }
void FontSupport::drawText(const WFont& font, const WRectF& rect, WFlags<AlignmentFlag> flags, const WString& text) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; std::string utf8 = text.toUTF8(); std::vector<PangoGlyphString *> glyphs; int width; GList *items = layoutText(font, utf8, glyphs, width); AlignmentFlag hAlign = flags & AlignHorizontalMask; AlignmentFlag vAlign = flags & AlignVerticalMask; /* FIXME handle bidi ! */ double x; switch (hAlign) { case AlignmentFlag::Left: x = rect.left(); break; case AlignmentFlag::Right: x = rect.right() - pangoUnitsToDouble(width); break; case AlignmentFlag::Center: x = rect.center().x() - pangoUnitsToDouble(width/2); break; default: x = 0; } unsigned i = 0; for (GList *elem = items; elem; elem = elem->next) { PangoItem *item = (PangoItem *)elem->data; PangoAnalysis *analysis = &item->analysis; PangoGlyphString *gl = glyphs[i++]; currentFont_ = analysis->font; /* * Note, we are actually ignoring the selected glyphs here, which * is a pitty and possibly wrong if the device does not make the * same selection ! */ WString s = WString::fromUTF8(utf8.substr(item->offset, item->length)); device_->drawText(WRectF(x, rect.y(), 1000, rect.height()), AlignmentFlag::Left | vAlign, TextFlag::SingleLine, s, nullptr); WTextItem textItem = device_->measureText(s, -1, false); x += textItem.width(); pango_item_free(item); pango_glyph_string_free(gl); } g_list_free(items); currentFont_ = nullptr; }
void YTDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); bool white = false; if(index.data(YTDialog::Clicked).toBool()) { painter->drawPixmap(option.rect.adjusted(0,0,0, -1), hoverBackground ); white = true; } else { if(index.row() % 2 == 0) { painter->fillRect(option.rect, QColor("#f0f6ff")); } else { painter->fillRect(option.rect, Qt::white); } } SingleVideoItem* item = qVariantValue<SingleVideoItem*>(index.data()); QSize sz = option.rect.size(); --sz.rheight(); painter->translate(option.rect.x() , option.rect.y()); painter->drawPixmap(0, 0, PIXWIDTH, sz.height(), item->pix ); if(index.data(YTDialog::Clicked).toBool()) { painter->drawPixmap(0, 0, PIXWIDTH, sz.height(), pixBorderOverlayHover); QPoint pop = QRect(0,0,PIXWIDTH, sz.height()).center() - playOverlay.rect().center(); painter->drawPixmap(pop, playOverlay); } else { painter->drawPixmap(0, 0, PIXWIDTH, sz.height(), index.row() %2 == 0 ? pixBorderOverlay1 : pixBorderOverlay2 ); } QFont font = option.font; font.setPixelSize(11); QFontMetrics fm(font); // total time QString totalTime = timeString(item->totalTime); QRect ttRect = fm.boundingRect(totalTime); ttRect.adjust(-2 , 0, 4, 2); ttRect.moveBottomRight(QPoint(PIXWIDTH -9, sz.height() -11 )); painter->setPen(Qt::white); painter->setFont(font); painter->setOpacity(0.7); painter->drawPixmap(ttRect, durationBackground); ttRect.adjust(1, 1, 1, 0); painter->drawText(ttRect, Qt::AlignHCenter | Qt::AlignTop, totalTime); painter->setOpacity(1); // Header font.setPixelSize(14); fm = QFontMetrics(font); painter->setFont(font); painter->setPen(cr(Qt::black, white)); QRect headerRect = fm.boundingRect(item->header); headerRect = QRect( PIXWIDTH + 4 , 7, sz.width() - PIXWIDTH - 8, headerRect.height() + 4 ); painter->drawText(headerRect, Qt::AlignTop | Qt::AlignLeft | Qt::TextSingleLine, fm.elidedText(item->header, Qt::ElideRight, headerRect.width()), &headerRect ); // Footer font.setPixelSize(11); fm = QFontMetrics(font); painter->setPen(cr(QColor("#636363"), white)); painter->setFont(font); QRect footerRect(PIXWIDTH + 4, ttRect.top(), sz.width() - PIXWIDTH - 8, ttRect.height()); painter->drawText(footerRect, Qt::AlignVCenter | Qt::AlignLeft, item->date.toString("yyyy-MM-dd")); painter->drawText(footerRect, Qt::AlignVCenter | Qt::AlignRight, tr("%L1 views").arg(item->views)); //Description font.setPixelSize(12); painter->setFont(font); QRect descRect( PIXWIDTH + 4, headerRect.bottom() + 7, sz.width() - PIXWIDTH - 8, ttRect.top() - headerRect.bottom() - 7); QTextLayout textLayout(item->desc, font); layoutText(textLayout, item->desc, descRect.size()); textLayout.draw(painter, descRect.topLeft()); QPen sepLinePen(QColor("#e3e3e3")); painter->setPen(sepLinePen); painter->drawLine(0, 90, sz.width(), 90); painter->restore(); }