File:  [WindowsNT SDKs] / q_a / samples / printer / paint.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:29:19 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-jun-1992, HEAD
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));
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.