char hb_utf16_script_run_next(unsigned *num_code_points, HB_ScriptItem *output, const uint16_t *chars, size_t len, ssize_t *iter) { if (*iter == len) return 0; output->pos = *iter; const uint32_t init_cp = utf16_to_code_point(chars, len, iter); unsigned cps = 1; if (init_cp == HB_InvalidCodePoint) return 0; const HB_Script init_script = code_point_to_script(init_cp); HB_Script current_script = init_script; output->script = init_script; for (;;) { if (*iter == len) break; const ssize_t prev_iter = *iter; const uint32_t cp = utf16_to_code_point(chars, len, iter); if (cp == HB_InvalidCodePoint) return 0; cps++; const HB_Script script = code_point_to_script(cp); if (script != current_script) { /* BEGIN android-changed The condition was not correct by doing "a == b == constant" END android-changed */ if (current_script == HB_Script_Inherited && init_script == HB_Script_Inherited) { // If we started off as inherited, we take whatever we can find. output->script = script; current_script = script; continue; } else if (script == HB_Script_Inherited) { continue; } else { *iter = prev_iter; cps--; break; } } } if (output->script == HB_Script_Inherited) output->script = HB_Script_Common; output->length = *iter - output->pos; if (num_code_points) *num_code_points = cps; return 1; }
static HB_Bool hb_freetype_can_render(HB_Font font, const HB_UChar16 *chars, hb_uint32 len) { FT_Face face = (FT_Face)font->userData; size_t i = 0; while (i < len) { const uint32_t cp = utf16_to_code_point(chars, len, &i); if (FT_Get_Char_Index(face, cp) == 0) return 0; } return 1; }
static HB_Bool hb_freetype_string_to_glyphs(HB_Font font, const HB_UChar16 *chars, hb_uint32 len, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool is_rtl) { FT_Face face = (FT_Face) font->userData; if (len > *numGlyphs) return 0; size_t i = 0, j = 0; while (i < len) { const uint32_t cp = utf16_to_code_point(chars, len, &i); glyphs[j++] = FT_Get_Char_Index(face, cp); } *numGlyphs = j; return 1; }
// Return the code point index for the given |x| offset into the text run. int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const { // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) TextRunWalker walker(run, 0, this); // If this is RTL text, the first glyph from the left is actually the last // code point. So we need to know how many code points there are total in // order to subtract. This is different from the length of the TextRun // because UTF-16 surrogate pairs are a single code point, but 32-bits long. // In LTR we leave this as 0 so that we get the correct value for // |basePosition|, below. unsigned totalCodePoints = 0; if (walker.rtl()) { ssize_t offset = 0; while (offset < run.length()) { utf16_to_code_point(run.characters(), run.length(), &offset); totalCodePoints++; } } unsigned basePosition = totalCodePoints; // For RTL: // code-point order: abcd efg hijkl // on screen: lkjih gfe dcba // ^ ^ // | | // basePosition--| | // totalCodePoints----| // Since basePosition is currently the total number of code-points, the // first thing we do is decrement it so that it's pointing to the start of // the current script-run. // // For LTR, basePosition is zero so it already points to the start of the // first script run. while (walker.nextScriptRun()) { if (walker.rtl()) basePosition -= walker.numCodePoints(); if (x < walker.width()) { // The x value in question is within this script run. We consider // each glyph in presentation order and stop when we find the one // covering this position. const int glyphIndex = glyphIndexForXPositionInScriptRun(walker, x); // Now that we have a glyph index, we have to turn that into a // code-point index. Because of ligatures, several code-points may // have gone into a single glyph. We iterate over the clusters log // and find the first code-point which contributed to the glyph. // Some shapers (i.e. Khmer) will produce cluster logs which report // that /no/ code points contributed to certain glyphs. Because of // this, we take any code point which contributed to the glyph in // question, or any subsequent glyph. If we run off the end, then // we take the last code point. const unsigned short* log = walker.logClusters(); for (unsigned j = 0; j < walker.numCodePoints(); ++j) { if (log[j] >= glyphIndex) return basePosition + j; } return basePosition + walker.numCodePoints() - 1; } x -= walker.width(); if (!walker.rtl()) basePosition += walker.numCodePoints(); } return basePosition; }