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)); }
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); }
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); } }
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(); } } } }