mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 20:41:43 +00:00
0f59cb4040
2003-02-20 Sven Neumann <sven@gimp.org> * app/widgets/gimpfontselection-dialog.c * app/widgets/gimpfontselection.c: connect the dialog to the font selection widget and block the signal handler when the font is changed from the dialog. Fixes weird behaviour noted by Jimmac.
751 lines
24 KiB
C
751 lines
24 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimpfontselection-dialog.c
|
|
* Copyright (C) 2001 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* Partially based on code from GtkFontSelection.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <pango/pangoft2.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "gimpfontselection.h"
|
|
#include "gimpfontselection-dialog.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
#define FONT_SIZE 18
|
|
|
|
#define FONT_LIST_HEIGHT 136
|
|
#define FONT_LIST_WIDTH 190
|
|
#define FONT_STYLE_LIST_WIDTH 170
|
|
|
|
enum
|
|
{
|
|
FAMILY_COLUMN,
|
|
FAMILY_NAME_COLUMN
|
|
};
|
|
|
|
enum
|
|
{
|
|
FACE_COLUMN,
|
|
FACE_NAME_COLUMN
|
|
};
|
|
|
|
|
|
struct _GimpFontSelectionDialog
|
|
{
|
|
GimpFontSelection *fontsel;
|
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *family_list;
|
|
GtkWidget *face_list;
|
|
|
|
PangoFontFamily *family;
|
|
PangoFontFace *face;
|
|
|
|
GtkWidget *preview;
|
|
FT_Bitmap bitmap;
|
|
PangoLayout *layout;
|
|
};
|
|
|
|
|
|
static void gimp_font_selection_dialog_font_changed (GimpFontSelection *fontsel,
|
|
GimpFontSelectionDialog *dialog);
|
|
|
|
static void gimp_font_selection_dialog_ok (GtkWidget *widget,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_apply (GtkWidget *widget,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_preview (GimpFontSelectionDialog *dialog);
|
|
static void gimp_font_selection_dialog_select_family (GtkTreeSelection *selection,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_select_style (GtkTreeSelection *selection,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_show_available_fonts (GimpFontSelectionDialog *dialog);
|
|
static void gimp_font_selection_dialog_show_available_styles (GimpFontSelectionDialog *dialog);
|
|
static gboolean gimp_font_selection_dialog_preview_expose (GtkWidget *widget,
|
|
GdkEventExpose *event,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_preview_resize (GtkWidget *widget,
|
|
GtkAllocation *allocation,
|
|
gpointer data);
|
|
static void gimp_font_selection_dialog_preview (GimpFontSelectionDialog *dialog);
|
|
|
|
|
|
/**
|
|
* gimp_font_selection_dialog_new:
|
|
* @fontsel: the GimpFontSelection that creates and owns this dialog.
|
|
*
|
|
* Creates a new #GimpFontSelectionDialog.
|
|
*
|
|
* Returns: A pointer to the new #GimpFontSelectionDialog.
|
|
**/
|
|
GimpFontSelectionDialog *
|
|
gimp_font_selection_dialog_new (GimpFontSelection *fontsel)
|
|
{
|
|
GimpFontSelectionDialog *dialog;
|
|
GtkListStore *model;
|
|
GtkTreeSelection *select;
|
|
GtkTreeViewColumn *column;
|
|
GtkWidget *scrolled_win;
|
|
GtkWidget *table;
|
|
GtkWidget *label;
|
|
GtkWidget *frame;
|
|
GClosure *closure;
|
|
|
|
g_return_val_if_fail (GIMP_IS_FONT_SELECTION (fontsel), NULL);
|
|
|
|
dialog = g_new0 (GimpFontSelectionDialog, 1);
|
|
|
|
dialog->fontsel = fontsel;
|
|
|
|
dialog->dialog =
|
|
gimp_dialog_new (_("GIMP Font Selection"), "font_selection",
|
|
gimp_standard_help_func, "dialogs/font_selection.html",
|
|
GTK_WIN_POS_MOUSE,
|
|
FALSE, TRUE, TRUE,
|
|
|
|
GTK_STOCK_APPLY, gimp_font_selection_dialog_apply,
|
|
dialog, NULL, NULL, TRUE, FALSE,
|
|
|
|
GTK_STOCK_CANCEL, gtk_widget_hide,
|
|
NULL, (gpointer) 1, NULL, FALSE, TRUE,
|
|
|
|
GTK_STOCK_OK, gimp_font_selection_dialog_ok,
|
|
dialog, NULL, NULL, TRUE, FALSE,
|
|
|
|
NULL);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (dialog->dialog), 1);
|
|
|
|
/* Create the font preview */
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->vbox), frame,
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (frame);
|
|
|
|
dialog->preview = gtk_drawing_area_new ();
|
|
gtk_widget_set_size_request (dialog->preview, -1, 30);
|
|
gtk_container_add (GTK_CONTAINER (frame), dialog->preview);
|
|
gtk_widget_show (dialog->preview);
|
|
g_signal_connect (dialog->preview, "size_allocate",
|
|
G_CALLBACK (gimp_font_selection_dialog_preview_resize),
|
|
dialog);
|
|
g_signal_connect (dialog->preview, "expose_event",
|
|
G_CALLBACK (gimp_font_selection_dialog_preview_expose),
|
|
dialog);
|
|
|
|
/* Create the table of font & style. */
|
|
table = gtk_table_new (2, 2, FALSE);
|
|
gtk_widget_show (table);
|
|
gtk_table_set_col_spacings (GTK_TABLE (table), 4);
|
|
|
|
/* Create the lists */
|
|
model = gtk_list_store_new (2,
|
|
G_TYPE_OBJECT, /* FAMILY_COLUMN */
|
|
G_TYPE_STRING); /* FAMILY_NAME_COLUMN */
|
|
dialog->family_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
|
g_object_unref (model);
|
|
|
|
column =
|
|
gtk_tree_view_column_new_with_attributes ("Family",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", FAMILY_NAME_COLUMN,
|
|
NULL);
|
|
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->family_list), column);
|
|
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->family_list),
|
|
FALSE);
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->family_list));
|
|
gtk_tree_selection_set_mode (select, GTK_SELECTION_BROWSE);
|
|
|
|
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
|
|
GTK_SHADOW_IN);
|
|
gtk_widget_set_size_request (scrolled_win,
|
|
FONT_LIST_WIDTH, FONT_LIST_HEIGHT);
|
|
gtk_container_add (GTK_CONTAINER (scrolled_win), dialog->family_list);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
|
|
|
|
gtk_widget_show (dialog->family_list);
|
|
gtk_widget_show (scrolled_win);
|
|
|
|
gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 1, 2,
|
|
GTK_EXPAND | GTK_FILL,
|
|
GTK_EXPAND | GTK_FILL, 0, 0);
|
|
|
|
|
|
model = gtk_list_store_new (2,
|
|
G_TYPE_OBJECT, /* FACE_COLUMN */
|
|
G_TYPE_STRING); /* FACE_NAME_COLUMN */
|
|
dialog->face_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
|
g_object_unref (model);
|
|
|
|
column =
|
|
gtk_tree_view_column_new_with_attributes ("Face",
|
|
gtk_cell_renderer_text_new (),
|
|
"text", FACE_NAME_COLUMN,
|
|
NULL);
|
|
gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->face_list), column);
|
|
|
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->face_list), FALSE);
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->face_list));
|
|
gtk_tree_selection_set_mode (select, GTK_SELECTION_BROWSE);
|
|
|
|
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
|
|
GTK_SHADOW_IN);
|
|
gtk_widget_set_size_request (scrolled_win,
|
|
FONT_STYLE_LIST_WIDTH, FONT_LIST_HEIGHT);
|
|
gtk_container_add (GTK_CONTAINER (scrolled_win), dialog->face_list);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
|
|
|
|
gtk_widget_show (dialog->face_list);
|
|
gtk_widget_show (scrolled_win);
|
|
gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 1, 2,
|
|
GTK_EXPAND | GTK_FILL,
|
|
GTK_EXPAND | GTK_FILL, 0, 0);
|
|
|
|
label = gtk_label_new_with_mnemonic (_("_Family:"));
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->family_list);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
gtk_widget_show (label);
|
|
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
|
|
GTK_FILL, 0, 0, 0);
|
|
label = gtk_label_new_with_mnemonic (_("_Style:"));
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->face_list);
|
|
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
gtk_widget_show (label);
|
|
gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
|
|
GTK_FILL, 0, 0, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog->dialog)->vbox), table,
|
|
FALSE, FALSE, 0);
|
|
gtk_widget_show (table);
|
|
|
|
/* Insert the fonts. */
|
|
gimp_font_selection_dialog_show_available_fonts (dialog);
|
|
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->family_list));
|
|
g_signal_connect (select, "changed",
|
|
G_CALLBACK (gimp_font_selection_dialog_select_family),
|
|
dialog);
|
|
|
|
gimp_font_selection_dialog_show_available_styles (dialog);
|
|
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->face_list));
|
|
g_signal_connect (select, "changed",
|
|
G_CALLBACK (gimp_font_selection_dialog_select_style),
|
|
dialog);
|
|
|
|
dialog->layout = pango_layout_new (fontsel->context);
|
|
pango_layout_set_text (dialog->layout,
|
|
/* This is a so-called pangram; it's supposed to
|
|
contain all characters found in the alphabet. */
|
|
_("Pack my box with five dozen liquor jugs."), -1);
|
|
|
|
gimp_font_selection_dialog_set_font_desc (dialog, fontsel->font_desc);
|
|
|
|
closure = g_cclosure_new (G_CALLBACK (gimp_font_selection_dialog_font_changed),
|
|
dialog, NULL);
|
|
g_object_watch_closure (G_OBJECT (dialog->dialog), closure);
|
|
g_signal_connect_closure (fontsel, "font_changed", closure, FALSE);
|
|
|
|
return dialog;
|
|
}
|
|
|
|
void
|
|
gimp_font_selection_dialog_destroy (GimpFontSelectionDialog *dialog)
|
|
{
|
|
g_return_if_fail (dialog != NULL);
|
|
|
|
gtk_widget_destroy (dialog->dialog);
|
|
g_free (dialog->bitmap.buffer);
|
|
|
|
g_free (dialog);
|
|
}
|
|
|
|
void
|
|
gimp_font_selection_dialog_show (GimpFontSelectionDialog *dialog)
|
|
{
|
|
g_return_if_fail (dialog != NULL);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog->dialog));
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_font_changed (GimpFontSelection *fontsel,
|
|
GimpFontSelectionDialog *dialog)
|
|
{
|
|
gimp_font_selection_dialog_set_font_desc (dialog,
|
|
gimp_font_selection_get_font_desc (fontsel));
|
|
}
|
|
|
|
static void
|
|
scroll_to_selection (GtkTreeView *tree_view)
|
|
{
|
|
GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
{
|
|
GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
|
|
gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.5);
|
|
gtk_tree_path_free (path);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
font_description_style_equal (const PangoFontDescription *a,
|
|
const PangoFontDescription *b)
|
|
{
|
|
return (pango_font_description_get_weight (a) == pango_font_description_get_weight (b) &&
|
|
pango_font_description_get_style (a) == pango_font_description_get_style (b) &&
|
|
pango_font_description_get_stretch (a) == pango_font_description_get_stretch (b) &&
|
|
pango_font_description_get_variant (a) == pango_font_description_get_variant (b));
|
|
}
|
|
|
|
void
|
|
gimp_font_selection_dialog_set_font_desc (GimpFontSelectionDialog *dialog,
|
|
PangoFontDescription *desc)
|
|
{
|
|
PangoFontFamily *new_family = NULL;
|
|
GtkTreeModel *model;
|
|
GtkTreeSelection *select;
|
|
GtkTreeIter iter;
|
|
gboolean valid;
|
|
const gchar *name;
|
|
|
|
g_return_if_fail (dialog != NULL);
|
|
g_return_if_fail (desc != NULL);
|
|
|
|
name = pango_font_description_get_family (desc);
|
|
if (!name)
|
|
return;
|
|
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->family_list));
|
|
for (valid = gtk_tree_model_get_iter_root (model, &iter);
|
|
valid && !new_family;
|
|
valid = gtk_tree_model_iter_next (model, &iter))
|
|
{
|
|
PangoFontFamily *family;
|
|
|
|
gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
|
|
|
|
if (g_ascii_strcasecmp (pango_font_family_get_name (family), name) == 0)
|
|
new_family = family;
|
|
|
|
g_object_unref (family);
|
|
}
|
|
|
|
if (!new_family && !gtk_tree_model_get_iter_root (model, &iter))
|
|
return;
|
|
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->family_list));
|
|
gtk_tree_selection_select_iter (select, &iter);
|
|
|
|
gimp_font_selection_dialog_show_available_styles (dialog);
|
|
|
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->face_list));
|
|
for (valid = gtk_tree_model_get_iter_root (model, &iter);
|
|
valid;
|
|
valid = gtk_tree_model_iter_next (model, &iter))
|
|
{
|
|
PangoFontFace *face;
|
|
PangoFontDescription *tmp_desc;
|
|
|
|
gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
|
|
tmp_desc = pango_font_face_describe (face);
|
|
|
|
if (font_description_style_equal (tmp_desc, desc))
|
|
{
|
|
select =
|
|
gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->face_list));
|
|
gtk_tree_selection_select_iter (select, &iter);
|
|
|
|
pango_font_description_free (tmp_desc);
|
|
g_object_unref (face);
|
|
break;
|
|
}
|
|
|
|
pango_font_description_free (tmp_desc);
|
|
g_object_unref (face);
|
|
}
|
|
|
|
scroll_to_selection (GTK_TREE_VIEW (dialog->family_list));
|
|
scroll_to_selection (GTK_TREE_VIEW (dialog->face_list));
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_ok (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
GimpFontSelectionDialog *dialog = (GimpFontSelectionDialog *) data;
|
|
|
|
gimp_font_selection_dialog_apply (widget, data);
|
|
gtk_widget_hide (dialog->dialog);
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_apply (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
PangoFontDescription *font_desc;
|
|
GimpFontSelectionDialog *dialog = (GimpFontSelectionDialog *) data;
|
|
|
|
if (dialog->face)
|
|
{
|
|
font_desc = pango_font_face_describe (dialog->face);
|
|
|
|
g_signal_handlers_block_by_func (dialog->fontsel,
|
|
G_CALLBACK (gimp_font_selection_dialog_font_changed),
|
|
dialog);
|
|
|
|
gimp_font_selection_set_font_desc (dialog->fontsel, font_desc);
|
|
|
|
g_signal_handlers_unblock_by_func (dialog->fontsel,
|
|
G_CALLBACK (gimp_font_selection_dialog_font_changed),
|
|
dialog);
|
|
|
|
pango_font_description_free (font_desc);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_select_family (GtkTreeSelection *selection,
|
|
gpointer data)
|
|
{
|
|
GimpFontSelectionDialog *dialog;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
|
|
dialog = (GimpFontSelectionDialog *) data;
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
{
|
|
PangoFontFamily *family;
|
|
|
|
gtk_tree_model_get (model, &iter, FAMILY_COLUMN, &family, -1);
|
|
if (dialog->family != family)
|
|
{
|
|
dialog->family = family;
|
|
gimp_font_selection_dialog_show_available_styles (dialog);
|
|
gimp_font_selection_dialog_preview (dialog);
|
|
}
|
|
|
|
g_object_unref (family);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_select_style (GtkTreeSelection *selection,
|
|
gpointer data)
|
|
{
|
|
GimpFontSelectionDialog *dialog;
|
|
GtkTreeModel *model;
|
|
GtkTreeIter iter;
|
|
|
|
dialog = (GimpFontSelectionDialog *) data;
|
|
|
|
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
|
{
|
|
PangoFontFace *face;
|
|
|
|
gtk_tree_model_get (model, &iter, FACE_COLUMN, &face, -1);
|
|
|
|
if (dialog->face != face)
|
|
{
|
|
dialog->face = face;
|
|
gimp_font_selection_dialog_preview (dialog);
|
|
}
|
|
|
|
g_object_unref (face);
|
|
}
|
|
}
|
|
|
|
static int
|
|
cmp_families (const void *a, const void *b)
|
|
{
|
|
const gchar *a_name = pango_font_family_get_name (*(PangoFontFamily **)a);
|
|
const gchar *b_name = pango_font_family_get_name (*(PangoFontFamily **)b);
|
|
|
|
return strcmp (a_name, b_name);
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_show_available_fonts (GimpFontSelectionDialog *dialog)
|
|
{
|
|
GtkListStore *model;
|
|
PangoFontFamily **families;
|
|
PangoFontFamily *match_family = NULL;
|
|
const gchar *current_name;
|
|
gint n_families, i;
|
|
|
|
model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->family_list)));
|
|
|
|
pango_context_list_families (dialog->fontsel->context,
|
|
&families, &n_families);
|
|
qsort (families, n_families, sizeof (PangoFontFamily *), cmp_families);
|
|
|
|
gtk_list_store_clear (model);
|
|
|
|
if (dialog->family)
|
|
current_name = pango_font_family_get_name (dialog->family);
|
|
else
|
|
current_name = "Sans";
|
|
|
|
for (i = 0; i < n_families; i++)
|
|
{
|
|
const gchar *name = pango_font_family_get_name (families[i]);
|
|
GtkTreeIter iter;
|
|
|
|
gtk_list_store_append (model, &iter);
|
|
gtk_list_store_set (model, &iter,
|
|
FAMILY_COLUMN, families[i],
|
|
FAMILY_NAME_COLUMN, name,
|
|
-1);
|
|
|
|
if (i == 0 || !g_ascii_strcasecmp (name, current_name))
|
|
match_family = families[i];
|
|
}
|
|
|
|
dialog->family = match_family;
|
|
|
|
g_free (families);
|
|
}
|
|
|
|
static gint
|
|
compare_font_descriptions (const PangoFontDescription *a,
|
|
const PangoFontDescription *b)
|
|
{
|
|
gint val;
|
|
|
|
val = strcmp (pango_font_description_get_family (a),
|
|
pango_font_description_get_family (b));
|
|
|
|
if (val != 0)
|
|
return val;
|
|
|
|
if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b))
|
|
return pango_font_description_get_weight (a) - pango_font_description_get_weight (b);
|
|
|
|
if (pango_font_description_get_style (a) != pango_font_description_get_style (b))
|
|
return pango_font_description_get_style (a) - pango_font_description_get_style (b);
|
|
|
|
if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b))
|
|
return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b);
|
|
|
|
if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b))
|
|
return pango_font_description_get_variant (a) - pango_font_description_get_variant (b);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static gint
|
|
faces_sort_func (const void *a, const void *b)
|
|
{
|
|
PangoFontDescription *desc_a;
|
|
PangoFontDescription *desc_b;
|
|
gint ord;
|
|
|
|
desc_a = pango_font_face_describe (*(PangoFontFace **)a);
|
|
desc_b = pango_font_face_describe (*(PangoFontFace **)b);
|
|
|
|
ord = compare_font_descriptions (desc_a, desc_b);
|
|
|
|
pango_font_description_free (desc_a);
|
|
pango_font_description_free (desc_b);
|
|
|
|
return ord;
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_show_available_styles (GimpFontSelectionDialog *dialog)
|
|
{
|
|
PangoFontFace **faces;
|
|
PangoFontDescription *old_desc;
|
|
GtkListStore *model;
|
|
GtkTreeSelection *select;
|
|
GtkTreeIter match_row;
|
|
PangoFontFace *match_face = NULL;
|
|
gint n_faces, i;
|
|
|
|
model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->face_list)));
|
|
|
|
if (dialog->face)
|
|
old_desc = pango_font_face_describe (dialog->face);
|
|
else
|
|
old_desc= NULL;
|
|
|
|
pango_font_family_list_faces (dialog->family, &faces, &n_faces);
|
|
qsort (faces, n_faces, sizeof (PangoFontFace *), faces_sort_func);
|
|
|
|
gtk_list_store_clear (model);
|
|
|
|
if (n_faces < 0)
|
|
return;
|
|
|
|
for (i = 0; i < n_faces; i++)
|
|
{
|
|
GtkTreeIter iter;
|
|
const gchar *str = pango_font_face_get_face_name (faces[i]);
|
|
|
|
gtk_list_store_append (model, &iter);
|
|
gtk_list_store_set (model, &iter,
|
|
FACE_COLUMN, faces[i],
|
|
FACE_NAME_COLUMN, str, -1);
|
|
|
|
if (i == 0)
|
|
{
|
|
match_row = iter;
|
|
match_face = faces[i];
|
|
}
|
|
else if (old_desc)
|
|
{
|
|
PangoFontDescription *tmp_desc = pango_font_face_describe (faces[i]);
|
|
|
|
if (font_description_style_equal (tmp_desc, old_desc))
|
|
{
|
|
match_row = iter;
|
|
match_face = faces[i];
|
|
}
|
|
|
|
pango_font_description_free (tmp_desc);
|
|
}
|
|
}
|
|
|
|
if (old_desc)
|
|
pango_font_description_free (old_desc);
|
|
|
|
dialog->face = match_face;
|
|
|
|
g_free (faces);
|
|
|
|
select = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->face_list));
|
|
gtk_tree_selection_select_iter (select, &match_row);
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_preview (GimpFontSelectionDialog *dialog)
|
|
{
|
|
PangoRectangle rect;
|
|
|
|
if (dialog->face)
|
|
{
|
|
PangoFontDescription *font_desc;
|
|
|
|
font_desc = pango_font_face_describe (dialog->face);
|
|
pango_font_description_set_size (font_desc, PANGO_SCALE * FONT_SIZE);
|
|
pango_layout_set_font_description (dialog->layout, font_desc);
|
|
pango_font_description_free (font_desc);
|
|
|
|
pango_layout_get_pixel_extents (dialog->layout, NULL, &rect);
|
|
|
|
if (rect.height + 4 > dialog->preview->allocation.height)
|
|
gtk_widget_set_size_request (dialog->preview, -1, rect.height + 4);
|
|
|
|
/* FIXME: align on baseline */
|
|
|
|
memset (dialog->bitmap.buffer, 0,
|
|
dialog->bitmap.rows * dialog->bitmap.pitch);
|
|
pango_ft2_render_layout (&dialog->bitmap, dialog->layout, 2, 2);
|
|
}
|
|
|
|
gtk_widget_queue_draw (dialog->preview);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_font_selection_dialog_preview_expose (GtkWidget *widget,
|
|
GdkEventExpose *event,
|
|
gpointer data)
|
|
{
|
|
GimpFontSelectionDialog *dialog = (GimpFontSelectionDialog *) data;
|
|
GdkRectangle *area;
|
|
|
|
if (!GTK_WIDGET_DRAWABLE (widget))
|
|
return FALSE;
|
|
|
|
area = &event->area;
|
|
gdk_draw_rectangle (widget->window,
|
|
widget->style->white_gc,
|
|
TRUE, area->x, area->y, area->width, area->height);
|
|
|
|
if (dialog->face && dialog->bitmap.buffer)
|
|
{
|
|
guchar *src;
|
|
GdkGC *gc;
|
|
|
|
src = dialog->bitmap.buffer + area->y * dialog->bitmap.pitch + area->x;
|
|
|
|
gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
|
|
gdk_gc_set_function (gc, GDK_COPY_INVERT);
|
|
|
|
gdk_draw_gray_image (widget->window,
|
|
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
|
|
area->x, area->y,
|
|
area->width, area->height,
|
|
GDK_RGB_DITHER_NORMAL,
|
|
src, dialog->bitmap.pitch);
|
|
|
|
gdk_gc_set_function (gc, GDK_COPY);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gimp_font_selection_dialog_preview_resize (GtkWidget *widget,
|
|
GtkAllocation *allocation,
|
|
gpointer data)
|
|
{
|
|
GimpFontSelectionDialog *dialog = (GimpFontSelectionDialog *) data;
|
|
FT_Bitmap *bitmap;
|
|
|
|
bitmap = &dialog->bitmap;
|
|
if (bitmap->buffer)
|
|
g_free (bitmap->buffer);
|
|
|
|
bitmap->rows = allocation->height;
|
|
bitmap->width = allocation->width;
|
|
bitmap->pitch = allocation->width;
|
|
if (bitmap->pitch & 3)
|
|
bitmap->pitch += 4 - (bitmap->pitch & 3);
|
|
bitmap->buffer = g_malloc (bitmap->rows * bitmap->pitch);
|
|
|
|
gimp_font_selection_dialog_preview (dialog);
|
|
}
|