Solved

KTextFormator of Feng Yuan

Posted on 2004-09-22
3
681 Views
Last Modified: 2013-12-03
I need the example code for the class KTextFormator from the book of Feng Yuan "Windows Graphics Programming". I has this book, but miss the CD with examples. Please help!
The common task is to otput the text in ANISOTROPIC mode with the random aspect ratio.
The text must have same width in all modes on screen and printer.
I give an additional 500 points for complete help.
0
Comment
Question by:alx512
  • 2
3 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 12123939
Are you looking for http://safariexamples.informit.com/0130869856/Samples/include/fonttext.h ?

#pragma once

//-----------------------------------------------------------------------------------//
//              Windows Graphics Programming: Win32 GDI and DirectDraw               //
//                             ISBN  0-13-086985-6                                   //
//                                                                                   //
//  Written            by  Yuan, Feng                             www.fengyuan.com   //
//  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
//  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
//                                                                                   //
//  FileName   : fonttext.h                                                                     //
//  Description: Font &  text routines and classes                                   //
//  Version    : 1.00.000, May 31, 2000                                              //
//-----------------------------------------------------------------------------------//

// convert point size to logical coordinate space size
int PointSizetoLogical(HDC hDC, int points, int divisor=1);

// Create a font as large as EM square size for accurate metrics
HFONT CreateReferenceFont(HFONT hFont, int & emsquare);

// justify text string within a left..right margin
BOOL TextOutJust(HDC hDC, int left, int right, int y, LPCTSTR lpStr, int nCount, bool bAllowNegative=false, TCHAR cBreakChar=' ');


// ABC extent of a text string
// ( A0, B0, C0 ) + ( A1, B1, C1 ) = ( A0, B0+C0+A1+B1, C1 }
BOOL GetTextABCExtent(HDC hDC, LPCTSTR lpString, int cbString, long * pHeight, ABC * pABC);

BOOL GetOpaqueBox(HDC hDC, LPCTSTR lpString, int cbString, RECT * pRect, int x, int y);

// Pixel-level precise text alignment
BOOL PreciseTextOut(HDC hDC, int x, int y, LPCTSTR lpString, int cbString);


class KLogFont
{
public:
      LOGFONT m_lf;

      KLogFont(int height, const TCHAR * typeface=NULL)
      {
            m_lf.lfHeight         = height;
            m_lf.lfWidth          = 0;
            m_lf.lfEscapement     = 0;
            m_lf.lfOrientation    = 0;
            m_lf.lfWeight         = FW_NORMAL;
            m_lf.lfItalic         = FALSE;
            m_lf.lfUnderline      = FALSE;
            m_lf.lfStrikeOut      = FALSE;
            m_lf.lfCharSet        = ANSI_CHARSET;
            m_lf.lfOutPrecision   = OUT_TT_PRECIS;
            m_lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;
            m_lf.lfQuality        = DEFAULT_QUALITY;
            m_lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;

            if ( typeface )
                  _tcsncpy(m_lf.lfFaceName, typeface, LF_FACESIZE-1);
            else
                  m_lf.lfFaceName[0] = 0;
      }

      HFONT CreateFont(void)
      {
            return ::CreateFontIndirect(& m_lf);
      }

      int GetObject(HFONT hFont)
      {
            return ::GetObject(hFont, sizeof(m_lf), & m_lf);
      }
};


template <int maxlength>
class KPlacement
{
public:
      GCP_RESULTS m_gcp;

      TCHAR            m_strOut[maxlength];
      int                  m_dx    [maxlength];
      unsigned      m_order [maxlength];
      int                  m_caret [maxlength];
      char            m_class [maxlength];
      WORD            m_glyphs[maxlength];

      DWORD GetPlacement(HDC hDC, const TCHAR * mess, DWORD flags=0, int maxextent=0)
      {
            memset(&m_gcp, 0, sizeof(m_gcp));
      
            m_gcp.lStructSize = sizeof(GCP_RESULTS);
            m_gcp.lpOutString = m_strOut;
            m_gcp.lpOrder     = m_order;
            m_gcp.lpDx        = m_dx;
            m_gcp.lpCaretPos  = m_caret;
            m_gcp.lpClass     = m_class;
            m_gcp.lpGlyphs    = m_glyphs;
            m_gcp.nGlyphs     = maxlength;

            return GetCharacterPlacement(hDC, mess, _tcslen(mess), maxextent, & m_gcp, flags);
      }

      BOOL GlyphTextOut(HDC hDC, int x, int y)
      {
            return ExtTextOut(hDC, x, y, ETO_GLYPH_INDEX, NULL, (LPCTSTR) m_glyphs, m_gcp.nGlyphs, m_dx);
      }
};


class KKerningPair
{
public:
      KERNINGPAIR * m_pKerningPairs;
      int                    m_nPairs;

      KKerningPair(HDC hDC)
      {
            m_nPairs = GetKerningPairs(hDC, 0, NULL);

            if ( m_nPairs==0 )
                  m_pKerningPairs = NULL;
            else
            {
                  m_pKerningPairs = new KERNINGPAIR[m_nPairs];
                  assert(m_pKerningPairs);

                  GetKerningPairs(hDC, m_nPairs, m_pKerningPairs);
            }
      }

      int GetKerning(TCHAR first, TCHAR second)
      {
            for (int i=0; i<m_nPairs; i++)
                  if ( (m_pKerningPairs[i].wFirst ==first) &&
                         (m_pKerningPairs[i].wSecond==second) )
                         return m_pKerningPairs[i].iKernAmount;

            return 0;
      }

      ~KKerningPair(void)
      {
            if ( m_pKerningPairs )
            {
                  delete m_pKerningPairs;
                  m_pKerningPairs = NULL;
            }
      }
};


class KGlyph
{
public:
      GLYPHMETRICS  m_metrics;
      BYTE *        m_pPixels;
      DWORD              m_nAllocSize;
      DWORD              m_nDataSize;
      int                    m_uFormat;

      KGlyph()
      {
            m_pPixels = NULL;
      }

      ~KGlyph(void);

      DWORD GetGlyph(HDC hDC, UINT uChar, UINT uFormat, const MAT2 * pMat2=NULL);
      
      BOOL  DrawGlyphROP(HDC HDC, int x, int y, DWORD rop, COLORREF crBack, COLORREF crFore);
      BOOL  DrawGlyph(HDC HDC, int x, int y, int & dx, int & dy);
};


template <int MAX_POINTS>
class KGlyphOutline
{
public:
      POINT m_Point[MAX_POINTS];
      BYTE  m_Flag [MAX_POINTS];

      int   m_nPoints;

private:
      void AddPoint(int x, int y, BYTE flag)
      {
            if ( m_nPoints < MAX_POINTS )
            {
                  m_Point[m_nPoints].x = x;
                  m_Point[m_nPoints].y = y;
                  m_Flag [m_nPoints]   = flag;
                  m_nPoints ++;
            }
            else
                  assert(false);
      }

      void AddQSpline(int x1, int y1, int x2, int y2)
      {
            assert(m_nPoints);

            // p0 p1 p2 -> p0 (p0+2p1)/3 (2p1+p2)/3, p2
            int x0 = m_Point[m_nPoints-1].x;
            int y0 = m_Point[m_nPoints-1].y;

            AddCSpline((x0+2*x1)/3, (y0+2*y1)/3, (2*x1+x2)/3, (2*y1+y2)/3, x2, y2);
      }

      void AddCSpline(int x1, int y1, int x2, int y2, int x3, int y3)
      {
            assert(m_nPoints);

            AddPoint(x1, y1, PT_BEZIERTO);
            AddPoint(x2, y2, PT_BEZIERTO);
            AddPoint(x3, y3, PT_BEZIERTO);
      }

      void MarkLast(BYTE flag)
      {
            assert(m_nPoints);
            m_Flag[m_nPoints-1] |= flag;
      }

      void Transform(int dx, int dy)
      {
            for (int i=0; i<m_nPoints; i++)
            {
                  m_Point[i].x = (   m_Point[i].x + 32768 ) / 65536 + dx;
                  m_Point[i].y = ( - m_Point[i].y + 32768 ) / 65536 + dy;
            }
      }

public:
      int DecodeTTPolygon(const TTPOLYGONHEADER * lpHeader, int size);

      BOOL Draw(HDC hDC, int x, int y)
      {
            Transform(x, y);
      
            return PolyDraw(hDC, m_Point, m_Flag, m_nPoints);
      }

