Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / Shaping / PlacementWorkspace.cs / 1 / PlacementWorkspace.cs
//---------------------------------------------------------------------- // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2005 // // File: PlacementWorkspace.cs // // Contents: support for all the shaping engines - all the local variable // for IShaper.GetGlyphPlacements and helpers are wrapped and // all unsafe pointer manipulation is done in this class. // // Created: 08-24-2005 by [....] // //----------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using MS.Internal.FontCache; using MS.Internal.FontFace; using System.Windows.Media; using System.Windows.Media.TextFormatting; using MS.Internal.PresentationCore; using MS.Utility; namespace MS.Internal.Shaping { ////// PlacementWorkspace provides safe interactions with the various buffers /// used by GetGlyphPlacement. /// ////// This struct is created every time a shaping engine's /// GetGlyphPlacement() method is called. /// /// All interaction on the unsafe buffers used for text characters and their related /// buffers (char map, cluster map, etc) done during IShaper.GetGlyphPlacement /// are done through this struct's accessors and methods. /// internal struct PlacementWorkspace { ////// PlacementWorkspace - initializer for GetGlyphPlacements currentRun /// ////// This function is always called from IShaper.GetGlyphPlacements. /// ////// Critical: This code accepts checked pointers and extracts /// unsafe pointers. /// [SecurityCritical] unsafe public PlacementWorkspace ( ShapingOptions shapingFlags, ShaperFontClient shaperFontClient, ShaperBuffers shaperBuffers, CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount, CheckedIntPointer glyphAdvances, CheckedGlyphOffsetPointer glyphOffsets, bool fontHasScriptGposFeatures, TextFlowDirection textFlowDirection) { Invariant.Assert(charCount > 0,"PlacementWorkspace: invalid char count"); // initialize our shaper buffers and set up our local references shaperBuffers.Initialize( (ushort)charCount, (ushort) glyphCount ); _charMap = shaperBuffers.CharMap; _glyphInfoList = shaperBuffers.GlyphInfoList; // keep track of our font client _fontClient = shaperFontClient; // positioning-specific members _pGlyphAdvances = glyphAdvances.Probe(0, glyphCount); _pGlyphOffsets = glyphOffsets.Probe(0, glyphCount); // initialize our various counts _nextGlyphIx = 0; _glyphCount = (ushort)glyphCount; // initialize our local booleans _inited = true; _finished = false; _fontHasScriptGposFeatures = fontHasScriptGposFeatures; _textFlowIsRTL = (textFlowDirection == TextFlowDirection.RTL); // unload the properties to our local representation DecompileShapingProperties( charProperties, charClusterMap, charCount, glyphIndices, glyphProperties, glyphCount ); } public UshortList CharMap { get { return _charMap; } } ////// CurrentGlyph - sets/gets current glyph /// public ushort CurrentGlyph { get { return _glyphInfoList.Glyphs[ _nextGlyphIx ]; } set { _glyphInfoList.Glyphs[ _nextGlyphIx ] = value; } } ////// CurrentGlyphAdvance - sets/gets current glyph advance /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphAdvance { [SecurityCritical] get { return _pGlyphAdvances[ _nextGlyphIx ]; } [SecurityCritical] set { _pGlyphAdvances [ _nextGlyphIx ] = value; } } ////// CurrentGlyphFlags - sets/gets current glyph flags /// public ushort CurrentGlyphFlags { get { return _glyphInfoList.GlyphFlags[ _nextGlyphIx ]; } } ////// CurrentGlyphIx - returns current glyphIx /// public ushort CurrentGlyphIx { get { return _nextGlyphIx; } } ////// CurrentGlyphOffsetDu - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDu { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].du; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].du = value; } } ////// CurrentGlyphOffsetDv - sets/gets current glyph offset.du /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public int CurrentGlyphOffsetDv { [SecurityCritical] get { return _pGlyphOffsets[ _nextGlyphIx ].dv; } [SecurityCritical] set { _pGlyphOffsets [ _nextGlyphIx ].dv = value; } } ////// Critical: This code is unsafe /// [SecurityCritical] unsafe private void DecompileShapingProperties ( CheckedCharacterShapingPropertiesPointer charProperties, CheckedUShortPointer charClusterMap, int charCount, CheckedUShortPointer glyphIndices, CheckedGlyphShapingPropertiesPointer glyphProperties, int glyphCount ) { Debug.Assert(charCount < ushort.MaxValue); Debug.Assert(glyphCount < ushort.MaxValue); ushort* pClusterMap = charClusterMap.Probe(0, charCount); CharacterShapingProperties* pCharProps = charProperties.Probe(0, charCount); ushort* pGlyphs = glyphIndices.Probe(0, glyphCount); GlyphShapingProperties* pGlyphProps = glyphProperties.Probe(0, glyphCount); ushort firstClusterGlyph = 0; ushort firstClusterChar = 0; ushort afterClusterGlyph; ushort afterClusterChar; // Fill glyphs array for(int i= 0; i < _glyphInfoList.Length; i++) { _glyphInfoList.Glyphs[i] = pGlyphs[i]; } // Compile shaping properties. Mapping is local to cluster, so doing every cluster as a whole for(int iChar = 1; iChar <= charCount; iChar++) { if (iChar < charCount && pClusterMap[iChar] == firstClusterGlyph) { //We are still inside same cluster continue; } // New cluster found. Get boundaries afterClusterChar = (ushort)iChar; afterClusterGlyph = (iChar < charCount) ? pClusterMap[iChar] : (ushort)glyphCount; //Cluster map should come valid from shaping engine Debug.Assert(firstClusterGlyph < afterClusterGlyph); for(int iClusterChar = firstClusterChar; iClusterChar < afterClusterChar; iClusterChar++) { byte localMap = pCharProps[iClusterChar].EngineReserved; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(localMap < (afterClusterGlyph - firstClusterGlyph)); CharMap[iClusterChar] = (ushort)(firstClusterGlyph + localMap); } for(int iClusterGlyph = firstClusterGlyph; iClusterGlyph < afterClusterGlyph; iClusterGlyph++) { ushort mappingStorage = pGlyphProps[iClusterGlyph].EngineReserved; int firstChar = mappingStorage & 0xFF; int ligaCount = mappingStorage >> 8; // Clusters should be independent, otherwise they should be merged by shaping engine // Debug.Assert(firstChar < (afterClusterChar - firstClusterChar)); _glyphInfoList.Glyphs[iClusterGlyph] = pGlyphs[iClusterGlyph]; _glyphInfoList.GlyphFlags[iClusterGlyph] = pGlyphProps[iClusterGlyph].GlyphFlags; _glyphInfoList.FirstChars[iClusterGlyph] = (ushort)(firstClusterChar + firstChar); _glyphInfoList.LigatureCounts[iClusterGlyph] = (ushort)ligaCount; } firstClusterChar = afterClusterChar; firstClusterGlyph = afterClusterGlyph; } } public ShaperFontClient FontClient { get { return _fontClient; } } ////// GlyphAdvances - returns glyph advance pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// [SecurityCritical] unsafe public int * GlyphAdvances { [SecurityCritical] get { return _pGlyphAdvances; } } public GlyphInfoList GlyphInfoList { get { return _glyphInfoList; } } ////// GlyphOffsets - returns glyph offsets pointer /// ////// Critical - The method reads into an unvalidated unsafe array /// unsafe public GlyphOffset * GlyphOffsets { [SecurityCritical] get { return _pGlyphOffsets; } } ////// PlacementWorkspace.InitializeGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function populates the glyph run's advance and offset values /// with each glyph's default value (offsets always start zero'ed and /// the advance value comes from the font). /// Shapers that are using GPOS features in the font will call this method /// with scalingFactor set to zero which is interpretted as meaning, /// "no scaling now" (ie, font supports this script, so we're going to let /// the font set the advance). Such shaping engines will apply scaling after /// the after all the features have been applied by calling ScaleGlyphInfoWidths(). /// If a shaping engine has no GPOS features, then the caller (ie, /// GetGlyphsPlacement()) can pass in the appropriate scaling factor. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void InitializeGlyphInfoWidths () { Invariant.Assert (_glyphCount == _glyphInfoList.Length); GlyphTypeface fontFace = FontClient.FontFace; // Init the advance width for all the glyphs. while ( ToNextGlyph() ) { int glyphAdvance = 0; // All diacritics get a zero'ed advance width // All non-diacritics get advance width from the font if ((CurrentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) == 0) { glyphAdvance = (int)Math.Round(fontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); } // set the initial start values CurrentGlyphAdvance = glyphAdvance; CurrentGlyphOffsetDu = 0; CurrentGlyphOffsetDv = 0; } } ////// ToNextGlyph - increments index, returns false if finished /// public bool ToNextGlyph() { if (_inited) { // if this is the first character, don't increment the // index (so we can use this in a while (ToNextGlyph){...} // loop _inited = false; } else if (_nextGlyphIx + 1 < _glyphCount) { ++_nextGlyphIx; } else { _finished = true; } return !_finished; } ////// PlacementWorkspace.Reset - used to re-initial the ToNextGlyph mechanism /// (our iterator function, if you please!) /// public void Reset( ) { _nextGlyphIx = 0; _inited = true; _finished = false; } ////// PlacementWorkspace.ScaleGlyphInfoWidths - helper function for GetGlyphsPlacement. /// ////// This function scales the glyph run's advance and offset values. /// Shapers that are using GPOS features in the font will call this method /// after applying the font's GPOS feaures. /// ////// Critical: This code accesses critical methods. /// [SecurityCritical] public void ScaleGlyphInfoWidths( double scalingFactor ) { // Some fonts have assigned an advance value for the dicritic glyphs. // We have to zero the advance width on any diacritic, and add the value // to the du width. int cumulativeAdvance = 0; // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { ushort currentGlyphFlags = CurrentGlyphFlags; int currentAdvanceWidth = CurrentGlyphAdvance; int currentOffsetDu = CurrentGlyphOffsetDu; // This is used for Arabic/Hebrew fonts that don't have GPOS support... if ( !_fontHasScriptGposFeatures ) { // for fonts without script GPOS support, if this is a suppressed ZWJ/ZWNJ // remove its advance width. if (( currentGlyphFlags & (ushort)GlyphFlags.ClusterStart ) != 0 ) { // for ZWJ/ZWNJ if ( FontClient.IsUnicodeSpaceGlyph(CurrentGlyph) && ( currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth ) != 0) { // treat zwj as zero-width base if (_textFlowIsRTL) { // this adjustment is to "undo" the // adjustment made below for all RTL scripts. currentOffsetDu -= currentAdvanceWidth; } currentAdvanceWidth = 0; currentGlyphFlags = (ushort)GlyphFlags.ClusterStart; } } } if ( (currentGlyphFlags & (ushort)GlyphFlags.ZeroWidth) != 0 ) { // For zero-width glyphs, move any advance width to the offset // du value before clearing the advance width (we want to leave // zero-width glyphs with zero advance). Also keep track of // cumulative advance for adjacent diacritics, adding the // updated advance to the offset du for each diacritic. if (_textFlowIsRTL) { cumulativeAdvance += currentAdvanceWidth; currentOffsetDu -= cumulativeAdvance; } else { currentOffsetDu += cumulativeAdvance; cumulativeAdvance += currentAdvanceWidth; } currentAdvanceWidth = 0; } else { cumulativeAdvance = 0; } // update the current glyph's advance/offset... // Make sure there is no negative advance width after applying positioning. CurrentGlyphAdvance = Math.Max(0, currentAdvanceWidth); CurrentGlyphOffsetDu = currentOffsetDu; } // For RTL scripts, go through all the glyphs and adjust thd du value so that it // takes into account any change in the glyph's advance width due to feature application. // This adjustment is necessary for fixed pitch fonts (like Courier New) which has // a fixed advance width for ALL glyphs (including zero-width diacritics) and this // adjustment is necessary when kerning has been applied. // NOTE: This adjustment is unique to Avalon - the unmanaged code (Uniscribe) doesn't // need this adjustment. if (_textFlowIsRTL) { // go through all the glyphs and adjust any diacritics so that their advance // widths are zero'ed and the advance width is included in the offset du value. Reset(); while ( ToNextGlyph() ) { int originalAdvanceWidth = (int)Math.Round(FontClient.FontFace.GetAdvanceWidthInDesignUnits(CurrentGlyph)); int offsetAdjustment = CurrentGlyphAdvance - originalAdvanceWidth; if (offsetAdjustment != 0) // if du is zero, nothing to do { CurrentGlyphOffsetDu -= offsetAdjustment; } } } // Finally, go through all the glyphs and scale them. if (scalingFactor != 0) { Reset(); while ( ToNextGlyph() ) { CurrentGlyphAdvance = (int)Math.Round((CurrentGlyphAdvance * scalingFactor)); int currentOffsetDu = CurrentGlyphOffsetDu; CurrentGlyphOffsetDu = (int)Math.Round((_textFlowIsRTL ? -currentOffsetDu : currentOffsetDu)*scalingFactor); CurrentGlyphOffsetDv = (int)Math.Round(CurrentGlyphOffsetDv*scalingFactor); } } } private UshortList _charMap; private bool _finished; private ShaperFontClient _fontClient; private ushort _glyphCount; private GlyphInfoList _glyphInfoList; private bool _inited; private ushort _nextGlyphIx; private bool _fontHasScriptGposFeatures; private bool _textFlowIsRTL; [SecurityCritical] private unsafe int* _pGlyphAdvances; [SecurityCritical] private unsafe GlyphOffset * _pGlyphOffsets; // private ShaperBuffers _shaperWorkspace; } } // 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
- RegionInfo.cs
- EventSchemaTraceListener.cs
- BitmapEffect.cs
- DEREncoding.cs
- TextRunProperties.cs
- StorageConditionPropertyMapping.cs
- WaitForChangedResult.cs
- StringValidator.cs
- TailCallAnalyzer.cs
- InfiniteTimeSpanConverter.cs
- TreeSet.cs
- ToolStripGrip.cs
- ToolTipService.cs
- ChildrenQuery.cs
- PermissionSet.cs
- ConstantProjectedSlot.cs
- Vector.cs
- DataControlImageButton.cs
- SessionPageStatePersister.cs
- StorageInfo.cs
- ErrorProvider.cs
- MappingItemCollection.cs
- ViewStateException.cs
- ProfilePropertyNameValidator.cs
- EdmRelationshipRoleAttribute.cs
- Evidence.cs
- GridItemPattern.cs
- Duration.cs
- SystemUnicastIPAddressInformation.cs
- SqlTypeSystemProvider.cs
- NameValueConfigurationElement.cs
- ProviderIncompatibleException.cs
- JsonQNameDataContract.cs
- FontStretch.cs
- MetricEntry.cs
- TableItemStyle.cs
- MetabaseServerConfig.cs
- OleDbException.cs
- NamespaceExpr.cs
- SyndicationSerializer.cs
- GridSplitterAutomationPeer.cs
- StrokeFIndices.cs
- OlePropertyStructs.cs
- IndexerNameAttribute.cs
- MobileDeviceCapabilitiesSectionHandler.cs
- QueuedDeliveryRequirementsMode.cs
- XmlSchemaObjectTable.cs
- CodeSpit.cs
- CacheModeValueSerializer.cs
- ProfileParameter.cs
- SqlUserDefinedTypeAttribute.cs
- Encoder.cs
- JournalEntryListConverter.cs
- FlowPosition.cs
- SingleAnimation.cs
- DurableInstancingOptions.cs
- CaseInsensitiveOrdinalStringComparer.cs
- RelAssertionDirectKeyIdentifierClause.cs
- RijndaelManagedTransform.cs
- EventMappingSettings.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- CodeObject.cs
- UrlAuthorizationModule.cs
- OperatorExpressions.cs
- SimpleRecyclingCache.cs
- ParallelLoopState.cs
- ToolBarButton.cs
- ObjectListTitleAttribute.cs
- Rfc4050KeyFormatter.cs
- HyperLinkDataBindingHandler.cs
- WebConfigurationHostFileChange.cs
- WorkflowInstance.cs
- PropertyBuilder.cs
- ExpressionNode.cs
- HtmlEncodedRawTextWriter.cs
- HttpRequest.cs
- TraceHandler.cs
- CharEnumerator.cs
- InfoCardKeyedHashAlgorithm.cs
- PowerModeChangedEventArgs.cs
- FrameworkName.cs
- CodeNamespaceImport.cs
- SizeAnimationBase.cs
- WebServiceData.cs
- HttpModuleActionCollection.cs
- SyntaxCheck.cs
- FunctionNode.cs
- XmlSchemaValidator.cs
- DeferredSelectedIndexReference.cs
- ReadOnlyCollectionBase.cs
- Monitor.cs
- WebFormsRootDesigner.cs
- Underline.cs
- CodeBlockBuilder.cs
- ValidatorCollection.cs
- MessageDecoder.cs
- BitmapCodecInfoInternal.cs
- CngKeyCreationParameters.cs
- ComEventsHelper.cs
- SecurityTokenException.cs