protected void ShapeGlyphRun(TextAnalyzer textAnalyzer, int runIndex, ref int glyphStart) { // Shapes a single run of text into glyphs. // Alternately, you could iteratively interleave shaping and line // breaking to reduce the number glyphs held onto at once. It's simpler // for this demostration to just do shaping and line breaking as two // separate processes, but realize that this does have the consequence that // certain advanced fonts containing line specific features (like Gabriola) // will shape as if the line is not broken. Run run = runs_[runIndex]; int textStart = run.textStart; int textLength = run.textLength; int maxGlyphCount = glyphIndices_.Length - glyphStart; int actualGlyphCount = 0; run.glyphStart = glyphStart; run.glyphCount = 0; if (textLength == 0) { return;// Nothing to do.. } // Allocate space for shaping to fill with glyphs and other information, // with about as many glyphs as there are text characters. We'll actually // need more glyphs than codepoints if they are decomposed into separate // glyphs, or fewer glyphs than codepoints if multiple are substituted // into a single glyph. In any case, the shaping process will need some // room to apply those rules to even make that determintation. if (textLength > maxGlyphCount) { maxGlyphCount = EstimateGlyphCount(textLength); int totalGlyphsArrayCount = glyphStart + maxGlyphCount; short[] Resized_glyphIndices_ = new short[totalGlyphsArrayCount]; glyphIndices_.CopyTo(Resized_glyphIndices_, 0); glyphIndices_ = Resized_glyphIndices_; } ShapingTextProperties[] textProps = new ShapingTextProperties[textLength]; ShapingGlyphProperties[] glyphProps = new ShapingGlyphProperties[maxGlyphCount]; // Get the glyphs from the text, retrying if needed. int tries = 0; do { short[] call_glyphClusters_ = new short[glyphClusters_.Length - textStart]; short[] call_glyphIndices_ = new short[glyphIndices_.Length - glyphStart]; var result = textAnalyzer.GetGlyphs( text_.Substring(textStart, textLength), textLength, fontFace_, run.isSideways, (run.bidiLevel % 2 == 1), run.script, localName_, run.isNumberSubstituted ? numberSubstitution_ : null, null, null, 0, maxGlyphCount, call_glyphClusters_, textProps, call_glyphIndices_, glyphProps, out actualGlyphCount); Array.Copy(call_glyphClusters_, 0, glyphClusters_, textStart, call_glyphClusters_.Length); Array.Copy(call_glyphIndices_, 0, glyphIndices_, glyphStart, call_glyphIndices_.Length); tries++; //if (result!=SharpDX.Result.OutOfMemory) if (result != SharpDX.Result.Ok) { // Try again using a larger buffer. maxGlyphCount = EstimateGlyphCount(maxGlyphCount); int totalGlyphsArrayCount = glyphStart + maxGlyphCount; glyphProps = new ShapingGlyphProperties[maxGlyphCount]; glyphIndices_ = new short[totalGlyphsArrayCount]; } else { break; } }while (tries < 2);// We'll give it two chances. // Get the placement of the all the glyphs. if (glyphAdvances_.Length < glyphStart + actualGlyphCount) { float[] Resized_glyphAdvances_ = new float[glyphStart + actualGlyphCount]; glyphAdvances_.CopyTo(Resized_glyphAdvances_, 0); glyphAdvances_ = Resized_glyphAdvances_; } if (glyphOffsets_.Length < glyphStart + actualGlyphCount) { GlyphOffset[] Resized_glyphOffsets_ = new GlyphOffset[glyphStart + actualGlyphCount]; glyphOffsets_.CopyTo(Resized_glyphOffsets_, 0); glyphOffsets_ = Resized_glyphOffsets_; } short[] call2_glyphClusters_ = new short[glyphClusters_.Length - textStart]; Array.Copy(glyphClusters_, textStart, call2_glyphClusters_, 0, call2_glyphClusters_.Length); short[] call2_glyphIndices_ = new short[glyphIndices_.Length - glyphStart]; Array.Copy(glyphIndices_, glyphStart, call2_glyphIndices_, 0, call2_glyphIndices_.Length); float[] call2_glyphAdvances_ = new float[glyphAdvances_.Length - glyphStart]; Array.Copy(glyphAdvances_, glyphStart, call2_glyphAdvances_, 0, call2_glyphAdvances_.Length); GlyphOffset[] call2_glyphOffsets_ = new GlyphOffset[glyphOffsets_.Length - glyphStart]; Array.Copy(glyphOffsets_, glyphStart, call2_glyphOffsets_, 0, call2_glyphOffsets_.Length); var result2 = textAnalyzer.GetGlyphPlacements( text_.Substring(textStart, textLength), call2_glyphClusters_, textProps, textLength, call2_glyphIndices_, glyphProps, actualGlyphCount, fontFace_, fontEmSize_, run.isSideways, run.bidiLevel % 2 == 1, run.script, localName_, null, null, 0, call2_glyphAdvances_, call2_glyphOffsets_); //call2_glyphClusters_.CopyTo(glyphClusters_, textStart); call2_glyphAdvances_.CopyTo(glyphAdvances_, glyphStart); call2_glyphOffsets_.CopyTo(glyphOffsets_, glyphStart); // Certain fonts, like Batang, contain glyphs for hidden control // and formatting characters. So we'll want to explicitly force their // advance to zero. if (run.script.Shapes == ScriptShapes.NoVisual) { for (int i = glyphStart; i < glyphStart + actualGlyphCount; i++) { glyphAdvances_[i] = 0; } } // Set the final glyph count of this run and advance the starting glyph. run.glyphCount = actualGlyphCount; runs_[runIndex] = run; glyphStart += actualGlyphCount; }