📄 qopentype.cpp
字号:
// reset kerning_feature_selected = false; if (gpos) { HB_GPOS_Clear_Features(gpos); FT_UShort script_index; FT_Error error = HB_GPOS_Select_Script(gpos, tag, &script_index); if (!error) {#ifdef OT_DEBUG { HB_FeatureList featurelist = gpos->FeatureList; int numfeatures = featurelist.FeatureCount; DEBUG("gpos table has %d features", numfeatures); for(int i = 0; i < numfeatures; i++) { HB_FeatureRecord *r = featurelist.FeatureRecord + i; FT_UShort feature_index; HB_GPOS_Select_Feature(gpos, r->FeatureTag, script_index, 0xffff, &feature_index); DEBUG(" feature '%s'", tag_to_string(r->FeatureTag)); } }#endif FT_ULong *feature_tag_list_buffer; error = HB_GPOS_Query_Features(gpos, script_index, 0xffff, &feature_tag_list_buffer); if (!error) { FT_ULong *feature_tag_list = feature_tag_list_buffer; while (*feature_tag_list) { FT_UShort feature_index; if (*feature_tag_list == FT_MAKE_TAG('k', 'e', 'r', 'n')) { if (!item->kerning_enabled) { ++feature_tag_list; continue; } kerning_feature_selected = true; } error = HB_GPOS_Select_Feature(gpos, *feature_tag_list, script_index, 0xffff, &feature_index); if (!error) { HB_GPOS_Add_Feature(gpos, feature_index, PositioningProperties); has_features = true; } ++feature_tag_list; } FT_Memory memory = gpos->memory; FREE(feature_tag_list_buffer); } } } current_script = script;}extern void qt_heuristicPosition(QShaperItem *item);bool QOpenType::shape(QShaperItem *item, const unsigned int *properties){ if (!has_features) return true; length = item->num_glyphs; hb_buffer_clear(hb_buffer); if (allocated < length) { tmpAttributes = (QGlyphLayout::Attributes *) realloc(tmpAttributes, length*sizeof(QGlyphLayout::Attributes)); tmpLogClusters = (unsigned int *) realloc(tmpLogClusters, length*sizeof(unsigned int)); allocated = length; } for (int i = 0; i < length; ++i) { hb_buffer_add_glyph(hb_buffer, item->glyphs[i].glyph, properties ? properties[i] : 0, i); tmpAttributes[i] = item->glyphs[i].attributes; tmpLogClusters[i] = item->log_clusters[i]; }#ifdef OT_DEBUG DEBUG("-----------------------------------------");// DEBUG("log clusters before shaping:");// for (int j = 0; j < length; j++)// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); DEBUG("original glyphs: %p", item->glyphs); for (int i = 0; i < length; ++i) DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex);// dump_string(hb_buffer);#endif // ### FT_LOAD_NO_HINTING might give problems here, see comment about MingLiu in qfontengine_ft.cpp loadFlags = item->flags & QTextEngine::DesignMetrics ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT; glyphs_substituted = false; if (gsub) { uint error = HB_GSUB_Apply_String(gsub, hb_buffer); if (error && error != HB_Err_Not_Covered) return false; glyphs_substituted = (error != HB_Err_Not_Covered); }#ifdef OT_DEBUG// DEBUG("log clusters before shaping:");// for (int j = 0; j < length; j++)// DEBUG(" log[%d] = %d", j, item->log_clusters[j]); DEBUG("shaped glyphs:"); for (int i = 0; i < length; ++i) DEBUG(" glyph=%4x", hb_buffer->in_string[i].gindex); DEBUG("-----------------------------------------");// dump_string(hb_buffer);#endif return true;}bool QOpenType::positionAndAdd(QShaperItem *item, int availableGlyphs, bool doLogClusters){ if (!has_features) return true; bool glyphs_positioned = false; if (gpos) { switch (fontEngine->type()) {#ifndef QT_NO_FREETYPE case QFontEngine::Freetype: face = static_cast<QFontEngineFT *>(fontEngine)->lockFace(); break;#endif#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) && !defined(QT_NO_FREETYPE) case QFontEngine::QPF2: face = static_cast<QFontEngineQPF *>(fontEngine)->lockFace(); break;#endif default: Q_ASSERT(false); } memset(hb_buffer->positions, 0, hb_buffer->in_length*sizeof(HB_PositionRec)); // #### check that passing "false,false" is correct glyphs_positioned = HB_GPOS_Apply_String(face, gpos, loadFlags, hb_buffer, false, false) != HB_Err_Not_Covered; switch (fontEngine->type()) { case QFontEngine::Freetype:#ifndef QT_NO_FREETYPE static_cast<QFontEngineFT *>(fontEngine)->unlockFace(); break;#endif#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) && !defined(QT_NO_FREETYPE) case QFontEngine::QPF2: static_cast<QFontEngineQPF *>(fontEngine)->unlockFace(); break;#endif default: break; } } if (!glyphs_substituted && !glyphs_positioned) return true; // nothing to do for us // make sure we have enough space to write everything back if (availableGlyphs < (int)hb_buffer->in_length) { item->num_glyphs = hb_buffer->in_length; return false; } QGlyphLayout *glyphs = item->glyphs; for (unsigned int i = 0; i < hb_buffer->in_length; ++i) { glyphs[i].glyph = hb_buffer->in_string[i].gindex; glyphs[i].attributes = tmpAttributes[hb_buffer->in_string[i].cluster]; if (i && hb_buffer->in_string[i].cluster == hb_buffer->in_string[i-1].cluster) glyphs[i].attributes.clusterStart = false; } item->num_glyphs = hb_buffer->in_length; if (doLogClusters) { // we can't do this for indic, as we pass the stuf in syllables and it's easier to do it in the shaper. unsigned short *logClusters = item->log_clusters; int clusterStart = 0; int oldCi = 0; for (unsigned int i = 0; i < hb_buffer->in_length; ++i) { int ci = hb_buffer->in_string[i].cluster; // DEBUG(" ci[%d] = %d mark=%d, cmb=%d, cs=%d", // i, ci, glyphAttributes[i].mark, glyphAttributes[i].combiningClass, glyphAttributes[i].clusterStart); if (!glyphs[i].attributes.mark && glyphs[i].attributes.clusterStart && ci != oldCi) { for (int j = oldCi; j < ci; j++) logClusters[j] = clusterStart; clusterStart = i; oldCi = ci; } } for (int j = oldCi; j < length; j++) logClusters[j] = clusterStart; } // calulate the advances for the shaped glyphs// DEBUG("unpositioned: "); if (glyphs_substituted) item->font->recalcAdvances(item->num_glyphs, glyphs, QFlag(item->flags)); // positioning code: if (gpos && glyphs_positioned) { HB_Position positions = hb_buffer->positions;// DEBUG("positioned glyphs:"); for (unsigned int i = 0; i < hb_buffer->in_length; i++) {// DEBUG(" %d:\t orig advance: (%d/%d)\tadv=(%d/%d)\tpos=(%d/%d)\tback=%d\tnew_advance=%d", i,// glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(),// (int)(positions[i].x_advance >> 6), (int)(positions[i].y_advance >> 6),// (int)(positions[i].x_pos >> 6), (int)(positions[i].y_pos >> 6),// positions[i].back, positions[i].new_advance); // ###### fix the case where we have y advances. How do we handle this in Uniscribe????? QFixed xValue = QFixed::fromFixed(item->flags & QTextEngine::RightToLeft ? -positions[i].x_advance : positions[i].x_advance); QFixed yValue = QFixed::fromFixed(-positions[i].y_advance); if (!(item->flags & QTextEngine::DesignMetrics)) { xValue = xValue.round(); yValue = yValue.round(); } if (positions[i].new_advance) { glyphs[i].advance.x = xValue; glyphs[i].advance.y = yValue; } else { glyphs[i].advance.x += xValue; glyphs[i].advance.y += yValue; } int back = 0; glyphs[i].offset.x = QFixed::fromFixed(positions[i].x_pos); glyphs[i].offset.y = QFixed::fromFixed(positions[i].y_pos); while (positions[i - back].back) { back += positions[i - back].back; glyphs[i].offset.x += QFixed::fromFixed(positions[i - back].x_pos); glyphs[i].offset.y += QFixed::fromFixed(positions[i - back].y_pos); } glyphs[i].offset.y = -glyphs[i].offset.y; if (item->flags & QTextEngine::RightToLeft) { // ### may need to go back multiple glyphs like in ltr back = positions[i].back; while (back--) { glyphs[i].offset.x -= glyphs[i-back].advance.x; glyphs[i].offset.y -= -glyphs[i-back].advance.y; } } else { back = 0; while (positions[i - back].back) { back += positions[i - back].back; glyphs[i].offset.x -= glyphs[i-back].advance.x; glyphs[i].offset.y -= -glyphs[i-back].advance.y; } }// DEBUG(" ->\tadv=%d\tpos=(%d/%d)",// glyphs[i].advance.x.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); } item->kerning_applied = kerning_feature_selected; } else { qt_heuristicPosition(item); }#ifdef OT_DEBUG if (doLogClusters) { DEBUG("log clusters after shaping:"); for (int j = 0; j < length; j++) DEBUG(" log[%d] = %d", j, item->log_clusters[j]); } DEBUG("final glyphs:"); for (int i = 0; i < (int)hb_buffer->in_length; ++i) DEBUG(" glyph=%4x char_index=%d mark: %d cmp: %d, clusterStart: %d advance=%d/%d offset=%d/%d", glyphs[i].glyph, hb_buffer->in_string[i].cluster, glyphs[i].attributes.mark, glyphs[i].attributes.combiningClass, glyphs[i].attributes.clusterStart, glyphs[i].advance.x.toInt(), glyphs[i].advance.y.toInt(), glyphs[i].offset.x.toInt(), glyphs[i].offset.y.toInt()); DEBUG("-----------------------------------------");#endif return true;}#endif // QT_NO_FREETYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -