Exemplo n.º 1
0
        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;
        }