You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
645 lines
26 KiB
645 lines
26 KiB
/****************************************************************************/
|
|
// ghapi.cpp
|
|
//
|
|
// Glyph handler - Windows specific
|
|
//
|
|
// Copyright (C) 1997-1999 Microsoft Corporation
|
|
/****************************************************************************/
|
|
|
|
#include <adcg.h>
|
|
extern "C" {
|
|
|
|
#define TRC_GROUP TRC_GROUP_CORE
|
|
#define TRC_FILE "wghapi"
|
|
#include <atrcapi.h>
|
|
}
|
|
#define TSC_HR_FILEID TSC_HR_GHAPI_CPP
|
|
|
|
#include "autil.h"
|
|
#include "gh.h"
|
|
#include "uh.h"
|
|
#include "clx.h"
|
|
|
|
|
|
static const PFN_MASTERTEXTTYPE MasterTextTypeTable[8] =
|
|
{
|
|
CGH::draw_nf_ntb_o_to_temp_start,
|
|
CGH::draw_f_ntb_o_to_temp_start,
|
|
CGH::draw_nf_ntb_o_to_temp_start,
|
|
CGH::draw_f_ntb_o_to_temp_start,
|
|
CGH::draw_nf_tb_no_to_temp_start,
|
|
CGH::draw_f_tb_no_to_temp_start,
|
|
CGH::draw_nf_ntb_o_to_temp_start,
|
|
CGH::draw_f_ntb_o_to_temp_start
|
|
};
|
|
|
|
|
|
CGH::CGH(CObjs* objs)
|
|
{
|
|
_pClientObjects = objs;
|
|
_pClipGlyphBitsBuffer = NULL;
|
|
_ClipGlyphBitsBufferSize = 0;
|
|
}
|
|
|
|
CGH::~CGH()
|
|
{
|
|
if (_pClipGlyphBitsBuffer!=NULL) {
|
|
LocalFree(_pClipGlyphBitsBuffer);
|
|
}
|
|
}
|
|
|
|
DCVOID DCAPI CGH::GH_Init(DCVOID)
|
|
{
|
|
DC_BEGIN_FN("GH_GlyphOut");
|
|
_pUh = _pClientObjects->_pUHObject;
|
|
_pClx = _pClientObjects->_pCLXObject;
|
|
_pUt = _pClientObjects->_pUtObject;
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Name: GH_GlyphOut */
|
|
/* */
|
|
/* Purpose: Process glyph output requests */
|
|
/* */
|
|
/* Returns: Process input event TRUE / FALSE */
|
|
/****************************************************************************/
|
|
HRESULT DCAPI CGH::GH_GlyphOut(
|
|
LPINDEX_ORDER pOrder,
|
|
LPVARIABLE_INDEXBYTES pVariableBytes)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
BYTE szTextBuffer[GH_TEXT_BUFFER_SIZE];
|
|
BYTE ajFrag[256];
|
|
UINT16 ajUnicode[256];
|
|
unsigned ulBufferWidth;
|
|
unsigned fDrawFlags;
|
|
PDCUINT8 pjBuffer;
|
|
PDCUINT8 pjEndBuffer;
|
|
unsigned crclFringe;
|
|
RECT arclFringe[4];
|
|
unsigned i;
|
|
int x;
|
|
int y;
|
|
PDCUINT8 pjData;
|
|
PDCUINT8 pjDataEnd;
|
|
unsigned iGlyph;
|
|
unsigned cacheIndex;
|
|
unsigned cbFrag;
|
|
PDCUINT8 pjFrag;
|
|
PDCUINT8 pjFragEnd;
|
|
int dx;
|
|
INT16 delta;
|
|
ULONG BufferAlign;
|
|
ULONG BufferOffset;
|
|
unsigned ulBytes;
|
|
unsigned ulHeight;
|
|
PFN_MASTERTEXTTYPE pfnMasterType;
|
|
|
|
DC_BEGIN_FN("GH_GlyphOut");
|
|
|
|
dx = 0;
|
|
|
|
// SECURITY 558128: GH_GlyphOut must verify data in VARAIBLE_INDEXBYTES
|
|
// parameter which is defined as 255 elements
|
|
if (255 < pVariableBytes->len) {
|
|
TRC_ABORT(( TB, _T("variable bytes len too long %u"),
|
|
pVariableBytes->len));
|
|
hr = E_TSC_CORE_LENGTH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
/************************************************************************/
|
|
// Alloc a temp work buffer -- use the stack buffer if large enough, or
|
|
// alloc heap memory if need be.
|
|
/************************************************************************/
|
|
// Make the buffer width WORD aligned.
|
|
ulBufferWidth = (unsigned)(((pOrder->BkRight + 31) & ~31) -
|
|
(pOrder->BkLeft & ~31)) >> 3;
|
|
ulHeight = (unsigned)(pOrder->BkBottom - pOrder->BkTop);
|
|
if ((ulBufferWidth <= FIFTEEN_BITS) && (ulHeight <= FIFTEEN_BITS)) {
|
|
ulBytes = ulBufferWidth * ulHeight + 64;
|
|
|
|
#ifdef DC_DEBUG
|
|
g_ulBytes = ulBytes;
|
|
#endif
|
|
|
|
// If the temp buffer is big enough, use it. Otherwise attempt to
|
|
// allocate enough memory to satisfy the request.
|
|
if (ulBytes <= (sizeof(szTextBuffer) - 20)) {
|
|
pjBuffer = szTextBuffer;
|
|
memset(szTextBuffer, 0, ulBytes);
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Allocating %d byte temp glyph buffer"), ulBytes));
|
|
pjBuffer = (PDCUINT8)UT_Malloc( _pUt, ulBytes);
|
|
if (pjBuffer != NULL) {
|
|
memset(pjBuffer, 0, ulBytes);
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Unable to alloc temp glyph buffer")));
|
|
DC_QUIT;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
TRC_NRM((TB, _T("Temp glyph buffer calc overflow")));
|
|
hr = E_TSC_UI_GLYPH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
pjEndBuffer = pjBuffer + ulBytes;
|
|
|
|
#ifdef DC_HICOLOR
|
|
TRC_NRM((TB, _T("Glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
|
|
ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
// Clear the fringe opaque rect if need be.
|
|
/************************************************************************/
|
|
// crclFringe ends up holding the number of fringe rectangles to
|
|
// post-process.
|
|
crclFringe = 0;
|
|
|
|
if (pOrder->OpTop < pOrder->OpBottom) {
|
|
// Establish solid brush.
|
|
UHUseBrushOrg(0, 0, _pUh);
|
|
_pUh->UHUseSolidPaletteBrush(pOrder->ForeColor);
|
|
|
|
// If the background brush is a solid brush, we need to compute the
|
|
// fringe opaque area outside the text rectangle and include the
|
|
// remaining rectangle in the text output. The fringe rectangles will
|
|
// be output last to reduce flickering when a string is "moved"
|
|
// continuously across the screen.
|
|
if (pOrder->BrushStyle == BS_SOLID) {
|
|
// Top fragment
|
|
if (pOrder->BkTop > pOrder->OpTop) {
|
|
arclFringe[crclFringe].left = (int) pOrder->OpLeft;
|
|
arclFringe[crclFringe].top = (int) pOrder->OpTop;
|
|
arclFringe[crclFringe].right = (int) pOrder->OpRight;
|
|
arclFringe[crclFringe].bottom = (int) pOrder->BkTop;
|
|
crclFringe++;
|
|
}
|
|
|
|
// Left fragment
|
|
if (pOrder->BkLeft > pOrder->OpLeft) {
|
|
arclFringe[crclFringe].left = (int) pOrder->OpLeft;
|
|
arclFringe[crclFringe].top = (int) pOrder->BkTop;
|
|
arclFringe[crclFringe].right = (int) pOrder->BkLeft;
|
|
arclFringe[crclFringe].bottom = (int) pOrder->BkBottom;
|
|
crclFringe++;
|
|
}
|
|
|
|
// Right fragment
|
|
if (pOrder->BkRight < pOrder->OpRight) {
|
|
arclFringe[crclFringe].left = (int) pOrder->BkRight;
|
|
arclFringe[crclFringe].top = (int) pOrder->BkTop;
|
|
arclFringe[crclFringe].right = (int) pOrder->OpRight;
|
|
arclFringe[crclFringe].bottom = (int) pOrder->BkBottom;
|
|
crclFringe++;
|
|
}
|
|
|
|
// Bottom fragment
|
|
if (pOrder->BkBottom < pOrder->OpBottom) {
|
|
arclFringe[crclFringe].left = (int) pOrder->OpLeft;
|
|
arclFringe[crclFringe].top = (int) pOrder->BkBottom;
|
|
arclFringe[crclFringe].right = (int) pOrder->OpRight;
|
|
arclFringe[crclFringe].bottom = (int) pOrder->OpBottom;
|
|
crclFringe++;
|
|
}
|
|
}
|
|
else {
|
|
// If the background brush is a pattern brush, we will output the
|
|
// whole rectangle now.
|
|
PatBlt(_pUh->_UH.hdcDraw,
|
|
(int)pOrder->OpLeft,
|
|
(int)pOrder->OpTop,
|
|
(int)(pOrder->OpRight - pOrder->OpLeft),
|
|
(int)(pOrder->OpBottom - pOrder->OpTop),
|
|
PATCOPY);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
// Get fixed pitch, overlap, and top & bottom Y alignment flags.
|
|
/************************************************************************/
|
|
if ((pOrder->flAccel & SO_HORIZONTAL) &&
|
|
!(pOrder->flAccel & SO_REVERSED)) {
|
|
fDrawFlags = ((pOrder->ulCharInc != 0) |
|
|
(((pOrder->flAccel &
|
|
(SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) !=
|
|
(SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT)) << 1) |
|
|
(((pOrder->flAccel &
|
|
(SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE)) ==
|
|
(SO_ZERO_BEARINGS | SO_FLAG_DEFAULT_PLACEMENT | SO_MAXEXT_EQUAL_BM_SIDE)) << 2));
|
|
}
|
|
else {
|
|
fDrawFlags = 0;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* Draw the text into the temp buffer by selecting and calling the */
|
|
/* appropriate glyph dispatch routine */
|
|
/************************************************************************/
|
|
pfnMasterType = MasterTextTypeTable[fDrawFlags];
|
|
|
|
x = (int)pOrder->x;
|
|
y = (int)pOrder->y;
|
|
|
|
pjData = &(pVariableBytes->arecs[0].byte);
|
|
pjDataEnd = pjData + pVariableBytes->len;
|
|
|
|
BufferAlign = (pOrder->BkLeft & 31);
|
|
BufferOffset = (pOrder->BkLeft - BufferAlign);
|
|
|
|
iGlyph = 0;
|
|
|
|
GHFRAGRESET(0);
|
|
|
|
while (pjData < pjDataEnd) {
|
|
/********************************************************************/
|
|
/* 'Add Fragment' */
|
|
/********************************************************************/
|
|
if (*pjData == ORD_INDEX_FRAGMENT_ADD) {
|
|
HPUHFRAGCACHE pCache;
|
|
HPDCUINT8 pCacheEntryData;
|
|
PUHFRAGCACHEENTRYHDR pCacheEntryHdr;
|
|
|
|
pjData++;
|
|
|
|
CHECK_READ_N_BYTES(pjData, pjDataEnd, 2, hr,
|
|
( TB, _T("reading glyph data off end")));
|
|
|
|
cacheIndex = *pjData++;
|
|
hr = _pUh->UHIsValidFragmentCacheIndex(cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
cbFrag = *pjData++;
|
|
|
|
// Add the fragment to the cache.
|
|
pCache = &_pUh->_UH.fragCache;
|
|
|
|
if (cbFrag > pCache->cbEntrySize) {
|
|
TRC_ABORT((TB,_T("Invalid fragment size")));
|
|
hr = E_TSC_CORE_LENGTH;
|
|
DC_QUIT;
|
|
}
|
|
|
|
pCacheEntryHdr = &(pCache->pHdr[cacheIndex]);
|
|
pCacheEntryHdr->cbFrag = cbFrag;
|
|
pCacheEntryHdr->cacheId = pOrder->cacheId;
|
|
|
|
pCacheEntryData = &(pCache->pData[cacheIndex *
|
|
pCache->cbEntrySize]);
|
|
|
|
CHECK_READ_N_BYTES_2ENDED(pjData - cbFrag - 3, &(pVariableBytes->arecs[0].byte),
|
|
pjDataEnd, cbFrag, hr, (TB,_T("Fragment for ADD begins before data")))
|
|
memcpy(pCacheEntryData, pjData - cbFrag - 3, cbFrag);
|
|
|
|
if (pOrder->ulCharInc == 0) {
|
|
if ((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0) {
|
|
if (pCacheEntryData[1] & 0x80) {
|
|
pCacheEntryData[2] = 0;
|
|
pCacheEntryData[3] = 0;
|
|
}
|
|
else {
|
|
pCacheEntryData[1] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* 'Use Fragment' */
|
|
/********************************************************************/
|
|
else if (*pjData == ORD_INDEX_FRAGMENT_USE) {
|
|
PUHFRAGCACHE pCache;
|
|
PDCUINT8 pCacheEntryData;
|
|
PUHFRAGCACHEENTRYHDR pCacheEntryHdr;
|
|
unsigned cbFrag;
|
|
|
|
pjData++;
|
|
|
|
CHECK_READ_ONE_BYTE(pjData, pjDataEnd, hr,
|
|
( TB, _T("reading glyph data off end")));
|
|
|
|
cacheIndex = *pjData++;
|
|
hr = _pUh->UHIsValidFragmentCacheIndex(cacheIndex);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
|
|
if ((pOrder->ulCharInc == 0) &&
|
|
((pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) == 0)) {
|
|
|
|
CHECK_READ_ONE_BYTE(pjData, pjDataEnd, hr,
|
|
( TB, _T("reading glyph data off end")))
|
|
delta = (*(PDCINT8)pjData++);
|
|
if (delta & 0x80) {
|
|
CHECK_READ_N_BYTES(pjData, pjDataEnd, sizeof(DCINT16), hr,
|
|
( TB, _T("reading glyph data off end")))
|
|
delta = (*(PDCINT16)pjData);
|
|
pjData += sizeof(DCINT16);
|
|
}
|
|
|
|
if (pOrder->flAccel & SO_HORIZONTAL)
|
|
x += delta;
|
|
else
|
|
y += delta;
|
|
}
|
|
|
|
// Get the fragment from the cache.
|
|
pCache = &_pUh->_UH.fragCache;
|
|
pCacheEntryHdr = &(pCache->pHdr[cacheIndex]);
|
|
pCacheEntryData = &(pCache->pData[cacheIndex *
|
|
pCache->cbEntrySize]);
|
|
|
|
if (pCacheEntryHdr->cacheId != pOrder->cacheId) {
|
|
TRC_ABORT((TB,_T("Fragment cache id mismatch")));
|
|
hr = E_TSC_CORE_CACHEVALUE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
cbFrag = (unsigned)pCacheEntryHdr->cbFrag;
|
|
if (cbFrag > sizeof(ajFrag)) {
|
|
TRC_ABORT(( TB, _T("cbFrag > sizeof (ajFrag)")));
|
|
hr = E_TSC_CORE_LENGTH;
|
|
DC_QUIT;
|
|
}
|
|
memcpy(ajFrag, pCacheEntryData, cbFrag);
|
|
|
|
GHFRAGLEFT(x);
|
|
pjFrag = ajFrag;
|
|
pjFragEnd = &ajFrag[cbFrag];
|
|
|
|
while (pjFrag < pjFragEnd) {
|
|
hr = pfnMasterType(this, pOrder, iGlyph++, &pjFrag, pjFragEnd, &x, &y,
|
|
pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, ajUnicode, &dx);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
}
|
|
|
|
if (pOrder->flAccel & SO_CHAR_INC_EQUAL_BM_BASE)
|
|
GHFRAGRIGHT(x);
|
|
else
|
|
GHFRAGRIGHT(x+dx);
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* Normal glyph out */
|
|
/********************************************************************/
|
|
else {
|
|
int dummy;
|
|
/****************************************************************/
|
|
/* if we have more than 255 glyphs, we won't get any unicode */
|
|
/* beyond 255 glyphs because ajUnicode has length of 256 */
|
|
/****************************************************************/
|
|
if (iGlyph < 255) {
|
|
hr = pfnMasterType(this, pOrder, iGlyph++, &pjData, pjDataEnd, &x, &y,
|
|
pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, ajUnicode, &dummy);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
} else {
|
|
hr = pfnMasterType(this, pOrder, iGlyph++, &pjData, pjDataEnd, &x, &y,
|
|
pjBuffer, pjEndBuffer, BufferOffset, ulBufferWidth, NULL, &dummy);
|
|
DC_QUIT_ON_FAIL(hr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iGlyph < 255)
|
|
ajUnicode[iGlyph] = 0;
|
|
else
|
|
ajUnicode[255] = 0;
|
|
|
|
|
|
/************************************************************************/
|
|
/* Draw the temp buffer to the output device */
|
|
/************************************************************************/
|
|
#if defined(OS_WINCE) || defined(OS_WINNT)
|
|
/************************************************************************/
|
|
// For WinCE, Win9x, and NT use a fast path if possible.
|
|
/************************************************************************/
|
|
#ifdef USE_GDIPLUS
|
|
if (_pUh->_UH.bmShadowBits != NULL &&
|
|
_pUh->_UH.protocolBpp == _pUh->_UH.shadowBitmapBpp &&
|
|
_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap) {
|
|
#else // USE_GDIPLUS
|
|
if (_pUh->_UH.bmShadowBits != NULL &&
|
|
_pUh->_UH.hdcDraw == _pUh->_UH.hdcShadowBitmap) {
|
|
#endif // USE_GDIPLUS
|
|
INT32 left, right, top, bottom;
|
|
UINT32 dx, dy;
|
|
|
|
if (_pUh->_UH.rectReset) {
|
|
left = pOrder->BkLeft;
|
|
right = pOrder->BkRight;
|
|
top = pOrder->BkTop;
|
|
bottom = pOrder->BkBottom;
|
|
}
|
|
else {
|
|
left = DC_MAX(pOrder->BkLeft, _pUh->_UH.lastLeft);
|
|
right = DC_MIN(pOrder->BkRight, _pUh->_UH.lastRight + 1);
|
|
top = DC_MAX(pOrder->BkTop, _pUh->_UH.lastTop);
|
|
bottom = DC_MIN(pOrder->BkBottom, _pUh->_UH.lastBottom + 1);
|
|
}
|
|
|
|
//
|
|
// Fix for bug#699321. In case the shadow bitmap is enabled and we will
|
|
// use the "performant" functions to copy the glyph fragment into
|
|
// the shadow buffer we have to make sure that the dest rect is clipped
|
|
// to the screen area. If it is not we might overflow the shadow screen
|
|
// buffer. The server should not send us orders that will result in
|
|
// the dest rect not being fully contained by the screen area. This is
|
|
// purely a security surface reduction fix.
|
|
//
|
|
if ((left < right) && (top < bottom) &&
|
|
(left >= 0) && (right <= (INT32)_pUh->_UH.bmShadowWidth) &&
|
|
(top >= 0) && (bottom <= (INT32)_pUh->_UH.bmShadowHeight)) {
|
|
#ifdef OS_WINNT
|
|
// On NT and Win9x we need to make sure all GDI buffered output
|
|
// is flushed out to the offscreen bitmap.
|
|
GdiFlush();
|
|
#endif
|
|
|
|
dx = (UINT32)(left - pOrder->BkLeft);
|
|
dy = (UINT32)(top - pOrder->BkTop);
|
|
|
|
if (pOrder->OpTop < pOrder->OpBottom) {
|
|
#ifdef DC_HICOLOR
|
|
TRC_NRM((TB, _T("Opaque glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
|
|
ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
|
|
|
|
if (_pUh->_UH.protocolBpp == 24)
|
|
{
|
|
vSrcOpaqCopyS1D8_24(pjBuffer + dy * ulBufferWidth,
|
|
BufferAlign + dx,
|
|
ulBufferWidth,
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
|
|
left,
|
|
right,
|
|
_pUh->_UH.bmShadowWidth,
|
|
bottom - top,
|
|
pOrder->BackColor.u.rgb,
|
|
pOrder->ForeColor.u.rgb);
|
|
}
|
|
else if ((_pUh->_UH.protocolBpp == 16) || (_pUh->_UH.protocolBpp == 15))
|
|
{
|
|
vSrcOpaqCopyS1D8_16(pjBuffer + dy * ulBufferWidth,
|
|
BufferAlign + dx,
|
|
ulBufferWidth,
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
|
|
left,
|
|
right,
|
|
_pUh->_UH.bmShadowWidth,
|
|
bottom - top,
|
|
*((PDCUINT16)&(pOrder->BackColor)),
|
|
*((PDCUINT16)&(pOrder->ForeColor)));
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
vSrcOpaqCopyS1D8(pjBuffer + dy * ulBufferWidth, // pointer to beginning of current scan line of src buffer
|
|
BufferAlign + dx, // left (starting) pixel in src rectangle
|
|
ulBufferWidth, // bytes from one src scan line to next
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth, // pointer to beginning of current scan line of Dst buffer
|
|
left, // left(first) dst pixel
|
|
right, // right(last) dst pixel
|
|
_pUh->_UH.bmShadowWidth, // bytes from one Dst scan line to next
|
|
bottom - top, // number of scan lines
|
|
pOrder->BackColor.u.index, // Foreground color
|
|
pOrder->ForeColor.u.index); // Background color
|
|
#ifdef DC_HICOLOR
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef DC_HICOLOR
|
|
TRC_NRM((TB, _T("Transparent glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
|
|
ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
|
|
|
|
if (_pUh->_UH.protocolBpp == 24)
|
|
{
|
|
vSrcTranCopyS1D8_24(pjBuffer + dy * ulBufferWidth,
|
|
BufferAlign + dx,
|
|
ulBufferWidth,
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
|
|
left,
|
|
right,
|
|
_pUh->_UH.bmShadowWidth,
|
|
bottom - top,
|
|
pOrder->BackColor.u.rgb);
|
|
}
|
|
else if ((_pUh->_UH.protocolBpp == 16) || (_pUh->_UH.protocolBpp == 15))
|
|
{
|
|
vSrcTranCopyS1D8_16(pjBuffer + dy * ulBufferWidth,
|
|
BufferAlign + dx,
|
|
ulBufferWidth,
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth * _pUh->_UH.copyMultiplier,
|
|
left,
|
|
right,
|
|
_pUh->_UH.bmShadowWidth,
|
|
bottom - top,
|
|
*((PDCUINT16)&(pOrder->BackColor)));
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
vSrcTranCopyS1D8(pjBuffer + dy * ulBufferWidth,
|
|
BufferAlign + dx,
|
|
ulBufferWidth,
|
|
_pUh->_UH.bmShadowBits + top * _pUh->_UH.bmShadowWidth,
|
|
left,
|
|
right,
|
|
_pUh->_UH.bmShadowWidth,
|
|
bottom - top,
|
|
pOrder->BackColor.u.index,
|
|
pOrder->ForeColor.u.index);
|
|
#ifdef DC_HICOLOR
|
|
}
|
|
#endif
|
|
}
|
|
} else {
|
|
if ((left > right) || (top > bottom)) {
|
|
TRC_NRM((TB, _T("Non-ordered glyph paint rect (%d, %d, %d, %d)."),
|
|
left, top, right, bottom));
|
|
} else if ((left == right) || (top == bottom)) {
|
|
TRC_NRM((TB, _T("Zero width/height glyph paint rect (%d, %d, %d, %d)."),
|
|
left, top, right, bottom));
|
|
} else {
|
|
TRC_ERR((TB, _T("Bad glyph paint rect (%d, %d, %d, %d)->(%d, %d)."),
|
|
left, top, right, bottom,
|
|
_pUh->_UH.bmShadowWidth, _pUh->_UH.bmShadowHeight));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif // defined(OS_WINCE) || defined(OS_WINNT)
|
|
{
|
|
#ifdef DC_HICOLOR
|
|
TRC_NRM((TB, _T("Slow glyph order w %d, h %d, fc %#06lx, bc %#06lx"),
|
|
ulBufferWidth, ulHeight, pOrder->ForeColor, pOrder->BackColor));
|
|
|
|
#endif
|
|
GHSlowOutputBuffer(pOrder, pjBuffer, BufferAlign, ulBufferWidth);
|
|
}
|
|
// Send the bitmap thru CLX
|
|
_pClx->CLX_ClxGlyphOut((UINT)(ulBufferWidth << 3),
|
|
(UINT)(pOrder->BkBottom - pOrder->BkTop), pjBuffer);
|
|
|
|
#ifdef DC_DEBUG
|
|
// In debug, hatch the output yellow if the option is turned on.
|
|
if (_pUh->_UH.hatchIndexPDUData) {
|
|
unsigned i;
|
|
|
|
for (i = 0; i < g_Fragment; i++)
|
|
_pUh->UH_HatchRect((int)(g_FragmentLeft[i]),
|
|
(int)pOrder->BkTop,
|
|
(int)(g_FragmentRight[i]),
|
|
(int)pOrder->BkBottom,
|
|
UH_RGB_YELLOW,
|
|
UH_BRUSHTYPE_FDIAGONAL);
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
// Post-process draw fringe rects.
|
|
/************************************************************************/
|
|
for (i = 0; i < crclFringe; i++) {
|
|
if (!PatBlt(_pUh->_UH.hdcDraw,
|
|
arclFringe[i].left,
|
|
arclFringe[i].top,
|
|
(int)(arclFringe[i].right - arclFringe[i].left),
|
|
(int)(arclFringe[i].bottom - arclFringe[i].top),
|
|
PATCOPY))
|
|
{
|
|
TRC_ERR((TB, _T("Glyph PatBlt failed")));
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* Free up any memory we may have allocated for the temp buffer */
|
|
/************************************************************************/
|
|
if (pjBuffer != szTextBuffer)
|
|
UT_Free( _pUt, pjBuffer);
|
|
|
|
|
|
/************************************************************************/
|
|
/* Let the clx have a look-see at the unicode text data */
|
|
/************************************************************************/
|
|
if ( _pUh->_UH.hdcDraw == _pUh->_UH.hdcOffscreenBitmap ) {
|
|
_pClx->CLX_ClxTextOut(ajUnicode, iGlyph, _pUh->_UH.hdcDraw,
|
|
pOrder->BkLeft, pOrder->BkRight, pOrder->BkTop, pOrder->BkBottom);
|
|
}
|
|
else {
|
|
_pClx->CLX_ClxTextOut(ajUnicode, iGlyph, NULL,
|
|
pOrder->BkLeft, pOrder->BkRight, pOrder->BkTop, pOrder->BkBottom);
|
|
}
|
|
hr = S_OK;
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|