Started by Aug 08 2001 05:11 PM

,
4 replies to this topic

Posted 08 August 2001 - 05:11 PM

Forgive the vague subject, I couldn''t find the words to accurately describe my question that space.
What I''m trying to do is draw a GDI font onto a GDI bitmap to use elsewhere. Lets say I want to draw 224 characters onto a bitmap, I can draw them all in a row and have a bitmap that''s 2042* 8 or something like that. What I want to do is find a way to make the bitmap as square as possible by putting them in rows/columns. In the above case the best way would be to have a 14*16 grid or a 16*14, but what if I have some other value, like say 96 characters, or 256, or 64, or 15, or 77?
Any help anyone can offer would be appreciated.
------------
- outRider -

Posted 10 August 2001 - 05:35 AM

DrawText( HDC hDC, // device context hnd

LPCTSTR lpString, // Pointer to string to draw

int nCount, // string length, in characters

LPRECT lpRect, // ptr to bounding RECT

UINT uFormat); // flags

// DT_LEFT formats to left

// Look in Win32 doc for more flags

// Both return the old color, so you can set it back when done.

COLORREF SetTextColor(HDC hDC, COLORREF Color);

COLORREF SetBkColor(HDC hDC, COLORREF Color);

// to get a color

COLORREF RGB(Red, Green, Blue)

LPCTSTR lpString, // Pointer to string to draw

int nCount, // string length, in characters

LPRECT lpRect, // ptr to bounding RECT

UINT uFormat); // flags

// DT_LEFT formats to left

// Look in Win32 doc for more flags

// Both return the old color, so you can set it back when done.

COLORREF SetTextColor(HDC hDC, COLORREF Color);

COLORREF SetBkColor(HDC hDC, COLORREF Color);

// to get a color

COLORREF RGB(Red, Green, Blue)

Posted 10 August 2001 - 07:29 AM

Uh...

To reply to the original question, I assume that your characters are square. Otherwise, you have more math on your hands.

You are given the total number of characters © and would like to place them in a grid as close to square as possible, with M rows of N columns each.

this is a pseudo-algorithm to do that:

let M=ceil(sqrt©)

repeat until M is a factor of C (C/M has no remainder)

M--

now, N=C/M

What this does is assume that M and N are equal so that MM=C. If this doesn''t work out quite right, we will use this as a starting point and work down until we hit a number that works.

This will not work if C is a prime number (in which case, you could increase C by one and try again).

To reply to the original question, I assume that your characters are square. Otherwise, you have more math on your hands.

You are given the total number of characters © and would like to place them in a grid as close to square as possible, with M rows of N columns each.

this is a pseudo-algorithm to do that:

let M=ceil(sqrt©)

repeat until M is a factor of C (C/M has no remainder)

M--

now, N=C/M

What this does is assume that M and N are equal so that MM=C. If this doesn''t work out quite right, we will use this as a starting point and work down until we hit a number that works.

This will not work if C is a prime number (in which case, you could increase C by one and try again).

Posted 10 August 2001 - 05:21 PM

MartinJ,

They aren''t necessarily square, the height is whatever I pass to CreateFont, but the width is different for each character in the font face. Here''s what I have so far:

That works fine, but if the amount of characters wont fit equally on the grid it doesn''t work, just because as CurrentDivisor increases, depending on the amount of characters, nChars % CurrentDivisor wont end up being zero... I''m not sure how to deal with that really.

Anyway, MartinJ, M=ceil(sqrt©), what is ceil()?

------------

- outRider -

They aren''t necessarily square, the height is whatever I pass to CreateFont, but the width is different for each character in the font face. Here''s what I have so far:

hFont = CreateFont(-byHeight, 0, 0, 0, FW_NORMAL, false, false, false, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE | DEFAULT_PITCH, pszFontname);

SelectObject(hDC, hFont);

GetTextMetrics(hDC, &tm);

rVal = FindOptimumGrid(byEndChar - (byStartChar - 1));

iGridWidth = LOBYTE(rVal) * tm.tmMaxCharWidth;

iGridHeight = HIBYTE(rVal) * tm.tmHeight;

BmpInfo.bmiHeader.biWidth = iGridWidth;

BmpInfo.bmiHeader.biHeight = iGridHeight;

hBmp = CreateDIBSection(hDC, &BmpInfo, DIB_RGB_COLORS, NULL, NULL, NULL);

SelectObject(hDC, hBmp);

for (y = 0; y < iGridHeight; y += tm.tmHeight)

{

for (x = 0; x < iGridWidth; x += tm.tmMaxCharWidth)

{

TextOut(hDC, x, y, &byCurrentChar, 1);

byCurrentChar++;

}

}

short FindOptimumGrid(BYTE nChars)

{

while (byFactor1 < byFactor2)

{

if (nChars % byCurrentDivisor == 0)

{

byFactor1 = byCurrentDivisor;

byFactor2 = nChars / byCurrentDivisor;

}

byCurrentDivisor++;

}

byOptimumGrid = byFactor1;

byOptimumGrid += byFactor2 << 8;

return iOptimumGrid;

}

That works fine, but if the amount of characters wont fit equally on the grid it doesn''t work, just because as CurrentDivisor increases, depending on the amount of characters, nChars % CurrentDivisor wont end up being zero... I''m not sure how to deal with that really.

Anyway, MartinJ, M=ceil(sqrt©), what is ceil()?

------------

- outRider -

Posted 10 August 2001 - 06:28 PM

ceil() should bring back an integer, always rounding up. Unless I''ve been sniffing the glue on the back of the post-it notes too much. It could be named something else... that''s just what I thought it was called. I just used that to get an integer number (you really can''t have 1.354 cells across).

Since each character has a different width, I can''t think of anything other than brute force.

Since each character has a different width, I can''t think of anything other than brute force.