MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / UniscribeShapeRun

Function UniscribeShapeRun

src/os/windows/string_uniscribe.cpp:156–246  ·  view source on GitHub ↗

Determine the glyph positions for a run. */

Source from the content-addressed store, hash-verified

154
155/** Determine the glyph positions for a run. */
156static bool UniscribeShapeRun(const UniscribeParagraphLayoutFactory::CharType *buff, UniscribeRun &range)
157{
158 /* Initial size guess for the number of glyphs recommended by Uniscribe. */
159 range.glyphs.resize(range.len * 3 / 2 + 16);
160 range.vis_attribs.resize(range.glyphs.size());
161
162 /* The char-to-glyph array is the same size as the input. */
163 range.char_to_glyph.resize(range.len);
164
165 HDC temp_dc = nullptr;
166 HFONT old_font = nullptr;
167 HFONT cur_font = nullptr;
168
169 while (true) {
170 /* Shape the text run by determining the glyphs needed for display. */
171 int glyphs_used = 0;
172 HRESULT hr = ScriptShape(temp_dc, &_script_cache[range.font->fc->GetSize()], buff + range.pos, range.len, (int)range.glyphs.size(), &range.sa, &range.glyphs[0], &range.char_to_glyph[0], &range.vis_attribs[0], &glyphs_used);
173
174 if (SUCCEEDED(hr)) {
175 range.glyphs.resize(glyphs_used);
176 range.vis_attribs.resize(glyphs_used);
177
178 /* Calculate the glyph positions. */
179 ABC abc;
180 range.advances.resize(range.glyphs.size());
181 range.offsets.resize(range.glyphs.size());
182 hr = ScriptPlace(temp_dc, &_script_cache[range.font->fc->GetSize()], &range.glyphs[0], (int)range.glyphs.size(), &range.vis_attribs[0], &range.sa, &range.advances[0], &range.offsets[0], &abc);
183 if (SUCCEEDED(hr)) {
184 /* We map our special sprite chars to values that don't fit into a WORD. Copy the glyphs
185 * into a new vector and query the real glyph to use for these special chars. */
186 range.ft_glyphs.resize(range.glyphs.size());
187 for (size_t g_id = 0; g_id < range.glyphs.size(); g_id++) {
188 range.ft_glyphs[g_id] = range.glyphs[g_id];
189 }
190 for (int i = 0; i < range.len; i++) {
191 if (buff[range.pos + i] >= SCC_SPRITE_START && buff[range.pos + i] <= SCC_SPRITE_END) {
192 auto pos = range.char_to_glyph[i];
193 if (range.ft_glyphs[pos] == 0) { // Font doesn't have our special glyph, so remap.
194 range.ft_glyphs[pos] = range.font->fc->MapCharToGlyph(buff[range.pos + i]);
195 range.offsets[pos].dv = (range.font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(range.font->fc->GetSize()))) / 2; // Align sprite font to centre
196 range.advances[pos] = range.font->fc->GetGlyphWidth(range.ft_glyphs[pos]);
197 }
198 }
199 }
200
201 range.total_advance = 0;
202 for (size_t i = 0; i < range.advances.size(); i++) {
203#ifdef WITH_FREETYPE
204 /* FreeType and GDI/Uniscribe seems to occasionally disagree over the width of a glyph. */
205 if (range.advances[i] > 0 && range.ft_glyphs[i] != 0xFFFF) range.advances[i] = range.font->fc->GetGlyphWidth(range.ft_glyphs[i]);
206#endif
207 range.total_advance += range.advances[i];
208 }
209 break;
210 }
211 }
212
213 if (hr == E_OUTOFMEMORY) {

Callers 2

GetParagraphLayoutMethod · 0.85
NextLineMethod · 0.85

Calls 8

ScaleSpriteTradFunction · 0.85
HFontFromFontFunction · 0.85
resizeMethod · 0.80
sizeMethod · 0.45
GetSizeMethod · 0.45
MapCharToGlyphMethod · 0.45
GetHeightMethod · 0.45
GetGlyphWidthMethod · 0.45

Tested by

no test coverage detected