📄 udbmffnt.c
字号:
UGL_BMF_FONT *pBMFFont = (UGL_BMF_FONT *)pFont;
int textWidth = 0;
void ** ppPageZero = pBMFFont->pageZero;
UGL_UINT8 *pGlyphData;
int i;
/* Check for null text */
if (text == UGL_NULL || text[0] == 0)
return (UGL_STATUS_ERROR);
/* Set a large text length, if -1 is specified */
if (length <= 0)
length = 0x0fff;
/* Compute the text width */
if (UGL_NULL != pWidth)
{
for (i = 0; UGL_NULL != *text && i < length; i++)
{
pGlyphData = (UGL_UINT8 *)ppPageZero[(UGL_UINT8)*(text++)];
if (UGL_NULL != pGlyphData)
{
textWidth += pGlyphData[1];
}
}
*pWidth = textWidth;
}
/* Compute the text height */
if (UGL_NULL != pHeight)
{
*pHeight = pBMFFont->pBMFFontDesc->maxAscent +
pBMFFont->pBMFFontDesc->maxDescent;
}
return (UGL_STATUS_OK);
}
#ifdef INCLUDE_UGL_UNICODE
/***************************************************************************
*
* uglBMFTextDrawW - draw double-wide text
*
* NOMANUAL
*
*/
UGL_LOCAL UGL_STATUS uglBMFTextDrawW
(
UGL_GC * pGc,
UGL_POS x,
UGL_POS y,
UGL_SIZE length,
const UGL_WCHAR * text
)
{
UGL_UGI_DRIVER * pDriver = pGc->pDriver;
UGL_BMF_FONT * pBMFFont = (UGL_BMF_FONT *)pGc->pFont;
UGL_BMF_FONT_DRIVER * pBMFFontDriver =
(UGL_BMF_FONT_DRIVER *)pBMFFont->header.pFontDriver;
UGL_FONT_DRIVER * pFontDriver =
(UGL_FONT_DRIVER *)pBMFFont->header.pFontDriver;
UGL_GLYPH_CACHE_ELEMENT *pCacheElement;
UGL_FONT_PAGE ** ppPageTable = pBMFFont->pageTable;
UGL_FONT_PAGE * pPageZero = ppPageTable[0];
UGL_FONT_PAGE * pPage;
void ** ppPageElement;
UGL_SIZE maxAscent = pBMFFont->pBMFFontDesc->maxAscent;
UGL_STATUS status = UGL_STATUS_OK;
UGL_COLOR saveColor;
UGL_POINT point;
int i;
/* Make sure the font and text are valid */
if (pBMFFont == UGL_NULL || text == UGL_NULL || text[0] == 0)
return (UGL_STATUS_ERROR);
/* Set a large text length, if -1 is specified */
if (length <= 0)
length = 0x0fff;
/* Draw the text background */
if (pGc->backgroundColor != UGL_COLOR_TRANSPARENT)
{
UGL_SIZE width, height;
UGL_RECT rect;
UGL_POS tmpY;
(*pFontDriver->textSizeGetW)(pGc->pFont, &width, &height, length, text);
if(pBMFFontDriver->textOrigin == UGL_FONT_TEXT_UPPER_LEFT)
{
rect.right = x + width - 1;
rect.bottom = y + height - 1;
rect.left = x;
rect.top = y;
}
else if(pBMFFontDriver->textOrigin == UGL_FONT_TEXT_BASELINE)
{
tmpY = y - maxAscent;
rect.right = x + width - 1;
rect.bottom = tmpY + height - 1;
rect.left = x;
rect.top = tmpY;
}
else
return(UGL_STATUS_ERROR);
saveColor = pGc->foregroundColor;
pGc->foregroundColor = UGL_COLOR_TRANSPARENT;
pGc->changed |= UGL_GC_FOREGROUND_COLOR_CHANGED;
UGL_GC_CHANGED_SET(pGc);
UGL_GC_SET(pDriver, pGc);
(*pDriver->rectangle)(pDriver, &rect);
pGc->foregroundColor = saveColor;
pGc->changed |= UGL_GC_FOREGROUND_COLOR_CHANGED;
UGL_GC_CHANGED_SET(pGc);
UGL_GC_SET(pDriver, pGc);
}
saveColor = pGc->backgroundColor;
pGc->backgroundColor = UGL_COLOR_TRANSPARENT;
pGc->changed |= UGL_GC_BACKGROUND_COLOR_CHANGED;
UGL_GC_CHANGED_SET(pGc);
UGL_GC_SET(pDriver, pGc);
/* Blit each character to the screen */
for (i = 0; UGL_NULL != *text && i < length; i++ )
{
pPage = ppPageTable[((UGL_UINT16)*text) >> 8];
/* Find page */
if (UGL_NULL == pPage)
{
ppPageElement = (void**) &(*pPageZero)[0];
}
else
{
ppPageElement = (void**) &(*pPage)[*text & 0xFF];
}
text++;
pCacheElement = (UGL_GLYPH_CACHE_ELEMENT *)*ppPageElement;
/* If encoding doesn't map to a glyph, don't do anything */
if (UGL_NULL == pCacheElement)
{
continue;
}
/* Check to see if glyph is in cache or not */
if (UGL_BMF_GLYPH_IN_CACHE != pCacheElement->cacheFlag)
{
pCacheElement = uglBMFGlyphCacheAlloc(pFontDriver, ppPageElement);
if (UGL_NULL == pCacheElement)
{
status = UGL_STATUS_ERROR;
break;
}
}
/* Blit glyph to the screen */
if(pBMFFontDriver->textOrigin == UGL_FONT_TEXT_UPPER_LEFT)
{
point.x = x;
point.y = y + maxAscent - (UGL_POS)pCacheElement->ascent;
(*pDriver->monoBitmapBlt)(pDriver, pCacheElement->bitmapID,
&pCacheElement->bitmapRect,
UGL_DEFAULT_ID, &point);
x += pCacheElement->width;
}
else if(pBMFFontDriver->textOrigin == UGL_FONT_TEXT_BASELINE)
{
point.x = x;
point.y = y - (UGL_POS)pCacheElement->ascent;
(*pDriver->monoBitmapBlt)(pDriver, pCacheElement->bitmapID,
&pCacheElement->bitmapRect,
UGL_DEFAULT_ID, &point);
x += pCacheElement->width;
}
else
{
status = UGL_STATUS_ERROR;
break;
}
}
pGc->backgroundColor = saveColor;
pGc->changed |= UGL_GC_BACKGROUND_COLOR_CHANGED;
UGL_GC_CHANGED_SET(pGc);
UGL_GC_SET(pDriver, pGc);
return (status);
}
/***************************************************************************
*
* uglBMFTextSizeGetW - get the width of double-byte text
*
* NOMANUAL
*
*/
UGL_LOCAL UGL_STATUS uglBMFTextSizeGetW
(
UGL_FONT * pFont,
UGL_SIZE * pWidth,
UGL_SIZE * pHeight,
UGL_SIZE length,
const UGL_WCHAR *text
)
{
UGL_BMF_FONT * pBMFFont = (UGL_BMF_FONT *)pFont;
UGL_FONT_PAGE **ppPageTable = pBMFFont->pageTable;
UGL_FONT_PAGE *pPageZero = ppPageTable[0];
UGL_FONT_PAGE *pPage;
UGL_UINT8 *pGlyphData;
int textWidth = 0;
int i;
/* Check for null text */
if (text == UGL_NULL || text[0] == 0)
return (UGL_STATUS_ERROR);
/* Set a large text length, if -1 is specified */
if (length <= 0)
length = 0x0fff;
/* Compute the text width */
if (UGL_NULL != pWidth)
{
for (i = 0; UGL_NULL != *text && i < length; i++)
{
pPage = ppPageTable[((UGL_UINT16)*text) >> 8];
if (UGL_NULL == pPage)
{
pGlyphData = (UGL_UINT8 *)(*pPageZero)[0];
}
else
{
pGlyphData = (UGL_UINT8 *)(*pPage)[*text & 0xFF];
}
text++;
if (UGL_NULL != pGlyphData)
{
textWidth += pGlyphData[1];
}
}
*pWidth = textWidth;
}
/* Compute the text height */
if (UGL_NULL != pHeight)
{
*pHeight = pBMFFont->pBMFFontDesc->maxAscent +
pBMFFont->pBMFFontDesc->maxDescent;
}
return (UGL_STATUS_OK);
}
#endif /* INCLUDE_UGL_UNICODE */
/*******************************************************************************
*
* uglBMFGlyphCacheAlloc
*
* NOMANUAL
*
*/
UGL_LOCAL UGL_GLYPH_CACHE_ELEMENT * uglBMFGlyphCacheAlloc
(
UGL_FONT_DRIVER * pFontDriver,
void ** ppPageElement
)
{
UGL_BMF_FONT_DRIVER *pBMFFontDriver = (UGL_BMF_FONT_DRIVER *)pFontDriver;
UGL_UGI_DRIVER * pDriver = pFontDriver->pDriver;
UGL_GLYPH_CACHE_ELEMENT * pCacheElement;
UGL_MDIB mDib;
UGL_MEM_POOL_ID glyphCachePoolId = pBMFFontDriver->glyphCachePoolId;
UGL_UINT8 *pGlyphData = (UGL_UINT8 *)*ppPageElement;
if (pBMFFontDriver->glyphCacheSize >= 0 &&
pBMFFontDriver->numCachedGlyphs >= pBMFFontDriver->glyphCacheSize)
{
uglBMFGlyphCacheFree(pFontDriver,
pBMFFontDriver->pLastCacheElement->ppPageElement);
}
/* Allocate new element */
pCacheElement =
(UGL_GLYPH_CACHE_ELEMENT *)uglMemCalloc(glyphCachePoolId, 1,
sizeof(UGL_GLYPH_CACHE_ELEMENT));
if(pCacheElement == UGL_NULL)
{
int i = 0;
/* Make sure there is enough room in cache for new element */
while(pCacheElement == UGL_NULL)
{
uglBMFGlyphCacheFree(pFontDriver,
pBMFFontDriver->pLastCacheElement->ppPageElement);
pCacheElement =
(UGL_GLYPH_CACHE_ELEMENT *)uglMemCalloc(glyphCachePoolId, 1,
sizeof(UGL_GLYPH_CACHE_ELEMENT));
/* something to prevent endless loops */
if(pCacheElement == UGL_NULL && i++ > 1000)
return(UGL_NULL);
}
}
pCacheElement->pGlyphData = pGlyphData;
pCacheElement->ppPageElement = ppPageElement;
pCacheElement->width = pGlyphData[1];
pCacheElement->height = pGlyphData[2];
pCacheElement->ascent = pGlyphData[3];
pCacheElement->bitmapRect.left = 0;
pCacheElement->bitmapRect.top = 0;
pCacheElement->bitmapRect.right = pCacheElement->width - 1;
pCacheElement->bitmapRect.bottom = pCacheElement->height - 1;
mDib.width = (UGL_SIZE)pCacheElement->width;
mDib.height = (UGL_SIZE)pCacheElement->height;
mDib.stride = (UGL_SIZE)pCacheElement->width;
mDib.pImage = &pGlyphData[4];
pCacheElement->bitmapID = (*pDriver->monoBitmapCreate) (pDriver,
&mDib,
UGL_DIB_INIT_DATA,
0,
glyphCachePoolId);
if (pCacheElement->bitmapID == UGL_NULL)
{
/* Make sure enough room in cache for the bitmap */
while(pCacheElement->bitmapID == UGL_NULL)
{
int i = 0;
uglBMFGlyphCacheFree(pFontDriver,
pBMFFontDriver->pLastCacheElement->ppPageElement);
pCacheElement->bitmapID = (*pDriver->monoBitmapCreate) (pDriver,
&mDib,
UGL_DIB_INIT_DATA,
0,
glyphCachePoolId);
/* something to prevent endless loops */
if(pCacheElement->bitmapID == UGL_NULL && i++ > 100)
{
uglMemFree(pCacheElement);
return(UGL_NULL);
}
}
}
/* Add element to the list */
pCacheElement->pNext = pBMFFontDriver->pFirstCacheElement;
/* If a first element exists, link it to the new first element before
replacing the first element with the new cache element. */
if (UGL_NULL != pBMFFontDriver->pFirstCacheElement)
{
pBMFFontDriver->pFirstCacheElement->pPrev = pCacheElement;
}
pBMFFontDriver->pFirstCacheElement = pCacheElement;
/* update last cache element */
if (UGL_NULL == pBMFFontDriver->pLastCacheElement)
{
pBMFFontDriver->pLastCacheElement = pCacheElement;
}
/* Point the entry in the page to the cacheElement */
*ppPageElement = pCacheElement;
pBMFFontDriver->numCachedGlyphs++;
return (pCacheElement);
}
/*******************************************************************************
*
* uglBMFGlyphCacheFree
*
* NOMANUAL
*
*/
UGL_LOCAL void uglBMFGlyphCacheFree
(
UGL_FONT_DRIVER * pFontDriver,
void ** ppPageElement
)
{
UGL_BMF_FONT_DRIVER * pBMFFontDriver = (UGL_BMF_FONT_DRIVER *)pFontDriver;
UGL_GLYPH_CACHE_ELEMENT *pCacheElement =
(UGL_GLYPH_CACHE_ELEMENT *)*ppPageElement;
UGL_UGI_DRIVER * pDriver = pFontDriver->pDriver;
/* remove link to predecessor */
if (UGL_NULL != pCacheElement->pPrev)
{
pCacheElement->pPrev->pNext = pCacheElement->pNext;
}
/* no prev indicates element is head of list, make next element head */
else
{
pBMFFontDriver->pFirstCacheElement = pCacheElement->pNext;
}
/* remove link to sucessor */
if (UGL_NULL != pCacheElement->pNext)
{
pCacheElement->pNext->pPrev = pCacheElement->pPrev;
}
/* no next indicates element is tail of list, make prev new tail */
else
{
pBMFFontDriver->pLastCacheElement = pCacheElement->pPrev;
}
if (UGL_NULL != pCacheElement->bitmapID)
{
(*pDriver->monoBitmapDestroy)(pDriver, pCacheElement->bitmapID);
}
if (UGL_NULL != pCacheElement)
{
*ppPageElement = pCacheElement->pGlyphData;
pBMFFontDriver->numCachedGlyphs--;
uglMemFree(pCacheElement);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -