📄 qtextengine.cpp
字号:
} } QFixed need = line.width - line.textWidth; if (need < 0) { // line overflows already! const_cast<QScriptLine &>(line).justified = true; return; }// qDebug("doing justification: textWidth=%x, requested=%x, maxJustify=%d", line.textWidth.value(), line.width.value(), maxJustify);// qDebug(" minKashida=%f, need=%f", minKashida, need); // distribute in priority order if (maxJustify >= QGlyphLayout::Arabic_Normal) { while (need >= minKashida) { for (int type = maxJustify; need >= minKashida && type >= QGlyphLayout::Arabic_Normal; --type) { for (int i = 0; need >= minKashida && i < nPoints; ++i) { if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) { justificationPoints[i].glyph->nKashidas++; // ############ justificationPoints[i].glyph->space_18d6 += justificationPoints[i].kashidaWidth.value(); need -= justificationPoints[i].kashidaWidth;// qDebug("adding kashida type %d with width %x, neednow %x", type, justificationPoints[i].kashidaWidth, need.value()); } } } } } Q_ASSERT(need >= 0); if (!need) goto end; maxJustify = qMin(maxJustify, (int)QGlyphLayout::Space); for (int type = maxJustify; need != 0 && type > 0; --type) { int n = 0; for (int i = 0; i < nPoints; ++i) { if (justificationPoints[i].type == type) ++n; }// qDebug("number of points for justification type %d: %d", type, n); if (!n) continue; for (int i = 0; i < nPoints; ++i) { if (justificationPoints[i].type == type) { QFixed add = need/n;// qDebug("adding %x to glyph %x", add.value(), justificationPoints[i].glyph->glyph); justificationPoints[i].glyph->space_18d6 = add.value(); need -= add; --n; } } Q_ASSERT(!need); } end: const_cast<QScriptLine &>(line).justified = true;}void QScriptLine::setDefaultHeight(QTextEngine *eng){ QFont f; QFontEngine *e; if (eng->block.docHandle() && eng->block.docHandle()->layout()) { f = eng->block.charFormat().font(); // Make sure we get the right dpi on printers QPaintDevice *pdev = eng->block.docHandle()->layout()->paintDevice(); if (pdev) f = QFont(f, pdev); e = f.d->engineForScript(QUnicodeTables::Common); } else { e = eng->fnt.d->engineForScript(QUnicodeTables::Common); } ascent = qMax(ascent, e->ascent()); descent = qMax(descent, e->descent());}QTextEngine::LayoutData::LayoutData(){ memory = 0; allocated = 0; num_glyphs = 0; memory_on_stack = false; used = 0; hasBidi = false; inLayout = false; haveCharAttributes = false; logClustersPtr = 0; glyphPtr = 0;}QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int _allocated) : string(str){ allocated = _allocated; int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1; int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1; available_glyphs = ((int)allocated - space_charAttributes - space_logClusters)*(int)sizeof(void*)/(int)sizeof(QGlyphLayout); if (available_glyphs < str.length()) { // need to allocate on the heap num_glyphs = 0; allocated = 0; memory_on_stack = false; memory = 0; logClustersPtr = 0; glyphPtr = 0; } else { num_glyphs = str.length(); memory_on_stack = true; memory = stack_memory; logClustersPtr = (unsigned short *)(memory + space_charAttributes); glyphPtr = (QGlyphLayout *)(memory + space_charAttributes + space_logClusters); memset(memory, 0, space_charAttributes*sizeof(void *)); memset(glyphPtr, 0, num_glyphs*sizeof(QGlyphLayout)); } used = 0; hasBidi = false; inLayout = false; haveCharAttributes = false;}QTextEngine::LayoutData::~LayoutData(){ if (!memory_on_stack) free(memory); memory = 0;}void QTextEngine::LayoutData::reallocate(int totalGlyphs){ Q_ASSERT(totalGlyphs >= num_glyphs); if (memory_on_stack && available_glyphs >= totalGlyphs) { memset(glyphPtr + num_glyphs, 0, (totalGlyphs - num_glyphs)*sizeof(QGlyphLayout)); num_glyphs = totalGlyphs; return; } int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1; int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1; int space_glyphs = sizeof(QGlyphLayout)*totalGlyphs/sizeof(void*) + 2; int newAllocated = space_charAttributes + space_glyphs + space_logClusters; Q_ASSERT(newAllocated >= allocated); void **old_mem = memory; memory = (void **)::realloc(memory_on_stack ? 0 : old_mem, newAllocated*sizeof(void *)); if (memory_on_stack && memory) memcpy(memory, old_mem, allocated*sizeof(void *)); memory_on_stack = false; void **m = memory; m += space_charAttributes; logClustersPtr = (unsigned short *) m; m += space_logClusters; glyphPtr = (QGlyphLayout *) m; memset(((char *)memory) + allocated*sizeof(void *), 0, (newAllocated - allocated)*sizeof(void *)); allocated = newAllocated; num_glyphs = totalGlyphs;}void QTextEngine::freeMemory(){ if (!stackEngine) { delete layoutData; layoutData = 0; } else { layoutData->used = 0; layoutData->hasBidi = false; layoutData->inLayout = false; layoutData->haveCharAttributes = false; } for (int i = 0; i < lines.size(); ++i) { lines[i].justified = 0; lines[i].gridfitted = 0; }}int QTextEngine::formatIndex(const QScriptItem *si) const{ if (specialData && !specialData->resolvedFormatIndices.isEmpty()) return specialData->resolvedFormatIndices.at(si - &layoutData->items[0]); QTextDocumentPrivate *p = block.docHandle(); if (!p) return -1; int pos = si->position; if (specialData && si->position >= specialData->preeditPosition) { if (si->position < specialData->preeditPosition + specialData->preeditText.length()) pos = qMax(specialData->preeditPosition - 1, 0); else pos -= specialData->preeditText.length(); } QTextDocumentPrivate::FragmentIterator it = p->find(block.position() + pos); return it.value()->format;}QTextCharFormat QTextEngine::format(const QScriptItem *si) const{ QTextCharFormat format; const QTextFormatCollection *formats = 0; if (block.docHandle()) { formats = this->formats(); format = formats->charFormat(formatIndex(si)); } if (specialData && specialData->resolvedFormatIndices.isEmpty()) { int end = si->position + length(si); for (int i = 0; i < specialData->addFormats.size(); ++i) { const QTextLayout::FormatRange &r = specialData->addFormats.at(i); if (r.start <= si->position && r.start + r.length >= end) { if (!specialData->addFormatIndices.isEmpty()) format.merge(formats->format(specialData->addFormatIndices.at(i))); else format.merge(r.format); } } } return format;}void QTextEngine::addRequiredBoundaries() const{ int position = 0; SpecialData *s = specialData; const QTextDocumentPrivate *p = block.docHandle(); if (p) { QTextDocumentPrivate::FragmentIterator it = p->find(block.position()); QTextDocumentPrivate::FragmentIterator end = p->find(block.position() + block.length() - 1); // -1 to omit the block separator char int format = it.value()->format; for (; it != end; ++it) { if (s && position >= s->preeditPosition) { position += s->preeditText.length(); s = 0; } const QTextFragmentData * const frag = it.value(); if (format != frag->format) setBoundary(position); format = frag->format; position += frag->size; } } if (specialData) { for (int i = 0; i < specialData->addFormats.size(); ++i) { const QTextLayout::FormatRange &r = specialData->addFormats.at(i); setBoundary(r.start); setBoundary(r.start + r.length); //qDebug("adding boundaries %d %d", r.start, r.start+r.length); } }}bool QTextEngine::atWordSeparator(int position) const{ const QChar c = layoutData->string.at(position); return c == QLatin1Char('.') || c == QLatin1Char(',') || c == QLatin1Char('?') || c == QLatin1Char('!') || c == QLatin1Char(':') || c == QLatin1Char(';') || c == QLatin1Char('-') || c == QLatin1Char('<') || c == QLatin1Char('>') || c == QLatin1Char('[') || c == QLatin1Char(']') || c == QLatin1Char('(') || c == QLatin1Char(')') || c == QLatin1Char('{') || c == QLatin1Char('}') || c == QLatin1Char('=') || c == QLatin1Char('\t') || c == QChar::Nbsp ;}void QTextEngine::indexAdditionalFormats(){ if (!block.docHandle()) return; specialData->addFormatIndices.resize(specialData->addFormats.count()); QTextFormatCollection * const formats = this->formats(); for (int i = 0; i < specialData->addFormats.count(); ++i) { specialData->addFormatIndices[i] = formats->indexForFormat(specialData->addFormats.at(i).format); specialData->addFormats[i].format = QTextCharFormat(); }}QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int flags) const{// qDebug() << "elidedText; available width" << width.toReal() << "text width:" << this->width(0, layoutData->string.length()).toReal(); if (flags & Qt::TextShowMnemonic) { itemize(); for (int i = 0; i < layoutData->items.size(); ++i) { QScriptItem &si = layoutData->items[i]; if (!si.num_glyphs) shape(i); unsigned short *logClusters = this->logClusters(&si); QGlyphLayout *glyphs = this->glyphs(&si); const int end = si.position + length(&si); for (int i = si.position; i < end - 1; ++i) if (layoutData->string.at(i) == QLatin1Char('&')) { const int gp = logClusters[i - si.position]; glyphs[gp].attributes.dontPrint = true; QCharAttributes *attributes = const_cast<QCharAttributes *>(this->attributes()); attributes[i + 1].charStop = false; attributes[i + 1].whiteSpace = false; attributes[i + 1].lineBreakType = QCharAttributes::NoBreak; if (i < end - 1 && layoutData->string.at(i + 1) == QLatin1Char('&')) ++i; } } } validate(); if (mode == Qt::ElideNone || this->width(0, layoutData->string.length()) <= width || layoutData->string.length() <= 1) return layoutData->string; QFixed ellipsisWidth; QString ellipsisText; { QChar ellipsisChar(0x2026); QFontEngine *fe = fnt.d->engineForScript(QUnicodeTables::Common); // the lookup can be really slow when we use XLFD fonts bool isXlfdEngine = (fe->type() == QFontEngine::XLFD) || (fe->type() == QFontEngine::Multi && static_cast<QFontEngineMulti*>(fe)->engine(0)->type() == QFontEngine::XLFD); if (!isXlfdEngine && fe->canRender(&ellipsisChar, 1)) { QGlyphLayout glyph; int nGlyphs = 1; fe->stringToCMap(&ellipsisChar, 1, &glyph, &nGlyphs, 0); ellipsisWidth = glyph.advance.x; ellipsisText = ellipsisChar; } else { QString dotDotDot(QLatin1String("...")); QGlyphLayout glyphs[3]; int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -