// Update desired size of the button. If the size changes, trigger layout // (which will in turn request repaints of affected areas) // To keep size of the button stable (to avoid re-layouts) we use font // line spacing to be the height of the button, even if text is empty. // Note: it might be that for some cases button with no text should collapse // in size but we don't have a need for that yet void Button::RecalculateSize(bool repaintIfSizeDidntChange) { Size prevSize = desiredSize; desiredSize = GetBorderAndPaddingSize(cachedStyle); Graphics *gfx = AllocGraphicsForMeasureText(); CachedStyle *s = cachedStyle; Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight); textDx = 0; float fontDy = font->GetHeight(gfx); RectF bbox; if (text) { bbox = MeasureText(gfx, font, text); textDx = (size_t)bbox.Width; // TODO: round up? // bbox shouldn't be bigger than fontDy. We apply magic adjustment because // bbox is bigger in n-th decimal point CrashIf(fontDy + .5f < bbox.Height); } desiredSize.Width += textDx; desiredSize.Height += (INT)fontDy; // TODO: round up? FreeGraphicsForMeasureText(gfx); if (!prevSize.Equals(desiredSize)) RequestLayout(this); else if (repaintIfSizeDidntChange) RequestRepaint(this); }
HFONT CachedFont::GetHFont() { if (!hFont) { LOGFONTW lf; // TODO: Graphics is probably only used for metrics, // so this might not be 100% correct (e.g. 2 monitors with different DPIs?) // but previous code wasn't much better Graphics *gfx = AllocGraphicsForMeasureText(); Status status = font->GetLogFontW(gfx, &lf); FreeGraphicsForMeasureText(gfx); CrashIf(status != Ok); hFont = CreateFontIndirectW(&lf); CrashIf(!hFont); } return hFont; }
// Update desired size of the button. If the size changes, trigger layout // (which will in turn request repaints of affected areas) // To keep size of the button stable (to avoid re-layouts) we use font // line spacing to be the height of the button, even if text is empty. // Note: it might be that for some cases button with no text should collapse // in size but we don't have a need for that yet void Button::RecalculateSize(bool repaintIfSizeDidntChange) { Size prevSize = desiredSize; desiredSize = GetBorderAndPaddingSize(cachedStyle); Graphics *gfx = AllocGraphicsForMeasureText(); CachedStyle *s = cachedStyle; Font *font = GetCachedFont(s->fontName, s->fontSize, s->fontWeight); textDx = 0; float fontDy = font->GetHeight(gfx); RectF bbox; if (text) { bbox = MeasureText(gfx, font, text); textDx = CeilI(bbox.Width); // I theorize that bbox shouldn't be bigger than fontDy. However, in practice // it is (e.g. for Lucida Grande and text "Page: 0 / 0", bbox.Dy is 19.00 // and fontDy is 18.11). I still want to know if the difference gets even bigger // than that float maxDiff = 1.f; if (bbox.Height > fontDy + maxDiff) { fontDy = bbox.Height; float diff = fontDy + maxDiff - bbox.Height; char *fontName = str::conv::ToUtf8(s->fontName); char *tmp = str::conv::ToUtf8(text); CrashLogFmt("fontDy=%.2f, bbox.Height=%.2f, diff=%.2f (should be > 0) font: %s, text='%s'\r\n", (float)fontDy, (float)bbox.Height, diff, fontName, tmp); CrashIf(diff < 0); } } desiredSize.Width += textDx; desiredSize.Height += CeilI(fontDy); FreeGraphicsForMeasureText(gfx); if (!prevSize.Equals(desiredSize)) RequestLayout(this); else if (repaintIfSizeDidntChange) RequestRepaint(this); }