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
- SHA384CryptoServiceProvider.cs
- SoapException.cs
- WorkflowEnvironment.cs
- CachedRequestParams.cs
- NotifyInputEventArgs.cs
- XmlSignificantWhitespace.cs
- X509SecurityTokenAuthenticator.cs
- ConnectorSelectionGlyph.cs
- WebCodeGenerator.cs
- RequestDescription.cs
- RtfControls.cs
- Cell.cs
- SmiEventSink_Default.cs
- ObjectSerializerFactory.cs
- SynchronizedRandom.cs
- XmlAtomicValue.cs
- OrderByBuilder.cs
- Msec.cs
- RuleProcessor.cs
- DataReaderContainer.cs
- TextElementEnumerator.cs
- DesignerActionItem.cs
- EncryptedType.cs
- ProfilePropertyNameValidator.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- EdmConstants.cs
- AsymmetricSignatureFormatter.cs
- TabControl.cs
- WrapPanel.cs
- TypeName.cs
- AuthenticateEventArgs.cs
- HybridDictionary.cs
- ScriptReferenceEventArgs.cs
- WpfWebRequestHelper.cs
- ProfilePropertyNameValidator.cs
- RegexCode.cs
- TransformerTypeCollection.cs
- CompilerResults.cs
- DocumentGridContextMenu.cs
- Image.cs
- PropertyAccessVisitor.cs
- MailAddressParser.cs
- CodeMemberField.cs
- BitmapEffectGeneralTransform.cs
- BasicDesignerLoader.cs
- InputEventArgs.cs
- XmlAnyElementAttribute.cs
- ClaimTypes.cs
- DataRecordInternal.cs
- DataSetMappper.cs
- EventLogInformation.cs
- WebConfigurationFileMap.cs
- SeekStoryboard.cs
- ImmutableCollection.cs
- EventArgs.cs
- TypeUnloadedException.cs
- CompilerHelpers.cs
- XmlDataProvider.cs
- UserPersonalizationStateInfo.cs
- SelectedGridItemChangedEvent.cs
- RelationshipConstraintValidator.cs
- XmlSchemaInclude.cs
- PromptEventArgs.cs
- DescendantOverDescendantQuery.cs
- CodeAttributeDeclarationCollection.cs
- RowSpanVector.cs
- TrustSection.cs
- IsolatedStorageException.cs
- ThreadAbortException.cs
- SubpageParaClient.cs
- MenuCommands.cs
- OdbcParameterCollection.cs
- SqlMetaData.cs
- HttpModuleCollection.cs
- HtmlElement.cs
- Vector.cs
- DateTimeConverter2.cs
- OleDbConnectionFactory.cs
- HtmlInputButton.cs
- WorkflowQueueInfo.cs
- FileSystemWatcher.cs
- DateRangeEvent.cs
- Utility.cs
- DataGridCommandEventArgs.cs
- ProcessHostServerConfig.cs
- ObjectDataSourceChooseMethodsPanel.cs
- SafeLocalMemHandle.cs
- PointLight.cs
- DockPatternIdentifiers.cs
- RegexGroupCollection.cs
- ApplicationTrust.cs
- Label.cs
- WebPartConnectionsConnectVerb.cs
- MeshGeometry3D.cs
- ComPlusServiceHost.cs
- TickBar.cs
- FtpWebRequest.cs
- DoubleLinkListEnumerator.cs
- ControlUtil.cs
- Membership.cs