home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_15 / Text / TextDemo.cpp < prev    next >
C/C++ Source or Header  |  2000-05-24  |  54KB  |  2,131 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : textdemo.cpp                                                         //
  10. //  Description: Text demo routines                                                  //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define _WIN32_WINNT 0x0500
  16. #define NOCRYPT
  17. #define WINVER 0x0500
  18.  
  19. #pragma pack(push, 4)
  20. #include <windows.h>
  21. #pragma pack(pop)
  22.  
  23. #include <assert.h>
  24. #include <tchar.h>
  25. #include <math.h>
  26. #include <stdio.h>
  27.  
  28. #include "..\..\include\gdiobject.h"
  29. #include "..\..\include\fonttext.h"
  30. #include "..\..\include\color.h"
  31. #include "..\..\include\axis.h"
  32. #include "..\..\include\curve.h"
  33. #include "..\..\include\fonttext.h"
  34. #include "..\..\include\OutlineMetric.h"
  35. #include "..\..\include\win.h"
  36.  
  37. #include "TextDemo.h"
  38. #include "resource.h"
  39.  
  40. void ZoomRect(HDC hDC, int x0, int y0, int x1, int y1, int dx, int dy, int zoom)
  41. {
  42.     // use black pen for border
  43.     HGDIOBJ hOld = SelectObject(hDC, GetStockObject(BLACK_PEN));
  44.  
  45.     for (int y=y0; y<y1; y++)
  46.     for (int x=x0; x<x1; x++)
  47.     {
  48.         COLORREF c = GetPixel(hDC, x, y);
  49.  
  50.         HBRUSH  hBrush = CreateSolidBrush(c);
  51.         HGDIOBJ hOld   = SelectObject(hDC, hBrush);
  52.  
  53.         Rectangle(hDC, dx+(x-x0)*(zoom+1), dy+(y-y0)*(zoom+1), 
  54.             dx+(x-x0)*(zoom+1)+zoom+2, 
  55.             dy+(y-y0)*(zoom+1)+zoom+2);
  56.         SelectObject(hDC, hOld);
  57.         DeleteObject(hBrush);
  58.     }
  59.  
  60.     SelectObject(hDC, hOld);
  61. }
  62.  
  63. //////// GLYPH View ///////////
  64.  
  65. void Line(HDC hDC, int x0, int y0, int x1, int y1)
  66. {
  67.     MoveToEx(hDC, x0, y0, NULL);
  68.     LineTo(hDC, x1, y1);
  69. }
  70.  
  71.  
  72. void Box(HDC hDC, int x0, int y0, int x1, int y1)
  73. {
  74.     MoveToEx(hDC, x0, y0, NULL);
  75.     LineTo(hDC, x1, y0);
  76.     LineTo(hDC, x1, y1);
  77.     LineTo(hDC, x0, y1);
  78.     LineTo(hDC, x0, y0);
  79. }
  80.  
  81. void disp(HDC hDC, int x, int y, const TCHAR * mess, int val)
  82. {
  83.     TCHAR temp[MAX_PATH];
  84.  
  85.     wsprintf(temp, mess, val);
  86.     TextOut(hDC, x, y, temp, _tcslen(temp));
  87. }
  88.  
  89. void disp(HDC hDC, int x, int y, const TCHAR * mess)
  90. {
  91.     TextOut(hDC, x, y, mess, _tcslen(mess));
  92. }
  93.  
  94.  
  95. int Demo_Font(HDC hDC, int x, int y, HFONT hFont, const TCHAR * name)
  96. {
  97.     HGDIOBJ hOld  = SelectObject(hDC, hFont);
  98.  
  99.     EXTLOGFONT elf;
  100.     int size = GetObject(hFont, sizeof(elf), & elf);
  101.  
  102.     LOGFONT lf;
  103.     GetObject(hFont, sizeof(lf), & lf);
  104.     
  105.     TEXTMETRIC tm;
  106.     GetTextMetrics(hDC, & tm);
  107.     int height = tm.tmHeight;
  108.  
  109.     disp(hDC, x, y, name); y+= height;
  110.  
  111. //    TCHAR face[MAX_PATH];
  112.  
  113. //    GetTextFace(hDC, MAX_PATH, face);
  114.  
  115.     TCHAR mess[MAX_PATH];
  116.     wsprintf(mess, "{%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, """"%s""""}", 
  117.         lf.lfHeight, lf.lfWidth, lf.lfEscapement, lf.lfOrientation, lf.lfWeight,
  118.         lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut, lf.lfCharSet, lf.lfOutPrecision,
  119.         lf.lfClipPrecision, lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName);
  120.  
  121.     disp(hDC, x, y, mess); y+= height;
  122.     
  123. //    wsprintf(mess, "%d %d %d %d", size, sizeof(LOGFONT), sizeof(ENUMLOGFONTEX), sizeof(ENUMLOGFONTEXDV));
  124. //    disp(hDC, x, y, mess); y+= height;
  125. //    disp(hDC, x, y, face); y+= height;
  126.  
  127.     SelectObject(hDC, hOld);
  128.  
  129.     return y;
  130. }
  131.  
  132. int Demo_Font(HDC hDC, int x, int y, int stockid, const TCHAR * name)
  133. {
  134.     return Demo_Font(hDC, x, y, (HFONT) GetStockObject(stockid), name);
  135. }
  136.  
  137.  
  138. void Demo_StockFonts(HDC hDC, const RECT * rcPaint)
  139. {
  140.     int y = 10;
  141.  
  142.     int base = GetDialogBaseUnits();
  143.     TCHAR temp[64];
  144.     wsprintf(temp, "DialogBaseUnits: baseunixX=%d, baseunitY=%d", LOWORD(base), HIWORD(base));
  145.     TextOut(hDC, 10, y, temp, _tcslen(temp));
  146.     y+= 30;
  147.  
  148.     wsprintf(temp, "GetDeviceCaps(LOGPIXELSX)=%d, GetDeviceCaps(LOGPIXELSX)=%d",
  149.         GetDeviceCaps(hDC, LOGPIXELSX), GetDeviceCaps(hDC, LOGPIXELSY));
  150.     TextOut(hDC, 10, y, temp, _tcslen(temp));
  151.  
  152.     y += 30;
  153.  
  154.     y = Demo_Font(hDC, 10, y, DEFAULT_GUI_FONT,       "GetStockObject(DEFAULT_GUI_FONT)")    + 5;
  155.     y = Demo_Font(hDC, 10, y, OEM_FIXED_FONT,       "GetStockObject(OEM_FIXED_FONT)")      + 5;
  156.     y = Demo_Font(hDC, 10, y, ANSI_FIXED_FONT,       "GetStockObject(ANSI_FIXED_FONT)")     + 5;
  157.     y = Demo_Font(hDC, 10, y, ANSI_VAR_FONT,       "GetStockObject(ANSI_VAR_FONT)")       + 5;
  158.     y = Demo_Font(hDC, 10, y, SYSTEM_FONT,           "GetStockObject(SYSTEM_FONT)")         + 5;
  159.     y = Demo_Font(hDC, 10, y, DEVICE_DEFAULT_FONT, "GetStockObject(DEVICE_DEFAULT_FONT)") + 5;
  160.     y = Demo_Font(hDC, 10, y, SYSTEM_FIXED_FONT,   "GetStockObject(SYSTEM_FIXED_FONT)")   + 5;
  161.  
  162.  
  163. /*    {
  164.         KLogFont lf(- PointSizetoLogical(hDC, 36), "Tahoma");
  165.         
  166.         lf.m_lf.lfItalic = TRUE;
  167.         lf.m_lf.lfCharSet = GB2312_CHARSET;
  168.         HFONT hFont = lf.CreateFont();
  169.  
  170.         SelectObject(hDC, hFont);
  171.  
  172.         TCHAR temp[32];
  173.         GetTextFace(hDC, 32, temp);
  174.         TextOut(hDC, 400, 10, temp, _tcslen(temp));
  175.  
  176.         wsprintf(temp, "%d %d", GB2312_CHARSET, GetTextCharset(hDC));
  177.         TextOut(hDC, 400, 60, temp, _tcslen(temp));
  178.  
  179.         SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
  180.         DeleteObject(hFont);
  181.     }
  182. */
  183. }
  184.  
  185. // Terminology and Metrics
  186.  
  187.  
  188. /*  int    otmsCharSlopeRise; 
  189.     int    otmsCharSlopeRun; 
  190.     int    otmItalicAngle; 
  191.     UINT   otmEMSquare; 
  192.     int    otmAscent; 
  193.     int    otmDescent; 
  194.     UINT   otmLineGap; 
  195.     UINT   otmsCapEmHeight; 
  196.     UINT   otmsXHeight; 
  197.     RECT   otmrcFontBox; 
  198.     UINT   otmusMinimumPPEM; 
  199. */
  200.  
  201. void Demo_Term(HDC hDC, const RECT * rcPaint)
  202. {
  203.     int point = 216;
  204.  
  205.     HFONT hFont = CreateFont( point * GetDeviceCaps(hDC, LOGPIXELSY) / 72,
  206.                          0, 0, 0, FW_NORMAL, TRUE, FALSE, FALSE, 
  207.                          ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, 
  208.                          ANTIALIASED_QUALITY, VARIABLE_PITCH, "Times New Roman");
  209.     SetTextAlign(hDC, TA_BASELINE | TA_LEFT);
  210.     SetBkMode(hDC, TRANSPARENT);
  211.  
  212.     SelectObject(hDC, hFont);
  213.  
  214.     {
  215.         KOutlineTextMetric otm(hDC);
  216.  
  217.         TEXTMETRIC tm;
  218.  
  219.         GetTextMetrics(hDC, & tm);
  220.         int x = 300;
  221.         int y = 450;
  222.  
  223.         // glyph bounding box
  224.         Rectangle(hDC, x + otm.m_pOtm->otmrcFontBox.left,
  225.                        y - otm.m_pOtm->otmrcFontBox.top,
  226.                        x + otm.m_pOtm->otmrcFontBox.right,
  227.                        y - otm.m_pOtm->otmrcFontBox.bottom);
  228.  
  229.         // draw the character(s)
  230.         TextOut(hDC, x, y, "@", 1);
  231.  
  232.         SIZE size;
  233.  
  234.         GetTextExtentPoint(hDC, "@" /*"ā•Ÿ"*/, 1, & size);
  235.  
  236.         // vertical metrics lines
  237.         HPEN hPen = CreatePen(PS_DOT, 0, RGB(0, 0, 0));
  238.         HGDIOBJ hOld = SelectObject(hDC, hPen);
  239.  
  240.         Line(hDC, x-160, y-tm.tmAscent-tm.tmExternalLeading,  x+400, y-tm.tmAscent-tm.tmExternalLeading);
  241.         Line(hDC, x-160, y-tm.tmAscent,                          x+400, y-tm.tmAscent);
  242.         Line(hDC, x-160, y-tm.tmAscent+tm.tmInternalLeading,  x+400, y-tm.tmAscent+tm.tmInternalLeading);
  243.         Line(hDC, x-160, y,                                      x+400, y);
  244.         Line(hDC, x-160, y+tm.tmDescent,                      x+400, y+tm.tmDescent);
  245.  
  246.         SelectObject(hDC, hOld);
  247.         DeleteObject(hPen);
  248.  
  249.         SelectObject(hDC, GetStockObject(SYSTEM_FONT));
  250.  
  251.         DeleteObject(hFont);
  252.  
  253.         disp(hDC, 10,  30, "tmHeight          %d", tm.tmHeight);
  254.         disp(hDC, 10,  55, "tmAscent          %d", tm.tmAscent);
  255.         disp(hDC, 10,  80, "tmDescent         %d", tm.tmDescent);
  256.         disp(hDC, 10, 105, "tmInternalLeading %d", tm.tmInternalLeading);
  257.         disp(hDC, 10, 130, "tmExternalLeading %d", tm.tmExternalLeading);
  258.  
  259.         Line(hDC, x+500, y-otm.m_pOtm->otmMacAscent-otm.m_pOtm->otmMacLineGap,  x+600, 
  260.             y-otm.m_pOtm->otmMacAscent-otm.m_pOtm->otmMacLineGap);
  261.         Line(hDC, x+500, y-otm.m_pOtm->otmMacAscent,                    x+620, y-otm.m_pOtm->otmMacAscent);
  262.         Line(hDC, x+500, y,                                        x+660, y);
  263.         Line(hDC, x+500, y-otm.m_pOtm->otmMacDescent,                    x+680, y-otm.m_pOtm->otmMacDescent);
  264.     
  265.         disp(hDC, 510,  30, "otmAscent   %d", otm.m_pOtm->otmMacAscent);
  266.         disp(hDC, 510,  55, "otmDescent  %d", otm.m_pOtm->otmMacDescent);
  267.         disp(hDC, 510,  80, "otmLineGap  %d", otm.m_pOtm->otmMacLineGap);
  268.  
  269.         // strikeout
  270.         SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  271.         Rectangle(hDC, x,         y - otm.m_pOtm->otmsStrikeoutPosition, 
  272.                  x+size.cx, y - otm.m_pOtm->otmsStrikeoutPosition + otm.m_pOtm->otmsStrikeoutSize); 
  273.  
  274.         // underscore
  275.         Rectangle(hDC, x,     y - otm.m_pOtm->otmsUnderscorePosition, 
  276.                  x+size.cx, y - otm.m_pOtm->otmsUnderscorePosition + otm.m_pOtm->otmsUnderscoreSize); 
  277.         SelectObject(hDC, GetStockObject(WHITE_BRUSH));
  278.  
  279.         x += size.cx;
  280.  
  281.         // slope
  282.         MoveToEx(hDC, x - otm.m_pOtm->otmsCharSlopeRun*3, y + otm.m_pOtm->otmsCharSlopeRise*3, NULL);
  283.         LineTo(hDC,   x + otm.m_pOtm->otmsCharSlopeRun*11, y - otm.m_pOtm->otmsCharSlopeRise*11);
  284.  
  285.         Box(hDC, x + otm.m_pOtm->otmptSubscriptOffset.x,
  286.                  y + otm.m_pOtm->otmptSubscriptOffset.y,
  287.                  x + otm.m_pOtm->otmptSubscriptOffset.x + otm.m_pOtm->otmptSubscriptSize.x,
  288.                  y + otm.m_pOtm->otmptSubscriptOffset.y - otm.m_pOtm->otmptSubscriptSize.y);
  289.  
  290.         Box(hDC, x + otm.m_pOtm->otmptSuperscriptOffset.x,
  291.                  y - otm.m_pOtm->otmptSuperscriptOffset.y,
  292.                  x + otm.m_pOtm->otmptSuperscriptOffset.x + otm.m_pOtm->otmptSuperscriptSize.x,
  293.                  y - otm.m_pOtm->otmptSuperscriptOffset.y - otm.m_pOtm->otmptSuperscriptSize.y);
  294.     }
  295. }
  296.  
  297.  
  298. int e_linespace;
  299. int e_pageheight;
  300. int e_externalleading;
  301.  
  302. int LinesPerPage(HDC hDC, int nPointSize, int nPageHeight)
  303. {
  304.     KLogFont lf(-PointSizetoLogical(hDC, nPointSize), "Times New Roman");
  305.  
  306.     HFONT hFont  = lf.CreateFont();
  307.     HGDIOBJ hOld = SelectObject(hDC, hFont);
  308.  
  309.     TEXTMETRIC tm;
  310.     GetTextMetrics(hDC, & tm);
  311.  
  312.     int linespace = tm.tmHeight + tm.tmExternalLeading;
  313.     SelectObject(hDC, hOld);
  314.     DeleteObject(hFont);
  315.  
  316.     POINT P[2] = { 0, 0, 0, nPageHeight }; // device coordinate
  317.     DPtoLP(hDC, P, 2);                       // logical coordinate
  318.     nPageHeight = abs(P[1].y-P[0].y);
  319.  
  320.     e_linespace       = linespace;
  321.     e_pageheight      = nPageHeight;
  322.     e_externalleading = tm.tmExternalLeading;
  323.  
  324.     return (nPageHeight + tm.tmExternalLeading) / linespace;
  325. }
  326.  
  327. /*
  328. const int UHR_WIN95 = 1800;
  329. const int UHR_WINNT = 7200;
  330.  
  331. // setup ultra-high-resolution logical coordinate system
  332. void Setup_UHR(HDC hDC, int dpi=UHR_WIN95)
  333. {
  334.     SetMapMode(hDC, MM_ANISOTROPIC);
  335.  
  336.     SetWindowExtEx(hDC, dpi, dpi, NULL);
  337.     SetWindowOrgEx(hDC, 0, 0,     NULL);
  338.  
  339.     SetViewportExtEx(hDC, GetDeviceCaps(hDC, LOGPIXELSX), GetDeviceCaps(hDC, LOGPIXELSY), NULL);
  340.     SetViewportOrgEx(hDC, 0, 0, NULL);
  341. }
  342. */
  343.  
  344. void Demo_Metrics(HDC hDisp, HDC hDC, int x, int y, int mapmode, int point, int winext=1)
  345. {
  346.     SaveDC(hDC);
  347.  
  348.     if ( mapmode==MM_ANISOTROPIC )
  349.     {
  350.         SetMapMode(hDC, MM_ANISOTROPIC);
  351.  
  352.         SetWindowExtEx(hDC, winext, winext, NULL);
  353.         SetViewportExtEx(hDC, 1, 1, NULL);
  354.     }
  355.     else
  356.         SetMapMode(hDC, mapmode);
  357.     
  358.     int lineno = LinesPerPage(hDC, point, 10 * GetDeviceCaps(hDC, LOGPIXELSY));
  359.     
  360.     SIZE wndext, viewext;
  361.     GetWindowExtEx(hDC, & wndext);
  362.     GetViewportExtEx(hDC, & viewext);
  363.  
  364.     RestoreDC(hDC, -1);
  365.  
  366.     TCHAR temp[MAX_PATH];
  367.     wsprintf(temp, _T("%d dpi, %d:%d, Page height %d, linespace %d, external leading %d, Lines per page %d"), 
  368.         GetDeviceCaps(hDC, LOGPIXELSY),
  369.         wndext.cx, viewext.cx,
  370.         e_pageheight, e_linespace, 
  371.         e_externalleading, lineno);
  372.  
  373.     TextOut(hDisp, x, y, temp, _tcslen(temp));
  374. }
  375.  
  376.  
  377. // Test the relationship between logical coordinate space resolution vs font metrics accuracy
  378. void Test_LC(void)
  379. {
  380.     HDC hDC = GetDC(NULL);
  381.  
  382.     SetMapMode(hDC, MM_ANISOTROPIC);
  383.     SetViewportExtEx(hDC, 1, 1, NULL);
  384.     
  385.     TCHAR mess[MAX_PATH];
  386.     mess[0] = 0;
  387.  
  388.     for (int i=1; i<=64; i*=2)
  389.     {
  390.         SetWindowExtEx(hDC, i, i, NULL);
  391.  
  392.         KLogFont lf(-PointSizetoLogical(hDC, 24), "Times New Roman"); // 24-point
  393.         HFONT hFont = lf.CreateFont();
  394.         SelectObject(hDC, hFont);
  395.  
  396.         TEXTMETRIC tm; 
  397.         GetTextMetrics(hDC, & tm);
  398.         wsprintf(mess + _tcslen(mess), "%d:1 lfHeight=%d, tmHeight=%d\n", i, lf.m_lf.lfHeight, tm.tmHeight);
  399.  
  400.         SelectObject(hDC, GetStockObject(ANSI_VAR_FONT));
  401.         DeleteObject(hFont);
  402.     }
  403.     ReleaseDC(NULL, hDC);
  404.  
  405.     MyMessageBox(NULL, mess, "LCS vs. TEXTMETRIC", MB_OK, IDI_TEXT);
  406. }
  407.  
  408.  
  409. // Test the relationship between font size vs font metrics accuracy
  410. void Test_Point(void)
  411. {
  412.     HDC hDC = GetDC(NULL);
  413.  
  414.     TCHAR mess[MAX_PATH*2];
  415.     mess[0] = 0;
  416.  
  417.     for (int i=1; i<=64; i*=2)
  418.     {
  419.         KLogFont lf(-PointSizetoLogical(hDC, 24*i), "Times New Roman"); 
  420.         HFONT hFont = lf.CreateFont();
  421.         SelectObject(hDC, hFont);
  422.  
  423.         TEXTMETRIC tm; 
  424.         GetTextMetrics(hDC, & tm);
  425.         wsprintf(mess + _tcslen(mess), "%d point lfHeight=%d, tmHeight=%d\n", 24*i, lf.m_lf.lfHeight, tm.tmHeight);
  426.  
  427.         SelectObject(hDC, GetStockObject(ANSI_VAR_FONT));
  428.         DeleteObject(hFont);
  429.     }
  430.     ReleaseDC(NULL, hDC);
  431.  
  432.     MyMessageBox(NULL, mess, "Point Size vs. TEXTMETRIC", MB_OK, IDI_TEXT);
  433. }
  434.  
  435.  
  436. void Demo_CoordinateSystem(HDC hDC, const RECT * rcPaint)
  437. {
  438.     Demo_Metrics(hDC, hDC, 30,  30, MM_TEXT,      10);
  439.     Demo_Metrics(hDC, hDC, 30,  60, MM_LOENGLISH, 10);
  440.     Demo_Metrics(hDC, hDC, 30,  90, MM_HIENGLISH, 10);
  441.     Demo_Metrics(hDC, hDC, 30, 120, MM_TWIPS,     10);
  442.  
  443.     PRINTDLG pd;
  444.     HWND hwnd = NULL;
  445.  
  446.     // Initialize PRINTDLG
  447.     ZeroMemory(&pd, sizeof(PRINTDLG));
  448.     pd.lStructSize = sizeof(PRINTDLG);
  449.     pd.hwndOwner   = hwnd;
  450.     pd.hDevMode    = NULL;      // Don't forget to free or store hDevMode.
  451.     pd.hDevNames   = NULL;      // Don't forget to free or store hDevNames.
  452.     pd.Flags       = PD_RETURNDC | PD_RETURNDEFAULT; 
  453.     pd.nCopies     = 1;
  454.     pd.nFromPage   = 0xFFFF; 
  455.     pd.nToPage     = 0xFFFF; 
  456.     pd.nMinPage    = 1; 
  457.     pd.nMaxPage    = 0xFFFF; 
  458.  
  459.     // default printer
  460.     if ( PrintDlg(&pd)) 
  461.     {
  462.         Demo_Metrics(hDC, pd.hDC, 30,  150, MM_TEXT, 10);
  463.     
  464.         // 1800-dpi ultra-high-resolution logical coordinate system
  465.         // Demo_Metrics(hDC, pd.hDC, 30, 200, MM_ANISOTROPIC);
  466.         // Demo_Metrics(hDC, hDC,    30, 230, MM_ANISOTROPIC);
  467.  
  468.         // Delete DC when done.
  469.         DeleteDC(pd.hDC);
  470.     }
  471.  
  472.     // reference
  473.     Demo_Metrics(hDC, hDC, 30, 200, MM_ANISOTROPIC, 15, 1);
  474.     
  475.     // test changing logic coordinate on metrics accuracy
  476.     Demo_Metrics(hDC, hDC, 30, 230, MM_ANISOTROPIC, 15, 5);
  477.     Demo_Metrics(hDC, hDC, 30, 260, MM_ANISOTROPIC, 15, 10);
  478.     Demo_Metrics(hDC, hDC, 30, 290, MM_ANISOTROPIC, 15, 20);
  479.     
  480.     // test font size on metrics accuracy
  481.     Demo_Metrics(hDC, hDC, 30, 320, MM_ANISOTROPIC,  75, 1);
  482.     Demo_Metrics(hDC, hDC, 30, 350, MM_ANISOTROPIC, 150, 1);
  483.     Demo_Metrics(hDC, hDC, 30, 380, MM_ANISOTROPIC, 300, 1);
  484. }
  485.  
  486.  
  487. void Demo_TextAlignment(HDC hDC, const RECT * rcPaint)
  488. {
  489.     KLogFont lf(-PointSizetoLogical(hDC, 48), "Georgia");
  490.  
  491.     {
  492.         const TCHAR * mess[] = { "TA_TOP | TA_LEFT", "TA_BASELINE | TA_CENTER", "TA_BOTTOM | TA_RIGHT" };
  493.  
  494.         TextOut(hDC,  50, 10, mess[0], _tcslen(mess[0]));
  495.         TextOut(hDC, 200, 10, mess[1], _tcslen(mess[1]));
  496.         TextOut(hDC, 400, 10, mess[2], _tcslen(mess[2]));
  497.     }
  498.  
  499.     KGDIObject font(hDC, lf.CreateFont());
  500.  
  501.     SetTextColor(hDC, RGB(0, 0, 0));          // black
  502.     SetBkColor(hDC,   RGB(0xD0, 0xD0, 0xD0)); // gray
  503.     SetBkMode(hDC,    OPAQUE);                  // opaque
  504.  
  505.     int x = 50; 
  506.     int y = 110;
  507.     
  508.     const TCHAR * mess = "Align";
  509.  
  510.     for (int i=0; i<3; i++, x+=250)
  511.     {
  512.         const UINT Align[] = { TA_TOP | TA_LEFT, TA_BASELINE | TA_CENTER, TA_BOTTOM | TA_RIGHT };
  513.             
  514.         SetTextAlign(hDC, Align[i] | TA_UPDATECP);
  515.         MoveToEx(hDC, x, y, NULL);            // set cp    
  516.         TextOut(hDC, x, y, mess, _tcslen(mess));
  517.         POINT cp;
  518.         MoveToEx(hDC, 0, 0, & cp);            // get cp
  519.         Line(hDC, cp.x-5, cp.y+5, cp.x+5, cp.y-5); // mark cp
  520.         Line(hDC, cp.x-5, cp.y-5, cp.x+5, cp.y+5);
  521.  
  522.         Line(hDC, x, y-75, x, y+75); // vertical refer line
  523.  
  524.         SIZE size;
  525.  
  526.         GetTextExtentPoint32(hDC, mess, _tcslen(mess), & size);
  527.  
  528.         Box(hDC, x, y, x + size.cx, y + size.cy);
  529.     }
  530.     x -= 250 * 3;
  531.     Line(hDC, x-20, y, x+520, y); // horizontal refer line
  532. }
  533.  
  534.  
  535. void Demo_RTL(HDC hDC, const RECT * rcPaint)
  536. {
  537. //    LCID lcid = GetThreadLocale();
  538. //    SetThreadLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_EGYPT), SORT_DEFAULT));
  539.     
  540.     KLogFont lf(-PointSizetoLogical(hDC, 36), "Lucida Sans Unicode");
  541.     lf.m_lf.lfCharSet = ARABIC_CHARSET;
  542.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  543.  
  544.     KGDIObject font(hDC, lf.CreateFont());
  545.     TEXTMETRIC tm;
  546.     GetTextMetrics(hDC, & tm);
  547.     int linespace = tm.tmHeight + tm.tmExternalLeading;
  548.  
  549.     const TCHAR * mess = "1-360-212-0000 \xD0\xD1\xD2";
  550.     
  551.     for (int i=0; i<4; i++)
  552.     {
  553.         if ( i & 1 )
  554.             SetTextAlign(hDC, TA_TOP | TA_LEFT | TA_RTLREADING);
  555.         else
  556.             SetTextAlign(hDC, TA_TOP | TA_LEFT);
  557.  
  558.         if ( i & 2 )
  559.             SetLayout(hDC, LAYOUT_RTL);
  560.         else
  561.             SetLayout(hDC, 0);
  562.         
  563.         TextOut(hDC, 10, 10 + linespace * i, mess, _tcslen(mess));
  564.     }
  565.  
  566. //    SetThreadLocale(lcid);
  567. }
  568.  
  569.  
  570. void Demo_Justification(HDC hDC, const RECT * rcPaint)
  571. {
  572.     SetTextColor(hDC, RGB(0, 0, 0));          // black
  573.     SetBkColor(hDC,   RGB(0xE0, 0xE0, 0xE0)); // gray
  574.     SetBkMode(hDC,    OPAQUE);                  // opaque
  575.  
  576.     {
  577.         KLogFont   lf(-PointSizetoLogical(hDC, 48), "Georgia");
  578.         KGDIObject font(hDC, lf.CreateFont());
  579.  
  580.         int x = 50; 
  581.         int y = 50;
  582.     
  583.         const TCHAR * mess = "Extra";
  584.  
  585.         SetTextAlign(hDC, TA_LEFT | TA_TOP);
  586.  
  587.         for (int i=0; i<3; i++)
  588.         {
  589.             SetTextCharacterExtra(hDC, i*10-10);
  590.             TextOut(hDC, x, y, mess, _tcslen(mess));
  591.  
  592.             SIZE size;
  593.             GetTextExtentPoint32(hDC, mess, _tcslen(mess), & size);
  594.             Box(hDC, x, y, x + size.cx, y + size.cy);
  595.  
  596.             y += size.cy + 10;
  597.         }
  598.  
  599.         SetTextCharacterExtra(hDC, 0);
  600.     }
  601.  
  602.     {
  603.         KLogFont   lf(-PointSizetoLogical(hDC, 16), "Times New Roman");
  604.         KGDIObject font(hDC, lf.CreateFont());
  605.  
  606.         int left  = 300;
  607.         int right = 600;
  608.         int y     =  50;
  609.  
  610.         TEXTMETRIC tm;
  611.         GetTextMetrics(hDC, & tm);
  612.         int ls = tm.tmHeight + tm.tmExternalLeading;
  613.  
  614.         const TCHAR * line = "The quick brown fox jumps over the lazy dog.";
  615.         const TCHAR * pend = line;
  616.  
  617.         while ( pend )
  618.         {
  619.             pend = _tcschr(pend, ' ');
  620.             int nCount;
  621.  
  622.             if ( pend )
  623.                 nCount = ((int) pend - (int) line) / sizeof(TCHAR);
  624.             else
  625.                 nCount = _tcslen(line);
  626.  
  627.             TextOutJust(hDC, left, right, y, line, nCount, true);
  628.             y += ls;
  629.  
  630.             if ( pend )
  631.                 pend ++;
  632.         }
  633.         
  634.         SetTextJustification(hDC, 0, 0);
  635.  
  636.         TextOut(hDC, left, y+1, line, _tcslen(line));
  637.  
  638.         // Line(hDC, left,  180, left, 340);
  639.         // Line(hDC, right, 180, right, 340);
  640.     }
  641. }
  642.  
  643.  
  644. void Demo_CharacterWidth(HDC hDC, const RECT * rcPaint)
  645. {
  646.     KLogFont lf(-PointSizetoLogical(hDC, 144), "Georgia");
  647.     lf.m_lf.lfItalic = TRUE;
  648.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  649.  
  650.     SetTextColor(hDC, RGB(0, 0, 0));          // black
  651.     SetBkColor(hDC,   RGB(0xD0, 0xD0, 0xD0)); // gray
  652.     SetBkMode(hDC,    OPAQUE);                  // opaque
  653.  
  654.     int x = 100; 
  655.     int y =  80;
  656.     
  657.     const TCHAR * mess = "font";
  658.     ABC abc[128];
  659.     SIZE size;
  660.  
  661.     {
  662.         KGDIObject font(hDC, lf.CreateFont());
  663.     
  664.         SetTextAlign(hDC, TA_LEFT | TA_TOP);
  665.         TextOut(hDC, x, y, mess, _tcslen(mess));
  666.     
  667.         GetCharABCWidths(hDC, 0, 0x7F, abc);
  668.  
  669.         GetTextExtentPoint32(hDC, mess, _tcslen(mess), & size);
  670.  
  671.         int xx = x;
  672.         int yy = 0;
  673.  
  674.         for (int i=0; mess[i]; i++)
  675.         {
  676.             ABC & ch = abc[mess[i]];
  677.  
  678.             Line(hDC, xx, y-25, xx, y+size.cy+25);            // current cursor position
  679.         
  680.             if ( ch.abcA < 0 )
  681.             {
  682.                 RECT rect = { xx, y-25, xx+ch.abcA, y-5 };
  683.                 FillRect(hDC, & rect, (HBRUSH) GetStockObject(GRAY_BRUSH));
  684.             }
  685.             xx += ch.abcA;
  686.             Line(hDC, xx, y-25, xx, y-5);                    // cp + A
  687.  
  688.             xx += ch.abcB;
  689.             Line(hDC, xx, y+size.cy+5, xx, y+size.cy+25);   // cp + A + B
  690.  
  691.             if ( ch.abcC < 0 )
  692.             {
  693.                 RECT rect = { xx, y+size.cy+5, xx+ch.abcC, y+size.cy+25 };
  694.                 FillRect(hDC, & rect, (HBRUSH) GetStockObject(GRAY_BRUSH));
  695.             }
  696.             xx += ch.abcC;
  697.         }
  698.         Line(hDC, xx, y-25, xx, y+size.cy+25);            // current cursor position
  699.     
  700.         Box(hDC, x, y-40, x + size.cx, y - 50);
  701.     }
  702.  
  703.     SetBkColor(hDC,   RGB(0xFF, 0xFF, 0xFF)); // white
  704.     
  705.     int sum = 0;
  706.  
  707.     x += size.cx + 55;
  708.     y -= 40;
  709.  
  710.     TCHAR temp[64];
  711.  
  712.     for (int i=0; mess[i]; i++)
  713.     {
  714.         ABC & ch = abc[mess[i]];
  715.  
  716.         sum += ch.abcA + ch.abcB + ch.abcC;
  717.  
  718.         wsprintf(temp, "'%c'(0x%02x): %d %d %d", mess[i], mess[i], ch.abcA, ch.abcB, ch.abcC);
  719.         TextOut(hDC, x, y, temp, _tcslen(temp));
  720.         y+= 25;
  721.     }
  722.  
  723.     wsprintf(temp, "ABC widths sum: %d", sum);
  724.     TextOut(hDC, x, y, temp, _tcslen(temp)); y+= 25;
  725.  
  726.     wsprintf(temp, "GetTextExtent %d %d", size.cx, size.cy);
  727.     TextOut(hDC, x, y, temp, _tcslen(temp)); y+= 25;
  728.  
  729.     {
  730.         ABC  abc;
  731.         long height;
  732.  
  733.         {
  734.             KLogFont lf(-PointSizetoLogical(hDC, 144), "Georgia");
  735.             lf.m_lf.lfItalic = TRUE;
  736.  
  737.             KGDIObject font(hDC, lf.CreateFont());
  738.  
  739.             GetTextABCExtent(hDC, mess, _tcslen(mess), & height, & abc);
  740.         }
  741.  
  742.         wsprintf(temp, "GetTextABCExtent %d %d %d", abc.abcA, abc.abcB, abc.abcC);
  743.         TextOut(hDC, x, y, temp, _tcslen(temp)); y+= 25;
  744.     }
  745.  
  746.     {
  747.         KLogFont lf(-PointSizetoLogical(hDC, 48), "Georgia");
  748.         lf.m_lf.lfItalic = TRUE;
  749.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  750.  
  751.         KGDIObject font(hDC, lf.CreateFont());
  752.         SetBkColor(hDC,   RGB(0xD0, 0xD0, 0xD0)); // gray
  753.         SetBkMode(hDC,    OPAQUE);                  // opaque
  754.  
  755.         const TCHAR * mess = "faroff";
  756.         int           len  = _tcslen(mess);
  757.         
  758.         SIZE size;
  759.         GetTextExtentPoint32(hDC, mess, len, & size);
  760.  
  761.         int left  = 100;
  762.         int y     = 350;
  763.         
  764.         int right = left + size.cx * 3/ 2;
  765.         int dx    = size.cx * 5/3;
  766.         int dy    = size.cy * 11 / 10;        
  767.         
  768.         SetTextAlign(hDC, TA_LEFT);
  769.         TextOut(hDC, left, y, mess, len);
  770.         PreciseTextOut(hDC, left+dx, y, mess, len);
  771.  
  772.         SetTextAlign(hDC, TA_CENTER);
  773.         TextOut(hDC, (left+right)/2, y+dy, mess, len);
  774.         PreciseTextOut(hDC, (left+right)/2+dx, y+dy, mess, len);
  775.         
  776.         SetTextAlign(hDC, TA_RIGHT);
  777.         TextOut(hDC, right, y+dy*2, mess, len);
  778.         PreciseTextOut(hDC, right+dx, y+dy*2, mess, len);
  779.         
  780.         Line(hDC, left, y-5, left, y+dy*3+5);
  781.         Line(hDC, right, y-5, right, y+dy*3+5);
  782.  
  783.         Line(hDC, left+dx, y-5, left+dx, y+dy*3+5);
  784.         Line(hDC, right+dx, y-5, right+dx, y+dy*3+5);
  785.     }
  786. }
  787.  
  788.  
  789. void dispsmall(HDC hDC, int x, int y, int row, const TCHAR * mess)
  790. {
  791.     HGDIOBJ hOld = SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
  792.     int oldmd    = SetBkMode(hDC, TRANSPARENT);
  793.  
  794.     TEXTMETRIC tm;
  795.     GetTextMetrics(hDC, & tm);
  796.  
  797.     TextOut(hDC, x, y + row * ( tm.tmHeight + tm.tmExternalLeading-1), mess, _tcslen(mess));
  798.  
  799.     SelectObject(hDC, hOld);
  800.     SetBkMode(hDC, oldmd);
  801. }
  802.  
  803.  
  804. void Demo_CharacterPlacement(HDC hDC, const RECT * rcPaint)
  805. {
  806.     KLogFont lf(-PointSizetoLogical(hDC, 60), "Times New Roman");
  807.     lf.m_lf.lfItalic  = TRUE;
  808.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  809.  
  810.     SetTextColor(hDC, RGB(0, 0, 0));          // black
  811.     SetBkColor(hDC,   RGB(0xD0, 0xD0, 0xD0)); // gray
  812.     SetBkMode(hDC,    OPAQUE);                  // opaque
  813.  
  814.     int x = 32; 
  815.     int y = 32;
  816.     
  817.     KGDIObject font(hDC, lf.CreateFont());
  818.  
  819.     const TCHAR mess [] = "AVOWAL";
  820.  
  821.     // originl text out
  822.     TextOut(hDC, x, y, mess, _tcslen(mess));
  823.  
  824.     KPlacement<MAX_PATH> placement;
  825.  
  826.     TEXTMETRIC tm;
  827.     GetTextMetrics(hDC, & tm);
  828.     int linespace = tm.tmHeight + tm.tmExternalLeading;
  829.  
  830.     KKerningPair kerning(hDC);
  831.  
  832.     SIZE size;
  833.     GetTextExtentPoint32(hDC, mess, _tcslen(mess), & size);
  834.  
  835.     for (int test=0; test<3; test++)
  836.     {
  837.         y += linespace;
  838.     
  839.         int opt;
  840.  
  841.         switch ( test )
  842.         {
  843.             case 0: opt = 0; break;
  844.             case 1: opt = GCP_USEKERNING; break;
  845.             case 2: opt = GCP_USEKERNING | GCP_JUSTIFY; break;
  846.         }
  847.         
  848.         placement.GetPlacement(hDC, mess, opt | GCP_MAXEXTENT, size.cx*11/10);
  849.         placement.GlyphTextOut(hDC, x, y);
  850.  
  851.         int xx = x;
  852.         TCHAR temp[128];
  853.         
  854.         for (unsigned i=0; mess[i]; i++)
  855.         {
  856.             Line(hDC, xx, y, xx, y + linespace);
  857.  
  858.             wsprintf(temp, "gi('%c')=%3d, dx[%2d]=%3d", 
  859.                 placement.m_strOut[i], placement.m_glyphs[i],
  860.                 i, placement.m_dx[placement.m_order[i]]);
  861.  
  862.             if ( (test==1) && mess[i+1] )
  863.                 wsprintf(temp+_tcslen(temp), ", kern('%c','%c')=%3d", 
  864.                     mess[i], mess[i+1], kerning.GetKerning(mess[i], mess[i+1]));
  865.  
  866.         //    if ( (test==2) && (i==0) )
  867.         //        wsprintf(temp+_tcslen(temp), "extent %d", size.cx*11/10);
  868.  
  869.             dispsmall(hDC, x + size.cx * 12/10, y, i, temp);
  870.  
  871.             xx += placement.m_dx[placement.m_order[i]];
  872.         }
  873.  
  874.         wsprintf(temp, "extent %d, sum dx=%d", size.cx*11/10, xx-x);
  875.         dispsmall(hDC, x + size.cx * 12/10, y, _tcslen(mess), temp);
  876.         
  877.         Line(hDC, xx, y, xx, y + linespace);
  878.     }
  879.  
  880.  
  881.     // RTL reading
  882.     {
  883.         KLogFont lf(-PointSizetoLogical(hDC, 48), "Andalus");
  884.         lf.m_lf.lfCharSet = ARABIC_CHARSET;
  885.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  886.  
  887.         KGDIObject font(hDC, lf.CreateFont());
  888.         
  889.         if ( GetFontLanguageInfo(hDC) & GCP_REORDER )
  890.             disp(hDC, 500, 410, "GCP_REORDER supported");
  891.         else
  892.             disp(hDC, 500, 410, "GCP_REORDER not supported");
  893.  
  894.         KPlacement<MAX_PATH> placement;
  895.                 
  896.         const TCHAR * mess = "abc \xC7\xC8\xC9\xCA";
  897.     
  898.         SIZE size;
  899.         GetTextExtentPoint32(hDC, mess, _tcslen(mess), & size);
  900.         
  901.         TEXTMETRIC tm;
  902.         GetTextMetrics(hDC, & tm);
  903.         int linespace = tm.tmHeight + tm.tmExternalLeading + 5;
  904.                 
  905.         for (test=0; test<2; test++)
  906.         {
  907.             int y = 420 + linespace * (test+1);
  908.             int x = 500;
  909.         
  910.             SetTextAlign(hDC, TA_LEFT | TA_RTLREADING);
  911.             placement.GetPlacement(hDC, mess, (test==0) ? 0 : GCP_REORDER);
  912.             placement.GlyphTextOut(hDC, x, y);
  913.             SetTextAlign(hDC, TA_LEFT);
  914.  
  915.             TCHAR temp[128];
  916.         
  917.             for (unsigned i=0; mess[i]; i++)
  918.             {
  919.                 wsprintf(temp, "order[%d]=%d, gi(0x%02x)=%3d, dx[%d]=%3d", 
  920.                     i, placement.m_order[i],
  921.                     placement.m_strOut[i] & 0xFF, placement.m_glyphs[i] & 0xFFFF,
  922.                     i, placement.m_dx[placement.m_order[i]]);
  923.  
  924.                 dispsmall(hDC, x + size.cx * 12/10, y, i, temp);
  925.             }
  926.         }
  927.     }
  928.  
  929.     // extra kerning samples
  930.     {
  931.         KLogFont lf(-PointSizetoLogical(hDC, 48), "Tahoma");
  932.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  933.  
  934.         KGDIObject font(hDC, lf.CreateFont());
  935.  
  936.         const TCHAR mess1[] = "F,) Ta r.";  
  937.         const TCHAR mess2[] = "ƆƦ f] f}";
  938.  
  939.         // originl text out
  940.         int x = 50;
  941.         int y = 420;
  942.         TEXTMETRIC tm;
  943.         GetTextMetrics(hDC, & tm);
  944.  
  945.         TextOut(hDC, x, y, mess1, _tcslen(mess1));
  946.  
  947.         KPlacement<MAX_PATH> placement;
  948.  
  949.         placement.GetPlacement(hDC, mess1, GCP_USEKERNING);
  950.         placement.GlyphTextOut(hDC, x, y+tm.tmHeight + tm.tmExternalLeading+10);
  951.  
  952.         x += 250;
  953.  
  954.         TextOut(hDC, x, y, mess2, _tcslen(mess2));
  955.  
  956.         placement.GetPlacement(hDC, mess2, GCP_USEKERNING);
  957.         placement.GlyphTextOut(hDC, x, y+tm.tmHeight + tm.tmExternalLeading+10);
  958.  
  959.     }
  960.  
  961. }
  962.  
  963.  
  964. void Demo_GlyphIndex(HDC hDC, const RECT *)
  965. {
  966.     KLogFont lf(-PointSizetoLogical(hDC, 12), "Courier New");
  967.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  968.  
  969.     KGDIObject font(hDC, lf.CreateFont());
  970.  
  971.     // query for size
  972.     DWORD size = GetFontUnicodeRanges(hDC, NULL);
  973.  
  974.     GLYPHSET * pGlyphSet = (GLYPHSET *) new BYTE[size];
  975.  
  976.     // get real data
  977.     pGlyphSet->cbThis = size;
  978.     size = GetFontUnicodeRanges(hDC, pGlyphSet);
  979.  
  980.     int x = 20;
  981.     int y = 20;
  982.  
  983.     TEXTMETRIC tm;
  984.     GetTextMetrics(hDC, & tm);
  985.  
  986.     for (unsigned i=0; i<min(16, pGlyphSet->cRanges); i++)
  987.     {
  988.         TCHAR text[MAX_PATH];
  989.         wsprintf(text, "%3d 0x%04X %3d", i, pGlyphSet->ranges[i].wcLow, pGlyphSet->ranges[i].cGlyphs);
  990.         TextOut(hDC, x, y, text, _tcslen(text));
  991.         
  992.         WCHAR sample[8];
  993.         WORD  glyphindex[8];
  994.  
  995.         int cGlyph = min(pGlyphSet->ranges[i].cGlyphs, 8);
  996.         
  997.         for (int j=0; j<cGlyph; j++)
  998.             sample[j] = pGlyphSet->ranges[i].wcLow + j;
  999.  
  1000.         TextOutW(hDC, x+150, y, sample, cGlyph);
  1001.  
  1002.         GetGlyphIndicesW(hDC, sample, cGlyph, glyphindex, 0);
  1003.             
  1004.         text[0] = 0;
  1005.         for (j=0; j<cGlyph; j++)
  1006.         {
  1007.             wsprintf(text + _tcslen(text), "%4d ", glyphindex[j]);
  1008.         }
  1009.             
  1010.         TextOut(hDC, x+300, y, text, _tcslen(text));
  1011.  
  1012.         y += tm.tmHeight + tm.tmExternalLeading;
  1013.     }
  1014.  
  1015.     delete (BYTE *) pGlyphSet;
  1016.  
  1017.     // exttextout
  1018.     {
  1019.         SetTextColor(hDC, RGB(0, 0, 0));          // black
  1020.         SetBkColor(hDC,   RGB(0xD0, 0xD0, 0xD0)); // gray
  1021.         SetBkMode(hDC,    OPAQUE);                  // opaque
  1022.  
  1023.         x = 50;
  1024.         y = 350;
  1025.  
  1026.         KLogFont lf(-PointSizetoLogical(hDC, 36), "Tahoma");
  1027.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1028.         lf.m_lf.lfCharSet = GB2312_CHARSET;
  1029.  
  1030.         KGDIObject font(hDC, lf.CreateFont());
  1031.         TEXTMETRIC tm;
  1032.         GetTextMetrics(hDC, & tm);
  1033.  
  1034.         const TCHAR * mess = "3.14159";
  1035.  
  1036.         RECT rect = { x-10, y+40, x+250, y+20 };
  1037.  
  1038.         ExtTextOut(hDC, x, y, ETO_OPAQUE, & rect, mess, _tcslen(mess), NULL);
  1039.  
  1040.         y += tm.tmHeight + tm.tmExternalLeading;
  1041.  
  1042.         RECT rect1 = { x-10, y+40, x+250, y+20 };
  1043.  
  1044.         ExtTextOut(hDC, x, y, ETO_CLIPPED, & rect1, mess, _tcslen(mess), NULL);
  1045.  
  1046.         y += tm.tmHeight + tm.tmExternalLeading;
  1047.  
  1048.         RECT rect2 = { x-10, y+40, x+250, y+20 };
  1049.  
  1050.         ExtTextOut(hDC, x, y, ETO_CLIPPED | ETO_OPAQUE, & rect2, mess, _tcslen(mess), NULL);
  1051.  
  1052.         y += tm.tmHeight + tm.tmExternalLeading;
  1053.  
  1054.         ExtTextOut(hDC, x, y, ETO_NUMERICSLATIN, NULL, mess, _tcslen(mess), NULL);
  1055.  
  1056.         int dx[] = { 30, 30, 30, 30, 30, 30, 30, 30 };
  1057.         y += tm.tmHeight + tm.tmExternalLeading;
  1058.         
  1059.         ExtTextOut(hDC, x, y, ETO_NUMERICSLOCAL, NULL, mess, _tcslen(mess), dx);
  1060.     }
  1061.  
  1062. }
  1063.  
  1064.  
  1065. //////////////////////////////////////////
  1066.  
  1067.  
  1068. void Demo_GlyphOutline(HDC hDC)
  1069. {
  1070.     KLogFont lf(-PointSizetoLogical(hDC, 96), "Times New Roman");
  1071.     lf.m_lf.lfItalic  = TRUE;
  1072.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1073.  
  1074.     KGDIObject font(hDC, lf.CreateFont());
  1075.  
  1076.     int x = 20; int y = 160;
  1077.     int dx, dy;
  1078.     
  1079.     SetTextAlign(hDC, TA_BASELINE | TA_LEFT);
  1080.  
  1081.     SetBkColor(hDC,   RGB(0xFF, 0xFF, 0)); // yellow
  1082.     SetTextColor(hDC, RGB(0, 0, 0xFF));       // blue
  1083. //    SetBkMode(hDC, TRANSPARENT);
  1084.  
  1085. //    MAT2 mat2;
  1086. //    mat2.eM11 = MakeFixed(cos(0.1));
  1087. //    mat2.eM12 = MakeFixed(sin(0.1));
  1088. //    mat2.eM21 = MakeFixed(-sin(0.1));
  1089. //    mat2.eM22 = MakeFixed(cos(0.1));
  1090.  
  1091.     KGlyph glyph;
  1092.  
  1093.     TextOut(hDC, x, y, "1248", 4); y+= 150;
  1094.  
  1095.     glyph.GetGlyph(hDC, '1', GGO_BITMAP); // , & mat2);
  1096.     glyph.DrawGlyph(hDC, x, y, dx, dy);    x+=dx;
  1097.  
  1098.     glyph.GetGlyph(hDC, '2', GGO_GRAY2_BITMAP); // , & mat2);
  1099.     glyph.DrawGlyph(hDC, x, y, dx, dy); x+=dx;
  1100.  
  1101.     glyph.GetGlyph(hDC, '4', GGO_GRAY4_BITMAP); // , & mat2);
  1102.     glyph.DrawGlyph(hDC, x, y, dx, dy); x+=dx;
  1103.  
  1104.     glyph.GetGlyph(hDC, '8', GGO_GRAY8_BITMAP); // , & mat2);
  1105.     glyph.DrawGlyph(hDC, x, y, dx, dy); x+=dx;
  1106.  
  1107.     OutlineTextOut(hDC, x+50, 130, "Outline", -1);
  1108.  
  1109.     SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
  1110.     SetTextColor(hDC, RGB(0, 0, 0));
  1111.     
  1112.     TextOut(hDC, x+50, 250, "Outline", 7);
  1113. }
  1114.  
  1115.  
  1116.  
  1117. void Demo_TabbedTextOut(HDC hDC)
  1118. {
  1119.     int tabstop[] = { -120, 125, 250 };
  1120.  
  1121.     const TCHAR * lines[] = 
  1122.     { 
  1123.         "Group" "\t"  "Result" "\t" "Function"    "\t" "Parameters",
  1124.         "Font"  "\t"  "DWORD"  "\t" "GetFontData" "\t" "(HDC hdc, ...)",
  1125.         "Text"  "\t"  "BOOL"   "\t" "TextOut"     "\t" "(HDC hdc, ...)"
  1126.     };
  1127.  
  1128.     int x=50, y=50;
  1129.     
  1130.     for (int i=0; i<3; i++)
  1131.         y += HIWORD(TabbedTextOut(hDC, x, y, lines[i], _tcslen(lines[i]), 
  1132.                 sizeof(tabstop)/sizeof(tabstop[0]), tabstop, x));
  1133.  
  1134. //    for (i=0; i<5; i++)
  1135. //        Line(hDC, x + abs(tabstop[i]), 0, x + abs(tabstop[i]), 100);
  1136.  
  1137.     {
  1138.         KLogFont lf(-PointSizetoLogical(hDC, 10), "MS Shell Dlg");
  1139.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1140.  
  1141.         KGDIObject font(hDC, lf.CreateFont());
  1142.  
  1143.         {
  1144.             const TCHAR * mess = 
  1145.                 "The DrawText function draws formatted text in the specified rectangle. "
  1146.                 "It formats the text according to the specified method (expanding tabs, "
  1147.                 "justifying characters, breaking lines, and so forth).";
  1148.  
  1149.             int width = 170;
  1150.             int x     = 220;
  1151.             RECT rect = { x, 120, x+width, 120+60 };
  1152.     
  1153.             SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
  1154.  
  1155.             int opt[] = { DT_WORDBREAK | DT_LEFT,
  1156.                       DT_WORDBREAK | DT_CENTER,
  1157.                       DT_WORDBREAK | DT_RIGHT | DT_EDITCONTROL
  1158.                     };
  1159.  
  1160.             for (i=0; i<3; i++)
  1161.             {
  1162.                 Box(hDC, rect.left-1, rect.top-1, rect.right+1, rect.bottom+1);
  1163.                 DrawText(hDC, mess, _tcslen(mess), & rect, opt[i]);
  1164.  
  1165.                 OffsetRect(&rect, 0, rect.bottom - rect.top + 10);
  1166.             }
  1167.  
  1168.             x += width + 10;
  1169.             {
  1170.                 KLogFont lf(-PointSizetoLogical(hDC, 20), "MS Shell Dlg");
  1171.                 lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1172.  
  1173.                 KGDIObject font(hDC, lf.CreateFont());
  1174.  
  1175.                 RECT rect2 = { x, 120, x+width*2, 120 + 120 };
  1176.                 Box(hDC, rect2.left-1, rect2.top-1, rect2.right+1, rect2.bottom+1);
  1177.                 DrawText(hDC, mess, _tcslen(mess), & rect2, DT_WORDBREAK | DT_LEFT);
  1178.             }
  1179.         }
  1180.  
  1181.         {
  1182.             const TCHAR * mess =
  1183.                 "&Open \tc:\\Win\\system32\\gdi32.dll";
  1184.  
  1185.             RECT rect = { 20, 120, 20+180, 120 + 32 };
  1186.  
  1187.             int opt[] = { DT_SINGLELINE | DT_TOP,
  1188.                           DT_SINGLELINE | DT_VCENTER | DT_EXPANDTABS,
  1189.                           DT_SINGLELINE | DT_BOTTOM  | DT_EXPANDTABS | DT_PATH_ELLIPSIS,
  1190.                           DT_SINGLELINE | DT_NOPREFIX | DT_EXPANDTABS | DT_WORD_ELLIPSIS,
  1191.                           DT_SINGLELINE | DT_HIDEPREFIX | DT_EXPANDTABS | DT_END_ELLIPSIS,
  1192.                         };
  1193.  
  1194.             for (i=0; i<5; i++)
  1195.             {
  1196.                 Box(hDC, rect.left-1, rect.top-1, rect.right+1, rect.bottom+1);
  1197.                 DrawText(hDC, mess, _tcslen(mess), & rect, opt[i]);
  1198.  
  1199.                 OffsetRect(&rect, 0, rect.bottom - rect.top + 10);
  1200.             }
  1201.         }
  1202.     }
  1203. }
  1204.  
  1205.  
  1206.  
  1207. void Demo_Paragraph(HDC hDC, bool bPrecise)
  1208. {
  1209.     const TCHAR * mess = 
  1210.         "The DrawText function draws formatted text in the specified rectangle. "
  1211.         "It formats the text according to the specified method (expanding tabs, "
  1212.         "justifying characters, breaking lines, and so forth).";
  1213.  
  1214.     int x = 20;
  1215.     int y = 20;
  1216.  
  1217.     SetBkMode(hDC, TRANSPARENT);
  1218.  
  1219.     for (int size=6; size<=21; size+=3) // 6, 9, 12, 15, 18, 21
  1220.     {
  1221.         int width  = size * 42;
  1222.         int height = size *  5;
  1223.  
  1224.         KLogFont lf(-PointSizetoLogical(hDC, size), "MS Shell Dlg");
  1225.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1226.  
  1227.         KGDIObject font(hDC, lf.CreateFont());
  1228.  
  1229.         RECT rect = { x, y, x+width, y+height };
  1230.  
  1231.         if ( bPrecise )
  1232.         {
  1233.             KTextFormator format;
  1234.         
  1235.             format.Setup(hDC, (HFONT) font.m_hObj, (float) size);
  1236.  
  1237.             format.DrawText(hDC, mess, _tcslen(mess), & rect, DT_WORDBREAK | DT_LEFT);
  1238.         }
  1239.         else
  1240.             DrawText(hDC, mess, _tcslen(mess), & rect, DT_WORDBREAK | DT_LEFT);
  1241.  
  1242.         Box(hDC, rect.left-1, rect.top-1, rect.right+1, rect.bottom+1);
  1243.  
  1244.         y = rect.bottom + 10;
  1245.     }    
  1246. }
  1247.  
  1248.  
  1249.  
  1250. void Demo_TextColor(HDC hDC, HINSTANCE hInst)
  1251. {
  1252.     KLogFont lf(-PointSizetoLogical(hDC, 16), "Times New Roman");
  1253.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1254.     KGDIObject font(hDC, lf.CreateFont());
  1255.  
  1256.     int x = 10, y= 10;
  1257.     TEXTMETRIC tm;
  1258.     GetTextMetrics(hDC, & tm);
  1259.  
  1260.     SetBkMode(hDC, OPAQUE);
  1261.  
  1262.     for (int ci=0; ci<8; ci+=2)
  1263.     {
  1264.         const COLORREF Color[] = 
  1265.             { RGB(0xFF, 0, 0), RGB(0, 0xFF, 0), RGB(0, 0, 0xFF),
  1266.               RGB(0xFF, 0xFF, 0), RGB(0, 0xFF, 0xFF), RGB(0xFF, 0, 0xFF),
  1267.               RGB(0, 0, 0), RGB(0xFF, 0xFF, 0xFF)
  1268.             };
  1269.         
  1270.         TCHAR temp[64];
  1271.  
  1272.         SetTextColor(hDC, Color[ci]);
  1273.         SetBkColor(hDC,   Color[ci+1]);
  1274.  
  1275.         wsprintf(temp, "0x%06X 0x%06X", Color[ci], Color[ci+1]);
  1276.  
  1277.         TextOut(hDC, x, y, temp, _tcslen(temp));
  1278.  
  1279.         y+= tm.tmHeight + tm.tmExternalLeading;
  1280.     }
  1281.  
  1282.     {
  1283.         HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0xFF));
  1284.  
  1285.         const TCHAR * mess = "GrayString";
  1286.         x = 260; y = 10;
  1287.     
  1288.         KLogFont lf(-PointSizetoLogical(hDC, 64), "Times New Roman");
  1289.         lf.m_lf.lfItalic  = TRUE;
  1290.         lf.m_lf.lfWeight  = FW_BOLD;
  1291.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1292.         KGDIObject font(hDC, lf.CreateFont());
  1293.  
  1294.         GrayString(hDC, hBrush, NULL, (LPARAM) mess, _tcslen(mess), x, y, 0, 0);
  1295.  
  1296.         DeleteObject(hBrush);
  1297.  
  1298.         y+= 80;
  1299.  
  1300.         hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0xFF, 0, 0));
  1301.         SetBkColor(hDC, RGB(0, 0xFF, 0xFF));
  1302.         ColorText(hDC, x, y, "ColorText", 9, hBrush);
  1303.         DeleteObject(hBrush);
  1304.         y+= 80;
  1305.  
  1306.         {
  1307.             KLogFont lf(-PointSizetoLogical(hDC, 72), "Tahoma");
  1308.             lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1309.             lf.m_lf.lfWeight  = FW_BOLD;
  1310.             KGDIObject font(hDC, lf.CreateFont());
  1311.  
  1312.             HBITMAP hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TIGER));
  1313.                 BitmapText(hDC, x, y, "TIGER", 5, hBmp);
  1314.  
  1315.             BitmapText2(hDC, x, y+100, "TIGER", 5, hBmp);
  1316.             
  1317.             DeleteObject(hBmp);
  1318.         }
  1319.     }
  1320. }
  1321.  
  1322.  
  1323. typedef struct
  1324. {
  1325.     BITMAPINFOHEADER bmiHeader;
  1326.     RGBQUAD             bmiColors[256];
  1327. }    BITMAPINFO4BPP;
  1328.  
  1329. bool Disp(const TCHAR * pFileName, HDC hDC)
  1330. {
  1331.     if ( pFileName==NULL )
  1332.         return false;
  1333.  
  1334.     HANDLE handle = CreateFile(pFileName, GENERIC_READ, FILE_SHARE_READ, 
  1335.         NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1336.     
  1337.     if ( handle == INVALID_HANDLE_VALUE )
  1338.         return false;
  1339.  
  1340.     DWORD size = GetFileSize(handle, NULL);
  1341.  
  1342.     BYTE * pBits = new BYTE[size];
  1343.     
  1344.     DWORD dwRead;
  1345.     ReadFile(handle, pBits, size, & dwRead, NULL);
  1346.     CloseHandle(handle);
  1347.  
  1348.     BITMAPINFO4BPP bmi;
  1349.     memset(& bmi, 0, sizeof(bmi));
  1350.     
  1351.     int width  = 864;
  1352.     int height = 1763;
  1353.  
  1354.     bmi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
  1355.     bmi.bmiHeader.biWidth    = width;
  1356.     bmi.bmiHeader.biHeight   = height; // top-down DIB
  1357.     bmi.bmiHeader.biPlanes   = 1;
  1358.     bmi.bmiHeader.biBitCount = 4;
  1359.  
  1360.     for (int i=0; i<16; i++)
  1361.     {
  1362.         bmi.bmiColors[i].rgbRed   = i * 255 / 15;
  1363.         bmi.bmiColors[i].rgbGreen = i * 255 / 15;
  1364.         bmi.bmiColors[i].rgbBlue  = i * 255 / 15;
  1365.     }
  1366.  
  1367.     int bps = (width * 4 + 31)/32 * 4;
  1368.  
  1369.  
  1370.     BYTE * p = pBits;
  1371.  
  1372.     for (i=0; i<height; i++)
  1373.     {
  1374.         BYTE temp[512];
  1375.  
  1376.         for (int j=0; j<bps/2; j++)
  1377.             temp[j] = p[j*2];
  1378.  
  1379.         for (j=bps/2; j<bps; j++)
  1380.             temp[j] = p[j*2+1];
  1381.  
  1382.         memcpy(p, temp, bps);
  1383.  
  1384.         p += bps;
  1385.     }
  1386.  
  1387.     StretchDIBits(hDC, 0, 0, width, height, 0, 0, width, height,
  1388.         pBits, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, SRCCOPY);
  1389.     
  1390.     delete [] pBits;
  1391.  
  1392.     return true;
  1393. }
  1394.  
  1395. void Demo_TextStyle(HDC hDC)
  1396. {
  1397.     SetBkColor(hDC, RGB(0xFF, 0xFF, 0));
  1398.     SetTextColor(hDC, RGB(0, 0, 0xFF));
  1399.  
  1400.     for (int f=0; f<2; f++)
  1401.     {
  1402.         for (int i=0; i<11; i++)
  1403.         {
  1404.             KLogFont lf(-PointSizetoLogical(hDC, 48), "Times New Roman");
  1405.  
  1406.             if ( f==1 )
  1407.                 _tcscpy(lf.m_lf.lfFaceName, "Colonna MT");
  1408.  
  1409.             SetBkColor(hDC, RGB(0xFF, 0xFF, 0));
  1410.             SetTextColor(hDC, RGB(0, 0, 0xFF));
  1411.  
  1412.             int x = 10 + f*520 + (i/4)*145; 
  1413.             int y = 10 +         (i%4)* 80;
  1414.     
  1415.             switch ( i+2 )
  1416.             {
  1417.                 case 2: lf.m_lf.lfWeight  = FW_NORMAL; break;
  1418.             //    case 0: lf.m_lf.lfWeight  = FW_THIN;   break;
  1419.             //    case 1: lf.m_lf.lfWeight  = FW_BOLD;   break;
  1420.                 case 3: lf.m_lf.lfWeight  = FW_BLACK;  break;
  1421.             
  1422.                 case 4: lf.m_lf.lfQuality = ANTIALIASED_QUALITY; break;
  1423.             
  1424.                 case 5:    lf.m_lf.lfItalic  = TRUE;                 break;
  1425.  
  1426.                 case 6: lf.m_lf.lfItalic  = TRUE; 
  1427.                         lf.m_lf.lfWeight  = FW_BOLD;              break;
  1428.  
  1429.                 case 7: lf.m_lf.lfUnderline = TRUE;
  1430.                         break;
  1431.  
  1432.                 case 8: lf.m_lf.lfStrikeOut = TRUE;
  1433.                         break;
  1434.  
  1435.                 case 9: SetTextColor(hDC, RGB(0xFF, 0xFF, 0));
  1436.                         SetBkColor(hDC, RGB(0, 0, 0xFF));
  1437.                         break;
  1438.             }
  1439.         
  1440.             KGDIObject font(hDC, lf.CreateFont());
  1441.  
  1442.             const TCHAR * mess = "Style";
  1443.  
  1444.             SetBkMode(hDC, OPAQUE);
  1445.  
  1446.             switch ( i+2 )
  1447.             {
  1448.                 case 10: 
  1449.                     OffsetTextOut(hDC, x, y, "Shadow", 6, 4, 4, 
  1450.                         GetSysColor(COLOR_3DSHADOW), 0, 0, 0);
  1451.                     break;
  1452.  
  1453.                 case 11: 
  1454.                     SetTextColor(hDC, RGB(0xFF, 0xFF, 0));
  1455.                     SetBkColor(hDC, RGB(0xD0, 0xD0, 0));
  1456.                     OffsetTextOut(hDC, x, y, "Emboss", 6, 
  1457.                         -1, -1, GetSysColor(COLOR_3DLIGHT),
  1458.                          1,  1, GetSysColor(COLOR_3DDKSHADOW));
  1459.                     break;
  1460.  
  1461.                 case 12: 
  1462.                     SetTextColor(hDC, RGB(0xD0, 0xD0, 0));
  1463.                     OffsetTextOut(hDC, x, y, "Engrave", 7,
  1464.                         -1, -1, GetSysColor(COLOR_3DDKSHADOW),
  1465.                          1,  1, GetSysColor(COLOR_3DLIGHT));
  1466.                     break;
  1467.  
  1468.                 default:
  1469.                     TextOut(hDC, x, y, mess, _tcslen(mess));
  1470.             }
  1471.         }
  1472.     }
  1473.  
  1474. //    LoadFile("c:\\mail_img.bin", hDC);
  1475. }
  1476.  
  1477. const double pi = 3.141592654;
  1478.  
  1479. HFONT ScaleFont(HDC hDC, int percent)
  1480. {
  1481.     LOGFONT lf;
  1482.  
  1483.     GetObject(GetCurrentObject(hDC, OBJ_FONT), sizeof(lf), & lf);
  1484.  
  1485.     TEXTMETRIC tm;
  1486.     GetTextMetrics(hDC, & tm);
  1487.     lf.lfWidth = (tm.tmAveCharWidth * percent + 50)/100;
  1488.  
  1489.     return CreateFontIndirect(&lf);
  1490. }
  1491.  
  1492. void Demo_TextGeometry(HDC hDC)
  1493. {
  1494.     KLogFont lf(-PointSizetoLogical(hDC, 16), "MS Shell Dlg");
  1495.     lf.m_lf.lfQuality    = ANTIALIASED_QUALITY;
  1496.  
  1497.     SetBkColor(hDC, RGB(0xFF, 0xFF, 0));
  1498.     SetTextAlign(hDC, TA_LEFT | TA_TOP);
  1499.  
  1500.     int x0 =  10;
  1501.     int y0 = 310;
  1502.  
  1503.     for (int i=0; i<10; i++)
  1504.     {
  1505.         int degree = i * 10;
  1506.         int r      = 160;
  1507.  
  1508.         lf.m_lf.lfEscapement  = degree * 10;
  1509.         lf.m_lf.lfOrientation = 0;
  1510.  
  1511.         KGDIObject font(hDC, lf.CreateFont());
  1512.  
  1513.         TCHAR mess[32];
  1514.         wsprintf(mess, "%02dā–‘ deg", degree);
  1515.  
  1516.         int x =  x0 + (int)( r * cos(degree*pi/180) );
  1517.         int y =  y0 - (int)( r * sin(degree*pi/180) );
  1518.  
  1519.         if ( i < 5 )
  1520.         {
  1521.             SetGraphicsMode(hDC, GM_ADVANCED);
  1522.             SetBkMode(hDC, OPAQUE); // TRANSPARENT);
  1523.         }
  1524.         
  1525.         TextOut(hDC, x, y, mess, _tcslen(mess));
  1526.  
  1527.         if ( i < 5 )
  1528.         {
  1529.             SetGraphicsMode(hDC, GM_COMPATIBLE);
  1530.             SetBkMode(hDC, OPAQUE);
  1531.         }
  1532.  
  1533.         // MoveToEx(hDC, x0, y0, NULL);
  1534.         // LineTo(hDC, x, y);
  1535.     }
  1536.  
  1537.     x0 = 400;
  1538.     y0 =  20;
  1539.     {
  1540.         KLogFont lf(-PointSizetoLogical(hDC, 24), "@SimSun");
  1541.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1542.         lf.m_lf.lfCharSet = GB2312_CHARSET;
  1543.         lf.m_lf.lfEscapement  = 2700;
  1544.         lf.m_lf.lfOrientation = 2700;
  1545.         
  1546.         KGDIObject font(hDC, lf.CreateFont());
  1547.  
  1548.         SetBkColor(hDC, RGB(0xFF, 0xFF, 0));
  1549.  
  1550.         WCHAR line1[] = { 0x59D1, 0x82CF, 0x57CE, 0x5916, 0x5BD2, 0x5C71, 0x5BFA };
  1551.         WCHAR line2[] = { 0x591C, 0x534A, 0x949F, 0x58F0, 0x5230, 0x5BA2, 0x8239 };
  1552.  
  1553.         TextOutW(hDC, x0, y0, line1, 7);  x0 -= 45;
  1554.         TextOutW(hDC, x0, y0, line2, 7);  x0 -= 50;
  1555.         TextOut (hDC, x0, y0, "270 degree", 10);
  1556.     }
  1557.  
  1558.     
  1559.     x0 = 430;
  1560.     y0 = 20;
  1561.  
  1562.     {
  1563.         KLogFont lf(-PointSizetoLogical(hDC, 24), "Times New Roman");
  1564.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1565.  
  1566.         int linespace;
  1567.         KGDIObject font(hDC, lf.CreateFont());
  1568.         
  1569.         TEXTMETRIC tm;
  1570.  
  1571.         GetTextMetrics(hDC, & tm);
  1572.  
  1573.         linespace = tm.tmHeight + tm.tmExternalLeading;
  1574.  
  1575.         for (int ratio=25; ratio<=125; ratio+=25)
  1576.         {
  1577.             KGDIObject font(hDC, ScaleFont(hDC, ratio));
  1578.             
  1579.             TCHAR temp[64];
  1580.  
  1581.             wsprintf(temp, "%d%c W", ratio, '%');
  1582.             TextOut(hDC, x0, y0, temp, _tcslen(temp));
  1583.  
  1584.             SIZE size; 
  1585.             GetTextExtentPoint32(hDC, temp, _tcslen(temp), & size);
  1586.             y0 += size.cy + 5;
  1587.         }
  1588.     }
  1589.  
  1590.     {
  1591.         BeginPath(hDC);
  1592.         MoveToEx(hDC, 20, 40, NULL);
  1593.  
  1594.         POINT p[] = { 200, 0, 300, 500, 560, 250 };
  1595.         PolyBezierTo(hDC, p, 3);
  1596.         EndPath(hDC);
  1597.  
  1598.         KLogFont lf(-PointSizetoLogical(hDC, 22), "Times New Roman");
  1599.         lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1600.         KGDIObject font(hDC, lf.CreateFont());
  1601.  
  1602.         SetTextAlign(hDC, TA_LEFT | TA_BASELINE);
  1603. //        SetBkMode(hDC, TRANSPARENT);
  1604.  
  1605.         PathTextOut(hDC, "Text on a curve is possible with some simple math.");
  1606.     }
  1607.  
  1608. }
  1609.  
  1610.  
  1611. void Demo_TextasBitmap(HDC hDC)
  1612. {
  1613.     KLogFont lf(-PointSizetoLogical(hDC, 48), "Times New Roman");
  1614.     lf.m_lf.lfWeight  = FW_BOLD;
  1615.     lf.m_lf.lfItalic  = TRUE;
  1616.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1617.     KGDIObject font(hDC, lf.CreateFont());
  1618.  
  1619.     TEXTMETRIC tm;
  1620.     GetTextMetrics(hDC, & tm);
  1621.     int linespace = tm.tmHeight + tm.tmExternalLeading;
  1622.  
  1623.     SetTextAlign(hDC, TA_TOP | TA_LEFT);
  1624.     SetBkMode(hDC, TRANSPARENT);
  1625.     SetBkColor(hDC, RGB(0xFF, 0xFF, 0));
  1626.  
  1627.     // reflection
  1628.     {
  1629.         SaveDC(hDC);
  1630.  
  1631.         SetMapMode(hDC, MM_ANISOTROPIC);
  1632.         SetWindowExtEx(hDC, 1, 1, NULL);
  1633.         SetViewportExtEx(hDC, -1, -1, NULL);
  1634.         SetViewportOrgEx(hDC, 300, 100, NULL);
  1635.  
  1636.         ShowAxes(hDC, 600, 180);
  1637.  
  1638.         int x= 0, y = 0;
  1639.  
  1640.         const TCHAR * mess = "Reflection";
  1641.     
  1642.         SetTextAlign(hDC, TA_LEFT | TA_BASELINE);
  1643.         SetTextColor(hDC, RGB(0, 0, 0xFF)); // blue ( dark )
  1644.         BitmapTextOut(hDC, x, y, mess, _tcslen(mess), GGO_GRAY4_BITMAP);
  1645.  
  1646.         SetTextColor(hDC, RGB(0xFF, 0xFF, 0)); // yellow (ligh)
  1647.             TextOut(hDC, x, y, mess, _tcslen(mess));
  1648.  
  1649.         RestoreDC(hDC, -1);
  1650.     }
  1651.  
  1652.     {
  1653.         int x = 20;
  1654.         int y = 70;
  1655.  
  1656.         KLogFont lf(-PointSizetoLogical(hDC, 48), "Times New Roman");
  1657.         lf.m_lf.lfWeight = FW_BOLD;
  1658.         lf.m_lf.lfQuality= ANTIALIASED_QUALITY;
  1659.         KGDIObject font(hDC, lf.CreateFont());
  1660.  
  1661.         const TCHAR * mess = "Raster";
  1662.  
  1663.         SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
  1664.         SetTextColor(hDC, RGB(0xFF, 0, 0));
  1665.         BitmapTextOutROP(hDC, x, y, mess, _tcslen(mess), SRCAND);
  1666.  
  1667.         SetBkColor(hDC, RGB(0, 0, 0));
  1668.         SetTextColor(hDC, RGB(0, 0xFF, 0));
  1669.         BitmapTextOutROP(hDC, x+5, y+5, mess, _tcslen(mess), SRCINVERT);
  1670.  
  1671.         {
  1672.             x = 10;
  1673.             y = 160;
  1674.  
  1675.             KTextBitmap bmp;
  1676.  
  1677.             SetBkMode(hDC, OPAQUE);
  1678.             SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));
  1679.             SetTextColor(hDC, RGB(0, 0, 0xFF));
  1680.  
  1681.             const TCHAR * mess = "fuzzy";
  1682.             bmp.Convert(hDC, mess, _tcslen(mess), 7);
  1683.             
  1684.             for (int i=0; i<3; i++)
  1685.             {
  1686.                 bmp.Draw(hDC, x, y);
  1687.  
  1688.                 x += bmp.m_width + 10;
  1689.  
  1690.                 bmp.Blur();
  1691.                 bmp.Blur();
  1692.             }
  1693.         }
  1694.  
  1695.         {
  1696.             x = 10;
  1697.             y = 250;
  1698.  
  1699.             KTextBitmap bmp;
  1700.  
  1701.             SetBkMode(hDC, OPAQUE);
  1702.             SetBkColor(hDC, RGB(0xFF, 0xFF, 0xFF));   // white
  1703.             SetTextColor(hDC, RGB(0x80, 0x80, 0x80)); // gray
  1704.  
  1705.             const TCHAR * mess = "Soft-Shadow";
  1706.             bmp.Convert(hDC, mess, _tcslen(mess), 7);
  1707.             
  1708.             for (int i=0; i<8; i++)
  1709.                 bmp.Blur();
  1710.  
  1711.             bmp.Draw(hDC, x, y);
  1712.             
  1713.             SetBkMode(hDC, TRANSPARENT);
  1714.             SetTextColor(hDC, RGB(0, 0, 0xFF)); // blue
  1715.             TextOut(hDC, x-5, y-5, mess, _tcslen(mess));
  1716.         }
  1717.     }
  1718. }
  1719.  
  1720.  
  1721. const BITMAPINFO * LoadDIB(HMODULE hModule, LPCTSTR pBitmapName)
  1722. {
  1723.     HRSRC   hRes = FindResource(hModule, pBitmapName, RT_BITMAP);
  1724.  
  1725.     if ( hRes==NULL )
  1726.         return NULL;
  1727.  
  1728.     HGLOBAL hGlb = LoadResource(hModule, hRes);
  1729.  
  1730.     if ( hGlb==NULL )
  1731.         return NULL;
  1732.  
  1733.     return (const BITMAPINFO *) LockResource(hGlb);
  1734. }
  1735.  
  1736. int GetDIBColorCount(const BITMAPINFOHEADER & bmih)
  1737. {
  1738.     if ( bmih.biBitCount <= 8 )
  1739.         if ( bmih.biClrUsed )
  1740.             return bmih.biClrUsed;
  1741.         else
  1742.             return 1 << bmih.biBitCount;
  1743.     else if ( bmih.biCompression==BI_BITFIELDS )
  1744.         return 3 + bmih.biClrUsed;
  1745.     else
  1746.         return bmih.biClrUsed;
  1747. }
  1748.  
  1749.  
  1750. void DispResBitmap(HDC hDC, int x, int y, int resid, int & width, int & height)
  1751. {
  1752.     const BITMAPINFO * pBMI = LoadDIB(
  1753.         (HINSTANCE) GetWindowLong(WindowFromDC(hDC), GWL_HINSTANCE), 
  1754.         MAKEINTRESOURCE(resid));
  1755.     
  1756.     width  = pBMI->bmiHeader.biWidth;
  1757.     height = abs(pBMI->bmiHeader.biHeight);
  1758.  
  1759.     const BYTE * pBits = (const BYTE *) & pBMI->bmiColors[GetDIBColorCount(pBMI->bmiHeader)];
  1760.  
  1761.     StretchDIBits(hDC, x, y, width, height, 
  1762.         0, 0, width, height, pBits, pBMI, DIB_RGB_COLORS, SRCCOPY);
  1763. }
  1764.  
  1765.  
  1766. void Demo_TextasBitmap2(HDC hDC)
  1767. {
  1768.     int x = 50;
  1769.     int y = 50;
  1770.  
  1771.     KLogFont lf(-PointSizetoLogical(hDC, 36), "Times New Roman");
  1772.     KGDIObject font(hDC, lf.CreateFont());
  1773.  
  1774.     for (int i=0; i<2; i++)
  1775.     {
  1776.         int width, height;
  1777.  
  1778.         DispResBitmap(hDC, x, y, IDB_FULLTIGER, width, height);
  1779.  
  1780.         const TCHAR * mess = "Siberian Tiger";
  1781.         TransparentEmboss(hDC, mess, _tcslen(mess), 
  1782.             RGB(0x80, 0x80, 0), RGB(0xFF, 0xFF, 0xFF),
  1783.             // RGB(0x80, 0x80, 0x40), RGB(0xE0, 0xE0, 0xE0), 
  1784.             2, x+260, y-5);
  1785.  
  1786.         {
  1787.             KLogFont lf(-PointSizetoLogical(hDC, 20), "Impact");
  1788.             KGDIObject font(hDC, lf.CreateFont());
  1789.  
  1790.             const TCHAR * mess1 = "http://mercury.spaceports.com/~schmode/";
  1791.             TransparentEmboss(hDC, mess1, _tcslen(mess1), 
  1792.                 RGB(0xFF, 0xFF, 0xFF), RGB(0, 0, 0),
  1793.                 // RGB(0xE0, 0xE0, 0xE0), RGB(0xC0, 0xC0, 0x40), 
  1794.                 1, x+5, y+240);
  1795.         }
  1796.  
  1797.         y += height + 20;
  1798.     }
  1799. }
  1800.  
  1801.  
  1802. void Demo_TextasCurve(HDC hDC)
  1803. {
  1804.     KLogFont lf(-PointSizetoLogical(hDC, 72), "BookMan Old Style");
  1805.     lf.m_lf.lfWeight  = FW_BOLD;
  1806.     lf.m_lf.lfQuality = ANTIALIASED_QUALITY;
  1807.     KGDIObject font(hDC, lf.CreateFont());
  1808.  
  1809.     const TCHAR * mess = "gdi";
  1810.     SetBkMode(hDC, TRANSPARENT);
  1811.  
  1812.     KGDIObject yellowbrush(hDC, CreateSolidBrush(RGB(0xFF, 0xFF, 0))); 
  1813.  
  1814.     LOGBRUSH lb = { BS_SOLID, DIB_RGB_COLORS, 0 };
  1815.  
  1816.     for (int test=0; test<9; test++)
  1817.     {
  1818.         int x = 10 + (test % 3) * 180;
  1819.         int y = 10 + (test / 3) *  95;
  1820.  
  1821.         TCHAR num[16];
  1822.         wsprintf(num, "%d", test+1);
  1823.  
  1824.         dispsmall(hDC, x, y+20, 0, num);
  1825.  
  1826.         BeginPath(hDC);
  1827.         TextOut(hDC, x, y, mess, _tcslen(mess));
  1828.         EndPath(hDC);
  1829.  
  1830.         switch (test)
  1831.         {
  1832.             case 0:
  1833.                 StrokePath(hDC); // black outline
  1834.                 break;
  1835.  
  1836.             case 1:
  1837.                 FillPath(hDC);     // yellow fill
  1838.                 break;
  1839.  
  1840.             case 2:
  1841.                 StrokeAndFillPath(hDC); // black outline, yellow fill
  1842.                 break;
  1843.  
  1844.             case 3:                        // 3 pixel round-dot geometric pen
  1845.                 {
  1846.                     KGDIObject dotpen(hDC, ExtCreatePen(PS_GEOMETRIC | PS_DOT | PS_ENDCAP_ROUND | PS_JOIN_ROUND,
  1847.                         3, & lb, 0, NULL));
  1848.                     StrokePath(hDC);
  1849.                 }
  1850.                 break;
  1851.  
  1852.             case 4:                        // 15 pixel simple pen + fill
  1853.                 {
  1854.                     KGDIObject bluepen(hDC, CreatePen(PS_SOLID, 15, RGB(0, 0, 0xFF)));
  1855.                     SaveDC(hDC);
  1856.                     StrokeAndFillPath(hDC);
  1857.                     RestoreDC(hDC, -1);
  1858.                     FillPath(hDC);
  1859.                 }
  1860.                 break;
  1861.  
  1862.             case 5:                        // 15 pixel MITER pen + fill
  1863.                 {
  1864.                     KGDIObject miter(hDC, ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_JOIN_MITER,
  1865.                         15, & lb, 0, NULL));
  1866.                     SaveDC(hDC);
  1867.                     StrokeAndFillPath(hDC);
  1868.                     RestoreDC(hDC, -1);
  1869.                     FillPath(hDC);
  1870.                 }
  1871.                 break;
  1872.  
  1873.             case 6:
  1874.                 {
  1875.                     KGDIObject bluepen(hDC, CreatePen(PS_SOLID, 7, RGB(0, 0, 0xFF)));
  1876.                     SaveDC(hDC);
  1877.                     StrokeAndFillPath(hDC);
  1878.                     RestoreDC(hDC, -1);
  1879.                 }
  1880.                 SelectObject(hDC, GetStockObject(WHITE_PEN));
  1881.                 StrokePath(hDC);
  1882.                 break;
  1883.  
  1884.             case 7:
  1885.             case 8:
  1886.                 {
  1887.                     for (int width=17; width>1; width -=2)
  1888.                     {
  1889.                         // (85, 85, 0) -> (225, 225, 0)
  1890.                         KGDIObject pen (hDC, CreatePen(PS_SOLID, width, 
  1891.                                 RGB(0xFF - width*10, 0xFF - width*10, 0)) );
  1892.     
  1893.                         SaveDC(hDC);
  1894.                         StrokePath(hDC);
  1895.                         RestoreDC(hDC, -1);
  1896.                     }
  1897.  
  1898.                     if ( test==7 )
  1899.                         FillPath(hDC);
  1900.                     else
  1901.                     {
  1902.                         SetTextColor(hDC, RGB(0x40, 0x40, 0x00));    // dark yellow
  1903.                         TextOut(hDC, x-1, y-1, mess, _tcslen(mess));
  1904.  
  1905.                         SetTextColor(hDC, RGB(0xFF, 0xFF, 0));    
  1906.                         TextOut(hDC, x+1, y+1, mess, _tcslen(mess));
  1907.  
  1908.                         SetTextColor(hDC, RGB(0x80, 0x80, 0));        
  1909.                         TextOut(hDC, x, y, mess, _tcslen(mess));
  1910.                     }
  1911.                 }
  1912.                 break;
  1913.         }
  1914.     } 
  1915. }
  1916.  
  1917.  
  1918. class KMove : public KTransCurve
  1919. {
  1920.     int m_dx, m_dy;
  1921.  
  1922. public:
  1923.     KMove(int seg, int dx, int dy) : KTransCurve(seg)
  1924.     {
  1925.         m_dx = dx;
  1926.         m_dy = dy;
  1927.     }
  1928.  
  1929.     virtual Map(float x, float y, float & rx, float & ry)
  1930.     {
  1931.         rx = x + m_dx;
  1932.         ry = y + m_dy;
  1933.     }
  1934. };
  1935.  
  1936.  
  1937. class KWave : public KTransCurve
  1938. {
  1939.     int m_dx, m_dy;
  1940.  
  1941. public:
  1942.     KWave(int seg, int dx, int dy) : KTransCurve(seg)
  1943.     {
  1944.         m_dx = dx;
  1945.         m_dy = dy;
  1946.     }
  1947.  
  1948.     virtual Map(float x, float y, float & rx, float & ry)
  1949.     {
  1950.         rx = x + m_dx;
  1951.         ry = y + m_dy + (int) (sin(x/50.0) * 20); // 100 pixel cycle +-20
  1952.     }
  1953. };
  1954.  
  1955.  
  1956. class KRandom : public KTransCurve
  1957. {
  1958.     int m_dx, m_dy;
  1959.  
  1960. public:
  1961.     KRandom(int seg, int dx, int dy) : KTransCurve(seg)
  1962.     {
  1963.         m_dx = dx;
  1964.         m_dy = dy;
  1965.     }
  1966.  
  1967.     virtual Map(float x, float y, float & rx, float & ry)
  1968.     {
  1969.         rx = x + m_dx + (rand() % 7-3);
  1970.         ry = y + m_dy + (rand() % 7-3);
  1971.     }
  1972. };
  1973.  
  1974.  
  1975. class KExtrude : public KTransCurve
  1976. {
  1977.     int m_dx, m_dy;
  1978.     int m_x0, m_y0;
  1979.     
  1980.     int m_depth;
  1981.     int m_eye_x;
  1982.     int m_eye_y;
  1983.     int m_eye_z;
  1984.  
  1985. public:
  1986.     
  1987.     KExtrude(int seglen, int dx, int dy, int depth, int ex, int ey, int ez) : KTransCurve(seglen)
  1988.     {
  1989.         m_dx    = dx;
  1990.         m_dy    = dy;
  1991.         m_depth = depth;
  1992.  
  1993.         m_eye_x = ex;
  1994.         m_eye_y = ey;
  1995.         m_eye_z = ez;
  1996.     }
  1997.  
  1998.     virtual Map(float x, float y, float & rx, float & ry)
  1999.     {
  2000.         rx = x + m_dx;
  2001.         ry = y + m_dy;
  2002.     }
  2003.  
  2004.     void Map3D(long & x, long & y, int z)
  2005.     {
  2006.         x = ( m_eye_z * x - m_eye_x * z) / ( m_eye_z - z);
  2007.         y = ( m_eye_z * y - m_eye_y * z) / ( m_eye_z - z);
  2008.     }
  2009.  
  2010.     virtual BOOL DrvMoveTo(HDC hDC, int x, int y)
  2011.     {
  2012.         m_x0 = x;
  2013.         m_y0 = y;
  2014.  
  2015.         return TRUE;
  2016.     }
  2017.  
  2018.     virtual BOOL DrvLineTo(HDC hDC, int x1, int y1)
  2019.     {
  2020.         POINT p[5] = { m_x0, m_y0, 
  2021.                        x1,   y1,
  2022.                        x1,   y1,
  2023.                        m_x0, m_y0,
  2024.                        m_x0, m_y0 };
  2025.  
  2026.         Map3D(p[0].x, p[0].y, 0);
  2027.         Map3D(p[1].x, p[1].y, 0);
  2028.         Map3D(p[2].x, p[2].y, m_depth);
  2029.         Map3D(p[3].x, p[3].y, m_depth);
  2030.         Map3D(p[4].x, p[4].y, 0);
  2031.  
  2032.         m_x0 = x1;
  2033.         m_y0 = y1;
  2034.  
  2035.         return Polygon(hDC, p, 4);
  2036.     }
  2037.  
  2038.     virtual BOOL DrvBezierTo(HDC hDC, POINT p[])
  2039.     {
  2040.         DrvLineTo(hDC, p[0].x, p[0].y);
  2041.         DrvLineTo(hDC, p[1].x, p[1].y);
  2042.         
  2043.         return DrvLineTo(hDC, p[2].x, p[2].y);
  2044.     }
  2045. };
  2046.  
  2047.  
  2048. void Demo_TextasCurve2(HDC hDC)
  2049. {
  2050.     KLogFont lf(-PointSizetoLogical(hDC, 96), "Impact");
  2051.     KGDIObject font(hDC, lf.CreateFont());
  2052.  
  2053.     const TCHAR * mess = "CURVE";
  2054.     SetBkMode(hDC, TRANSPARENT);
  2055.     int x = 10, y= 0;
  2056.  
  2057.     KGDIObject yellowbrush(hDC, CreateSolidBrush(RGB(0xFF, 0xFF, 0))); 
  2058.  
  2059.     BeginPath(hDC);
  2060.     TextOut(hDC, x, y, mess, _tcslen(mess));
  2061.     EndPath(hDC);
  2062.  
  2063.     KPathData pd;
  2064.  
  2065.     pd.GetPathData(hDC);
  2066.  
  2067.     StrokeAndFillPath(hDC);
  2068.  
  2069.     {
  2070.         KWave wave(8, 360, 0);
  2071.         pd.Draw(hDC, wave, true);
  2072.         StrokeAndFillPath(hDC);
  2073.     }
  2074.  
  2075.     {
  2076.         KRandom random(12, 0, 140);
  2077.  
  2078.         pd.Draw(hDC, random, true);
  2079.         StrokeAndFillPath(hDC);
  2080.     }
  2081.  
  2082.     {
  2083.         KExtrude extrude(5, 360, 140, 2, 0, 0, -100);
  2084.  
  2085.         {
  2086.             KGDIObject darkyellowb(hDC, CreateSolidBrush(RGB(0x80, 0x80, 0))); 
  2087.             KGDIObject darkyellowp(hDC, CreatePen(PS_SOLID, 1, RGB(0x80, 0x80, 0))); 
  2088.             
  2089.             pd.Draw(hDC, extrude, false);
  2090.         }
  2091.  
  2092.         KMove move(12, 360, 140);
  2093.         pd.Draw(hDC, move, true);
  2094.         StrokeAndFillPath(hDC);
  2095.     }
  2096.  
  2097.     // text to region
  2098.     {
  2099.         BeginPath(hDC);
  2100.         TextOut(hDC, 30, 290, "Tiger", 5);
  2101.         EndPath(hDC);
  2102.  
  2103.         SelectClipPath(hDC, RGN_COPY);
  2104.         int width, height;
  2105.  
  2106.         DispResBitmap(hDC, 10, 280, IDB_FULLTIGER, width, height);
  2107.         SelectClipRgn(hDC, NULL);
  2108.         // TextOut(hDC, 30, 290, "Tiger", 5);
  2109.     }
  2110.  
  2111.     {
  2112.         KLogFont lf(-PointSizetoLogical(hDC, 512), "Wingdings");
  2113.         lf.m_lf.lfCharSet = SYMBOL_CHARSET;
  2114.  
  2115.         KGDIObject font(hDC, lf.CreateFont());
  2116.  
  2117.         const TCHAR * mess = "\x43";
  2118.         SetBkMode(hDC, OPAQUE);
  2119.         int x = 600, y = 10;
  2120.         
  2121.         SetBkMode(hDC, TRANSPARENT);
  2122.         BeginPath(hDC);
  2123.         TextOut(hDC, x, y, mess, _tcslen(mess));
  2124.         EndPath(hDC);
  2125.  
  2126.         HRGN hRgn = PathToRegion(hDC);
  2127.  
  2128.         FrameRgn(hDC, hRgn, (HBRUSH) GetStockObject(GRAY_BRUSH), 1, 1);
  2129.         DeleteObject(hRgn);
  2130.     }
  2131. }