#include "qscriptengine_p.h"
#include "qdebug.h"
#include "qstring.h"
#include "qrect.h"
#include "qfont.h"
#include <private/qunicodetables_p.h>
#include "qtextengine_p.h"
#include "qfontengine_p.h"
#include <stdlib.h>
#include <qvarlengtharray.h>
#include "qopentype_p.h"
#include <qtextcodec.h>
#include <qlibrary.h>
Include dependency graph for qscriptengine.cpp:

Go to the source code of this file.
Classes | |
| struct | JoiningPair |
| struct | IndicOrdering |
Defines | |
| #define | IDEBUG if(0) qDebug |
| #define | KHDEBUG if(0) qDebug |
| #define | MMDEBUG if(0) qDebug |
Typedefs | |
| typedef unsigned long | KhmerCharClass |
| typedef int | MymrCharClass |
Enumerations | |
| enum | |
| enum | ArabicGroup |
| enum | Joining |
| enum | |
| enum | Form |
| enum | Position |
| enum | IndicScriptProperties |
| enum | IndicProperties |
| enum | TibetanForm |
| enum | KhmerCharClassValues |
| enum | KhmerCharClassFlags |
| enum | KhmerChar |
| enum | |
| enum | KhmerCharClassesRange |
| enum | MymrCharClassValues |
| enum | MymrCharClassFlags |
| enum | MymrChar |
| enum | |
| enum | |
| enum | HangulType |
Functions | |
| static void | positionCluster (QShaperItem *item, int gfrom, int glast) |
| void | qt_heuristicPosition (QShaperItem *item) |
| static void | heuristicSetGlyphAttributes (QShaperItem *item, const QChar *uc, int length) |
| static void | heuristicSetGlyphAttributes (QShaperItem *item) |
| static bool | basic_shape (QShaperItem *item) |
| static bool | hebrew_shape (QShaperItem *item) |
| static ArabicGroup | arabicGroup (unsigned short uc) |
| void | qt_getArabicProperties (const unsigned short *chars, int len, QArabicProperties *properties) |
| static int | getShape (uchar cell, int shape) |
| static const QChar | prevChar (const QString *str, int pos) |
| static const QChar | nextChar (const QString *str, int pos) |
| static void | shapedString (const QString *uc, int from, int len, QChar *shapeBuffer, int *shapedLength, bool reverse, QGlyphLayout *glyphs, unsigned short *logClusters) |
| static bool | arabicSyriacOpenTypeShape (QOpenType *openType, QShaperItem *item, bool *ot_ok) |
| static bool | arabic_shape (QShaperItem *item) |
| static bool | syriac_shape (QShaperItem *item) |
| static bool | thaana_shape (QShaperItem *item) |
| static Form | form (unsigned short uc) |
| static Position | indic_position (unsigned short uc) |
| static void | splitMatra (unsigned short *reordered, int matra, int &len, int &base) |
| static bool | indic_shape_syllable (QOpenType *openType, QShaperItem *item, bool invalid) |
| static int | indic_nextSyllableBoundary (int script, const QString &s, int start, int end, bool *invalid) |
| static bool | indic_shape (QShaperItem *item) |
| static void | indic_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
| static void | thaiWordBreaks (const QChar *string, const int len, QCharAttributes *attributes) |
| static void | thai_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
| static TibetanForm | tibetan_form (const QChar &c) |
| static bool | tibetan_shape_syllable (QOpenType *openType, QShaperItem *item, bool invalid) |
| static int | tibetan_nextSyllableBoundary (const QString &s, int start, int end, bool *invalid) |
| static bool | tibetan_shape (QShaperItem *item) |
| static void | tibetan_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
| static KhmerCharClass | getKhmerCharClass (const QChar &uc) |
| static int | khmer_nextSyllableBoundary (const QString &s, int start, int end, bool *invalid) |
| static bool | khmer_shape_syllable (QOpenType *openType, QShaperItem *item) |
| static bool | khmer_shape (QShaperItem *item) |
| static void | khmer_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
| static MymrCharClass | getMyanmarCharClass (const QChar &ch) |
| static int | myanmar_nextSyllableBoundary (const QString &s, int start, int end, bool *invalid) |
| static bool | myanmar_shape_syllable (QOpenType *openType, QShaperItem *item, bool invalid) |
| static bool | myanmar_shape (QShaperItem *item) |
| static void | myanmar_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
| static bool | hangul_isPrecomposed (unsigned short uc) |
| static bool | hangul_isLV (unsigned short uc) |
| static HangulType | hangul_type (unsigned short uc) |
| static int | hangul_nextSyllableBoundary (const QString &s, int start, int end) |
| static bool | hangul_shape_syllable (QOpenType *openType, QShaperItem *item) |
| static bool | hangul_shape (QShaperItem *item) |
| static void | hangul_attributes (int script, const QString &text, int from, int len, QCharAttributes *attributes) |
Variables | |
| static const QOpenType::Features | basic_features [] |
| static const QOpenType::Features | hebrew_features [] |
| static const unsigned char | arabic_group [0x150] |
| static const Joining | joining_for_group [ArabicGroupsEnd] |
| static const JoiningPair | joining_table [5][4] |
| static const ushort | arabicUnicodeMapping [256][2] |
| static const ushort | alefMaksura [4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9} |
| static const ushort | arabicUnicodeLamAlefMapping [6][4] |
| static const QOpenType::Features | arabic_features [] |
| static const QOpenType::Features | syriac_features [] |
| static const unsigned char | indicForms [0xe00-0x900] |
| static const unsigned char | indicPosition [0xe00-0x900] |
| const uchar | scriptProperties [10] |
| static const IndicOrdering | devanagari_order [] |
| static const IndicOrdering | bengali_order [] |
| static const IndicOrdering | gurmukhi_order [] |
| static const IndicOrdering | tamil_order [] |
| static const IndicOrdering | telugu_order [] |
| static const IndicOrdering | kannada_order [] |
| static const IndicOrdering | malayalam_order [] |
| static const IndicOrdering | sinhala_order [] |
| static const IndicOrdering *const | indic_order [] |
| static const unsigned short | split_matras [] |
| static const QOpenType::Features | indic_features [] |
| static const unsigned char | tibetanForm [0x80] |
| static const QOpenType::Features | tibetan_features [] |
| static const KhmerCharClass | khmerCharClasses [] |
| static const signed char | khmerStateTable [][CC_COUNT] |
| static const QOpenType::Features | khmer_features [] |
| static const MymrCharClass | mymrCharClasses [] |
| static const signed char | mymrStateTable [][Mymr_CC_COUNT] |
| static const QOpenType::Features | myanmar_features [] |
| static const QOpenType::Features | hangul_features [] |
| const q_scriptEngine | qt_scriptEngines [] |
| #define IDEBUG if(0) qDebug |
Definition at line 2741 of file qscriptengine.cpp.
Referenced by hangul_shape_syllable(), indic_nextSyllableBoundary(), indic_shape(), indic_shape_syllable(), tibetan_shape(), and tibetan_shape_syllable().
| #define KHDEBUG if(0) qDebug |
Definition at line 4028 of file qscriptengine.cpp.
Referenced by khmer_nextSyllableBoundary(), khmer_shape(), and khmer_shape_syllable().
| #define MMDEBUG if(0) qDebug |
Definition at line 4551 of file qscriptengine.cpp.
Referenced by myanmar_nextSyllableBoundary(), myanmar_shape(), and myanmar_shape_syllable().
| typedef unsigned long KhmerCharClass |
Definition at line 3878 of file qscriptengine.cpp.
| typedef int MymrCharClass |
Definition at line 4476 of file qscriptengine.cpp.
| anonymous enum |
| anonymous enum |
Definition at line 1450 of file qscriptengine.cpp.
01450 { 01451 InitProperty = 0x2, 01452 IsolProperty = 0x4, 01453 FinaProperty = 0x8, 01454 MediProperty = 0x10, 01455 RligProperty = 0x20, 01456 CaltProperty = 0x40, 01457 LigaProperty = 0x80, 01458 DligProperty = 0x100, 01459 CswhProperty = 0x200, 01460 MsetProperty = 0x400 01461 };
| anonymous enum |
Definition at line 3854 of file qscriptengine.cpp.
03854 { 03855 _xx = CC_RESERVED, 03856 _sa = CC_SIGN_ABOVE | CF_DOTTED_CIRCLE | CF_POS_ABOVE, 03857 _sp = CC_SIGN_AFTER | CF_DOTTED_CIRCLE| CF_POS_AFTER, 03858 _c1 = CC_CONSONANT | CF_CONSONANT, 03859 _c2 = CC_CONSONANT2 | CF_CONSONANT, 03860 _c3 = CC_CONSONANT3 | CF_CONSONANT, 03861 _rb = CC_ROBAT | CF_POS_ABOVE | CF_DOTTED_CIRCLE, 03862 _cs = CC_CONSONANT_SHIFTER | CF_DOTTED_CIRCLE | CF_SHIFTER, 03863 _dl = CC_DEPENDENT_VOWEL | CF_POS_BEFORE | CF_DOTTED_CIRCLE, 03864 _db = CC_DEPENDENT_VOWEL | CF_POS_BELOW | CF_DOTTED_CIRCLE, 03865 _da = CC_DEPENDENT_VOWEL | CF_POS_ABOVE | CF_DOTTED_CIRCLE | CF_ABOVE_VOWEL, 03866 _dr = CC_DEPENDENT_VOWEL | CF_POS_AFTER | CF_DOTTED_CIRCLE, 03867 _co = CC_COENG | CF_COENG | CF_DOTTED_CIRCLE, 03868 03869 // split vowel 03870 _va = _da | CF_SPLIT_VOWEL, 03871 _vr = _dr | CF_SPLIT_VOWEL 03872 };
| anonymous enum |
Definition at line 4454 of file qscriptengine.cpp.
04455 { 04456 Mymr_xx = Mymr_CC_RESERVED, 04457 Mymr_c1 = Mymr_CC_CONSONANT | Mymr_CF_CONSONANT | Mymr_CF_POS_BELOW, 04458 Mymr_c2 = Mymr_CC_CONSONANT2 | Mymr_CF_CONSONANT, 04459 Mymr_ng = Mymr_CC_NGA | Mymr_CF_CONSONANT | Mymr_CF_POS_ABOVE, 04460 Mymr_ya = Mymr_CC_YA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_AFTER | Mymr_CF_AFTER_KINZI, 04461 Mymr_ra = Mymr_CC_RA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BEFORE, 04462 Mymr_wa = Mymr_CC_WA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, 04463 Mymr_ha = Mymr_CC_HA | Mymr_CF_CONSONANT | Mymr_CF_MEDIAL | Mymr_CF_POS_BELOW, 04464 Mymr_id = Mymr_CC_IND_VOWEL | Mymr_CF_IND_VOWEL, 04465 Mymr_vi = Mymr_CC_VIRAMA | Mymr_CF_VIRAMA | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE, 04466 Mymr_dl = Mymr_CC_PRE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BEFORE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, 04467 Mymr_db = Mymr_CC_BELOW_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, 04468 Mymr_da = Mymr_CC_ABOVE_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, 04469 Mymr_dr = Mymr_CC_POST_VOWEL | Mymr_CF_DEP_VOWEL | Mymr_CF_POS_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI, 04470 Mymr_sa = Mymr_CC_SIGN_ABOVE | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_ABOVE | Mymr_CF_AFTER_KINZI, 04471 Mymr_sb = Mymr_CC_SIGN_BELOW | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_POS_BELOW | Mymr_CF_AFTER_KINZI, 04472 Mymr_sp = Mymr_CC_SIGN_AFTER | Mymr_CF_DOTTED_CIRCLE | Mymr_CF_AFTER_KINZI 04473 };
| anonymous enum |
Definition at line 4929 of file qscriptengine.cpp.
04929 { 04930 Hangul_SBase = 0xac00, 04931 Hangul_LBase = 0x1100, 04932 Hangul_VBase = 0x1161, 04933 Hangul_TBase = 0x11a7, 04934 Hangul_SCount = 11172, 04935 Hangul_LCount = 19, 04936 Hangul_VCount = 21, 04937 Hangul_TCount = 28, 04938 Hangul_NCount = 21*28 04939 };
| enum ArabicGroup |
Definition at line 560 of file qscriptengine.cpp.
00560 { 00561 // NonJoining 00562 ArabicNone, 00563 ArabicSpace, 00564 // Transparent 00565 Transparent, 00566 // Causing 00567 Center, 00568 Kashida, 00569 00570 // Arabic 00571 // Dual 00572 Beh, 00573 Noon, 00574 Meem = Noon, 00575 Heh = Noon, 00576 KnottedHeh = Noon, 00577 HehGoal = Noon, 00578 SwashKaf = Noon, 00579 Yeh, 00580 Hah, 00581 Seen, 00582 Sad = Seen, 00583 Tah, 00584 Kaf = Tah, 00585 Gaf = Tah, 00586 Lam = Tah, 00587 Ain, 00588 Feh = Ain, 00589 Qaf = Ain, 00590 // Right 00591 Alef, 00592 Waw, 00593 Dal, 00594 TehMarbuta = Dal, 00595 Reh, 00596 HamzaOnHehGoal, 00597 YehWithTail = HamzaOnHehGoal, 00598 YehBarre = HamzaOnHehGoal, 00599 00600 // Syriac 00601 // Dual 00602 Beth = Beh, 00603 Gamal = Ain, 00604 Heth = Noon, 00605 Teth = Hah, 00606 Yudh = Noon, 00607 Kaph = Noon, 00608 Lamadh = Lam, 00609 Mim = Noon, 00610 Nun = Noon, 00611 Semakh = Noon, 00612 FinalSemakh = Noon, 00613 SyriacE = Ain, 00614 Pe = Ain, 00615 ReversedPe = Hah, 00616 Qaph = Noon, 00617 Shin = Noon, 00618 Fe = Ain, 00619 00620 // Right 00621 Alaph = Alef, 00622 Dalath = Dal, 00623 He = Dal, 00624 SyriacWaw = Waw, 00625 Zain = Alef, 00626 YudhHe = Waw, 00627 Sadhe = HamzaOnHehGoal, 00628 Taw = Dal, 00629 00630 // Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. 00631 Dummy = HamzaOnHehGoal, 00632 ArabicGroupsEnd 00633 };
| enum Form |
Definition at line 1636 of file qscriptengine.cpp.
01636 { 01637 Invalid = 0x0, 01638 UnknownForm = Invalid, 01639 Consonant, 01640 Nukta, 01641 Halant, 01642 Matra, 01643 VowelMark, 01644 StressMark, 01645 IndependentVowel, 01646 LengthMark, 01647 Control, 01648 Other 01649 };
| enum HangulType |
| enum IndicProperties |
Definition at line 2696 of file qscriptengine.cpp.
02696 { 02697 // these two are already defined 02698 // CcmpProperty = 0x1, 02699 // InitProperty = 0x2, 02700 NuktaProperty = 0x4, 02701 AkhantProperty = 0x8, 02702 RephProperty = 0x10, 02703 PreFormProperty = 0x20, 02704 BelowFormProperty = 0x40, 02705 AboveFormProperty = 0x80, 02706 HalfFormProperty = 0x100, 02707 PostFormProperty = 0x200, 02708 VattuProperty = 0x400, 02709 PreSubstProperty = 0x800, 02710 BelowSubstProperty = 0x1000, 02711 AboveSubstProperty = 0x2000, 02712 PostSubstProperty = 0x4000, 02713 HalantProperty = 0x8000, 02714 CligProperty = 0x10000 02715 };
| enum Joining |
Definition at line 792 of file qscriptengine.cpp.
00792 { 00793 JNone, 00794 JCausing, 00795 JDual, 00796 JRight, 00797 JTransparent 00798 };
| enum KhmerChar |
Definition at line 3837 of file qscriptengine.cpp.
03837 { 03838 C_SIGN_ZWNJ = 0x200C, 03839 C_SIGN_ZWJ = 0x200D, 03840 C_DOTTED_CIRCLE = 0x25CC, 03841 C_RO = 0x179A, 03842 C_VOWEL_AA = 0x17B6, 03843 C_SIGN_NIKAHIT = 0x17C6, 03844 C_VOWEL_E = 0x17C1, 03845 C_COENG = 0x17D2 03846 };
Definition at line 3909 of file qscriptengine.cpp.
03909 { 03910 KhmerFirstChar = 0x1780, 03911 KhmerLastChar = 0x17df 03912 };
| enum KhmerCharClassFlags |
Definition at line 3817 of file qscriptengine.cpp.
03817 { 03818 CF_CLASS_MASK = 0x0000FFFF, 03819 03820 CF_CONSONANT = 0x01000000, // flag to speed up comparing 03821 CF_SPLIT_VOWEL = 0x02000000, // flag for a split vowel -> the first part is added in front of the syllable 03822 CF_DOTTED_CIRCLE = 0x04000000, // add a dotted circle if a character with this flag is the first in a syllable 03823 CF_COENG = 0x08000000, // flag to speed up comparing 03824 CF_SHIFTER = 0x10000000, // flag to speed up comparing 03825 CF_ABOVE_VOWEL = 0x20000000, // flag to speed up comparing 03826 03827 // position flags 03828 CF_POS_BEFORE = 0x00080000, 03829 CF_POS_BELOW = 0x00040000, 03830 CF_POS_ABOVE = 0x00020000, 03831 CF_POS_AFTER = 0x00010000, 03832 CF_POS_MASK = 0x000f0000 03833 };
| enum KhmerCharClassValues |
Definition at line 3800 of file qscriptengine.cpp.
03800 { 03801 CC_RESERVED = 0, 03802 CC_CONSONANT = 1, // Consonant of type 1 or independent vowel 03803 CC_CONSONANT2 = 2, // Consonant of type 2 03804 CC_CONSONANT3 = 3, // Consonant of type 3 03805 CC_ZERO_WIDTH_NJ_MARK = 4, // Zero Width non joiner character (0x200C) 03806 CC_CONSONANT_SHIFTER = 5, 03807 CC_ROBAT = 6, // Khmer special diacritic accent -treated differently in state table 03808 CC_COENG = 7, // Subscript consonant combining character 03809 CC_DEPENDENT_VOWEL = 8, 03810 CC_SIGN_ABOVE = 9, 03811 CC_SIGN_AFTER = 10, 03812 CC_ZERO_WIDTH_J_MARK = 11, // Zero width joiner character 03813 CC_COUNT = 12 // This is the number of character classes 03814 };
| enum MymrChar |
Definition at line 4442 of file qscriptengine.cpp.
04443 { 04444 Mymr_C_SIGN_ZWNJ = 0x200C, 04445 Mymr_C_SIGN_ZWJ = 0x200D, 04446 Mymr_C_DOTTED_CIRCLE = 0x25CC, 04447 Mymr_C_RA = 0x101B, 04448 Mymr_C_YA = 0x101A, 04449 Mymr_C_NGA = 0x1004, 04450 Mymr_C_VOWEL_E = 0x1031, 04451 Mymr_C_VIRAMA = 0x1039 04452 };
| enum MymrCharClassFlags |
Definition at line 4420 of file qscriptengine.cpp.
04421 { 04422 Mymr_CF_CLASS_MASK = 0x0000FFFF, 04423 04424 Mymr_CF_CONSONANT = 0x01000000, /* flag to speed up comparing */ 04425 Mymr_CF_MEDIAL = 0x02000000, /* flag to speed up comparing */ 04426 Mymr_CF_IND_VOWEL = 0x04000000, /* flag to speed up comparing */ 04427 Mymr_CF_DEP_VOWEL = 0x08000000, /* flag to speed up comparing */ 04428 Mymr_CF_DOTTED_CIRCLE = 0x10000000, /* add a dotted circle if a character with this flag is the first in a syllable */ 04429 Mymr_CF_VIRAMA = 0x20000000, /* flag to speed up comparing */ 04430 04431 /* position flags */ 04432 Mymr_CF_POS_BEFORE = 0x00080000, 04433 Mymr_CF_POS_BELOW = 0x00040000, 04434 Mymr_CF_POS_ABOVE = 0x00020000, 04435 Mymr_CF_POS_AFTER = 0x00010000, 04436 Mymr_CF_POS_MASK = 0x000f0000, 04437 04438 Mymr_CF_AFTER_KINZI = 0x00100000 04439 };
| enum MymrCharClassValues |
Definition at line 4396 of file qscriptengine.cpp.
04397 { 04398 Mymr_CC_RESERVED = 0, 04399 Mymr_CC_CONSONANT = 1, /* Consonant of type 1, that has subscript form */ 04400 Mymr_CC_CONSONANT2 = 2, /* Consonant of type 2, that has no subscript form */ 04401 Mymr_CC_NGA = 3, /* Consonant NGA */ 04402 Mymr_CC_YA = 4, /* Consonant YA */ 04403 Mymr_CC_RA = 5, /* Consonant RA */ 04404 Mymr_CC_WA = 6, /* Consonant WA */ 04405 Mymr_CC_HA = 7, /* Consonant HA */ 04406 Mymr_CC_IND_VOWEL = 8, /* Independent vowel */ 04407 Mymr_CC_ZERO_WIDTH_NJ_MARK = 9, /* Zero Width non joiner character (0x200C) */ 04408 Mymr_CC_VIRAMA = 10, /* Subscript consonant combining character */ 04409 Mymr_CC_PRE_VOWEL = 11, /* Dependent vowel, prebase (Vowel e) */ 04410 Mymr_CC_BELOW_VOWEL = 12, /* Dependent vowel, prebase (Vowel u, uu) */ 04411 Mymr_CC_ABOVE_VOWEL = 13, /* Dependent vowel, prebase (Vowel i, ii, ai) */ 04412 Mymr_CC_POST_VOWEL = 14, /* Dependent vowel, prebase (Vowel aa) */ 04413 Mymr_CC_SIGN_ABOVE = 15, 04414 Mymr_CC_SIGN_BELOW = 16, 04415 Mymr_CC_SIGN_AFTER = 17, 04416 Mymr_CC_ZERO_WIDTH_J_MARK = 18, /* Zero width joiner character */ 04417 Mymr_CC_COUNT = 19 /* This is the number of character classes */ 04418 };
| enum Position |
| enum TibetanForm |
Definition at line 3521 of file qscriptengine.cpp.
03521 { 03522 TibetanOther, 03523 TibetanHeadConsonant, 03524 TibetanSubjoinedConsonant, 03525 TibetanSubjoinedVowel, 03526 TibetanVowel 03527 };
| static bool arabic_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 1547 of file qscriptengine.cpp.
References QGlyphLayout::advance, QUnicodeTables::Arabic, arabicSyriacOpenTypeShape(), QGlyphLayout::attributes, QVarLengthArray< T, Prealloc >::data(), QShaperItem::flags, QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, i, QShaperItem::length, QShaperItem::log_clusters, QShaperItem::num_glyphs, openType, QFontEngine::openType(), qt_heuristicPosition(), QTextEngine::RightToLeft, QShaperItem::script, shapedString(), QShaperItem::string, and QFontEngine::stringToCMap().
01548 { 01549 Q_ASSERT(item->script == QUnicodeTables::Arabic); 01550 01551 #ifndef QT_NO_OPENTYPE 01552 QOpenType *openType = item->font->openType(); 01553 01554 if (openType && openType->supportsScript(QUnicodeTables::Arabic)) { 01555 bool ot_ok; 01556 if (arabicSyriacOpenTypeShape(openType, item, &ot_ok)) 01557 return true; 01558 if (ot_ok) 01559 return false; 01560 // fall through to the non OT code 01561 } 01562 #endif 01563 01564 QVarLengthArray<ushort> shapedChars(item->length); 01565 01566 int slen; 01567 shapedString(item->string, item->from, item->length, (QChar *)shapedChars.data(), &slen, 01568 item->flags & QTextEngine::RightToLeft, 01569 item->glyphs, item->log_clusters); 01570 01571 if (!item->font->stringToCMap((QChar *)shapedChars.data(), slen, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 01572 return false; 01573 01574 for (int i = 0; i < slen; ++i) 01575 if (item->glyphs[i].attributes.mark) 01576 item->glyphs[i].advance = QFixedPoint(); 01577 qt_heuristicPosition(item); 01578 return true; 01579 }
Here is the call graph for this function:

| static ArabicGroup arabicGroup | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 746 of file qscriptengine.cpp.
References ArabicNone, ArabicSpace, QUnicodeTables::category(), Center, and QChar::Separator_Space.
Referenced by qt_getArabicProperties().
00747 { 00748 if (uc >= 0x0600 && uc < 0x750) 00749 return (ArabicGroup) arabic_group[uc-0x600]; 00750 else if (uc == 0x200d) 00751 return Center; 00752 else if (QUnicodeTables::category(uc) == QChar::Separator_Space) 00753 return ArabicSpace; 00754 else 00755 return ArabicNone; 00756 }
Here is the call graph for this function:

| static bool arabicSyriacOpenTypeShape | ( | QOpenType * | openType, | |
| QShaperItem * | item, | |||
| bool * | ot_ok | |||
| ) | [static] |
Definition at line 1495 of file qscriptengine.cpp.
References QUnicodeTables::Arabic, arabic_features, FinaProperty, QShaperItem::flags, QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, heuristicSetGlyphAttributes(), i, InitProperty, IsolProperty, l, QShaperItem::length, MediProperty, QShaperItem::num_glyphs, openType, properties, props, qt_getArabicProperties(), QShaperItem::script, QShaperItem::string, QFontEngine::stringToCMap(), syriac_features, QString::unicode(), XFinal, XInitial, XIsolated, and XMedial.
Referenced by arabic_shape(), and syriac_shape().
01496 { 01497 *ot_ok = true; 01498 01499 openType->selectScript(item, item->script, item->script == QUnicodeTables::Arabic ? arabic_features : syriac_features); 01500 const int nglyphs = item->num_glyphs; 01501 if (!item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 01502 return false; 01503 heuristicSetGlyphAttributes(item); 01504 01505 const unsigned short *uc = (const unsigned short *)item->string->unicode() + item->from; 01506 01507 QVarLengthArray<QArabicProperties> props(item->length+2); 01508 QArabicProperties *properties = props.data(); 01509 int f = 0; 01510 int l = item->length; 01511 if (item->from > 0) { 01512 --f; 01513 ++l; 01514 ++properties; 01515 } 01516 if (f + l < item->string->length()) { 01517 ++l; 01518 } 01519 qt_getArabicProperties((const unsigned short *)(uc+f), l, props.data()); 01520 01521 QVarLengthArray<uint> apply(item->num_glyphs); 01522 01523 for (int i = 0; i < item->num_glyphs; i++) { 01524 apply[i] = 0; 01525 01526 if (properties[i].shape == XIsolated) 01527 apply[i] |= MediProperty|FinaProperty|InitProperty; 01528 else if (properties[i].shape == XMedial) 01529 apply[i] |= IsolProperty|FinaProperty|InitProperty; 01530 else if (properties[i].shape == XFinal) 01531 apply[i] |= IsolProperty|MediProperty|InitProperty; 01532 else if (properties[i].shape == XInitial) 01533 apply[i] |= IsolProperty|MediProperty|FinaProperty; 01534 } 01535 01536 if (!openType->shape(item, apply.data())) { 01537 *ot_ok = false; 01538 return false; 01539 } 01540 return openType->positionAndAdd(item, nglyphs); 01541 }
Here is the call graph for this function:

| static bool basic_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 356 of file qscriptengine.cpp.
References QShaperItem::flags, QShaperItem::font, QShaperItem::from, QGlyphLayout::glyph, QShaperItem::glyphs, heuristicSetGlyphAttributes(), i, QShaperItem::length, QFontEngine::Multi, QShaperItem::num_glyphs, openType, QFontEngine::openType(), QShaperItem::string, QFontEngine::stringToCMap(), QFontEngine::type(), and QString::unicode().
Referenced by hangul_shape(), syriac_shape(), and thaana_shape().
00357 { 00358 00359 #ifndef QT_NO_OPENTYPE 00360 const int availableGlyphs = item->num_glyphs; 00361 #endif 00362 00363 if (!item->font->stringToCMap(item->string->unicode()+item->from, item->length, 00364 item->glyphs, &item->num_glyphs, QFlag(item->flags))) 00365 return false; 00366 heuristicSetGlyphAttributes(item); 00367 00368 #ifndef QT_NO_OPENTYPE 00369 QOpenType *openType = item->font->openType(); 00370 if (!openType && item->font->type() == QFontEngine::Multi) { 00371 openType = static_cast<QFontEngineMulti *>(item->font)->engine(0)->openType(); 00372 if (openType) { 00373 for (int i = 0; i < item->num_glyphs; ++i) { 00374 if (item->glyphs[i].glyph & 0xff000000) { 00375 openType = 0; 00376 break; 00377 } 00378 } 00379 } 00380 } 00381 if (openType && openType->supportsScript(item->script)) { 00382 openType->selectScript(item, item->script, basic_features); 00383 00384 openType->shape(item); 00385 return openType->positionAndAdd(item, availableGlyphs); 00386 } 00387 00388 #endif 00389 00390 qt_heuristicPosition(item); 00391 return true; 00392 }
Here is the call graph for this function:

| static Form form | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 2488 of file qscriptengine.cpp.
References Consonant, and Control.
Referenced by QString::arg(), QView3DWidget::beginAddingWidgets(), qdesigner_internal::BuddyEditor::BuddyEditor(), canBeBuddy(), qdesigner_internal::classList(), qdesigner_internal::ConnectionEdit::ConnectionEdit(), Ui3Reader::createFormImpl(), createReadHandler(), MultiPageWidgetPlugin::currentIndexChanged(), qdesigner_internal::FindIconDialog::defaultFilePath(), qdesigner_internal::FormWindowDnDItem::domUi(), qdesigner_internal::FindIconDialog::FindIconDialog(), indic_nextSyllableBoundary(), indic_shape_syllable(), qdesigner_internal::ListWidgetEditor::ListWidgetEditor(), qdesigner_internal::memberList(), qdesigner_internal::merge(), qdesigner_internal::objectNameList(), qdesigner_internal::NewActionDialog::on_iconButton_clicked(), qdesigner_internal::OrderDialog::OrderDialog(), MultiPageWidgetPlugin::pageTitleChanged(), qdesigner_internal::GraphicsPropertyEditor::populateCombo(), qdesigner_internal::PropertyEditor::resetProperty(), qdesigner_internal::SignalSlotEditorWindow::setActiveFormWindow(), qdesigner_internal::ConnectionModel::setData(), qdesigner_internal::ConnectionDelegate::setForm(), QString::setNum(), QByteArray::setNum(), qdesigner_internal::GraphicsPropertyEditor::showDialog(), qdesigner_internal::TableWidgetEditor::TableWidgetEditor(), qdesigner_internal::TabOrderEditor::TabOrderEditor(), QLocale::toString(), qdesigner_internal::TreeWidgetEditor::TreeWidgetEditor(), QString::vsprintf(), and widgetToDom().
02488 { 02489 if (uc < 0x900 || uc > 0xdff) { 02490 if (uc == 0x25cc) 02491 return Consonant; 02492 if (uc == 0x200c || uc == 0x200d) 02493 return Control; 02494 return Other; 02495 } 02496 return (Form)indicForms[uc-0x900]; 02497 }
| static KhmerCharClass getKhmerCharClass | ( | const QChar & | uc | ) | [inline, static] |
Definition at line 3919 of file qscriptengine.cpp.
References C_SIGN_ZWJ, C_SIGN_ZWNJ, CC_RESERVED, CC_ZERO_WIDTH_J_MARK, CC_ZERO_WIDTH_NJ_MARK, KhmerFirstChar, KhmerLastChar, and QChar::unicode().
Referenced by khmer_nextSyllableBoundary(), and khmer_shape_syllable().
03920 { 03921 if (uc.unicode() == C_SIGN_ZWJ) { 03922 return CC_ZERO_WIDTH_J_MARK; 03923 } 03924 03925 if (uc.unicode() == C_SIGN_ZWNJ) { 03926 return CC_ZERO_WIDTH_NJ_MARK; 03927 } 03928 03929 if (uc.unicode() < KhmerFirstChar || uc.unicode() > KhmerLastChar) { 03930 return CC_RESERVED; 03931 } 03932 03933 return khmerCharClasses[uc.unicode() - KhmerFirstChar]; 03934 }
Here is the call graph for this function:

| static MymrCharClass getMyanmarCharClass | ( | const QChar & | ch | ) | [static] |
Definition at line 4496 of file qscriptengine.cpp.
References Mymr_C_SIGN_ZWJ, Mymr_C_SIGN_ZWNJ, Mymr_CC_RESERVED, Mymr_CC_ZERO_WIDTH_J_MARK, Mymr_CC_ZERO_WIDTH_NJ_MARK, and QChar::unicode().
Referenced by myanmar_nextSyllableBoundary(), and myanmar_shape_syllable().
04497 { 04498 if (ch.unicode() == Mymr_C_SIGN_ZWJ) 04499 return Mymr_CC_ZERO_WIDTH_J_MARK; 04500 04501 if (ch.unicode() == Mymr_C_SIGN_ZWNJ) 04502 return Mymr_CC_ZERO_WIDTH_NJ_MARK; 04503 04504 if (ch.unicode() < 0x1000 || ch.unicode() > 0x105f) 04505 return Mymr_CC_RESERVED; 04506 04507 return mymrCharClasses[ch.unicode() - 0x1000]; 04508 }
Here is the call graph for this function:

| static int getShape | ( | uchar | cell, | |
| int | shape | |||
| ) | [inline, static] |
Definition at line 1298 of file qscriptengine.cpp.
Referenced by shapedString().
01299 { 01300 // the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, handle this here 01301 uint ch = (cell != 0x49) 01302 ? (shape ? arabicUnicodeMapping[cell][0] + shape : 0x600+cell) 01303 : alefMaksura[shape] ; 01304 return ch; 01305 }
| static void hangul_attributes | ( | int | script, | |
| const QString & | text, | |||
| int | from, | |||
| int | len, | |||
| QCharAttributes * | attributes | |||
| ) | [static] |
Definition at line 5140 of file qscriptengine.cpp.
References QCharAttributes::charStop, hangul_nextSyllableBoundary(), i, and QString::unicode().
05141 { 05142 Q_UNUSED(script); 05143 05144 int end = from + len; 05145 const QChar *uc = text.unicode() + from; 05146 attributes += from; 05147 int i = 0; 05148 while (i < len) { 05149 int boundary = hangul_nextSyllableBoundary(text, from+i, end) - from; 05150 05151 attributes[i].charStop = true; 05152 05153 if (boundary > len-1) boundary = len; 05154 i++; 05155 while (i < boundary) { 05156 attributes[i].charStop = false; 05157 ++uc; 05158 ++i; 05159 } 05160 assert(i == boundary); 05161 } 05162 }
Here is the call graph for this function:

| static bool hangul_isLV | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 4945 of file qscriptengine.cpp.
References Hangul_SBase, and Hangul_TCount.
Referenced by hangul_type().
04945 { 04946 return ((uc - Hangul_SBase) % Hangul_TCount == 0); 04947 }
| static bool hangul_isPrecomposed | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 4941 of file qscriptengine.cpp.
References Hangul_SBase, and Hangul_SCount.
Referenced by hangul_shape().
04941 { 04942 return (uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount); 04943 }
| static int hangul_nextSyllableBoundary | ( | const QString & | s, | |
| int | start, | |||
| int | end | |||
| ) | [static] |
Definition at line 4970 of file qscriptengine.cpp.
References hangul_type(), L, LV, LVT, s, T, QChar::unicode(), and V.
Referenced by hangul_attributes(), and hangul_shape().
04971 { 04972 const QChar *uc = s.unicode() + start; 04973 04974 HangulType state = hangul_type(uc->unicode()); 04975 int pos = 1; 04976 04977 while (pos < end - start) { 04978 HangulType newState = hangul_type(uc[pos].unicode()); 04979 switch(newState) { 04980 case X: 04981 goto finish; 04982 case L: 04983 case V: 04984 case T: 04985 if (state > newState) 04986 goto finish; 04987 state = newState; 04988 break; 04989 case LV: 04990 if (state > L) 04991 goto finish; 04992 state = V; 04993 break; 04994 case LVT: 04995 if (state > L) 04996 goto finish; 04997 state = T; 04998 } 04999 ++pos; 05000 } 05001 05002 finish: 05003 return start+pos; 05004 }
Here is the call graph for this function:

| static bool hangul_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 5083 of file qscriptengine.cpp.
References basic_shape(), QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, QUnicodeTables::Hangul, hangul_features, hangul_isPrecomposed(), hangul_nextSyllableBoundary(), hangul_shape_syllable(), i, QShaperItem::length, QShaperItem::num_glyphs, openType, QFontEngine::openType(), QShaperItem::script, QOpenType::selectScript(), QShaperItem::string, and QString::unicode().
05084 { 05085 Q_ASSERT(item->script == QUnicodeTables::Hangul); 05086 05087 const QChar *uc = item->string->unicode() + item->from; 05088 05089 bool allPrecomposed = true; 05090 for (int i = 0; i < item->length; ++i) { 05091 if (!hangul_isPrecomposed(uc[i].unicode())) { 05092 allPrecomposed = false; 05093 break; 05094 } 05095 } 05096 05097 if (!allPrecomposed) { 05098 #ifndef QT_NO_OPENTYPE 05099 QOpenType *openType = item->font->openType(); 05100 if (openType && !openType->supportsScript(item->script)) 05101 openType = 0; 05102 if (openType) 05103 openType->selectScript(item, QUnicodeTables::Hangul, hangul_features); 05104 #else 05105 QOpenType *openType = 0; 05106 #endif 05107 05108 unsigned short *logClusters = item->log_clusters; 05109 05110 QShaperItem syllable = *item; 05111 int first_glyph = 0; 05112 05113 int sstart = item->from; 05114 int end = sstart + item->length; 05115 while (sstart < end) { 05116 int send = hangul_nextSyllableBoundary(*(item->string), sstart, end); 05117 05118 syllable.from = sstart; 05119 syllable.length = send-sstart; 05120 syllable.glyphs = item->glyphs + first_glyph; 05121 syllable.num_glyphs = item->num_glyphs - first_glyph; 05122 if (!hangul_shape_syllable(openType, &syllable)) { 05123 item->num_glyphs += syllable.num_glyphs; 05124 return false; 05125 } 05126 // fix logcluster array 05127 for (int i = sstart; i < send; ++i) 05128 logClusters[i-item->from] = first_glyph; 05129 sstart = send; 05130 first_glyph += syllable.num_glyphs; 05131 } 05132 item->num_glyphs = first_glyph; 05133 return true; 05134 } 05135 05136 return basic_shape(item); 05137 }
Here is the call graph for this function:

| static bool hangul_shape_syllable | ( | QOpenType * | openType, | |
| QShaperItem * | item | |||
| ) | [static] |
Definition at line 5017 of file qscriptengine.cpp.
References QGlyphLayout::attributes, c, QShaperItem::flags, QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, Hangul_LBase, Hangul_LCount, Hangul_SBase, Hangul_TBase, Hangul_TCount, Hangul_VBase, Hangul_VCount, i, IDEBUG, QShaperItem::length, QShaperItem::log_clusters, QShaperItem::num_glyphs, openType, QShaperItem::string, QFontEngine::stringToCMap(), QString::unicode(), and QChar::unicode().
Referenced by hangul_shape().
05018 { 05019 Q_UNUSED(openType) 05020 const QChar *ch = item->string->unicode() + item->from; 05021 05022 int i; 05023 unsigned short composed = 0; 05024 // see if we can compose the syllable into a modern hangul 05025 if (item->length == 2) { 05026 int LIndex = ch[0].unicode() - Hangul_LBase; 05027 int VIndex = ch[1].unicode() - Hangul_VBase; 05028 if (LIndex >= 0 && LIndex < Hangul_LCount && 05029 VIndex >= 0 && VIndex < Hangul_VCount) 05030 composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase; 05031 } else if (item->length == 3) { 05032 int LIndex = ch[0].unicode() - Hangul_LBase; 05033 int VIndex = ch[1].unicode() - Hangul_VBase; 05034 int TIndex = ch[2].unicode() - Hangul_TBase; 05035 if (LIndex >= 0 && LIndex < Hangul_LCount && 05036 VIndex >= 0 && VIndex < Hangul_VCount && 05037 TIndex >= 0 && TIndex < Hangul_TCount) 05038 composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase; 05039 } 05040 05041 05042 int len = item->length; 05043 QChar c(composed); 05044 05045 // if we have a modern hangul use the composed form 05046 if (composed) { 05047 // chars = &c; 05048 len = 1; 05049 } 05050 05051 #ifndef QT_NO_OPENTYPE 05052 const int availableGlyphs = item->num_glyphs; 05053 #endif 05054 if (!item->font->stringToCMap(ch, len, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 05055 return false; 05056 for (i = 0; i < len; i++) { 05057 item->glyphs[i].attributes.mark = false; 05058 item->glyphs[i].attributes.clusterStart = false; 05059 item->glyphs[i].attributes.justification = 0; 05060 item->glyphs[i].attributes.zeroWidth = false; 05061 IDEBUG(" %d: %4x", i, ch[i].unicode()); 05062 } 05063 05064 #ifndef QT_NO_OPENTYPE 05065 if (openType && !composed) { 05066 05067 QVarLengthArray<unsigned short> logClusters(len); 05068 for (i = 0; i < len; ++i) 05069 logClusters[i] = i; 05070 item->log_clusters = logClusters.data(); 05071 05072 openType->shape(item); 05073 if (!openType->positionAndAdd(item, availableGlyphs, false)) 05074 return false; 05075 05076 } 05077 #endif 05078 05079 item->glyphs[0].attributes.clusterStart = true; 05080 return true; 05081 }
Here is the call graph for this function:

| static HangulType hangul_type | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 4958 of file qscriptengine.cpp.
References hangul_isLV(), Hangul_SBase, Hangul_SCount, Hangul_TBase, Hangul_VBase, L, LV, LVT, T, and V.
Referenced by hangul_nextSyllableBoundary().
04958 { 04959 if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount) 04960 return hangul_isLV(uc) ? LV : LVT; 04961 if (uc < Hangul_LBase || uc > 0x11ff) 04962 return X; 04963 if (uc < Hangul_VBase) 04964 return L; 04965 if (uc < Hangul_TBase) 04966 return V; 04967 return T; 04968 }
Here is the call graph for this function:

| static bool hebrew_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 414 of file qscriptengine.cpp.
References QGlyphLayout::advance, QGlyphLayout::attributes, base, QFontEngine::canRender(), QUnicodeTables::category(), QUnicodeTables::combiningClass(), QShaperItem::flags, QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, QUnicodeTables::Hebrew, hebrew_features, heuristicSetGlyphAttributes(), i, QShaperItem::length, QShaperItem::log_clusters, QChar::Mark_NonSpacing, QShaperItem::num_glyphs, openType, QFontEngine::openType(), qIsControlChar(), QShaperItem::script, QShaperItem::string, QFontEngine::stringToCMap(), QString::unicode(), and QFixedPoint::x.
00415 { 00416 Q_ASSERT(item->script == QUnicodeTables::Hebrew); 00417 00418 #ifndef QT_NO_OPENTYPE 00419 QOpenType *openType = item->font->openType(); 00420 00421 if (openType && openType->supportsScript(item->script)) { 00422 openType->selectScript(item, item->script, hebrew_features); 00423 00424 const int availableGlyphs = item->num_glyphs; 00425 if (!item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 00426 return false; 00427 00428 heuristicSetGlyphAttributes(item); 00429 openType->shape(item); 00430 return openType->positionAndAdd(item, availableGlyphs); 00431 } 00432 #endif 00433 00434 enum { 00435 Dagesh = 0x5bc, 00436 ShinDot = 0x5c1, 00437 SinDot = 0x5c2, 00438 Patah = 0x5b7, 00439 Qamats = 0x5b8, 00440 Holam = 0x5b9, 00441 Rafe = 0x5bf 00442 }; 00443 unsigned short chars[512]; 00444 QChar *shapedChars = item->length > 256 ? (QChar *)::malloc(2*item->length * sizeof(QChar)) : (QChar *)chars; 00445 00446 const QChar *uc = item->string->unicode() + item->from; 00447 unsigned short *logClusters = item->log_clusters; 00448 QGlyphLayout *glyphs = item->glyphs; 00449 00450 *shapedChars = *uc; 00451 logClusters[0] = 0; 00452 int slen = 1; 00453 int cluster_start = 0; 00454 for (int i = 1; i < item->length; ++i) { 00455 ushort base = shapedChars[slen-1].unicode(); 00456 ushort shaped = 0; 00457 bool invalid = false; 00458 if (uc[i].unicode() == Dagesh) { 00459 if (base >= 0x5d0 00460 && base <= 0x5ea 00461 && base != 0x5d7 00462 && base != 0x5dd 00463 && base != 0x5df 00464 && base != 0x5e2 00465 && base != 0x5e5) { 00466 shaped = base - 0x5d0 + 0xfb30; 00467 } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) { 00468 shaped = base + 2; 00469 } else { 00470 invalid = true; 00471 } 00472 } else if (uc[i].unicode() == ShinDot) { 00473 if (base == 0x05e9) 00474 shaped = 0xfb2a; 00475 else if (base == 0xfb49) 00476 shaped = 0xfb2c; 00477 else 00478 invalid = true; 00479 } else if (uc[i].unicode() == SinDot) { 00480 if (base == 0x05e9) 00481 shaped = 0xfb2b; 00482 else if (base == 0xfb49) 00483 shaped = 0xfb2d; 00484 else 00485 invalid = true; 00486 } else if (uc[i].unicode() == Patah) { 00487 if (base == 0x5d0) 00488 shaped = 0xfb2e; 00489 } else if (uc[i].unicode() == Qamats) { 00490 if (base == 0x5d0) 00491 shaped = 0xfb2f; 00492 } else if (uc[i].unicode() == Holam) { 00493 if (base == 0x5d5) 00494 shaped = 0xfb4b; 00495 } else if (uc[i].unicode() == Rafe) { 00496 if (base == 0x5d1) 00497 shaped = 0xfb4c; 00498 else if (base == 0x5db) 00499 shaped = 0xfb4d; 00500 else if (base == 0x5e4) 00501 shaped = 0xfb4e; 00502 } 00503 00504 if (invalid) { 00505 shapedChars[slen] = 0x25cc; 00506 glyphs[slen].attributes.clusterStart = true; 00507 glyphs[slen].attributes.mark = false; 00508 glyphs[slen].attributes.combiningClass = 0; 00509 cluster_start = slen; 00510 ++slen; 00511 } 00512 if (shaped) { 00513 if (item->font->canRender((QChar *)&shaped, 1)) { 00514 shapedChars[slen-1] = QChar(shaped); 00515 } else 00516 shaped = 0; 00517 } 00518 if (!shaped) { 00519 shapedChars[slen] = uc[i]; 00520 if (QUnicodeTables::category(uc[i]) != QChar::Mark_NonSpacing) { 00521 glyphs[slen].attributes.clusterStart = true; 00522 glyphs[slen].attributes.mark = false; 00523 glyphs[slen].attributes.combiningClass = 0; 00524 glyphs[slen].attributes.dontPrint = qIsControlChar(uc[i].unicode()); 00525 cluster_start = slen; 00526 } else { 00527 glyphs[slen].attributes.clusterStart = false; 00528 glyphs[slen].attributes.mark = true; 00529 glyphs[slen].attributes.combiningClass = QUnicodeTables::combiningClass(uc[i]); 00530 } 00531 ++slen; 00532 } 00533 logClusters[i] = cluster_start; 00534 } 00535 00536 if (!item->font->stringToCMap(shapedChars, slen, glyphs, &item->num_glyphs, QFlag(item->flags))) { 00537 if (item->length > 256) 00538 ::free(shapedChars); 00539 return false; 00540 } 00541 for (int i = 0; i < item->num_glyphs; ++i) { 00542 if (glyphs[i].attributes.mark) { 00543 glyphs[i].advance.x = 0; 00544 } 00545 } 00546 qt_heuristicPosition(item); 00547 00548 if (item->length > 256) 00549 ::free(shapedChars); 00550 return true; 00551 }
Here is the call graph for this function:

| static void heuristicSetGlyphAttributes | ( | QShaperItem * | item | ) | [static] |
Definition at line 338 of file qscriptengine.cpp.
References QShaperItem::from, heuristicSetGlyphAttributes(), QShaperItem::length, QShaperItem::string, and QString::unicode().
00339 { 00340 heuristicSetGlyphAttributes(item, item->string->unicode() + item->from, item->length); 00341 }
Here is the call graph for this function:

| static void heuristicSetGlyphAttributes | ( | QShaperItem * | item, | |
| const QChar * | uc, | |||
| int | length | |||
| ) | [static] |
Definition at line 218 of file qscriptengine.cpp.
References QGlyphLayout::advance, QGlyphLayout::attributes, QUnicodeTables::Properties::category, QUnicodeTables::category(), QChar::cell(), QGlyphLayout::Character, QChar::Combining_Above, QChar::Combining_AboveRight, QChar::Combining_Below, QShaperItem::font, QShaperItem::glyphs, i, QShaperItem::log_clusters, QChar::Mark_NonSpacing, QGlyphLayout::NoJustification, QShaperItem::num_glyphs, QUnicodeTables::properties(), qIsControlChar(), QChar::Separator_Space, QGlyphLayout::Space, QFontEngine::symbol, QChar::unicode(), and x31.
Referenced by arabicSyriacOpenTypeShape(), basic_shape(), hebrew_shape(), heuristicSetGlyphAttributes(), and thaana_shape().
00219 { 00220 // ### zeroWidth and justification are missing here!!!!! 00221 00222 Q_ASSERT(item->num_glyphs <= length); 00223 00224 // qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs); 00225 QGlyphLayout *glyphs = item->glyphs; 00226 unsigned short *logClusters = item->log_clusters; 00227 00228 00229 // the mac font engine does the setup already in stringToCMap 00230 #ifndef Q_WS_MAC 00231 int glyph_pos = 0; 00232 for (int i = 0; i < length; i++) { 00233 if (uc[i].unicode() >= 0xd800 && uc[i].unicode() < 0xdc00 && i < length-1 00234 && uc[i+1].unicode() >= 0xdc00 && uc[i+1].unicode() < 0xe000) { 00235 logClusters[i] = glyph_pos; 00236 logClusters[++i] = glyph_pos; 00237 } else { 00238 logClusters[i] = glyph_pos; 00239 } 00240 ++glyph_pos; 00241 } 00242 Q_ASSERT(glyph_pos == item->num_glyphs); 00243 #endif 00244 00245 // first char in a run is never (treated as) a mark 00246 #if !defined(Q_WS_MAC) 00247 int cStart = 0; 00248 #endif 00249 const bool symbolFont = item->font->symbol; 00250 glyphs[0].attributes.mark = false; 00251 glyphs[0].attributes.clusterStart = true; 00252 glyphs[0].attributes.dontPrint = (!symbolFont && uc[0].unicode() == 0x00ad) || qIsControlChar(uc[0].unicode()); 00253 00254 int pos = 0; 00255 int lastCat = QUnicodeTables::category(uc[0]); 00256 for (int i = 1; i < length; ++i) { 00257 if (logClusters[i] == pos) 00258 // same glyph 00259 continue; 00260 ++pos; 00261 while (pos < logClusters[i]) { 00262 // the mac engine already has attributes setup properly 00263 #if !defined(Q_WS_MAC) 00264 glyphs[pos].attributes = glyphs[pos-1].attributes; 00265 #endif 00266 ++pos; 00267 } 00268 // hide soft-hyphens by default 00269 if ((!symbolFont && uc[i].unicode() == 0x00ad) || qIsControlChar(uc[i].unicode())) 00270 glyphs[pos].attributes.dontPrint = true; 00271 const QUnicodeTables::Properties *prop = QUnicodeTables::properties(uc[i].unicode()); 00272 int cat = prop->category; 00273 #if !defined(Q_WS_MAC) 00274 if (cat != QChar::Mark_NonSpacing) { 00275 glyphs[pos].attributes.mark = false; 00276 glyphs[pos].attributes.clusterStart = true; 00277 glyphs[pos].attributes.combiningClass = 0; 00278 cStart = logClusters[i]; 00279 } else { 00280 int cmb = prop->combiningClass; 00281 00282 if (cmb == 0) { 00283 // Fix 0 combining classes 00284 if ((uc[pos].unicode() & 0xff00) == 0x0e00) { 00285 // thai or lao 00286 unsigned char col = uc[pos].cell(); 00287 if (col == 0x31 || 00288 col == 0x34 || 00289 col == 0x35 || 00290 col == 0x36 || 00291 col == 0x37 || 00292 col == 0x47 || 00293 col == 0x4c || 00294 col == 0x4d || 00295 col == 0x4e) { 00296 cmb = QChar::Combining_AboveRight; 00297 } else if (col == 0xb1 || 00298 col == 0xb4 || 00299 col == 0xb5 || 00300 col == 0xb6 || 00301 col == 0xb7 || 00302 col == 0xbb || 00303 col == 0xcc || 00304 col == 0xcd) { 00305 cmb = QChar::Combining_Above; 00306 } else if (col == 0xbc) { 00307 cmb = QChar::Combining_Below; 00308 } 00309 } 00310 } 00311 00312 glyphs[pos].attributes.mark = true; 00313 glyphs[pos].attributes.clusterStart = false; 00314 glyphs[pos].attributes.combiningClass = cmb; 00315 logClusters[i] = cStart; 00316 glyphs[pos].advance = QFixedPoint(); 00317 } 00318 #endif 00319 // one gets an inter character justification point if the current char is not a non spacing mark. 00320 // as then the current char belongs to the last one and one gets a space justification point 00321 // after the space char. 00322 if (lastCat == QChar::Separator_Space) 00323 glyphs[pos-1].attributes.justification = QGlyphLayout::Space; 00324 else if (cat != QChar::Mark_NonSpacing) 00325 glyphs[pos-1].attributes.justification = QGlyphLayout::Character; 00326 else 00327 glyphs[pos-1].attributes.justification = QGlyphLayout::NoJustification; 00328 00329 lastCat = cat; 00330 } 00331 pos = logClusters[length-1]; 00332 if (lastCat == QChar::Separator_Space) 00333 glyphs[pos].attributes.justification = QGlyphLayout::Space; 00334 else 00335 glyphs[pos].attributes.justification = QGlyphLayout::Character; 00336 }
Here is the call graph for this function:

| static void indic_attributes | ( | int | script, | |
| const QString & | text, | |||
| int | from, | |||
| int | len, | |||
| QCharAttributes * | attributes | |||
| ) | [static] |
Definition at line 3417 of file qscriptengine.cpp.
References QCharAttributes::charStop, i, indic_nextSyllableBoundary(), and QString::unicode().
03418 { 03419 int end = from + len; 03420 const QChar *uc = text.unicode() + from; 03421 attributes += from; 03422 int i = 0; 03423 while (i < len) { 03424 bool invalid; 03425 int boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from; 03426 attributes[i].charStop = true; 03427 03428 if (boundary > len-1) boundary = len; 03429 i++; 03430 while (i < boundary) { 03431 attributes[i].charStop = false; 03432 ++uc; 03433 ++i; 03434 } 03435 assert(i == boundary); 03436 } 03437 03438 03439 }
Here is the call graph for this function:

| static int indic_nextSyllableBoundary | ( | int | script, | |
| const QString & | s, | |||
| int | start, | |||
| int | end, | |||
| bool * | invalid | |||
| ) | [static] |
Definition at line 3283 of file qscriptengine.cpp.
References QUnicodeTables::Bengali, Consonant, Control, form(), Halant, IDEBUG, IndependentVowel, Invalid, LengthMark, Matra, Nukta, s, QUnicodeTables::Sinhala, StressMark, QUnicodeTables::Tamil, and VowelMark.
Referenced by indic_attributes(), and indic_shape().
03284 { 03285 *invalid = false; 03286 IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end); 03287 const QChar *uc = s.unicode()+start; 03288 03289 int pos = 0; 03290 Form state = form(uc[pos].unicode()); 03291 IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos].unicode()); 03292 pos++; 03293 03294 if (state != Consonant && state != IndependentVowel) { 03295 if (state != Other) 03296 *invalid = true; 03297 goto finish; 03298 } 03299 03300 while (pos < end - start) { 03301 Form newState = form(uc[pos].unicode()); 03302 IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos].unicode()); 03303 switch(newState) { 03304 case Control: 03305 newState = state; 03306 if (state == Halant && uc[pos].unicode() == 0x200d /* ZWJ */) 03307 break; 03308 // the control character should be the last char in the item 03309 ++pos; 03310 goto finish; 03311 case Consonant: 03312 if (state == Halant && (script != QUnicodeTables::Sinhala || uc[pos-1].unicode() == 0x200d /* ZWJ */)) 03313 break; 03314 goto finish; 03315 case Halant: 03316 if (state == Nukta || state == Consonant) 03317 break; 03318 // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya 03319 if (script == QUnicodeTables::Bengali && pos == 1 && 03320 (uc[0].unicode() == 0x0985 || uc[0].unicode() == 0x098f)) 03321 break; 03322 goto finish; 03323 case Nukta: 03324 if (state == Consonant) 03325 break; 03326 goto finish; 03327 case StressMark: 03328 if (state == VowelMark) 03329 break; 03330 // fall through 03331 case VowelMark: 03332 if (state == Matra || state == IndependentVowel) 03333 break; 03334 // fall through 03335 case Matra: 03336 if (state == Consonant || state == Nukta) 03337 break; 03338 // ### not sure if this is correct. If it is, does it apply only to Bengali or should 03339 // it work for all Indic languages? 03340 // the combination Independent_A + Vowel Sign AA is allowed. 03341 if (script == QUnicodeTables::Bengali && uc[pos].unicode() == 0x9be && uc[pos-1].unicode() == 0x985) 03342 break; 03343 if (script == QUnicodeTables::Tamil && state == Matra) { 03344 if (uc[pos-1].unicode() == 0x0bc6 && 03345 (uc[pos].unicode() == 0xbbe || uc[pos].unicode() == 0xbd7)) 03346 break; 03347 if (uc[pos-1].unicode() == 0x0bc7 && uc[pos].unicode() == 0xbbe) 03348 break; 03349 } 03350 goto finish; 03351 03352 case LengthMark: 03353 case IndependentVowel: 03354 case Invalid: 03355 case Other: 03356 goto finish; 03357 } 03358 state = newState; 03359 pos++; 03360 } 03361 finish: 03362 return pos+start; 03363 }
Here is the call graph for this function:

| static Position indic_position | ( | unsigned short | uc | ) | [inline, static] |
Definition at line 2499 of file qscriptengine.cpp.
Referenced by indic_shape_syllable(), and splitMatra().
02499 { 02500 if (uc < 0x900 || uc > 0xdff) 02501 return None; 02502 return (Position) indicPosition[uc-0x900]; 02503 }
| static bool indic_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 3367 of file qscriptengine.cpp.
References QUnicodeTables::Devanagari, QShaperItem::font, QShaperItem::from, QShaperItem::glyphs, i, IDEBUG, indic_features, indic_nextSyllableBoundary(), indic_shape_syllable(), QShaperItem::length, QShaperItem::num_glyphs, openType, QFontEngine::openType(), QShaperItem::script, and QUnicodeTables::Sinhala.
03368 { 03369 Q_ASSERT(item->script >= QUnicodeTables::Devanagari && item->script <= QUnicodeTables::Sinhala); 03370 03371 #ifndef QT_NO_OPENTYPE 03372 QOpenType *openType = item->font->openType(); 03373 if (openType) 03374 openType->selectScript(item, item->script, indic_features); 03375 #else 03376 QOpenType *openType = 0; 03377 #endif 03378 unsigned short *logClusters = item->log_clusters; 03379 03380 QShaperItem syllable = *item; 03381 int first_glyph = 0; 03382 03383 int sstart = item->from; 03384 int end = sstart + item->length; 03385 IDEBUG("indic_shape: from %d length %d", item->from, item->length); 03386 while (sstart < end) { 03387 bool invalid; 03388 int send = indic_nextSyllableBoundary(item->script, *item->string, sstart, end, &invalid); 03389 IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, 03390 invalid ? "true" : "false"); 03391 syllable.from = sstart; 03392 syllable.length = send-sstart; 03393 syllable.glyphs = item->glyphs + first_glyph; 03394 syllable.num_glyphs = item->num_glyphs - first_glyph; 03395 if (!indic_shape_syllable(openType, &syllable, invalid)) { 03396 IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); 03397 item->num_glyphs += syllable.num_glyphs; 03398 return false; 03399 } 03400 // fix logcluster array 03401 IDEBUG("syllable:"); 03402 for (int i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) 03403 IDEBUG(" %d -> glyph %x", i, item->glyphs[i].glyph); 03404 IDEBUG(" logclusters:"); 03405 for (int i = sstart; i < send; ++i) { 03406 IDEBUG(" %d -> glyph %d", i, first_glyph); 03407 logClusters[i-item->from] = first_glyph; 03408 } 03409 sstart = send; 03410 first_glyph += syllable.num_glyphs; 03411 } 03412 item->num_glyphs = first_glyph; 03413 return true; 03414 }
Here is the call graph for this function:

| static bool indic_shape_syllable | ( | QOpenType * | openType, | |
| QShaperItem * | item, | |||
| bool | invalid | |||
| ) | [static] |
Definition at line 2788 of file qscriptengine.cpp.
References AboveSubstProperty, AkhantProperty, QGlyphLayout::attributes, base, Base, BelowFormProperty, BelowSubstProperty, QUnicodeTables::Bengali, CcmpProperty, Consonant, Control, data, QVarLengthArray< T, Prealloc >::data(), QUnicodeTables::Devanagari, QTextStream::fixed(), QShaperItem::flags, QShaperItem::font, form(), QShaperItem::from, QShaperItem::glyphs, QUnicodeTables::Gujarati, HalantProperty, HalfFormProperty, HasReph, i, IDEBUG, IndependentVowel, indic_order, indic_position(), InitProperty, QChar::isLetter(), QChar::isMark(), j, QUnicodeTables::Kannada, len, QShaperItem::length, QShaperItem::log_clusters, m, QUnicodeTables::Malayalam, Matra, NuktaProperty, QShaperItem::num_glyphs, openType, PositioningProperties, PostFormProperty, PostSubstProperty, Pre, PreSubstProperty, properties, qDebug(), RephProperty, QUnicodeTables::script(), QShaperItem::script, QUnicodeTables::Sinhala, Split, splitMatra(), QShaperItem::string, QFontEngine::stringToCMap(), QUnicodeTables::Tamil, QUnicodeTables::Telugu, QString::unicode(), Vattu, and VattuProperty.
Referenced by indic_shape().
02789 { 02790 Q_UNUSED(openType) 02791 int script = item->script; 02792 Q_ASSERT(script >= QUnicodeTables::Devanagari && script <= QUnicodeTables::Sinhala); 02793 const unsigned short script_base = 0x0900 + 0x80*(script-QUnicodeTables::Devanagari); 02794 const unsigned short ra = script_base + 0x30; 02795 const unsigned short halant = script_base + 0x4d; 02796 const unsigned short nukta = script_base + 0x3c; 02797 02798 int len = item->length; 02799 IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->from, item->length, invalid); 02800 02801 if (item->num_glyphs < len+4) { 02802 item->num_glyphs = len+4; 02803 return false; 02804 } 02805 02806 QVarLengthArray<unsigned short> reordered(len+4); 02807 QVarLengthArray<unsigned char> position(len+4); 02808 02809 unsigned char properties = scriptProperties[script-QUnicodeTables::Devanagari]; 02810 02811 if (invalid) { 02812 *reordered.data() = 0x25cc; 02813 memcpy(reordered.data()+1, item->string->unicode() + item->from, len*sizeof(QChar)); 02814 len++; 02815 } else { 02816 memcpy(reordered.data(), item->string->unicode() + item->from, len*sizeof(QChar)); 02817 } 02818 if (reordered[len-1] == 0x200c) // zero width non joiner 02819 len--; 02820 02821 int i; 02822 int base = 0; 02823 int reph = -1; 02824 02825 #ifdef INDIC_DEBUG 02826 IDEBUG("original:"); 02827 for (i = 0; i < len; i++) { 02828 IDEBUG(" %d: %4x", i, reordered[i]); 02829 } 02830 #endif 02831 02832 if (len != 1) { 02833 unsigned short *uc = reordered.data(); 02834 bool beginsWithRa = false; 02835 02836 // Rule 1: find base consonant 02837 // 02838 // The shaping engine finds the base consonant of the 02839 // syllable, using the following algorithm: starting from the 02840 // end of the syllable, move backwards until a consonant is 02841 // found that does not have a below-base or post-base form 02842 // (post-base forms have to follow below-base forms), or 02843 // arrive at the first consonant. The consonant stopped at 02844 // will be the base. 02845 // 02846 // * If the syllable starts with Ra + H (in a script that has 02847 // 'Reph'), Ra is excluded from candidates for base 02848 // consonants. 02849 // 02850 // * In Kannada and Telugu, the base consonant cannot be 02851 // farther than 3 consonants from the end of the syllable. 02852 // #### replace the HasReph property by testing if the feature exists in the font! 02853 if (form(*uc) == Consonant || (script == QUnicodeTables::Bengali && form(*uc) == IndependentVowel)) { 02854 beginsWithRa = (properties & HasReph) && ((len > 2) && *uc == ra && *(uc+1) == halant); 02855 02856 if (beginsWithRa && form(*(uc+2)) == Control) 02857 beginsWithRa = false; 02858 02859 base = (beginsWithRa ? 2 : 0); 02860 IDEBUG(" length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base); 02861 02862 int lastConsonant = 0; 02863 int matra = -1; 02864 // we remember: 02865 // * the last consonant since we need it for rule 2 02866 // * the matras position for rule 3 and 4 02867 02868 // figure out possible base glyphs 02869 memset(position.data(), 0, len); 02870 if (script == QUnicodeTables::Devanagari || script == QUnicodeTables::Gujarati) { 02871 bool vattu = false; 02872 for (i = base; i < len; ++i) { 02873 position[i] = form(uc[i]); 02874 if (position[i] == Consonant) { 02875 lastConsonant = i; 02876 vattu = (!vattu && uc[i] == ra); 02877 if (vattu) { 02878 IDEBUG("excluding vattu glyph at %d from base candidates", i); 02879 position[i] = Vattu; 02880 } 02881 } else if (position[i] == Matra) { 02882 matra = i; 02883 } 02884 } 02885 } else { 02886 for (i = base; i < len; ++i) { 02887 position[i] = form(uc[i]); 02888 if (position[i] == Consonant) 02889 lastConsonant = i; 02890 else if (matra < 0 && position[i] == Matra) 02891 matra = i; 02892 } 02893 } 02894 int skipped = 0; 02895 Position pos = Post; 02896 for (i = len-1; i > base; i--) { 02897 if (position[i] != Consonant && (position[i] != Control || script == QUnicodeTables::Kannada)) 02898 continue; 02899 02900 Position charPosition = indic_position(uc[i]); 02901 if (pos == Post && charPosition == Post) { 02902 pos = Post; 02903 } else if ((pos == Post || pos == Below) && charPosition == Below) { 02904 if (script == QUnicodeTables::Devanagari || script == QUnicodeTables::Gujarati) 02905 base = i; 02906 pos = Below; 02907 } else { 02908 base = i; 02909 break; 02910 } 02911 if (skipped == 2 && (script == QUnicodeTables::Kannada || script == QUnicodeTables::Telugu)) { 02912 base = i; 02913 break; 02914 } 02915 ++skipped; 02916 } 02917 02918 IDEBUG(" base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant); 02919 02920 // Rule 2: 02921 // 02922 // If the base consonant is not the last one, Uniscribe 02923 // moves the halant from the base consonant to the last 02924 // one. 02925 if (lastConsonant > base) { 02926 int halantPos = 0; 02927 if (uc[base+1] == halant) 02928 halantPos = base + 1; 02929 else if (uc[base+1] == nukta && uc[base+2] == halant) 02930 halantPos = base + 2; 02931 if (halantPos > 0) { 02932 IDEBUG(" moving halant from %d to %d!", base+1, lastConsonant); 02933 for (i = halantPos; i < lastConsonant; i++) 02934 uc[i] = uc[i+1]; 02935 uc[lastConsonant] = halant; 02936 } 02937 } 02938 02939 // Rule 3: 02940 // 02941 // If the syllable starts with Ra + H, Uniscribe moves 02942 // this combination so that it follows either: 02943 02944 // * the post-base 'matra' (if any) or the base consonant 02945 // (in scripts that show similarity to Devanagari, i.e., 02946 // Devanagari, Gujarati, Bengali) 02947 // * the base consonant (other scripts) 02948 // * the end of the syllable (Kannada) 02949 02950 Position matra_position = None; 02951 if (matra > 0) 02952 matra_position = indic_position(uc[matra]); 02953 IDEBUG(" matra at %d with form %d, base=%d", matra, matra_position, base); 02954 02955 if (beginsWithRa && base != 0) { 02956 int toPos = base+1; 02957 if (toPos < len && uc[toPos] == nukta) 02958 toPos++; 02959 if (toPos < len && uc[toPos] == halant) 02960 toPos++; 02961 if (toPos < len && uc[toPos] == 0x200d) 02962 toPos++; 02963 if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant) 02964 toPos += 2; 02965 if (script == QUnicodeTables::Devanagari || script == QUnicodeTables::Gujarati || script == QUnicodeTables::Bengali) { 02966 if (matra_position == Post || matra_position == Split) { 02967 toPos = matra+1; 02968 matra -= 2; 02969 } 02970 } else if (script == QUnicodeTables::Kannada) { 02971 toPos = len; 02972 matra -= 2; 02973 } 02974 02975 IDEBUG("moving leading ra+halant to position %d", toPos); 02976 for (i = 2; i < toPos; i++) 02977 uc[i-2] = uc[i]; 02978 uc[toPos-2] = ra; 02979 uc[toPos-1] = halant; 02980 base -= 2; 02981 if (properties & HasReph) 02982 reph = toPos-2; 02983 } 02984 02985 // Rule 4: 02986 02987 // Uniscribe splits two- or three-part matras into their 02988 // parts. This splitting is a character-to-character 02989 // operation). 02990 // 02991 // Uniscribe describes some moving operations for these 02992 // matras here. For shaping however all pre matras need 02993 // to be at the beginning of the syllable, so we just move 02994 // them there now. 02995 if (matra_position == Split) { 02996 splitMatra(uc, matra, len, base); 02997 // Handle three-part matras (0xccb in Kannada) 02998 matra_position = indic_position(uc[matra]); 02999 if (matra_position == Split) 03000 splitMatra(uc, matra, len, base); 03001 } else if (matra_position == Pre) { 03002 unsigned short m = uc[matra]; 03003 while (matra--) 03004 uc[matra+1] = uc[matra]; 03005 uc[0] = m; 03006 base++; 03007 } 03008 } 03009 03010 // Rule 5: 03011 // 03012 // Uniscribe classifies consonants and 'matra' parts as 03013 // pre-base, above-base (Reph), below-base or post-base. This 03014 // classification exists on the character code level and is 03015 // language-dependent, not font-dependent. 03016 for (i = 0; i < base; ++i) 03017 position[i] = Pre; 03018 position[base] = Base; 03019 for (i = base+1; i < len; ++i) { 03020 position[i] = indic_position(uc[i]); 03021 // #### replace by adjusting table 03022 if (uc[i] == nukta || uc[i] == halant) 03023 position[i] = Inherit; 03024 } 03025 if (reph > 0) { 03026 // recalculate reph, it might have changed. 03027 for (i = base+1; i < len; ++i) 03028 if (uc[i] == ra) 03029 reph = i; 03030 position[reph] = Reph; 03031 position[reph+1] = Inherit; 03032 } 03033 03034 // all reordering happens now to the chars after the base 03035 int fixed = base+1; 03036 if (fixed < len && uc[fixed] == nukta) 03037 fixed++; 03038 if (fixed < len && uc[fixed] == halant) 03039 fixed++; 03040 if (fixed < len && uc[fixed] == 0x200d) 03041 fixed++; 03042 03043 #ifdef INDIC_DEBUG 03044 for (i = fixed; i < len; ++i) 03045 IDEBUG("position[%d] = %d, form=%d", i, position[i], form(uc[i])); 03046 #endif 03047 // we continuosly position the matras and vowel marks and increase the fixed 03048 // until we reached the end. 03049 const IndicOrdering *finalOrder = indic_order[script-QUnicodeTables::Devanagari]; 03050 03051 IDEBUG(" reordering pass:"); 03052 //IDEBUG(" base=%d fixed=%d", base, fixed); 03053 int toMove = 0; 03054 while (finalOrder[toMove].form && fixed < len-1) { 03055 //IDEBUG(" fixed = %d, moving form %d with pos %d", fixed, finalOrder[toMove].form, finalOrder[toMove].position); 03056 for (i = fixed; i < len; i++) { 03057 if (form(uc[i]) == finalOrder[toMove].form && 03058 position[i] == finalOrder[toMove].position) { 03059 // need to move this glyph 03060 int to = fixed; 03061 if (i < len-1 && position[i+1] == Inherit) { 03062 IDEBUG(" moving two chars from %d to %d", i, to); 03063 unsigned short ch = uc[i]; 03064 unsigned short ch2 = uc[i+1]; 03065 unsigned char pos = position[i]; 03066 for (int j = i+1; j > to+1; j--) { 03067 uc[j] = uc[j-2]; 03068 position[j] = uc[j-2]; 03069 } 03070 uc[to] = ch; 03071 uc[to+1] = ch2; 03072 position[to] = pos; 03073 position[to+1] = pos; 03074 fixed += 2; 03075 } else { 03076 IDEBUG(" moving one char from %d to %d", i, to); 03077 unsigned short ch = uc[i]; 03078 unsigned char pos = position[i]; 03079 for (int j = i; j > to; j--) { 03080 uc[j] = uc[j-1]; 03081 position[j] = position[j-1]; 03082 } 03083 uc[to] = ch; 03084 position[to] = pos; 03085 fixed++; 03086 } 03087 } 03088 } 03089 toMove++; 03090 } 03091 03092 } 03093 03094 if (reph > 0) { 03095 // recalculate reph, it might have changed. 03096 for (i = base+1; i < len; ++i) 03097 if (reordered[i] == ra) 03098 reph = i; 03099 } 03100 03101 #ifndef QT_NO_OPENTYPE 03102 const int availableGlyphs = item->num_glyphs; 03103 #endif 03104 if (!item->font->stringToCMap((const QChar *)reordered.data(), len, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 03105 return false; 03106 03107 03108 IDEBUG(" base=%d, reph=%d", base, reph); 03109 IDEBUG("reordered:"); 03110 for (i = 0; i < len; i++) { 03111 item->glyphs[i].attributes.mark = false; 03112 item->glyphs[i].attributes.clusterStart = false; 03113 item->glyphs[i].attributes.justification = 0; 03114 item->glyphs[i].attributes.zeroWidth = false; 03115 IDEBUG(" %d: %4x", i, reordered[i]); 03116 } 03117 03118 // now we have the syllable in the right order, and can start running it through open type. 03119 03120 bool control = false; 03121 for (i = 0; i < len; ++i) 03122 control |= (form(reordered[i]) == Control); 03123 03124 #ifndef QT_NO_OPENTYPE 03125 if (openType) { 03126 03127 // we need to keep track of where the base glyph is for some 03128 // scripts and use the cluster feature for this. This 03129 // also means we have to correct the logCluster output from 03130 // the open type engine manually afterwards. for indic this 03131 // is rather simple, as all chars just point to the first 03132 // glyph in the syllable. 03133 QVarLengthArray<unsigned short> clusters(len); 03134 QVarLengthArray<unsigned int> properties(len); 03135 03136 for (i = 0; i < len; ++i) 03137 clusters[i] = i; 03138 03139 // features we should always apply 03140 for (i = 0; i < len; ++i) 03141 properties[i] = ~(CcmpProperty 03142 | NuktaProperty 03143 | VattuProperty 03144 | PreSubstProperty 03145 | BelowSubstProperty 03146 | AboveSubstProperty 03147 | HalantProperty 03148 | PositioningProperties); 03149 03150 // Ccmp always applies 03151 // Init 03152 if (item->from == 0 03153 || !(item->string->unicode()[item->from-1].isLetter() || item->string->unicode()[item->from-1].isMark())) 03154 properties[0] &= ~InitProperty; 03155 03156 // Nukta always applies 03157 // Akhant 03158 for (i = 0; i <= base; ++i) 03159 properties[i] &= ~AkhantProperty; 03160 // Reph 03161 if (reph >= 0) { 03162 properties[reph] &= ~RephProperty; 03163 properties[reph+1] &= ~RephProperty; 03164 } 03165 // BelowForm 03166 for (i = base+1; i < len; ++i) 03167 properties[i] &= ~BelowFormProperty; 03168 03169 if (script == QUnicodeTables::Devanagari || script == QUnicodeTables::Gujarati) { 03170 // vattu glyphs need this aswell 03171 bool vattu = false; 03172 for (i = base-2; i > 1; --i) { 03173 if (form(reordered[i]) == Consonant) { 03174 vattu = (!vattu && reordered[i] == ra); 03175 if (vattu) { 03176 IDEBUG("forming vattu ligature at %d", i); 03177 properties[i] &= ~BelowFormProperty; 03178 properties[i+1] &= ~BelowFormProperty; 03179 } 03180 } 03181 } 03182 } 03183 // HalfFormProperty 03184 for (i = 0; i < base; ++i) 03185 properties[i] &= ~HalfFormProperty; 03186 if (control) { 03187 for (i = 2; i < len; ++i) { 03188 if (reordered[i] == 0x200d /* ZWJ */) { 03189 properties[i-1] &= ~HalfFormProperty; 03190 properties[i-2] &= ~HalfFormProperty; 03191 } else if (reordered[i] == 0x200c /* ZWNJ */) { 03192 properties[i-1] &= ~HalfFormProperty; 03193 properties[i-2] &= ~HalfFormProperty; 03194 } 03195 } 03196 } 03197 // PostFormProperty 03198 for (i = base+1; i < len; ++i) 03199 properties[i] &= ~PostFormProperty; 03200 // vattu always applies 03201 // pres always applies 03202 // blws always applies 03203 // abvs always applies 03204 03205 // psts 03206 // ### this looks slightly different from before, but I believe it's correct 03207 if (reordered[len-1] != halant || base != len-2) 03208 properties[base] &= ~PostSubstProperty; 03209 for (i = base+1; i < len; ++i) 03210 properties[i] &= ~PostSubstProperty; 03211 03212 // halant always applies 03213 03214 #ifdef INDIC_DEBUG 03215 { 03216 IDEBUG("OT properties:"); 03217 for (int i = 0; i < len; ++i) 03218 qDebug(" i: %s", ::propertiesToString(properties[i]).toLatin1().data()); 03219 } 03220 #endif 03221 03222 // initialize 03223 item->log_clusters = clusters.data(); 03224 openType->shape(item, properties.data()); 03225 03226 int newLen = openType->len(); 03227 HB_GlyphItem otl_glyphs = openType->glyphs(); 03228 03229 // move the left matra back to its correct position in malayalam and tamil 03230 if ((script == QUnicodeTables::Malayalam || script == QUnicodeTables::Tamil) && (form(reordered[0]) == Matra)) { 03231 // qDebug("reordering matra, len=%d", newLen); 03232 // need to find the base in the shaped string and move the matra there 03233 int basePos = 0; 03234 while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base) 03235 basePos++; 03236 --basePos; 03237 if (basePos < newLen && basePos > 1) { 03238 // qDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen); 03239 HB_GlyphItemRec m = otl_glyphs[0]; 03240 --basePos; 03241 for (i = 0; i < basePos; ++i) 03242 otl_glyphs[i] = otl_glyphs[i+1]; 03243 otl_glyphs[basePos] = m; 03244 } 03245 } 03246 03247 if (!openType->positionAndAdd(item, availableGlyphs, false)) 03248 return false; 03249 03250 if (control) { 03251 IDEBUG("found a control char in the syllable"); 03252 int i = 0, j = 0; 03253 while (i < item->num_glyphs) { 03254 if (form(reordered[otl_glyphs[i].cluster]) == Control) { 03255 ++i; 03256 if (i >= item->num_glyphs) 03257 break; 03258 } 03259 item->glyphs[j] = item->glyphs[i]; 03260 ++i; 03261 ++j; 03262 } 03263 item->num_glyphs = j; 03264 } 03265 03266 } 03267 #endif // QT_NO_OPENTYPE 03268 item->glyphs[0].attributes.clusterStart = true; 03269 03270 IDEBUG("<<<<<<"); 03271 return true; 03272 }
Here is the call graph for this function:

| static void khmer_attributes | ( | int | script, | |
| const QString & | text, | |||
| int | from, | |||
| int | len, | |||
| QCharAttributes * | attributes | |||
| ) | [static] |
Definition at line 4362 of file qscriptengine.cpp.
References QCharAttributes::charStop, i, khmer_nextSyllableBoundary(), and QString::unicode().
04363 { 04364 Q_UNUSED(script); 04365 04366 int end = from + len; 04367 const QChar *uc = text.unicode() + from; 04368 attributes += from; 04369 int i = 0; 04370 while ( i < len ) { 04371 bool invalid; 04372 int boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from; 04373 04374 attributes[i].charStop = true; 04375 04376 if ( boundary > len-1 ) boundary = len; 04377 i++; 04378 while ( i < boundary ) { 04379 attributes[i].charStop = false; 04380 ++uc; 04381 ++i; 04382 } 04383 assert( i == boundary ); 04384 } 04385 }
Here is the call graph for this function:

| static int khmer_nextSyllableBoundary | ( | const QString & | s, | |
| int | start, | |||
| int | end, | |||
| bool * | invalid | |||
| ) | [inline, static] |
Definition at line 4035 of file qscriptengine.cpp.
References CF_CLASS_MASK, CF_CONSONANT, getKhmerCharClass(), KHDEBUG, s, and QChar::unicode().
Referenced by khmer_attributes(), and khmer_shape().
04036 { 04037 *invalid = false; 04038 const QChar *uc = s.unicode() + start; 04039 int state = 0; 04040 int pos = start; 04041 04042 while (pos < end) { 04043 KhmerCharClass charClass = getKhmerCharClass(*uc); 04044 if (pos == start) { 04045 *invalid = (charClass > 0) && ! (charClass & CF_CONSONANT); 04046 } 04047 state = khmerStateTable[state][charClass & CF_CLASS_MASK]; 04048 04049 KHDEBUG("state[%d]=%d class=%8lx (uc=%4x)", pos - start, state, 04050 charClass, uc->unicode() ); 04051 04052 if (state < 0) { 04053 break; 04054 } 04055 ++uc; 04056 ++pos; 04057 } 04058 return pos; 04059 }
Here is the call graph for this function:

| static bool khmer_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 4312 of file qscriptengine.cpp.
References QShaperItem::font, QShaperItem::from, QGlyphLayout::glyph, QShaperItem::glyphs, i, KHDEBUG, QUnicodeTables::Khmer, khmer_nextSyllableBoundary(), khmer_shape_syllable(), QShaperItem::length, QShaperItem::log_clusters, QShaperItem::num_glyphs, openType, QFontEngine::openType(), QShaperItem::script, and QShaperItem::string.
04313 { 04314 assert(item->script == QUnicodeTables::Khmer); 04315 04316 #ifndef QT_NO_OPENTYPE 04317 QOpenType *openType = item->font->openType(); 04318 if (openType && !openType->supportsScript(item->script)) 04319 openType = 0; 04320 #else 04321 QOpenType *openType = 0; 04322 #endif 04323 unsigned short *logClusters = item->log_clusters; 04324 04325 QShaperItem syllable = *item; 04326 int first_glyph = 0; 04327 04328 int sstart = item->from; 04329 int end = sstart + item->length; 04330 KHDEBUG("khmer_shape: from %d length %d", item->from, item->length); 04331 while (sstart < end) { 04332 bool invalid; 04333 int send = khmer_nextSyllableBoundary(*item->string, sstart, end, &invalid); 04334 KHDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, 04335 invalid ? "true" : "false"); 04336 syllable.from = sstart; 04337 syllable.length = send-sstart; 04338 syllable.glyphs = item->glyphs + first_glyph; 04339 syllable.num_glyphs = item->num_glyphs - first_glyph; 04340 if (!khmer_shape_syllable(openType, &syllable)) { 04341 KHDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); 04342 item->num_glyphs += syllable.num_glyphs; 04343 return false; 04344 } 04345 // fix logcluster array 04346 KHDEBUG("syllable:"); 04347 for (int i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) 04348 KHDEBUG(" %d -> glyph %x", i, item->glyphs[i].glyph); 04349 KHDEBUG(" logclusters:"); 04350 for (int i = sstart; i < send; ++i) { 04351 KHDEBUG(" %d -> glyph %d", i, first_glyph); 04352 logClusters[i-item->from] = first_glyph; 04353 } 04354 sstart = send; 04355 first_glyph += syllable.num_glyphs; 04356 } 04357 item->num_glyphs = first_glyph; 04358 return true; 04359 }
Here is the call graph for this function:

| static bool khmer_shape_syllable | ( | QOpenType * | openType, | |
| QShaperItem * | item | |||
| ) | [static] |
Definition at line 4079 of file qscriptengine.cpp.
References C_VOWEL_E, CC_CONSONANT2, CF_CLASS_MASK, CF_COENG, CF_POS_BEFORE, CF_SPLIT_VOWEL, getKhmerCharClass(), i, KHDEBUG, QUnicodeTables::Khmer, khmer_features, len, openType, properties, and qDebug().
Referenced by khmer_shape().
04080 { 04081 #ifndef QT_NO_OPENTYPE 04082 if (openType) 04083 openType->selectScript(item, QUnicodeTables::Khmer, khmer_features); 04084 #endif 04085 // according to the specs this is the max length one can get 04086 // ### the real value should be smaller 04087 assert(item->length < 13); 04088 04089 KHDEBUG("syllable from %d len %d, str='%s'", item->from, item->length, 04090 item->string->mid(item->from, item->length).toUtf8().data()); 04091 04092 int len = 0; 04093 int syllableEnd = item->from + item->length; 04094 unsigned short reordered[16]; 04095 unsigned char properties[16]; 04096 enum { 04097 AboveForm = 0x01, 04098 PreForm = 0x02, 04099 PostForm = 0x04, 04100 BelowForm = 0x08 04101 }; 04102 memset(properties, 0, 16*sizeof(unsigned char)); 04103 04104 #ifdef KHMER_DEBUG 04105 qDebug("original:"); 04106 for (int i = from; i < syllableEnd; i++) { 04107 qDebug(" %d: %4x", i, string[i].unicode()); 04108 } 04109 #endif 04110 04111 // write a pre vowel or the pre part of a split vowel first 04112 // and look out for coeng + ro. RO is the only vowel of type 2, and 04113 // therefore the only one that requires saving space before the base. 04114 // 04115 int coengRo = -1; // There is no Coeng Ro, if found this value will change 04116 for (int i = item->from; i < syllableEnd; i += 1) { 04117 KhmerCharClass charClass = getKhmerCharClass(item->string->at(i)); 04118 04119 // if a split vowel, write the pre part. In Khmer the pre part 04120 // is the same for all split vowels, same glyph as pre vowel C_VOWEL_E 04121 if (charClass & CF_SPLIT_VOWEL) { 04122 reordered[len] = C_VOWEL_E; 04123 properties[len] = PreForm; 04124 ++len; 04125 break; // there can be only one vowel 04126 } 04127 // if a vowel with pos before write it out 04128 if (charClass & CF_POS_BEFORE) { 04129 reordered[len] = item->string->at(i).unicode(); 04130 properties[len] = PreForm; 04131 ++len; 04132 break; // there can be only one vowel 04133 } 04134 // look for coeng + ro and remember position 04135 // works because coeng + ro is always in front of a vowel (if there is a vowel) 04136 // and because CC_CONSONANT2 is enough to identify it, as it is the only consonant 04137 // with this flag 04138 if ( (charClass & CF_COENG) && (i + 1 < syllableEnd) && 04139 ( (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT2) ) { 04140 coengRo = i; 04141 } 04142 } 04143 04144 // write coeng + ro if found 04145 if (coengRo > -1) { 04146 reordered[len] = C_COENG; 04147 properties[len] = PreForm; 04148 ++len; 04149 reordered[len] = C_RO; 04150 properties[len] = PreForm; 04151 ++len; 04152 } 04153 04154 // shall we add a dotted circle? 04155 // If in the position in which the base should be (first char in the string) there is 04156 // a character that has the Dotted circle flag (a character that cannot be a base) 04157 // then write a dotted circle 04158 if (getKhmerCharClass(item->string->at(item->from)) & CF_DOTTED_CIRCLE) { 04159 reordered[len] = C_DOTTED_CIRCLE; 04160 ++len; 04161 } 04162 04163 // copy what is left to the output, skipping before vowels and 04164 // coeng Ro if they are present 04165 for (int i = item->from; i < syllableEnd; i += 1) { 04166 QChar uc = item->string->at(i); 04167 KhmerCharClass charClass = getKhmerCharClass(uc); 04168 04169 // skip a before vowel, it was already processed 04170 if (charClass & CF_POS_BEFORE) { 04171 continue; 04172 } 04173 04174 // skip coeng + ro, it was already processed 04175 if (i == coengRo) { 04176 i += 1; 04177 continue; 04178 } 04179 04180 switch (charClass & CF_POS_MASK) 04181 { 04182 case CF_POS_ABOVE : 04183 reordered[len] = uc.unicode(); 04184 properties[len] = AboveForm; 04185 ++len; 04186 break; 04187 04188 case CF_POS_AFTER : 04189 reordered[len] = uc.unicode(); 04190 properties[len] = PostForm; 04191 ++len; 04192 break; 04193 04194 case CF_POS_BELOW : 04195 reordered[len] = uc.unicode(); 04196 properties[len] = BelowForm; 04197 ++len; 04198 break; 04199 04200 default: 04201 // assign the correct flags to a coeng consonant 04202 // Consonants of type 3 are taged as Post forms and those type 1 as below forms 04203 if ( (charClass & CF_COENG) && i + 1 < syllableEnd ) { 04204 unsigned char property = (getKhmerCharClass(item->string->at(i+1)) & CF_CLASS_MASK) == CC_CONSONANT3 ? 04205 PostForm : BelowForm; 04206 reordered[len] = uc.unicode(); 04207 properties[len] = property; 04208 ++len; 04209 i += 1; 04210 reordered[len] = item->string->at(i).unicode(); 04211 properties[len] = property; 04212 ++len; 04213 break; 04214 } 04215 04216 // if a shifter is followed by an above vowel change the shifter to below form, 04217 // an above vowel can have two possible positions i + 1 or i + 3 04218 // (position i+1 corresponds to unicode 3, position i+3 to Unicode 4) 04219 // and there is an extra rule for C_VOWEL_AA + C_SIGN_NIKAHIT also for two 04220 // different positions, right after the shifter or after a vowel (Unicode 4) 04221 if ( (charClass & CF_SHIFTER) && (i + 1 < syllableEnd) ) { 04222 if (getKhmerCharClass(item->string->at(i+1)) & CF_ABOVE_VOWEL ) { 04223 reordered[len] = uc.unicode(); 04224 properties[len] = BelowForm; 04225 ++len; 04226 break; 04227 } 04228 if (i + 2 < syllableEnd && 04229 (item->string->at(i+1).unicode() == C_VOWEL_AA) && 04230 (item->string->at(i+2).unicode() == C_SIGN_NIKAHIT) ) 04231 { 04232 reordered[len] = uc.unicode(); 04233 properties[len] = BelowForm; 04234 ++len; 04235 break; 04236 } 04237 if (i + 3 < syllableEnd && (getKhmerCharClass(item->string->at(i+3)) & CF_ABOVE_VOWEL) ) { 04238 reordered[len] = uc.unicode(); 04239 properties[len] = BelowForm; 04240 ++len; 04241 break; 04242 } 04243 if (i + 4 < syllableEnd && 04244 (item->string->at(i+3).unicode() == C_VOWEL_AA) && 04245 (item->string->at(i+4).unicode() == C_SIGN_NIKAHIT) ) 04246 { 04247 reordered[len] = uc.unicode(); 04248 properties[len] = BelowForm; 04249 ++len; 04250 break; 04251 } 04252 } 04253 04254 // default - any other characters 04255 reordered[len] = uc.unicode(); 04256 ++len; 04257 break; 04258 } // switch 04259 } // for 04260 04261 #ifndef QT_NO_OPENTYPE 04262 const int availableGlyphs = item->num_glyphs; 04263 #endif 04264 if (!item->font->stringToCMap((const QChar *)reordered, len, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 04265 return false; 04266 04267 KHDEBUG("after shaping: len=%d", len); 04268 for (int i = 0; i < len; i++) { 04269 item->glyphs[i].attributes.mark = false; 04270 item->glyphs[i].attributes.clusterStart = false; 04271 item->glyphs[i].attributes.justification = 0; 04272 item->glyphs[i].attributes.zeroWidth = false; 04273 KHDEBUG(" %d: %4x property=%x", i, reordered[i], properties[i]); 04274 } 04275 04276 // now we have the syllable in the right order, and can start running it through open type. 04277 04278 #ifndef QT_NO_OPENTYPE 04279 if (openType) { 04280 uint where[16]; 04281 for (int i = 0; i < len; ++i) { 04282 where[i] = ~(PreSubstProperty 04283 | BelowSubstProperty 04284 | AboveSubstProperty 04285 | PostSubstProperty 04286 | CligProperty 04287 | PositioningProperties); 04288 if (properties[i] == PreForm) 04289 where[i] &= ~PreFormProperty; 04290 else if (properties[i] == BelowForm) 04291 where[i] &= ~BelowFormProperty; 04292 else if (properties[i] == AboveForm) 04293 where[i] &= ~AboveFormProperty; 04294 else if (properties[i] == PostForm) 04295 where[i] &= ~PostFormProperty; 04296 } 04297 04298 openType->shape(item, where); 04299 if (!openType->positionAndAdd(item, availableGlyphs, false)) 04300 return false; 04301 } else 04302 #endif 04303 { 04304 KHDEBUG("Not using openType"); 04305 Q_UNUSED(openType); 04306 } 04307 04308 item->glyphs[0].attributes.clusterStart = true; 04309 return true; 04310 }
Here is the call graph for this function:

| static void myanmar_attributes | ( | int | script, | |
| const QString & | text, | |||
| int | from, | |||
| int | len, | |||
| QCharAttributes * | attributes | |||
| ) | [static] |
Definition at line 4873 of file qscriptengine.cpp.
References QCharAttributes::charStop, i, myanmar_nextSyllableBoundary(), QCharAttributes::softBreak, and QString::unicode().
04874 { 04875 Q_UNUSED(script); 04876 04877 int end = from + len; 04878 const QChar *uc = text.unicode() + from; 04879 attributes += from; 04880 int i = 0; 04881 while (i < len) { 04882 bool invalid; 04883 int boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from; 04884 04885 attributes[i].charStop = true; 04886 attributes[i].softBreak = true; 04887 04888 if (boundary > len-1) 04889 boundary = len; 04890 i++; 04891 while (i < boundary) { 04892 attributes[i].charStop = false; 04893 ++uc; 04894 ++i; 04895 } 04896 Q_ASSERT(i == boundary); 04897 } 04898 }
Here is the call graph for this function:

| static int myanmar_nextSyllableBoundary | ( | const QString & | s, | |
| int | start, | |||
| int | end, | |||
| bool * | invalid | |||
| ) | [inline, static] |
Definition at line 4558 of file qscriptengine.cpp.
References getMyanmarCharClass(), MMDEBUG, Mymr_CF_CLASS_MASK, Mymr_CF_DOTTED_CIRCLE, s, and QChar::unicode().
Referenced by myanmar_attributes(), and myanmar_shape().
04559 { 04560 *invalid = false; 04561 const QChar *uc = s.unicode() + start; 04562 int state = 0; 04563 int pos = start; 04564 04565 while (pos < end) { 04566 MymrCharClass charClass = getMyanmarCharClass(*uc); 04567 state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK]; 04568 if (pos == start) 04569 *invalid = charClass & Mymr_CF_DOTTED_CIRCLE; 04570 04571 MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, uc->unicode()); 04572 04573 if (state < 0) { 04574 if (state < -1) 04575 --pos; 04576 break; 04577 } 04578 ++uc; 04579 ++pos; 04580 } 04581 return pos; 04582 }
Here is the call graph for this function:

| static bool myanmar_shape | ( | QShaperItem * | item | ) | [static] |
Definition at line 4823 of file qscriptengine.cpp.
References QShaperItem::font, QShaperItem::from, QGlyphLayout::glyph, QShaperItem::glyphs, i, QShaperItem::length, QShaperItem::log_clusters, MMDEBUG, QUnicodeTables::Myanmar, myanmar_nextSyllableBoundary(), myanmar_shape_syllable(), QShaperItem::num_glyphs, openType, QFontEngine::openType(), QShaperItem::script, and QShaperItem::string.
04824 { 04825 Q_ASSERT(item->script == QUnicodeTables::Myanmar); 04826 04827 #ifndef QT_NO_OPENTYPE 04828 QOpenType *openType = item->font->openType(); 04829 if (openType && !openType->supportsScript(item->script)) 04830 openType = 0; 04831 #else 04832 QOpenType *openType = 0; 04833 #endif 04834 unsigned short *logClusters = item->log_clusters; 04835 04836 QShaperItem syllable = *item; 04837 int first_glyph = 0; 04838 04839 int sstart = item->from; 04840 int end = sstart + item->length; 04841 MMDEBUG("myanmar_shape: from %d length %d", item->from, item->length); 04842 while (sstart < end) { 04843 bool invalid; 04844 int send = myanmar_nextSyllableBoundary(*item->string, sstart, end, &invalid); 04845 MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart, 04846 invalid ? "true" : "false"); 04847 syllable.from = sstart; 04848 syllable.length = send-sstart; 04849 syllable.glyphs = item->glyphs + first_glyph; 04850 syllable.num_glyphs = item->num_glyphs - first_glyph; 04851 if (!myanmar_shape_syllable(openType, &syllable, invalid)) { 04852 MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs); 04853 item->num_glyphs += syllable.num_glyphs; 04854 return false; 04855 } 04856 04857 // fix logcluster array 04858 MMDEBUG("syllable:"); 04859 for (int i = first_glyph; i < first_glyph + syllable.num_glyphs; ++i) 04860 MMDEBUG(" %d -> glyph %x", i, item->glyphs[i].glyph); 04861 MMDEBUG(" logclusters:"); 04862 for (int i = sstart; i < send; ++i) { 04863 MMDEBUG(" %d -> glyph %d", i, first_glyph); 04864 logClusters[i-item->from] = first_glyph; 04865 } 04866 sstart = send; 04867 first_glyph += syllable.num_glyphs; 04868 } 04869 item->num_glyphs = first_glyph; 04870 return true; 04871 }
Here is the call graph for this function:

| static bool myanmar_shape_syllable | ( | QOpenType * | openType, | |
| QShaperItem * | item, | |||
| bool | invalid | |||
| ) | [static] |
Definition at line 4616 of file qscriptengine.cpp.
References AboveFormProperty, AboveSubstProperty, base, BelowFormProperty, BelowSubstProperty, C_DOTTED_CIRCLE, CligProperty, getMyanmarCharClass(), i, MMDEBUG, QUnicodeTables::Myanmar, myanmar_features, Mymr_C_NGA, Mymr_C_RA, Mymr_C_SIGN_ZWJ, Mymr_C_SIGN_ZWNJ, Mymr_C_VIRAMA, Mymr_C_VOWEL_E, Mymr_CF_AFTER_KINZI, Mymr_CF_CONSONANT, Mymr_CF_POS_ABOVE, Mymr_CF_POS_AFTER, Mymr_CF_POS_BEFORE, Mymr_CF_POS_BELOW, Mymr_CF_POS_MASK, openType, PositioningProperties, PostFormProperty, PostSubstProperty, PreFormProperty, PreSubstProperty, properties, qDebug(), and QChar::unicode().
Referenced by myanmar_shape().
04617 { 04618 #ifndef QT_NO_OPENTYPE 04619 if (openType) 04620 openType->selectScript(item, QUnicodeTables::Myanmar, myanmar_features); 04621 #endif 04622 // according to the table the max length of a syllable should be around 14 chars 04623 Q_ASSERT(item->length < 32); 04624 04625 MMDEBUG("\nsyllable from %d len %d, str='%s'", item->from, item->length, 04626 item->string->mid(item->from, item->length).toUtf8().data()); 04627 04628 const QChar *uc = item->string->unicode() + item->from; 04629 #ifdef MYANMAR_DEBUG 04630 qDebug("original:"); 04631 for (int i = 0; i < item->length; i++) { 04632 qDebug(" %d: %4x", i, uc[i].unicode()); 04633 } 04634 #endif 04635 int vowel_e = -1; 04636 int kinzi = -1; 04637 int medial_ra = -1; 04638 int base = -1; 04639 04640 for (int i = 0; i < item->length; ++i) { 04641 ushort chr = uc[i].unicode(); 04642 04643 if (chr == Mymr_C_VOWEL_E) { 04644 vowel_e = i; 04645 continue; 04646 } 04647 if (i == 0 04648 && chr == Mymr_C_NGA 04649 && i + 2 < item->length 04650 && uc[i+1].unicode() == Mymr_C_VIRAMA) { 04651 int mc = getMyanmarCharClass(uc[i+2]); 04652 //MMDEBUG("maybe kinzi: mc=%x", mc); 04653 if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) { 04654 kinzi = i; 04655 continue; 04656 } 04657 } 04658 if (base >= 0 04659 && chr == Mymr_C_VIRAMA 04660 && i + 1 < item->length 04661 && uc[i+1].unicode() == Mymr_C_RA) { 04662 medial_ra = i; 04663 continue; 04664 } 04665 if (base < 0) 04666 base = i; 04667 } 04668 04669 MMDEBUG("\n base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra); 04670 int len = 0; 04671 unsigned short reordered[32]; 04672 unsigned char properties[32]; 04673 enum { 04674 AboveForm = 0x01, 04675 PreForm = 0x02, 04676 PostForm = 0x04, 04677 BelowForm = 0x08 04678 }; 04679 memset(properties, 0, 32*sizeof(unsigned char)); 04680 04681 // write vowel_e if found 04682 if (vowel_e >= 0) { 04683 reordered[0] = Mymr_C_VOWEL_E; 04684 len = 1; 04685 } 04686 // write medial_ra 04687 if (medial_ra >= 0) { 04688 reordered[len] = Mymr_C_VIRAMA; 04689 reordered[len+1] = Mymr_C_RA; 04690 properties[len] = PreForm; 04691 properties[len+1] = PreForm; 04692 len += 2; 04693 } 04694 04695 // shall we add a dotted circle? 04696 // If in the position in which the base should be (first char in the string) there is 04697 // a character that has the Dotted circle flag (a character that cannot be a base) 04698 // then write a dotted circle 04699 if (invalid) { 04700 reordered[len] = C_DOTTED_CIRCLE; 04701 ++len; 04702 } 04703 04704 bool lastWasVirama = false; 04705 int basePos = -1; 04706 // copy the rest of the syllable to the output, inserting the kinzi 04707 // at the correct place 04708 for (int i = 0; i < item->length; ++i) { 04709 if (i == vowel_e) 04710 continue; 04711 if (i == medial_ra || i == kinzi) { 04712 ++i; 04713 continue; 04714 } 04715 04716 ushort chr = uc[i].unicode(); 04717 MymrCharClass cc = getMyanmarCharClass(uc[i]); 04718 if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) { 04719 reordered[len] = Mymr_C_NGA; 04720 reordered[len+1] = Mymr_C_VIRAMA; 04721 properties[len-1] = AboveForm; 04722 properties[len] = AboveForm; 04723 len += 2; 04724 kinzi = -1; 04725 } 04726 04727 if (lastWasVirama) { 04728 int prop = 0; 04729 switch(cc & Mymr_CF_POS_MASK) { 04730 case Mymr_CF_POS_BEFORE: 04731 prop = PreForm; 04732 break; 04733 case Mymr_CF_POS_BELOW: 04734 prop = BelowForm; 04735 break; 04736 case Mymr_CF_POS_ABOVE: 04737 prop = AboveForm; 04738 break; 04739 case Mymr_CF_POS_AFTER: 04740 prop = PostForm; 04741 break; 04742 default: 04743 break; 04744 } 04745 properties[len-1] = prop; 04746 properties[len] = prop; 04747 if(basePos >= 0 && basePos == len-2) 04748 properties[len-2] = prop; 04749 } 04750 lastWasVirama = (chr == Mymr_C_VIRAMA); 04751 if(i == base) 04752 basePos = len; 04753 04754 if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) { 04755 reordered[len] = chr; 04756 ++len; 04757 } 04758 } 04759 if (kinzi >= 0) { 04760 reordered[len] = Mymr_C_NGA; 04761 reordered[len+1] = Mymr_C_VIRAMA; 04762 properties[len] = AboveForm; 04763 properties[len+1] = AboveForm; 04764 len += 2; 04765 } 04766 04767 #ifndef QT_NO_OPENTYPE 04768 const int availableGlyphs = item->num_glyphs; 04769 #endif 04770 if (!item->font->stringToCMap((const QChar *)reordered, len, item->glyphs, &item->num_glyphs, QFlag(item->flags))) 04771 return false; 04772 04773 MMDEBUG("after shaping: