Files
Slnkdwf/SlnkDWFImpl/TextFormatter.cpp
Jos Groot Lipman 80d0142c23 SLNKDWF 2.00
svn path=/Slnkdwf/trunk/; revision=12481
2007-08-01 13:42:28 +00:00

157 lines
4.7 KiB
C++

#include "StdAfx.h"
#include "TextFormatter.h"
// pixelsize: in logical space
BOOL KTextFormator::SetupPixel(HDC hDC, HFONT hFont, double pixelsize)
{
OUTLINETEXTMETRIC otm[3]; // big enough for the strings
if ( GetOutlineTextMetrics(hDC, sizeof(otm), otm)==0 )
return FALSE;
LOGFONT lf;
::GetObject(hFont, sizeof(lf), & lf);
int emsquare= otm[0].otmEMSquare; // get EM square size
double scale = 1.0;
if (lf.lfWidth != 0 && lf.lfHeight != 0)
scale = ((double)lf.lfWidth)/abs(lf.lfHeight)*emsquare/1024;
lf.lfHeight = - emsquare; // font size for 1:1 mapping
lf.lfWidth = 0; // original proportion rekenen
HFONT hRefFont = CreateFontIndirect(&lf);
HDC hRefDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hRefDC, hRefFont);
int nCharWidth[MaxCharNo];
GetCharWidth32(hRefDC, 0, MaxCharNo-1, nCharWidth);
if ( GetOutlineTextMetrics(hRefDC, sizeof(otm), otm)==0 )
return FALSE;
SelectObject(hRefDC, hOld);
DeleteObject(hRefDC);
DeleteObject(hRefFont);
m_fHeight = otm[0].otmTextMetrics.tmHeight * pixelsize / emsquare;
m_fLinespace = ( otm[0].otmTextMetrics.tmHeight + otm
[0].otmTextMetrics.tmExternalLeading) * pixelsize / emsquare;
for (int i=0; i<MaxCharNo; i++)
m_fCharWidth[i] = scale*((double) nCharWidth[i]) * pixelsize / emsquare;
return TRUE;
}
BOOL KTextFormator::Setup(HDC hDC, HFONT hFont, double pointsize)
{
//return SetupPixel(hDC, hFont, pointsize * GetDeviceCaps(hDC, LOGPIXELSY) / 72);
return SetupPixel(hDC, hFont, pointsize);
}
BOOL KTextFormator::GetTextExtent(HDC hdc, LPCTSTR lpString, int cbString,
double & width, double& height)
{
if ( cbString<=0 )
cbString = (int)_tcslen(lpString);
width = 0;
for (int i=0; i<cbString; i++)
width = width + m_fCharWidth[(unsigned)lpString[i]];
height = m_fHeight;
return TRUE;
}
// Genereer de tekst met een bepaalde spacing tussen de letters
// Let wel: daarnaast wordt ook nog nauwkeuriger de breedte van de tekst bepaald
BOOL KTextFormator::TextOutSpacing(HDC hDC, int x, int y, LPCTSTR pString, int nCount,
double dSpacing)
{
// return true;
// myDoTRACE("\nSpacing: %s, %.3f", pString, dSpacing);
int lastx = 0;
double sum = 0.0;
int Dx[MAX_PATH];
for (int i=0; i<nCount && i<MAX_PATH; i++)
{
//Dx[i] = int (m_fCharWidth[(unsigned)pString[i]]*dSpacing + 0.5);;
sum = sum + m_fCharWidth[(unsigned)pString[i]]*dSpacing;
int newx = myRound(sum);
Dx[i] = newx - lastx;
lastx = newx;
//sumdx += Dx[i];
}
return ExtTextOut(hDC, x, y, 0, NULL, pString, nCount, Dx);
}
// Tekst plaatsen en zeer krachtig forceren binnen BOUNDS breedte
// Nadeel: door de GetPath worden texten wel iets grover
BOOL KTextFormator::TextOutSize(HDC hDC, int x, int y, LPCTSTR pString, int nCount,
double dxWidth, double dxHeight)
{
ATLASSERT(false);
#if 0
niet gebruiken bij voorkeur. Geeft toch wel heel lelijke teksten
// Bepaal eerst de tekst als losse vectoren
BeginPath(hDC);
::TextOut(hDC, x, y, pString, nCount);
EndPath(hDC);
// Let wel: num_points hangt bij GDI automatisch van de zoomfactor af
const int num_points = GetPath(hDC, NULL, NULL, 0);
// myDoTRACE("Tekst %s, scaleXY %.4f/%.4f, num_points %d", pString, dxWidth, dxHeight, num_points);
if (num_points > 0)
{
// allocate memory for the point data and for the vertex types
LPPOINT p_points = new POINT[num_points];
LPBYTE p_types = new BYTE[num_points];
// get the path's description
GetPath(hDC, p_points, p_types, num_points);
//myTRACE(", points: %d", num_points);
//
// Let wel: aanroeper heeft al gecorrigeerd voor rotatie op dxWidth en dxHeight
for (int i = 0; i < num_points; i++)
{
p_points[i].x = x + myRound((p_points[i].x - x) * dxWidth);
p_points[i].y = y + myRound((p_points[i].y - y) * dxHeight);
}
//
// Make pen width 0, just in case
//HPEN hpenNew, hpenOld;
LOGPEN lp;
GetObject((HPEN)GetCurrentObject(hDC, OBJ_PEN), sizeof(LOGPEN), &lp);
lp.lopnWidth = CPoint(5,5);
myTempPEN tempPen(hDC, 0, GetTextColor(hDC));
// Via nieuw path zodat we kunnen vullen met FillPath
BeginPath(hDC);
PolyDraw(hDC, p_points, p_types, num_points);
EndPath(hDC);
// Make brush solid just in case
HBRUSH hbrushNew, hbrushOld;
LOGBRUSH lb;
lb.lbColor = GetTextColor(hDC);
//b.lbHatch = hatchCode;
lb.lbStyle = BS_SOLID;
hbrushNew = CreateBrushIndirect(&lb);
hbrushOld = (HBRUSH)SelectObject(hDC, hbrushNew);
StrokeAndFillPath(hDC);
// Opruimen
SelectObject(hDC, hbrushOld);
DeleteObject(hbrushNew);
delete [] p_points;
delete [] p_types;
}
#endif
return true;
}