Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / MS / Internal / TextFormatting / LineServicesRun.cs / 1600529 / LineServicesRun.cs
//------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2001 // // File: LSRun.cs // // Contents: Text run in a full text line // // Created: 9-6-2001 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Media; using System.Windows.Media.TextFormatting; using System.Globalization; using System.Security; using System.Security.Permissions; using MS.Internal.Shaping; using MS.Internal.FontCache; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; using MS.Internal.Text.TextInterface; namespace MS.Internal.TextFormatting { ////// Run represented by a plsrun value dispatched to LS during FetchRun /// internal sealed class LSRun { private TextRunInfo _runInfo; // TextRun Info of the text private Plsrun _type; // Plsrun used as run type private int _offsetToFirstCp; // dcp from line's cpFirst private int _textRunLength; // textrun length private CharacterBufferRange _charBufferRange; // character buffer range private int _baselineOffset; // distance from top to baseline private int _height; // height private int _baselineMoveOffset; // run is moved by this offset from baseline private int _emSize; // run ideal EM size private TextShapeableSymbols _shapeable; // shapeable run private ushort _charFlags; // character attribute flags private byte _bidiLevel; // resolved bidi level private IList_textEffects; // TextEffects that should be applied for this run /// /// Construct an lsrun /// internal LSRun( TextRunInfo runInfo, IListtextEffects, 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 ) {} /// /// Construct an lsrun /// private LSRun( TextRunInfo runInfo, IListtextEffects, 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; } /// /// Construct an lsrun for a constant control char /// internal LSRun( Plsrun type, IntPtr controlChar ) : this( null, // text run info type, controlChar, 0, // textRunLength -1, // offsetToFirstChar 0 ) {} ////// Construct an lsrun /// /// TextRunInfo /// plsrun type /// control character /// text run length /// character offset to the first cp /// bidi level of this run ////// Critical: This has an unsafe code block /// TreatAsSafe: This code is ok to call since it does not expose the critical pointer /// [SecurityCritical, SecurityTreatAsSafe] internal LSRun( TextRunInfo runInfo, Plsrun type, IntPtr controlChar, int textRunLength, int offsetToFirstCp, byte bidiLevel ) { unsafe { _runInfo = runInfo; _type = type; _charBufferRange = new CharacterBufferRange((char*)controlChar, 1); _textRunLength = textRunLength; _offsetToFirstCp = offsetToFirstCp; _bidiLevel = bidiLevel; } } internal void Truncate(int newLength) { _charBufferRange = new CharacterBufferRange( _charBufferRange.CharacterBufferReference, newLength ); _textRunLength = newLength; } ////// A Boolean value indicates whether hit-testing is allowed within the run /// internal bool IsHitTestable { get { return _type == Plsrun.Text; } } ////// A Boolean value indicates whether this run contains visible content. /// internal bool IsVisible { get { return (_type == Plsrun.Text || _type == Plsrun.InlineObject); } } ////// A Boolean value indicates whether this run is End-Of-Line marker. /// internal bool IsNewline { get { return (_type == Plsrun.LineBreak || _type == Plsrun.ParaBreak); } } ////// A Boolean value indicates whether additional info is required for caret positioning /// internal bool NeedsCaretInfo { get { return _shapeable != null && _shapeable.NeedsCaretInfo; } } ////// A Boolean value indicates whether run has extended character /// internal bool HasExtendedCharacter { get { return _shapeable != null && _shapeable.HasExtendedCharacter; } } ////// Draw glyphrun /// /// The drawing context to draw into /// /// The foreground brush of the glyphrun. Pass in "null" to draw the /// glyph run with the foreground in TextRunProperties. /// /// The GlyphRun to be drawn ///bounding rectangle of drawn glyphrun ////// TextEffect drawing code may use a different foreground brush for the text. /// internal Rect DrawGlyphRun( DrawingContext drawingContext, Brush foregroundBrush, GlyphRun glyphRun ) { Debug.Assert(_shapeable != null); Rect inkBoundingBox = glyphRun.ComputeInkBoundingBox(); if (!inkBoundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin inkBoundingBox.X += glyphRun.BaselineOrigin.X; inkBoundingBox.Y += glyphRun.BaselineOrigin.Y; } if (drawingContext != null) { int pushCount = 0; // the number of push we do try { if (_textEffects != null) { // we need to push in the same order as they are set for (int i = 0; i < _textEffects.Count; i++) { // get the text effect by its index TextEffect textEffect = _textEffects[i]; if (textEffect.Transform != null && textEffect.Transform != Transform.Identity) { drawingContext.PushTransform(textEffect.Transform); pushCount++; } if (textEffect.Clip != null) { drawingContext.PushClip(textEffect.Clip); pushCount++; } if (textEffect.Foreground != null) { // remember the out-most non-null brush // this brush will be used to draw the glyph run foregroundBrush = textEffect.Foreground; } } } _shapeable.Draw(drawingContext, foregroundBrush, glyphRun); } finally { for (int i = 0; i < pushCount; i++) { drawingContext.Pop(); } } } return inkBoundingBox; } ////// Map a UV real coordinate to an XY real coordinate /// /// line drawing origin XY /// vector to line origin UV /// real distance in text flow direction /// real distance in paragraph flow direction /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, double u, double v, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth) - vectorToOrigin.X - u + origin.X, v + origin.Y); } else { xy = new Point(u + vectorToOrigin.X + origin.X, v + origin.Y); } return xy; } ////// Map a UV ideal coordinate to an XY real coordinate /// /// line drawing origin /// vector to line origin UV /// ideal distance in text flow direction /// ideal distance in paragraph flow direction /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, int u, int v, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth - u) - vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); } else { xy = new Point(line.Formatter.IdealToReal(u) + vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); } return xy; } ////// Map a UV ideal coordinate to an XY ideal coordinate /// /// line drawing origin /// vector to line origin UV /// ideal distance in text flow direction /// ideal distance in paragraph flow direction /// container line /// ideal X origin /// ideal Y origin internal static void UVToNominalXY( Point origin, Point vectorToOrigin, int u, int v, TextMetrics.FullTextLine line, out int nominalX, out int nominalY ) { origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { nominalX = line.ParagraphWidth - u + TextFormatterImp.RealToIdeal(-vectorToOrigin.X + origin.X); } else { nominalX = u + TextFormatterImp.RealToIdeal(vectorToOrigin.X + origin.X); } nominalY = v + TextFormatterImp.RealToIdeal(origin.Y); } ////// Create a rectangle of the two specified UV coordinates /// /// line drawing origin /// logical top-left point /// logical bottom-right point /// container line internal static Rect RectUV( Point origin, LSPOINT topLeft, LSPOINT bottomRight, TextMetrics.FullTextLine line ) { int dx = topLeft.x - bottomRight.x; if(dx == 1 || dx == -1) { // in certain situation LS can be off by 1 bottomRight.x = topLeft.x; } Rect rect = new Rect( new Point(line.Formatter.IdealToReal(topLeft.x), line.Formatter.IdealToReal(topLeft.y)), new Point(line.Formatter.IdealToReal(bottomRight.x), line.Formatter.IdealToReal(bottomRight.y)) ); if(DoubleUtil.AreClose(rect.TopLeft.X, rect.BottomRight.X)) { rect.Width = 0; } if(DoubleUtil.AreClose(rect.TopLeft.Y, rect.BottomRight.Y)) { rect.Height = 0; } return rect; } ////// Move text run's baseline by the specified value /// /// offset to be moved away from baseline internal void Move(int baselineMoveOffset) { _baselineMoveOffset += baselineMoveOffset; } internal byte BidiLevel { get { return _bidiLevel; } } internal bool IsSymbol { get { TextShapeableCharacters shapeable = _shapeable as TextShapeableCharacters; return shapeable != null && shapeable.IsSymbol; } } internal int OffsetToFirstCp { get { return _offsetToFirstCp; } } internal int Length { get { return _textRunLength; } } internal TextModifierScope TextModifierScope { get { return _runInfo.TextModifierScope; } } internal Plsrun Type { get { return _type; } } internal ushort CharacterAttributeFlags { get { return _charFlags; } } internal CharacterBuffer CharacterBuffer { get { return _charBufferRange.CharacterBuffer; } } internal int StringLength { get { return _charBufferRange.Length; } } internal int OffsetToFirstChar { get { return _charBufferRange.OffsetToFirstChar; } } internal TextRun TextRun { get { return _runInfo.TextRun; } } internal TextShapeableSymbols Shapeable { get { return _shapeable; } } internal int BaselineOffset { get { return _baselineOffset; } set { _baselineOffset = value; } } internal int Height { get { return _height; } set { _height = value; } } internal int Descent { get { return Height - BaselineOffset; } } internal TextRunProperties RunProp { get { return _runInfo.Properties; } } internal CultureInfo TextCulture { get { return CultureMapper.GetSpecificCulture(RunProp != null ? RunProp.CultureInfo : null); } } internal int EmSize { get { return _emSize; } } internal int BaselineMoveOffset { get { return _baselineMoveOffset; } } ////// required set of features that will be added to every feature set /// It will be used if nothing is set in typogrpahy porperties /// private enum CustomOpenTypeFeatures { AlternativeFractions , PetiteCapitalsFrom----s , SmallCapitalsFrom----s , ContextualAlternates , CaseSensitiveForms , ContextualLigatures , CapitalSpacing , ContextualSwash , CursivePositioning , DiscretionaryLigatures , ExpertForms , Fractions , FullWidth , HalfForms , HalantForms , AlternateHalfWidth , HistoricalForms , HorizontalKanaAlternates , HistoricalLigatures , HojoKanjiForms , HalfWidth , JIS78Forms , JIS83Forms , JIS90Forms , JIS04Forms , Kerning , StandardLigatures , LiningFigures , MathematicalGreek , AlternateAnnotationForms , NLCKanjiForms , OldStyleFigures , Ordinals , ProportionalAlternateWidth , PetiteCapitals , ProportionalFigures , ProportionalWidths , QuarterWidths , RubyNotationForms , StylisticAlternates , ScientificInferiors , SmallCapitals , SimplifiedForms , StylisticSet1 , StylisticSet2 , StylisticSet3 , StylisticSet4 , StylisticSet5 , StylisticSet6 , StylisticSet7 , StylisticSet8 , StylisticSet9 , StylisticSet10 , StylisticSet11 , StylisticSet12 , StylisticSet13 , StylisticSet14 , StylisticSet15 , StylisticSet16 , StylisticSet17 , StylisticSet18 , StylisticSet19 , StylisticSet20 , Subscript , Superscript , Swash , Titling , TraditionalNameForms , TabularFigures , TraditionalForms , ThirdWidths , Unicase , SlashedZero , Count } private const ushort FeatureNotEnabled = 0xffff; private static DWriteFontFeature[] CreateDWriteFontFeatures(TextRunTypographyProperties textRunTypographyProperties) { if (textRunTypographyProperties != null) { if (textRunTypographyProperties.CachedFeatureSet != null) { return textRunTypographyProperties.CachedFeatureSet; } else { ListfontFeatures = new List ((int)CustomOpenTypeFeatures.Count); if (textRunTypographyProperties.CapitalSpacing) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CapitalSpacing, 1)); } if (textRunTypographyProperties.CaseSensitiveForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CaseSensitiveForms, 1)); } if (textRunTypographyProperties.ContextualAlternates) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualAlternates, 1)); } if (textRunTypographyProperties.ContextualLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualLigatures, 1)); } if (textRunTypographyProperties.DiscretionaryLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.DiscretionaryLigatures, 1)); } if (textRunTypographyProperties.HistoricalForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalForms, 1)); } if (textRunTypographyProperties.HistoricalLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalLigatures, 1)); } if (textRunTypographyProperties.Kerning) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Kerning, 1)); } if (textRunTypographyProperties.MathematicalGreek) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.MathematicalGreek, 1)); } if (textRunTypographyProperties.SlashedZero) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SlashedZero, 1)); } if (textRunTypographyProperties.StandardLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StandardLigatures, 1)); } if (textRunTypographyProperties.StylisticSet1) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet1, 1)); } if (textRunTypographyProperties.StylisticSet10) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet10, 1)); } if (textRunTypographyProperties.StylisticSet11) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet11, 1)); } if (textRunTypographyProperties.StylisticSet12) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet12, 1)); } if (textRunTypographyProperties.StylisticSet13) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet13, 1)); } if (textRunTypographyProperties.StylisticSet14) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet14, 1)); } if (textRunTypographyProperties.StylisticSet15) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet15, 1)); } if (textRunTypographyProperties.StylisticSet16) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet16, 1)); } if (textRunTypographyProperties.StylisticSet17) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet17, 1)); } if (textRunTypographyProperties.StylisticSet18) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet18, 1)); } if (textRunTypographyProperties.StylisticSet19) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet19, 1)); } if (textRunTypographyProperties.StylisticSet2) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet2, 1)); } if (textRunTypographyProperties.StylisticSet20) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet20, 1)); } if (textRunTypographyProperties.StylisticSet3) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet3, 1)); } if (textRunTypographyProperties.StylisticSet4) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet4, 1)); } if (textRunTypographyProperties.StylisticSet5) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet5, 1)); } if (textRunTypographyProperties.StylisticSet6) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet6, 1)); } if (textRunTypographyProperties.StylisticSet7) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet7, 1)); } if (textRunTypographyProperties.StylisticSet8) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet8, 1)); } if (textRunTypographyProperties.StylisticSet9) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet9, 1)); } if (textRunTypographyProperties.EastAsianExpertForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ExpertForms, 1)); } if (textRunTypographyProperties.AnnotationAlternates > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateAnnotationForms, checked((uint)textRunTypographyProperties.AnnotationAlternates))); } if (textRunTypographyProperties.ContextualSwashes > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualSwash, checked((uint)textRunTypographyProperties.ContextualSwashes))); } if (textRunTypographyProperties.StylisticAlternates > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticAlternates, checked((uint)textRunTypographyProperties.StylisticAlternates))); } if (textRunTypographyProperties.StandardSwashes > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Swash, checked((uint)textRunTypographyProperties.StandardSwashes))); } switch (textRunTypographyProperties.Capitals) { case FontCapitals.AllPetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitalsFrom----s, 1)); break; case FontCapitals.AllSmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitalsFrom----s, 1)); break; case FontCapitals.PetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); break; case FontCapitals.SmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); break; case FontCapitals.Titling: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Titling, 1)); break; case FontCapitals.Unicase: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Unicase, 1)); break; } switch (textRunTypographyProperties.EastAsianLanguage) { case FontEastAsianLanguage.Simplified: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SimplifiedForms, 1)); break; case FontEastAsianLanguage.Traditional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalForms, 1)); break; case FontEastAsianLanguage.TraditionalNames: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalNameForms, 1)); break; case FontEastAsianLanguage.NlcKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.NLCKanjiForms, 1)); break; case FontEastAsianLanguage.HojoKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HojoKanjiForms, 1)); break; case FontEastAsianLanguage.Jis78: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS78Forms, 1)); break; case FontEastAsianLanguage.Jis83: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS83Forms, 1)); break; case FontEastAsianLanguage.Jis90: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS90Forms, 1)); break; case FontEastAsianLanguage.Jis04: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS04Forms, 1)); break; } switch (textRunTypographyProperties.Fraction) { case FontFraction.Stacked: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternativeFractions, 1)); break; case FontFraction.Slashed: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Fractions, 1)); break; } switch (textRunTypographyProperties.NumeralAlignment) { case FontNumeralAlignment.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalFigures, 1)); break; case FontNumeralAlignment.Tabular: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TabularFigures, 1)); break; } switch (textRunTypographyProperties.NumeralStyle) { case FontNumeralStyle.Lining: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.LiningFigures, 1)); break; case FontNumeralStyle.OldStyle: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.OldStyleFigures, 1)); break; } switch (textRunTypographyProperties.Variants) { case FontVariants.Inferior: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ScientificInferiors, 1)); break; case FontVariants.Ordinal: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Ordinals, 1)); break; case FontVariants.Ruby: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.RubyNotationForms, 1)); break; case FontVariants.Subscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Subscript, 1)); break; case FontVariants.Superscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Superscript, 1)); break; } switch (textRunTypographyProperties.EastAsianWidths) { case FontEastAsianWidths.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalWidths, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalAlternateWidth, 1)); break; case FontEastAsianWidths.Full: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.FullWidth, 1)); break; case FontEastAsianWidths.Half: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HalfWidth, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateHalfWidth, 1)); break; case FontEastAsianWidths.Third: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ThirdWidths, 1)); break; case FontEastAsianWidths.Quarter: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.QuarterWidths, 1)); break; } textRunTypographyProperties.CachedFeatureSet = fontFeatures.ToArray(); return textRunTypographyProperties.CachedFeatureSet; } } return null; } /// /// Compile feature set from the linked list of LSRuns. /// TypographyProperties should be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// ////// Critical - deals with unsafe int array /// [SecurityCritical] internal static unsafe void CompileFeatureSet( LSRun[] lsruns, int* pcchRuns, uint totalLength, out DWriteFontFeature[][] fontFeatures, out uint[] fontFeatureRanges ) { Debug.Assert(lsruns != null && lsruns.Length > 0 && lsruns[0] != null); // // Quick check for null properties // Run properties should be all null or all not null // if (lsruns[0].RunProp.TypographyProperties == null) { for (int i = 1; i < lsruns.Length; i++) { if (lsruns[i].RunProp.TypographyProperties != null) { throw new ArgumentException(SR.Get(SRID.CompileFeatureSet_InvalidTypographyProperties)); } } fontFeatures = null; fontFeatureRanges = null; return; } //End of quick check. We will process custom features now. fontFeatures = new DWriteFontFeature[lsruns.Length][]; fontFeatureRanges = new uint[lsruns.Length]; for (int i = 0; i < lsruns.Length; i++) { TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; fontFeatures[i] = CreateDWriteFontFeatures(properties); fontFeatureRanges[i] = checked((uint)pcchRuns[i]); } } ////// Compile feature set from the linked list of LSRuns. /// TypographyProperties should be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// internal static void CompileFeatureSet( TextRunTypographyProperties textRunTypographyProperties, uint totalLength, out DWriteFontFeature[][] fontFeatures, out uint[] fontFeatureRanges ) { // // Quick check for null properties // Run properties should be all null or all not null // if (textRunTypographyProperties == null) { fontFeatures = null; fontFeatureRanges = null; } else { // End of quick check. We will process custom features now. fontFeatures = new DWriteFontFeature[1][]; fontFeatureRanges = new uint[1]; fontFeatures[0] = CreateDWriteFontFeatures(textRunTypographyProperties); fontFeatureRanges[0] = totalLength; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2001 // // File: LSRun.cs // // Contents: Text run in a full text line // // Created: 9-6-2001 Worachai Chaoweeraprasit (wchao) // //----------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Media; using System.Windows.Media.TextFormatting; using System.Globalization; using System.Security; using System.Security.Permissions; using MS.Internal.Shaping; using MS.Internal.FontCache; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; using MS.Internal.Text.TextInterface; namespace MS.Internal.TextFormatting { ////// Run represented by a plsrun value dispatched to LS during FetchRun /// internal sealed class LSRun { private TextRunInfo _runInfo; // TextRun Info of the text private Plsrun _type; // Plsrun used as run type private int _offsetToFirstCp; // dcp from line's cpFirst private int _textRunLength; // textrun length private CharacterBufferRange _charBufferRange; // character buffer range private int _baselineOffset; // distance from top to baseline private int _height; // height private int _baselineMoveOffset; // run is moved by this offset from baseline private int _emSize; // run ideal EM size private TextShapeableSymbols _shapeable; // shapeable run private ushort _charFlags; // character attribute flags private byte _bidiLevel; // resolved bidi level private IList_textEffects; // TextEffects that should be applied for this run /// /// Construct an lsrun /// internal LSRun( TextRunInfo runInfo, IListtextEffects, 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 ) {} /// /// Construct an lsrun /// private LSRun( TextRunInfo runInfo, IListtextEffects, 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; } /// /// Construct an lsrun for a constant control char /// internal LSRun( Plsrun type, IntPtr controlChar ) : this( null, // text run info type, controlChar, 0, // textRunLength -1, // offsetToFirstChar 0 ) {} ////// Construct an lsrun /// /// TextRunInfo /// plsrun type /// control character /// text run length /// character offset to the first cp /// bidi level of this run ////// Critical: This has an unsafe code block /// TreatAsSafe: This code is ok to call since it does not expose the critical pointer /// [SecurityCritical, SecurityTreatAsSafe] internal LSRun( TextRunInfo runInfo, Plsrun type, IntPtr controlChar, int textRunLength, int offsetToFirstCp, byte bidiLevel ) { unsafe { _runInfo = runInfo; _type = type; _charBufferRange = new CharacterBufferRange((char*)controlChar, 1); _textRunLength = textRunLength; _offsetToFirstCp = offsetToFirstCp; _bidiLevel = bidiLevel; } } internal void Truncate(int newLength) { _charBufferRange = new CharacterBufferRange( _charBufferRange.CharacterBufferReference, newLength ); _textRunLength = newLength; } ////// A Boolean value indicates whether hit-testing is allowed within the run /// internal bool IsHitTestable { get { return _type == Plsrun.Text; } } ////// A Boolean value indicates whether this run contains visible content. /// internal bool IsVisible { get { return (_type == Plsrun.Text || _type == Plsrun.InlineObject); } } ////// A Boolean value indicates whether this run is End-Of-Line marker. /// internal bool IsNewline { get { return (_type == Plsrun.LineBreak || _type == Plsrun.ParaBreak); } } ////// A Boolean value indicates whether additional info is required for caret positioning /// internal bool NeedsCaretInfo { get { return _shapeable != null && _shapeable.NeedsCaretInfo; } } ////// A Boolean value indicates whether run has extended character /// internal bool HasExtendedCharacter { get { return _shapeable != null && _shapeable.HasExtendedCharacter; } } ////// Draw glyphrun /// /// The drawing context to draw into /// /// The foreground brush of the glyphrun. Pass in "null" to draw the /// glyph run with the foreground in TextRunProperties. /// /// The GlyphRun to be drawn ///bounding rectangle of drawn glyphrun ////// TextEffect drawing code may use a different foreground brush for the text. /// internal Rect DrawGlyphRun( DrawingContext drawingContext, Brush foregroundBrush, GlyphRun glyphRun ) { Debug.Assert(_shapeable != null); Rect inkBoundingBox = glyphRun.ComputeInkBoundingBox(); if (!inkBoundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin inkBoundingBox.X += glyphRun.BaselineOrigin.X; inkBoundingBox.Y += glyphRun.BaselineOrigin.Y; } if (drawingContext != null) { int pushCount = 0; // the number of push we do try { if (_textEffects != null) { // we need to push in the same order as they are set for (int i = 0; i < _textEffects.Count; i++) { // get the text effect by its index TextEffect textEffect = _textEffects[i]; if (textEffect.Transform != null && textEffect.Transform != Transform.Identity) { drawingContext.PushTransform(textEffect.Transform); pushCount++; } if (textEffect.Clip != null) { drawingContext.PushClip(textEffect.Clip); pushCount++; } if (textEffect.Foreground != null) { // remember the out-most non-null brush // this brush will be used to draw the glyph run foregroundBrush = textEffect.Foreground; } } } _shapeable.Draw(drawingContext, foregroundBrush, glyphRun); } finally { for (int i = 0; i < pushCount; i++) { drawingContext.Pop(); } } } return inkBoundingBox; } ////// Map a UV real coordinate to an XY real coordinate /// /// line drawing origin XY /// vector to line origin UV /// real distance in text flow direction /// real distance in paragraph flow direction /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, double u, double v, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth) - vectorToOrigin.X - u + origin.X, v + origin.Y); } else { xy = new Point(u + vectorToOrigin.X + origin.X, v + origin.Y); } return xy; } ////// Map a UV ideal coordinate to an XY real coordinate /// /// line drawing origin /// vector to line origin UV /// ideal distance in text flow direction /// ideal distance in paragraph flow direction /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, int u, int v, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.Formatter.IdealToReal(line.ParagraphWidth - u) - vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); } else { xy = new Point(line.Formatter.IdealToReal(u) + vectorToOrigin.X + origin.X, line.Formatter.IdealToReal(v) + origin.Y); } return xy; } ////// Map a UV ideal coordinate to an XY ideal coordinate /// /// line drawing origin /// vector to line origin UV /// ideal distance in text flow direction /// ideal distance in paragraph flow direction /// container line /// ideal X origin /// ideal Y origin internal static void UVToNominalXY( Point origin, Point vectorToOrigin, int u, int v, TextMetrics.FullTextLine line, out int nominalX, out int nominalY ) { origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { nominalX = line.ParagraphWidth - u + TextFormatterImp.RealToIdeal(-vectorToOrigin.X + origin.X); } else { nominalX = u + TextFormatterImp.RealToIdeal(vectorToOrigin.X + origin.X); } nominalY = v + TextFormatterImp.RealToIdeal(origin.Y); } ////// Create a rectangle of the two specified UV coordinates /// /// line drawing origin /// logical top-left point /// logical bottom-right point /// container line internal static Rect RectUV( Point origin, LSPOINT topLeft, LSPOINT bottomRight, TextMetrics.FullTextLine line ) { int dx = topLeft.x - bottomRight.x; if(dx == 1 || dx == -1) { // in certain situation LS can be off by 1 bottomRight.x = topLeft.x; } Rect rect = new Rect( new Point(line.Formatter.IdealToReal(topLeft.x), line.Formatter.IdealToReal(topLeft.y)), new Point(line.Formatter.IdealToReal(bottomRight.x), line.Formatter.IdealToReal(bottomRight.y)) ); if(DoubleUtil.AreClose(rect.TopLeft.X, rect.BottomRight.X)) { rect.Width = 0; } if(DoubleUtil.AreClose(rect.TopLeft.Y, rect.BottomRight.Y)) { rect.Height = 0; } return rect; } ////// Move text run's baseline by the specified value /// /// offset to be moved away from baseline internal void Move(int baselineMoveOffset) { _baselineMoveOffset += baselineMoveOffset; } internal byte BidiLevel { get { return _bidiLevel; } } internal bool IsSymbol { get { TextShapeableCharacters shapeable = _shapeable as TextShapeableCharacters; return shapeable != null && shapeable.IsSymbol; } } internal int OffsetToFirstCp { get { return _offsetToFirstCp; } } internal int Length { get { return _textRunLength; } } internal TextModifierScope TextModifierScope { get { return _runInfo.TextModifierScope; } } internal Plsrun Type { get { return _type; } } internal ushort CharacterAttributeFlags { get { return _charFlags; } } internal CharacterBuffer CharacterBuffer { get { return _charBufferRange.CharacterBuffer; } } internal int StringLength { get { return _charBufferRange.Length; } } internal int OffsetToFirstChar { get { return _charBufferRange.OffsetToFirstChar; } } internal TextRun TextRun { get { return _runInfo.TextRun; } } internal TextShapeableSymbols Shapeable { get { return _shapeable; } } internal int BaselineOffset { get { return _baselineOffset; } set { _baselineOffset = value; } } internal int Height { get { return _height; } set { _height = value; } } internal int Descent { get { return Height - BaselineOffset; } } internal TextRunProperties RunProp { get { return _runInfo.Properties; } } internal CultureInfo TextCulture { get { return CultureMapper.GetSpecificCulture(RunProp != null ? RunProp.CultureInfo : null); } } internal int EmSize { get { return _emSize; } } internal int BaselineMoveOffset { get { return _baselineMoveOffset; } } ////// required set of features that will be added to every feature set /// It will be used if nothing is set in typogrpahy porperties /// private enum CustomOpenTypeFeatures { AlternativeFractions , PetiteCapitalsFrom----s , SmallCapitalsFrom----s , ContextualAlternates , CaseSensitiveForms , ContextualLigatures , CapitalSpacing , ContextualSwash , CursivePositioning , DiscretionaryLigatures , ExpertForms , Fractions , FullWidth , HalfForms , HalantForms , AlternateHalfWidth , HistoricalForms , HorizontalKanaAlternates , HistoricalLigatures , HojoKanjiForms , HalfWidth , JIS78Forms , JIS83Forms , JIS90Forms , JIS04Forms , Kerning , StandardLigatures , LiningFigures , MathematicalGreek , AlternateAnnotationForms , NLCKanjiForms , OldStyleFigures , Ordinals , ProportionalAlternateWidth , PetiteCapitals , ProportionalFigures , ProportionalWidths , QuarterWidths , RubyNotationForms , StylisticAlternates , ScientificInferiors , SmallCapitals , SimplifiedForms , StylisticSet1 , StylisticSet2 , StylisticSet3 , StylisticSet4 , StylisticSet5 , StylisticSet6 , StylisticSet7 , StylisticSet8 , StylisticSet9 , StylisticSet10 , StylisticSet11 , StylisticSet12 , StylisticSet13 , StylisticSet14 , StylisticSet15 , StylisticSet16 , StylisticSet17 , StylisticSet18 , StylisticSet19 , StylisticSet20 , Subscript , Superscript , Swash , Titling , TraditionalNameForms , TabularFigures , TraditionalForms , ThirdWidths , Unicase , SlashedZero , Count } private const ushort FeatureNotEnabled = 0xffff; private static DWriteFontFeature[] CreateDWriteFontFeatures(TextRunTypographyProperties textRunTypographyProperties) { if (textRunTypographyProperties != null) { if (textRunTypographyProperties.CachedFeatureSet != null) { return textRunTypographyProperties.CachedFeatureSet; } else { ListfontFeatures = new List ((int)CustomOpenTypeFeatures.Count); if (textRunTypographyProperties.CapitalSpacing) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CapitalSpacing, 1)); } if (textRunTypographyProperties.CaseSensitiveForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.CaseSensitiveForms, 1)); } if (textRunTypographyProperties.ContextualAlternates) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualAlternates, 1)); } if (textRunTypographyProperties.ContextualLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualLigatures, 1)); } if (textRunTypographyProperties.DiscretionaryLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.DiscretionaryLigatures, 1)); } if (textRunTypographyProperties.HistoricalForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalForms, 1)); } if (textRunTypographyProperties.HistoricalLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HistoricalLigatures, 1)); } if (textRunTypographyProperties.Kerning) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Kerning, 1)); } if (textRunTypographyProperties.MathematicalGreek) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.MathematicalGreek, 1)); } if (textRunTypographyProperties.SlashedZero) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SlashedZero, 1)); } if (textRunTypographyProperties.StandardLigatures) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StandardLigatures, 1)); } if (textRunTypographyProperties.StylisticSet1) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet1, 1)); } if (textRunTypographyProperties.StylisticSet10) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet10, 1)); } if (textRunTypographyProperties.StylisticSet11) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet11, 1)); } if (textRunTypographyProperties.StylisticSet12) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet12, 1)); } if (textRunTypographyProperties.StylisticSet13) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet13, 1)); } if (textRunTypographyProperties.StylisticSet14) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet14, 1)); } if (textRunTypographyProperties.StylisticSet15) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet15, 1)); } if (textRunTypographyProperties.StylisticSet16) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet16, 1)); } if (textRunTypographyProperties.StylisticSet17) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet17, 1)); } if (textRunTypographyProperties.StylisticSet18) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet18, 1)); } if (textRunTypographyProperties.StylisticSet19) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet19, 1)); } if (textRunTypographyProperties.StylisticSet2) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet2, 1)); } if (textRunTypographyProperties.StylisticSet20) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet20, 1)); } if (textRunTypographyProperties.StylisticSet3) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet3, 1)); } if (textRunTypographyProperties.StylisticSet4) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet4, 1)); } if (textRunTypographyProperties.StylisticSet5) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet5, 1)); } if (textRunTypographyProperties.StylisticSet6) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet6, 1)); } if (textRunTypographyProperties.StylisticSet7) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet7, 1)); } if (textRunTypographyProperties.StylisticSet8) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet8, 1)); } if (textRunTypographyProperties.StylisticSet9) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticSet9, 1)); } if (textRunTypographyProperties.EastAsianExpertForms) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ExpertForms, 1)); } if (textRunTypographyProperties.AnnotationAlternates > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateAnnotationForms, checked((uint)textRunTypographyProperties.AnnotationAlternates))); } if (textRunTypographyProperties.ContextualSwashes > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ContextualSwash, checked((uint)textRunTypographyProperties.ContextualSwashes))); } if (textRunTypographyProperties.StylisticAlternates > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.StylisticAlternates, checked((uint)textRunTypographyProperties.StylisticAlternates))); } if (textRunTypographyProperties.StandardSwashes > 0) { fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Swash, checked((uint)textRunTypographyProperties.StandardSwashes))); } switch (textRunTypographyProperties.Capitals) { case FontCapitals.AllPetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitalsFrom----s, 1)); break; case FontCapitals.AllSmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitalsFrom----s, 1)); break; case FontCapitals.PetiteCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.PetiteCapitals, 1)); break; case FontCapitals.SmallCaps: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SmallCapitals, 1)); break; case FontCapitals.Titling: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Titling, 1)); break; case FontCapitals.Unicase: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Unicase, 1)); break; } switch (textRunTypographyProperties.EastAsianLanguage) { case FontEastAsianLanguage.Simplified: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.SimplifiedForms, 1)); break; case FontEastAsianLanguage.Traditional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalForms, 1)); break; case FontEastAsianLanguage.TraditionalNames: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TraditionalNameForms, 1)); break; case FontEastAsianLanguage.NlcKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.NLCKanjiForms, 1)); break; case FontEastAsianLanguage.HojoKanji: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HojoKanjiForms, 1)); break; case FontEastAsianLanguage.Jis78: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS78Forms, 1)); break; case FontEastAsianLanguage.Jis83: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS83Forms, 1)); break; case FontEastAsianLanguage.Jis90: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS90Forms, 1)); break; case FontEastAsianLanguage.Jis04: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.JIS04Forms, 1)); break; } switch (textRunTypographyProperties.Fraction) { case FontFraction.Stacked: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternativeFractions, 1)); break; case FontFraction.Slashed: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Fractions, 1)); break; } switch (textRunTypographyProperties.NumeralAlignment) { case FontNumeralAlignment.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalFigures, 1)); break; case FontNumeralAlignment.Tabular: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.TabularFigures, 1)); break; } switch (textRunTypographyProperties.NumeralStyle) { case FontNumeralStyle.Lining: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.LiningFigures, 1)); break; case FontNumeralStyle.OldStyle: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.OldStyleFigures, 1)); break; } switch (textRunTypographyProperties.Variants) { case FontVariants.Inferior: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ScientificInferiors, 1)); break; case FontVariants.Ordinal: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Ordinals, 1)); break; case FontVariants.Ruby: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.RubyNotationForms, 1)); break; case FontVariants.Subscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Subscript, 1)); break; case FontVariants.Superscript: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.Superscript, 1)); break; } switch (textRunTypographyProperties.EastAsianWidths) { case FontEastAsianWidths.Proportional: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalWidths, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ProportionalAlternateWidth, 1)); break; case FontEastAsianWidths.Full: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.FullWidth, 1)); break; case FontEastAsianWidths.Half: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.HalfWidth, 1)); fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.AlternateHalfWidth, 1)); break; case FontEastAsianWidths.Third: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.ThirdWidths, 1)); break; case FontEastAsianWidths.Quarter: fontFeatures.Add(new DWriteFontFeature(Text.TextInterface.DWriteFontFeatureTag.QuarterWidths, 1)); break; } textRunTypographyProperties.CachedFeatureSet = fontFeatures.ToArray(); return textRunTypographyProperties.CachedFeatureSet; } } return null; } /// /// Compile feature set from the linked list of LSRuns. /// TypographyProperties should be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// ////// Critical - deals with unsafe int array /// [SecurityCritical] internal static unsafe void CompileFeatureSet( LSRun[] lsruns, int* pcchRuns, uint totalLength, out DWriteFontFeature[][] fontFeatures, out uint[] fontFeatureRanges ) { Debug.Assert(lsruns != null && lsruns.Length > 0 && lsruns[0] != null); // // Quick check for null properties // Run properties should be all null or all not null // if (lsruns[0].RunProp.TypographyProperties == null) { for (int i = 1; i < lsruns.Length; i++) { if (lsruns[i].RunProp.TypographyProperties != null) { throw new ArgumentException(SR.Get(SRID.CompileFeatureSet_InvalidTypographyProperties)); } } fontFeatures = null; fontFeatureRanges = null; return; } //End of quick check. We will process custom features now. fontFeatures = new DWriteFontFeature[lsruns.Length][]; fontFeatureRanges = new uint[lsruns.Length]; for (int i = 0; i < lsruns.Length; i++) { TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; fontFeatures[i] = CreateDWriteFontFeatures(properties); fontFeatureRanges[i] = checked((uint)pcchRuns[i]); } } ////// Compile feature set from the linked list of LSRuns. /// TypographyProperties should be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// internal static void CompileFeatureSet( TextRunTypographyProperties textRunTypographyProperties, uint totalLength, out DWriteFontFeature[][] fontFeatures, out uint[] fontFeatureRanges ) { // // Quick check for null properties // Run properties should be all null or all not null // if (textRunTypographyProperties == null) { fontFeatures = null; fontFeatureRanges = null; } else { // End of quick check. We will process custom features now. fontFeatures = new DWriteFontFeature[1][]; fontFeatureRanges = new uint[1]; fontFeatures[0] = CreateDWriteFontFeatures(textRunTypographyProperties); fontFeatureRanges[0] = totalLength; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PrivateUnsafeNativeCompoundFileMethods.cs
- FileInfo.cs
- DataGridViewUtilities.cs
- Parallel.cs
- GPStream.cs
- StylusButtonEventArgs.cs
- TableProviderWrapper.cs
- QueryGeneratorBase.cs
- Group.cs
- BeginEvent.cs
- ContextMenuService.cs
- ArraySubsetEnumerator.cs
- JsonSerializer.cs
- xmlglyphRunInfo.cs
- TrustManagerMoreInformation.cs
- CodeDelegateInvokeExpression.cs
- TextWriter.cs
- ColorConverter.cs
- ToolStripDropTargetManager.cs
- BitmapImage.cs
- PeerInvitationResponse.cs
- ColumnResizeAdorner.cs
- WindowVisualStateTracker.cs
- DecoderBestFitFallback.cs
- TraceInternal.cs
- PartialClassGenerationTaskInternal.cs
- BinaryParser.cs
- DialogResultConverter.cs
- DesignerActionItemCollection.cs
- TemplateBindingExtension.cs
- QilPatternFactory.cs
- ToolStripDesignerAvailabilityAttribute.cs
- ClientScriptManager.cs
- ProfilePropertyNameValidator.cs
- ServiceBusyException.cs
- Identity.cs
- DTCTransactionManager.cs
- DbProviderFactoriesConfigurationHandler.cs
- InkCanvasAutomationPeer.cs
- LinearKeyFrames.cs
- SynchronizationFilter.cs
- PageContentCollection.cs
- Serializer.cs
- DependencyPropertyHelper.cs
- PropertiesTab.cs
- Int32CollectionConverter.cs
- BufferBuilder.cs
- NumberFormatInfo.cs
- StatusBar.cs
- MembershipPasswordException.cs
- FormatConvertedBitmap.cs
- TextEndOfParagraph.cs
- GroupByExpressionRewriter.cs
- TableParaClient.cs
- CodeAssignStatement.cs
- DataGridViewBindingCompleteEventArgs.cs
- XmlSchemaSimpleContentExtension.cs
- CodeComment.cs
- CommandDevice.cs
- DoubleAnimationBase.cs
- RightNameExpirationInfoPair.cs
- BatchServiceHost.cs
- CustomValidator.cs
- CharacterString.cs
- CqlErrorHelper.cs
- RegexReplacement.cs
- Executor.cs
- DesignerVerb.cs
- ProviderMetadataCachedInformation.cs
- QilLiteral.cs
- SqlWriter.cs
- WinFormsComponentEditor.cs
- SqlServices.cs
- CmsUtils.cs
- CompiledRegexRunner.cs
- UInt64.cs
- StrokeNodeOperations2.cs
- relpropertyhelper.cs
- HyperlinkAutomationPeer.cs
- ServiceObjectContainer.cs
- FixedSOMTextRun.cs
- SelectionItemProviderWrapper.cs
- util.cs
- Int64KeyFrameCollection.cs
- KeyFrames.cs
- TableCellCollection.cs
- DPTypeDescriptorContext.cs
- WrapperEqualityComparer.cs
- ClientScriptManager.cs
- AsyncOperationManager.cs
- ScriptReferenceEventArgs.cs
- WebBrowserBase.cs
- SettingsContext.cs
- SequenceRange.cs
- Int32CollectionConverter.cs
- ComponentChangedEvent.cs
- NGCSerializationManagerAsync.cs
- SourceItem.cs
- StateDesigner.Helpers.cs
- ProfileBuildProvider.cs