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 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 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 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; } }