src/gui/text/qscriptengine.cpp File Reference

#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 Documentation

#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 Documentation

typedef unsigned long KhmerCharClass

Definition at line 3878 of file qscriptengine.cpp.

typedef int MymrCharClass

Definition at line 4476 of file qscriptengine.cpp.


Enumeration Type Documentation

anonymous enum

Definition at line 343 of file qscriptengine.cpp.

00343      {
00344     CcmpProperty = 0x1
00345 };

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.

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

Definition at line 4949 of file qscriptengine.cpp.

04949                 {
04950     L,
04951     V,
04952     T,
04953     LV,
04954     LVT,
04955     X
04956 };

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 IndicScriptProperties

Definition at line 2506 of file qscriptengine.cpp.

02506                            {
02507     HasReph = 0x01,
02508     HasSplit = 0x02
02509 };

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 };

enum KhmerCharClassesRange

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

Definition at line 2063 of file qscriptengine.cpp.

02063               {
02064     None,
02065     Pre,
02066     Above,
02067     Below,
02068     Post,
02069     Split,
02070     Base,
02071     Reph,
02072     Vattu,
02073     Inherit
02074 };

enum TibetanForm

Definition at line 3521 of file qscriptengine.cpp.


Function Documentation

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: