зеркало из https://github.com/github/putty.git
Implemented a Pango back end. GTK 2 PuTTY can now switch seamlessly
back and forth between X fonts and Pango fonts, provided you're willing to type in the names of the former by hand. [originally from svn r7937]
This commit is contained in:
Родитель
93c6e2c987
Коммит
debbee0fe4
196
unix/gtkfont.c
196
unix/gtkfont.c
|
@ -25,10 +25,11 @@
|
|||
/*
|
||||
* To do:
|
||||
*
|
||||
* - import flags to do VT100 double-width, and import the icky
|
||||
* pixmap stretch code for it.
|
||||
* - import flags to do VT100 double-width; import the icky
|
||||
* pixmap stretch code on to the X11 side, and do something
|
||||
* nicer in Pango.
|
||||
*
|
||||
* - add the Pango back end!
|
||||
* - unified font selector dialog, arrgh!
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -56,12 +57,12 @@ struct unifont_vtable {
|
|||
/*
|
||||
* `Methods' of the `class'.
|
||||
*/
|
||||
unifont *(*create)(char *name, int wide, int bold,
|
||||
unifont *(*create)(GtkWidget *widget, char *name, int wide, int bold,
|
||||
int shadowoffset, int shadowalways);
|
||||
void (*destroy)(unifont *font);
|
||||
void (*draw_text)(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len, int wide,
|
||||
int bold);
|
||||
int bold, int cellwidth);
|
||||
/*
|
||||
* `Static data members' of the `class'.
|
||||
*/
|
||||
|
@ -74,8 +75,9 @@ struct unifont_vtable {
|
|||
|
||||
static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold);
|
||||
static unifont *x11font_create(char *name, int wide, int bold,
|
||||
int wide, int bold, int cellwidth);
|
||||
static unifont *x11font_create(GtkWidget *widget, char *name,
|
||||
int wide, int bold,
|
||||
int shadowoffset, int shadowalways);
|
||||
static void x11font_destroy(unifont *font);
|
||||
|
||||
|
@ -99,11 +101,6 @@ struct x11font {
|
|||
* whether we use gdk_draw_text_wc() or gdk_draw_text().
|
||||
*/
|
||||
int sixteen_bit;
|
||||
/*
|
||||
* Font charsets. public_charset and real_charset can differ
|
||||
* for X11 fonts, because many X fonts use CS_ISO8859_1_X11.
|
||||
*/
|
||||
int public_charset, real_charset;
|
||||
/*
|
||||
* Data passed in to unifont_create().
|
||||
*/
|
||||
|
@ -181,7 +178,8 @@ static int x11_font_width(GdkFont *font, int sixteen_bit)
|
|||
}
|
||||
}
|
||||
|
||||
static unifont *x11font_create(char *name, int wide, int bold,
|
||||
static unifont *x11font_create(GtkWidget *widget, char *name,
|
||||
int wide, int bold,
|
||||
int shadowoffset, int shadowalways)
|
||||
{
|
||||
struct x11font *xfont;
|
||||
|
@ -299,7 +297,7 @@ static void x11_alloc_subfont(struct x11font *xfont, int sfid)
|
|||
|
||||
static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold)
|
||||
int wide, int bold, int cellwidth)
|
||||
{
|
||||
struct x11font *xfont = (struct x11font *)font;
|
||||
int sfid;
|
||||
|
@ -374,6 +372,164 @@ static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
|||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Pango font implementation.
|
||||
*/
|
||||
|
||||
static void pangofont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold, int cellwidth);
|
||||
static unifont *pangofont_create(GtkWidget *widget, char *name,
|
||||
int wide, int bold,
|
||||
int shadowoffset, int shadowalways);
|
||||
static void pangofont_destroy(unifont *font);
|
||||
|
||||
struct pangofont {
|
||||
struct unifont u;
|
||||
/*
|
||||
* Pango objects.
|
||||
*/
|
||||
PangoFontDescription *desc;
|
||||
PangoFontset *fset;
|
||||
/*
|
||||
* The containing widget.
|
||||
*/
|
||||
GtkWidget *widget;
|
||||
/*
|
||||
* Data passed in to unifont_create().
|
||||
*/
|
||||
int bold, shadowoffset, shadowalways;
|
||||
};
|
||||
|
||||
static const struct unifont_vtable pangofont_vtable = {
|
||||
pangofont_create,
|
||||
pangofont_destroy,
|
||||
pangofont_draw_text,
|
||||
"pango"
|
||||
};
|
||||
|
||||
static unifont *pangofont_create(GtkWidget *widget, char *name,
|
||||
int wide, int bold,
|
||||
int shadowoffset, int shadowalways)
|
||||
{
|
||||
struct pangofont *pfont;
|
||||
PangoContext *ctx;
|
||||
PangoFontMap *map;
|
||||
PangoFontDescription *desc;
|
||||
PangoFontset *fset;
|
||||
PangoFontMetrics *metrics;
|
||||
|
||||
desc = pango_font_description_from_string(name);
|
||||
if (!desc)
|
||||
return NULL;
|
||||
ctx = gtk_widget_get_pango_context(widget);
|
||||
if (!ctx) {
|
||||
pango_font_description_free(desc);
|
||||
return NULL;
|
||||
}
|
||||
map = pango_context_get_font_map(ctx);
|
||||
if (!map) {
|
||||
pango_font_description_free(desc);
|
||||
return NULL;
|
||||
}
|
||||
fset = pango_font_map_load_fontset(map, ctx, desc,
|
||||
pango_context_get_language(ctx));
|
||||
if (!fset) {
|
||||
pango_font_description_free(desc);
|
||||
return NULL;
|
||||
}
|
||||
metrics = pango_fontset_get_metrics(fset);
|
||||
if (!metrics ||
|
||||
pango_font_metrics_get_approximate_digit_width(metrics) == 0) {
|
||||
pango_font_description_free(desc);
|
||||
g_object_unref(fset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pfont = snew(struct pangofont);
|
||||
pfont->u.vt = &pangofont_vtable;
|
||||
pfont->u.width =
|
||||
PANGO_PIXELS(pango_font_metrics_get_approximate_digit_width(metrics));
|
||||
pfont->u.ascent = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics));
|
||||
pfont->u.descent = PANGO_PIXELS(pango_font_metrics_get_descent(metrics));
|
||||
pfont->u.height = pfont->u.ascent + pfont->u.descent;
|
||||
/* The Pango API is hardwired to UTF-8 */
|
||||
pfont->u.public_charset = CS_UTF8;
|
||||
pfont->u.real_charset = CS_UTF8;
|
||||
pfont->desc = desc;
|
||||
pfont->fset = fset;
|
||||
pfont->widget = widget;
|
||||
pfont->bold = bold;
|
||||
pfont->shadowoffset = shadowoffset;
|
||||
pfont->shadowalways = shadowalways;
|
||||
|
||||
return (unifont *)pfont;
|
||||
}
|
||||
|
||||
static void pangofont_destroy(unifont *font)
|
||||
{
|
||||
struct pangofont *pfont = (struct pangofont *)font;
|
||||
pfont = pfont; /* FIXME */
|
||||
pango_font_description_free(pfont->desc);
|
||||
g_object_unref(pfont->fset);
|
||||
sfree(font);
|
||||
}
|
||||
|
||||
static void pangofont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold, int cellwidth)
|
||||
{
|
||||
struct pangofont *pfont = (struct pangofont *)font;
|
||||
PangoLayout *layout;
|
||||
PangoRectangle rect;
|
||||
int shadowbold = FALSE;
|
||||
|
||||
if (wide)
|
||||
cellwidth *= 2;
|
||||
|
||||
y -= pfont->u.ascent;
|
||||
|
||||
layout = pango_layout_new(gtk_widget_get_pango_context(pfont->widget));
|
||||
pango_layout_set_font_description(layout, pfont->desc);
|
||||
if (bold > pfont->bold) {
|
||||
if (pfont->shadowalways)
|
||||
shadowbold = TRUE;
|
||||
else {
|
||||
PangoFontDescription *desc2 =
|
||||
pango_font_description_copy_static(pfont->desc);
|
||||
pango_font_description_set_weight(desc2, PANGO_WEIGHT_BOLD);
|
||||
pango_layout_set_font_description(layout, desc2);
|
||||
}
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
int clen;
|
||||
|
||||
/*
|
||||
* Extract a single UTF-8 character from the string.
|
||||
*/
|
||||
clen = 1;
|
||||
while (clen < len &&
|
||||
(unsigned char)string[clen] >= 0x80 &&
|
||||
(unsigned char)string[clen] < 0xC0)
|
||||
clen++;
|
||||
|
||||
pango_layout_set_text(layout, string, clen);
|
||||
pango_layout_get_pixel_extents(layout, NULL, &rect);
|
||||
gdk_draw_layout(target, gc, x + (cellwidth - rect.width)/2,
|
||||
y + (pfont->u.height - rect.height)/2, layout);
|
||||
if (shadowbold)
|
||||
gdk_draw_layout(target, gc, x + (cellwidth - rect.width)/2 + pfont->shadowoffset,
|
||||
y + (pfont->u.height - rect.height)/2, layout);
|
||||
|
||||
len -= clen;
|
||||
string += clen;
|
||||
x += cellwidth;
|
||||
}
|
||||
|
||||
g_object_unref(layout);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Outermost functions which do the vtable dispatch.
|
||||
*/
|
||||
|
@ -385,9 +541,10 @@ static void x11font_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
|||
* the font name.
|
||||
*/
|
||||
static const struct unifont_vtable *unifont_types[] = {
|
||||
&pangofont_vtable,
|
||||
&x11font_vtable,
|
||||
};
|
||||
unifont *unifont_create(char *name, int wide, int bold,
|
||||
unifont *unifont_create(GtkWidget *widget, char *name, int wide, int bold,
|
||||
int shadowoffset, int shadowalways)
|
||||
{
|
||||
int colonpos = strcspn(name, ":");
|
||||
|
@ -405,14 +562,14 @@ unifont *unifont_create(char *name, int wide, int bold,
|
|||
}
|
||||
if (i == lenof(unifont_types))
|
||||
return NULL; /* prefix not recognised */
|
||||
return unifont_types[i]->create(name+colonpos+1, wide, bold,
|
||||
return unifont_types[i]->create(widget, name+colonpos+1, wide, bold,
|
||||
shadowoffset, shadowalways);
|
||||
} else {
|
||||
/*
|
||||
* No colon prefix, so just go through all the subclasses.
|
||||
*/
|
||||
for (i = 0; i < lenof(unifont_types); i++) {
|
||||
unifont *ret = unifont_types[i]->create(name, wide, bold,
|
||||
unifont *ret = unifont_types[i]->create(widget, name, wide, bold,
|
||||
shadowoffset,
|
||||
shadowalways);
|
||||
if (ret)
|
||||
|
@ -429,7 +586,8 @@ void unifont_destroy(unifont *font)
|
|||
|
||||
void unifont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold)
|
||||
int wide, int bold, int cellwidth)
|
||||
{
|
||||
font->vt->draw_text(target, gc, font, x, y, string, len, wide, bold);
|
||||
font->vt->draw_text(target, gc, font, x, y, string, len,
|
||||
wide, bold, cellwidth);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ typedef struct unifont {
|
|||
int width, height, ascent, descent;
|
||||
} unifont;
|
||||
|
||||
unifont *unifont_create(char *name, int wide, int bold,
|
||||
unifont *unifont_create(GtkWidget *widget, char *name, int wide, int bold,
|
||||
int shadowoffset, int shadowalways);
|
||||
void unifont_destroy(unifont *font);
|
||||
void unifont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
|
||||
int x, int y, const char *string, int len,
|
||||
int wide, int bold);
|
||||
int wide, int bold, int cellwidth);
|
||||
|
||||
#endif /* PUTTY_GTKFONT_H */
|
||||
|
|
|
@ -1455,7 +1455,7 @@ void palette_reset(void *frontend)
|
|||
/* Since Default Background may have changed, ensure that space
|
||||
* between text area and window border is refreshed. */
|
||||
set_window_background(inst);
|
||||
if (inst->area) {
|
||||
if (inst->area && inst->area->window) {
|
||||
draw_backing_rect(inst);
|
||||
gtk_widget_queue_draw(inst->area);
|
||||
}
|
||||
|
@ -2026,7 +2026,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
|
|||
unifont_draw_text(inst->pixmap, gc, inst->fonts[fontid],
|
||||
x*inst->font_width+inst->cfg.window_border,
|
||||
y*inst->font_height+inst->cfg.window_border+inst->fonts[0]->ascent,
|
||||
gcs, mblen, widefactor > 1, bold);
|
||||
gcs, mblen, widefactor > 1, bold, inst->font_width);
|
||||
}
|
||||
|
||||
sfree(gcs);
|
||||
|
@ -2618,7 +2618,8 @@ void setup_fonts_ucs(struct gui_data *inst)
|
|||
if (inst->fonts[3])
|
||||
unifont_destroy(inst->fonts[3]);
|
||||
|
||||
inst->fonts[0] = unifont_create(inst->cfg.font.name, FALSE, FALSE,
|
||||
inst->fonts[0] = unifont_create(inst->area, inst->cfg.font.name,
|
||||
FALSE, FALSE,
|
||||
inst->cfg.shadowboldoffset,
|
||||
inst->cfg.shadowbold);
|
||||
if (!inst->fonts[0]) {
|
||||
|
@ -2630,7 +2631,8 @@ void setup_fonts_ucs(struct gui_data *inst)
|
|||
if (inst->cfg.shadowbold || !inst->cfg.boldfont.name[0]) {
|
||||
inst->fonts[1] = NULL;
|
||||
} else {
|
||||
inst->fonts[1] = unifont_create(inst->cfg.boldfont.name, FALSE, TRUE,
|
||||
inst->fonts[1] = unifont_create(inst->area, inst->cfg.boldfont.name,
|
||||
FALSE, TRUE,
|
||||
inst->cfg.shadowboldoffset,
|
||||
inst->cfg.shadowbold);
|
||||
if (!inst->fonts[1]) {
|
||||
|
@ -2641,7 +2643,8 @@ void setup_fonts_ucs(struct gui_data *inst)
|
|||
}
|
||||
|
||||
if (inst->cfg.widefont.name[0]) {
|
||||
inst->fonts[2] = unifont_create(inst->cfg.widefont.name, TRUE, FALSE,
|
||||
inst->fonts[2] = unifont_create(inst->area, inst->cfg.widefont.name,
|
||||
TRUE, FALSE,
|
||||
inst->cfg.shadowboldoffset,
|
||||
inst->cfg.shadowbold);
|
||||
if (!inst->fonts[2]) {
|
||||
|
@ -2656,7 +2659,8 @@ void setup_fonts_ucs(struct gui_data *inst)
|
|||
if (inst->cfg.shadowbold || !inst->cfg.wideboldfont.name[0]) {
|
||||
inst->fonts[3] = NULL;
|
||||
} else {
|
||||
inst->fonts[3] = unifont_create(inst->cfg.wideboldfont.name, TRUE,
|
||||
inst->fonts[3] = unifont_create(inst->area,
|
||||
inst->cfg.wideboldfont.name, TRUE,
|
||||
TRUE, inst->cfg.shadowboldoffset,
|
||||
inst->cfg.shadowbold);
|
||||
if (!inst->fonts[3]) {
|
||||
|
@ -3320,6 +3324,8 @@ int pt_main(int argc, char **argv)
|
|||
if (!utf8_string_atom)
|
||||
utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE);
|
||||
|
||||
inst->area = gtk_drawing_area_new();
|
||||
|
||||
setup_fonts_ucs(inst);
|
||||
init_cutbuffers();
|
||||
|
||||
|
@ -3333,7 +3339,6 @@ int pt_main(int argc, char **argv)
|
|||
inst->width = inst->cfg.width;
|
||||
inst->height = inst->cfg.height;
|
||||
|
||||
inst->area = gtk_drawing_area_new();
|
||||
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area),
|
||||
inst->font_width * inst->cfg.width + 2*inst->cfg.window_border,
|
||||
inst->font_height * inst->cfg.height + 2*inst->cfg.window_border);
|
||||
|
|
Загрузка…
Ссылка в новой задаче