GlyphCache.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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( 
                SecurityCriticalData fontFileName, 
                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(
                IList glyphIndices,
                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(
            SecurityCriticalData fontFileName, 
            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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK