[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

KTextFormator of Feng Yuan

Posted on 2004-09-22
3
Medium Priority
?
708 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 1500 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

 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows a few slightly more advanced techniques for Windows 7 gadget programming, including how to save and restore user settings for your gadget and how to populate the "details" panel that is displayed in the Windows 7 gadget gallery.  …
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
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…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …

656 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