📄 qtextengine.cpp
字号:
case QGlyphLayout::Arabic_Space : if (kashida_pos >= 0) {// qDebug("kashida position at %d in word", kashida_pos); set(&justificationPoints[nPoints], kashida_type, g+kashida_pos, fontEngine(si)); minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); ++nPoints; } kashida_pos = -1; kashida_type = QGlyphLayout::Arabic_Normal; // fall through case QGlyphLayout::Character : set(&justificationPoints[nPoints++], justification, g+i, fontEngine(si)); maxJustify = qMax(maxJustify, justification); break; case QGlyphLayout::Arabic_Normal : case QGlyphLayout::Arabic_Waw : case QGlyphLayout::Arabic_BaRa : case QGlyphLayout::Arabic_Alef : case QGlyphLayout::Arabic_HaaDal : case QGlyphLayout::Arabic_Seen : case QGlyphLayout::Arabic_Kashida : if (justification >= kashida_type) { kashida_pos = i; kashida_type = justification; } } } if (kashida_pos >= 0) { set(&justificationPoints[nPoints], kashida_type, g+kashida_pos, fontEngine(si)); minKashida = qMin(minKashida, justificationPoints[nPoints].kashidaWidth); maxJustify = qMax(maxJustify, justificationPoints[nPoints].type); ++nPoints; } } 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()) { 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) - 2; 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(); allocated = 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; 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 == '.' || c == ',' || c == ':' || c == ';' || c == '-' || c == '<' || c == '>' || c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' || 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(); }}void QTextEngine::setBoundary(int strPos) const{ if (strPos <= 0 || strPos >= layoutData->string.length()) return; int itemToSplit = 0; while (itemToSplit < layoutData->items.size() && layoutData->items[itemToSplit].position <= strPos) itemToSplit++; itemToSplit--; if (layoutData->items[itemToSplit].position == strPos) { // already a split at the requested position return; } splitItem(itemToSplit, strPos - layoutData->items[itemToSplit].position);}void QTextEngine::splitItem(int item, int pos) const{ if (pos <= 0) return; layoutData->items.insert(item + 1, QScriptItem(layoutData->items[item])); QScriptItem &oldItem = layoutData->items[item]; QScriptItem &newItem = layoutData->items[item+1]; newItem.position += pos; if (oldItem.num_glyphs) { // already shaped, break glyphs aswell int breakGlyph = logClusters(&oldItem)[pos]; newItem.num_glyphs = oldItem.num_glyphs - breakGlyph; oldItem.num_glyphs = breakGlyph; newItem.glyph_data_offset = oldItem.glyph_data_offset + breakGlyph; for (int i = 0; i < newItem.num_glyphs; i++) logClusters(&newItem)[i] -= breakGlyph; QFixed w = 0; const QGlyphLayout *g = glyphs(&oldItem); for(int j = 0; j < breakGlyph; ++j) w += (g++)->advance.x; newItem.width = oldItem.width - w; oldItem.width = w; }// qDebug("split at position %d itempos=%d", pos, item);}QFixed QTextEngine::nextTab(const QScriptItem *si, QFixed x) const{ // #### should work for alignright and righttoleft if (!(option.alignment() & Qt::AlignLeft) || option.textDirection() != Qt::LeftToRight) return x + si->width; QList<qreal> tabArray = option.tabArray(); if (!tabArray.isEmpty()) { for (int i = 0; i < tabArray.size(); ++i) { if (tabArray.at(i) > x.toReal()) return QFixed::fromReal(tabArray.at(i)); } } QFixed tab = QFixed::fromReal(option.tabStop()); if (tab <= 0) tab = 80; // default return ((x / tab).truncate() + 1) * tab;}void QTextEngine::resolveAdditionalFormats() const{ if (!specialData || specialData->addFormats.isEmpty() || !block.docHandle()) return; QTextFormatCollection *collection = this->formats(); specialData->resolvedFormatIndices.clear(); QVector<int> indices(layoutData->items.count()); for (int i = 0; i < layoutData->items.count(); ++i) { QTextCharFormat f = format(&layoutData->items.at(i)); indices[i] = collection->indexForFormat(f); } specialData->resolvedFormatIndices = indices;}QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) : _layoutData(string, _memory, MemSize){ fnt = f; text = string; stackEngine = true; layoutData = &_layoutData;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -