This topic is now archived and is closed to further replies.


storing something in a compact grid

Recommended Posts

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 -

Share this post

Link to post
Share on other sites
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.

// to get a color
COLORREF RGB(Red, Green, Blue)

Share this post

Link to post
Share on other sites

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 (C) 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(C))
repeat until M is a factor of C (C/M has no remainder)
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).

Share this post

Link to post
Share on other sites

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);

short FindOptimumGrid(BYTE nChars)
while (byFactor1 < byFactor2)
if (nChars % byCurrentDivisor == 0)
byFactor1 = byCurrentDivisor;
byFactor2 = nChars / 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(C)), what is ceil()?

- outRider -

Share this post

Link to post
Share on other sites
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.

Share this post

Link to post
Share on other sites