1 #define __SP_FONT_SELECTOR_C__
3 /*
4 * Font selection widgets
5 *
6 * Authors:
7 * Chris Lahey <clahey@ximian.com>
8 * Lauris Kaplinski <lauris@kaplinski.com>
9 * bulia byak <buliabyak@users.sf.net>
10 *
11 * Copyright (C) 1999-2001 Ximian, Inc.
12 * Copyright (C) 2002 Lauris Kaplinski
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 */
17 #ifdef HAVE_CONFIG_H
18 # include "config.h"
19 #endif
21 #include <libnr/nr-blit.h>
22 #include <libnrtype/font-instance.h>
23 #include <libnrtype/raster-glyph.h>
24 #include <libnrtype/RasterFont.h>
25 #include <libnrtype/TextWrapper.h>
26 #include <libnrtype/one-glyph.h>
28 #include <gtk/gtkframe.h>
29 #include <gtk/gtkscrolledwindow.h>
30 #include <gtk/gtkclist.h>
31 #include <gtk/gtkvbox.h>
32 #include <gtk/gtkcombo.h>
33 #include <gtk/gtkentry.h>
34 #include <gtk/gtkdrawingarea.h>
36 #include "../display/nr-plain-stuff-gdk.h"
37 #include <glibmm/i18n.h>
39 #include "font-selector.h"
41 /* SPFontSelector */
43 struct SPFontSelector
44 {
45 GtkHBox hbox;
47 unsigned int block_emit : 1;
49 GtkWidget *family;
50 GtkWidget *style;
51 GtkWidget *size;
53 NRNameList families;
54 NRStyleList styles;
55 int familyidx;
56 int styleidx;
57 gfloat fontsize;
58 bool fontsize_dirty;
59 font_instance *font;
60 };
63 struct SPFontSelectorClass
64 {
65 GtkHBoxClass parent_class;
67 void (* font_set) (SPFontSelector *fsel, font_instance *font);
68 };
70 enum {
71 FONT_SET,
72 LAST_SIGNAL
73 };
75 static void sp_font_selector_class_init(SPFontSelectorClass *c);
76 static void sp_font_selector_init(SPFontSelector *fsel);
77 static void sp_font_selector_destroy(GtkObject *object);
79 static void sp_font_selector_family_select_row(GtkCList *clist, gint row, gint column,
80 GdkEvent *event, SPFontSelector *fsel);
81 static void sp_font_selector_style_select_row(GtkCList *clist, gint row, gint column,
82 GdkEvent *event, SPFontSelector *fsel);
83 static void sp_font_selector_size_changed(GtkEditable *editable, SPFontSelector *fsel);
85 static void sp_font_selector_emit_set(SPFontSelector *fsel);
87 static const gchar *sizes[] = {
88 "4", "6", "8", "9", "10", "11", "12", "13", "14",
89 "16", "18", "20", "22", "24", "28",
90 "32", "36", "40", "48", "56", "64", "72", "144",
91 NULL
92 };
94 static GtkHBoxClass *fs_parent_class = NULL;
95 static guint fs_signals[LAST_SIGNAL] = { 0 };
97 GtkType sp_font_selector_get_type()
98 {
99 static GtkType type = 0;
100 if (!type) {
101 static const GtkTypeInfo info = {
102 "SPFontSelector",
103 sizeof(SPFontSelector),
104 sizeof(SPFontSelectorClass),
105 (GtkClassInitFunc) sp_font_selector_class_init,
106 (GtkObjectInitFunc) sp_font_selector_init,
107 NULL, NULL, NULL
108 };
109 type = gtk_type_unique(GTK_TYPE_HBOX, &info);
110 }
111 return type;
112 }
114 static void sp_font_selector_class_init(SPFontSelectorClass *c)
115 {
116 GtkObjectClass *object_class = (GtkObjectClass *) c;
118 fs_parent_class = (GtkHBoxClass* )gtk_type_class(GTK_TYPE_HBOX);
120 fs_signals[FONT_SET] = gtk_signal_new ("font_set",
121 GTK_RUN_FIRST,
122 GTK_CLASS_TYPE(object_class),
123 GTK_SIGNAL_OFFSET(SPFontSelectorClass, font_set),
124 gtk_marshal_NONE__POINTER,
125 GTK_TYPE_NONE,
126 1, GTK_TYPE_POINTER);
128 object_class->destroy = sp_font_selector_destroy;
129 }
131 static void sp_font_selector_init(SPFontSelector *fsel)
132 {
133 gtk_box_set_homogeneous(GTK_BOX(fsel), TRUE);
134 gtk_box_set_spacing(GTK_BOX(fsel), 4);
136 /* Family frame */
137 GtkWidget *f = gtk_frame_new(_("Font family"));
138 gtk_widget_show(f);
139 gtk_box_pack_start(GTK_BOX(fsel), f, TRUE, TRUE, 0);
141 GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
142 gtk_widget_show(sw);
143 gtk_container_set_border_width(GTK_CONTAINER (sw), 4);
144 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
145 gtk_container_add(GTK_CONTAINER(f), sw);
147 fsel->family = gtk_clist_new (1);
148 gtk_widget_show (fsel->family);
149 gtk_clist_set_selection_mode(GTK_CLIST(fsel->family), GTK_SELECTION_SINGLE);
150 gtk_clist_column_titles_hide(GTK_CLIST(fsel->family));
151 gtk_signal_connect(GTK_OBJECT(fsel->family), "select_row", GTK_SIGNAL_FUNC(sp_font_selector_family_select_row), fsel);
152 gtk_container_add(GTK_CONTAINER(sw), fsel->family);
154 if ((font_factory::Default())->Families(&fsel->families)) {
155 gtk_clist_freeze(GTK_CLIST(fsel->family));
156 for (guint i = 0; i < fsel->families.length; i++) {
157 gtk_clist_append(GTK_CLIST(fsel->family), (gchar **) fsel->families.names + i);
158 gtk_clist_set_row_data(GTK_CLIST(fsel->family), i, GUINT_TO_POINTER(i));
159 }
160 gtk_clist_thaw(GTK_CLIST(fsel->family));
161 }
163 /* Style frame */
164 f = gtk_frame_new(_("Style"));
165 gtk_widget_show(f);
166 gtk_box_pack_start(GTK_BOX (fsel), f, TRUE, TRUE, 0);
168 GtkWidget *vb = gtk_vbox_new(FALSE, 4);
169 gtk_widget_show(vb);
170 gtk_container_set_border_width(GTK_CONTAINER (vb), 4);
171 gtk_container_add(GTK_CONTAINER(f), vb);
173 sw = gtk_scrolled_window_new(NULL, NULL);
174 gtk_widget_show(sw);
175 gtk_container_set_border_width(GTK_CONTAINER (sw), 4);
176 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
177 gtk_box_pack_start(GTK_BOX (vb), sw, TRUE, TRUE, 0);
179 fsel->style = gtk_clist_new (1);
180 gtk_widget_show (fsel->style);
181 gtk_clist_set_selection_mode(GTK_CLIST (fsel->style), GTK_SELECTION_SINGLE);
182 gtk_clist_column_titles_hide(GTK_CLIST (fsel->style));
183 gtk_signal_connect(GTK_OBJECT(fsel->style), "select_row", GTK_SIGNAL_FUNC (sp_font_selector_style_select_row), fsel);
184 gtk_container_add(GTK_CONTAINER(sw), fsel->style);
186 GtkWidget *hb = gtk_hbox_new(FALSE, 4);
187 gtk_widget_show(hb);
188 gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, FALSE, 0);
190 fsel->size = gtk_combo_new();
191 gtk_widget_show (fsel->size);
192 gtk_combo_set_value_in_list(GTK_COMBO (fsel->size), FALSE, FALSE);
193 gtk_combo_set_use_arrows(GTK_COMBO (fsel->size), TRUE);
194 gtk_combo_set_use_arrows_always(GTK_COMBO (fsel->size), TRUE);
195 gtk_widget_set_size_request(fsel->size, 90, -1);
196 gtk_signal_connect(GTK_OBJECT(GTK_COMBO(fsel->size)->entry), "changed", GTK_SIGNAL_FUNC(sp_font_selector_size_changed), fsel);
197 gtk_box_pack_end(GTK_BOX(hb), fsel->size, FALSE, FALSE, 0);
199 GtkWidget *l = gtk_label_new(_("Font size:"));
200 gtk_widget_show(l);
201 gtk_box_pack_end(GTK_BOX (hb), l, FALSE, FALSE, 0);
203 /* Setup strings */
204 GList *sl = NULL;
205 for (int i = 0; sizes[i] != NULL; i++) {
206 sl = g_list_prepend (sl, (gpointer) sizes[i]);
207 }
208 sl = g_list_reverse (sl);
209 gtk_combo_set_popdown_strings(GTK_COMBO(fsel->size), sl);
210 g_list_free (sl);
212 fsel->familyidx = 0;
213 fsel->styleidx = 0;
214 fsel->fontsize = 10.0;
215 fsel->fontsize_dirty = false;
216 fsel->font = NULL;
217 }
219 static void sp_font_selector_destroy(GtkObject *object)
220 {
221 SPFontSelector *fsel = SP_FONT_SELECTOR (object);
223 if (fsel->font) {
224 fsel->font->Unref();
225 fsel->font = NULL;
226 }
228 if (fsel->families.length > 0) {
229 nr_name_list_release(&fsel->families);
230 fsel->families.length = 0;
231 }
233 if (fsel->styles.length > 0) {
234 nr_style_list_release(&fsel->styles);
235 fsel->styles.length = 0;
236 }
238 if (GTK_OBJECT_CLASS(fs_parent_class)->destroy) {
239 GTK_OBJECT_CLASS(fs_parent_class)->destroy(object);
240 }
241 }
243 static void sp_font_selector_family_select_row(GtkCList *clist, gint row, gint column,
244 GdkEvent *event, SPFontSelector *fsel)
245 {
246 fsel->familyidx = GPOINTER_TO_UINT (gtk_clist_get_row_data (clist, row));
248 if (fsel->styles.length > 0) {
249 nr_style_list_release (&fsel->styles);
250 fsel->styles.length = 0;
251 fsel->styleidx = 0;
252 }
253 gtk_clist_clear (GTK_CLIST (fsel->style));
255 if ( static_cast<unsigned int> (fsel->familyidx) < fsel->families.length ) {
257 const gchar *family = (const gchar *) fsel->families.names[fsel->familyidx];
259 if ((font_factory::Default())->Styles(family, &fsel->styles)) {
261 gtk_clist_freeze(GTK_CLIST(fsel->style));
262 for (unsigned int i = 0; i < fsel->styles.length; i++) {
264 const gchar *p = (const gchar *) ((fsel->styles.records)[i].name);
266 gtk_clist_append(GTK_CLIST(fsel->style), (gchar **) &p);
267 gtk_clist_set_row_data(GTK_CLIST(fsel->style), static_cast<gint> (i), GUINT_TO_POINTER (i));
268 }
269 gtk_clist_thaw(GTK_CLIST(fsel->style));
270 gtk_clist_select_row(GTK_CLIST(fsel->style), 0, 0);
271 }
272 }
273 }
275 static void sp_font_selector_style_select_row(GtkCList *clist, gint row, gint column,
276 GdkEvent *event, SPFontSelector *fsel)
277 {
278 fsel->styleidx = GPOINTER_TO_UINT(gtk_clist_get_row_data(clist, row));
280 if (!fsel->block_emit) {
281 sp_font_selector_emit_set (fsel);
282 }
283 }
285 static void sp_font_selector_size_changed(GtkEditable *editable, SPFontSelector *fsel)
286 {
287 const gchar *sstr = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(fsel->size)->entry));
288 gfloat old_size = fsel->fontsize;
289 fsel->fontsize = MAX(atof(sstr), 0.1);
290 if ( fabs(fsel->fontsize-old_size) > 0.001) {
291 fsel->fontsize_dirty = true;
292 }
294 sp_font_selector_emit_set(fsel);
295 }
297 static void sp_font_selector_emit_set(SPFontSelector *fsel)
298 {
299 font_instance *font;
301 if (static_cast<unsigned int>(fsel->styleidx) < fsel->styles.length
302 && static_cast<unsigned int>(fsel->familyidx) < fsel->families.length)
303 {
304 font = (font_factory::Default())->FaceFromDescr ((gchar *) ((fsel->families.names)[fsel->familyidx]),
305 (gchar *) ((fsel->styles.records)[fsel->styleidx].name));
306 } else {
307 font = NULL;
308 }
310 // FIXME: when a text object uses non-available font, font==NULL and we can't set size
311 // (and the size shown in the widget is invalid). To fix, here we must always get some
312 // default font, exactly the same as sptext uses for on-canvas display, so that
313 // font!=NULL ever.
314 if (font != fsel->font || ( font && fsel->fontsize_dirty ) ) {
315 if ( font ) {
316 font->Ref();
317 }
318 if ( fsel->font ) {
319 fsel->font->Unref();
320 }
321 fsel->font = font;
322 gtk_signal_emit(GTK_OBJECT(fsel), fs_signals[FONT_SET], fsel->font);
323 }
324 fsel->fontsize_dirty = false;
325 if (font) {
326 font->Unref();
327 }
328 font = NULL;
329 }
331 GtkWidget *sp_font_selector_new()
332 {
333 SPFontSelector *fsel = (SPFontSelector*) gtk_type_new(SP_TYPE_FONT_SELECTOR);
335 return (GtkWidget *) fsel;
336 }
338 void sp_font_selector_set_font(SPFontSelector *fsel, font_instance *font, double size)
339 {
340 GtkCList *fcl = GTK_CLIST(fsel->family);
341 GtkCList *scl = GTK_CLIST(fsel->style);
343 if (font && (fsel->font != font || size != fsel->fontsize)) {
344 { // select family in the list
345 gchar family[256];
346 font->Family (family, 256);
348 unsigned int i;
349 for (i = 0; i < fsel->families.length; i++) {
350 if (!strcasecmp (family, (gchar *)fsel->families.names[i])) {
351 break;
352 }
353 }
355 if (i >= fsel->families.length) {
356 return;
357 }
359 fsel->block_emit = TRUE;
360 gtk_clist_select_row(fcl, i, 0);
361 gtk_clist_moveto(fcl, i, 0, 0.66, 0.0);
362 fsel->block_emit = FALSE;
363 }
365 { // select best-matching style in the list
366 gchar descr[256];
367 font->Name(descr, 256);
368 PangoFontDescription *descr_ = pango_font_description_from_string(descr);
369 PangoFontDescription *best_ = pango_font_description_from_string((fsel->styles.records)[0].descr);
370 guint best_i = 0;
372 for (guint i = 0; i < fsel->styles.length; i++) {
373 PangoFontDescription *try_ = pango_font_description_from_string((fsel->styles.records)[i].descr);
374 if (pango_font_description_better_match(descr_, best_, try_)) {
375 pango_font_description_free(best_);
376 best_ = pango_font_description_from_string((fsel->styles.records)[i].descr);
377 best_i = i;
378 }
379 pango_font_description_free(try_);
380 }
382 gtk_clist_select_row(scl, best_i, 0);
383 gtk_clist_moveto(scl, best_i, 0, 0.66, 0.0);
384 }
386 if (size != fsel->fontsize) {
387 gchar s[8];
388 g_snprintf (s, 8, "%.5g", size); // UI, so printf is ok
389 gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (fsel->size)->entry), s);
390 fsel->fontsize = size;
391 }
392 }
393 }
395 font_instance* sp_font_selector_get_font(SPFontSelector *fsel)
396 {
397 if (fsel->font) {
398 fsel->font->Ref();
399 }
401 return fsel->font;
402 }
404 double sp_font_selector_get_size(SPFontSelector *fsel)
405 {
406 return fsel->fontsize;
407 }
409 /* SPFontPreview */
411 struct SPFontPreview
412 {
413 GtkDrawingArea darea;
415 font_instance *font;
416 raster_font *rfont;
417 gchar *phrase;
418 unsigned long rgba;
419 };
421 struct SPFontPreviewClass
422 {
423 GtkDrawingAreaClass parent_class;
424 };
426 static void sp_font_preview_class_init(SPFontPreviewClass *c);
427 static void sp_font_preview_init(SPFontPreview *fsel);
428 static void sp_font_preview_destroy(GtkObject *object);
430 void sp_font_preview_size_request(GtkWidget *widget, GtkRequisition *req);
431 static gint sp_font_preview_expose(GtkWidget *widget, GdkEventExpose *event);
433 static GtkDrawingAreaClass *fp_parent_class = NULL;
435 GtkType sp_font_preview_get_type()
436 {
437 static GtkType type = 0;
438 if (!type) {
439 static const GtkTypeInfo info = {
440 "SPFontPreview",
441 sizeof (SPFontPreview),
442 sizeof (SPFontPreviewClass),
443 (GtkClassInitFunc) sp_font_preview_class_init,
444 (GtkObjectInitFunc) sp_font_preview_init,
445 NULL, NULL, NULL
446 };
447 type = gtk_type_unique (GTK_TYPE_DRAWING_AREA, &info);
448 }
449 return type;
450 }
452 static void sp_font_preview_class_init (SPFontPreviewClass *c)
453 {
454 GtkObjectClass *object_class = (GtkObjectClass *) c;
455 GtkWidgetClass *widget_class = (GtkWidgetClass *) c;
457 fp_parent_class = (GtkDrawingAreaClass*) gtk_type_class(GTK_TYPE_DRAWING_AREA);
459 object_class->destroy = sp_font_preview_destroy;
461 widget_class->size_request = sp_font_preview_size_request;
462 widget_class->expose_event = sp_font_preview_expose;
463 }
465 static void sp_font_preview_init(SPFontPreview *fprev)
466 {
467 fprev->rgba = 0x000000ff;
468 }
470 static void sp_font_preview_destroy(GtkObject *object)
471 {
472 SPFontPreview *fprev = SP_FONT_PREVIEW (object);
474 if (fprev->rfont) {
475 fprev->rfont->Unref();
476 fprev->rfont = NULL;
477 }
479 if (fprev->font) {
480 fprev->font->Unref();
481 fprev->font = NULL;
482 }
484 g_free(fprev->phrase);
485 fprev->phrase = NULL;
487 if (GTK_OBJECT_CLASS (fp_parent_class)->destroy) {
488 GTK_OBJECT_CLASS (fp_parent_class)->destroy(object);
489 }
490 }
492 void sp_font_preview_size_request(GtkWidget *widget, GtkRequisition *req)
493 {
494 req->width = 256;
495 req->height = 32;
496 }
498 #define SPFP_MAX_LEN 64
500 static gint sp_font_preview_expose(GtkWidget *widget, GdkEventExpose *event)
501 {
502 SPFontPreview *fprev = SP_FONT_PREVIEW(widget);
504 if (GTK_WIDGET_DRAWABLE (widget)) {
505 if (fprev->rfont) {
507 int glyphs[SPFP_MAX_LEN];
508 double hpos[SPFP_MAX_LEN];
510 font_instance *tface = fprev->rfont->daddy;
512 double theSize = NR_MATRIX_DF_EXPANSION (&fprev->rfont->style.transform);
514 gchar const *p;
515 if (fprev->phrase) {
516 p = fprev->phrase;
517 } else {
518 /* TRANSLATORS: Test string used in text and font dialog (when no
519 * text has been entered) to get a preview of the font. Choose
520 * some representative characters that users of your locale will be
521 * interested in. */
522 p = _("AaBbCcIiPpQq12368.;/()");
523 }
524 int len = 0;
526 NRRect bbox;
527 bbox.x0 = bbox.y0 = bbox.x1 = bbox.y1 = 0.0;
529 text_wrapper* str_text=new text_wrapper;
530 str_text->SetDefaultFont(tface);
531 str_text->AppendUTF8(p,-1);
532 if ( str_text->uni32_length > 0 ) {
533 str_text->DoLayout();
534 if ( str_text->glyph_length > 0 ) {
535 PangoFont *curPF = NULL;
536 font_instance *curF = NULL;
537 for (int i = 0; i < str_text->glyph_length && i < SPFP_MAX_LEN; i++) {
538 if ( str_text->glyph_text[i].font != curPF ) {
539 curPF = str_text->glyph_text[i].font;
540 if (curF) {
541 curF->Unref();
542 }
543 curF = NULL;
544 if ( curPF ) {
545 PangoFontDescription* pfd = pango_font_describe(curPF);
546 curF = (font_factory::Default())->Face(pfd);
547 pango_font_description_free(pfd);
548 }
549 }
550 NR::Point base_pt(str_text->glyph_text[i].x, str_text->glyph_text[i].y);
551 base_pt *= theSize;
553 glyphs[len] = str_text->glyph_text[i].gl;
554 hpos[len] = base_pt[0];
555 len++;
556 if ( curF ) {
557 NR::Rect nbbox = curF->BBox(str_text->glyph_text[i].gl);
558 bbox.x0 = MIN(bbox.x0, base_pt[NR::X] + theSize * (nbbox.min())[0]);
559 bbox.y0 = MIN(bbox.y0, base_pt[NR::Y] - theSize * (nbbox.max())[1]);
560 bbox.x1 = MAX(bbox.x1, base_pt[NR::X] + theSize * (nbbox.max())[0]);
561 bbox.y1 = MAX(bbox.y1, base_pt[NR::Y] - theSize * (nbbox.min())[1]);
562 }
563 }
564 if ( curF ) {
565 curF->Unref();
566 }
567 }
568 }
570 // XXX: FIXME: why does this code ignore adv.y
571 /* while (p && *p && (len < SPFP_MAX_LEN)) {
572 unsigned int unival;
573 NRRect gbox;
574 unival = g_utf8_get_char (p);
575 glyphs[len] = tface->MapUnicodeChar( unival);
576 hpos[len] = (int)px;
577 NR::Point adv = fprev->rfont->Advance(glyphs[len]);
578 fprev->rfont->BBox( glyphs[len], &gbox);
579 bbox.x0 = MIN (px + gbox.x0, bbox.x0);
580 bbox.y0 = MIN (py + gbox.y0, bbox.y0);
581 bbox.x1 = MAX (px + gbox.x1, bbox.x1);
582 bbox.y1 = MAX (py + gbox.y1, bbox.y1);
583 px += adv[NR::X];
584 len += 1;
585 p = g_utf8_next_char (p);
586 }*/
588 float startx = (widget->allocation.width - (bbox.x1 - bbox.x0)) / 2;
589 float starty = widget->allocation.height - (widget->allocation.height - (bbox.y1 - bbox.y0)) / 2 - bbox.y1;
591 for (int y = event->area.y; y < event->area.y + event->area.height; y += 64) {
592 for (int x = event->area.x; x < event->area.x + event->area.width; x += 64) {
593 NRPixBlock pb, m;
594 int x0 = x;
595 int y0 = y;
596 int x1 = MIN(x0 + 64, event->area.x + event->area.width);
597 int y1 = MIN(y0 + 64, event->area.y + event->area.height);
598 guchar *ps = nr_pixelstore_16K_new (TRUE, 0xff);
599 nr_pixblock_setup_extern(&pb, NR_PIXBLOCK_MODE_R8G8B8, x0, y0, x1, y1, ps, 3 * (x1 - x0), FALSE, FALSE);
600 nr_pixblock_setup_fast(&m, NR_PIXBLOCK_MODE_A8, x0, y0, x1, y1, TRUE);
601 pb.empty = FALSE;
603 PangoFont *curPF = NULL;
604 font_instance *curF = NULL;
605 raster_font *curRF = NULL;
606 for (int i=0; i < len; i++) {
607 if ( str_text->glyph_text[i].font != curPF ) {
608 curPF=str_text->glyph_text[i].font;
609 if ( curF ) {
610 curF->Unref();
611 }
612 curF = NULL;
613 if ( curPF ) {
614 PangoFontDescription* pfd = pango_font_describe(curPF);
615 curF=(font_factory::Default())->Face(pfd);
616 pango_font_description_free(pfd);
617 }
618 if ( curF ) {
619 if ( curRF ) {
620 curRF->Unref();
621 }
622 curRF = NULL;
623 curRF = curF->RasterFont(fprev->rfont->style);
624 }
625 }
626 raster_glyph *g = (curRF) ? curRF->GetGlyph(glyphs[i]) : NULL;
627 if ( g ) {
628 g->Blit(NR::Point(hpos[i] + startx, starty), m);
629 }
630 }
631 if (curRF) {
632 curRF->Unref();
633 }
634 if (curF) {
635 curF->Unref();
636 }
638 nr_blit_pixblock_mask_rgba32(&pb, &m, fprev->rgba);
639 gdk_draw_rgb_image(widget->window, widget->style->black_gc,
640 x0, y0, x1 - x0, y1 - y0,
641 GDK_RGB_DITHER_NONE, NR_PIXBLOCK_PX (&pb), pb.rs);
642 nr_pixblock_release(&m);
643 nr_pixblock_release(&pb);
644 nr_pixelstore_16K_free(ps);
645 }
646 }
648 delete str_text;
650 } else {
651 nr_gdk_draw_gray_garbage(widget->window, widget->style->black_gc,
652 event->area.x, event->area.y,
653 event->area.width, event->area.height);
654 }
655 }
657 return TRUE;
658 }
660 GtkWidget * sp_font_preview_new()
661 {
662 GtkWidget *w = (GtkWidget*) gtk_type_new(SP_TYPE_FONT_PREVIEW);
664 return w;
665 }
667 void sp_font_preview_set_font(SPFontPreview *fprev, font_instance *font, SPFontSelector *fsel)
668 {
669 if (font != fprev->font) {
670 if (font) {
671 font->Ref();
672 }
673 if (fprev->font) {
674 fprev->font->Unref();
675 }
676 fprev->font = font;
678 if (fprev->rfont) {
679 fprev->rfont->Unref();
680 fprev->rfont=NULL;
681 }
682 if (fprev->font) {
683 NRMatrix flip;
684 nr_matrix_set_scale (&flip, fsel->fontsize, -fsel->fontsize);
685 fprev->rfont = fprev->font->RasterFont(flip, 0);
686 }
687 if (GTK_WIDGET_DRAWABLE (fprev)) gtk_widget_queue_draw (GTK_WIDGET (fprev));
688 }
689 }
691 void sp_font_preview_set_rgba32(SPFontPreview *fprev, guint32 rgba)
692 {
693 fprev->rgba = rgba;
694 if (GTK_WIDGET_DRAWABLE (fprev)) {
695 gtk_widget_queue_draw (GTK_WIDGET (fprev));
696 }
697 }
699 void sp_font_preview_set_phrase(SPFontPreview *fprev, const gchar *phrase)
700 {
701 g_free (fprev->phrase);
702 if (phrase) {
703 fprev->phrase = g_strdup (phrase);
704 } else {
705 fprev->phrase = NULL;
706 }
707 if (GTK_WIDGET_DRAWABLE(fprev)) {
708 gtk_widget_queue_draw (GTK_WIDGET (fprev));
709 }
710 }
713 /*
714 Local Variables:
715 mode:c++
716 c-file-style:"stroustrup"
717 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
718 indent-tabs-mode:nil
719 fill-column:99
720 End:
721 */
722 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :