📄 qtextengine.cpp
字号:
eor = current; status.eor = dirCurrent; break; case QChar::DirR: case QChar::DirAL: case QChar::DirAN: if (!first) appendItems(engine, sor, eor, control, dir); status.eor = QChar::DirEN; dir = QChar::DirAN; break; case QChar::DirES: case QChar::DirCS: if(status.eor == QChar::DirEN || dir == QChar::DirAN) { eor = current; break; } case QChar::DirBN: case QChar::DirB: case QChar::DirS: case QChar::DirWS: case QChar::DirON: if(status.eor == QChar::DirR) { // neutrals go to R eor = current - 1; appendItems(engine, sor, eor, control, dir); dir = QChar::DirON; status.eor = QChar::DirEN; dir = QChar::DirAN; } else if(status.eor == QChar::DirL || (status.eor == QChar::DirEN && status.lastStrong == QChar::DirL)) { eor = current; status.eor = dirCurrent; } else { // numbers on both sides, neutrals get right to left direction if(dir != QChar::DirL) { appendItems(engine, sor, eor, control, dir); dir = QChar::DirON; status.eor = QChar::DirON; eor = current - 1; dir = QChar::DirR; appendItems(engine, sor, eor, control, dir); dir = QChar::DirON; status.eor = QChar::DirON; dir = QChar::DirAN; } else { eor = current; status.eor = dirCurrent; } } default: break; } break; } case QChar::DirAN: hasBidi = true; dirCurrent = QChar::DirAN; if(dir == QChar::DirON) dir = QChar::DirAN; switch(status.last) { case QChar::DirL: case QChar::DirAN: eor = current; status.eor = QChar::DirAN; break; case QChar::DirR: case QChar::DirAL: case QChar::DirEN: if (!first) appendItems(engine, sor, eor, control, dir); dir = QChar::DirON; status.eor = QChar::DirAN; break; case QChar::DirCS: if(status.eor == QChar::DirAN) { eor = current; break; } case QChar::DirES: case QChar::DirET: case QChar::DirBN: case QChar::DirB: case QChar::DirS: case QChar::DirWS: case QChar::DirON: if(status.eor == QChar::DirR) { // neutrals go to R eor = current - 1; appendItems(engine, sor, eor, control, dir); status.eor = QChar::DirAN; dir = QChar::DirAN; } else if(status.eor == QChar::DirL || (status.eor == QChar::DirEN && status.lastStrong == QChar::DirL)) { eor = current; status.eor = dirCurrent; } else { // numbers on both sides, neutrals get right to left direction if(dir != QChar::DirL) { appendItems(engine, sor, eor, control, dir); status.eor = QChar::DirON; eor = current - 1; dir = QChar::DirR; appendItems(engine, sor, eor, control, dir); status.eor = QChar::DirAN; dir = QChar::DirAN; } else { eor = current; status.eor = dirCurrent; } } default: break; } break; case QChar::DirES: case QChar::DirCS: break; case QChar::DirET: if(status.last == QChar::DirEN) { dirCurrent = QChar::DirEN; eor = current; status.eor = dirCurrent; } break; // boundary neutrals should be ignored case QChar::DirBN: break; // neutrals case QChar::DirB: // ### what do we do with newline and paragraph separators that come to here? break; case QChar::DirS: // ### implement rule L1 break; case QChar::DirWS: case QChar::DirON: break; default: break; } //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << control.direction() << endl; if(current >= (int)length) break; // set status.last as needed. switch(dirCurrent) { case QChar::DirET: case QChar::DirES: case QChar::DirCS: case QChar::DirS: case QChar::DirWS: case QChar::DirON: switch(status.last) { case QChar::DirL: case QChar::DirR: case QChar::DirAL: case QChar::DirEN: case QChar::DirAN: status.last = dirCurrent; break; default: status.last = QChar::DirON; } break; case QChar::DirNSM: case QChar::DirBN: // ignore these break; case QChar::DirLRO: case QChar::DirLRE: status.last = QChar::DirL; break; case QChar::DirRLO: case QChar::DirRLE: status.last = QChar::DirR; break; case QChar::DirEN: if (status.last == QChar::DirL) { status.last = QChar::DirL; break; } // fall through default: status.last = dirCurrent; } first = false; ++current; }#if (BIDI_DEBUG >= 1) cout << "reached end of line current=" << current << ", eor=" << eor << endl;#endif eor = current - 1; // remove dummy char if (sor <= eor) appendItems(engine, sor, eor, control, dir); return hasBidi;}void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrder){ // first find highest and lowest levels uchar levelLow = 128; uchar levelHigh = 0; int i = 0; while (i < numItems) { //printf("level = %d\n", r->level); if (levels[i] > levelHigh) levelHigh = levels[i]; if (levels[i] < levelLow) levelLow = levels[i]; i++; } // implements reordering of the line (L2 according to BiDi spec): // L2. From the highest level found in the text to the lowest odd level on each line, // reverse any contiguous sequence of characters that are at that level or higher. // reversing is only done up to the lowest odd level if(!(levelLow%2)) levelLow++;#if (BIDI_DEBUG >= 1) cout << "reorderLine: lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl;#endif int count = numItems - 1; for (i = 0; i < numItems; i++) visualOrder[i] = i; while(levelHigh >= levelLow) { int i = 0; while (i < count) { while(i < count && levels[i] < levelHigh) i++; int start = i; while(i <= count && levels[i] >= levelHigh) i++; int end = i-1; if(start != end) { //cout << "reversing from " << start << " to " << end << endl; for(int j = 0; j < (end-start+1)/2; j++) { int tmp = visualOrder[start+j]; visualOrder[start+j] = visualOrder[end-j]; visualOrder[end-j] = tmp; } } i++; } levelHigh--; }#if (BIDI_DEBUG >= 1) cout << "visual order is:" << endl; for (i = 0; i < numItems; i++) cout << visualOrder[i] << endl;#endif}// -----------------------------------------------------------------------------------------------------//// The line break algorithm. See http://www.unicode.org/reports/tr14/tr14-13.html//// -----------------------------------------------------------------------------------------------------/* The Unicode algorithm does in our opinion allow line breaks at some places they shouldn't be allowed. The following changes were thus made in comparison to the Unicode reference: CL->AL from Dbk to Ibk CL->PR from Dbk to Ibk EX->AL from Dbk to Ibk IS->AL from Dbk to Ibk PO->AL from Dbk to Ibk SY->AL from Dbk to Ibk SY->PO from Dbk to Ibk SY->PR from Dbk to Ibk SY->OP from Dbk to Ibk Al->OP from Dbk to Ibk AL->HY from Dbk to Ibk AL->PR from Dbk to Ibk AL->PO from Dbk to Ibk PR->PR from Dbk to Ibk PO->PO from Dbk to Ibk PR->PO from Dbk to Ibk PO->PR from Dbk to Ibk HY->PO from Dbk to Ibk HY->PR from Dbk to Ibk HY->OP from Dbk to Ibk PO->OP from Dbk to Ibk NU->EX from Dbk to Ibk NU->PR from Dbk to Ibk PO->NU from Dbk to Ibk EX->PO from Dbk to Ibk*/enum break_action { Dbk, // Direct break Ibk, // Indirect break; only allowed if space between the two chars Pbk // Prohibited break; no break allowed even if space between chars};// The following line break classes are not treated by the table:// SA, BK, CR, LF, SG, CB, SPstatic const quint8 breakTable[QUnicodeTables::LineBreak_CM+1][QUnicodeTables::LineBreak_CM+1] ={ // OP, CL, QU, GL, NS, EX, SY, IS, PR, PO, NU, AL, ID, IN, HY, BA, BB, B2, ZW, CM { Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk, Pbk }, // OP { Dbk, Pbk, Ibk, Pbk, Pbk, Pbk, Pbk, Pbk, Ibk, Ibk, Dbk, Ibk, Dbk, Dbk, Ibk, Ibk, Pbk, Pbk, Pbk, Pbk }, // CL { Pbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // QU { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Pbk }, // GL { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // NS { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // EX { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // SY { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IS { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // PR { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // PO { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // NU { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk }, // AL { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // ID { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // IN { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // HY { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Dbk, Pbk, Ibk }, // BA { Ibk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Ibk, Pbk, Ibk }, // BB { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Ibk, Ibk, Dbk, Pbk, Pbk, Ibk }, // B2 { Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Dbk, Pbk, Ibk }, // ZW { Dbk, Pbk, Ibk, Pbk, Ibk, Pbk, Pbk, Pbk, Dbk, Ibk, Dbk, Dbk, Dbk, Ibk, Ibk, Ibk, Dbk, Dbk, Pbk, Pbk } // CM};// set the soft break flag at every possible line breaking point. This needs correct clustering information.static void calcLineBreaks(const QString &str, QCharAttributes *charAttributes){ int len = str.length(); if (!len) return; const QChar *uc = str.unicode(); const QUnicodeTables::Properties *prop = QUnicodeTables::properties(uc->unicode()); int cls = prop->line_break_class; if (cls >= QUnicodeTables::LineBreak_CM) cls = QUnicodeTables::LineBreak_ID; charAttributes[0].softBreak = false; charAttributes[0].whiteSpace = (cls == QUnicodeTables::LineBreak_SP || cls == QUnicodeTables::LineBreak_BK); charAttributes[0].charStop = true; charAttributes[0].category = prop->category; for (int i = 1; i < len; ++i) { prop = QUnicodeTables::properties(uc[i].unicode()); int ncls = prop->line_break_class; int category = prop->category; if (category == QChar::Mark_NonSpacing) goto nsm; if (category == QChar::Other_Surrogate) { // char stop only on first pair if (uc[i].unicode() >= 0xd800 && uc[i].unicode() < 0xdc00 && i < len-1 && uc[i+1].unicode() >= 0xdc00 && uc[i+1].unicode() < 0xe000) goto nsm; // ### correctly handle second surrogate } if (ncls == QUnicodeTables::LineBreak_SP || ncls == QUnicodeTables::LineBreak_BK) { charAttributes[i].softBreak = false; charAttributes[i].whiteSpace = true; charAttributes[i].charStop = true; charAttributes[i].category = QChar::Separator_Space; cls = ncls; continue; } if (cls == QUnicodeTables::LineBreak_SA && ncls == QUnicodeTables::LineBreak_SA) { // two complex chars (thai or lao), thai_attributes might override, but here // we do a best guess charAttributes[i].softBreak = true; charAttributes[i].whiteSpace = false; charAttributes[i].charStop = true; charAttributes[i].category = QChar::Separator_Space; cls = ncls; continue; } { int tcls = ncls; if (tcls >= QUnicodeTables::LineBreak_SA) tcls = QUnicodeTables::LineBreak_ID; if (cls >= QUnicodeTables::LineBreak_SA) cls = QUnicodeTables::LineBreak_ID; bool softBreak; int brk = breakTable[cls][tcls]; if (brk == Ibk) softBreak = (cls == QUnicodeTables::LineBreak_SP); else softBreak = (brk == Dbk);// qDebug("char = %c %04x, cls=%d, ncls=%d, brk=%d soft=%d", uc[i].cell(), uc[i].unicode(), cls, ncls, brk, charAttributes[i].softBreak); charAttributes[i].softBreak = softBreak; charAttributes[i].whiteSpace = false; charAttributes[i].charStop = true; charAttributes[i].category = category; cls = ncls; } continue; nsm: charAttributes[i].softBreak = false; charAttributes[i].whiteSpace = false; charAttributes[i].charStop = false; charAttributes[i].category = QChar::Mark_NonSpacing; }}#if defined(Q_WS_X11) || defined (Q_WS_QWS)# include "qtextengine_unix.cpp"#elif defined(Q_WS_WIN)# include "qtextengine_win.cpp"#elif defined(Q_WS_MAC)# include "qtextengine_mac.cpp"#endifstatic void init(QTextEngine *e){#ifdef Q_WS_WIN if(!resolvedUsp10) resolveUsp10();#endif e->ignoreBidi = false; e->cacheGlyphs = false; e->layoutData = 0; e->minWidth = 0; e->maxWidth = 0; e->underlinePositions = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -