| 82 | } |
| 83 | |
| 84 | HRESULT Initialize(const WCHAR* fontName, const int fontHeight, UINT fontFlags, const WCHAR* chars, UINT length) |
| 85 | { |
| 86 | DeleteObject(m_hBitmap); |
| 87 | m_pBitmapBits = nullptr; |
| 88 | m_charCoords.clear(); |
| 89 | |
| 90 | HRESULT hr = S_OK; |
| 91 | |
| 92 | // Create a font. By specifying ANTIALIASED_QUALITY, we might get an |
| 93 | // antialiased font, but this is not guaranteed. |
| 94 | HFONT hFont = CreateFontW( |
| 95 | fontHeight, 0, 0, 0, |
| 96 | (fontFlags & D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL, |
| 97 | (fontFlags & D3DFONT_ITALIC) ? TRUE : FALSE, |
| 98 | FALSE, FALSE, |
| 99 | DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, |
| 100 | CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, |
| 101 | DEFAULT_PITCH, fontName); |
| 102 | |
| 103 | HDC hDC = CreateCompatibleDC(nullptr); |
| 104 | SetMapMode(hDC, MM_TEXT); |
| 105 | HFONT hFontOld = (HFONT)SelectObject(hDC, hFont); |
| 106 | |
| 107 | std::vector<SIZE> charSizes; |
| 108 | charSizes.reserve(length); |
| 109 | SIZE size; |
| 110 | LONG maxWidth = 0; |
| 111 | LONG maxHeight = 0; |
| 112 | for (UINT i = 0; i < length; i++) { |
| 113 | if (GetTextExtentPoint32W(hDC, &chars[i], 1, &size) == FALSE) { |
| 114 | hr = E_FAIL; |
| 115 | break; |
| 116 | } |
| 117 | charSizes.emplace_back(size); |
| 118 | |
| 119 | if (size.cx > maxWidth) { |
| 120 | maxWidth = size.cx; |
| 121 | } |
| 122 | if (size.cy > maxHeight) { |
| 123 | maxHeight = size.cy; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | if (S_OK == hr) { |
| 128 | m_MaxCharMetric = { maxWidth, maxHeight }; |
| 129 | UINT stepX = m_MaxCharMetric.cx + 2; |
| 130 | UINT stepY = m_MaxCharMetric.cy; |
| 131 | UINT bmWidth = 128; |
| 132 | UINT bmHeight = 128; |
| 133 | UINT columns = bmWidth / stepX; |
| 134 | UINT lines = bmHeight / stepY; |
| 135 | |
| 136 | while (length > lines * columns) { |
| 137 | if (bmWidth <= bmHeight) { |
| 138 | bmWidth *= 2; |
| 139 | } else { |
| 140 | bmHeight += 128; |
| 141 | } |
no test coverage detected