Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / MS / Internal / Shaping / Positioning.cs / 2 / Positioning.cs
//+------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2002 // // File: Positioning.cs // // Contents: OpentTypeLayout positioning classes // // contact: [....] // // History: 2002-03-23 Created ([....]) // //----------------------------------------------------------------------- using System.Diagnostics; using System.Security; using System.Security.Permissions; using System; using System.IO; namespace MS.Internal.Shaping { // ////// Critical - Everything in this class is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal static class Positioning { public static int DesignToPixels(ushort DesignUnitsPerEm, ushort PixelsPerEm, int Value) { //Result requested in design units if (DesignUnitsPerEm==0) return Value; int rounding = ((int)DesignUnitsPerEm)/2;; if (Value >= 0) { // Half of Units per Em rounding = ((int)DesignUnitsPerEm)/2; } else { // -(Half of Units per Em). +1 to ensure rounding rounding = -((int)DesignUnitsPerEm >> 1)+1; } return (Value*(int)PixelsPerEm + rounding)/DesignUnitsPerEm; } ////// Align to anchors between two glyphs (e.g. mark and base) /// by changing adv.width and offsets for both of them /// /// /// /// /// /// /// /// /// /// /// /// ///public static unsafe void AlignAnchors( IOpenTypeFont Font, FontTable Table, LayoutMetrics Metrics, GlyphInfoList GlyphInfo, int* Advances, LayoutOffset* Offsets, int StaticGlyph, int MobileGlyph, AnchorTable StaticAnchor, AnchorTable MobileAnchor, bool UseAdvances ) { Invariant.Assert(StaticGlyph>=0 && StaticGlyph =0 && MobileGlyph /// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct DeviceTable { private const int offsetStartSize = 0; private const int offsetEndSize = 2; private const int offsetDeltaFormat = 4; private const int offsetDeltaValueArray = 6; private const int sizeDeltaValue = 2; private ushort StartSize(FontTable Table) { return Table.GetUShort(offset + offsetStartSize); } private ushort EndSize(FontTable Table) { return Table.GetUShort(offset + offsetEndSize); } private ushort DeltaFormat(FontTable Table) { return Table.GetUShort(offset + offsetDeltaFormat); } private ushort DeltaValue(FontTable Table, ushort Index) { return Table.GetUShort( offset + offsetDeltaValueArray + Index * sizeDeltaValue); } public int Value(FontTable Table, ushort PixelsPerEm) { if (IsNull()) return 0; ushort startSize = StartSize(Table); ushort endSize = EndSize(Table); if (PixelsPerEm endSize) return 0; ushort sizeIndex = (ushort)(PixelsPerEm-startSize); ushort valueIndex, shiftUp, shiftDown; switch (DeltaFormat(Table)) { case 1: valueIndex = (ushort)(sizeIndex>>3); shiftUp = (ushort)(16 + 2*(sizeIndex&0x0007)); shiftDown = 30; break; case 2: valueIndex = (ushort)(sizeIndex>>2); shiftUp = (ushort)(16 + 4*(sizeIndex&0x0003)); shiftDown = 28; break; case 3: valueIndex = (ushort)(sizeIndex>>1); shiftUp = (ushort)(16 + 8*(sizeIndex&0x0001)); shiftDown = 24; break; default: return 0; //Unknown format } int delta = DeltaValue(Table,valueIndex); delta <<= shiftUp; //clear leading bits delta >>= shiftDown; //extend sign and clear trailing bits return delta; } public DeviceTable(int Offset) { offset = Offset; } bool IsNull() { return (offset==0); } private int offset; } /// /// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct ValueRecordTable { const ushort XPlacmentFlag = 0x0001; const ushort YPlacmentFlag = 0x0002; const ushort XAdvanceFlag = 0x0004; const ushort YAdvanceFlag = 0x0008; const ushort XPlacementDeviceFlag = 0x0010; const ushort YPlacementDeviceFlag = 0x0020; const ushort XAdvanceDeviceFlag = 0x0040; const ushort YAdvanceDeviceFlag = 0x0080; private static ushort[] BitCount = new ushort[16] { 0, 2, 2, 4, 2, 4, 4, 6, 2, 4, 4, 6, 4, 6, 6, 8 }; public static ushort Size(ushort Format) { return (ushort)(BitCount[Format&0x000F]+BitCount[(Format>>4)&0x000F]); } public void AdjustPos( FontTable Table, LayoutMetrics Metrics, ref LayoutOffset GlyphOffset, ref int GlyphAdvance ) { int curOffset=offset; if ((format&XPlacmentFlag)!=0) { GlyphOffset.dx += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth, Table.GetShort(curOffset)); curOffset+=2; } if ((format&YPlacmentFlag)!=0) { GlyphOffset.dy += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight, Table.GetShort(curOffset)); curOffset+=2; } if ((format&XAdvanceFlag)!=0) { GlyphAdvance += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth, Table.GetShort(curOffset)); curOffset+=2; } if ((format&YAdvanceFlag)!=0) { GlyphAdvance += Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight, Table.GetShort(curOffset)); curOffset+=2; } if ((format&XPlacementDeviceFlag)!=0) { int deviceTableOffset = Table.GetOffset(curOffset); if (deviceTableOffset != FontTable.NullOffset) { DeviceTable deviceTable = new DeviceTable(baseTableOffset+deviceTableOffset); GlyphOffset.dx += deviceTable.Value(Table,Metrics.PixelsEmWidth); } curOffset+=2; } if ((format&YPlacementDeviceFlag)!=0) { int deviceTableOffset = Table.GetOffset(curOffset); if (deviceTableOffset != FontTable.NullOffset) { DeviceTable deviceTable = new DeviceTable(baseTableOffset+deviceTableOffset); GlyphOffset.dy += deviceTable.Value(Table,Metrics.PixelsEmHeight); } curOffset+=2; } if ((format&XAdvanceDeviceFlag)!=0) { if (Metrics.Direction==TextFlowDirection.LTR || Metrics.Direction==TextFlowDirection.RTL) { int deviceTableOffset = Table.GetOffset(curOffset); if (deviceTableOffset != FontTable.NullOffset) { DeviceTable deviceTable = new DeviceTable(baseTableOffset+deviceTableOffset); GlyphAdvance += deviceTable.Value(Table,Metrics.PixelsEmWidth); } } curOffset+=2; } if ((format&YAdvanceDeviceFlag)!=0) { if (Metrics.Direction==TextFlowDirection.TTB || Metrics.Direction==TextFlowDirection.BTT) { int deviceTableOffset = Table.GetOffset(curOffset); if (deviceTableOffset != FontTable.NullOffset) { DeviceTable deviceTable = new DeviceTable(baseTableOffset+deviceTableOffset); GlyphAdvance += deviceTable.Value(Table,Metrics.PixelsEmHeight); } } curOffset+=2; } } public ValueRecordTable(int Offset, int BaseTableOffset, ushort Format) { offset = Offset; baseTableOffset = BaseTableOffset; format=Format; } private ushort format; private int baseTableOffset; private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct AnchorTable { private const int offsetFormat = 0; private const int offsetXCoordinate = 2; private const int offsetYCoordinate = 4; private const int offsetFormat2AnchorPoint = 6; private const int offsetFormat3XDeviceTable = 6; private const int offsetFormat3YDeviceTable = 8; private short XCoordinate(FontTable Table) { return Table.GetShort(offset + offsetXCoordinate); } private short YCoordinate(FontTable Table) { return Table.GetShort(offset + offsetYCoordinate); } private ushort Format2AnchorPoint(FontTable Table) { Invariant.Assert(format==2); return Table.GetUShort(offset + offsetFormat2AnchorPoint); } private DeviceTable Format3XDeviceTable(FontTable Table) { Invariant.Assert(format==3); int DeviceOffset = Table.GetUShort(offset + offsetFormat3XDeviceTable); if (DeviceOffset!=0) { return new DeviceTable(offset + DeviceOffset); } else { return new DeviceTable(0); } } private DeviceTable Format3YDeviceTable(FontTable Table) { Invariant.Assert(format==3); int DeviceOffset = Table.GetUShort(offset + offsetFormat3YDeviceTable); if (DeviceOffset!=0) { return new DeviceTable(offset + DeviceOffset); } else { return new DeviceTable(0); } } public bool NeedContourPoint(FontTable Table) { return (format==2); } public ushort ContourPointIndex(FontTable Table) { Invariant.Assert(NeedContourPoint(Table)); return Format2AnchorPoint(Table); } public LayoutOffset AnchorCoordinates( FontTable Table, LayoutMetrics Metrics, LayoutOffset ContourPoint ) { LayoutOffset Point = new LayoutOffset(); switch (format) { case 1: //Simple coordinates Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table)); Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table)); break; case 2: //Coordinates + anchor point if (ContourPoint.dx==int.MinValue) { Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table)); Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table)); } else { Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,ContourPoint.dx); Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,ContourPoint.dy); } break; case 3: //Coordinates + Device table Point.dx = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmWidth,XCoordinate(Table))+ Format3XDeviceTable(Table).Value(Table,Metrics.PixelsEmWidth); Point.dy = Positioning.DesignToPixels(Metrics.DesignEmHeight,Metrics.PixelsEmHeight,YCoordinate(Table))+ Format3YDeviceTable(Table).Value(Table,Metrics.PixelsEmHeight); break; default: //Unknown format Point.dx = 0; Point.dx = 0; break; } return Point; } public AnchorTable(FontTable Table, int Offset) { offset = Offset; if (offset != 0) format = Table.GetUShort(offset + offsetFormat); else format = 0; } public bool IsNull() { return (offset==0); } private int offset; private ushort format; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct SinglePositioningSubtable { private const int offsetFormat = 0; private const int offsetCoverage = 2; private const int offsetValueFormat = 4; private const int offsetFormat1Value = 6; private const int offsetFormat2ValueCount = 6; private const int offsetFormat2ValueArray = 8; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable Coverage(FontTable Table) { return new CoverageTable(offset + Table.GetOffset(offset + offsetCoverage)); } private ushort ValueFormat(FontTable Table) { return Table.GetUShort(offset + offsetValueFormat); } private ValueRecordTable Format1ValueRecord(FontTable Table) { Invariant.Assert(Format(Table)==1); return new ValueRecordTable(offset + offsetFormat1Value, offset, ValueFormat(Table)); } private ValueRecordTable Format2ValueRecord(FontTable Table, ushort Index) { Invariant.Assert(Format(Table)==2); return new ValueRecordTable(offset + offsetFormat2ValueArray + Index * ValueRecordTable.Size(ValueFormat(Table)), offset, ValueFormat(Table)); } public unsafe bool Apply( FontTable Table, LayoutMetrics Metrics, // LayoutMetrics GlyphInfoList GlyphInfo, // List of GlyphInfo structs int* Advances, // Glyph adv.widths LayoutOffset* Offsets, // Glyph offsets int FirstGlyph, // where to apply lookup int AfterLastGlyph, // how long is a context we can use out int NextGlyph // Next glyph to process ) { Invariant.Assert(FirstGlyph>=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph + 1; //In case we don't match; int glyphCount=GlyphInfo.Length; ushort glyphId = GlyphInfo.Glyphs[FirstGlyph]; int coverageIndex = Coverage(Table).GetGlyphIndex(Table,glyphId); if (coverageIndex == -1) return false; ValueRecordTable valueRecord; switch (Format(Table)) { case 1: valueRecord = Format1ValueRecord(Table); break; case 2: valueRecord = Format2ValueRecord(Table,(ushort)coverageIndex); break; default: return false; } valueRecord.AdjustPos(Table, Metrics, ref Offsets[FirstGlyph], ref Advances[FirstGlyph]); return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { return Coverage(table).IsAnyGlyphCovered(table, glyphBits, minGlyphId, maxGlyphId ); } public CoverageTable GetPrimaryCoverage(FontTable table) { return Coverage(table); } public SinglePositioningSubtable(int Offset) { offset = Offset; } private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct PairPositioningSubtable { private const int offsetFormat = 0; private const int offsetCoverage = 2; private const int offsetValueFormat1 = 4; private const int offsetValueFormat2 = 6; private const int offsetFormat1PairSetCount = 8; private const int offsetFormat1PairSetArray = 10; private const int sizeFormat1PairSetOffset = 2; private const int offsetFormat2ClassDef1 = 8; private const int offsetFormat2ClassDef2 = 10; private const int offsetFormat2Class1Count = 12; private const int offsetFormat2Class2Count = 14; private const int offsetFormat2ValueRecordArray = 16; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable Coverage(FontTable Table) { return new CoverageTable(offset + Table.GetOffset(offset + offsetCoverage)); } private ushort FirstValueFormat(FontTable Table) { return Table.GetUShort(offset + offsetValueFormat1); } private ushort SecondValueFormat(FontTable Table) { return Table.GetUShort(offset + offsetValueFormat2); } // Not used. This value should be equal to glyph count in coverage table // Keeping it for future reference //private ushort Format1PairSetCount(FontTable Table) //{ // Debug.Assert(Format(Table)==1); // return Table.GetUShort(offset + offsetFormat1PairSetCount); //} private PairSetTable Format1PairSet(FontTable Table, ushort Index) { Invariant.Assert(Format(Table)==1); return new PairSetTable(offset + Table.GetUShort(offset + offsetFormat1PairSetArray + Index * sizeFormat1PairSetOffset), FirstValueFormat(Table), SecondValueFormat(Table)); } private ClassDefTable Format2Class1Table(FontTable Table) { Invariant.Assert(Format(Table)==2); return new ClassDefTable(offset+Table.GetUShort(offset + offsetFormat2ClassDef1)); } private ClassDefTable Format2Class2Table(FontTable Table) { Invariant.Assert(Format(Table)==2); return new ClassDefTable(offset+Table.GetUShort(offset + offsetFormat2ClassDef2)); } private ushort Format2Class1Count(FontTable Table) { Invariant.Assert(Format(Table)==2); return Table.GetUShort(offset + offsetFormat2Class1Count); } private ushort Format2Class2Count(FontTable Table) { Invariant.Assert(Format(Table)==2); return Table.GetUShort(offset + offsetFormat2Class2Count); } private ValueRecordTable Format2FirstValueRecord(FontTable Table, ushort Class2Count, ushort Class1Index, ushort Class2Index ) { Invariant.Assert(Format(Table)==2); ushort firstValueFormat = FirstValueFormat(Table), secondValueFormat = SecondValueFormat(Table); int recordSize = ValueRecordTable.Size(firstValueFormat) + ValueRecordTable.Size(secondValueFormat); return new ValueRecordTable(offset + offsetFormat2ValueRecordArray + (Class1Index*Class2Count+Class2Index)*recordSize, offset, firstValueFormat); } private ValueRecordTable Format2SecondValueRecord(FontTable Table, ushort Class2Count, ushort Class1Index, ushort Class2Index ) { Invariant.Assert(Format(Table)==2); ushort firstValueFormat = FirstValueFormat(Table), secondValueFormat = SecondValueFormat(Table); int secondRecordOffset = ValueRecordTable.Size(firstValueFormat), recordSize = secondRecordOffset + ValueRecordTable.Size(secondValueFormat); return new ValueRecordTable(offset + offsetFormat2ValueRecordArray + (Class1Index*Class2Count+Class2Index)*recordSize + secondRecordOffset, offset, secondValueFormat ); } #region Pair positioing child structures ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] private struct PairSetTable { private const int offsetPairValueCount = 0; private const int offsetPairValueArray = 2; private const int offsetPairValueSecondGlyph = 0; private const int offsetPairValueValue1 = 2; public ushort PairValueCount(FontTable Table) { return Table.GetUShort(offset + offsetPairValueCount); } public ushort PairValueGlyph(FontTable Table, ushort Index) { return Table.GetUShort( offset + offsetPairValueArray + Index*pairValueRecordSize + offsetPairValueSecondGlyph); } public ValueRecordTable FirstValueRecord(FontTable Table, ushort Index, ushort Format) { return new ValueRecordTable(offset + offsetPairValueArray + Index*pairValueRecordSize + offsetPairValueValue1, offset, Format); } public ValueRecordTable SecondValueRecord(FontTable Table, ushort Index, ushort Format) { return new ValueRecordTable(offset + offsetPairValueArray + Index*pairValueRecordSize + secondValueRecordOffset, offset, Format); } //Search for second glyph in pair. returns -1 if not found public int FindPairValue(FontTable Table, ushort Glyph) { //PERF: binary search ushort pairCount = PairValueCount(Table); for(ushort i=0; i=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not int glyphCount=GlyphInfo.Length; ushort firstGlyphId = GlyphInfo.Glyphs[FirstGlyph]; int secondGlyph = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo,FirstGlyph+1,LookupFlags,LayoutEngine.LookForward); if (secondGlyph>=AfterLastGlyph) return false; ushort secondGlyphId = GlyphInfo.Glyphs[secondGlyph]; ValueRecordTable firstValueRecord, secondValueRecord; switch (Format(Table)) { case 1: { int coverageIndex = Coverage(Table).GetGlyphIndex(Table,firstGlyphId); if (coverageIndex==-1) return false; PairSetTable pairSet = Format1PairSet(Table,(ushort)coverageIndex); int pairValueIndex = pairSet.FindPairValue(Table, secondGlyphId); if (pairValueIndex == -1) return false; firstValueRecord = pairSet.FirstValueRecord(Table,(ushort)pairValueIndex,FirstValueFormat(Table)); secondValueRecord = pairSet.SecondValueRecord(Table,(ushort)pairValueIndex,SecondValueFormat(Table)); break; } case 2: { int coverageIndex = Coverage(Table).GetGlyphIndex(Table,firstGlyphId); if (coverageIndex == -1) return false; ushort firstClassIndex = Format2Class1Table(Table).GetClass(Table,firstGlyphId); if (firstClassIndex >= Format2Class1Count(Table)) return false; //this is invalid font; ushort secondClassIndex = Format2Class2Table(Table).GetClass(Table,secondGlyphId); if (secondClassIndex >= Format2Class2Count(Table)) return false; //this is invalid font; ushort class2Count = Format2Class2Count(Table); firstValueRecord = Format2FirstValueRecord(Table, class2Count, firstClassIndex, secondClassIndex ); secondValueRecord = Format2SecondValueRecord(Table, class2Count, firstClassIndex, secondClassIndex ); break; } default: return false; } //Now adjust positions firstValueRecord.AdjustPos (Table, Metrics, ref Offsets[FirstGlyph], ref Advances[FirstGlyph]); secondValueRecord.AdjustPos(Table, Metrics, ref Offsets[secondGlyph], ref Advances[secondGlyph]); return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { return Coverage(table).IsAnyGlyphCovered(table, glyphBits, minGlyphId, maxGlyphId ); // } public CoverageTable GetPrimaryCoverage(FontTable table) { return Coverage(table); } public PairPositioningSubtable(int Offset) { offset = Offset; } private int offset; } /// /// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct MarkArray { private const int offsetClassArray = 2; private const int sizeClassRecord = 4; private const int offsetClassRecordClass = 0; private const int offsetClassRecordAnchor = 2; public ushort Class(FontTable Table, ushort Index) { return Table.GetUShort(offset + offsetClassArray + Index*sizeClassRecord + offsetClassRecordClass); } public AnchorTable MarkAnchor(FontTable Table, ushort Index) { int anchorTableOffset = Table.GetUShort(offset + offsetClassArray + Index*sizeClassRecord+ offsetClassRecordAnchor ); if (anchorTableOffset == 0) { return new AnchorTable(Table, 0); } return new AnchorTable(Table,offset + anchorTableOffset); } public MarkArray(int Offset) { offset = Offset; } private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct MarkToBasePositioningSubtable { private const int offsetFormat = 0; private const int offsetCoverage = 2; private const int offsetBaseCoverage = 4; private const int offsetClassCount = 6; private const int offsetMarkArray = 8; private const int offsetBaseArray = 10; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable MarkCoverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage)); } private CoverageTable BaseCoverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetBaseCoverage)); } private ushort ClassCount(FontTable Table) { return Table.GetUShort(offset + offsetClassCount); } private MarkArray Marks(FontTable Table) { return new MarkArray(offset + Table.GetUShort(offset + offsetMarkArray)); } private BaseArray Bases(FontTable Table) { return new BaseArray(offset + Table.GetUShort(offset + offsetBaseArray)); } #region Mark to base positioning child structures ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] private struct BaseArray { private const int offsetAnchorArray = 2; private const int sizeAnchorOffset = 2; public AnchorTable BaseAnchor(FontTable Table, ushort BaseIndex, ushort MarkClassCount, ushort MarkClass) { int anchorTableOffset = Table.GetUShort(offset + offsetAnchorArray + (BaseIndex*MarkClassCount + MarkClass) * sizeAnchorOffset ); if (anchorTableOffset == 0) { return new AnchorTable(Table, 0); } return new AnchorTable(Table, offset + anchorTableOffset); } public BaseArray(int Offset) { offset = Offset; } private int offset; } #endregion public unsafe bool Apply( IOpenTypeFont Font, FontTable Table, LayoutMetrics Metrics, // LayoutMetrics GlyphInfoList GlyphInfo, // List of GlyphInfo structs ushort LookupFlags, // Lookup flags for glyph lookups int* Advances, // Glyph adv.widths LayoutOffset* Offsets, // Glyph offsets int FirstGlyph, // where to apply lookup int AfterLastGlyph, // how long is a context we can use out int NextGlyph // Next glyph to process ) { Invariant.Assert(FirstGlyph>=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not if (Format(Table) != 1) return false; //unknown format int glyphCount=GlyphInfo.Length; int markGlyph=FirstGlyph; //Lookup works with marks only if ((GlyphInfo.GlyphFlags[markGlyph]&(ushort)GlyphFlags.GlyphTypeMask)!=(ushort)GlyphFlags.Mark) return false; int markCoverageIndex = MarkCoverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[markGlyph]); if (markCoverageIndex==-1) return false; //Find preceeding base (precisely, not mark ). Uses special lookup flag int baseGlyph = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, FirstGlyph - 1, LayoutEngine.LookupFlagFindBase, LayoutEngine.LookBackward); if (baseGlyph<0) return false; int baseCoverageIndex = BaseCoverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[baseGlyph]); if (baseCoverageIndex == -1) return false; ushort classCount = ClassCount(Table); MarkArray marks = Marks(Table); ushort markClass = marks.Class(Table,(ushort)markCoverageIndex); if (markClass>=classCount) return false; //Invalid mark class AnchorTable markAnchor = marks.MarkAnchor(Table,(ushort)markCoverageIndex); if (markAnchor.IsNull()) { return false; } AnchorTable baseAnchor = Bases(Table).BaseAnchor(Table,(ushort)baseCoverageIndex,classCount,markClass); if (baseAnchor.IsNull()) { return false; } Positioning.AlignAnchors(Font,Table,Metrics,GlyphInfo,Advances,Offsets, baseGlyph,markGlyph,baseAnchor,markAnchor,false); return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { // return false; } public CoverageTable GetPrimaryCoverage(FontTable table) { return MarkCoverage(table); } public MarkToBasePositioningSubtable(int Offset) { offset = Offset; } private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct MarkToMarkPositioningSubtable { private const int offsetFormat = 0; private const int offsetCoverage = 2; private const int offsetMark2Coverage = 4; private const int offsetClassCount = 6; private const int offsetMark1Array = 8; private const int offsetMark2Array = 10; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable Mark1Coverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage)); } private CoverageTable Mark2Coverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetMark2Coverage)); } private ushort Mark1ClassCount(FontTable Table) { return Table.GetUShort(offset + offsetClassCount); } private MarkArray Mark1Array(FontTable Table) { return new MarkArray(offset + Table.GetUShort(offset + offsetMark1Array)); } private Mark2Array Marks2(FontTable Table) { return new Mark2Array(offset + Table.GetUShort(offset + offsetMark2Array)); } #region Mark to mark positioning child structures ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] private struct Mark2Array { private const int offsetCount = 0; private const int offsetAnchors = 2; private const int sizeAnchorOffset = 2; public AnchorTable Anchor(FontTable Table, ushort Mark2Index, ushort Mark1ClassCount, ushort Mark1Class) { int anchorTableOffset = Table.GetUShort(offset + offsetAnchors + (Mark2Index*Mark1ClassCount+Mark1Class) * sizeAnchorOffset ); if (anchorTableOffset == 0) { return new AnchorTable(Table, 0); } return new AnchorTable(Table, offset + anchorTableOffset); } #endregion public Mark2Array(int Offset) { offset = Offset; } private int offset; } public unsafe bool Apply( IOpenTypeFont Font, FontTable Table, LayoutMetrics Metrics, // LayoutMetrics GlyphInfoList GlyphInfo, // List of GlyphInfo structs ushort LookupFlags, // Lookup flags for glyph lookups int* Advances, // Glyph adv.widths LayoutOffset* Offsets, // Glyph offsets int FirstGlyph, // where to apply lookup int AfterLastGlyph, // how long is a context we can use out int NextGlyph // Next glyph to process ) { Invariant.Assert(FirstGlyph>=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not if (Format(Table) != 1) return false; //unknown format int glyphCount=GlyphInfo.Length; int mark1Glyph=FirstGlyph; //Lookup works with marks only if ((GlyphInfo.GlyphFlags[mark1Glyph]&(ushort)GlyphFlags.GlyphTypeMask)!=(ushort)GlyphFlags.Mark) return false; int mark1CoverageIndex = Mark1Coverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[mark1Glyph]); if (mark1CoverageIndex==-1) return false; //Find preceeding mark according mark from specified class int mark2Glyph = LayoutEngine.GetNextGlyphInLookup(Font, GlyphInfo, FirstGlyph-1, (ushort)(LookupFlags & 0xFF00), //Clear Ignore... flags LayoutEngine.LookBackward); if (mark2Glyph<0) return false; int mark2CoverageIndex = Mark2Coverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[mark2Glyph]); if (mark2CoverageIndex==-1) return false; ushort classCount = Mark1ClassCount(Table); MarkArray mark1Array = Mark1Array(Table); ushort mark1Class = mark1Array.Class(Table,(ushort)mark1CoverageIndex); if (mark1Class>=classCount) return false; //Invalid mark class AnchorTable mark1Anchor = mark1Array.MarkAnchor(Table,(ushort)mark1CoverageIndex); if (mark1Anchor.IsNull()) { return false; } AnchorTable mark2Anchor = Marks2(Table).Anchor(Table,(ushort)mark2CoverageIndex,classCount,mark1Class); if (mark2Anchor.IsNull()) { return false; } Positioning.AlignAnchors(Font,Table,Metrics,GlyphInfo,Advances,Offsets, mark2Glyph,mark1Glyph,mark2Anchor,mark1Anchor,false); return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { // return false; } public CoverageTable GetPrimaryCoverage(FontTable table) { return Mark1Coverage(table); } public MarkToMarkPositioningSubtable(int Offset) { offset = Offset; } private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] struct CursivePositioningSubtable { private const ushort offsetFormat = 0; private const ushort offsetCoverage = 2; private const ushort offsetEntryExitCount = 4; private const ushort offsetEntryExitArray = 6; private const ushort sizeEntryExitRecord = 4; private const ushort offsetEntryAnchor = 0; private const ushort offsetExitAnchor = 2; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable Coverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetCoverage)); } // Not used. This value should be equal to glyph count in Coverage. // Keeping it for future reference //private ushort EntryExitCount(FontTable Table) //{ // return Table.GetUShort(offsetEntryExitCount); //} private AnchorTable EntryAnchor(FontTable Table, int Index) { int anchorTableOffset = Table.GetUShort(offset + offsetEntryExitArray + sizeEntryExitRecord * Index + offsetEntryAnchor); if (anchorTableOffset == 0) return new AnchorTable(Table,0); return new AnchorTable(Table, offset + anchorTableOffset); } private AnchorTable ExitAnchor(FontTable Table, int Index) { int anchorTableOffset = Table.GetUShort(offset + offsetEntryExitArray + sizeEntryExitRecord * Index + offsetExitAnchor); if (anchorTableOffset == 0) return new AnchorTable(Table,0); return new AnchorTable(Table, offset + anchorTableOffset); } public unsafe bool Apply( IOpenTypeFont Font, FontTable Table, LayoutMetrics Metrics, // LayoutMetrics GlyphInfoList GlyphInfo, // List of GlyphInfo structs ushort LookupFlags, // Lookup flags for glyph lookups int* Advances, // Glyph adv.widths LayoutOffset* Offsets, // Glyph offsets int FirstGlyph, // where to apply lookup int AfterLastGlyph, // how long is a context we can use out int NextGlyph // Next glyph to process ) { Invariant.Assert(FirstGlyph>=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph+1; if (Format(Table) != 1) return false; // Unknown format bool RTL = (LookupFlags & LayoutEngine.LookupFlagRightToLeft) != 0; ushort cursiveBit = (ushort)GlyphFlags.CursiveConnected; // int glyphIndex, prevGlyphIndex, coverageIndex, prevCoverageIndex; glyphIndex = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo, FirstGlyph,LookupFlags, LayoutEngine.LookForward ); //clear "CursiveConected" bit, //we will set it only if there is a connection to previous glyph if (RTL) { GlyphInfo.GlyphFlags[glyphIndex] &= (ushort)~cursiveBit; } if ( glyphIndex >= AfterLastGlyph ) { return false; } prevGlyphIndex = LayoutEngine.GetNextGlyphInLookup(Font,GlyphInfo, FirstGlyph-1,LookupFlags, LayoutEngine.LookBackward ); if ( prevGlyphIndex < 0 ) { return false; } CoverageTable coverage = Coverage(Table); coverageIndex = coverage.GetGlyphIndex(Table,GlyphInfo.Glyphs[glyphIndex]); if (coverageIndex == -1) { return false; } prevCoverageIndex = coverage. GetGlyphIndex(Table,GlyphInfo.Glyphs[prevGlyphIndex]); if (prevCoverageIndex == -1) { return false; } AnchorTable prevExitAnchor, entryAnchor; prevExitAnchor = ExitAnchor(Table, prevCoverageIndex); if (prevExitAnchor.IsNull()) { return false; } entryAnchor = EntryAnchor(Table,coverageIndex); if (entryAnchor.IsNull()) { return false; } Positioning.AlignAnchors(Font, Table, Metrics, GlyphInfo, Advances, Offsets, prevGlyphIndex, glyphIndex, prevExitAnchor, entryAnchor, true); if (RTL) { UshortList glyphFlags = GlyphInfo.GlyphFlags; int index; //set "cursive" bit for everything up to prevGlyphIndex for(index = glyphIndex; index>prevGlyphIndex; index--) { glyphFlags[index] |= cursiveBit; } //fix cursive dependencies int yCorrection = Offsets[glyphIndex].dy; for(index = glyphIndex; (glyphFlags[index] & cursiveBit) != 0 ; index-- ) { Offsets[index].dy -= yCorrection; } Invariant.Assert(glyphIndex>=0); //First glyph should not have bit set Offsets[index].dy -= yCorrection; } return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { // return true; } public CoverageTable GetPrimaryCoverage(FontTable table) { return Coverage(table); } public CursivePositioningSubtable(int Offset) { offset = Offset; } private int offset; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct LigatureAttachTable { private const int offsetAnchorArray = 2; private const int sizeAnchorOffset = 2; public AnchorTable LigatureAnchor(FontTable Table, ushort Component, ushort MarkClass) { int anchorTableOffset = Table.GetUShort(offset + offsetAnchorArray + (Component*classCount + MarkClass) * sizeAnchorOffset); if (anchorTableOffset == 0) { return new AnchorTable(Table, 0); } return new AnchorTable(Table, offset + anchorTableOffset); } public LigatureAttachTable(int Offset,ushort ClassCount) { offset = Offset; classCount = ClassCount; } private int offset; private int classCount; } ////// Critical - Everything in this struct is considered critical /// because they either operate on raw font table bits or unsafe pointers. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal struct MarkToLigaturePositioningSubtable { private const int offsetFormat = 0; private const int offsetMarkCoverage = 2; private const int offsetLigatureCoverage = 4; private const int offsetClassCount = 6; private const int offsetMarkArray = 8; private const int offsetLigatureArray = 10; private const int offsetLigatureAttachArray = 2; private const int sizeOffset = 2; private ushort Format(FontTable Table) { return Table.GetUShort(offset + offsetFormat); } private CoverageTable MarkCoverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetMarkCoverage)); } private CoverageTable LigatureCoverage(FontTable Table) { return new CoverageTable(offset + Table.GetUShort(offset + offsetLigatureCoverage)); } private ushort ClassCount(FontTable Table) { return Table.GetUShort(offset + offsetClassCount); } private MarkArray Marks(FontTable Table) { return new MarkArray(offset + Table.GetUShort(offset + offsetMarkArray)); } private LigatureAttachTable Ligatures(FontTable Table, int Index, ushort ClassCount) { int offsetLigatureArrayTable = offset + Table.GetUShort(offset + offsetLigatureArray); return new LigatureAttachTable(offsetLigatureArrayTable + Table.GetUShort(offsetLigatureArrayTable + offsetLigatureAttachArray + Index * sizeOffset), ClassCount ); } // Find base ligature and component corresponding to the mark private unsafe void FindBaseLigature ( int CharCount, UshortList Charmap, GlyphInfoList GlyphInfo, int markGlyph, out ushort component, out int ligatureGlyph ) { int ligatureChar = 0; ligatureGlyph = -1; component = 0; bool FoundBase = false; for (int ch = GlyphInfo.FirstChars[markGlyph]; ch >= 0 && !FoundBase; ch--) { ushort glyph = Charmap[ch]; if ((GlyphInfo.GlyphFlags[glyph] & (ushort)GlyphFlags.GlyphTypeMask) != (ushort)GlyphFlags.Mark) { ligatureChar = ch; ligatureGlyph = glyph; FoundBase = true; } } if (!FoundBase) return; ushort comp = 0; for(ushort ch = GlyphInfo.FirstChars[ligatureGlyph]; ch=0); Invariant.Assert(AfterLastGlyph<=GlyphInfo.Length); NextGlyph = FirstGlyph+1; //Always move to the next glyph, whether matched or not if (Format(Table) != 1) return false; //unknown format int glyphCount=GlyphInfo.Length; int markGlyph=FirstGlyph; //Lookup works with marks only if ((GlyphInfo.GlyphFlags[markGlyph]&(ushort)GlyphFlags.GlyphTypeMask)!=(ushort)GlyphFlags.Mark) return false; int markCoverageIndex = MarkCoverage(Table).GetGlyphIndex(Table,GlyphInfo.Glyphs[markGlyph]); if (markCoverageIndex==-1) return false; int baseGlyph; ushort component; FindBaseLigature(CharCount, Charmap,GlyphInfo,markGlyph, out component, out baseGlyph); if (baseGlyph<0) return false; int baseCoverageIndex = LigatureCoverage(Table). GetGlyphIndex(Table,GlyphInfo.Glyphs[baseGlyph]); if (baseCoverageIndex == -1) return false; ushort classCount = ClassCount(Table); MarkArray marks = Marks(Table); ushort markClass = marks.Class(Table,(ushort)markCoverageIndex); if (markClass>=classCount) return false; //Invalid mark class AnchorTable baseAnchor = Ligatures(Table,baseCoverageIndex, classCount). LigatureAnchor(Table,component,markClass); if (baseAnchor.IsNull()) { return false; } AnchorTable markAnchor = marks.MarkAnchor(Table,(ushort)markCoverageIndex); if (markAnchor.IsNull()) { return false; } Positioning.AlignAnchors(Font,Table,Metrics,GlyphInfo,Advances,Offsets, baseGlyph,markGlyph,baseAnchor,markAnchor,false); return true; } public bool IsLookupCovered( FontTable table, uint[] glyphBits, ushort minGlyphId, ushort maxGlyphId) { // return false; } public CoverageTable GetPrimaryCoverage(FontTable table) { return MarkCoverage(table); } public MarkToLigaturePositioningSubtable(int Offset) { offset = Offset; } private int offset; } } // 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
- SystemThemeKey.cs
- ToolTip.cs
- SmtpNtlmAuthenticationModule.cs
- DataSourceProvider.cs
- SaveFileDialog.cs
- DataGridViewSortCompareEventArgs.cs
- CodeObjectCreateExpression.cs
- HtmlDocument.cs
- OdbcParameterCollection.cs
- DSASignatureFormatter.cs
- SoapRpcServiceAttribute.cs
- WorkflowRuntimeSection.cs
- HttpCacheParams.cs
- SqlRowUpdatingEvent.cs
- DtrList.cs
- ServiceReflector.cs
- ListSortDescription.cs
- GeneralTransform3DGroup.cs
- CustomCategoryAttribute.cs
- Condition.cs
- SocketElement.cs
- WmlObjectListAdapter.cs
- BinaryParser.cs
- _Connection.cs
- SoapObjectWriter.cs
- Function.cs
- SchemaImporter.cs
- OdbcDataAdapter.cs
- HMACSHA256.cs
- InternalSendMessage.cs
- TiffBitmapDecoder.cs
- VScrollBar.cs
- PackagePart.cs
- BoolExpression.cs
- DataServiceQueryOfT.cs
- SynchronizingStream.cs
- XmlTextReaderImpl.cs
- SchemaImporterExtension.cs
- DocumentViewerBase.cs
- EventArgs.cs
- BigInt.cs
- StylusPointProperties.cs
- NgenServicingAttributes.cs
- CheckBoxBaseAdapter.cs
- ToolBarButton.cs
- MD5CryptoServiceProvider.cs
- DeviceFiltersSection.cs
- PeerPresenceInfo.cs
- SystemInfo.cs
- SelectionProviderWrapper.cs
- XmlAttributeCollection.cs
- DesignerActionPanel.cs
- MarkupObject.cs
- Codec.cs
- BamlRecordWriter.cs
- SessionStateContainer.cs
- VBIdentifierTrimConverter.cs
- TraceSource.cs
- TypedReference.cs
- BinaryFormatter.cs
- DetailsViewPageEventArgs.cs
- DataBindingHandlerAttribute.cs
- ChangePasswordDesigner.cs
- DoubleUtil.cs
- DataServiceRequest.cs
- SimpleMailWebEventProvider.cs
- XLinq.cs
- PeerNameResolver.cs
- XmlNamedNodeMap.cs
- FullTextLine.cs
- ComAdminInterfaces.cs
- ListViewGroupConverter.cs
- WindowsTab.cs
- XPathSelectionIterator.cs
- CustomWebEventKey.cs
- GatewayDefinition.cs
- DesignTimeParseData.cs
- XmlQueryTypeFactory.cs
- ElapsedEventArgs.cs
- ManagementObject.cs
- TextMarkerSource.cs
- shaperfactoryquerycacheentry.cs
- ListItemViewAttribute.cs
- DataProviderNameConverter.cs
- XsltConvert.cs
- Variant.cs
- FileSystemWatcher.cs
- DoubleStorage.cs
- ListChangedEventArgs.cs
- HtmlInputSubmit.cs
- TypeTypeConverter.cs
- StagingAreaInputItem.cs
- DiscoveryClientOutputChannel.cs
- SimpleTextLine.cs
- ArgumentNullException.cs
- LongValidatorAttribute.cs
- RequestResponse.cs
- StaticFileHandler.cs
- DesignerProperties.cs
- WebReferencesBuildProvider.cs