      int DecodeOutline(KGlyph & glyph)
      {
            if ( (glyph.m_uFormat==GGO_NATIVE) || (glyph.m_uFormat==GGO_BEZIER) )
                  return DecodeTTPolygon((const TTPOLYGONHEADER *) glyph.m_pPixels, glyph.m_nDataSize);
            else
                  return 0;
      }

};


template <int MAX_POINTS>
int KGlyphOutline<MAX_POINTS>::DecodeTTPolygon(const TTPOLYGONHEADER * pHeader, int size)
{
      m_nPoints = 0;

      while ( size>sizeof(TTPOLYGONHEADER) )
    {
            int curvesize = pHeader->cb;

            size -= curvesize;

            if ( size<0 )
            {
                  assert(false);
                  break;
            }

            if (pHeader->dwType != TT_POLYGON_TYPE)
            {
                  assert(false);
                  break;
            }

            const POINT * p = (const POINT *) & pHeader->pfxStart;

            AddPoint(p[0].x, p[0].y, PT_MOVETO);

            const TTPOLYCURVE * pCurve = (const TTPOLYCURVE *) & pHeader[1];
            
            while ( (unsigned) pCurve < ( ((unsigned) pHeader) + curvesize) )
            {
                  int i;

                  p = (const POINT *) pCurve->apfx;

                  switch ( pCurve->wType )
                  {
                        case TT_PRIM_LINE:            // polyline.
                              for (i=0; i<pCurve->cpfx; i++)
                                    AddPoint(p[i].x, p[i].y, PT_LINETO);
                              break;

                        case TT_PRIM_QSPLINE:      // quadratic Bézier spline.
                              assert(pCurve->cpfx>=2);

                              for (i=0; i<(pCurve->cpfx-1); i++)
                                    if ( i==(pCurve->cpfx-2) )
                                          AddQSpline(p[i].x, p[i].y, p[i+1].x, p[i+1].y);
                                    else
                                          AddQSpline(
                                                p[i].x,
                                                p[i].y,
                                                ( p[i].x + p[i+1].x ) / 2,
                                                ( p[i].y + p[i+1].y ) / 2);
                              break;

                        case TT_PRIM_CSPLINE:      // cubic Bezier spline
                              assert((pCurve->cpfx % 3) ==0);
                              for (i=0; i<pCurve->cpfx; i+=3)
                                    AddCSpline(p[i].x, p[i].y, p[i+1].x, p[i+1].y, p[i+2].x, p[i+2].y);
                              break;

                        default:
                              assert(false);
                              return 0;
                  }

                  pCurve = (const TTPOLYCURVE *) & pCurve->apfx[pCurve->cpfx];
            }

            MarkLast(PT_CLOSEFIGURE);

            pHeader = (const TTPOLYGONHEADER *) ((unsigned) pHeader + curvesize);
    }

      return m_nPoints;
}

BOOL BitmapTextOut(HDC hDC, int x, int y, const TCHAR * str, int count, int format = GGO_BITMAP);
BOOL BitmapTextOutROP(HDC hDC, int x, int y, const TCHAR * str, int count, DWORD rop);

BOOL OutlineTextOut(HDC hDC, int x, int y, const TCHAR * str, int count);

///////////////////////////////////////////////////////////

class KTextFormator
{
      typedef enum { MaxCharNo = 256 };

      float m_fCharWidth[MaxCharNo];
      float m_fHeight;
      float m_fLinespace;

public:

      BOOL  SetupPixel(HDC hDC, HFONT hFont, float pixelsize);
      BOOL  Setup(HDC hDC, HFONT hFont, float pointsize);

      float GetLinespace(void) const
      {
            return m_fLinespace;
      }

      BOOL  GetTextExtent(HDC hdc, LPCTSTR pString, int cbString, float & width, float & height);
      BOOL  TextOut(HDC hDC, int x, int y, LPCTSTR pString, int nCount);
      DWORD DrawText(HDC hDC, LPCTSTR pString, int nCount, const RECT * pRect, UINT uFormat);
};


BOOL ColorText(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBRUSH hFore);
 BOOL BitmapText(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBITMAP hBmp);
BOOL BitmapText2(HDC hDC, int x, int y, LPCTSTR pString, int nCount, HBITMAP hBmp);
BOOL OffsetTextOut(HDC hDC, int x, int y, LPCTSTR pStr, int nCount,
                           int dx1, int dy1, COLORREF cr1,
                           int dx2, int dy2, COLORREF cr2);

BOOL DrawChar(HDC hDC, double x0, double y0, double x1, double y1, TCHAR ch);
void PathTextOut(HDC hDC, LPCTSTR pString, POINT point[], int no);
BOOL PathTextOut(HDC hDC, LPCTSTR pString);


// 3x3 average filter for any 8-bpp, 24-bpp, or 32-bpp frame buffer
template <int bytepp>
void Average(BYTE * pBits, int pitch, int width, int height)
{
      BYTE * buffer = new BYTE[pitch*2];

      for (int y=1; y<height; y++)
      {
            pBits += pitch; // first channel of pixel 0

            if ( y<(height-1) )
            {
                  BYTE * P = pBits + bytepp;                        // pixel 1
                  BYTE * B = buffer + pitch * (y & 1);      // pixel 1..n-2      

                  for (int x=1; x<(width-1); x++)
                  {
                        for (int b=0; b<bytepp; b++)
                        {
                              B[0] = ( P[-pitch-bytepp] + P[-pitch] + P[-pitch+bytepp] +
                                           P[      -bytepp] + P[     0] + P[       bytepp] +
                                           P[ pitch-bytepp] + P[ pitch] + P[ pitch+bytepp])/9;

                              P ++;
                              B ++;
                        }
                  }
            }

            if ( y>=2 )
            {
                  memcpy(pBits-pitch+bytepp, buffer + pitch * ( 1 - (y & 1)), (width-2) * bytepp);
            }
      }

      delete [] buffer;
}


// Conver text string to bitmap
class KTextBitmap
{
public:
      
      HBITMAP            m_hBitmap;
      HDC                m_hMemDC;
      HGDIOBJ            m_hOldBmp;
      int                  m_width;
      int                  m_height;
      int                  m_dx;
      int                  m_dy;
      BYTE *      m_pBits;

      BOOL Convert(HDC hDC, LPCTSTR pString, int nCount, int extra);

      void ReleaseBitmap(void)
      {
            if ( m_hOldBmp )
            {
                  SelectObject(m_hMemDC, m_hOldBmp);
                  m_hOldBmp = NULL;
            }

            if ( m_hBitmap )
            {
                  DeleteObject(m_hBitmap);
                  m_hBitmap = NULL;
            }
      }

      KTextBitmap()
      {
            m_hBitmap = NULL;
            m_hMemDC  = NULL;
            m_hOldBmp = NULL;
      }

      ~KTextBitmap()
      {
            if ( m_hMemDC )
            {
                  DeleteObject(m_hMemDC);
                  m_hMemDC = NULL;
            }
      }

      void Blur(void);

      BOOL Draw(HDC hDC, int x, int y, int rop=SRCCOPY)
      {
            return BitBlt(hDC, x - m_dx, y - m_dy, m_width, m_height,
                            m_hMemDC, 0, 0, rop);
      }

      BOOL RenderText(HDC hDC, int x, int y, const TCHAR * pString, int nCount);
};

// Embossing or Engraving by change edges only, good for non-solod background
void TransparentEmboss(HDC hDC, const TCHAR * pString, int nCount, COLORREF crTL, COLORREF crBR, int offset, int x, int y);
      

0
 
LVL 1

Author Comment

by:alx512
ID: 12130357
I need the code for the following methods:
KTextFormator::GetTextExtent(HDC hdc, LPCTSTR pString, int cbString, float & width, float & height);
KTextFormator::TextOut(HDC hDC, int x, int y, LPCTSTR pString, int nCount);
KTextFormator::DrawText(HDC hDC, LPCTSTR pString, int nCount, const RECT * pRect, UINT uFormat);
0
 
LVL 1

Author Comment

by:alx512
ID: 12130994
I think the another way to solve this problem is to use the gdi+.
I take the good results with graphics.DrawString method
after scaling with graphics.SetTransform.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
TFS Branching 4 63
Windows Installer 4 59
How To Display a Conditional Image in a Microsoft Access Report 23 76
Windows Process running 3 40
This article describes how to add a user-defined command button to the Windows 7 Explorer toolbar.  In the previous article (http://www.experts-exchange.com/A_2172.html), we saw how to put the Delete button back there where it belongs.  "Delete" is …
A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now