storing something in a compact grid
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 -
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)
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 (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)
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 (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)
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).
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(C)), 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(C)), what is ceil()?
------------
- outRider -
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement