Hide the justification algorithm implementation details

The justification "classes" stored in the glyph attributes
are actually a justification priorities suitable for a particular
language (script). The external API only uses the justification
metrics array calculated on top of these priorities.

Change-Id: I5b0a39e35954084c63a798b632fd6108f9ae7608
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
bb10
Konstantin Ritt 2014-02-11 02:26:57 +02:00 committed by The Qt Project
parent ead6cc40df
commit 25e34dadab
2 changed files with 45 additions and 43 deletions

View File

@ -839,6 +839,22 @@ void QTextEngine::bidiReorder(int numItems, const quint8 *levels, int *visualOrd
#endif
}
enum JustificationClass {
Justification_Prohibited = 0, // Justification can not be applied after this glyph
Justification_Arabic_Space = 1, // This glyph represents a space inside arabic text
Justification_Character = 2, // Inter-character justification point follows this glyph
Justification_Space = 4, // This glyph represents a blank outside an Arabic run
Justification_Arabic_Normal = 7, // Normal Middle-Of-Word glyph that connects to the right (begin)
Justification_Arabic_Waw = 8, // Next character is final form of Waw/Ain/Qaf/Feh
Justification_Arabic_BaRa = 9, // Next two characters are Ba + Ra/Ya/AlefMaksura
Justification_Arabic_Alef = 10, // Next character is final form of Alef/Tah/Lam/Kaf/Gaf
Justification_Arabic_HahDal = 11, // Next character is final form of Hah/Dal/Teh Marbuta
Justification_Arabic_Seen = 12, // Initial or medial form of Seen/Sad
Justification_Arabic_Kashida = 13 // User-inserted Kashida(U+0640)
};
// shape all the items that intersect with the line, taking tab widths into account to find out what text actually fits in the line.
void QTextEngine::shapeLine(const QScriptLine &line)
{
@ -1018,12 +1034,12 @@ void QTextEngine::shapeText(int item) const
}
if (wordSpacing != 0) {
for (int i = 0; i < si.num_glyphs; ++i) {
if (glyphs.attributes[i].justification == QGlyphAttributes::Space
|| glyphs.attributes[i].justification == QGlyphAttributes::Arabic_Space) {
if (glyphs.attributes[i].justification == Justification_Space
|| glyphs.attributes[i].justification == Justification_Arabic_Space) {
// word spacing only gets added once to a consecutive run of spaces (see CSS spec)
if (i + 1 == si.num_glyphs
||(glyphs.attributes[i+1].justification != QGlyphAttributes::Space
&& glyphs.attributes[i+1].justification != QGlyphAttributes::Arabic_Space))
||(glyphs.attributes[i+1].justification != Justification_Space
&& glyphs.attributes[i+1].justification != Justification_Arabic_Space))
glyphs.advances[i] += wordSpacing;
}
}
@ -1980,7 +1996,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
point->type = type;
point->glyph = glyph;
if (type >= QGlyphAttributes::Arabic_Normal) {
if (type >= Justification_Arabic_Normal) {
QChar ch(0x640); // Kashida character
glyph_t kashidaGlyph;
@ -1999,7 +2015,7 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
if (kashidaGlyph != 0 && kashidaWidth != 0) {
point->kashidaWidth = kashidaWidth;
} else {
point->type = QGlyphAttributes::NoJustification;
point->type = Justification_Prohibited;
point->kashidaWidth = 0;
}
}
@ -2067,7 +2083,7 @@ void QTextEngine::justify(const QScriptLine &line)
for (int i = 0; i < nItems; ++i) {
QScriptItem &si = layoutData->items[firstItem + i];
int kashida_type = QGlyphAttributes::Arabic_Normal;
int kashida_type = Justification_Arabic_Normal;
int kashida_pos = -1;
int start = qMax(line.from - si.position, 0);
@ -2091,11 +2107,11 @@ void QTextEngine::justify(const QScriptLine &line)
int justification = g.attributes[i].justification;
switch(justification) {
case QGlyphAttributes::NoJustification:
case Justification_Prohibited:
break;
case QGlyphAttributes::Space :
case Justification_Space:
// fall through
case QGlyphAttributes::Arabic_Space :
case Justification_Arabic_Space:
if (kashida_pos >= 0) {
// qDebug("kashida position at %d in word", kashida_pos);
set(&justificationPoints[nPoints], kashida_type, g.mid(kashida_pos), fontEngine(si));
@ -2106,19 +2122,19 @@ void QTextEngine::justify(const QScriptLine &line)
}
}
kashida_pos = -1;
kashida_type = QGlyphAttributes::Arabic_Normal;
kashida_type = Justification_Arabic_Normal;
// fall through
case QGlyphAttributes::Character :
case Justification_Character:
set(&justificationPoints[nPoints++], justification, g.mid(i), fontEngine(si));
maxJustify = qMax(maxJustify, justification);
break;
case QGlyphAttributes::Arabic_Normal :
case QGlyphAttributes::Arabic_Waw :
case QGlyphAttributes::Arabic_BaRa :
case QGlyphAttributes::Arabic_Alef :
case QGlyphAttributes::Arabic_HaaDal :
case QGlyphAttributes::Arabic_Seen :
case QGlyphAttributes::Arabic_Kashida :
case Justification_Arabic_Normal:
case Justification_Arabic_Waw:
case Justification_Arabic_BaRa:
case Justification_Arabic_Alef:
case Justification_Arabic_HahDal:
case Justification_Arabic_Seen:
case Justification_Arabic_Kashida:
if (justification >= kashida_type) {
kashida_pos = i;
kashida_type = justification;
@ -2147,9 +2163,9 @@ void QTextEngine::justify(const QScriptLine &line)
// qDebug(" minKashida=%f, need=%f", minKashida.toReal(), need.toReal());
// distribute in priority order
if (maxJustify >= QGlyphAttributes::Arabic_Normal) {
if (maxJustify >= Justification_Arabic_Normal) {
while (need >= minKashida) {
for (int type = maxJustify; need >= minKashida && type >= QGlyphAttributes::Arabic_Normal; --type) {
for (int type = maxJustify; need >= minKashida && type >= Justification_Arabic_Normal; --type) {
for (int i = 0; need >= minKashida && i < nPoints; ++i) {
if (justificationPoints[i].type == type && justificationPoints[i].kashidaWidth <= need) {
justificationPoints[i].glyph.justifications->nKashidas++;
@ -2166,7 +2182,7 @@ void QTextEngine::justify(const QScriptLine &line)
if (!need)
goto end;
maxJustify = qMin(maxJustify, int(QGlyphAttributes::Space));
maxJustify = qMin(maxJustify, int(Justification_Space));
for (int type = maxJustify; need != 0 && type > 0; --type) {
int n = 0;
for (int i = 0; i < nPoints; ++i) {

View File

@ -95,28 +95,14 @@ typedef unsigned q_hb_bitfield;
typedef quint8 q_hb_bitfield;
#endif
typedef struct {
typedef enum {
NoJustification= 0, /* Justification can't be applied after this glyph */
Arabic_Space = 1, /* This glyph represents a space inside arabic text */
Character = 2, /* Inter-character justification point follows this glyph */
Space = 4, /* This glyph represents a blank outside an Arabic run */
Arabic_Normal = 7, /* Normal Middle-Of-Word glyph that connects to the right (begin) */
Arabic_Waw = 8, /* Next character is final form of Waw/Ain/Qaf/Fa */
Arabic_BaRa = 9, /* Next two chars are Ba + Ra/Ya/AlefMaksura */
Arabic_Alef = 10, /* Next character is final form of Alef/Tah/Lam/Kaf/Gaf */
Arabic_HaaDal = 11, /* Next character is final form of Haa/Dal/Taa Marbutah */
Arabic_Seen = 12, /* Initial or Medial form Of Seen/Sad */
Arabic_Kashida = 13 /* Kashida(U+640) in middle of word */
} JustificationClass;
q_hb_bitfield justification :4; /* Justification class */
q_hb_bitfield clusterStart :1; /* First glyph of representation of cluster */
q_hb_bitfield mark :1; /* needs to be positioned around base char */
q_hb_bitfield zeroWidth :1; /* ZWJ, ZWNJ etc, with no width */
struct QGlyphAttributes {
q_hb_bitfield justification :4;
q_hb_bitfield clusterStart :1;
q_hb_bitfield unused1 :1;
q_hb_bitfield unused2 :1;
q_hb_bitfield dontPrint :1;
q_hb_bitfield combiningClass :8;
} QGlyphAttributes;
q_hb_bitfield unused3 :8;
};
// this uses the same coordinate system as Qt, but a different one to freetype.
// * y is usually negative, and is equal to the ascent.