TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) : m_font(font) , m_startingX(startingX) , m_offsetX(m_startingX) , m_run(getTextRun(run)) , m_iterateBackwards(m_run.rtl()) { // Do not use |run| inside this constructor. Use |m_run| instead. memset(&m_item, 0, sizeof(m_item)); // We cannot know, ahead of time, how many glyphs a given script run // will produce. We take a guess that script runs will not produce more // than twice as many glyphs as there are code points and fallback if // we find that we are wrong. m_maxGlyphs = m_run.length() * 2; createGlyphArrays(); m_item.log_clusters = new unsigned short[m_run.length()]; m_item.face = 0; m_item.font = allocHarfbuzzFont(); m_item.string = m_run.characters(); m_item.stringLength = m_run.length(); m_item.item.bidiLevel = m_run.rtl(); reset(); }
void shapeGlyphs() { for (;;) { if (HB_ShapeItem(&m_item)) break; // We overflowed our arrays. Resize and retry. // HB_ShapeItem fills in m_item.num_glyphs with the needed size. deleteGlyphArrays(); // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer // shaper (at least) can fail because of insufficient glyph buffers // and request 0 additional glyphs: throwing us into an infinite // loop. createGlyphArrays(m_item.num_glyphs + 1); } }
void ComplexTextController::shapeGlyphs() { // HB_ShapeItem() resets m_item.num_glyphs. If the previous call to // HB_ShapeItem() used less space than was available, the capacity of // the array may be larger than the current value of m_item.num_glyphs. // So, we need to reset the num_glyphs to the capacity of the array. m_item.num_glyphs = m_glyphsArrayCapacity; resetGlyphArrays(); while (!HB_ShapeItem(&m_item)) { // We overflowed our arrays. Resize and retry. // HB_ShapeItem fills in m_item.num_glyphs with the needed size. deleteGlyphArrays(); // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer // shaper (at least) can fail because of insufficient glyph buffers // and request 0 additional glyphs: throwing us into an infinite // loop. createGlyphArrays(m_item.num_glyphs + 1); } }
TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) : m_font(font) , m_startingX(startingX) , m_offsetX(m_startingX) , m_run(getTextRun(run)) , m_iterateBackwards(m_run.rtl()) , m_wordSpacingAdjustment(0) , m_padding(0) , m_padError(0) { // Do not use |run| inside this constructor. Use |m_run| instead. memset(&m_item, 0, sizeof(m_item)); // We cannot know, ahead of time, how many glyphs a given script run // will produce. We take a guess that script runs will not produce more // than twice as many glyphs as there are code points plus a bit of // padding and fallback if we find that we are wrong. createGlyphArrays((m_run.length() + 2) * 2); m_item.log_clusters = new unsigned short[m_run.length()]; m_item.face = 0; m_item.font = allocHarfbuzzFont(); m_item.item.bidiLevel = m_run.rtl(); int length = m_run.length(); m_item.stringLength = length; if (!m_item.item.bidiLevel) m_item.string = m_run.characters(); else { // Assume mirrored character is in the same Unicode multilingual plane as the original one. UChar* string = new UChar[length]; mirrorCharacters(string, m_run.characters(), length); m_item.string = string; } reset(); }
bool expandGlyphArrays() { deleteGlyphArrays(); m_maxGlyphs <<= 1; return createGlyphArrays(); }