int findNextGraphiteBreak(void) { int ret = -1; if (grSegment != NULL) { if (grPrevSlot && grPrevSlot != gr_seg_last_slot(grSegment)) { for (const gr_slot* s = gr_slot_next_in_segment(grPrevSlot); s != NULL; s = gr_slot_next_in_segment(s)) { const gr_char_info* ci = NULL; int bw; ci = gr_seg_cinfo(grSegment, gr_slot_index(s)); bw = gr_cinfo_break_weight(ci); if (bw < gr_breakNone && bw >= gr_breakBeforeWord) { grPrevSlot = s; ret = gr_cinfo_base(ci); } else if (bw > gr_breakNone && bw <= gr_breakWord) { grPrevSlot = gr_slot_next_in_segment(s); ret = gr_cinfo_base(ci) + 1; } if (ret != -1) break; } if (ret == -1) { grPrevSlot = gr_seg_last_slot(grSegment); ret = grTextLen; } } } return ret; }
cluster_t *GraphiteLayoutShaper::getCluster(gr_segment *segment, size_t numCodePoints) { const gr_slot *is; int ic, ci = 0; cluster_t *clusters = (cluster_t *) malloc(numCodePoints * sizeof(cluster_t)); memset(clusters, 0, numCodePoints * sizeof(cluster_t)); for (is = gr_seg_first_slot(segment), ic = 0; is; is = gr_slot_next_in_segment(is), ic++) { unsigned int before = gr_slot_before(is); unsigned int after = gr_slot_after(is); while (clusters[ci].base_char > before && ci) { clusters[ci - 1].num_chars += clusters[ci].num_chars; clusters[ci - 1].num_glyphs += clusters[ci].num_glyphs; --ci; } if (gr_slot_can_insert_before(is) && clusters[ci].num_chars && before >= clusters[ci].base_char + clusters[ci].num_chars) { cluster_t *c = clusters + ci + 1; c->base_char = clusters[ci].base_char + clusters[ci].num_chars; c->num_chars = before - c->base_char; c->base_glyph = ic; c->num_glyphs = 0; ++ci; } ++clusters[ci].num_glyphs; if (clusters[ci].base_char + clusters[ci].num_chars < after + 1) { clusters[ci].num_chars = after + 1 - clusters[ci].base_char; } } return clusters; }
jfloat GraphiteLayoutShaper::shapeScriptRun(const SkPaint* paint, const UChar* chars, size_t count, bool isRTL, Vector<jfloat>* const outAdvances, Vector<jchar>* const outGlyphs, Vector<jfloat>* const outPos, jfloat startXPosition, uint32_t startScriptRun, size_t glyphBaseCount) { ALOGD("Shape Scrit Run with Graphite"); SkTypeface *typeface = paint->getTypeface(); mShapingGrFace = getCachedGrFace(typeface); unsigned int x_ppem; unsigned int y_ppem; int x_scale; int y_scale; getConversionFactor(x_ppem, y_ppem, x_scale, y_scale, paint); mShapingGrFont = gr_make_font_with_ops(x_ppem, paint, &GraphiteFontOps, mShapingGrFace); const uint16_t *charsScriptStart = chars ; const uint16_t *charsScriptEnd = chars + count; size_t numCP; char *pError; numCP = gr_count_unicode_characters(gr_utf16, charsScriptStart, charsScriptEnd, (const void **)(&pError)); #if DEBUG_GLYPHS ALOGD("Myanmar shape with Graphite, numCP = %d, grFont = %p, grFace = %p, pError = %p", numCP, mShapingGrFont, mShapingGrFace, pError); #endif if(!mShapingGrFont || !mShapingGrFace || pError) { ALOGD("Invalid grFont is NULL, grFace is NULL or parse string error."); return 0.0; } mShapingSegment = gr_make_seg(mShapingGrFont, mShapingGrFace, 0, 0, gr_utf16, charsScriptStart, numCP, isRTL); cluster_t *clusters = getCluster(mShapingSegment, numCP); #if DEBUG_GLYPHS ALOGD("Got from Graphite"); #endif const gr_slot *slot; size_t glyphIndex, clusterIndex = 0; jfloat totalFontRunAdvance = 0; for (slot = gr_seg_first_slot(mShapingSegment), glyphIndex = 0; slot; slot = gr_slot_next_in_segment(slot), ++ glyphIndex) { #if DEBUG_GLYPHS ALOGD(" -- Glyph = %d, origin = (%f, %f), advance = (%f, %f)\n", gr_slot_gid(slot), gr_slot_origin_X(slot), gr_slot_origin_Y(slot), gr_slot_advance_X(slot, mShapingGrFace, mShapingGrFont), gr_slot_advance_Y(slot, mShapingGrFace, mShapingGrFont)); #endif if(glyphIndex == clusters[clusterIndex].base_glyph + clusters[clusterIndex].num_glyphs) { uint32_t clusterStart = clusters[clusterIndex].base_char + startScriptRun; jfloat startOrigin = outAdvances->itemAt(clusterStart); jfloat advance = gr_slot_origin_X(slot) - startOrigin; outAdvances->replaceAt(advance, clusterStart); ++ clusterIndex; clusterStart = clusters[clusterIndex].base_char + startScriptRun; outAdvances->replaceAt(gr_slot_origin_X(slot), clusterStart); } jfloat charRight = gr_slot_origin_X(slot) + gr_slot_advance_X(slot, mShapingGrFace, mShapingGrFont); if (charRight > totalFontRunAdvance) { totalFontRunAdvance = charRight; } jchar glyph = glyphBaseCount + gr_slot_gid(slot); outGlyphs->add(glyph); outPos->add(startXPosition + gr_slot_origin_X(slot)); outPos->add(gr_slot_origin_Y(slot)); } uint32_t clusterStart = clusters[clusterIndex].base_char + startScriptRun; jfloat startOrigin = outAdvances->itemAt(clusterStart); jfloat advance = totalFontRunAdvance - startOrigin; outAdvances->replaceAt(advance, clusterStart); if(mShapingSegment) { gr_seg_destroy(mShapingSegment); mShapingSegment = NULL; } if(mShapingGrFont) { gr_font_destroy(mShapingGrFont); mShapingGrFont = NULL; } #if DEBUG_GLYPHS ALOGD(" -- totalFontRunAdvance = %f", totalFontRunAdvance); #endif return totalFontRunAdvance; }