{"id":13913,"date":"2010-05-26T07:00:00","date_gmt":"2010-05-26T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/05\/26\/how-do-i-find-the-bounding-box-for-a-character-in-a-font\/"},"modified":"2010-05-26T07:00:00","modified_gmt":"2010-05-26T07:00:00","slug":"how-do-i-find-the-bounding-box-for-a-character-in-a-font","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100526-00\/?p=13913","title":{"rendered":"How do I find the bounding box for a character in a font?"},"content":{"rendered":"<p>\nA customer had the following question:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nI&#8217;m looking for a way to get the height of text which consists\nentirely of digits, for example <code>\"123\"<\/code>,\nas these characters do not have any descent or internal leading.\nI expected functions like\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd144937(VS.85).aspx\">\n<code>Get&shy;Text&shy;Extent<\/code><\/a>\nto return the character&#8217;s ascent minus the internal leading, but\nin fact it returns the ascent plus the descent plus the internal leading.\nI considered getting the font metrics and taking the\n<code>TEXT&shy;METRICS.tmAscent<\/code>, but I&#8217;m worried that\nnumbers in other languages might have a nonzero descent and internal\nleading.\nIs there a function I can call to return the &#8220;real&#8221; height of the\ntext?\n<\/p><\/blockquote>\n<p>\nWell, first of all, this question makes an assumption about digits\nthat isn&#8217;t even true in English.\nFonts developed in recent years\ntend to keep all digits the same height (and often\nthe same width), but fonts\ndesigned before the advent of computers\n(or computer fonts which were inspired by old-timey fonts)\nwill often vary the height, and sometimes even have digits\nwith descenders.\nHere&#8217;s an example from the font Georgia:\n<\/p>\n<table CELLPADDING=\"0\" CELLSPACING=\"0\">\n<tbody>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" COLSPAN=\"15\" STYLE=\"width: 15ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" COLSPAN=\"14\" STYLE=\"width: 14ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" COLSPAN=\"9\" STYLE=\"width: 9ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"3\" STYLE=\"width: 3ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"5\" STYLE=\"width: 5ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"2\" STYLE=\"width: 2ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"6\" STYLE=\"width: 6ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"2\" STYLE=\"width: 2ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"5\" STYLE=\"width: 5ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"2\" STYLE=\"width: 2ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"2\" STYLE=\"width: 2ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"6\" STYLE=\"width: 6ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"7\" STYLE=\"width: 7ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"2\" STYLE=\"width: 2ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: .75pt\">\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" COLSPAN=\"7\" STYLE=\"width: 7ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"black\" STYLE=\"width: 1ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"7\" STYLE=\"width: 7ex\"><\/td>\n<\/tr>\n<tr STYLE=\"height: 1ex\">\n<td BGCOLOR=\"white\" COLSPAN=\"8\" STYLE=\"width: 8ex\"><\/td>\n<td BGCOLOR=\"black\" COLSPAN=\"4\" STYLE=\"width: 4ex\"><\/td>\n<td BGCOLOR=\"white\" COLSPAN=\"8\" STYLE=\"width: 8ex\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<caption ALIGN=\"bottom\"><font FACE=\"Georgia\">058<\/font><\/caption>\n<p>\nObserve that the number zero is six pixels tall, whereas\nthe number eight is nine pixels tall,\nand the number five has a two-pixel descender!\n<\/p>\n<p>\nOkay, so you&#8217;re going to have to take the descent into account\nfor all languages, including English.\nInternal leading is the space above a character to separate it\nfrom elements above it.\nFor example, you need some space above a capital&nbsp;T so that\nthe horizontal bar remains readable.\nAgain, the assumption that English doesn&#8217;t need internal leading\nis false.\n<\/p>\n<p>\nOkay, but what about the original question?\nWell, when I heard this question, my first thoughts went back\nto the early days of Win32 when the coolest new GDI feature\nwas paths, and everybody was showing off\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd183441(VS.85).aspx\">\nthe fancy text effects\nyou could pull off with the aid of paths<\/a>.\nMy initial instinct was therefore to use the\n<a HREF=\"http:\/\/www.microsoft.com\/mspress\/books\/sampchap\/2344c.aspx\">\nsame technique<\/a>\nas those cool demos by combining\n<code>Begin&shy;Path<\/code>,\n<code>Text&shy;Out<\/code>,\nand <code>End&shy;Path<\/code>.\nOnce I had a path, I could get its dimensions by using\n<code>Path&shy;To&shy;Region<\/code> and <code>Get&shy;Rgn&shy;Box<\/code>.\n<\/p>\n<p>\nFortunately, it turns out that there&#8217;s an easier way.\nThe\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd144891(VS.85).aspx\">\n<code>Get&shy;Glyph&shy;Outline<\/code><\/a> function\nreturns the glyph metrics, which describe the bounding box of the\npixels of a character.\n<\/p>\n<pre>\n\/\/ Create an identity matrix\nstatic const MAT2 c_mat2Identity = {\n    { 0, 1 }, \/* eM11 = 1.0 *\/\n    { 0, 0 }, \/* eM12 = 0.0 *\/\n    { 0, 0 }, \/* eM21 = 0.0 *\/\n    { 0, 1 }, \/* eM22 = 1.0 *\/\n };\nGetGlyphOutline(hdc, L'0', GGO_METRICS, &amp;gm, 0, NULL, &amp;c_mat2Identity);\n<\/pre>\n<p>\nThe dimensions of the character are returned in the\n<code>GLYPH&shy;METRICS<\/code> structure, and in particular,\nyou can derive the bounding box from the\n<code>gmptGlyph&shy;Origin<\/code>,\n<code>gmBlack&shy;BoxX<\/code>, and\n<code>gmBlack&shy;BoxY<\/code> members.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer had the following question: I&#8217;m looking for a way to get the height of text which consists entirely of digits, for example &#8220;123&#8221;, as these characters do not have any descent or internal leading. I expected functions like Get&shy;Text&shy;Extent to return the character&#8217;s ascent minus the internal leading, but in fact it returns [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-13913","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer had the following question: I&#8217;m looking for a way to get the height of text which consists entirely of digits, for example &#8220;123&#8221;, as these characters do not have any descent or internal leading. I expected functions like Get&shy;Text&shy;Extent to return the character&#8217;s ascent minus the internal leading, but in fact it returns [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13913","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=13913"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/13913\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=13913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=13913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=13913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}