Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / GlyphCache.cs / 2 / GlyphCache.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: // Glyph cache master definitions. // // Two classes, managed GlyphCache (master) and unmanaged CMilSlaveGlyphCache, // provide a storage for a data required for text rendering (glyph bitmaps). // // Glyph cache master keeps track of the content of glyph cache slave. // // The master doesn't hold glyph bitmaps; it only stores reference count for each glyph bitmap. // // Glyph cache master is capable to serve many glyph run masters (i.e. GlyphRun instances). // // Glyph cache is created empty, then modified when glyph run requires new realization // or abandon old one. At this moment the glyph cache master generates glyph bitmaps // and update requests to its slave. // // History: // 2004/03/25 : [....] - Created it // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Security; using System.Text; using System.Windows; using System.Windows.Media; using System.Windows.Media.Composition; using System.Runtime.InteropServices; using MS.Internal; using MS.Internal.FontCache; using SR = MS.Internal.PresentationCore.SR; using SRID = MS.Internal.PresentationCore.SRID; namespace System.Windows.Media { ////// Master Glyph Cache class /// internal class GlyphCache { ////// Run16: stores reference counts for up to 16 glyph bitmaps /// private class Run16 { private uint[] _refCounts = new uint[16]; private uint _count; private const int Power = 4; private const uint Mask = (uint)((1 << Power) - 1); internal bool IsEmpty() { return _count == 0; } // Increase refcount for a bitmap with given glyph index. // Return true if it is new allocation internal bool AddrefBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); bool fNew = _refCounts[glyphIndex]++ == 0; if (fNew) _count++; return fNew; } // Decrease refcount for a bitmap with given glyph index. // Return true if refcount reached zero internal bool ReleaseBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); Debug.Assert(_refCounts[glyphIndex] != 0); bool reachedZero = (--_refCounts[glyphIndex] == 0); if (reachedZero) _count--; return reachedZero; } }; ////// Run256: stores reference counts for up to 256 glyph bitmaps /// in 16 packs that are Run16 /// private class Run256 { private Run16[] _runs = new Run16[16]; private uint _count; // number of non-zeros in _runs private const int Power = 8; private const int Shift = Power - 4; private const uint Mask = (uint)((1 << Power) - 1); private const uint ChildMask = (uint)(Mask >> 4); internal bool IsEmpty() { return _count == 0; } // Increase refcount for a bitmap with given glyph index. // Return true if it is new allocation internal bool AddrefBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run16 run = _runs[i]; if (run == null) { run = new Run16(); _runs[i] = run; _count++; } return run.AddrefBitmap(glyphIndex & ChildMask); } // Decrease refcount for a bitmap with given glyph index. // Return true if refcount reached zero internal bool ReleaseBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run16 run = _runs[i]; Debug.Assert(run != null); bool reachedZero = run.ReleaseBitmap(glyphIndex & ChildMask); if (reachedZero && run.IsEmpty()) { _runs[i] = null; _count--; } return reachedZero; } } ////// Run4096: stores reference counts for up to 4096 glyph bitmaps /// in 16 packs that are Run256 /// private class Run4096 { private Run256[] _runs = new Run256[16]; private uint _count; // number of non-zeros in _runs private const int Power = 12; private const int Shift = Power - 4; private const uint Mask = (uint)((1 << Power) - 1); private const uint ChildMask = (uint)(Mask >> 4); internal bool IsEmpty() { return _count == 0; } // Increase refcount for a bitmap with given glyph index. // Return true if it is new allocation internal bool AddrefBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run256 run = _runs[i]; if (run == null) { run = new Run256(); _runs[i] = run; _count++; } return run.AddrefBitmap(glyphIndex & ChildMask); } // Decrease refcount for a bitmap with given glyph index. // Return true if refcount reached zero internal bool ReleaseBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run256 run = _runs[i]; Debug.Assert(run != null); bool reachedZero = run.ReleaseBitmap(glyphIndex & ChildMask); if (reachedZero && run.IsEmpty()) { _runs[i] = null; _count--; } return reachedZero; } } ////// Run65536: stores reference counts for up to 65536 glyph bitmaps /// in 16 packs that are Run4096 /// private class Run65536 { private Run4096[] _runs = new Run4096[16]; private uint _count; // number of non-zeros in _runs private const int Power = 16; private const int Shift = Power - 4; private const uint Mask = (uint)((1 << Power) - 1); private const uint ChildMask = (uint)(Mask >> 4); internal bool IsEmpty() { return _count == 0; } // Increase refcount for a bitmap with given glyph index. // Return true if it is new allocation internal bool AddrefBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run4096 run = _runs[i]; if (run == null) { run = new Run4096(); _runs[i] = run; _count++; } return run.AddrefBitmap(glyphIndex & ChildMask); } // Decrease refcount for a bitmap with given glyph index. // Return true if refcount reached zero internal bool ReleaseBitmap(uint glyphIndex) { Debug.Assert((glyphIndex & ~Mask) == 0); uint i = glyphIndex >> Shift; Run4096 run = _runs[i]; Debug.Assert(run != null); bool reachedZero = run.ReleaseBitmap(glyphIndex & ChildMask); if (reachedZero && run.IsEmpty()) { _runs[i] = null; _count--; } return reachedZero; } } private struct FontFaceID { internal SecurityCriticalData_fontFileName; internal int _faceIndex; internal int _scaleX; internal int _scaleY; internal ushort _flags; internal ushort _pointSize; } /// /// FontFace: stores refcounts for up to 65536 glyph bitmaps together with /// font face identification parameters /// private class FontFace : Run65536 { // face identification parameters private FontFaceID _id; internal FontFace(FontFaceID id) { _id = id; } ////// Critical - as this accesses critical data. /// TreatAsSafe - The critical data is used only for comparison. /// [SecurityCritical, SecurityTreatAsSafe] internal bool Match(FontFaceID id) { return _id._faceIndex == id._faceIndex && _id._flags == id._flags && _id._scaleX == id._scaleX && _id._scaleY == id._scaleY && _id._pointSize == id._pointSize && String.Compare(_id._fontFileName.Value, id._fontFileName.Value, StringComparison.OrdinalIgnoreCase) == 0; } } ////// Manager: short-life GlyphCache helper /// private class Manager { private DUCE.Channel _channel; private List_faceList; private FontFaceID _faceId; private IList _glyphIndices; private int _glyphCount; private ushort[] _missedGlyphIndices; private int _missedGlyphCount; private FontFace _face; private int _faceHandle; private const ushort _fontCacheFlagMask = (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunHinting | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunBoldSimulation | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunItalicSimulation | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunSideways | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunIsTrueType; private const ushort _faceFlagMask = _fontCacheFlagMask | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunForceVAA | (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunVerticalDropOut; private const uint _verticalAntialiasingThreashold = 20 * 0x10000; internal Manager(DUCE.Channel channel, List faceList) { _channel = channel; _faceList = faceList; } /// /// AddRealization generates glyph bitmaps and submits tham to the /// slave glyph cache. Before doing this it checks whether required glyphs /// are already contained on a slave side. If so then these bitmaps are not /// generated and not transmitted, however the trace of the request is kept /// locally, in a form of reference counters, so consequent FreeRealization /// call would not release bitmaps too early. /// ////// Font face handle. This value should be used to identify /// ////// Critical - as this accesses critical data and calls GetGlyphs which is Critical. /// Safe - as this doesn't save or return information obtained from GetGlyphs(). /// It hands it over to Mil which'll use this information for rendering. /// [SecurityCritical, SecurityTreatAsSafe] internal unsafe int AddRealization( SecurityCriticalDatafontFileName, int fontFaceIndex, ushort glyphRunFlags, double scaleX, double scaleY, double hintingEmSize, IList glyphIndices ) { _faceId._fontFileName = fontFileName; _faceId._faceIndex = fontFaceIndex; _faceId._scaleX = (int)(scaleX * 0x10000); _faceId._scaleY = (int)(scaleY * 0x10000); _faceId._pointSize = (ushort)hintingEmSize; _faceId._flags = (ushort)(glyphRunFlags & _faceFlagMask); if ((_faceId._flags & (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunItalicSimulation) == 0) { // when calling rasterizer, the sideways flag makes a difference only in case of italic simulation _faceId._flags = (ushort)(_faceId._flags & ~(ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunSideways); } if (_faceId._scaleY > _verticalAntialiasingThreashold) { // we are using VAA (vertical anti aliasing, that means 6*5 overscaled // bitmaps instead of regular 6*1) if font size is big, or if VAA // is forced by user _faceId._flags |= (ushort)MIL_GLYPHRUN_FLAGS.MilGlyphRunForceVAA; } _glyphIndices = glyphIndices; _glyphCount = glyphIndices.Count; if (!FindFace()) CreateFace(); GatherMissedGlyphs(); if (_missedGlyphCount != 0) { void*[] glyphBitmaps = new void*[_missedGlyphCount]; FontCacheAccessor fontCacheAccessor = new FontCacheAccessor(); fontCacheAccessor.GetBitmaps( _faceId._fontFileName.Value, _faceId._faceIndex, _faceId._scaleX, _faceId._scaleY, _faceId._pointSize, (_faceId._flags & (uint)MIL_GLYPHRUN_FLAGS.MilGlyphRunForceVAA) != 0 ? (ushort)MS.Internal.FontRasterization.OverscaleMode.OverscaleXandY : (ushort)MS.Internal.FontRasterization.OverscaleMode.OverscaleX, //renderingMode (ushort)(_faceId._flags & _fontCacheFlagMask), //renderingFlags, _missedGlyphCount, _missedGlyphIndices, glyphBitmaps ); bool needDropOut = (_faceId._flags & (uint)MIL_GLYPHRUN_FLAGS.MilGlyphRunVerticalDropOut) != 0; AddBitmapsToSlaveCache(glyphBitmaps, needDropOut); // keep font cache accessor alive until all bitmaps are copied by AddBitmapsToSlaveCache GC.KeepAlive(fontCacheAccessor); } return _faceHandle; } /// /// Critical - as this calls RemoveBitmapsFromSlaveCache which is critical /// TreatASSafe - It Frees the realizations and does not hand out anything critical /// [SecurityCritical, SecurityTreatAsSafe] internal void FreeRealization( IListglyphIndices, int faceHandle ) { Debug.Assert((uint)faceHandle < (uint)_faceList.Count); _faceHandle = faceHandle; _face = _faceList[_faceHandle]; Debug.Assert(_face != null); _glyphIndices = glyphIndices; _glyphCount = glyphIndices.Count; GatherExtraGlyphs(); if (_missedGlyphCount != 0) { unsafe { RemoveBitmapsFromSlaveCache(); } } if (_face.IsEmpty()) { _faceList[_faceHandle] = null; } } // Find the face by given request parameters private bool FindFace() { int faceCount = _faceList.Count; for (_faceHandle = 0; _faceHandle < faceCount; _faceHandle++) { _face = _faceList[_faceHandle]; if (_face != null && _face.Match(_faceId)) return true; } _face = null; return false; } private void CreateFace() { _face = new FontFace(_faceId); // insert newly created face into the list int faceCount = _faceList.Count; for (_faceHandle = 0; _faceHandle < faceCount; _faceHandle++) { if (_faceList[_faceHandle] == null) break; } if (_faceHandle == faceCount) { _faceList.Add(_face); } else { _faceList[_faceHandle] = _face; } } private void GatherMissedGlyphs() { Debug.Assert(_face != null); _missedGlyphIndices = new ushort[_glyphCount]; _missedGlyphCount = 0; for (int i = 0; i < _glyphCount; i++) { ushort glyphIndex = _glyphIndices[i]; bool fNeedRasterize = _face.AddrefBitmap(glyphIndex); if (fNeedRasterize) { _missedGlyphIndices[_missedGlyphCount++] = glyphIndex; } } } private void GatherExtraGlyphs() { Debug.Assert(_face != null); _missedGlyphIndices = new ushort[_glyphCount]; _missedGlyphCount = 0; for (int i = 0; i < _glyphCount; i++) { ushort glyphIndex = _glyphIndices[i]; bool fNeedRelease = _face.ReleaseBitmap(glyphIndex); if (fNeedRelease) { _missedGlyphIndices[_missedGlyphCount++] = glyphIndex; } } } /// /// Critical - as this accesses unsafe code blocks. /// [SecurityCritical] private unsafe void AddBitmapsToSlaveCache(void*[] glyphBitmaps, bool needDropOut) { Debug.Assert(_missedGlyphCount != 0); Debug.Assert(glyphBitmaps != null); DUCE.MILCMD_GLYPHCACHE_ADDBITMAPS command; try { command.Type = MILCMD.MilCmdGlyphCacheAddBitmaps; command.FontFaceHandle = (uint)_faceHandle; command.FaceFlags = _faceId._flags; command.GlyphCount = checked((UInt16)_missedGlyphCount); command.Handle = _channel.GlyphCache.Handle; // Precalculate size of command data buffer int dataSize = _missedGlyphCount * sizeof(ushort); // Count the total size of the bitmaps. if (!needDropOut) { for (int i = 0; i < _missedGlyphCount; i++) { int blockSize = GetBitmapTransferSize((GlyphBitmap*)glyphBitmaps[i]); dataSize = checked(dataSize + blockSize); } } else { for (int i = 0; i < _missedGlyphCount; i++) { int blockSize = GetTransformedBitmapTransferSize((GlyphBitmap*)glyphBitmaps[i]); dataSize = checked(dataSize + blockSize); } } Debug.Assert(_channel != null); _channel.BeginCommand( (byte*)&command, sizeof(DUCE.MILCMD_GLYPHCACHE_ADDBITMAPS), dataSize ); } catch (System.OverflowException e) { // re-throw more readable exception throw new OutOfMemoryException(SR.Get(SRID.TooManyGlyphRuns), e); } // Write the bitmaps if needed. // Bitmaps should go first because of aligning. if (!needDropOut) { for (int i = 0; i < _missedGlyphCount; i++) { TransferBitmap((GlyphBitmap*)glyphBitmaps[i]); } } else { for (int i = 0; i < _missedGlyphCount; i++) { TransferTransformedBitmap((GlyphBitmap*)glyphBitmaps[i]); } } // Write the glyph indices. fixed (ushort* pData = _missedGlyphIndices) { _channel.AppendCommandData((byte*)pData, _missedGlyphCount * sizeof(ushort)); } _channel.EndCommand(); } ////// Critical - as this accesses unsafe code blocks. /// [SecurityCritical] private unsafe void RemoveBitmapsFromSlaveCache() { Debug.Assert(_missedGlyphCount != 0); DUCE.MILCMD_GLYPHCACHE_REMOVEBITMAPS command; command.Type = MILCMD.MilCmdGlyphCacheRemoveBitmaps; command.FontFaceHandle = (UInt32)_faceHandle; command.GlyphCount = (UInt32)_missedGlyphCount; command.Handle = _channel.GlyphCache.Handle; try { // Precalculate size of command data buffer int dataSize = checked(_missedGlyphCount * sizeof(ushort)); Debug.Assert(_channel != null); _channel.BeginCommand( (byte*)&command, sizeof(DUCE.MILCMD_GLYPHCACHE_REMOVEBITMAPS), dataSize ); } catch (System.OverflowException e) { // re-throw more readable exception throw new OutOfMemoryException(SR.Get(SRID.TooManyGlyphRuns), e); } // Write the glyph indices. fixed (ushort* pData = _missedGlyphIndices) { _channel.AppendCommandData((byte*)pData, _missedGlyphCount * sizeof(ushort)); } _channel.EndCommand(); } ////// Calculate the size in command buffer, required for transferring /// given bitmap to rendering machine. /// /// ///size, in bytes ////// Critical - as this accesses unsafe code blocks. /// TreatAsSafe - This does not return any unsafe information, but returns size of a GlypBitmap /// [SecurityCritical, SecurityTreatAsSafe] private static unsafe int GetBitmapTransferSize(GlyphBitmap* pBitmap) { int cbSize = sizeof(DUCE.MILCMD_GLYPHBITMAP); if (pBitmap != null) { cbSize += pBitmap->height * pBitmap->stride; } return cbSize; } ////// Compose and transfer a piece of MILCMD_GLYPHCACHE_ADDBITMAPS command /// that represents given glyph bitmap. /// /// ////// Critical - as this accesses unsafe code blocks. /// [SecurityCritical] private unsafe void TransferBitmap(GlyphBitmap* pBitmap) { if (pBitmap == null) { TransferStub(); return; } DUCE.MILCMD_GLYPHBITMAP bitmap = new DUCE.MILCMD_GLYPHBITMAP(); bitmap.horOriginX = checked((Int16)(pBitmap->horOriginX)); bitmap.horOriginY = checked((Int16)(pBitmap->horOriginY)); bitmap.horAdvance = checked((Int16)(pBitmap->horAdvance)); bitmap.verOriginX = checked((Int16)(pBitmap->verOriginX)); bitmap.verOriginY = checked((Int16)(pBitmap->verOriginY)); bitmap.width = checked((UInt16)(pBitmap->width)); bitmap.height = checked((UInt16)(pBitmap->height)); bitmap.stride = checked((UInt16)(pBitmap->stride)); int cbDataSize = (int)bitmap.height * (int)bitmap.stride; _channel.AppendCommandData((byte*)&bitmap, sizeof(DUCE.MILCMD_GLYPHBITMAP)); if (cbDataSize != 0) { byte* pData = (byte*)pBitmap + sizeof(GlyphBitmap); _channel.AppendCommandData(pData, cbDataSize); } } ////// This routine is for seldom circumstances, when /// font cache unabled supply particular glyph bitmap. /// When happened so we'll replace glyph with special shape /// (currently empty) /// ////// Critical - as this accesses unsafe code blocks. /// [SecurityCritical] private unsafe void TransferStub() { // create empty struct GlyphBitmap in stack frame DUCE.MILCMD_GLYPHBITMAP bitmap = new DUCE.MILCMD_GLYPHBITMAP(); _channel.AppendCommandData((byte*)&bitmap, sizeof(DUCE.MILCMD_GLYPHBITMAP)); } ////// Precalculate the size of MILCMD_GLYPHCACHE_ADDBITMAPS command segment /// that will be used by TransferTransformedBitmap /// /// given glyph bitmap ///size, in bytes ////// Critical: accepts a pointer and processes it with no validation /// [SecurityCritical] private static unsafe int GetTransformedBitmapTransferSize(GlyphBitmap* pBitmap) { int cbSize = sizeof(DUCE.MILCMD_GLYPHBITMAP); if (pBitmap != null) { // Vertical drop out needs glyph bitmap (that's ovescaled 5 times by Y axis) // to be vertically aligned to physycal pixel grid. // We may need to allocate extra rows above and below // original image. int bitmapTop = -pBitmap->horOriginY; int bitmapBottom = bitmapTop + pBitmap->height; int pixelTop = bitmapTop >= 0 ? bitmapTop / 5 : -((4 - bitmapTop) / 5); int pixelBottom = bitmapBottom >= 0 ? (bitmapBottom + 4) / 5 : -((-bitmapBottom) / 5); int rowsAbove = bitmapTop - pixelTop * 5; int rowsBelow = pixelBottom * 5 - bitmapBottom; Debug.Assert(rowsAbove >= 0 && rowsAbove < 5); Debug.Assert(rowsBelow >= 0 && rowsBelow < 5); cbSize += (pBitmap->height + rowsBelow + rowsAbove) * pBitmap->stride; } return cbSize; } ////// Pass the GlyphBitmap to command buffer, along the way /// making horizontal strokes *a little* thicker than given /// GlyphBitmap has. /// /// This thickening algorythm (also referred to as "virtual /// drop out control") is completely heuristic. It was /// initially proposed by Beat Stamm (beats). This version /// differs much from the initial. It thickens only /// horizontal strokes, increasing stroke width up to 2 virtual /// pixels. Heuristic prohibits thickening if it cause /// the stroke to bleed through pixel boundary, and also if /// next stroke is too close to given. /// /// given glyph bitmap ////// Critical - as this accesses unsafe code blocks. /// [SecurityCritical] private unsafe void TransferTransformedBitmap(GlyphBitmap* pBitmap) { if (pBitmap == null) { TransferStub(); return; } // Vertical drop out needs glyph bitmap (that's ovescaled 5 times by Y axis) // to be vertically aligned to physycal pixel grid. // We may need to allocate extra rows above and below // original image. int bitmapTop = -pBitmap->horOriginY; int bitmapBottom = bitmapTop + pBitmap->height; int pixelTop = bitmapTop >= 0 ? bitmapTop / 5 : -((4 - bitmapTop) / 5); int pixelBottom = bitmapBottom >= 0 ? (bitmapBottom + 4) / 5 : -((-bitmapBottom) / 5); int rowsAbove = bitmapTop - pixelTop * 5; int rowsBelow = pixelBottom * 5 - bitmapBottom; Debug.Assert(rowsAbove >= 0 && rowsAbove < 5); Debug.Assert(rowsBelow >= 0 && rowsBelow < 5); int newSize = checked( sizeof(DUCE.MILCMD_GLYPHBITMAP) + (pBitmap->height + rowsBelow + rowsAbove) * pBitmap->stride ); byte* pData = stackalloc byte[newSize]; DUCE.MILCMD_GLYPHBITMAP* pNewBitmap = (DUCE.MILCMD_GLYPHBITMAP*)pData; // fill bitmap header pNewBitmap->horOriginX = checked((Int16)(pBitmap->horOriginX)); pNewBitmap->horOriginY = checked((Int16)(pBitmap->horOriginY + rowsAbove)); pNewBitmap->horAdvance = checked((Int16)(pBitmap->horAdvance)); pNewBitmap->verOriginX = checked((Int16)(pBitmap->verOriginX - rowsAbove)); pNewBitmap->verOriginY = checked((Int16)(pBitmap->verOriginY)); pNewBitmap->width = checked((UInt16)(pBitmap->width)); pNewBitmap->height = checked((UInt16)(pBitmap->height + rowsAbove + rowsBelow)); pNewBitmap->stride = checked((UInt16)(pBitmap->stride)); UInt32* pSrc = (UInt32*)((byte*)pBitmap + sizeof(GlyphBitmap)); UInt32* pDst = (UInt32*)(pData + sizeof(DUCE.MILCMD_GLYPHBITMAP)); int stride32 = pBitmap->stride >> 2; // fill added rows above with zeros UInt32* pDstAbove = pDst; int sizeAbove = rowsAbove * stride32; for (int i = sizeAbove; --i >= 0; ) pDst[i] = 0; // copy bitmap bits UInt32* pDstOrigin = pDstAbove + sizeAbove; int sizeOrigin = stride32 * pBitmap->height; for (int i = sizeOrigin; --i >= 0; ) pDstOrigin[i] = pSrc[i]; // fill added rows above with zeros UInt32* pDstBelow = pDstOrigin + sizeOrigin; int sizeBelow = rowsBelow * stride32; for (int i = sizeBelow; --i >= 0; ) pDstBelow[i] = 0; UInt32* pColon = pDst; int bandsCount = pixelBottom - pixelTop; int colonsCount = (int)((pNewBitmap->width + 31) >> 5); Debug.Assert(colonsCount <= stride32); if (bandsCount == 1) { for (int i = 0; i < colonsCount; i++, pColon++) { UInt32* p0 = pColon; UInt32* p1 = p0 + stride32; UInt32* p2 = p1 + stride32; UInt32* p3 = p2 + stride32; UInt32* p4 = p3 + stride32; // bleeding up: set the bit if there is "one" // on next row but not two previous and second next. // The magic code below actually repeats many times // the same formula: // bit |= nextBit & ~next2Bit & ~previousBit & ~previous2Bit // where some members are removed if we are close to the // edge so some "next" and "previous" are missed. *p0 |= *p1 & ~*p2; *p1 |= ~*p0 & *p2 & ~*p3; *p2 |= ~*p0 & ~*p1 & *p3 & ~*p4; *p3 |= ~*p1 & ~*p2 & *p4; // bleed down: same as bleeding up but Y direction is reversed *p4 |= ~*p2 & *p3; *p3 |= ~*p1 & *p2 & ~*p4; *p2 |= ~*p0 & *p1 & ~*p3 & ~*p4; *p1 |= *p0 & ~*p2 & ~*p3; } } else { // there are two or more bands for (int i = 0; i < colonsCount; i++, pColon++) { UInt32* p0 = pColon; UInt32* p1 = p0 + stride32; UInt32* p2 = p1 + stride32; UInt32* p3 = p2 + stride32; UInt32* p4 = p3 + stride32; UInt32* p5 = p4 + stride32; UInt32* p6 = p5 + stride32; // Handle first band // bleed up *p0 |= *p1 & ~*p2; *p1 |= ~*p0 & *p2 & ~*p3; *p2 |= ~*p0 & ~*p1 & *p3 & ~*p4; *p3 |= ~*p1 & ~*p2 & *p4 & ~*p5; // bleed down *p4 |= ~*p2 & *p3 & ~*p5 & ~*p6; *p3 |= ~*p1 & *p2 & ~*p4 & ~*p5; *p2 |= ~*p0 & *p1 & ~*p3 & ~*p4; *p1 |= *p0 & ~*p2 & ~*p3; UInt32* q1 = p4; UInt32* q2 = p3; // Handle middle bands for (int b = bandsCount - 2; --b >= 0; ) { p0 = q1 + stride32; p1 = p0 + stride32; p2 = p1 + stride32; p3 = p2 + stride32; p4 = p3 + stride32; p5 = p4 + stride32; p6 = p5 + stride32; // bleed up *p0 |= ~*q2 & ~*q1 & *p1 & ~*p2; *p1 |= ~*q1 & ~*p0 & *p2 & ~*p3; *p2 |= ~*p0 & ~*p1 & *p3 & ~*p4; *p3 |= ~*p1 & ~*p2 & *p4 & ~*p5; // bleed down *p4 |= ~*p2 & *p3 & ~*p5 & ~*p6; *p3 |= ~*p1 & *p2 & ~*p4 & ~*p5; *p2 |= ~*p0 & *p1 & ~*p3 & ~*p4; *p1 |= ~*q1 & *p0 & ~*p2 & ~*p3; q1 = p4; q2 = p3; } // Handle last band p0 = q1 + stride32; p1 = p0 + stride32; p2 = p1 + stride32; p3 = p2 + stride32; p4 = p3 + stride32; // bleed up *p0 |= ~*q2 & ~*q1 & *p1 & ~*p2; *p1 |= ~*q1 & ~*p0 & *p2 & ~*p3; *p2 |= ~*p0 & ~*p1 & *p3 & ~*p4; *p3 |= ~*p1 & ~*p2 & *p4; // bleed down *p4 |= ~*p2 & *p3; *p3 |= ~*p1 & *p2 & ~*p4; *p2 |= ~*p0 & *p1 & ~*p3 & ~*p4; *p1 |= ~*q1 & *p0 & ~*p2 & ~*p3; } } _channel.AppendCommandData(pData, newSize); } } //Manager private DUCE.Resource _duceResource = new DUCE.Resource(); internal DUCE.ResourceHandle Handle { get { return _duceResource.Handle; } } private List_faceList = new List (5); // Service channel that serves for both // pre-commit and post-commit actions internal DUCE.Channel _channel; internal void RemoveFromChannel() { if (_channel != null) { _duceResource.ReleaseOnChannel(_channel); } } internal GlyphCache(DUCE.Channel channel) { _channel = channel; if (_channel != null) { _duceResource.CreateOrAddRefOnChannel(_channel, DUCE.ResourceType.TYPE_GLYPHCACHE); } } /// /// Create realization for glyph run. /// During this call we'll figure out which glyph bitmaps /// are needed for given glyph run and given scales, /// generate these bitmaps and transfer them to /// slave glyph cache. /// ////// GlyphRun.Realization that will keep trace /// of glyph cache state changes and will /// serve to undo these changes on PostCommit call. /// internal GlyphRun.Realization CreateRealization( SecurityCriticalDatafontFileName, int fontFaceIndex, ushort glyphRunFlags, double scaleX, double scaleY, double hintingEmSize, IList glyphIndices ) { GlyphRun.Realization realization; // create new realization realization = new GlyphRun.Realization(); realization._scaleX = scaleX; realization._scaleY = scaleY; realization._glyphIndices = glyphIndices; Manager man = new Manager(_channel, _faceList); realization._faceHandle = man.AddRealization( fontFileName, fontFaceIndex, glyphRunFlags, scaleX, scaleY, hintingEmSize, glyphIndices ); return realization; } /// /// /// internal void RemoveRealization(GlyphRun.Realization r) { Manager man = new Manager(_channel, _faceList); man.FreeRealization( r._glyphIndices, r._faceHandle ); } } } // 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
- RegexMatch.cs
- SecurityContextSecurityToken.cs
- PropertyCollection.cs
- DynamicHyperLink.cs
- ExpressionBindings.cs
- TypeConverterValueSerializer.cs
- ProcessInputEventArgs.cs
- Line.cs
- ArcSegment.cs
- TabRenderer.cs
- DocobjHost.cs
- EntityKey.cs
- DynamicResourceExtensionConverter.cs
- HMACSHA1.cs
- FilteredDataSetHelper.cs
- ToolZone.cs
- TextEncodedRawTextWriter.cs
- SmiContext.cs
- NTAccount.cs
- DataObject.cs
- StringCollection.cs
- SchemaCollectionCompiler.cs
- GifBitmapDecoder.cs
- ThemeableAttribute.cs
- CredentialCache.cs
- SpellerHighlightLayer.cs
- FormsAuthentication.cs
- FrameworkContentElement.cs
- JsonWriter.cs
- DateTimeFormat.cs
- HttpListener.cs
- StorageModelBuildProvider.cs
- ObsoleteAttribute.cs
- DelegateHelpers.cs
- SpotLight.cs
- CodeIdentifier.cs
- RectangleHotSpot.cs
- TaiwanCalendar.cs
- TableRow.cs
- UserNamePasswordValidator.cs
- GifBitmapEncoder.cs
- SmiEventSink_Default.cs
- TextEditorSelection.cs
- TimeZoneNotFoundException.cs
- TreeNodeCollectionEditor.cs
- EditBehavior.cs
- AccessibleObject.cs
- KeyGestureConverter.cs
- BezierSegment.cs
- DocumentApplicationJournalEntry.cs
- WebPartEditorOkVerb.cs
- _AutoWebProxyScriptEngine.cs
- PropertyReferenceSerializer.cs
- RadioButton.cs
- TreeView.cs
- LinkArea.cs
- FrameworkContentElement.cs
- ReadOnlyCollection.cs
- InitiatorServiceModelSecurityTokenRequirement.cs
- Codec.cs
- SymbolType.cs
- ToolStripMenuItem.cs
- ClientSponsor.cs
- SoapBinding.cs
- ScriptResourceAttribute.cs
- GraphicsContainer.cs
- EventLogTraceListener.cs
- CharacterMetricsDictionary.cs
- User.cs
- CacheAxisQuery.cs
- StreamProxy.cs
- ExtensionSimplifierMarkupObject.cs
- SafeNativeMethodsOther.cs
- NativeMethods.cs
- HMACSHA1.cs
- FrameworkElementAutomationPeer.cs
- Header.cs
- DesignerActionItem.cs
- EmptyEnumerable.cs
- SelectionListComponentEditor.cs
- NameScope.cs
- ConstraintConverter.cs
- Attribute.cs
- ToolStripContentPanel.cs
- OpenFileDialog.cs
- SocketInformation.cs
- PersistenceTypeAttribute.cs
- ToolStripPanelRow.cs
- BookmarkInfo.cs
- CompilerCollection.cs
- CounterNameConverter.cs
- Win32Exception.cs
- DrawingCollection.cs
- CommandDesigner.cs
- TextEffectResolver.cs
- WindowsToolbarAsMenu.cs
- DataGridHelper.cs
- ConfigurationValues.cs
- ResourceReferenceExpression.cs
- CompilerGlobalScopeAttribute.cs