diff options
-rw-r--r-- | pluma/Makefile.am | 2 | ||||
-rw-r--r-- | pluma/pluma-pango.c | 230 | ||||
-rw-r--r-- | pluma/pluma-pango.h | 28 | ||||
-rw-r--r-- | pluma/pluma-view.c | 136 |
4 files changed, 292 insertions, 104 deletions
diff --git a/pluma/Makefile.am b/pluma/Makefile.am index fa8685a3..36d93c6a 100644 --- a/pluma/Makefile.am +++ b/pluma/Makefile.am @@ -48,6 +48,7 @@ NOINST_H_FILES = \ pluma-history-entry.h \ pluma-io-error-message-area.h \ pluma-language-manager.h \ + pluma-pango.h \ pluma-plugins-engine.h \ pluma-print-job.h \ pluma-print-preview.h \ @@ -120,6 +121,7 @@ libpluma_c_files = \ pluma-message.c \ pluma-notebook.c \ pluma-panel.c \ + pluma-pango.c \ pluma-plugins-engine.c \ pluma-print-job.c \ pluma-print-preview.c \ diff --git a/pluma/pluma-pango.c b/pluma/pluma-pango.c new file mode 100644 index 00000000..189d1770 --- /dev/null +++ b/pluma/pluma-pango.c @@ -0,0 +1,230 @@ +/* pluma-pango.c + * + * This file is a copy of pango_font_description_to_css from gtk gtkfontbutton.c + * + * Copyright (C) 2016 Matthias Clasen <[email protected]> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define G_LOG_DOMAIN "pluma-pango" + +#include "config.h" + +#include "pluma-pango.h" + +#if PANGO_VERSION_CHECK (1, 44, 0) +static void +add_css_variations (GString *s, + const char *variations) +{ + const char *p; + const char *sep = ""; + + if (variations == NULL || variations[0] == '\0') + { + g_string_append (s, "normal"); + return; + } + + p = variations; + while (p && *p) + { + const char *start; + const char *end, *end2; + double value; + char name[5]; + + while (g_ascii_isspace (*p)) p++; + + start = p; + end = strchr (p, ','); + if (end && (end - p < 6)) + goto skip; + + name[0] = p[0]; + name[1] = p[1]; + name[2] = p[2]; + name[3] = p[3]; + name[4] = '\0'; + + p += 4; + while (g_ascii_isspace (*p)) p++; + if (*p == '=') p++; + + if (p - start < 5) + goto skip; + + value = g_ascii_strtod (p, (char **) &end2); + + while (end2 && g_ascii_isspace (*end2)) end2++; + + if (end2 && (*end2 != ',' && *end2 != '\0')) + goto skip; + + g_string_append_printf (s, "%s\"%s\" %g", sep, name, value); + sep = ", "; + +skip: + p = end ? end + 1 : NULL; + } +} +#endif + +/** + * pluma_pango_font_description_to_css: + * + * This function will generate CSS suitable for Gtk's CSS engine + * based on the properties of the #PangoFontDescription. + * + * Returns: (transfer full): A newly allocated string containing the + * CSS describing the font description. + */ +gchar * +pluma_pango_font_description_to_css (const PangoFontDescription *desc) +{ + GString *s; + PangoFontMask set; + + s = g_string_new (""); + + set = pango_font_description_get_set_fields (desc); + if (set & PANGO_FONT_MASK_FAMILY) + { + g_string_append (s, "font-family: "); + g_string_append (s, pango_font_description_get_family (desc)); + g_string_append (s, "; "); + } + if (set & PANGO_FONT_MASK_STYLE) + { + switch (pango_font_description_get_style (desc)) + { + case PANGO_STYLE_NORMAL: + g_string_append (s, "font-style: normal; "); + break; + case PANGO_STYLE_OBLIQUE: + g_string_append (s, "font-style: oblique; "); + break; + case PANGO_STYLE_ITALIC: + g_string_append (s, "font-style: italic; "); + break; + default: + break; + } + } + if (set & PANGO_FONT_MASK_VARIANT) + { + switch (pango_font_description_get_variant (desc)) + { + case PANGO_VARIANT_NORMAL: + g_string_append (s, "font-variant: normal; "); + break; + case PANGO_VARIANT_SMALL_CAPS: + g_string_append (s, "font-variant: small-caps; "); + break; + default: + break; + } + } + if (set & PANGO_FONT_MASK_WEIGHT) + { + switch (pango_font_description_get_weight (desc)) + { + case PANGO_WEIGHT_THIN: + g_string_append (s, "font-weight: 100; "); + break; + case PANGO_WEIGHT_ULTRALIGHT: + g_string_append (s, "font-weight: 200; "); + break; + case PANGO_WEIGHT_LIGHT: + case PANGO_WEIGHT_SEMILIGHT: + g_string_append (s, "font-weight: 300; "); + break; + case PANGO_WEIGHT_BOOK: + case PANGO_WEIGHT_NORMAL: + g_string_append (s, "font-weight: 400; "); + break; + case PANGO_WEIGHT_MEDIUM: + g_string_append (s, "font-weight: 500; "); + break; + case PANGO_WEIGHT_SEMIBOLD: + g_string_append (s, "font-weight: 600; "); + break; + case PANGO_WEIGHT_BOLD: + g_string_append (s, "font-weight: 700; "); + break; + case PANGO_WEIGHT_ULTRABOLD: + g_string_append (s, "font-weight: 800; "); + break; + case PANGO_WEIGHT_HEAVY: + case PANGO_WEIGHT_ULTRAHEAVY: + g_string_append (s, "font-weight: 900; "); + break; + default: + break; + } + } + if (set & PANGO_FONT_MASK_STRETCH) + { + switch (pango_font_description_get_stretch (desc)) + { + case PANGO_STRETCH_ULTRA_CONDENSED: + g_string_append (s, "font-stretch: ultra-condensed; "); + break; + case PANGO_STRETCH_EXTRA_CONDENSED: + g_string_append (s, "font-stretch: extra-condensed; "); + break; + case PANGO_STRETCH_CONDENSED: + g_string_append (s, "font-stretch: condensed; "); + break; + case PANGO_STRETCH_SEMI_CONDENSED: + g_string_append (s, "font-stretch: semi-condensed; "); + break; + case PANGO_STRETCH_NORMAL: + g_string_append (s, "font-stretch: normal; "); + break; + case PANGO_STRETCH_SEMI_EXPANDED: + g_string_append (s, "font-stretch: semi-expanded; "); + break; + case PANGO_STRETCH_EXPANDED: + g_string_append (s, "font-stretch: expanded; "); + break; + case PANGO_STRETCH_EXTRA_EXPANDED: + break; + case PANGO_STRETCH_ULTRA_EXPANDED: + g_string_append (s, "font-stretch: ultra-expanded; "); + break; + default: + break; + } + } + if (set & PANGO_FONT_MASK_SIZE) + { + g_string_append_printf (s, "font-size: %dpt; ", pango_font_description_get_size (desc) / PANGO_SCALE); + } + +#if PANGO_VERSION_CHECK (1, 44, 0) + if (set & PANGO_FONT_MASK_VARIATIONS) + { + const char *variations; + + g_string_append (s, "font-variation-settings: "); + variations = pango_font_description_get_variations (desc); + add_css_variations (s, variations); + g_string_append (s, "; "); + } +#endif + + return g_string_free (s, FALSE); +} diff --git a/pluma/pluma-pango.h b/pluma/pluma-pango.h new file mode 100644 index 00000000..81db9660 --- /dev/null +++ b/pluma/pluma-pango.h @@ -0,0 +1,28 @@ +/* pluma-pango.h + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PLUMA_PANGO_H +#define PLUMA_PANGO_H + +#include <pango/pango.h> + +G_BEGIN_DECLS + +gchar *pluma_pango_font_description_to_css (const PangoFontDescription *font_desc); + +G_END_DECLS + +#endif /* PLUMA_PANGO_H */ diff --git a/pluma/pluma-view.c b/pluma/pluma-view.c index c1918ca4..9b94da3f 100644 --- a/pluma/pluma-view.c +++ b/pluma/pluma-view.c @@ -44,6 +44,7 @@ #include "pluma-view.h" #include "pluma-debug.h" +#include "pluma-pango.h" #include "pluma-utils.h" #include "pluma-settings.h" @@ -97,6 +98,9 @@ struct _PlumaViewPrivate gboolean disable_popdown; GtkTextBuffer *current_buffer; + + GtkCssProvider *css_provider; + PangoFontDescription *font_desc; }; /* The search entry completion is shared among all the views */ @@ -481,6 +485,7 @@ pluma_view_init (PlumaView *view) guint right_margin_position; GtkWrapMode wrap_mode; GtkSourceSmartHomeEndType smart_home_end; + GtkStyleContext *context; pluma_debug (DEBUG_VIEW); @@ -490,6 +495,15 @@ pluma_view_init (PlumaView *view) view->priv->editor_settings = g_settings_new (PLUMA_SCHEMA_ID); view->priv->interface_settings = g_settings_new ("org.mate.interface"); + view->priv->css_provider = gtk_css_provider_new (); + context = gtk_widget_get_style_context (GTK_WIDGET (view)); + gtk_style_context_add_class (context, "pluma-view"); + + gtk_style_context_add_provider (context, + GTK_STYLE_PROVIDER (view->priv->css_provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + /* Get setting values */ use_default_font = g_settings_get_boolean (view->priv->editor_settings, PLUMA_SETTINGS_USE_DEFAULT_FONT); @@ -600,6 +614,9 @@ pluma_view_dispose (GObject *object) current_buffer_removed (view); g_signal_handlers_disconnect_by_func (view, on_notify_buffer_cb, NULL); + g_clear_object (&view->priv->css_provider); + g_clear_pointer (&view->priv->font_desc, pango_font_description_free); + (* G_OBJECT_CLASS (pluma_view_parent_class)->dispose) (object); } @@ -900,101 +917,21 @@ pluma_view_scroll_to_cursor (PlumaView *view) 0.0); } -static PangoFontDescription* get_system_font (GSettings *settings) -{ - PangoFontDescription *desc = NULL; - char *name; - - name = g_settings_get_string (settings, "font-name"); - - if (name) - { - desc = pango_font_description_from_string (name); - g_free (name); - } - - return desc; -} - static void -system_font_changed_cb (GSettings *settings, - gchar *key, - gpointer user_data) +update_css_provider (PlumaView *view) { - PangoFontDescription *sys_font_desc = NULL; - sys_font_desc = get_system_font (settings); - if (sys_font_desc) - { - pluma_override_font (NULL, "label", sys_font_desc); - pango_font_description_free (sys_font_desc); - } -} + gchar *str; + gchar *css; -void -pluma_override_font (PlumaView *view, - const gchar *item, - PangoFontDescription *font) -{ - static GtkCssProvider *provider = NULL; /*We need to keep this as long as Pluma is running*/ - gchar *prov_str; - gchar *css; - gchar *family; - gchar *weight; - const gchar *style; - gchar *size; - - family = g_strdup_printf ("font-family: %s;", pango_font_description_get_family (font)); - - weight = g_strdup_printf ("font-weight: %d;", pango_font_description_get_weight (font)); - - if (pango_font_description_get_style (font) == PANGO_STYLE_NORMAL) - style = "font-style: normal;"; - else if (pango_font_description_get_style (font) == PANGO_STYLE_ITALIC) - style = "font-style: italic;"; - else - style = "font-style: oblique;"; + g_assert (PLUMA_IS_VIEW (view)); + g_assert (view->priv->font_desc != NULL); - size = g_strdup_printf ("font-size: %d%s;", - pango_font_description_get_size (font) / PANGO_SCALE, - pango_font_description_get_size_is_absolute (font) ? "px" : "pt"); - - if (provider == NULL) - { - provider = gtk_css_provider_new (); - - g_signal_connect (view->priv->interface_settings, - "changed::" "font-name", - G_CALLBACK (system_font_changed_cb), NULL); - - gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (GTK_WIDGET(view)), - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - } - - prov_str = gtk_css_provider_to_string (provider); - - if (g_str_has_prefix (prov_str, "textview") && g_str_has_prefix (item, "label")) - { - if (strstr (prov_str, "label")) - { - g_strdelimit (prov_str, "}", '\0'); - gchar *prov_new_str = g_strdup_printf ("%s}", prov_str); - css = g_strdup_printf ("%s %s { %s %s %s %s }", prov_new_str, item, family, weight, style, size); - g_free (prov_new_str); - } - else - css = g_strdup_printf ("%s %s { %s %s %s %s }", prov_str, item, family, weight, style, size); - } - else - css = g_strdup_printf ("%s { %s %s %s %s }", item, family, weight, style, size); - - gtk_css_provider_load_from_data (provider, css, -1, NULL); + str = pluma_pango_font_description_to_css (view->priv->font_desc); + css = g_strdup_printf ("textview { %s }", str ? str : ""); + gtk_css_provider_load_from_data (view->priv->css_provider, css, -1, NULL); g_free (css); - g_free (family); - g_free (weight); - g_free (size); - g_free (prov_str); + g_free (str); } /* FIXME this is an issue for introspection */ @@ -1012,13 +949,12 @@ pluma_view_set_font (PlumaView *view, gboolean def, const gchar *font_name) { - PangoFontDescription *font_desc = NULL; - PangoFontDescription *sys_font_desc = NULL; - pluma_debug (DEBUG_VIEW); g_return_if_fail (PLUMA_IS_VIEW (view)); + g_clear_pointer (&view->priv->font_desc, pango_font_description_free); + if (def) { PlumaSettings *settings; @@ -1026,27 +962,19 @@ pluma_view_set_font (PlumaView *view, settings = _pluma_settings_get_singleton (); font = pluma_settings_get_system_font (settings); - font_desc = pango_font_description_from_string (font); + view->priv->font_desc = pango_font_description_from_string (font); g_free (font); } else { g_return_if_fail (font_name != NULL); - font_desc = pango_font_description_from_string (font_name); + view->priv->font_desc = pango_font_description_from_string (font_name); } - g_return_if_fail (font_desc != NULL); - - pluma_override_font (view, "textview", font_desc); - - sys_font_desc = get_system_font (view->priv->interface_settings); - if (sys_font_desc) { - pluma_override_font (view, "label", sys_font_desc); - pango_font_description_free (sys_font_desc); - } + g_return_if_fail (view->priv->font_desc != NULL); - pango_font_description_free (font_desc); + update_css_provider (view); } static void |