📄 qtextengine.cpp
字号:
// fprintf(stderr, " %d", logClusters[k]);// fprintf(stderr, "\n"); // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. int charFrom = from - pos; if (charFrom < 0) charFrom = 0; int glyphStart = logClusters[charFrom]; if (charFrom > 0 && logClusters[charFrom-1] == glyphStart) while (charFrom < ilen && logClusters[charFrom] == glyphStart) charFrom++; if (charFrom < ilen) { glyphStart = logClusters[charFrom]; int charEnd = from + len - 1 - pos; if (charEnd >= ilen) charEnd = ilen-1; int glyphEnd = logClusters[charEnd]; while (charEnd < ilen && logClusters[charEnd] == glyphEnd) charEnd++; glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];// qDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd); for (int i = glyphStart; i < glyphEnd; i++) w += glyphs[i].advance.x * !glyphs[i].attributes.dontPrint; } } }// qDebug(" --> w= %d ", w); return w;}glyph_metrics_t QTextEngine::boundingBox(int from, int len) const{ itemize(); glyph_metrics_t gm; for (int i = 0; i < layoutData->items.size(); i++) { const QScriptItem *si = layoutData->items.constData() + i; int pos = si->position; int ilen = length(i); if (pos > from + len) break; if (pos + len > from) { if (!si->num_glyphs) shape(i); unsigned short *logClusters = this->logClusters(si); QGlyphLayout *glyphs = this->glyphs(si); // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. int charFrom = from - pos; if (charFrom < 0) charFrom = 0; int glyphStart = logClusters[charFrom]; if (charFrom > 0 && logClusters[charFrom-1] == glyphStart) while (charFrom < ilen && logClusters[charFrom] == glyphStart) charFrom++; if (charFrom < ilen) { glyphStart = logClusters[charFrom]; int charEnd = from + len - 1 - pos; if (charEnd >= ilen) charEnd = ilen-1; int glyphEnd = logClusters[charEnd]; while (charEnd < ilen && logClusters[charEnd] == glyphEnd) charEnd++; glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; if (glyphStart <= glyphEnd ) { QFontEngine *fe = fontEngine(*si); glyph_metrics_t m = fe->boundingBox(glyphs+glyphStart, glyphEnd-glyphStart); gm.x = qMin(gm.x, m.x + gm.xoff); gm.y = qMin(gm.y, m.y + gm.yoff); gm.width = qMax(gm.width, m.width+gm.xoff); gm.height = qMax(gm.height, m.height+gm.yoff); gm.xoff += m.xoff; gm.yoff += m.yoff; } } } } return gm;}glyph_metrics_t QTextEngine::tightBoundingBox(int from, int len) const{ itemize(); glyph_metrics_t gm; for (int i = 0; i < layoutData->items.size(); i++) { const QScriptItem *si = layoutData->items.constData() + i; int pos = si->position; int ilen = length(i); if (pos > from + len) break; if (pos + len > from) { if (!si->num_glyphs) shape(i); unsigned short *logClusters = this->logClusters(si); QGlyphLayout *glyphs = this->glyphs(si); // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0. int charFrom = from - pos; if (charFrom < 0) charFrom = 0; int glyphStart = logClusters[charFrom]; if (charFrom > 0 && logClusters[charFrom-1] == glyphStart) while (charFrom < ilen && logClusters[charFrom] == glyphStart) charFrom++; if (charFrom < ilen) { glyphStart = logClusters[charFrom]; int charEnd = from + len - 1 - pos; if (charEnd >= ilen) charEnd = ilen-1; int glyphEnd = logClusters[charEnd]; while (charEnd < ilen && logClusters[charEnd] == glyphEnd) charEnd++; glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd]; if (glyphStart <= glyphEnd ) { QFontEngine *fe = fontEngine(*si); glyph_metrics_t m = fe->tightBoundingBox(glyphs+glyphStart, glyphEnd-glyphStart); gm.x = qMin(gm.x, m.x + gm.xoff); gm.y = qMin(gm.y, m.y + gm.yoff); gm.width = qMax(gm.width, m.width+gm.xoff); gm.height = qMax(gm.height, m.height+gm.yoff); gm.xoff += m.xoff; gm.yoff += m.yoff; } } } } return gm;}QFont QTextEngine::font(const QScriptItem &si) const{ if (!hasFormats()) return fnt; QTextCharFormat f = format(&si); QFont font = f.font(); if (block.docHandle() && block.docHandle()->layout()) { // Make sure we get the right dpi on printers QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); if (pdev) font = QFont(font, pdev); } else { font = font.resolve(fnt); } QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { if (font.pointSize() != -1) font.setPointSize((font.pointSize() * 2) / 3); else font.setPixelSize((font.pixelSize() * 2) / 3); } return font;}QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent) const{ QFontEngine *engine; QFontEngine *scaledEngine = 0; int script = si.analysis.script;#if defined(Q_WS_WIN) if (hasUsp10) { const SCRIPT_PROPERTIES *script_prop = script_properties[si.analysis.script]; script = scriptForWinLanguage(script_prop->langid); }#endif if (!hasFormats()) { engine = fnt.d->engineForScript(script);#if defined(Q_WS_WIN) if (engine->type() == QFontEngine::Box) engine = fnt.d->engineForScript(QUnicodeTables::Common);#endif } else { QTextCharFormat f = format(&si); QFont font = f.font(); if (block.docHandle() && block.docHandle()->layout()) { // Make sure we get the right dpi on printers QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); if (pdev) font = QFont(font, pdev); } else { font = font.resolve(fnt); } engine = font.d->engineForScript(script);#if defined(Q_WS_WIN) if (engine->type() == QFontEngine::Box) engine = font.d->engineForScript(QUnicodeTables::Common);#endif QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { if (font.pointSize() != -1) font.setPointSize((font.pointSize() * 2) / 3); else font.setPixelSize((font.pixelSize() * 2) / 3); scaledEngine = font.d->engineForScript(script);#if defined(Q_WS_WIN) if (scaledEngine->type() == QFontEngine::Box) scaledEngine = font.d->engineForScript(QUnicodeTables::Common);#endif } } if (ascent) { *ascent = engine->ascent(); *descent = engine->descent(); } if (scaledEngine) return scaledEngine; return engine;}struct QJustificationPoint { int type; QFixed kashidaWidth; QGlyphLayout *glyph; QFontEngine *fontEngine;};Q_DECLARE_TYPEINFO(QJustificationPoint, Q_PRIMITIVE_TYPE);static void set(QJustificationPoint *point, int type, QGlyphLayout *glyph, QFontEngine *fe){ point->type = type; point->glyph = glyph; point->fontEngine = fe; if (type >= QGlyphLayout::Arabic_Normal) { QChar ch(0x640); // Kashida character QGlyphLayout glyphs[8]; int nglyphs = 7; fe->stringToCMap(&ch, 1, glyphs, &nglyphs, 0); if (glyphs[0].glyph && glyphs[0].advance.x != 0) { point->kashidaWidth = glyphs[0].advance.x; } else { point->type = QGlyphLayout::NoJustification; point->kashidaWidth = 0; } }}void QTextEngine::justify(const QScriptLine &line){// qDebug("justify: line.gridfitted = %d, line.justified=%d", line.gridfitted, line.justified); if (line.gridfitted && line.justified) return; if (!line.gridfitted) { // redo layout in device metrics, then adjust const_cast<QScriptLine &>(line).gridfitted = true; } if ((option.alignment() & Qt::AlignHorizontal_Mask) != Qt::AlignJustify) return; itemize(); if (!forceJustification && (line.from + (int)line.length == layoutData->string.length() || layoutData->string.at(line.from + line.length - 1) == QChar::LineSeparator)) return; // justify line int maxJustify = 0; // don't include trailing white spaces when doing justification int line_length = line.length; const QCharAttributes *a = attributes()+line.from; while (line_length && a[line_length-1].whiteSpace) --line_length; // subtract one char more, as we can't justfy after the last character --line_length; if (!line_length) return; int firstItem = findItem(line.from); int nItems = findItem(line.from + line_length - 1) - firstItem + 1; QVarLengthArray<QJustificationPoint> justificationPoints; int nPoints = 0;// qDebug("justifying from %d len %d, firstItem=%d, nItems=%d", line.from, line_length, firstItem, nItems); QFixed minKashida = 0x100000; // we need to do all shaping before we go into the next loop, as we there // store pointers to the glyph data that could get reallocated by the shaping // process. for (int i = 0; i < nItems; ++i) { QScriptItem &si = layoutData->items[firstItem + i]; if (!si.num_glyphs) shape(firstItem + i); } for (int i = 0; i < nItems; ++i) { QScriptItem &si = layoutData->items[firstItem + i]; int kashida_type = QGlyphLayout::Arabic_Normal; int kashida_pos = -1; int start = qMax(line.from - si.position, 0); int end = qMin(line.from + line_length - (int)si.position, length(firstItem+i)); unsigned short *log_clusters = logClusters(&si); int gs = log_clusters[start]; int ge = (end == length(firstItem+i) ? si.num_glyphs : log_clusters[end]); QGlyphLayout *g = glyphs(&si); for (int i = gs; i < ge; ++i) { g[i].justificationType = QGlyphLayout::JustifyNone; g[i].nKashidas = 0; g[i].space_18d6 = 0; justificationPoints.resize(nPoints+3); int justification = g[i].attributes.justification; switch(justification) { case QGlyphLayout::NoJustification: break; case QGlyphLayout::Space : // fall through 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -