|
|
Microsoft Windows NT Build 297 06-28-1992
/******************************************************************************\
*
* MODULE: PAINT.C
*
* PURPOSE: Given an HDC and a pointer to a bounding rectangle
* draw all graphics/fonts based on the flags set in
* the dwGraphicsOptions global variable.
*
* FUNTIONS: Paint() - main painting routine
* GetFirstGraphicSlot() - computes bounding rect of 1st
* graphic
* GetNextGraphicSlot() - computes bounding rect of next
* graphic
* DrawFonts() - draws enumerated fonts
* BuildFontList() - builds a list of fonts of fonts
* supported by a given DC
* MyEnumFaces() - enumerates the font facenames
* supported by a given DC
* MyEnumCopy() - copies LOGFONT & TEXTMETRIC info
* to a global variable
* MyEnumCount() - counts total number of fonts
* supported by a given DC
* FreeFontList() - frees a (BuildFontList-) font list
*
* COMMENTS: Most of the font-enumeration code "lifted" from NTF.EXE
* sample. For more complete documentation have a look a
* that.
*
\******************************************************************************/
#include <windows.h>
#include <string.h>
#include "lookup.h"
#include "paint.h"
#include "vars.h"
/******************************************************************************\
*
* FUNCTION: Paint
*
* INPUTS: hdc - device context to paint
* lpR - bounding rectangle of device to paint
*
* RETURNS: TRUE if painting went ok, or
* FALSE if error while painting
*
* GLOBAL VARS: dwGraphicsOptions - current graphics options
*
* LOCAL VARS: ri - a scratch rectangle with integer elements
*
\******************************************************************************/
BOOL Paint (HDC hdc, LPRECT lpR)
{
RECTI ri;
if (dwGraphicsOptions & ENUMFONTS)
{
DrawFonts (hdc, lpR);
return TRUE;
}
iDeltaX = (int) ((lpR->right - BORDER)/NUM_GRAPHICS_XSLOTS);
iDeltaY = (int) ((lpR->bottom- BORDER)/NUM_GRAPHICS_YSLOTS);
GetFirstGraphicSlot (&ri);
if (dwGraphicsOptions & ARC)
{
Arc (hdc, ri.left, ri.top, ri.right, ri.bottom,
ri.left, ri.top, ri.right-10, ri.bottom-10);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & ELLIPSE)
{
SelectObject (hdc, GetStockObject (DKGRAY_BRUSH));
Ellipse (hdc, ri.left, ri.top, ri.right, ri.bottom);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & LINETO)
{
int i;
for (i = PS_SOLID; i <= PS_DASHDOTDOT; i++)
{
HPEN hpenSave;
HPEN hpen = CreatePen (i, i+1, RGB(0,0,0));
hpenSave = SelectObject (hdc, hpen);
MoveToEx (hdc, ri.left, ri.top + (i+1)*iDeltaY/7, NULL);
LineTo (hdc, ri.right, ri.top + (i+1)*iDeltaY/7);
SelectObject (hdc, hpenSave);
DeleteObject (hpen);
}
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & PIE)
{
SelectObject (hdc, GetStockObject (LTGRAY_BRUSH));
Pie (hdc, ri.left, ri.top, ri.right, ri.bottom,
ri.left, ri.top, ri.right-10, ri.bottom-10);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & POLYBEZIER)
{
POINT ap[4];
ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
PolyBezier (hdc, ap, 4);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & POLYGON)
{
POINT ap[5];
ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
ap[1].x = (LONG) ri.right; ap[1].y = (LONG) ri.bottom;
ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
ap[3].x = (LONG) ri.left; ap[3].y = (LONG) ri.bottom;
ap[4].x = (LONG) ri.left; ap[4].y = (LONG) ri.top;
SelectObject (hdc, GetStockObject (BLACK_BRUSH));
Polygon (hdc, ap, 4);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & POLYLINE)
{
POINT ap[4];
ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
Polyline (hdc, ap, 4);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & POLYPOLYGON)
{
POINT ap[8];
int ai[2] = { 4, 4 };
ap[0].x = (LONG) ri.left;
ap[0].y = (LONG) ri.top;
ap[1].x = (LONG) (ri.left + iDeltaX/4);
ap[1].y = (LONG) ri.top;
ap[2].x = (LONG) (ri.left + iDeltaX/4);
ap[2].y = (LONG) (ri.top + iDeltaY/4);
ap[3].x = (LONG) ri.left;
ap[3].y = (LONG) (ri.top + iDeltaY/4);
ap[4].x = (LONG) (ri.right - 2*iDeltaX/3);
ap[4].y = (LONG) (ri.bottom - 2*iDeltaY/3);
ap[5].x = (LONG) ri.right;
ap[5].y = (LONG) (ri.bottom - 2*iDeltaY/3);
ap[6].x = (LONG) ri.right;
ap[6].y = (LONG) ri.bottom;
ap[7].x = (LONG) (ri.right - 2*iDeltaX/3);
ap[7].y = (LONG) ri.bottom;
SelectObject (hdc, GetStockObject (BLACK_BRUSH));
PolyPolygon (hdc, ap, ai, 2);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & RECTANGLE)
{
SelectObject (hdc, GetStockObject (LTGRAY_BRUSH));
Rectangle (hdc, ri.left, ri.top, ri.right, ri.bottom);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & ROUNDRECT)
{
SelectObject (hdc, GetStockObject (DKGRAY_BRUSH));
RoundRect (hdc, ri.left, ri.top, ri.right, ri.bottom, 12, 19);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & STRETCH_BLT)
{
HBITMAP hbm;
BITMAP bm;
HDC hdcMem;
hbm = LoadBitmap (hInst, "printer");
hdcMem = CreateCompatibleDC (hdc);
SelectObject (hdcMem, hbm);
SetMapMode (hdcMem, GetMapMode(hdc));
GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
StretchBlt (hdc, ri.left, ri.top, ri.right-ri.left,
ri.bottom - ri.top, hdcMem, 0, 0,
bm.bmWidth, bm.bmHeight, SRCCOPY);
DeleteDC(hdcMem);
GetNextGraphicSlot (&ri);
}
if (dwGraphicsOptions & TEXTOUT)
{
TextOut (hdc, ri.left, ri.top + iDeltaY/2, "TextOut", 7);
GetNextGraphicSlot (&ri);
}
return TRUE;
}
/******************************************************************************\
*
* FUNCTION: GetFirstGraphicSlot
*
* INPUTS: pri - pointer to a RECTI
*
* GLOBAL VARS: column - current grpahics column/slot
* iDeltax - width of grahics slots
* iDeltaY - height of grahics slots
*
\******************************************************************************/
void GetFirstGraphicSlot (PRECTI pri)
{
pri->left = BORDER;
pri->top = BORDER;
pri->right = iDeltaX;
pri->bottom = iDeltaY;
column = 1;
}
/******************************************************************************\
*
* FUNCTION: GetNextGraphicSlot
*
* INPUTS: pri - pointer to a RECTI
*
* GLOBAL VARS: column - current grpahics column/slot
* iDeltax - width of grahics slots
* iDeltaY - height of grahics slots
*
\******************************************************************************/
void GetNextGraphicSlot (PRECTI pri)
{
if (++column <= NUM_GRAPHICS_XSLOTS)
{
pri->left += iDeltaX;
pri->right += iDeltaX;
}
else
{
column = 1;
pri->left = BORDER;
pri->top += iDeltaY;
pri->right = iDeltaX;
pri->bottom += iDeltaY;
}
}
/******************************************************************************\
*
* FUNCTION: DrawFonts
*
* LOCAL VARS: i, j - loop variables
* xText - starting x position to draw text
* yText - starting y position to draw text
* iMaxStrLen - length in pels of string to draw
*
\******************************************************************************/
void DrawFonts (HDC hdc, LPRECT lpR)
{
int i, j, xText, yText, iMaxStrLen = 0;
PARFONTS paf;
paf = BuildFontList (hdc);
xText = yText = 2;
for (i = 0; i < nFaces; i++)
{
for (j = 0; j < (paf + i)->nFonts; j++)
{
HFONT hFont, hSaveFont;
SIZE size;
TEXTMETRIC *pNextTM;
POINT LogPtBtmRt;
LogPtBtmRt.x = lpR->right;
LogPtBtmRt.y = lpR->bottom;
if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
LogPtBtmRt.y += TOOLBARHEIGHT;
DPtoLP (hdc, &LogPtBtmRt, 1);
hFont = CreateFontIndirect ((paf + i)->lf + j);
hSaveFont = SelectObject (hdc, hFont);
TextOut (hdc, xText, yText, ((paf + i)->lf + j)->lfFaceName,
strlen(((paf + i)->lf + j)->lfFaceName));
GetTextExtentPoint (hdc, ((paf + i)->lf + j)->lfFaceName,
strlen(((paf+i)->lf+j)->lfFaceName),
&size);
size.cx += 2;
iMaxStrLen = iMaxStrLen > (int)size.cx ? iMaxStrLen:
(int) size.cx;
if (!(i == (nFaces - 1) && j == ((paf + i)->nFonts - 1)))
{
pNextTM = j < ((paf+i)->nFonts-1) ?
(paf+i)->tm+j+1 : (paf+i+1)->tm;
if ((yText += (int) ((paf + i)->tm + j)->tmHeight) +
(int) pNextTM->tmHeight > (int) LogPtBtmRt.y)
{
yText = 2;
xText += iMaxStrLen + 2;
iMaxStrLen = 0;
}
}
SelectObject (hdc, hSaveFont);
DeleteObject (hFont);
if (xText > (int) LogPtBtmRt.x)
{
if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
{
/********************************************************************\
* If we're drawing to the screen & have run out of
* room then tell user how many fonts there are left
* (that we haven't displayed
\********************************************************************/
int k;
int iFontsLeft = (paf + i)->nFonts - j - 1;
char buf[40];
SIZE size;
for (k = i + 1; k < nFaces; k++)
iFontsLeft += (paf + k)->nFonts;
wsprintf (buf, "%ld more display fonts (not listed)",
iFontsLeft);
GetTextExtentPoint (hdc, buf, strlen(buf), &size);
TextOut (hdc, lpR->right - size.cx, lpR->bottom - size.cy,
buf, strlen(buf));
goto done_enumfonts;
}
else
{
/********************************************************************\
* Else we're drawing to a printer & have filled up
* the first page. If there's any fonts left to draw
* then start a new page.
\********************************************************************/
if (!(i == nFaces - 1 && j == (paf + i)->nFonts - 1))
{ EndPage (hdc);
xText = yText = 2;
StartPage (hdc);
}
}
}
}
}
done_enumfonts:
FreeFontList (paf);
}
/* In the callback functions from the enumerations, there is a limited
* ability to pass in parameters. For that reason, declare the following
* global variables to be used by any of the call back functions.
*
* HDC hdcGlobal;
* PARFONTS parFontsGlobal;
* int iFace,jFont;
* int nFaces;
*
*
* General call structure:
*
* BuildFontList()
* EnumFonts
* MyEnumCount()
* LocalAlloc
* EnumFonts
* MyEnumFaces()
* EnumFonts
* MyEnumCount()
* LocalAlloc
* LocalAlloc
* LocalAlloc
* EnumFonts
* MyEnumCopy()
*/
/******************************************************************************\
*
* FUNCTION: BuildFontList
*
* GLOBAL VARS: (see above)
*
\******************************************************************************/
PARFONTS BuildFontList (HDC hdcIn)
{
nFaces = 0;
hdcGlobal = hdcIn;
/****************************************************************************\
* count the total number of face names.
\****************************************************************************/
EnumFonts (hdcGlobal, NULL, (PROC)MyEnumCount, (LPARAM)&nFaces);
/****************************************************************************\
* allocate the pointer to the array of PArFont structures.
\****************************************************************************/
parFontsGlobal = LocalAlloc (LPTR, sizeof(ARFONTS) * (nFaces+1));
/****************************************************************************\
* step through all fonts again. For each one fill a LOGFONT and
* a TEXTMETRIC stucture.
\****************************************************************************/
iFace = 0;
EnumFonts (hdcGlobal, NULL, (PROC)MyEnumFaces, NULL);
return parFontsGlobal;
}
/******************************************************************************\
*
* FUNCTION: MyEnumFaces
*
* GLOBAL VARS: (see above)
*
\******************************************************************************/
int APIENTRY MyEnumFaces (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
DWORD fFontType, LPVOID lpData)
{
int nFonts;
nFonts = 0;
EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (PROC)MyEnumCount,
(LPARAM)&nFonts);
parFontsGlobal[iFace].lf = LocalAlloc (LPTR,
sizeof(LOGFONT) * nFonts);
parFontsGlobal[iFace].tm = LocalAlloc (LPTR,
sizeof(TEXTMETRIC) * nFonts);
parFontsGlobal[iFace].Type = LocalAlloc (LPTR,
sizeof(int) * nFonts);
if ((parFontsGlobal[iFace].lf == NULL) ||
(parFontsGlobal[iFace].tm == NULL) ||
(parFontsGlobal[iFace].Type == NULL)) {
MessageBox (NULL, "alloc failed", "HEY!", MB_ICONSTOP | MB_OK);
return FALSE;
}
parFontsGlobal[iFace].nFonts = nFonts;
jFont = 0;
EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (PROC)MyEnumCopy, NULL);
iFace++;
return TRUE;
}
/******************************************************************************\
*
* FUNCTION: MyEnumCopy
*
* GLOBAL VARS: (see above)
*
\******************************************************************************/
int APIENTRY MyEnumCopy (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
DWORD fFontType, LPVOID lpData)
{
LOGFONT *lplf;
TEXTMETRIC *lptm;
int *pType;
lplf = parFontsGlobal[iFace].lf;
lptm = parFontsGlobal[iFace].tm;
pType = parFontsGlobal[iFace].Type;
lplf[jFont] = *lpLogFont;
lptm[jFont] = *lpTEXTMETRICs;
pType[jFont] = fFontType;
jFont++;
return TRUE;
}
/******************************************************************************\
*
* FUNCTION: MyEnumCount
*
* GLOBAL VARS: (see above)
*
\******************************************************************************/
int APIENTRY MyEnumCount (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
DWORD fFontType, LPVOID lpData)
{
(*(LPINT)lpData)++;
return TRUE;
}
/******************************************************************************\
*
* FUNCTION: FreeFontList
*
* INPUTS: paf - pointer to ARFONTS struct to free
*
* LOCAL VARS: i - loop variable
*
\******************************************************************************/
void FreeFontList (PARFONTS paf)
{
int i;
for (i = 0; i < nFaces; i++)
{ LocalFree (LocalHandle ((LPSTR) ((paf + i)->lf )));
LocalFree (LocalHandle ((LPSTR) ((paf + i)->tm )));
LocalFree (LocalHandle ((LPSTR) ((paf + i)->Type)));
}
LocalFree (LocalHandle ((LPSTR) paf));
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.