Beispiel #1
0
 /// <summary>
 /// Construct an lsrun
 /// </summary>
 private LSRun(
     TextRunInfo runInfo,
     IList <TextEffect> textEffects,
     Plsrun type,
     int offsetToFirstCp,
     int textRunLength,
     int emSize,
     ushort charFlags,
     CharacterBufferRange charBufferRange,
     int baselineOffset,
     int height,
     TextShapeableSymbols shapeable,
     byte bidiLevel
     )
 {
     _runInfo         = runInfo;
     _type            = type;
     _offsetToFirstCp = offsetToFirstCp;
     _textRunLength   = textRunLength;
     _emSize          = emSize;
     _charFlags       = charFlags;
     _charBufferRange = charBufferRange;
     _baselineOffset  = baselineOffset;
     _height          = height;
     _bidiLevel       = bidiLevel;
     _shapeable       = shapeable;
     _textEffects     = textEffects;
 }
Beispiel #2
0
        private IList <TextEffect> _textEffects;                    // TextEffects that should be applied for this run


        /// <summary>
        /// Construct an lsrun
        /// </summary>
        internal LSRun(
            TextRunInfo runInfo,
            IList <TextEffect> textEffects,
            Plsrun type,
            int offsetToFirstCp,
            int textRunLength,
            int emSize,
            ushort charFlags,
            CharacterBufferRange charBufferRange,
            TextShapeableSymbols shapeable,
            double realToIdeal,
            byte bidiLevel
            ) :
            this(
                runInfo,
                textEffects,
                type,
                offsetToFirstCp,
                textRunLength,
                emSize,
                charFlags,
                charBufferRange,
                (shapeable != null ? (int)Math.Round(shapeable.Baseline * realToIdeal) : 0),
                (shapeable != null ? (int)Math.Round(shapeable.Height * realToIdeal) : 0),
                shapeable,
                bidiLevel
                )
        {
        }
Beispiel #3
0
 /// <summary>
 /// Construct a nominal description of glyph data
 /// </summary>
 internal Glyphs(
     TextShapeableSymbols shapeable,
     char[]                  charArray,
     int[]                  nominalAdvances,
     double scalingFactor
     ) :
     this(
         shapeable,
         charArray,
         nominalAdvances,
         null,   // clusterMap
         null,   // glyphIndices
         null,   // glyphOffsets
         scalingFactor
         )
 {
 }
Beispiel #4
0
        public FormattedTextSymbols(
            GlyphingCache glyphingCache,
            TextRun textSymbols,
            bool rightToLeft,
            double scalingFactor,
            float pixelsPerDip,
            TextFormattingMode textFormattingMode,
            bool isSideways
            )
        {
            _textFormattingMode = textFormattingMode;
            _isSideways         = isSideways;
            ITextSymbols symbols = textSymbols as ITextSymbols;

            Debug.Assert(symbols != null);

            // break down a single text run into pieces
            IList <TextShapeableSymbols> shapeables = symbols.GetTextShapeableSymbols(
                glyphingCache,
                textSymbols.CharacterBufferReference,
                textSymbols.Length,
                rightToLeft, // This is a bool indicating the RTL
                             // based on the bidi level of text (if applicable).
                             // For FormattedTextSymbols it is equal to paragraph flow direction.

                rightToLeft, // This is the flow direction of the paragraph as
                             // specified by the user. DWrite needs the paragraph
                             // flow direction of the paragraph
                             // while WPF algorithms need the RTL of the text based on
                             // Bidi if possible.

                null,        // cultureInfo
                null,        // textModifierScope
                _textFormattingMode,
                _isSideways
                );

            Debug.Assert(shapeables != null && shapeables.Count > 0);

            _rightToLeft = rightToLeft;
            _glyphs      = new Glyphs[shapeables.Count];

            CharacterBuffer charBuffer        = textSymbols.CharacterBufferReference.CharacterBuffer;
            int             offsetToFirstChar = textSymbols.CharacterBufferReference.OffsetToFirstChar;

            int i   = 0;
            int ich = 0;

            while (i < shapeables.Count)
            {
                TextShapeableSymbols current = shapeables[i] as TextShapeableSymbols;
                Debug.Assert(current != null);

                int cch = current.Length;
                int j;

                // make a separate character buffer for glyphrun persistence
                char[] charArray = new char[cch];
                for (j = 0; j < cch; j++)
                {
                    charArray[j] = charBuffer[offsetToFirstChar + ich + j];
                }

                if (current.IsShapingRequired)
                {
                    ushort[]      clusterMap;
                    ushort[]      glyphIndices;
                    int[]         glyphAdvances;
                    GlyphOffset[] glyphOffsets;


                    //



                    unsafe
                    {
                        fixed(char *fixedCharArray = &charArray[0])
                        {
                            MS.Internal.Text.TextInterface.TextAnalyzer textAnalyzer = MS.Internal.FontCache.DWriteFactory.Instance.CreateTextAnalyzer();

                            GlyphTypeface glyphTypeface = current.GlyphTypeFace;

                            DWriteFontFeature[][] fontFeatures;
                            uint[] fontFeatureRanges;
                            uint   unsignedCch = checked ((uint)cch);

                            LSRun.CompileFeatureSet(current.Properties.TypographyProperties, unsignedCch, out fontFeatures, out fontFeatureRanges);


                            textAnalyzer.GetGlyphsAndTheirPlacements(
                                (ushort *)fixedCharArray,
                                unsignedCch,
                                glyphTypeface.FontDWrite,
                                glyphTypeface.BlankGlyphIndex,
                                false,   // no sideway support yet
                                /************************************************************************************************/
                                //
                                rightToLeft,
                                current.Properties.CultureInfo,
                                /************************************************************************************************/
                                fontFeatures,
                                fontFeatureRanges,
                                current.Properties.FontRenderingEmSize,
                                scalingFactor,
                                pixelsPerDip,
                                _textFormattingMode,
                                current.ItemProps,
                                out clusterMap,
                                out glyphIndices,
                                out glyphAdvances,
                                out glyphOffsets
                                );
                        }

                        _glyphs[i] = new Glyphs(
                            current,
                            charArray,
                            glyphAdvances,
                            clusterMap,
                            glyphIndices,
                            glyphOffsets,
                            scalingFactor
                            );
                    }
                }
                else
                {
                    // shaping not required,
                    // bypass glyphing process altogether
                    int[] nominalAdvances = new int[charArray.Length];

                    unsafe
                    {
                        fixed(char *fixedCharArray = &charArray[0])
                        fixed(int *fixedNominalAdvances = &nominalAdvances[0])
                        {
                            current.GetAdvanceWidthsUnshaped(
                                fixedCharArray,
                                cch,
                                scalingFactor, // format resolution specified per em,
                                fixedNominalAdvances
                                );
                        }
                    }

                    _glyphs[i] = new Glyphs(
                        current,
                        charArray,
                        nominalAdvances,
                        scalingFactor
                        );
                }

                i++;
                ich += cch;
            }
        }
Beispiel #5
0
            /// <summary>
            /// Construct a full description of glyph data
            /// </summary>
            internal Glyphs(
                TextShapeableSymbols shapeable,
                char[]                   charArray,
                int[]                   glyphAdvances,
                ushort[]                 clusterMap,
                ushort[]                 glyphIndices,
                GlyphOffset[]            glyphOffsets,
                double scalingFactor
                )
            {
                _shapeable = shapeable;
                _charArray = charArray;

                // create double array for glyph run creation, because Shaping is all done in
                // ideal units. FormattedTextSymbol is used to draw text collapsing symbols
                // which usually contains very few glyphs. Using double[] and Point[] directly
                // is more efficient.
                _glyphAdvances = new double[glyphAdvances.Length];

                double ToReal = 1.0 / scalingFactor;

                for (int i = 0; i < glyphAdvances.Length; i++)
                {
                    _glyphAdvances[i] = glyphAdvances[i] * ToReal;
                    _width           += _glyphAdvances[i];
                }

                if (glyphIndices != null)
                {
                    _clusterMap = clusterMap;

                    if (glyphOffsets != null)
                    {
                        _glyphOffsets = new PartialArray <Point>(new Point[glyphOffsets.Length]);

                        for (int i = 0; i < glyphOffsets.Length; i++)
                        {
                            _glyphOffsets[i] = new Point(
                                glyphOffsets[i].du * ToReal,
                                glyphOffsets[i].dv * ToReal
                                );
                        }
                    }

                    Debug.Assert(glyphAdvances.Length <= glyphIndices.Length);

                    if (glyphAdvances.Length != glyphIndices.Length)
                    {
                        _glyphIndices = new ushort[glyphAdvances.Length];

                        for (int i = 0; i < glyphAdvances.Length; i++)
                        {
                            _glyphIndices[i] = glyphIndices[i];
                        }
                    }
                    else
                    {
                        _glyphIndices = glyphIndices;
                    }
                }
            }
Beispiel #6
0
 /// <summary>
 /// Return value indicates whether two runs can shape together
 /// </summary>
 /// <param name="shapeable">another run</param>
 internal abstract bool CanShapeTogether(
     TextShapeableSymbols shapeable
     );