diff --git a/gtk/inspector/fpsoverlay.c b/gtk/inspector/fpsoverlay.c index 63c948259b..a5aa45275c 100644 --- a/gtk/inspector/fpsoverlay.c +++ b/gtk/inspector/fpsoverlay.c @@ -24,6 +24,7 @@ #include "gtkwidget.h" #include "gtkwindow.h" #include "gtknative.h" +#include "gtkmain.h" /* duration before we start fading in us */ #define GDK_FPS_OVERLAY_LINGER_DURATION (1000 * 1000) @@ -40,6 +41,11 @@ struct _GtkFpsOverlay GtkInspectorOverlay parent_instance; GHashTable *infos; /* GtkWidget => GtkFpsInfo */ + + PangoFont *font; + PangoGlyphString *glyphs; + PangoGlyphString *digits; + int width, height, baseline; }; struct _GtkFpsOverlayClass @@ -89,15 +95,13 @@ gtk_fps_overlay_snapshot (GtkInspectorOverlay *overlay, { GtkFpsOverlay *self = GTK_FPS_OVERLAY (overlay); GtkFpsInfo *info; - PangoLayout *layout; - PangoAttrList *attrs; gint64 now; double fps; - char *fps_string; graphene_rect_t bounds; gboolean has_bounds; - int width, height; double overlay_opacity; + PangoGlyphString *glyphs; + GskRenderNode *fps_node; now = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget)); info = g_hash_table_lookup (self->infos, widget); @@ -131,12 +135,6 @@ gtk_fps_overlay_snapshot (GtkInspectorOverlay *overlay, } } - fps = gtk_fps_overlay_get_fps (widget); - if (fps == 0.0) - fps_string = g_strdup ("--- fps"); - else - fps_string = g_strdup_printf ("%.2f fps", fps); - if (GTK_IS_WINDOW (widget)) { GtkWidget *child = gtk_window_get_child (GTK_WINDOW (widget)); @@ -146,33 +144,50 @@ gtk_fps_overlay_snapshot (GtkInspectorOverlay *overlay, else has_bounds = gtk_widget_compute_bounds (child, widget, &bounds); } - else + else { has_bounds = gtk_widget_compute_bounds (widget, widget, &bounds); } - layout = gtk_widget_create_pango_layout (widget, fps_string); - attrs = pango_attr_list_new (); - pango_attr_list_insert (attrs, pango_attr_font_features_new ("tnum=1")); - pango_layout_set_attributes (layout, attrs); - pango_attr_list_unref (attrs); - pango_layout_get_pixel_size (layout, &width, &height); + glyphs = pango_glyph_string_copy (self->glyphs); + + fps = gtk_fps_overlay_get_fps (widget); + if (fps == 0.0) + { + for (int i = 0; i < 7; i++) + glyphs->glyphs[i].glyph = PANGO_GLYPH_EMPTY; + } + else + { + char *fps_string = g_strdup_printf ("%7.2f fps", fps); + for (int i = 0; i < 7; i++) + { + if (g_ascii_isdigit (fps_string[i])) + glyphs->glyphs[i].glyph = self->digits->glyphs[fps_string[i] - '0'].glyph; + else if (fps_string[i] == ' ') + glyphs->glyphs[i].glyph = PANGO_GLYPH_EMPTY; + } + g_free (fps_string); + } gtk_snapshot_save (snapshot); if (has_bounds) - gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (bounds.origin.x + bounds.size.width - width, bounds.origin.y)); + gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (bounds.origin.x + bounds.size.width - self->width, bounds.origin.y)); + if (overlay_opacity < 1.0) gtk_snapshot_push_opacity (snapshot, overlay_opacity); gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 0.5 }, - &GRAPHENE_RECT_INIT (-1, -1, width + 2, height + 2)); - gtk_snapshot_append_layout (snapshot, - layout, - &(GdkRGBA) { 1, 1, 1, 1 }); + &GRAPHENE_RECT_INIT (-1, -1, self->width + 2, self->height + 2)); + fps_node = gsk_text_node_new (self->font, + glyphs, + &(GdkRGBA) { 1, 1, 1, 1 }, + &GRAPHENE_POINT_INIT (0, self->baseline)); + gtk_snapshot_append_node (snapshot, fps_node); + gsk_render_node_unref (fps_node); if (overlay_opacity < 1.0) gtk_snapshot_pop (snapshot); gtk_snapshot_restore (snapshot); - g_free (fps_string); gtk_widget_add_tick_callback (widget, gtk_fps_overlay_force_redraw, NULL, NULL); } @@ -196,6 +211,10 @@ gtk_fps_overlay_dispose (GObject *object) g_hash_table_unref (self->infos); + g_clear_pointer (&self->glyphs, pango_glyph_string_free); + g_clear_pointer (&self->digits, pango_glyph_string_free); + g_clear_object (&self->font); + G_OBJECT_CLASS (gtk_fps_overlay_parent_class)->dispose (object); } @@ -214,7 +233,44 @@ gtk_fps_overlay_class_init (GtkFpsOverlayClass *klass) static void gtk_fps_overlay_init (GtkFpsOverlay *self) { + PangoContext *context; + PangoLayout *layout; + PangoLayoutIter *iter; + PangoLayoutRun *run; + PangoAttrList *attrs; + self->infos = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, gtk_fps_info_free); + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + pango_context_set_language (context, gtk_get_default_language ()); + + layout = pango_layout_new (context); + pango_layout_set_text (layout, "0000.00 fps", -1); + attrs = pango_attr_list_new (); + pango_attr_list_insert (attrs, pango_attr_font_features_new ("tnum=1")); + pango_layout_set_attributes (layout, attrs); + pango_attr_list_unref (attrs); + pango_layout_get_pixel_size (layout, &self->width, &self->height); + + iter = pango_layout_get_iter (layout); + self->baseline = pango_layout_iter_get_baseline (iter) / (double) PANGO_SCALE; + run = pango_layout_iter_get_run_readonly (iter); + + self->glyphs = pango_glyph_string_copy (run->glyphs); + self->font = g_object_ref (run->item->analysis.font); + + pango_layout_iter_free (iter); + + pango_layout_set_text (layout, "0123456789", -1); + + iter = pango_layout_get_iter (layout); + run = pango_layout_iter_get_run_readonly (iter); + + self->digits = pango_glyph_string_copy (run->glyphs); + + pango_layout_iter_free (iter); + g_object_unref (layout); + g_object_unref (context); } GtkInspectorOverlay *