Mercurial > emacs
comparison src/w32font.c @ 92151:664a09af03dc
(w32font_text_extents): Avoid getting HDC and selecting
a font into it unless we have to.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Sun, 24 Feb 2008 15:07:46 +0000 |
parents | 3081b8f848bc |
children | b7277e09e943 |
comparison
equal
deleted
inserted
replaced
92150:1c088baa9d2d | 92151:664a09af03dc |
---|---|
288 unsigned *code; | 288 unsigned *code; |
289 int nglyphs; | 289 int nglyphs; |
290 struct font_metrics *metrics; | 290 struct font_metrics *metrics; |
291 { | 291 { |
292 int i; | 292 int i; |
293 HFONT old_font; | 293 HFONT old_font = NULL; |
294 HDC dc; | 294 HDC dc = NULL; |
295 struct frame * f; | 295 struct frame * f; |
296 int total_width = 0; | 296 int total_width = 0; |
297 WORD *wcode = alloca(nglyphs * sizeof (WORD)); | 297 WORD *wcode = alloca(nglyphs * sizeof (WORD)); |
298 SIZE size; | 298 SIZE size; |
299 | 299 |
300 /* TODO: Frames can come and go, and their fonts outlive them. So we | 300 /* TODO: Frames can come and go, and their fonts outlive them. So we |
301 can't cache the frame in the font structure. Use selected_frame | 301 can't cache the frame in the font structure. Use selected_frame |
302 until the API is updated to pass in a frame. */ | 302 until the API is updated to pass in a frame. */ |
303 f = XFRAME (selected_frame); | 303 f = XFRAME (selected_frame); |
304 | |
305 dc = get_frame_dc (f); | |
306 old_font = SelectObject (dc, ((W32FontStruct *)(font->font.font))->hfont); | |
307 | 304 |
308 if (metrics) | 305 if (metrics) |
309 { | 306 { |
310 GLYPHMETRICS gm; | 307 GLYPHMETRICS gm; |
311 MAT2 transform; | 308 MAT2 transform; |
337 metrics->width + char_metric->rbearing); | 334 metrics->width + char_metric->rbearing); |
338 metrics->width += char_metric->width; | 335 metrics->width += char_metric->width; |
339 metrics->ascent = max (metrics->ascent, char_metric->ascent); | 336 metrics->ascent = max (metrics->ascent, char_metric->ascent); |
340 metrics->descent = max (metrics->descent, char_metric->descent); | 337 metrics->descent = max (metrics->descent, char_metric->descent); |
341 } | 338 } |
342 else if (GetGlyphOutlineW (dc, *(code + i), GGO_METRICS, &gm, 0, | |
343 NULL, &transform) != GDI_ERROR) | |
344 { | |
345 int new_val = metrics->width + gm.gmBlackBoxX | |
346 + gm.gmptGlyphOrigin.x; | |
347 metrics->rbearing = max (metrics->rbearing, new_val); | |
348 new_val = -gm.gmptGlyphOrigin.x - metrics->width; | |
349 metrics->lbearing = max (metrics->lbearing, new_val); | |
350 metrics->width += gm.gmCellIncX; | |
351 new_val = -gm.gmptGlyphOrigin.y; | |
352 metrics->ascent = max (metrics->ascent, new_val); | |
353 new_val = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y; | |
354 metrics->descent = max (metrics->descent, new_val); | |
355 } | |
356 else | 339 else |
357 { | 340 { |
358 /* Rely on an estimate based on the overall font metrics. */ | 341 if (dc == NULL) |
359 break; | 342 { |
343 dc = get_frame_dc (f); | |
344 old_font = SelectObject (dc, ((W32FontStruct *) | |
345 (font->font.font))->hfont); | |
346 } | |
347 if (GetGlyphOutlineW (dc, *(code + i), GGO_METRICS, &gm, 0, | |
348 NULL, &transform) != GDI_ERROR) | |
349 { | |
350 int new_val = metrics->width + gm.gmBlackBoxX | |
351 + gm.gmptGlyphOrigin.x; | |
352 metrics->rbearing = max (metrics->rbearing, new_val); | |
353 new_val = -gm.gmptGlyphOrigin.x - metrics->width; | |
354 metrics->lbearing = max (metrics->lbearing, new_val); | |
355 metrics->width += gm.gmCellIncX; | |
356 new_val = -gm.gmptGlyphOrigin.y; | |
357 metrics->ascent = max (metrics->ascent, new_val); | |
358 new_val = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y; | |
359 metrics->descent = max (metrics->descent, new_val); | |
360 } | |
361 else | |
362 { | |
363 /* Rely on an estimate based on the overall font metrics. */ | |
364 break; | |
365 } | |
360 } | 366 } |
361 } | 367 } |
362 | 368 |
363 /* If we got through everything, return. */ | 369 /* If we got through everything, return. */ |
364 if (i == nglyphs) | 370 if (i == nglyphs) |
365 { | 371 { |
366 /* Restore state and release DC. */ | 372 if (dc != NULL) |
367 SelectObject (dc, old_font); | 373 { |
368 release_frame_dc (f, dc); | 374 /* Restore state and release DC. */ |
375 SelectObject (dc, old_font); | |
376 release_frame_dc (f, dc); | |
377 } | |
369 | 378 |
370 return metrics->width; | 379 return metrics->width; |
371 } | 380 } |
372 } | 381 } |
373 | 382 |
378 else | 387 else |
379 { | 388 { |
380 /* TODO: Convert to surrogate, reallocating array if needed */ | 389 /* TODO: Convert to surrogate, reallocating array if needed */ |
381 wcode[i] = 0xffff; | 390 wcode[i] = 0xffff; |
382 } | 391 } |
392 } | |
393 | |
394 if (dc == NULL) | |
395 { | |
396 dc = get_frame_dc (f); | |
397 old_font = SelectObject (dc, ((W32FontStruct *) | |
398 (font->font.font))->hfont); | |
383 } | 399 } |
384 | 400 |
385 if (GetTextExtentPoint32W (dc, wcode, nglyphs, &size)) | 401 if (GetTextExtentPoint32W (dc, wcode, nglyphs, &size)) |
386 { | 402 { |
387 total_width = size.cx; | 403 total_width = size.cx; |