Optimize stringToCMap() usage
CMAP guarantees there is 1:1 mapping between the Unicode code points array and the glyph indexes array, which means the QString length always greater than or equal to a sufficient glyph indexes array length. Simply add some asserts and improve the memory consumption and the performance where possible. Change-Id: I0bc8cdba5f86c1c0ba9e79c8d5f96cbe56ec463e Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
93aec932ff
commit
4e319ca4c4
@ -5845,11 +5845,8 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
|
||||
int numGlyphs = len;
|
||||
QVarLengthGlyphLayoutArray glyphs(len);
|
||||
QFontEngine *fontEngine = d->state->font.d->engineForScript(QChar::Script_Common);
|
||||
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0)) {
|
||||
glyphs.resize(numGlyphs);
|
||||
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
|
||||
}
|
||||
if (!fontEngine->stringToCMap(str.data(), len, &glyphs, &numGlyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
|
||||
QTextItemInt gf(glyphs, &d->state->font, str.data(), len, fontEngine);
|
||||
drawTextItem(p, gf);
|
||||
|
@ -739,13 +739,19 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
|
||||
if (!fe)
|
||||
return false;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
const QChar uc(QLatin1Char('O'));
|
||||
|
||||
glyph_t glyph;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
int numGlyphs = 1;
|
||||
QChar uc = QLatin1Char('O');
|
||||
fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly);
|
||||
|
||||
if (!fe->stringToCMap(&uc, 1, &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(numGlyphs == 1);
|
||||
|
||||
QImage im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
|
||||
|
||||
Q_ASSERT(fe->ref.load() == 0);
|
||||
|
@ -2533,7 +2533,9 @@ bool QFontInfo::fixedPitch() const
|
||||
QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
|
||||
QGlyphLayoutArray<2> g;
|
||||
int l = 2;
|
||||
engine->stringToCMap(ch, 2, &g, &l, 0);
|
||||
if (!engine->stringToCMap(ch, 2, &g, &l, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(l == 2);
|
||||
engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
|
||||
engine->fontDef.fixedPitchComputed = true;
|
||||
}
|
||||
|
@ -384,23 +384,39 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix
|
||||
|
||||
QFixed QFontEngine::xHeight() const
|
||||
{
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
QChar x((ushort)'x');
|
||||
stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
|
||||
|
||||
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
|
||||
return bb.height;
|
||||
}
|
||||
|
||||
QFixed QFontEngine::averageCharWidth() const
|
||||
{
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
QChar x((ushort)'x');
|
||||
stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly);
|
||||
|
||||
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyphs.glyphs[0]);
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!stringToCMap(&x, 1, &glyphs, &nglyphs, GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
glyph_metrics_t bb = const_cast<QFontEngine *>(this)->boundingBox(glyph);
|
||||
return bb.xoff;
|
||||
}
|
||||
|
||||
@ -459,11 +475,22 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
|
||||
++current;
|
||||
if (glyphs.justifications[i].nKashidas) {
|
||||
QChar ch(0x640); // Kashida character
|
||||
QGlyphLayoutArray<8> g;
|
||||
int nglyphs = 7;
|
||||
stringToCMap(&ch, 1, &g, &nglyphs, 0);
|
||||
|
||||
glyph_t kashidaGlyph;
|
||||
QFixed kashidaWidth;
|
||||
|
||||
QGlyphLayout g;
|
||||
g.numGlyphs = 1;
|
||||
g.glyphs = &kashidaGlyph;
|
||||
g.advances = &kashidaWidth;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!stringToCMap(&ch, 1, &g, &nglyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
for (uint k = 0; k < glyphs.justifications[i].nKashidas; ++k) {
|
||||
xpos -= g.advances[0];
|
||||
xpos -= kashidaWidth;
|
||||
|
||||
QFixed gpos_x = xpos + glyphs.offsets[i].x;
|
||||
QFixed gpos_y = ypos + glyphs.offsets[i].y;
|
||||
@ -475,7 +502,7 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
|
||||
}
|
||||
positions[current].x = gpos_x;
|
||||
positions[current].y = gpos_y;
|
||||
glyphs_out[current] = g.glyphs[0];
|
||||
glyphs_out[current] = kashidaGlyph;
|
||||
++current;
|
||||
}
|
||||
} else {
|
||||
@ -1536,9 +1563,10 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
|
||||
if (!(flags & GlyphIndicesOnly))
|
||||
glyphs->advances[glyph_pos] = QFixed();
|
||||
int num = 2;
|
||||
QGlyphLayout offs = glyphs->mid(glyph_pos, num);
|
||||
engine->stringToCMap(str + i, surrogate ? 2 : 1, &offs, &num, flags);
|
||||
Q_ASSERT(num == 1); // surrogates only give 1 glyph
|
||||
QGlyphLayout g = glyphs->mid(glyph_pos, num);
|
||||
if (!engine->stringToCMap(str + i, surrogate ? 2 : 1, &g, &num, flags))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(num == 1);
|
||||
if (glyphs->glyphs[glyph_pos]) {
|
||||
// set the high byte to indicate which engine the glyph came from
|
||||
glyphs->glyphs[glyph_pos] |= (x << 24);
|
||||
@ -1849,16 +1877,11 @@ bool QFontEngineMulti::canRender(const QChar *string, int len)
|
||||
QGlyphLayout g;
|
||||
g.numGlyphs = nglyphs;
|
||||
g.glyphs = glyphs.data();
|
||||
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly)) {
|
||||
glyphs.resize(nglyphs);
|
||||
g.numGlyphs = nglyphs;
|
||||
g.glyphs = glyphs.data();
|
||||
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
|
||||
}
|
||||
if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
|
||||
for (int i = 0; i < nglyphs; i++) {
|
||||
if (g.glyphs[i] == 0)
|
||||
if (glyphs[i] == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1274,13 +1274,22 @@ qreal QFontEngineFT::minRightBearing() const
|
||||
{
|
||||
if (rbearing == SHRT_MIN) {
|
||||
lbearing = rbearing = 0;
|
||||
const QChar *ch = (const QChar *)(const void*)char_table;
|
||||
QGlyphLayoutArray<char_table_entries> glyphs;
|
||||
|
||||
const QChar *ch = reinterpret_cast<const QChar *>(char_table);
|
||||
|
||||
glyph_t glyphs[char_table_entries];
|
||||
|
||||
QGlyphLayout g;
|
||||
g.glyphs = glyphs;
|
||||
g.numGlyphs = char_table_entries;
|
||||
int ng = char_table_entries;
|
||||
stringToCMap(ch, char_table_entries, &glyphs, &ng, GlyphIndicesOnly);
|
||||
if (!stringToCMap(ch, char_table_entries, &g, &ng, GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(ng == char_table_entries);
|
||||
|
||||
while (--ng) {
|
||||
if (glyphs.glyphs[ng]) {
|
||||
glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs.glyphs[ng]);
|
||||
if (glyphs[ng]) {
|
||||
glyph_metrics_t gi = const_cast<QFontEngineFT *>(this)->boundingBox(glyphs[ng]);
|
||||
lbearing = qMin(lbearing, gi.x);
|
||||
rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width));
|
||||
}
|
||||
|
@ -458,12 +458,19 @@ int QFontMetrics::leftBearing(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
// ### can nglyphs != 1 happen at all? Not currently I think
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
qreal lb;
|
||||
engine->getGlyphBearings(glyphs.glyphs[0], &lb);
|
||||
engine->getGlyphBearings(glyph, &lb);
|
||||
return qRound(lb);
|
||||
}
|
||||
|
||||
@ -493,12 +500,19 @@ int QFontMetrics::rightBearing(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
// ### can nglyphs != 1 happen at all? Not currently I think
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
qreal rb;
|
||||
engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
|
||||
engine->getGlyphBearings(glyph, 0, &rb);
|
||||
return qRound(rb);
|
||||
}
|
||||
|
||||
@ -538,11 +552,8 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
|
||||
int numGlyphs = len;
|
||||
QVarLengthGlyphLayoutArray glyphs(numGlyphs);
|
||||
QFontEngine *engine = d->engineForScript(QChar::Script_Common);
|
||||
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0)) {
|
||||
glyphs.resize(numGlyphs);
|
||||
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
|
||||
}
|
||||
if (!engine->stringToCMap(text.data(), len, &glyphs, &numGlyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
|
||||
QFixed width;
|
||||
for (int i = 0; i < numGlyphs; ++i)
|
||||
@ -594,10 +605,20 @@ int QFontMetrics::width(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
|
||||
return qRound(glyphs.advances[0]);
|
||||
QFixed advance;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyph_t glyph;
|
||||
glyphs.glyphs = &glyph;
|
||||
glyphs.advances = &advance;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
return qRound(advance);
|
||||
}
|
||||
|
||||
/*! \obsolete
|
||||
@ -639,10 +660,20 @@ int QFontMetrics::charWidth(const QString &text, int pos) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
|
||||
width = qRound(glyphs.advances[0]);
|
||||
QFixed advance;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyph_t glyph;
|
||||
glyphs.glyphs = &glyph;
|
||||
glyphs.advances = &advance;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
width = qRound(advance);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
@ -708,10 +739,18 @@ QRect QFontMetrics::boundingRect(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
glyph_metrics_t gm = engine->boundingBox(glyph);
|
||||
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
|
||||
}
|
||||
|
||||
@ -1326,12 +1365,19 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
// ### can nglyphs != 1 happen at all? Not currently I think
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
qreal lb;
|
||||
engine->getGlyphBearings(glyphs.glyphs[0], &lb);
|
||||
engine->getGlyphBearings(glyph, &lb);
|
||||
return lb;
|
||||
}
|
||||
|
||||
@ -1361,12 +1407,19 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
// ### can nglyphs != 1 happen at all? Not currently I think
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
qreal rb;
|
||||
engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
|
||||
engine->getGlyphBearings(glyph, 0, &rb);
|
||||
return rb;
|
||||
|
||||
}
|
||||
@ -1431,10 +1484,20 @@ qreal QFontMetricsF::width(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
|
||||
return glyphs.advances[0].toReal();
|
||||
QFixed advance;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyph_t glyph;
|
||||
glyphs.glyphs = &glyph;
|
||||
glyphs.advances = &advance;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
return advance.toReal();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1496,10 +1559,18 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const
|
||||
|
||||
d->alterCharForCapitalization(ch);
|
||||
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
int nglyphs = 9;
|
||||
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
glyph_metrics_t gm = engine->boundingBox(glyphs.glyphs[0]);
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &glyph;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
glyph_metrics_t gm = engine->boundingBox(glyph);
|
||||
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
|
||||
}
|
||||
|
||||
|
@ -201,12 +201,22 @@ static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
|
||||
QVector<int> QFontSubset::getReverseMap() const
|
||||
{
|
||||
QVector<int> reverseMap(0x10000, 0);
|
||||
QGlyphLayoutArray<10> glyphs;
|
||||
|
||||
glyph_t glyph;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.glyphs = &glyph;
|
||||
glyphs.numGlyphs = 1;
|
||||
|
||||
for (uint uc = 0; uc < 0x10000; ++uc) {
|
||||
QChar ch(uc);
|
||||
int nglyphs = 10;
|
||||
fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly);
|
||||
int idx = glyph_indices.indexOf(glyphs.glyphs[0]);
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
int idx = glyph_indices.indexOf(glyph);
|
||||
if (idx >= 0 && !reverseMap.at(idx))
|
||||
reverseMap[idx] = uc;
|
||||
}
|
||||
|
@ -397,13 +397,7 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
|
||||
QFontEngine *fe = (QFontEngine *)font_data;
|
||||
Q_ASSERT(fe);
|
||||
|
||||
glyph_t glyphs[2] = { 0, 0 };
|
||||
|
||||
QGlyphLayout g;
|
||||
g.numGlyphs = 2;
|
||||
g.glyphs = glyphs;
|
||||
|
||||
QChar chars[4];
|
||||
QChar chars[2];
|
||||
int numChars = 0;
|
||||
if (Q_UNLIKELY(QChar::requiresSurrogates(unicode))) {
|
||||
chars[numChars++] = QChar(QChar::highSurrogate(unicode));
|
||||
@ -422,11 +416,14 @@ _hb_qt_font_get_glyph(hb_font_t * /*font*/, void *font_data,
|
||||
}
|
||||
#endif
|
||||
|
||||
int numGlyphs = g.numGlyphs;
|
||||
bool ok = fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly);
|
||||
Q_ASSERT(ok); Q_UNUSED(ok)
|
||||
QGlyphLayout g;
|
||||
g.numGlyphs = numChars;
|
||||
g.glyphs = glyph;
|
||||
|
||||
*glyph = g.glyphs[0];
|
||||
int numGlyphs = numChars;
|
||||
if (!fe->stringToCMap(chars, numChars, &g, &numGlyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(numGlyphs == 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -448,7 +445,7 @@ _hb_qt_font_get_glyph_h_advance(hb_font_t *font, void *font_data,
|
||||
|
||||
fe->recalcAdvances(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
|
||||
|
||||
return g.advances[0].value();
|
||||
return advance.value();
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
@ -497,7 +494,7 @@ _hb_qt_font_get_glyph_h_kerning(hb_font_t *font, void *font_data,
|
||||
|
||||
fe->doKerning(&g, QFontEngine::ShaperFlags(hb_qt_font_get_use_design_metrics(font)));
|
||||
|
||||
return g.advances[0].value();
|
||||
return advance.value();
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
|
@ -479,16 +479,8 @@ QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = numGlyphs;
|
||||
glyphs.glyphs = glyphIndexes.data();
|
||||
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
|
||||
glyphIndexes.resize(numGlyphs);
|
||||
|
||||
glyphs.numGlyphs = numGlyphs;
|
||||
glyphs.glyphs = glyphIndexes.data();
|
||||
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) {
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice");
|
||||
return QVector<quint32>();
|
||||
}
|
||||
}
|
||||
if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
|
||||
Q_UNREACHABLE();
|
||||
|
||||
glyphIndexes.resize(numGlyphs);
|
||||
return glyphIndexes;
|
||||
@ -565,10 +557,11 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
|
||||
if (!d->isValid() || numGlyphs <= 0)
|
||||
return false;
|
||||
|
||||
QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.glyphs = const_cast<glyph_t *>(glyphIndexes);
|
||||
glyphs.numGlyphs = numGlyphs;
|
||||
QVarLengthArray<QFixed> tmpAdvances(numGlyphs);
|
||||
glyphs.advances = tmpAdvances.data();
|
||||
|
||||
bool design = layoutFlags & UseDesignMetrics;
|
||||
@ -578,7 +571,7 @@ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *adv
|
||||
d->fontEngine->doKerning(&glyphs, design ? QFontEngine::DesignMetrics : QFontEngine::ShaperFlag(0));
|
||||
|
||||
for (int i=0; i<numGlyphs; ++i)
|
||||
advances[i] = QPointF(glyphs.advances[i].toReal(), 0.0);
|
||||
advances[i] = QPointF(tmpAdvances[i].toReal(), 0.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -932,18 +932,8 @@ void QTextEngine::shapeText(int item) const
|
||||
|
||||
int nGlyphs = initialGlyphs.numGlyphs;
|
||||
QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
|
||||
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
|
||||
nGlyphs = qMax(nGlyphs, itemLength); // ### needed for QFontEngine::stringToCMap() to not fail twice
|
||||
if (!ensureSpace(nGlyphs)) {
|
||||
Q_UNREACHABLE(); // ### report OOM error somehow
|
||||
return;
|
||||
}
|
||||
initialGlyphs = availableGlyphs(&si);
|
||||
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags)) {
|
||||
Q_UNREACHABLE(); // ### if this happens there is a bug in the fontengine
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
|
||||
Q_UNREACHABLE();
|
||||
|
||||
uint lastEngine = 0;
|
||||
for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
|
||||
@ -2003,11 +1993,22 @@ static void set(QJustificationPoint *point, int type, const QGlyphLayout &glyph,
|
||||
|
||||
if (type >= QGlyphAttributes::Arabic_Normal) {
|
||||
QChar ch(0x640); // Kashida character
|
||||
QGlyphLayoutArray<8> glyphs;
|
||||
int nglyphs = 7;
|
||||
fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
|
||||
if (glyphs.glyphs[0] != 0 && glyphs.advances[0].value() != 0) {
|
||||
point->kashidaWidth = glyphs.advances[0];
|
||||
|
||||
glyph_t kashidaGlyph;
|
||||
QFixed kashidaWidth;
|
||||
|
||||
QGlyphLayout glyphs;
|
||||
glyphs.numGlyphs = 1;
|
||||
glyphs.glyphs = &kashidaGlyph;
|
||||
glyphs.advances = &kashidaWidth;
|
||||
|
||||
int nglyphs = 1;
|
||||
if (!fe->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nglyphs == 1);
|
||||
|
||||
if (kashidaGlyph != 0 && kashidaWidth != 0) {
|
||||
point->kashidaWidth = kashidaWidth;
|
||||
} else {
|
||||
point->type = QGlyphAttributes::NoJustification;
|
||||
point->kashidaWidth = 0;
|
||||
@ -2639,10 +2640,10 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
|
||||
if (feForEllipsis->type() == QFontEngine::Mac)
|
||||
feForEllipsis = fe;
|
||||
|
||||
if (feForEllipsis->canRender(&ellipsisChar, 1)) {
|
||||
int nGlyphs = 1;
|
||||
feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0);
|
||||
}
|
||||
int nGlyphs = 1;
|
||||
if (!feForEllipsis->stringToCMap(&ellipsisChar, 1, &ellipsisGlyph, &nGlyphs, 0))
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nGlyphs == 1);
|
||||
}
|
||||
|
||||
if (ellipsisGlyph.glyphs[0]) {
|
||||
@ -2654,8 +2655,9 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
|
||||
QGlyphLayoutArray<3> glyphs;
|
||||
int nGlyphs = 3;
|
||||
if (!fe->stringToCMap(dotDotDot.constData(), 3, &glyphs, &nGlyphs, 0))
|
||||
// should never happen...
|
||||
return layoutData->string;
|
||||
Q_UNREACHABLE();
|
||||
Q_ASSERT(nGlyphs == 3);
|
||||
|
||||
for (int i = 0; i < nGlyphs; ++i)
|
||||
ellipsisWidth += glyphs.advances[i];
|
||||
ellipsisText = dotDotDot;
|
||||
|
Loading…
x
Reference in New Issue
Block a user