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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FormatterServices.cs
- COM2FontConverter.cs
- HtmlInputControl.cs
- FocusWithinProperty.cs
- FontUnit.cs
- ProbeMatchesCD1.cs
- XmlSchemaComplexContent.cs
- BoundingRectTracker.cs
- Trace.cs
- NavigationProgressEventArgs.cs
- SingleObjectCollection.cs
- DbConnectionPoolGroup.cs
- PackagePart.cs
- EditorPartChrome.cs
- UnsafeNativeMethods.cs
- Helpers.cs
- PageAsyncTaskManager.cs
- DetailsViewRowCollection.cs
- DataObjectCopyingEventArgs.cs
- TypeUtil.cs
- CodeDomComponentSerializationService.cs
- WindowsIPAddress.cs
- CompilerResults.cs
- SystemTcpStatistics.cs
- MgmtResManager.cs
- PropVariant.cs
- HashHelper.cs
- FixedElement.cs
- Stopwatch.cs
- HttpDebugHandler.cs
- Block.cs
- CriticalExceptions.cs
- AccessedThroughPropertyAttribute.cs
- ByteStreamMessageEncoderFactory.cs
- CngProperty.cs
- MasterPageBuildProvider.cs
- GatewayDefinition.cs
- DatatypeImplementation.cs
- IdentityReference.cs
- ListenerAdaptersInstallComponent.cs
- OutgoingWebRequestContext.cs
- LoginName.cs
- CultureInfo.cs
- OpenFileDialog.cs
- TrackingParameters.cs
- AdvancedBindingPropertyDescriptor.cs
- TextFindEngine.cs
- precedingquery.cs
- Comparer.cs
- UpdateTranslator.cs
- AttributeCollection.cs
- FrameworkElement.cs
- StreamUpdate.cs
- DocumentAutomationPeer.cs
- SHA512Cng.cs
- FrameworkReadOnlyPropertyMetadata.cs
- DSACryptoServiceProvider.cs
- BaseTemplateParser.cs
- StringArrayConverter.cs
- PriorityBinding.cs
- BitmapEffectDrawingContextWalker.cs
- GACMembershipCondition.cs
- PageTextBox.cs
- JapaneseCalendar.cs
- ExportFileRequest.cs
- Transform3D.cs
- MetadataItem_Static.cs
- TraceProvider.cs
- TextHidden.cs
- VolatileEnlistmentMultiplexing.cs
- RectKeyFrameCollection.cs
- ImageAutomationPeer.cs
- EventBuilder.cs
- ToolStripProfessionalLowResolutionRenderer.cs
- ListParaClient.cs
- HostExecutionContextManager.cs
- DecoderBestFitFallback.cs
- OutputCacheSettingsSection.cs
- DoubleCollectionConverter.cs
- StreamInfo.cs
- WindowsBrush.cs
- PerfCounterSection.cs
- IdleTimeoutMonitor.cs
- ConfigXmlText.cs
- SpellerError.cs
- SessionIDManager.cs
- TableCell.cs
- CqlIdentifiers.cs
- WebBrowserContainer.cs
- SQLBinary.cs
- BoundConstants.cs
- EventDescriptor.cs
- _Semaphore.cs
- TypeDefinition.cs
- unsafenativemethodstextservices.cs
- XmlSchemaValidationException.cs
- CookieParameter.cs
- ExtentCqlBlock.cs
- SkewTransform.cs
- AppDomainManager.cs