📄 qscriptengine.cpp
字号:
{ 0x06AB, 0 }, // 0x06AB { 0x06AC, 0 }, // 0x06AC { 0xFBD3, 3 }, // 0x06AD D NG { 0x06AE, 0 }, // 0x06AE { 0xFB92, 3 }, // 0x06AF D GAF { 0x06B0, 0 }, // 0x06B0 { 0xFB9A, 3 }, // 0x06B1 D NGOEH { 0x06B2, 0 }, // 0x06B2 { 0xFB96, 3 }, // 0x06B3 D GUEH { 0x06B4, 0 }, // 0x06B4 { 0x06B5, 0 }, // 0x06B5 { 0x06B6, 0 }, // 0x06B6 { 0x06B7, 0 }, // 0x06B7 { 0x06B8, 0 }, // 0x06B8 { 0x06B9, 0 }, // 0x06B9 { 0xFB9E, 1 }, // 0x06BA R NOON GHUNNA { 0xFBA0, 3 }, // 0x06BB D RNOON { 0x06BC, 0 }, // 0x06BC { 0x06BD, 0 }, // 0x06BD { 0xFBAA, 3 }, // 0x06BE D HEH DOACHASHMEE { 0x06BF, 0 }, // 0x06BF { 0xFBA4, 1 }, // 0x06C0 R HEH WITH YEH ABOVE { 0xFBA6, 3 }, // 0x06C1 D HEH GOAL { 0x06C2, 0 }, // 0x06C2 { 0x06C3, 0 }, // 0x06C3 { 0x06C4, 0 }, // 0x06C4 { 0xFBE0, 1 }, // 0x06C5 R KIRGHIZ OE { 0xFBD9, 1 }, // 0x06C6 R OE { 0xFBD7, 1 }, // 0x06C7 R U { 0xFBDB, 1 }, // 0x06C8 R YU { 0xFBE2, 1 }, // 0x06C9 R KIRGHIZ YU { 0x06CA, 0 }, // 0x06CA { 0xFBDE, 1 }, // 0x06CB R VE { 0xFBFC, 3 }, // 0x06CC D FARSI YEH { 0x06CD, 0 }, // 0x06CD { 0x06CE, 0 }, // 0x06CE { 0x06CF, 0 }, // 0x06CF { 0xFBE4, 3 }, // 0x06D0 D E { 0x06D1, 0 }, // 0x06D1 { 0xFBAE, 1 }, // 0x06D2 R YEH BARREE { 0xFBB0, 1 }, // 0x06D3 R YEH BARREE WITH HAMZA ABOVE { 0x06D4, 0 }, // 0x06D4 { 0x06D5, 0 }, // 0x06D5 { 0x06D6, 0 }, // 0x06D6 { 0x06D7, 0 }, // 0x06D7 { 0x06D8, 0 }, // 0x06D8 { 0x06D9, 0 }, // 0x06D9 { 0x06DA, 0 }, // 0x06DA { 0x06DB, 0 }, // 0x06DB { 0x06DC, 0 }, // 0x06DC { 0x06DD, 0 }, // 0x06DD { 0x06DE, 0 }, // 0x06DE { 0x06DF, 0 }, // 0x06DF { 0x06E0, 0 }, // 0x06E0 { 0x06E1, 0 }, // 0x06E1 { 0x06E2, 0 }, // 0x06E2 { 0x06E3, 0 }, // 0x06E3 { 0x06E4, 0 }, // 0x06E4 { 0x06E5, 0 }, // 0x06E5 { 0x06E6, 0 }, // 0x06E6 { 0x06E7, 0 }, // 0x06E7 { 0x06E8, 0 }, // 0x06E8 { 0x06E9, 0 }, // 0x06E9 { 0x06EA, 0 }, // 0x06EA { 0x06EB, 0 }, // 0x06EB { 0x06EC, 0 }, // 0x06EC { 0x06ED, 0 }, // 0x06ED { 0x06EE, 0 }, // 0x06EE { 0x06EF, 0 }, // 0x06EF { 0x06F0, 0 }, // 0x06F0 { 0x06F1, 0 }, // 0x06F1 { 0x06F2, 0 }, // 0x06F2 { 0x06F3, 0 }, // 0x06F3 { 0x06F4, 0 }, // 0x06F4 { 0x06F5, 0 }, // 0x06F5 { 0x06F6, 0 }, // 0x06F6 { 0x06F7, 0 }, // 0x06F7 { 0x06F8, 0 }, // 0x06F8 { 0x06F9, 0 }, // 0x06F9 { 0x06FA, 0 }, // 0x06FA { 0x06FB, 0 }, // 0x06FB { 0x06FC, 0 }, // 0x06FC { 0x06FD, 0 }, // 0x06FD { 0x06FE, 0 }, // 0x06FE { 0x06FF, 0 } // 0x06FF};// the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, this table doesstatic const ushort alefMaksura[4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9};// this is a bit tricky. Alef always binds to the right, so the second parameter descibing the shape// of the lam can be either initial of medial. So initial maps to the isolated form of the ligature,// medial to the final formstatic const ushort arabicUnicodeLamAlefMapping[6][4] = { { 0xfffd, 0xfffd, 0xfef5, 0xfef6 }, // 0x622 R Alef with Madda above { 0xfffd, 0xfffd, 0xfef7, 0xfef8 }, // 0x623 R Alef with Hamza above { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x624 // Just to fill the table ;-) { 0xfffd, 0xfffd, 0xfef9, 0xfefa }, // 0x625 R Alef with Hamza below { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x626 // Just to fill the table ;-) { 0xfffd, 0xfffd, 0xfefb, 0xfefc } // 0x627 R Alef};static inline int getShape(uchar cell, int shape){ // the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, handle this here uint ch = (cell != 0x49) ? (shape ? arabicUnicodeMapping[cell][0] + shape : 0x600+cell) : alefMaksura[shape] ; return ch;}/* Two small helper functions for arabic shaping.*/static inline const QChar prevChar(const QString *str, int pos){ //qDebug("leftChar: pos=%d", pos); pos--; const QChar *ch = str->unicode() + pos; while(pos > -1) { if(::category(*ch) != QChar::Mark_NonSpacing) return *ch; pos--; ch--; } return QChar::ReplacementCharacter;}static inline const QChar nextChar(const QString *str, int pos){ pos++; int len = str->length(); const QChar *ch = str->unicode() + pos; while(pos < len) { //qDebug("rightChar: %d isLetter=%d, joining=%d", pos, ch.isLetter(), ch.joining()); if(::category(*ch) != QChar::Mark_NonSpacing) return *ch; // assume it's a transparent char, this might not be 100% correct pos++; ch++; } return QChar::ReplacementCharacter;}#ifndef Q_WS_MACstatic void shapedString(const QString *uc, int from, int len, QChar *shapeBuffer, int *shapedLength, bool reverse, QGlyphLayout *glyphs, unsigned short *logClusters){ Q_ASSERT(uc->length() >= from + len); if(len == 0) { *shapedLength = 0; return; } QVarLengthArray<QArabicProperties> props(len+2); QArabicProperties *properties = props.data(); int f = from; int l = len; if (from > 0) { --f; ++l; ++properties; } if (f + l < uc->length()) { ++l; } qt_getArabicProperties((const unsigned short *)(uc->unicode()+f), l, props.data()); const QChar *ch = uc->unicode() + from; QChar *data = shapeBuffer; int clusterStart = 0; for (int i = 0; i < len; i++) { uchar r = ch->row(); int gpos = data - shapeBuffer; if (r != 0x06) { if (r == 0x20) { uchar c = ch->cell(); if (c == 0x0c || c == 0x0d) // remove ZWJ and ZWNJ goto skip; } if (reverse) *data = mirroredChar(*ch); else *data = *ch; } else { uchar c = ch->cell(); int pos = i + from; int shape = properties[i].shape;// qDebug("mapping U+%x to shape %d glyph=0x%x", ch->unicode(), shape, getShape(c, shape)); // take care of lam-alef ligatures (lam right of alef) ushort map; switch (c) { case 0x44: { // lam const QChar pch = nextChar(uc, pos); if (pch.row() == 0x06) { switch (pch.cell()) { case 0x22: case 0x23: case 0x25: case 0x27:// qDebug(" lam of lam-alef ligature"); map = arabicUnicodeLamAlefMapping[pch.cell() - 0x22][shape]; goto next; default: break; } } break; } case 0x22: // alef with madda case 0x23: // alef with hamza above case 0x25: // alef with hamza below case 0x27: // alef if (prevChar(uc, pos).unicode() == 0x0644) { // have a lam alef ligature //qDebug(" alef of lam-alef ligature"); goto skip; } default: break; } map = getShape(c, shape); next: *data = map; } // ##### Fixme //glyphs[gpos].attributes.zeroWidth = zeroWidth; if (::category(*ch) == QChar::Mark_NonSpacing) { glyphs[gpos].attributes.mark = true;// qDebug("glyph %d (char %d) is mark!", gpos, i); } else { glyphs[gpos].attributes.mark = false; clusterStart = data - shapeBuffer; } glyphs[gpos].attributes.clusterStart = !glyphs[gpos].attributes.mark; glyphs[gpos].attributes.combiningClass = combiningClass(*ch); glyphs[gpos].attributes.justification = properties[i].justification;// qDebug("data[%d] = %x (from %x)", gpos, (uint)data->unicode(), ch->unicode()); data++; skip: ch++; logClusters[i] = clusterStart; } *shapedLength = data - shapeBuffer;}#endif#ifndef QT_NO_OPENTYPEenum { InitProperty = 0x2, IsolProperty = 0x4, FinaProperty = 0x8, MediProperty = 0x10, RligProperty = 0x20, CaltProperty = 0x40, LigaProperty = 0x80, DligProperty = 0x100, CswhProperty = 0x200, MsetProperty = 0x400};static const QOpenType::Features arabic_features[] = { { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, { FT_MAKE_TAG('c', 's', 'w', 'h'), CswhProperty }, // mset is used in old Win95 fonts that don't have a 'mark' positioning table. { FT_MAKE_TAG('m', 's', 'e', 't'), MsetProperty }, {0, 0}};static const QOpenType::Features syriac_features[] = { { FT_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, { FT_MAKE_TAG('i', 's', 'o', 'l'), IsolProperty }, { FT_MAKE_TAG('f', 'i', 'n', 'a'), FinaProperty }, { FT_MAKE_TAG('f', 'i', 'n', '2'), FinaProperty }, { FT_MAKE_TAG('f', 'i', 'n', '3'), FinaProperty }, { FT_MAKE_TAG('m', 'e', 'd', 'i'), MediProperty }, { FT_MAKE_TAG('m', 'e', 'd', '2'), MediProperty }, { FT_MAKE_TAG('i', 'n', 'i', 't'), InitProperty }, { FT_MAKE_TAG('r', 'l', 'i', 'g'), RligProperty }, { FT_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty }, { FT_MAKE_TAG('l', 'i', 'g', 'a'), LigaProperty }, { FT_MAKE_TAG('d', 'l', 'i', 'g'), DligProperty }, {0, 0}};static bool arabicSyriacOpenTypeShape(QOpenType *openType, QShaperItem *item, bool *ot_ok){ *ot_ok = true; openType->selectScript(item->script, item->script == QUnicodeTables::Arabic ? arabic_features : syriac_features); const int nglyphs = item->num_glyphs; if (!item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, &item->num_glyphs, QFlag(item->flags))) return false; heuristicSetGlyphAttributes(item); const unsigned short *uc = (const unsigned short *)item->string->unicode() + item->from; QVarLengthArray<QArabicProperties> props(item->length+2); QArabicProperties *properties = props.data(); int f = 0; int l = item->length; if (item->from > 0) { --f; ++l; ++properties; } if (f + l < item->string->length()) { ++l; } qt_getArabicProperties((const unsigned short *)(uc+f), l, props.data()); QVarLengthArray<uint> apply(item->num_glyphs); for (int i = 0; i < item->num_glyphs; i++) { apply[i] = 0; if (properties[i].shape == XIsolated) apply[i] |= MediProperty|FinaProperty|InitProperty; else if (properties[i].shape == XMedial) apply[i] |= IsolProperty|FinaProperty|InitProperty; else if (properties[i].shape == XFinal) apply[i] |= IsolProperty|MediProperty|InitProperty; else if (properties[i].shape == XInitial) apply[i] |= IsolProperty|MediProperty|FinaProperty; } if (!openType->shape(item, apply.data())) { *ot_ok = false; return false; } return openType->positionAndAdd(item, nglyphs);}#endif#ifndef Q_WS_MAC// #### stil missing: identify invalid character combinationsstatic bool arabic_shape(QShaperItem *item){ Q_ASSERT(item->script == QUnicodeTables::Arabic);#ifndef QT_NO_OPENTYPE QOpenType *openType = item->font->openType(); if (openType && openType->supportsScript(QUnicodeTables::Arabic)) { bool ot_ok; if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) return true; if (ot_ok) return false; // fall through to the non OT code }#endif QVarLengthArray<ushort> shapedChars(item->length); int slen; shapedString(item->string, item->from, item->length, (QChar *)shapedChars.data(), &slen, item->flags & QTextEngine::RightToLeft, item->glyphs, item->log_clusters); if (!item->font->stringToCMap((QChar *)shapedChars.data(), slen, item->glyphs, &item->num_glyphs, QFlag(item->flags))) return false; for (int i = 0; i < slen; ++i)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -