Beispiel #1
0
        internal static int GetGdiCompatibleMetrics(
            IntPtr _fontFace,
            float emSize,
            float pixels_per_dip,
            DWriteMatrix transform,
            out FontMetrics metrics)
        {
            var GetGdiCompatibleMetricsFn = GetFunctionFromVTable <Delegate_GetGdiCompatibleMetrics>(_fontFace, 16);

            return(GetGdiCompatibleMetricsFn(_fontFace, emSize, pixels_per_dip, ref transform, out metrics));
        }
Beispiel #2
0
        public static DWriteMatrix GetIdentityTransform()
        {
            DWriteMatrix transform = new DWriteMatrix();

            transform.M11 = 1;
            transform.M12 = 0;
            transform.M22 = 1;
            transform.M21 = 0;
            transform.Dx  = 0;
            transform.Dy  = 0;

            return(transform);
        }
Beispiel #3
0
        public FontMetrics DisplayMetrics(float emSize, float pixelsPerDip)
        {
            FontMetrics fontMetrics;
            IntPtr      fontFace = _font.CreateFontFace();

            try {
                DWriteMatrix transform = Factory.GetIdentityTransform();
                FontFace.GetGdiCompatibleMetrics(
                    fontFace,
                    emSize,
                    pixelsPerDip,
                    transform,
                    out fontMetrics
                    );
                return(fontMetrics);
            }
            finally
            {
                Marshal.Release(fontFace);
            }
        }
