📄 udbmffnt.c
字号:
/* udbmffnt.c - Bitmapped Monochrome Font (BMF) driver for UGL */
/* Copyright 2000 Wind River Systems, Inc. All Rights Reserved */
/*
modification history
--------------------
01g,20nov00,msr Fixed bug with drawing glyph from page that doesn't exist.
01f,10nov00,rfm Fixed pageZero reference
01e,10nov00,jlb Change INCLUDE_UGL_BMF_UNICODE to INCLUDE_UGL_UNICODE
01d,23oct00,msr Fixed fontFindFisrt()/Next() to be re-entrant.
01c,15sep00,rfm Fixed SPR #34479
01b,06sep00,rbp Modifications for refgen added.
01a,11feb00,rfm Created
*/
/*
DESCRIPTION
The Bitmapped Monochrome Font (BMF) driver is contained in this file.
NOMANUAL
*/
/* includes */
#define BUILD_DRIVER
#include <ugl/driver/font/udbmffnt.h>
#include <ugl/uglmem.h>
#include <string.h>
/* Local funtion prototypes */
UGL_LOCAL UGL_STATUS uglBMFFontDriverDestroy (UGL_FONT_DRIVER * pFontDriver);
UGL_LOCAL UGL_FONT * uglBMFFontCreate (UGL_FONT_DRIVER * pFontDriver,
UGL_FONT_DEF * pFontDefinition);
UGL_LOCAL UGL_STATUS uglBMFFontDestroy (UGL_FONT * pFont);
UGL_LOCAL UGL_SEARCH_ID uglBMFFontFindFirst (UGL_FONT_DRIVER * pFontDriver,
UGL_FONT_DESC * pFontDescriptor);
UGL_LOCAL UGL_STATUS uglBMFFontFindNext (UGL_FONT_DRIVER * pFontDriver,
UGL_FONT_DESC * pFontDescriptor,
UGL_SEARCH_ID searchId);
UGL_LOCAL UGL_STATUS uglBMFFontFindClose (UGL_FONT_DRIVER * pFontDriver,
UGL_SEARCH_ID searchId);
UGL_LOCAL UGL_STATUS uglBMFFontDriverInfo (UGL_FONT_DRIVER * pFontDriver,
UGL_INFO_REQ infoRequest,
void * pInfo);
UGL_LOCAL UGL_STATUS uglBMFFontMetricsGet (UGL_FONT * pFont,
UGL_FONT_METRICS * pFontMetrics);
UGL_LOCAL UGL_STATUS uglBMFFontRotationAngleSet (UGL_FONT * pFont,
UGL_ORD angle);
UGL_LOCAL UGL_STATUS uglBMFFontSizeSet (UGL_FONT * pFont,
UGL_SIZE size);
UGL_LOCAL UGL_STATUS uglBMFFontWeightSet (UGL_FONT * pFont,
UGL_SIZE weight);
UGL_LOCAL UGL_STATUS uglBMFTextDraw (UGL_GC * pGc, UGL_POS x, UGL_POS y,
UGL_SIZE length, const UGL_CHAR * text);
UGL_LOCAL UGL_STATUS uglBMFTextSizeGet (UGL_FONT * pFont, UGL_SIZE * pWidth,
UGL_SIZE * pHeight, UGL_SIZE length,
const UGL_CHAR *text);
#ifdef INCLUDE_UGL_UNICODE
UGL_LOCAL UGL_STATUS uglBMFTextDrawW (UGL_GC * pGc, UGL_POS x, UGL_POS y,
UGL_SIZE length, const UGL_WCHAR * text);
UGL_LOCAL UGL_STATUS uglBMFTextSizeGetW (UGL_FONT * pFont, UGL_SIZE * pWidth,
UGL_SIZE * pHeight, UGL_SIZE length,
const UGL_WCHAR *text);
#endif /* INCLUDE_UGL_UNICODE */
UGL_LOCAL UGL_GLYPH_CACHE_ELEMENT *
uglBMFGlyphCacheAlloc (UGL_FONT_DRIVER * pFontDriver,
void ** pPageElement);
UGL_LOCAL void uglBMFGlyphCacheFree(UGL_FONT_DRIVER * pFontDriver,
void ** pPageElement);
/* This global is declared in the UGL configuration file */
extern const UGL_BMF_FONT_DESC * uglBMFFontData[];
UGL_LOCAL UGL_BOOL uglBMFCacheConfig = UGL_FALSE;
/*******************************************************************************
* uglBMFFontDriverCreate - create the BMF font driver
*
* This function creates a BMF driver that interfaces with UGL font APIs.
*
* RETURNS: Identifier for the created font driver, if successful. Otherwise
* UGL_NULL when the driver cannot be created.
*
* SEE ALSO:
*
*/
UGL_FONT_DRIVER * uglBMFFontDriverCreate
(
UGL_UGI_DRIVER * pDriver
)
{
UGL_BMF_FONT_DRIVER * pBMFFontDriver = UGL_NULL;
UGL_FONT_DRIVER * pFontDriver = UGL_NULL;
UGL_SIZE numFonts;
/* Verify that fonts are available */
if (uglBMFFontData == UGL_NULL)
{
return(UGL_NULL);
}
/* Count the number of available fonts */
for(numFonts = 0; UGL_NULL != uglBMFFontData[numFonts]; numFonts++);
/* If there are no fonts available, return */
if (numFonts == 0)
{
return(UGL_NULL);
}
pBMFFontDriver =
(UGL_BMF_FONT_DRIVER *)UGL_CALLOC(1, sizeof(UGL_BMF_FONT_DRIVER));
if (UGL_NULL != pBMFFontDriver)
{
pFontDriver = (UGL_FONT_DRIVER *)pBMFFontDriver;
pFontDriver->fontCreate = uglBMFFontCreate;
pFontDriver->fontDestroy = uglBMFFontDestroy;
pFontDriver->fontDriverDestroy = uglBMFFontDriverDestroy;
pFontDriver->fontFindFirst = uglBMFFontFindFirst;
pFontDriver->fontFindNext = uglBMFFontFindNext;
pFontDriver->fontFindClose = uglBMFFontFindClose;
pFontDriver->fontDriverInfo = uglBMFFontDriverInfo;
pFontDriver->fontMetricsGet = uglBMFFontMetricsGet;
pFontDriver->fontRotationAngleSet = uglBMFFontRotationAngleSet;
pFontDriver->fontSizeSet = uglBMFFontSizeSet;
pFontDriver->fontWeightSet = uglBMFFontWeightSet;
pFontDriver->textDraw = uglBMFTextDraw;
pFontDriver->textSizeGet = uglBMFTextSizeGet;
#ifdef INCLUDE_UGL_UNICODE
pFontDriver->textDrawW = uglBMFTextDrawW;
pFontDriver->textSizeGetW = uglBMFTextSizeGetW;
#endif /* INCLUDE_UGL_UNICODE */
pFontDriver->pDriver = pDriver;
pBMFFontDriver->lockId = uglOSLockCreate ();
pBMFFontDriver->textOrigin = UGL_FONT_TEXT_BASELINE;
pBMFFontDriver->pFirstFont = UGL_NULL;
pBMFFontDriver->pLastFont = UGL_NULL;
pBMFFontDriver->glyphCacheSize = UGL_BMF_GLYPH_CACHE_SIZE_MAX;
pBMFFontDriver->glyphCachePoolId= UGL_DEFAULT_MEM_POOL_ID;
}
return ((UGL_FONT_DRIVER *)pBMFFontDriver);
}
/***************************************************************************
*
* uglBMFFontCreate - create a font
*
* NOMANUAL
*
*/
UGL_LOCAL UGL_FONT * uglBMFFontCreate
(
UGL_FONT_DRIVER * pFontDriver,
UGL_FONT_DEF * pFontDefinition
)
{
UGL_FONT * pFont = UGL_NULL;
UGL_BMF_FONT * pBMFFont;
UGL_BMF_FONT_DRIVER * pBMFFontDriver =
(UGL_BMF_FONT_DRIVER *)pFontDriver;
int i;
/* Make sure font hasn't all ready been created */
uglOSLock(pBMFFontDriver->lockId);
pBMFFont = pBMFFontDriver->pFirstFont;
if (UGL_NULL != pBMFFont)
{
for(pFont = (UGL_FONT *)pBMFFont; UGL_NULL != pFont;
pFont = (UGL_FONT *)pBMFFont = pBMFFont->pNextFont)
{
/* Find only an exact match */
if((pFontDefinition->structSize == sizeof(UGL_FONT_DEF))
&& (pFontDefinition->pixelSize == pBMFFont->pBMFFontDesc->header.pixelSize.min)
&& (pFontDefinition->weight == pBMFFont->pBMFFontDesc->header.weight.min)
&& (pFontDefinition->italic == pBMFFont->pBMFFontDesc->header.italic)
&& (pFontDefinition->charSet == pBMFFont->pBMFFontDesc->header.charSet)
&& !strncmp(pFontDefinition->faceName,
pBMFFont->pBMFFontDesc->header.faceName,
UGL_FONT_FACE_NAME_MAX_LENGTH - 1)
&& !strncmp(pFontDefinition->familyName,
pBMFFont->pBMFFontDesc->header.familyName,
UGL_FONT_FAMILY_NAME_MAX_LENGTH - 1))
{
pBMFFont = (UGL_BMF_FONT *)pFont;
pBMFFont->referenceCount++;
uglOSUnlock(pBMFFontDriver->lockId);
return((UGL_FONT *)pBMFFont);
}
}
}
/* Hasn't been created yet, need to create it */
pBMFFont = (UGL_BMF_FONT *)UGL_CALLOC(1, sizeof(UGL_BMF_FONT));
if (UGL_NULL != pBMFFont)
{
int pageIndex = 0;
pFont = (UGL_FONT *)pBMFFont;
/* Look at each font in the uglBMFFontData array to find a match */
for(i = 0; UGL_NULL != uglBMFFontData[i]; i++)
{
/* Find only an exact match */
if (pFontDefinition->structSize == sizeof(UGL_FONT_DEF)
&& uglBMFFontData[i]->header.pixelSize.min ==
pFontDefinition->pixelSize
&& uglBMFFontData[i]->header.weight.min ==
pFontDefinition->weight
&& uglBMFFontData[i]->header.italic ==
pFontDefinition->italic
&& uglBMFFontData[i]->header.charSet ==
pFontDefinition->charSet
&& !strncmp(uglBMFFontData[i]->header.faceName,
pFontDefinition->faceName,
UGL_FONT_FACE_NAME_MAX_LENGTH - 1)
&& !strncmp(uglBMFFontData[i]->header.familyName,
pFontDefinition->familyName,
UGL_FONT_FAMILY_NAME_MAX_LENGTH - 1))
{
pBMFFont->pBMFFontDesc = uglBMFFontData[i];
pFont->pFontDriver = pFontDriver;
pBMFFont->referenceCount = 1;
#ifdef INCLUDE_UGL_UNICODE
/*
------
|----->| |
| ------
------ | | |
| | ---------- ------
------ ...
| | ------
------ | |
... ------
------ pageZero
| |
------
pageTable
A "page" and a "pageTable" are both arrays of 256
void pointers. Thus, you can have up to 256 glyphs per
page (each glyph in a page is pointed to by an entry in
the page) and up to 256 pages (each page is
pointed to by an entry in the pageTable).
*/
pBMFFont->pageTable[0] = &pBMFFont->pageZero;
#endif /* INCLUDE_UGL_UNICODE */
/* Map each glyph in each page */
while (UGL_NULL != uglBMFFontData[i]->pageData[pageIndex])
{
/* Get the pointer to the page */
const UGL_UINT8 *pageData =
uglBMFFontData[i]->pageData[pageIndex];
UGL_FOREVER
{
UGL_UINT32 size = 0;
int page;
int offset;
/* page and pageIndex do not have to
be equal. pageIndex is simply the index
into the pageData array, while page
could be discontinuous between pages.
For example, a pageIndex of 1 could
actually coorespond to data from page
100. */
page = *(pageData++);
/* offset = encoding */
offset = *(pageData++);
/* Read size of glyph data */
size = *(pageData++) << 8;
size += *pageData;
/* Test for end of data */
if (size == 0)
break;
/* Save the glyph location. */
#ifdef INCLUDE_UGL_UNICODE
/* Allocate the page if it isn't allocated yet.
Make sure the proper entry in the page table
points to the newly created page */
if (UGL_NULL == pBMFFont->pageTable[page])
{
pBMFFont->pageTable[page] =
(UGL_FONT_PAGE *)UGL_CALLOC(1, sizeof(UGL_FONT_PAGE));
}
/* Point the entry in the page cooresponding
to the offset (ie. encoding) at the glyph data
(The glyph data is not cached. It could still
be in ROM) */
if (UGL_NULL != pBMFFont->pageTable[page])
{
(*pBMFFont->pageTable[page])[offset] =
(UGL_UINT8 *) pageData;
}
#else /* INCLUDE_UGL_UNICODE */
/* Non-Unicode data only requires page zero,
thus, no page table is necessary. */
if (page == 0)
{
pBMFFont->pageZero[offset] = (UGL_UINT8 *)pageData;
}
#endif /* INCLUDE_UGL_UNICODE */
/* Advance pageData to the next glyph */
pageData += size;
}
/* Advance pageIndex to point at the next array of
glyphs */
pageIndex++;
}
/* Add the newly font to the list of available fonts */
if (pBMFFontDriver->pFirstFont)
{
/* Append it to the end of the list */
pBMFFont->pPrevFont = pBMFFontDriver->pLastFont;
pBMFFontDriver->pLastFont->pNextFont = pBMFFont;
pBMFFontDriver->pLastFont = pBMFFont;
}
else
{
pBMFFontDriver->pFirstFont =
pBMFFontDriver->pLastFont = pBMFFont;
}
uglOSUnlock(pBMFFontDriver->lockId);
return((UGL_FONT *)pBMFFont);
}
}
}
uglOSUnlock(pBMFFontDriver->lockId);
return(UGL_NULL);
}
/***************************************************************************
*
* uglBMFFontDestroy - destroy a font
*
* NOMANUAL
*
*/
UGL_LOCAL UGL_STATUS uglBMFFontDestroy
(
UGL_FONT * pFont
)
{
UGL_BMF_FONT_DRIVER * pBMFFontDriver =
(UGL_BMF_FONT_DRIVER *)pFont->pFontDriver;
UGL_BMF_FONT * pBMFFont = (UGL_BMF_FONT *)pFont;
UGL_STATUS status = UGL_STATUS_OK;
/* If the font has been created more than once, simply decrement
the referenceCount variable and return */
uglOSLock(pBMFFontDriver->lockId);
if (pBMFFont->referenceCount > 1)
{
pBMFFont->referenceCount--;
}
/* Only one instance of the font, so it has to be "removed" */
else
{
/* Find the font in the list of fonts and remove it */
if (pBMFFont == pBMFFontDriver->pFirstFont)
{
pBMFFontDriver->pFirstFont = pBMFFont->pNextFont;
if (UGL_NULL != pBMFFontDriver->pFirstFont)
{
pBMFFontDriver->pFirstFont->pPrevFont = UGL_NULL;
}
}
else if (pBMFFont == pBMFFontDriver->pLastFont)
{
pBMFFontDriver->pLastFont = pBMFFont->pPrevFont;
if (UGL_NULL != pBMFFontDriver->pLastFont)
{
pBMFFontDriver->pLastFont->pNextFont = UGL_NULL;
}
}
else
{
UGL_BMF_FONT * pBMFFont = pBMFFontDriver->pFirstFont;
while (UGL_NULL != pBMFFont &&
pBMFFont->pNextFont != (UGL_BMF_FONT *)pFont)
{
pBMFFont = pBMFFont->pNextFont;
}
if (UGL_NULL != pBMFFont)
{
pBMFFont->pNextFont = ((UGL_BMF_FONT *)pFont)->pNextFont;
if (UGL_NULL != pBMFFont->pNextFont)
{
pBMFFont->pNextFont->pPrevFont = pBMFFont;
}
}
else
{
status = UGL_STATUS_ERROR;
}
}
/* Free up the glyph cache entrys */
if (UGL_STATUS_OK == status)
{
#ifdef INCLUDE_UGL_UNICODE
int i;
for (i = 0; i < 256; i++)
if (pBMFFont->pageTable[i])
{
int j;
for (j = 0; j < 256; j++)
{
void ** ppPageData = &(*pBMFFont->pageTable[i])[j];
/* Make sure element is in cache first */
if (*ppPageData && 0 == *(UGL_UINT8 *)*ppPageData)
uglBMFGlyphCacheFree((UGL_FONT_DRIVER *)pBMFFontDriver,
ppPageData);
}
}
#else /*INCLUDE_UGL_UNICODE */
int j;
for (j = 0; j < 256; j++)
{
void ** ppPageData = &pBMFFont->pageZero[j];
if (*ppPageData && 0 == *(UGL_UINT8 *)*ppPageData)
uglBMFGlyphCacheFree((UGL_FONT_DRIVER *)pBMFFontDriver,
ppPageData);
}
#endif /*INCLUDE_UGL_UNICODE */
UGL_FREE(pFont);
pFont = UGL_NULL;
}
}
uglOSUnlock(pBMFFontDriver->lockId);
return(status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -