Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / MS / Internal / TextFormatting / LineServicesRun.cs / 1 / 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; 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 /// ideal to real scaling factor /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, double u, double v, double toReal, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.ParagraphWidth * toReal - 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 /// ideal to real scaling factor /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, int u, int v, double toReal, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point((line.ParagraphWidth - u) * toReal - vectorToOrigin.X + origin.X, v * toReal + origin.Y); } else { xy = new Point(u * toReal + vectorToOrigin.X + origin.X, v * toReal + origin.Y); } return xy; } ////// Create a rectangle of the two specified UV coordinates /// /// line drawing origin /// logical top-left point /// logical bottom-right point /// ideal to real scaling factor /// container line internal static Rect RectUV( Point origin, LSPOINT topLeft, LSPOINT bottomRight, double toReal, 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(topLeft.x * toReal, topLeft.y * toReal), new Point(bottomRight.x * toReal, bottomRight.y * toReal) ); 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 static readonly Feature[] RequiredFeatures = { new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.locl,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.ccmp,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.rlig,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mark,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mkmk,1) }; ////// Set of features corresponding to TextRunTypographyProperties.DefaultProperties /// private static readonly Feature[] DefaultFeatures = { new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.locl,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.ccmp,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.rlig,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.kern,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mark,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mkmk,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.liga,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.calt,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.clig,1) }; 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 static FeatureTags[] CustomOpenTypeFeatureTags = new FeatureTags[(int)CustomOpenTypeFeatures.Count] { FeatureTags.AlternativeFractions , FeatureTags.PetiteCapitalsFrom----s , FeatureTags.SmallCapitalsFrom----s , FeatureTags.ContextualAlternates , FeatureTags.CaseSensitiveForms , FeatureTags.ContextualLigatures , FeatureTags.CapitalSpacing , FeatureTags.ContextualSwash , FeatureTags.CursivePositioning , FeatureTags.DiscretionaryLigatures , FeatureTags.ExpertForms , FeatureTags.Fractions , FeatureTags.FullWidth , FeatureTags.HalfForms , FeatureTags.HalantForms , FeatureTags.AlternateHalfWidth , FeatureTags.HistoricalForms , FeatureTags.HorizontalKanaAlternates , FeatureTags.HistoricalLigatures , FeatureTags.HojoKanjiForms , FeatureTags.HalfWidth , FeatureTags.JIS78Forms , FeatureTags.JIS83Forms , FeatureTags.JIS90Forms , FeatureTags.JIS04Forms , FeatureTags.Kerning , FeatureTags.StandardLigatures , FeatureTags.LiningFigures , FeatureTags.MathematicalGreek , FeatureTags.AlternateAnnotationForms , FeatureTags.NLCKanjiForms , FeatureTags.OldStyleFigures , FeatureTags.Ordinals , FeatureTags.ProportionalAlternateWidth , FeatureTags.PetiteCapitals , FeatureTags.ProportionalFigures , FeatureTags.ProportionalWidths , FeatureTags.QuarterWidths , FeatureTags.RubyNotationForms , FeatureTags.StylisticAlternates , FeatureTags.ScientificInferiors , FeatureTags.SmallCapitals , FeatureTags.SimplifiedForms , FeatureTags.StylisticSet1 , FeatureTags.StylisticSet2 , FeatureTags.StylisticSet3 , FeatureTags.StylisticSet4 , FeatureTags.StylisticSet5 , FeatureTags.StylisticSet6 , FeatureTags.StylisticSet7 , FeatureTags.StylisticSet8 , FeatureTags.StylisticSet9 , FeatureTags.StylisticSet10 , FeatureTags.StylisticSet11 , FeatureTags.StylisticSet12 , FeatureTags.StylisticSet13 , FeatureTags.StylisticSet14 , FeatureTags.StylisticSet15 , FeatureTags.StylisticSet16 , FeatureTags.StylisticSet17 , FeatureTags.StylisticSet18 , FeatureTags.StylisticSet19 , FeatureTags.StylisticSet20 , FeatureTags.Subscript , FeatureTags.Superscript , FeatureTags.Swash , FeatureTags.Titling , FeatureTags.TraditionalNameForms , FeatureTags.TabularFigures , FeatureTags.TraditionalForms , FeatureTags.ThirdWidths , FeatureTags.Unicase , FeatureTags.SlashedZero }; private const ushort FeatureNotEnabled = 0xffff; /// /// Compile feature set from the linked list of LSRuns /// /// TypographyProperties shoulde be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// /// ///Feature set ////// Critical - This method uses stackalloc to allocate buffer on stack and uses a pointer to that buffer. /// It also accesses unmanaged memory. /// [SecurityCritical] internal static unsafe FeatureSet CompileFeatureSet( LSRun[] lsruns, int* pcchRuns ) { 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)); } } return new FeatureSet((uint)LanguageTags.Default, DefaultFeatures, DefaultFeatures.Length); } //End of quick check. We will process custom features now. Feature[] features; int featureCount; // Check if this properties are already cached. // This will work only if they already had been cached together, // i.e. all cached features are the same. // ( We do not call Equals on all porperties, because it is considered expensive) bool sameFeatures = true; lsruns[0].RunProp.TypographyProperties.GetCachedFeatureSet(out features, out featureCount); if (features != null) // otherwise, we will have to go through features anyway { for(int i = 1; i < lsruns.Length; i++) { Feature[] currentFeatures; int currentFeatureCount; lsruns[i].RunProp.TypographyProperties.GetCachedFeatureSet(out currentFeatures, out currentFeatureCount); if (features != currentFeatures || featureCount != currentFeatureCount /* can this actually be if arrays are the same? I guess not, but just in case */ ) { sameFeatures = false; break; } } if (sameFeatures) { return new FeatureSet((uint)LanguageTags.Default,features,featureCount); } } //Create new set, add required features int initialFeatureCount = RequiredFeatures.Length + 5; features = new Feature[initialFeatureCount]; featureCount = RequiredFeatures.Length; Array.Copy(RequiredFeatures,features,RequiredFeatures.Length); //Allocate feature index array, initalize all features to not enabled ushort* featureIndex = stackalloc ushort[(int)CustomOpenTypeFeatures.Count]; for (int i = 0; i < (int)CustomOpenTypeFeatures.Count; i++) { featureIndex[i] = FeatureNotEnabled; } int currentStart = 0, currentLength; for(int i = 0; i < lsruns.Length; i++) { TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; currentLength = pcchRuns[i]; Debug.Assert(currentStart < ushort.MaxValue); Debug.Assert((currentStart + currentLength) < ushort.MaxValue); //StandardLigatures SetFeature(CustomOpenTypeFeatures.StandardLigatures, properties.StandardLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Kerning SetFeature(CustomOpenTypeFeatures.Kerning, properties.Kerning?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //----s switch (properties.Capitals) { case FontCapitals.Normal: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.SmallCaps: SetFeature( CustomOpenTypeFeatures.SmallCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.AllSmallCaps: SetFeature( CustomOpenTypeFeatures.SmallCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature( CustomOpenTypeFeatures.SmallCapitalsFrom----s, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.PetiteCaps: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); SetFeature( CustomOpenTypeFeatures.PetiteCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.AllPetiteCaps: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); SetFeature( CustomOpenTypeFeatures.PetiteCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature( CustomOpenTypeFeatures.PetiteCapitalsFrom----s,1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.Unicase: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); SetFeature( CustomOpenTypeFeatures.Unicase, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.Titling: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); SetFeature( CustomOpenTypeFeatures.Titling, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //NumeralStyle switch (properties.NumeralStyle) { case FontNumeralStyle.Normal: DisableFeature(CustomOpenTypeFeatures.LiningFigures, featureIndex); DisableFeature(CustomOpenTypeFeatures.OldStyleFigures, featureIndex); break; case FontNumeralStyle.Lining: SetFeature( CustomOpenTypeFeatures.LiningFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.OldStyleFigures, featureIndex); break; case FontNumeralStyle.OldStyle: DisableFeature(CustomOpenTypeFeatures.LiningFigures, featureIndex); SetFeature( CustomOpenTypeFeatures.OldStyleFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //NumeralAlignment switch (properties.NumeralAlignment) { case FontNumeralAlignment.Normal: DisableFeature(CustomOpenTypeFeatures.ProportionalFigures, featureIndex); DisableFeature(CustomOpenTypeFeatures.TabularFigures, featureIndex); break; case FontNumeralAlignment.Proportional: SetFeature( CustomOpenTypeFeatures.ProportionalFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TabularFigures, featureIndex); break; case FontNumeralAlignment.Tabular: DisableFeature(CustomOpenTypeFeatures.ProportionalFigures, featureIndex); SetFeature( CustomOpenTypeFeatures.TabularFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //Fraction switch (properties.Fraction) { case FontFraction.Normal: DisableFeature(CustomOpenTypeFeatures.Fractions, featureIndex); DisableFeature(CustomOpenTypeFeatures.AlternativeFractions, featureIndex); break; case FontFraction.Stacked: DisableFeature(CustomOpenTypeFeatures.Fractions, featureIndex); SetFeature( CustomOpenTypeFeatures.AlternativeFractions, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; case FontFraction.Slashed: SetFeature( CustomOpenTypeFeatures.Fractions, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.AlternativeFractions, featureIndex); break; } //DiscretionaryLigatures SetFeature(CustomOpenTypeFeatures.DiscretionaryLigatures, properties.DiscretionaryLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //HistoricalLigatures SetFeature(CustomOpenTypeFeatures.HistoricalLigatures, properties.HistoricalLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //HistoricalForms SetFeature(CustomOpenTypeFeatures.HistoricalForms, properties.HistoricalForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //FontVariants switch (properties.Variants) { case FontVariants.Normal: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Inferior: SetFeature( CustomOpenTypeFeatures.ScientificInferiors, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Ordinal: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); SetFeature( CustomOpenTypeFeatures.Ordinals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Ruby: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); SetFeature (CustomOpenTypeFeatures.RubyNotationForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Subscript: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); SetFeature (CustomOpenTypeFeatures.Subscript, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Superscript: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); SetFeature (CustomOpenTypeFeatures.Superscript, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //ContextualLigatures SetFeature(CustomOpenTypeFeatures.ContextualLigatures, properties.ContextualLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Contextual alternates SetFeature(CustomOpenTypeFeatures.ContextualAlternates, properties.ContextualAlternates?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //CapitalSpacing SetFeature(CustomOpenTypeFeatures.CapitalSpacing, properties.CapitalSpacing?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Case sensitive forms SetFeature(CustomOpenTypeFeatures.CaseSensitiveForms, properties.CaseSensitiveForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet1 SetFeature(CustomOpenTypeFeatures.StylisticSet1, properties.StylisticSet1?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet2 SetFeature(CustomOpenTypeFeatures.StylisticSet2, properties.StylisticSet2?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet3 SetFeature(CustomOpenTypeFeatures.StylisticSet3, properties.StylisticSet3?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet4 SetFeature(CustomOpenTypeFeatures.StylisticSet4, properties.StylisticSet4?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet5 SetFeature(CustomOpenTypeFeatures.StylisticSet5, properties.StylisticSet5?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet6 SetFeature(CustomOpenTypeFeatures.StylisticSet6, properties.StylisticSet6?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet7 SetFeature(CustomOpenTypeFeatures.StylisticSet7, properties.StylisticSet7?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet8 SetFeature(CustomOpenTypeFeatures.StylisticSet8, properties.StylisticSet8?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet9 SetFeature(CustomOpenTypeFeatures.StylisticSet9, properties.StylisticSet9?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet10 SetFeature(CustomOpenTypeFeatures.StylisticSet10, properties.StylisticSet10?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet11 SetFeature(CustomOpenTypeFeatures.StylisticSet11, properties.StylisticSet11?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet12 SetFeature(CustomOpenTypeFeatures.StylisticSet12, properties.StylisticSet12?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet13 SetFeature(CustomOpenTypeFeatures.StylisticSet13, properties.StylisticSet13?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet14 SetFeature(CustomOpenTypeFeatures.StylisticSet14, properties.StylisticSet14?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet15 SetFeature(CustomOpenTypeFeatures.StylisticSet15, properties.StylisticSet15?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet16 SetFeature(CustomOpenTypeFeatures.StylisticSet16, properties.StylisticSet16?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet17 SetFeature(CustomOpenTypeFeatures.StylisticSet17, properties.StylisticSet17?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet18 SetFeature(CustomOpenTypeFeatures.StylisticSet18, properties.StylisticSet18?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet19 SetFeature(CustomOpenTypeFeatures.StylisticSet19, properties.StylisticSet19?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet20 SetFeature(CustomOpenTypeFeatures.StylisticSet20, properties.StylisticSet20?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //SlashedZero SetFeature(CustomOpenTypeFeatures.SlashedZero, properties.SlashedZero?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //MathematicalGreek SetFeature(CustomOpenTypeFeatures.MathematicalGreek, properties.MathematicalGreek?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //EastAsian expert forms SetFeature(CustomOpenTypeFeatures.ExpertForms, properties.EastAsianExpertForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Standard swashes SetFeature(CustomOpenTypeFeatures.Swash, properties.StandardSwashes, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Contextual swashes SetFeature(CustomOpenTypeFeatures.ContextualSwash, properties.ContextualSwashes, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Stylistic alternates SetFeature(CustomOpenTypeFeatures.StylisticAlternates, properties.StylisticAlternates, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Annotation alternates. SetFeature(CustomOpenTypeFeatures.AlternateAnnotationForms, properties.AnnotationAlternates, currentStart, currentLength, featureIndex, ref features, ref featureCount); //EastAsian Widths switch (properties.EastAsianWidths) { case FontEastAsianWidths.Normal: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Proportional: SetFeature (CustomOpenTypeFeatures.ProportionalWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature (CustomOpenTypeFeatures.ProportionalAlternateWidth,1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Full: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); SetFeature (CustomOpenTypeFeatures.FullWidth, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Half: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); SetFeature (CustomOpenTypeFeatures.HalfWidth, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Third: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); SetFeature (CustomOpenTypeFeatures.ThirdWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Quarter: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); SetFeature (CustomOpenTypeFeatures.QuarterWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //EastAsian language switch (properties.EastAsianLanguage) { case FontEastAsianLanguage.Normal: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Simplified: SetFeature (CustomOpenTypeFeatures.SimplifiedForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Traditional: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); SetFeature (CustomOpenTypeFeatures.TraditionalForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.TraditionalNames: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); SetFeature (CustomOpenTypeFeatures.TraditionalNameForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.NlcKanji: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); SetFeature (CustomOpenTypeFeatures.NLCKanjiForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.HojoKanji: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); SetFeature (CustomOpenTypeFeatures.HojoKanjiForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis78: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS78Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis83: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS83Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis90: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS90Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis04: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS04Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } currentStart += currentLength; } // Check if all runs have actually the same features. // All feature record should start at 0 and have full length // We skip required features in this check, because they are always the same sameFeatures = true; for(int i = RequiredFeatures.Length; i < featureCount; i++) { if (features[i].StartIndex != 0 || features[i].Length != currentStart ) { sameFeatures = false; break; } } if (sameFeatures) { // Change length for each feature record to 65535, so they do not depend on // particular input length and can be cached for(int i = RequiredFeatures.Length; i < featureCount; i++) { features[i].Length = ushort.MaxValue; } // Now cache features inside each run for(int i = 0; i < lsruns.Length; i++) { lsruns[i].RunProp.TypographyProperties.SetCachedFeatureSet(features, featureCount); } } return new FeatureSet((uint)LanguageTags.Default,features,featureCount); } ////// Critical: This code dereferences a pointer without validation /// [SecurityCritical] private static unsafe void SetFeature( CustomOpenTypeFeatures feature, int parameter, int start, int length, ushort* featureIndex, ref Feature[] features, ref int featureCount ) { if (parameter == 0) { // Nothing to change, just set featureIndex to not enabled featureIndex[(int)feature] = FeatureNotEnabled; return; } ushort index = featureIndex[(int)feature]; Debug.Assert( // if feature is already enabled, index should be valid and feature record should have the same tag index == FeatureNotEnabled || (index < featureCount && features[index].Tag == (uint)CustomOpenTypeFeatureTags[(int)feature]) ); // Check if we can just append to existing feature record if (index != FeatureNotEnabled && features[index].Parameter == parameter ) { features[index].Length += (ushort)length; return; } // // We should add another feature record // if (featureCount == ushort.MaxValue) { throw new OutOfMemoryException(); } // reallocate if it is needed if (featureCount == features.Length) { Feature[] tempFeatures = new Feature[features.Length + 3]; Array.Copy(features, tempFeatures, features.Length); features = tempFeatures; } features[featureCount] = new Feature( (ushort)start, (ushort)length, (uint)CustomOpenTypeFeatureTags[(int)feature], (uint)parameter ); //Set this as current record for the feature featureIndex[(int)feature] = (ushort)featureCount; featureCount++; } ////// This is simplified version of SetFeature, /// assuming that parameter is 0 /// ////// Critical: This code dereferences a pointer without validation /// [SecurityCritical] private static unsafe void DisableFeature( CustomOpenTypeFeatures feature, ushort* featureIndex ) { // Nothing to change, just set featureIndex to not enabled featureIndex[(int)feature] = FeatureNotEnabled; } } } // 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; 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 /// ideal to real scaling factor /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, double u, double v, double toReal, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point(line.ParagraphWidth * toReal - 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 /// ideal to real scaling factor /// container line internal static Point UVToXY( Point origin, Point vectorToOrigin, int u, int v, double toReal, TextMetrics.FullTextLine line ) { Point xy; origin.Y += vectorToOrigin.Y; if (line.RightToLeft) { xy = new Point((line.ParagraphWidth - u) * toReal - vectorToOrigin.X + origin.X, v * toReal + origin.Y); } else { xy = new Point(u * toReal + vectorToOrigin.X + origin.X, v * toReal + origin.Y); } return xy; } ////// Create a rectangle of the two specified UV coordinates /// /// line drawing origin /// logical top-left point /// logical bottom-right point /// ideal to real scaling factor /// container line internal static Rect RectUV( Point origin, LSPOINT topLeft, LSPOINT bottomRight, double toReal, 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(topLeft.x * toReal, topLeft.y * toReal), new Point(bottomRight.x * toReal, bottomRight.y * toReal) ); 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 static readonly Feature[] RequiredFeatures = { new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.locl,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.ccmp,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.rlig,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mark,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mkmk,1) }; ////// Set of features corresponding to TextRunTypographyProperties.DefaultProperties /// private static readonly Feature[] DefaultFeatures = { new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.locl,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.ccmp,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.rlig,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.kern,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mark,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.mkmk,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.liga,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.calt,1), new Feature(0,ushort.MaxValue,(uint)OpenTypeTags.clig,1) }; 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 static FeatureTags[] CustomOpenTypeFeatureTags = new FeatureTags[(int)CustomOpenTypeFeatures.Count] { FeatureTags.AlternativeFractions , FeatureTags.PetiteCapitalsFrom----s , FeatureTags.SmallCapitalsFrom----s , FeatureTags.ContextualAlternates , FeatureTags.CaseSensitiveForms , FeatureTags.ContextualLigatures , FeatureTags.CapitalSpacing , FeatureTags.ContextualSwash , FeatureTags.CursivePositioning , FeatureTags.DiscretionaryLigatures , FeatureTags.ExpertForms , FeatureTags.Fractions , FeatureTags.FullWidth , FeatureTags.HalfForms , FeatureTags.HalantForms , FeatureTags.AlternateHalfWidth , FeatureTags.HistoricalForms , FeatureTags.HorizontalKanaAlternates , FeatureTags.HistoricalLigatures , FeatureTags.HojoKanjiForms , FeatureTags.HalfWidth , FeatureTags.JIS78Forms , FeatureTags.JIS83Forms , FeatureTags.JIS90Forms , FeatureTags.JIS04Forms , FeatureTags.Kerning , FeatureTags.StandardLigatures , FeatureTags.LiningFigures , FeatureTags.MathematicalGreek , FeatureTags.AlternateAnnotationForms , FeatureTags.NLCKanjiForms , FeatureTags.OldStyleFigures , FeatureTags.Ordinals , FeatureTags.ProportionalAlternateWidth , FeatureTags.PetiteCapitals , FeatureTags.ProportionalFigures , FeatureTags.ProportionalWidths , FeatureTags.QuarterWidths , FeatureTags.RubyNotationForms , FeatureTags.StylisticAlternates , FeatureTags.ScientificInferiors , FeatureTags.SmallCapitals , FeatureTags.SimplifiedForms , FeatureTags.StylisticSet1 , FeatureTags.StylisticSet2 , FeatureTags.StylisticSet3 , FeatureTags.StylisticSet4 , FeatureTags.StylisticSet5 , FeatureTags.StylisticSet6 , FeatureTags.StylisticSet7 , FeatureTags.StylisticSet8 , FeatureTags.StylisticSet9 , FeatureTags.StylisticSet10 , FeatureTags.StylisticSet11 , FeatureTags.StylisticSet12 , FeatureTags.StylisticSet13 , FeatureTags.StylisticSet14 , FeatureTags.StylisticSet15 , FeatureTags.StylisticSet16 , FeatureTags.StylisticSet17 , FeatureTags.StylisticSet18 , FeatureTags.StylisticSet19 , FeatureTags.StylisticSet20 , FeatureTags.Subscript , FeatureTags.Superscript , FeatureTags.Swash , FeatureTags.Titling , FeatureTags.TraditionalNameForms , FeatureTags.TabularFigures , FeatureTags.TraditionalForms , FeatureTags.ThirdWidths , FeatureTags.Unicase , FeatureTags.SlashedZero }; private const ushort FeatureNotEnabled = 0xffff; /// /// Compile feature set from the linked list of LSRuns /// /// TypographyProperties shoulde be either all null or all not-null. /// First is used for internal purposes, also can be used by simple clients. /// /// ///Feature set ////// Critical - This method uses stackalloc to allocate buffer on stack and uses a pointer to that buffer. /// It also accesses unmanaged memory. /// [SecurityCritical] internal static unsafe FeatureSet CompileFeatureSet( LSRun[] lsruns, int* pcchRuns ) { 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)); } } return new FeatureSet((uint)LanguageTags.Default, DefaultFeatures, DefaultFeatures.Length); } //End of quick check. We will process custom features now. Feature[] features; int featureCount; // Check if this properties are already cached. // This will work only if they already had been cached together, // i.e. all cached features are the same. // ( We do not call Equals on all porperties, because it is considered expensive) bool sameFeatures = true; lsruns[0].RunProp.TypographyProperties.GetCachedFeatureSet(out features, out featureCount); if (features != null) // otherwise, we will have to go through features anyway { for(int i = 1; i < lsruns.Length; i++) { Feature[] currentFeatures; int currentFeatureCount; lsruns[i].RunProp.TypographyProperties.GetCachedFeatureSet(out currentFeatures, out currentFeatureCount); if (features != currentFeatures || featureCount != currentFeatureCount /* can this actually be if arrays are the same? I guess not, but just in case */ ) { sameFeatures = false; break; } } if (sameFeatures) { return new FeatureSet((uint)LanguageTags.Default,features,featureCount); } } //Create new set, add required features int initialFeatureCount = RequiredFeatures.Length + 5; features = new Feature[initialFeatureCount]; featureCount = RequiredFeatures.Length; Array.Copy(RequiredFeatures,features,RequiredFeatures.Length); //Allocate feature index array, initalize all features to not enabled ushort* featureIndex = stackalloc ushort[(int)CustomOpenTypeFeatures.Count]; for (int i = 0; i < (int)CustomOpenTypeFeatures.Count; i++) { featureIndex[i] = FeatureNotEnabled; } int currentStart = 0, currentLength; for(int i = 0; i < lsruns.Length; i++) { TextRunTypographyProperties properties = lsruns[i].RunProp.TypographyProperties; currentLength = pcchRuns[i]; Debug.Assert(currentStart < ushort.MaxValue); Debug.Assert((currentStart + currentLength) < ushort.MaxValue); //StandardLigatures SetFeature(CustomOpenTypeFeatures.StandardLigatures, properties.StandardLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Kerning SetFeature(CustomOpenTypeFeatures.Kerning, properties.Kerning?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //----s switch (properties.Capitals) { case FontCapitals.Normal: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.SmallCaps: SetFeature( CustomOpenTypeFeatures.SmallCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.AllSmallCaps: SetFeature( CustomOpenTypeFeatures.SmallCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature( CustomOpenTypeFeatures.SmallCapitalsFrom----s, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.PetiteCaps: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); SetFeature( CustomOpenTypeFeatures.PetiteCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.AllPetiteCaps: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); SetFeature( CustomOpenTypeFeatures.PetiteCapitals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature( CustomOpenTypeFeatures.PetiteCapitalsFrom----s,1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.Unicase: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); SetFeature( CustomOpenTypeFeatures.Unicase, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Titling, featureIndex); break; case FontCapitals.Titling: DisableFeature(CustomOpenTypeFeatures.SmallCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.SmallCapitalsFrom----s, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitals, featureIndex); DisableFeature(CustomOpenTypeFeatures.PetiteCapitalsFrom----s,featureIndex); DisableFeature(CustomOpenTypeFeatures.Unicase, featureIndex); SetFeature( CustomOpenTypeFeatures.Titling, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //NumeralStyle switch (properties.NumeralStyle) { case FontNumeralStyle.Normal: DisableFeature(CustomOpenTypeFeatures.LiningFigures, featureIndex); DisableFeature(CustomOpenTypeFeatures.OldStyleFigures, featureIndex); break; case FontNumeralStyle.Lining: SetFeature( CustomOpenTypeFeatures.LiningFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.OldStyleFigures, featureIndex); break; case FontNumeralStyle.OldStyle: DisableFeature(CustomOpenTypeFeatures.LiningFigures, featureIndex); SetFeature( CustomOpenTypeFeatures.OldStyleFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //NumeralAlignment switch (properties.NumeralAlignment) { case FontNumeralAlignment.Normal: DisableFeature(CustomOpenTypeFeatures.ProportionalFigures, featureIndex); DisableFeature(CustomOpenTypeFeatures.TabularFigures, featureIndex); break; case FontNumeralAlignment.Proportional: SetFeature( CustomOpenTypeFeatures.ProportionalFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TabularFigures, featureIndex); break; case FontNumeralAlignment.Tabular: DisableFeature(CustomOpenTypeFeatures.ProportionalFigures, featureIndex); SetFeature( CustomOpenTypeFeatures.TabularFigures, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //Fraction switch (properties.Fraction) { case FontFraction.Normal: DisableFeature(CustomOpenTypeFeatures.Fractions, featureIndex); DisableFeature(CustomOpenTypeFeatures.AlternativeFractions, featureIndex); break; case FontFraction.Stacked: DisableFeature(CustomOpenTypeFeatures.Fractions, featureIndex); SetFeature( CustomOpenTypeFeatures.AlternativeFractions, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; case FontFraction.Slashed: SetFeature( CustomOpenTypeFeatures.Fractions, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.AlternativeFractions, featureIndex); break; } //DiscretionaryLigatures SetFeature(CustomOpenTypeFeatures.DiscretionaryLigatures, properties.DiscretionaryLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //HistoricalLigatures SetFeature(CustomOpenTypeFeatures.HistoricalLigatures, properties.HistoricalLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //HistoricalForms SetFeature(CustomOpenTypeFeatures.HistoricalForms, properties.HistoricalForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //FontVariants switch (properties.Variants) { case FontVariants.Normal: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Inferior: SetFeature( CustomOpenTypeFeatures.ScientificInferiors, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Ordinal: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); SetFeature( CustomOpenTypeFeatures.Ordinals, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Ruby: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); SetFeature (CustomOpenTypeFeatures.RubyNotationForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Subscript: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); SetFeature (CustomOpenTypeFeatures.Subscript, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.Superscript, featureIndex); break; case FontVariants.Superscript: DisableFeature(CustomOpenTypeFeatures.ScientificInferiors, featureIndex); DisableFeature(CustomOpenTypeFeatures.Ordinals, featureIndex); DisableFeature(CustomOpenTypeFeatures.RubyNotationForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.Subscript, featureIndex); SetFeature (CustomOpenTypeFeatures.Superscript, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //ContextualLigatures SetFeature(CustomOpenTypeFeatures.ContextualLigatures, properties.ContextualLigatures?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Contextual alternates SetFeature(CustomOpenTypeFeatures.ContextualAlternates, properties.ContextualAlternates?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //CapitalSpacing SetFeature(CustomOpenTypeFeatures.CapitalSpacing, properties.CapitalSpacing?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Case sensitive forms SetFeature(CustomOpenTypeFeatures.CaseSensitiveForms, properties.CaseSensitiveForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet1 SetFeature(CustomOpenTypeFeatures.StylisticSet1, properties.StylisticSet1?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet2 SetFeature(CustomOpenTypeFeatures.StylisticSet2, properties.StylisticSet2?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet3 SetFeature(CustomOpenTypeFeatures.StylisticSet3, properties.StylisticSet3?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet4 SetFeature(CustomOpenTypeFeatures.StylisticSet4, properties.StylisticSet4?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet5 SetFeature(CustomOpenTypeFeatures.StylisticSet5, properties.StylisticSet5?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet6 SetFeature(CustomOpenTypeFeatures.StylisticSet6, properties.StylisticSet6?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet7 SetFeature(CustomOpenTypeFeatures.StylisticSet7, properties.StylisticSet7?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet8 SetFeature(CustomOpenTypeFeatures.StylisticSet8, properties.StylisticSet8?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet9 SetFeature(CustomOpenTypeFeatures.StylisticSet9, properties.StylisticSet9?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet10 SetFeature(CustomOpenTypeFeatures.StylisticSet10, properties.StylisticSet10?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet11 SetFeature(CustomOpenTypeFeatures.StylisticSet11, properties.StylisticSet11?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet12 SetFeature(CustomOpenTypeFeatures.StylisticSet12, properties.StylisticSet12?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet13 SetFeature(CustomOpenTypeFeatures.StylisticSet13, properties.StylisticSet13?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet14 SetFeature(CustomOpenTypeFeatures.StylisticSet14, properties.StylisticSet14?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet15 SetFeature(CustomOpenTypeFeatures.StylisticSet15, properties.StylisticSet15?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet16 SetFeature(CustomOpenTypeFeatures.StylisticSet16, properties.StylisticSet16?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet17 SetFeature(CustomOpenTypeFeatures.StylisticSet17, properties.StylisticSet17?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet18 SetFeature(CustomOpenTypeFeatures.StylisticSet18, properties.StylisticSet18?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet19 SetFeature(CustomOpenTypeFeatures.StylisticSet19, properties.StylisticSet19?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //StylisticSet20 SetFeature(CustomOpenTypeFeatures.StylisticSet20, properties.StylisticSet20?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //SlashedZero SetFeature(CustomOpenTypeFeatures.SlashedZero, properties.SlashedZero?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //MathematicalGreek SetFeature(CustomOpenTypeFeatures.MathematicalGreek, properties.MathematicalGreek?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //EastAsian expert forms SetFeature(CustomOpenTypeFeatures.ExpertForms, properties.EastAsianExpertForms?1:0, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Standard swashes SetFeature(CustomOpenTypeFeatures.Swash, properties.StandardSwashes, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Contextual swashes SetFeature(CustomOpenTypeFeatures.ContextualSwash, properties.ContextualSwashes, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Stylistic alternates SetFeature(CustomOpenTypeFeatures.StylisticAlternates, properties.StylisticAlternates, currentStart, currentLength, featureIndex, ref features, ref featureCount); //Annotation alternates. SetFeature(CustomOpenTypeFeatures.AlternateAnnotationForms, properties.AnnotationAlternates, currentStart, currentLength, featureIndex, ref features, ref featureCount); //EastAsian Widths switch (properties.EastAsianWidths) { case FontEastAsianWidths.Normal: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Proportional: SetFeature (CustomOpenTypeFeatures.ProportionalWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); SetFeature (CustomOpenTypeFeatures.ProportionalAlternateWidth,1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Full: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); SetFeature (CustomOpenTypeFeatures.FullWidth, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Half: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); SetFeature (CustomOpenTypeFeatures.HalfWidth, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Third: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); SetFeature (CustomOpenTypeFeatures.ThirdWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.QuarterWidths, featureIndex); break; case FontEastAsianWidths.Quarter: DisableFeature(CustomOpenTypeFeatures.ProportionalWidths, featureIndex); DisableFeature(CustomOpenTypeFeatures.ProportionalAlternateWidth,featureIndex); DisableFeature(CustomOpenTypeFeatures.FullWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.HalfWidth, featureIndex); DisableFeature(CustomOpenTypeFeatures.ThirdWidths, featureIndex); SetFeature (CustomOpenTypeFeatures.QuarterWidths, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } //EastAsian language switch (properties.EastAsianLanguage) { case FontEastAsianLanguage.Normal: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Simplified: SetFeature (CustomOpenTypeFeatures.SimplifiedForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Traditional: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); SetFeature (CustomOpenTypeFeatures.TraditionalForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.TraditionalNames: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); SetFeature (CustomOpenTypeFeatures.TraditionalNameForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.NlcKanji: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); SetFeature (CustomOpenTypeFeatures.NLCKanjiForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.HojoKanji: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); SetFeature (CustomOpenTypeFeatures.HojoKanjiForms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis78: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS78Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis83: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS83Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis90: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS90Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); DisableFeature(CustomOpenTypeFeatures.JIS04Forms, featureIndex); break; case FontEastAsianLanguage.Jis04: DisableFeature(CustomOpenTypeFeatures.SimplifiedForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.TraditionalNameForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.NLCKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.HojoKanjiForms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS78Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS83Forms, featureIndex); DisableFeature(CustomOpenTypeFeatures.JIS90Forms, featureIndex); SetFeature (CustomOpenTypeFeatures.JIS04Forms, 1, currentStart, currentLength, featureIndex, ref features, ref featureCount); break; } currentStart += currentLength; } // Check if all runs have actually the same features. // All feature record should start at 0 and have full length // We skip required features in this check, because they are always the same sameFeatures = true; for(int i = RequiredFeatures.Length; i < featureCount; i++) { if (features[i].StartIndex != 0 || features[i].Length != currentStart ) { sameFeatures = false; break; } } if (sameFeatures) { // Change length for each feature record to 65535, so they do not depend on // particular input length and can be cached for(int i = RequiredFeatures.Length; i < featureCount; i++) { features[i].Length = ushort.MaxValue; } // Now cache features inside each run for(int i = 0; i < lsruns.Length; i++) { lsruns[i].RunProp.TypographyProperties.SetCachedFeatureSet(features, featureCount); } } return new FeatureSet((uint)LanguageTags.Default,features,featureCount); } ////// Critical: This code dereferences a pointer without validation /// [SecurityCritical] private static unsafe void SetFeature( CustomOpenTypeFeatures feature, int parameter, int start, int length, ushort* featureIndex, ref Feature[] features, ref int featureCount ) { if (parameter == 0) { // Nothing to change, just set featureIndex to not enabled featureIndex[(int)feature] = FeatureNotEnabled; return; } ushort index = featureIndex[(int)feature]; Debug.Assert( // if feature is already enabled, index should be valid and feature record should have the same tag index == FeatureNotEnabled || (index < featureCount && features[index].Tag == (uint)CustomOpenTypeFeatureTags[(int)feature]) ); // Check if we can just append to existing feature record if (index != FeatureNotEnabled && features[index].Parameter == parameter ) { features[index].Length += (ushort)length; return; } // // We should add another feature record // if (featureCount == ushort.MaxValue) { throw new OutOfMemoryException(); } // reallocate if it is needed if (featureCount == features.Length) { Feature[] tempFeatures = new Feature[features.Length + 3]; Array.Copy(features, tempFeatures, features.Length); features = tempFeatures; } features[featureCount] = new Feature( (ushort)start, (ushort)length, (uint)CustomOpenTypeFeatureTags[(int)feature], (uint)parameter ); //Set this as current record for the feature featureIndex[(int)feature] = (ushort)featureCount; featureCount++; } ////// This is simplified version of SetFeature, /// assuming that parameter is 0 /// ////// Critical: This code dereferences a pointer without validation /// [SecurityCritical] private static unsafe void DisableFeature( CustomOpenTypeFeatures feature, ushort* featureIndex ) { // Nothing to change, just set featureIndex to not enabled featureIndex[(int)feature] = FeatureNotEnabled; } } } // 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
- PasswordBox.cs
- MediaScriptCommandRoutedEventArgs.cs
- ArraySubsetEnumerator.cs
- TextAdaptor.cs
- DocumentViewerBaseAutomationPeer.cs
- ByteStack.cs
- ConditionCollection.cs
- BitmapFrameEncode.cs
- StoryFragments.cs
- VisualStyleElement.cs
- GenericParameterDataContract.cs
- DispatcherProcessingDisabled.cs
- XmlLinkedNode.cs
- AssociationType.cs
- TimeIntervalCollection.cs
- FrameworkRichTextComposition.cs
- ReachPageContentCollectionSerializer.cs
- Exceptions.cs
- SafeBitVector32.cs
- CryptographicAttribute.cs
- DecoderReplacementFallback.cs
- RuleSettingsCollection.cs
- ZipFileInfo.cs
- BitmapEffectState.cs
- MemberDomainMap.cs
- LockRecursionException.cs
- CodeCommentStatementCollection.cs
- HierarchicalDataBoundControl.cs
- HTMLTagNameToTypeMapper.cs
- WebBrowserUriTypeConverter.cs
- MultiBindingExpression.cs
- URLBuilder.cs
- XPathExpr.cs
- SecurityUtils.cs
- ReadOnlyPropertyMetadata.cs
- PageParser.cs
- PermissionListSet.cs
- SerialStream.cs
- SynthesizerStateChangedEventArgs.cs
- MemberCollection.cs
- SizeAnimationUsingKeyFrames.cs
- EnumMember.cs
- IApplicationTrustManager.cs
- NavigationCommands.cs
- SettingsBindableAttribute.cs
- TrackingProvider.cs
- ZipPackage.cs
- GridProviderWrapper.cs
- DiffuseMaterial.cs
- StyleSelector.cs
- SoapHeaders.cs
- WorkflowMarkupSerializationException.cs
- HMACMD5.cs
- DataFieldEditor.cs
- NumberSubstitution.cs
- DataContractSerializer.cs
- ReliableMessagingVersion.cs
- NumberFormatInfo.cs
- HtmlEncodedRawTextWriter.cs
- TextBoxBaseDesigner.cs
- QualifiedCellIdBoolean.cs
- EventMap.cs
- Stylesheet.cs
- DesignerAttribute.cs
- XmlNode.cs
- CacheOutputQuery.cs
- ImageSourceConverter.cs
- SatelliteContractVersionAttribute.cs
- XsltCompileContext.cs
- ReverseInheritProperty.cs
- EntityDataSourceWizardForm.cs
- ClockGroup.cs
- ToolStripManager.cs
- SubstitutionList.cs
- HitTestParameters.cs
- SendKeys.cs
- TextDecorationUnitValidation.cs
- MimeWriter.cs
- entityreference_tresulttype.cs
- FloaterBaseParagraph.cs
- TableDesigner.cs
- BitmapEffectOutputConnector.cs
- XamlTypeMapper.cs
- Image.cs
- DistributedTransactionPermission.cs
- SelectingProviderEventArgs.cs
- TypeLibConverter.cs
- BasicSecurityProfileVersion.cs
- UnsettableComboBox.cs
- TreeView.cs
- WebPartDescription.cs
- RuntimeConfigLKG.cs
- TabletCollection.cs
- InlinedAggregationOperatorEnumerator.cs
- AttributeTableBuilder.cs
- ObjectQueryExecutionPlan.cs
- QueryPrefixOp.cs
- RuntimeWrappedException.cs
- IChannel.cs
- IISUnsafeMethods.cs