Beispiel #4
0
        unsafe public void GetGlyphPlacements(
            IntPtr textString,
            ushort *clusterMap,            /* textLength */
            ushort *textProps,             /* textLength */
            uint textLength,
            ushort *glyphIndices,          /* glyphCount */
            ushort *glyphProps,            /* glyphCount */
            uint glyphCount,
            Font font,
            double fontEmSize,
            double scalingFactor,
            bool isSideways,
            bool isRightToLeft,
            CultureInfo cultureInfo,
            DWriteFontFeature[][]   features,
            uint[]                  featureRangeLengths,
            TextFormattingMode textFormattingMode,
            ItemProps itemProps,
            float pixelsPerDip,
            int *glyphAdvances,                /* glyphCount */
            [Out] out GlyphOffset[] glyphOffsets
            )
        {
            // Shaping should not have taken place if ScriptAnalysis is NULL!
            Debug.Assert(itemProps.ScriptAnalysis != null);

            // These are control characters and WPF will not display control characters.
            if (GetScriptShapes(itemProps) != DWriteScriptShapes.Default)
            {
                GetGlyphPlacementsForControlCharacters(
                    textString,
                    textLength,
                    font,
                    textFormattingMode,
                    fontEmSize,
                    scalingFactor,
                    isSideways,
                    pixelsPerDip,
                    glyphCount,
                    glyphIndices,
                    glyphAdvances,
                    out glyphOffsets
                    );
            }
            else
            {
                float[]             dwriteGlyphAdvances = new float[glyphCount];
                DWriteGlyphOffset[] dwriteGlyphOffsets  = null;

                var featureRangeLengthsNonNull = featureRangeLengths != null ? featureRangeLengths : new uint[0];
                fixed(uint *pFeatureRangeLengthsPinned = featureRangeLengthsNonNull)
                {
                    GCHandle[] dwriteFontFeaturesGCHandles = null;
                    uint       featureRanges = 0;

                    IntPtr[] dwriteTypographicFeatures       = null;
                    IntPtr   dwriteTypographicFeaturesMemory = IntPtr.Zero;
                    uint *   pFeatureRangeLengths            = null;

                    if (features != null)
                    {
                        pFeatureRangeLengths            = pFeatureRangeLengthsPinned;
                        featureRanges                   = (uint)featureRangeLengths.Length;
                        dwriteTypographicFeatures       = new IntPtr[featureRanges];
                        dwriteFontFeaturesGCHandles     = new GCHandle[featureRanges];
                        dwriteTypographicFeatures       = new IntPtr[featureRanges];
                        dwriteTypographicFeaturesMemory = Marshal.AllocCoTaskMem(Marshal.SizeOf <DWriteTypographicFeatures>() * (int)featureRanges);
                    }

                    FontFace fontFace       = font.GetFontFace();
                    IntPtr   scriptAnalysis = itemProps.ScriptAnalysisCoTaskMem();

                    try
                    {
                        string       localeName = cultureInfo.IetfLanguageTag;
                        DWriteMatrix transform  = Factory.GetIdentityTransform();

                        if (features != null)
                        {
                            for (uint i = 0; i < featureRanges; ++i)
                            {
                                dwriteFontFeaturesGCHandles[i] = GCHandle.Alloc(features[i], GCHandleType.Pinned);
                                var new_feature = new DWriteTypographicFeatures();
                                new_feature.features         = dwriteFontFeaturesGCHandles[i].AddrOfPinnedObject();
                                new_feature.featureCount     = features[i].Length;
                                dwriteTypographicFeatures[i] = dwriteTypographicFeaturesMemory + (int)i * Marshal.SizeOf <DWriteTypographicFeatures>();
                                Marshal.StructureToPtr <DWriteTypographicFeatures>(new_feature, dwriteTypographicFeatures[i], false);
                            }
                        }

                        float fontEmSizeFloat = (float)fontEmSize;

                        dwriteGlyphOffsets = new DWriteGlyphOffset[glyphCount];
                        if (textFormattingMode == TextFormattingMode.Ideal)
                        {
                            try {
                                _textAnalyzer.GetGlyphPlacements(
                                    textString,
                                    clusterMap,
                                    textProps,
                                    textLength,
                                    glyphIndices,
                                    glyphProps,
                                    glyphCount,
                                    fontFace.DWriteFontFaceNoAddRef,
                                    fontEmSizeFloat,
                                    isSideways,
                                    isRightToLeft,
                                    scriptAnalysis,
                                    localeName,
                                    dwriteTypographicFeatures,
                                    pFeatureRangeLengths,
                                    featureRanges,
                                    dwriteGlyphAdvances,
                                    dwriteGlyphOffsets
                                    );
                            }
                            catch (ArgumentException)
                            {
                                // If pLocaleName is unsupported (e.g. "prs-af"), DWrite returns E_INVALIDARG.
                                // Try again with the default mapping.
                                _textAnalyzer.GetGlyphPlacements(
                                    textString,
                                    clusterMap,
                                    textProps,
                                    textLength,
                                    glyphIndices,
                                    glyphProps,
                                    glyphCount,
                                    fontFace.DWriteFontFaceNoAddRef,
                                    fontEmSizeFloat,
                                    isSideways,
                                    isRightToLeft,
                                    scriptAnalysis,
                                    null,
                                    dwriteTypographicFeatures,
                                    pFeatureRangeLengths,
                                    featureRanges,
                                    dwriteGlyphAdvances,
                                    dwriteGlyphOffsets
                                    );
                            }
                        }
                        else
                        {
                            Debug.Assert(textFormattingMode == TextFormattingMode.Display);

                            try {
                                _textAnalyzer.GetGdiCompatibleGlyphPlacements(
                                    textString,
                                    clusterMap,
                                    textProps,
                                    textLength,
                                    glyphIndices,
                                    glyphProps,
                                    glyphCount,
                                    fontFace.DWriteFontFaceNoAddRef,
                                    fontEmSizeFloat,
                                    pixelsPerDip,
                                    ref transform,
                                    false,
                                    isSideways,
                                    isRightToLeft,
                                    scriptAnalysis,
                                    localeName,
                                    dwriteTypographicFeatures,
                                    pFeatureRangeLengths,
                                    featureRanges,
                                    dwriteGlyphAdvances,
                                    dwriteGlyphOffsets
                                    );
                            }
                            catch (ArgumentException) {
                                // If pLocaleName is unsupported (e.g. "prs-af"), DWrite returns E_INVALIDARG.
                                // Try again with the default mapping.
                                _textAnalyzer.GetGdiCompatibleGlyphPlacements(
                                    textString,
                                    clusterMap,
                                    textProps,
                                    textLength,
                                    glyphIndices,
                                    glyphProps,
                                    glyphCount,
                                    fontFace.DWriteFontFaceNoAddRef,
                                    fontEmSizeFloat,
                                    pixelsPerDip,
                                    ref transform,
                                    false,
                                    isSideways,
                                    isRightToLeft,
                                    scriptAnalysis,
                                    null,
                                    dwriteTypographicFeatures,
                                    pFeatureRangeLengths,
                                    featureRanges,
                                    dwriteGlyphAdvances,
                                    dwriteGlyphOffsets
                                    );
                            }
                        }

                        glyphOffsets = new GlyphOffset[glyphCount];
                        if (textFormattingMode == TextFormattingMode.Ideal)
                        {
                            for (uint i = 0; i < glyphCount; ++i)
                            {
                                glyphAdvances[i]   = (int)Math.Round(dwriteGlyphAdvances[i] * fontEmSize * scalingFactor / fontEmSizeFloat);
                                glyphOffsets[i].du = (int)(dwriteGlyphOffsets[i].AdvanceOffset * scalingFactor);
                                glyphOffsets[i].dv = (int)(dwriteGlyphOffsets[i].AscenderOffset * scalingFactor);
                            }
                        }
                        else
                        {
                            for (uint i = 0; i < glyphCount; ++i)
                            {
                                glyphAdvances[i]   = (int)Math.Round(dwriteGlyphAdvances[i] * scalingFactor);
                                glyphOffsets[i].du = (int)(dwriteGlyphOffsets[i].AdvanceOffset * scalingFactor);
                                glyphOffsets[i].dv = (int)(dwriteGlyphOffsets[i].AscenderOffset * scalingFactor);
                            }
                        }
                    }
                    finally
                    {
                        Marshal.FreeCoTaskMem(scriptAnalysis);

                        if (features != null)
                        {
                            for (uint i = 0; i < featureRanges; ++i)
                            {
                                dwriteFontFeaturesGCHandles[i].Free();
                            }
                            Marshal.FreeCoTaskMem(dwriteTypographicFeaturesMemory);
                        }

                        fontFace.Release();
                    }
                }
            }
        }