void tst_QRawFont::textLayout() { QFontDatabase fontDatabase; int id = fontDatabase.addApplicationFont(SRCDIR "testfont.ttf"); QVERIFY(id >= 0); QString familyName = QString::fromLatin1("QtBidiTestFont"); QFont font(familyName); font.setPixelSize(18.0); QCOMPARE(QFontInfo(font).family(), familyName); QTextLayout layout(QLatin1String("Foobar")); layout.setFont(font); layout.beginLayout(); layout.createLine(); layout.endLayout(); QList<QGlyphRun> glyphRuns = layout.glyphRuns(); QCOMPARE(glyphRuns.size(), 1); QGlyphRun glyphs = glyphRuns.at(0); QRawFont rawFont = glyphs.rawFont(); QVERIFY(rawFont.isValid()); QCOMPARE(rawFont.familyName(), familyName); QCOMPARE(rawFont.pixelSize(), 18.0); QVector<quint32> expectedGlyphIndices; expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices); QVERIFY(fontDatabase.removeApplicationFont(id)); }
void QSGTextNode::addTextLayout(const QPointF &position, QTextLayout *textLayout, const QColor &color, QSGText::TextStyle style, const QColor &styleColor) { QList<QGlyphRun> glyphsList(textLayout->glyphRuns()); QSGGlyphNode *prevNode = 0; QFont font = textLayout->font(); qreal underlinePosition, ascent, lineThickness; int decorations = NoDecoration; decorations |= (font.underline() ? Underline : 0); decorations |= (font.overline() ? Overline : 0); decorations |= (font.strikeOut() ? StrikeOut : 0); underlinePosition = ascent = lineThickness = 0; for (int i=0; i<glyphsList.size(); ++i) { QGlyphRun glyphs = glyphsList.at(i); QRawFont rawfont = glyphs.rawFont(); prevNode = addGlyphs(position + QPointF(0, rawfont.ascent()), glyphs, color, style, styleColor); if (decorations) { qreal rawAscent = rawfont.ascent(); if (decorations & Underline) { ascent = qMax(ascent, rawAscent); qreal pos = rawfont.underlinePosition(); if (pos > underlinePosition) { underlinePosition = pos; // take line thickness from the rawfont with maximum underline // position in this case lineThickness = rawfont.lineThickness(); } } else { // otherwise it's strike out or overline, we take line thickness // from the rawfont with maximum ascent if (rawAscent > ascent) { ascent = rawAscent; lineThickness = rawfont.lineThickness(); } } } } if (decorations) { addTextDecorations(Decoration(decorations), position + QPointF(0, ascent), color, textLayout->boundingRect().width(), lineThickness, underlinePosition, ascent); } }
void tst_QRawFont::unsupportedWritingSystem() { QFETCH(QFont::HintingPreference, hintingPreference); QFontDatabase fontDatabase; int id = fontDatabase.addApplicationFont(QLatin1String(SRCDIR "testfont.ttf")); QFont font("QtBidiTestFont"); font.setHintingPreference(hintingPreference); font.setPixelSize(12.0); QRawFont rawFont = QRawFont::fromFont(font, QFontDatabase::Any); QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont")); QCOMPARE(rawFont.pixelSize(), 12.0); rawFont = QRawFont::fromFont(font, QFontDatabase::Hebrew); QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont")); QCOMPARE(rawFont.pixelSize(), 12.0); QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic); QTextLayout layout; layout.setFont(font); layout.setText(arabicText); layout.beginLayout(); layout.createLine(); layout.endLayout(); QList<QGlyphRun> glyphRuns = layout.glyphRuns(); QCOMPARE(glyphRuns.size(), 1); QGlyphRun glyphs = glyphRuns.at(0); QRawFont layoutFont = glyphs.rawFont(); QVERIFY(layoutFont.familyName() != QString::fromLatin1("QtBidiTestFont")); QCOMPARE(layoutFont.pixelSize(), 12.0); rawFont = QRawFont::fromFont(font, QFontDatabase::Arabic); QCOMPARE(rawFont.familyName(), layoutFont.familyName()); QCOMPARE(rawFont.pixelSize(), 12.0); fontDatabase.removeApplicationFont(id); }
QT_BEGIN_NAMESPACE void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState, QQuickTextNode::Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position) { QRectF searchRect = glyphRun.boundingRect(); searchRect.translate(position); if (qFuzzyIsNull(searchRect.width()) || qFuzzyIsNull(searchRect.height())) return; decorations |= (glyphRun.underline() ? QQuickTextNode::Underline : QQuickTextNode::NoDecoration); decorations |= (glyphRun.overline() ? QQuickTextNode::Overline : QQuickTextNode::NoDecoration); decorations |= (glyphRun.strikeOut() ? QQuickTextNode::StrikeOut : QQuickTextNode::NoDecoration); decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration); qreal ascent = glyphRun.rawFont().ascent(); insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations, textColor, backgroundColor, position, ascent)); }
void setLatinText(const QString &text, const QFont &font, const QColor &color) { QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin); if (raw_font != m_raw_font) { m_raw_font = raw_font; m_positions.clear(); } if (m_positions.size() < text.size()) { qreal x_pos = 0; qreal max_char_width = raw_font.averageCharWidth(); qreal ascent = raw_font.ascent(); if (m_positions.size()) x_pos = m_positions.last().x() + max_char_width; int to_add = text.size() - m_positions.size(); for (int i = 0; i < to_add; i++) { m_positions << QPointF(x_pos, ascent); x_pos += max_char_width; } } deleteContent(); QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext(); QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr, false); node->setOwnerElement(m_owner); node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern); node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern); node->setStyle(QQuickText::Normal); node->setColor(color); QGlyphRun glyphrun; glyphrun.setRawFont(raw_font); glyphrun.setGlyphIndexes(raw_font.glyphIndexesForString(text)); glyphrun.setPositions(m_positions); node->setGlyphs(QPointF(0, raw_font.ascent()), glyphrun); node->update(); appendChildNode(node); }
void tst_QRawFont::rawFontSetPixelSize() { QFETCH(QFont::HintingPreference, hintingPreference); QTextLayout layout("Foobar"); QFont font = layout.font(); font.setHintingPreference(hintingPreference); font.setPixelSize(12); layout.setFont(font); layout.beginLayout(); layout.createLine(); layout.endLayout(); QGlyphRun glyphs = layout.glyphRuns().at(0); QRawFont rawFont = glyphs.rawFont(); QCOMPARE(rawFont.pixelSize(), 12.0); rawFont.setPixelSize(24); QCOMPARE(rawFont.pixelSize(), 24.0); }
void QSGDefaultGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs) { if (m_material != 0) delete m_material; QRawFont font = glyphs.rawFont(); m_material = new QSGTextMaskMaterial(font); m_material->setColor(m_color); QRectF boundingRect; m_material->populate(position, glyphs.glyphIndexes(), glyphs.positions(), geometry(), &boundingRect, &m_baseLine); setMaterial(m_material); setBoundingRect(boundingRect); markDirty(DirtyGeometry); #ifdef QML_RUNTIME_TESTING description = QLatin1String("glyphs"); #endif }
void QSGTextNode::addTextBlock(const QPointF &position, QTextDocument *textDocument, const QTextBlock &block, const QColor &overrideColor, QSGText::TextStyle style, const QColor &styleColor) { if (!block.isValid()) return; QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft(); QTextBlock::iterator it = block.begin(); while (!it.atEnd()) { QTextFragment fragment = it.fragment(); if (!fragment.text().isEmpty()) { QTextCharFormat charFormat = fragment.charFormat(); QColor color = overrideColor.isValid() ? overrideColor : charFormat.foreground().color(); QList<QGlyphRun> glyphsList = fragment.glyphRuns(); for (int i=0; i<glyphsList.size(); ++i) { QGlyphRun glyphs = glyphsList.at(i); QRawFont font = glyphs.rawFont(); QSGGlyphNode *glyphNode = addGlyphs(position + blockPosition + QPointF(0, font.ascent()), glyphs, color, style, styleColor); int decorations = (glyphs.overline() ? Overline : 0) | (glyphs.strikeOut() ? StrikeOut : 0) | (glyphs.underline() ? Underline : 0); if (decorations) { QPointF baseLine = glyphNode->baseLine(); qreal width = glyphNode->boundingRect().width(); addTextDecorations(Decoration(decorations), baseLine, color, width, font.lineThickness(), font.underlinePosition(), font.ascent()); } } } ++it; } }
void QQuickTextNodeEngine::addToSceneGraph(QQuickTextNode *parentNode, QQuickText::TextStyle style, const QColor &styleColor) { if (m_currentLine.isValid()) processCurrentLine(); for (int i=0; i<m_backgrounds.size(); ++i) { const QRectF &rect = m_backgrounds.at(i).first; const QColor &color = m_backgrounds.at(i).second; parentNode->appendChildNode(new QSGSimpleRectNode(rect, color)); } // First, prepend all selection rectangles to the tree for (int i=0; i<m_selectionRects.size(); ++i) { const QRectF &rect = m_selectionRects.at(i); parentNode->appendChildNode(new QSGSimpleRectNode(rect, m_selectionColor)); } // Finally, add decorations for each node to the tree. for (int i=0; i<m_lines.size(); ++i) { const TextDecoration &textDecoration = m_lines.at(i); QColor color = textDecoration.selectionState == Selected ? m_selectedTextColor : textDecoration.color; parentNode->appendChildNode(new QSGSimpleRectNode(textDecoration.rect, color)); } // Then, go through all the nodes for all lines and combine all QGlyphRuns with a common // font, selection state and clip node. typedef QPair<QFontEngine *, QPair<QQuickDefaultClipNode *, QPair<QRgb, int> > > KeyType; QHash<KeyType, BinaryTreeNode *> map; QList<BinaryTreeNode *> nodes; for (int i = 0; i < m_processedNodes.size(); ++i) { BinaryTreeNode *node = m_processedNodes.data() + i; if (node->image.isNull()) { QGlyphRun glyphRun = node->glyphRun; QRawFont rawFont = glyphRun.rawFont(); QRawFontPrivate *rawFontD = QRawFontPrivate::get(rawFont); QFontEngine *fontEngine = rawFontD->fontEngine; KeyType key(qMakePair(fontEngine, qMakePair(node->clipNode, qMakePair(node->color.rgba(), int(node->selectionState))))); BinaryTreeNode *otherNode = map.value(key, 0); if (otherNode != 0) { QGlyphRun &otherGlyphRun = otherNode->glyphRun; QVector<quint32> otherGlyphIndexes = otherGlyphRun.glyphIndexes(); QVector<QPointF> otherGlyphPositions = otherGlyphRun.positions(); otherGlyphIndexes += glyphRun.glyphIndexes(); QVector<QPointF> glyphPositions = glyphRun.positions(); otherGlyphPositions.reserve(otherGlyphPositions.size() + glyphPositions.size()); for (int j = 0; j < glyphPositions.size(); ++j) { otherGlyphPositions += glyphPositions.at(j) + (node->position - otherNode->position); } otherGlyphRun.setGlyphIndexes(otherGlyphIndexes); otherGlyphRun.setPositions(otherGlyphPositions); } else { map.insert(key, node); nodes.append(node); } } else { parentNode->addImage(node->boundingRect, node->image); if (node->selectionState == Selected) { QColor color = m_selectionColor; color.setAlpha(128); parentNode->appendChildNode(new QSGSimpleRectNode(node->boundingRect, color)); } } } foreach (const BinaryTreeNode *node, nodes) { QQuickDefaultClipNode *clipNode = node->clipNode; if (clipNode != 0 && clipNode->parent() == 0 ) parentNode->appendChildNode(clipNode); QColor color = node->selectionState == Selected ? m_selectedTextColor : node->color; parentNode->addGlyphs(node->position, node->glyphRun, color, style, styleColor, clipNode); }
void Rest::draw(QPainter* painter) const { if ( (staff() && staff()->isTabStaff() // in tab staff, do not draw rests is rests are off OR if dur. symbols are on && ( !((StaffTypeTablature*)staff()->staffType())->showRests() || ((StaffTypeTablature*)staff()->staffType())->genDurations()) ) || generated()) return; qreal _spatium = spatium(); painter->setPen(curColor()); if (parent() && measure() && measure()->multiMeasure()) { Measure* m = measure(); int n = m->multiMeasure(); qreal pw = _spatium * .7; QPen pen(painter->pen()); pen.setWidthF(pw); painter->setPen(pen); qreal w = _mmWidth; qreal y = 0.0; qreal x1 = 0.0; qreal x2 = w; pw *= .5; painter->drawLine(QLineF(x1 + pw, y, x2 - pw, y)); // draw vertical lines: pen.setWidthF(_spatium * .2); painter->setPen(pen); painter->drawLine(QLineF(x1, y-_spatium, x1, y+_spatium)); painter->drawLine(QLineF(x2, y-_spatium, x2, y+_spatium)); #ifdef USE_GLYPHS QRawFont rfont = fontId2RawFont(0); rfont.setPixelSize(20.0 * spatium()/(PPI * SPATIUM20)); QGlyphRun glyphs; QVector<quint32> idx = rfont.glyphIndexesForString(QString("%1").arg(n)); glyphs.setGlyphIndexes(idx); QVector<QPointF> adv = rfont.advancesForGlyphIndexes(idx); adv.insert(0, QPointF()); glyphs.setPositions(adv); glyphs.setRawFont(rfont); QRectF r = glyphs.boundingRect(); y = -_spatium * .5; painter->drawGlyphRun(QPointF((x2 - x1) * .5 + x1 - r.width() * .5, y), glyphs); #else QFont font = fontId2font(0); font.setPixelSize(lrint(20.0 * spatium()/(PPI * SPATIUM20))); painter->setFont(font); QFontMetricsF fm(font); // y = -_spatium * .5 - (staff()->height()*.5) - fm.ascent(); y = -_spatium * .5 - fm.ascent(); painter->drawText(QRectF(center(x1, x2), y, .0, .0), Qt::AlignHCenter|Qt::TextDontClip, QString("%1").arg(n)); #endif } else { qreal mag = magS(); symbols[score()->symIdx()][_sym].draw(painter, mag); int dots = durationType().dots(); if (dots) { qreal y = dotline * _spatium * .5; for (int i = 1; i <= dots; ++i) { qreal x = symbols[score()->symIdx()][_sym].width(mag) + point(score()->styleS(ST_dotNoteDistance)) * i; symbols[score()->symIdx()][dotSym].draw(painter, mag, QPointF(x, y)); } } } }
void BoxBuilder::handleGlyphRun_(const QGlyphRun& glyphRun) { QPainter painter_(&pixmap_); painter_.setPen(glyphPen_); painter_.drawGlyphRun(glyphPosition_,glyphRun); QVector<quint32> indices = glyphRun.glyphIndexes(); QVector<QPointF> positions = glyphRun.positions(); if(indices.size() != positions.size()) log_ << "the number of indices and the number of positions are different: " << indices.size() << " and " << positions.size() << std::endl; QVector<QPointF>::Iterator posit = positions.begin(); qreal posx = glyphPosition_.x(), posy = glyphPosition_.y(); for(QVector<quint32>::iterator ixIt = indices.begin();ixIt != indices.end();++ixIt) { QRawFont rawFont = glyphRun.rawFont(); QPainterPath painterPath = rawFont.pathForGlyph(*ixIt); QRectF glyphBoundingRect = painterPath.boundingRect(); QVector<uint> blockTextIndices(blockText_.length()); int blockTextIndicesSize = blockTextIndices.size(); rawFont.glyphIndexesForChars(blockText_.begin(),blockText_.length(),blockTextIndices.begin(),&blockTextIndicesSize); std::map<uint,QChar> glyphIndicesToChars; std::wstring blockTextStdw = blockText_.toStdWString(); // build index for acessing chars in text, since glyphs order may not correspond chars order in text for(int i = 0; i < blockTextIndices.size(); ++i) glyphIndicesToChars[blockTextIndices[i] ] = blockText_.at(i); QChar currentChar = glyphIndicesToChars[*ixIt]; unsigned histValue = 0; if(histogram.find(currentChar) == histogram.end()) histogram[currentChar] = 0; else histValue = ++histogram[currentChar]; maxHistogramValue = std::max(maxHistogramValue,histValue); //std::wcout << "processing \" "<< QString(currentChar).toStdWString() << " \"... " << std::endl; // // //log_ << "glyphBoundingRect = (" << glyphBoundingRect.x() << "," << glyphBoundingRect.y() << // "," << glyphBoundingRect.width() << "," << glyphBoundingRect.height() << ")" << std::endl; QRect screenBoundingRect( posx + posit->x() + glyphBoundingRect.x(), posy + posit->y() + glyphBoundingRect.y(), glyphBoundingRect.width()+1, glyphBoundingRect.height()+1); /* log_ << "screen layout position = (" << posx << "," << posy << ")" << std::endl; log_ << "screen glyph position = (" << posit->x() << "," << posit->y() << ")" << std::endl; log_ << "screenBoundingRect = (" << screenBoundingRect.x() << "," << screenBoundingRect.y() << "," << screenBoundingRect.width() << "," << screenBoundingRect.height() << ")" << std::end*/; QRect imageBoundingRect(QPoint( screenBoundingRect.x(), pixmap_.height()-1 - screenBoundingRect.y() - screenBoundingRect.height()+1), QPoint( screenBoundingRect.x() + screenBoundingRect.width()-1, pixmap_.height() - screenBoundingRect.y()-1) ); //log_ << "imageBoundingRect = (" << imageBoundingRect.x() << "," << imageBoundingRect.y() << // "," << imageBoundingRect.width() << "," << imageBoundingRect.height() << ")" << std::endl; if(glyphBoundingRect.width()&&glyphBoundingRect.height()) boxes_.push_back(box(glyphIndicesToChars[*ixIt],imageBoundingRect)); //painter_.setPen(boxPen_); painter_.setPen(Qt::green); //painter_.drawRect(screenBoundingRect); ++posit; } }