579 lines
11 KiB
C++
579 lines
11 KiB
C++
|
/***************************************************************************
|
||
|
|
||
|
gfont.cpp
|
||
|
|
||
|
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
|
||
|
|
||
|
Gtkmae "GTK+ made easy" classes
|
||
|
|
||
|
Realizado para la Junta de Extremadura.
|
||
|
Consejería de Educación Ciencia y Tecnología.
|
||
|
Proyecto gnuLinEx
|
||
|
|
||
|
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 1, 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, write to the Free Software
|
||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "widgets.h"
|
||
|
#include "font-parser.h"
|
||
|
#include "gdesktop.h"
|
||
|
#include "gb.form.font.h"
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
static void set_font_from_string(gFont *font, const char *str)
|
||
|
{
|
||
|
gchar **tokens, **p;
|
||
|
gchar *elt;
|
||
|
int grade;
|
||
|
double size;
|
||
|
|
||
|
font->setBold(false);
|
||
|
font->setItalic(false);
|
||
|
font->setUnderline(false);
|
||
|
font->setStrikeOut(false);
|
||
|
font->setName(gDesktop::font()->name());
|
||
|
font->setSize(gDesktop::font()->size());
|
||
|
|
||
|
if (!str || !*str)
|
||
|
return;
|
||
|
|
||
|
tokens = g_strsplit(str, ",", 0);
|
||
|
|
||
|
p = tokens;
|
||
|
for(p = tokens; *p; p++)
|
||
|
{
|
||
|
elt = *p;
|
||
|
|
||
|
if (!strcasecmp(elt, "bold"))
|
||
|
font->setBold(true);
|
||
|
else if (!strcasecmp(elt, "italic"))
|
||
|
font->setItalic(true);
|
||
|
else if (!strcasecmp(elt, "underline"))
|
||
|
font->setUnderline(true);
|
||
|
else if (!strcasecmp(elt, "strikeout"))
|
||
|
font->setStrikeOut(true);
|
||
|
else if (elt[0] == '+' || elt[0] == '-' || elt[0] == '0')
|
||
|
{
|
||
|
grade = atoi(elt);
|
||
|
if (grade || elt[0] == '0')
|
||
|
font->setGrade(grade);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
size = atof(elt);
|
||
|
if (size != 0.0)
|
||
|
font->setSize(size);
|
||
|
else
|
||
|
font->setName(elt);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
g_strfreev(tokens);
|
||
|
}
|
||
|
|
||
|
|
||
|
/********************************************************************************
|
||
|
|
||
|
gFont
|
||
|
|
||
|
*********************************************************************************/
|
||
|
static int FONT_n_families;
|
||
|
GList *FONT_families = NULL;
|
||
|
|
||
|
static int _nfont = 0;
|
||
|
|
||
|
void gFont::init()
|
||
|
{
|
||
|
PangoFontFamily **_families;
|
||
|
PangoContext *ct;
|
||
|
char *buf1,*buf2;
|
||
|
int bucle;
|
||
|
|
||
|
ct=gdk_pango_context_get();
|
||
|
pango_context_list_families(ct, &_families, &FONT_n_families);
|
||
|
|
||
|
for (bucle=0;bucle<FONT_n_families;bucle++)
|
||
|
{
|
||
|
buf1=(char*)pango_font_family_get_name (_families[bucle]);
|
||
|
if (buf1){
|
||
|
buf2=(char*)g_malloc(sizeof(char)*(strlen(buf1)+1));
|
||
|
strcpy(buf2,buf1);
|
||
|
FONT_families=g_list_prepend (FONT_families,buf2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FONT_families) FONT_families=g_list_sort(FONT_families,(GCompareFunc)strcasecmp);
|
||
|
|
||
|
g_free(_families);
|
||
|
g_object_unref(G_OBJECT(ct));
|
||
|
}
|
||
|
|
||
|
void gFont::exit()
|
||
|
{
|
||
|
GList *iter;
|
||
|
|
||
|
iter=FONT_families;
|
||
|
|
||
|
if (iter)
|
||
|
{
|
||
|
iter=g_list_first(iter);
|
||
|
while (iter)
|
||
|
{
|
||
|
g_free(iter->data);
|
||
|
iter=iter->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FONT_families) g_list_free(FONT_families);
|
||
|
|
||
|
//if (_nfont)
|
||
|
// fprintf(stderr, "WARNING: %d gFont objects were not freed.\n", _nfont);
|
||
|
}
|
||
|
|
||
|
long gFont::count()
|
||
|
{
|
||
|
if (!FONT_families) gFont::init();
|
||
|
return FONT_n_families;
|
||
|
}
|
||
|
|
||
|
const char *gFont::familyItem(long pos)
|
||
|
{
|
||
|
if (!FONT_families) gFont::init();
|
||
|
if ( (pos<0) || (pos>=FONT_n_families) ) return NULL;
|
||
|
|
||
|
return (const char*)g_list_nth (FONT_families,pos)->data;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
void gFont::updateWidget()
|
||
|
{
|
||
|
if (!wid) return;
|
||
|
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
gtk_widget_modify_font(wid,desc);
|
||
|
|
||
|
if (G_OBJECT_TYPE(wid)==GTK_TYPE_LABEL)
|
||
|
{
|
||
|
PangoAttrList *pal=pango_attr_list_new();
|
||
|
if (strike)
|
||
|
{
|
||
|
PangoAttribute *pa=pango_attr_strikethrough_new(true);
|
||
|
pa->start_index = 0;
|
||
|
pa->end_index = g_utf8_strlen(gtk_label_get_text(GTK_LABEL(wid)), -1);
|
||
|
pango_attr_list_insert(pal, pa);
|
||
|
}
|
||
|
if (uline)
|
||
|
{
|
||
|
PangoAttribute *pa=pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
|
||
|
pa->start_index = 0;
|
||
|
pa->end_index = g_utf8_strlen(gtk_label_get_text(GTK_LABEL(wid)), -1);
|
||
|
pango_attr_list_insert(pal, pa);
|
||
|
}
|
||
|
gtk_label_set_attributes(GTK_LABEL(wid), pal);
|
||
|
pango_attr_list_unref(pal);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void gFont::realize()
|
||
|
{
|
||
|
gShare::gShare();
|
||
|
strike=false;
|
||
|
uline=false;
|
||
|
_nfont++;
|
||
|
//fprintf(stderr, "new gFont() %p\n", this);
|
||
|
}
|
||
|
|
||
|
gFont::gFont(GtkWidget *wid)
|
||
|
{
|
||
|
PangoAttrList *lst;
|
||
|
PangoAttrIterator* iter;
|
||
|
|
||
|
realize();
|
||
|
ct=gtk_widget_create_pango_context(wid);
|
||
|
g_object_ref(ct);
|
||
|
|
||
|
|
||
|
if (G_OBJECT_TYPE(wid)==GTK_TYPE_LABEL)
|
||
|
{
|
||
|
lst=gtk_label_get_attributes(GTK_LABEL(wid));
|
||
|
if (lst)
|
||
|
{
|
||
|
iter=pango_attr_list_get_iterator(lst);
|
||
|
if (pango_attr_iterator_get(iter,PANGO_ATTR_STRIKETHROUGH)) strike=true;
|
||
|
if (pango_attr_iterator_get(iter,PANGO_ATTR_UNDERLINE)) uline=true;
|
||
|
pango_attr_iterator_destroy(iter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
gFont::gFont()
|
||
|
{
|
||
|
GtkStyle *sty=gtk_widget_get_default_style();
|
||
|
|
||
|
realize();
|
||
|
ct=gdk_pango_context_get();
|
||
|
pango_context_set_font_description(ct,sty->font_desc);
|
||
|
}
|
||
|
|
||
|
gFont::gFont(PangoFontDescription *fd)
|
||
|
{
|
||
|
//GtkStyle *sty=gtk_widget_get_default_style();
|
||
|
|
||
|
realize();
|
||
|
ct=gdk_pango_context_get();
|
||
|
pango_context_set_font_description(ct, fd);
|
||
|
}
|
||
|
|
||
|
gFont::gFont(const char *name)
|
||
|
{
|
||
|
GtkStyle *sty=gtk_widget_get_default_style();
|
||
|
|
||
|
realize();
|
||
|
ct=gdk_pango_context_get();
|
||
|
pango_context_set_font_description(ct,sty->font_desc);
|
||
|
|
||
|
set_font_from_string(this, name);
|
||
|
}
|
||
|
|
||
|
gFont *gFont::copy()
|
||
|
{
|
||
|
gFont *f = new gFont();
|
||
|
|
||
|
f->setName(name());
|
||
|
f->setSize(size());
|
||
|
f->setBold(bold());
|
||
|
f->setItalic(italic());
|
||
|
f->setUnderline(underline());
|
||
|
f->setStrikeOut(strikeOut());
|
||
|
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
gFont::~gFont()
|
||
|
{
|
||
|
g_object_unref(ct);
|
||
|
_nfont--;
|
||
|
//fprintf(stderr, "delete gFont() %p\n", this);
|
||
|
}
|
||
|
|
||
|
|
||
|
long gFont::ascent()
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
PangoFontMetrics *metric=pango_context_get_metrics(ct,desc,NULL);
|
||
|
long mt;
|
||
|
|
||
|
mt=pango_font_metrics_get_ascent(metric)/PANGO_SCALE;
|
||
|
|
||
|
return mt;
|
||
|
}
|
||
|
|
||
|
long gFont::descent()
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
PangoFontMetrics *metric=pango_context_get_metrics(ct,desc,NULL);
|
||
|
long mt;
|
||
|
|
||
|
mt=pango_font_metrics_get_descent(metric)/PANGO_SCALE;
|
||
|
|
||
|
return mt;
|
||
|
}
|
||
|
|
||
|
bool gFont::bold()
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
PangoWeight w;
|
||
|
|
||
|
w=pango_font_description_get_weight(desc);
|
||
|
if (w>PANGO_WEIGHT_NORMAL) return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void gFont::setBold(bool vl)
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
if (vl)
|
||
|
pango_font_description_set_weight(desc,PANGO_WEIGHT_BOLD);
|
||
|
else
|
||
|
pango_font_description_set_weight(desc,PANGO_WEIGHT_NORMAL);
|
||
|
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
bool gFont::italic()
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
if (pango_font_description_get_style(desc)==PANGO_STYLE_NORMAL) return false;
|
||
|
return true;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void gFont::setItalic(bool vl)
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
if (vl)
|
||
|
pango_font_description_set_style(desc,PANGO_STYLE_ITALIC);
|
||
|
else
|
||
|
pango_font_description_set_style(desc,PANGO_STYLE_NORMAL);
|
||
|
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
char* gFont::name()
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
return (char *)pango_font_description_get_family (desc);
|
||
|
|
||
|
}
|
||
|
|
||
|
void gFont::setName(char *nm)
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
pango_font_description_set_family (desc,nm);
|
||
|
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
double gFont::size()
|
||
|
{
|
||
|
double size;
|
||
|
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
size=pango_font_description_get_size(desc);
|
||
|
return size / (double)PANGO_SCALE;
|
||
|
}
|
||
|
|
||
|
int gFont::grade()
|
||
|
{
|
||
|
double desktop = gDesktop::font()->size();
|
||
|
return SIZE_TO_GRADE(size(), desktop);
|
||
|
}
|
||
|
|
||
|
void gFont::setSize(double sz)
|
||
|
{
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
|
||
|
pango_font_description_set_size (desc,(int)(sz*PANGO_SCALE));
|
||
|
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
void gFont::setGrade(int grade)
|
||
|
{
|
||
|
double desktop = gDesktop::font()->size();
|
||
|
|
||
|
if (grade < -4 || grade > 16)
|
||
|
return;
|
||
|
|
||
|
setSize(GRADE_TO_SIZE(grade, desktop));
|
||
|
}
|
||
|
|
||
|
const char *gFont::toString()
|
||
|
{
|
||
|
//PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
//return pango_font_description_to_string(desc);
|
||
|
|
||
|
GString *desc = g_string_new(name());
|
||
|
char *ret;
|
||
|
|
||
|
g_string_append_printf(desc, ",%g", (double)((int)(size() * 10 + 0.5)) / 10);
|
||
|
if (bold())
|
||
|
g_string_append(desc, ",Bold");
|
||
|
if (italic())
|
||
|
g_string_append(desc, ",Italic");
|
||
|
if (underline())
|
||
|
g_string_append(desc, ",Underline");
|
||
|
if (strikeOut())
|
||
|
g_string_append(desc, ",StrikeOut");
|
||
|
|
||
|
ret = g_string_free(desc, false);
|
||
|
gt_free_later(ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int gFont::width(const char *text, int len)
|
||
|
{
|
||
|
PangoLayout *ly;
|
||
|
int w;
|
||
|
|
||
|
if (!text) return 0;
|
||
|
if (!strlen(text)) return 0;
|
||
|
|
||
|
ly=pango_layout_new(ct);
|
||
|
pango_layout_set_text(ly,text,len);
|
||
|
pango_layout_get_size(ly,&w,NULL);
|
||
|
g_object_unref(G_OBJECT(ly));
|
||
|
|
||
|
return w/PANGO_SCALE;
|
||
|
}
|
||
|
|
||
|
int gFont::height(const char *text, int len)
|
||
|
{
|
||
|
PangoLayout *ly;
|
||
|
int h;
|
||
|
|
||
|
if (!text || !*text) return 0;
|
||
|
|
||
|
ly=pango_layout_new(ct);
|
||
|
pango_layout_set_text(ly,text,len);
|
||
|
pango_layout_get_size(ly,NULL,&h);
|
||
|
g_object_unref(G_OBJECT(ly));
|
||
|
|
||
|
return h/PANGO_SCALE;
|
||
|
}
|
||
|
|
||
|
int gFont::height()
|
||
|
{
|
||
|
return height(" ", 1);
|
||
|
}
|
||
|
|
||
|
bool gFont::scalable()
|
||
|
{
|
||
|
bool ret=false;
|
||
|
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
//PangoFontDescription *tmp;
|
||
|
const char* name=pango_font_description_get_family(desc);
|
||
|
PangoFontFamily **families;
|
||
|
PangoFontFace **faces;
|
||
|
int *sizes;
|
||
|
int n_families;
|
||
|
int n_faces;
|
||
|
int n_sizes;
|
||
|
//int b2;
|
||
|
const char *buf;
|
||
|
|
||
|
if (!name) return false;
|
||
|
|
||
|
pango_context_list_families(ct,&families,&n_families);
|
||
|
|
||
|
if (!families) return false;
|
||
|
|
||
|
for (int bucle=0;bucle<n_families;bucle++)
|
||
|
{
|
||
|
buf=pango_font_family_get_name(families[bucle]);
|
||
|
if (!strcmp(buf,name))
|
||
|
{
|
||
|
pango_font_family_list_faces(families[bucle],&faces,&n_faces);
|
||
|
if (faces)
|
||
|
{
|
||
|
pango_font_face_list_sizes(faces[0],&sizes,&n_sizes);
|
||
|
if (sizes)
|
||
|
g_free(sizes);
|
||
|
else
|
||
|
ret=true;
|
||
|
g_free(faces);
|
||
|
g_free(families);
|
||
|
return ret;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
g_free(families);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
g_free(families);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool gFont::fixed()
|
||
|
{
|
||
|
bool ret=false;
|
||
|
|
||
|
PangoFontDescription *desc=pango_context_get_font_description(ct);
|
||
|
const char* name=pango_font_description_get_family(desc);
|
||
|
PangoFontFamily **families;
|
||
|
int n_families;
|
||
|
const char *buf;
|
||
|
|
||
|
if (!name) return false;
|
||
|
|
||
|
pango_context_list_families(ct,&families,&n_families);
|
||
|
|
||
|
if (!families) return false;
|
||
|
|
||
|
for (int bucle=0;bucle<n_families;bucle++)
|
||
|
{
|
||
|
buf=pango_font_family_get_name(families[bucle]);
|
||
|
if (!strcmp(buf,name))
|
||
|
{
|
||
|
ret=pango_font_family_is_monospace (families[bucle]);
|
||
|
g_free(families);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
g_free(families);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
char** gFont::styles()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
long gFont::resolution()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool gFont::strikeOut()
|
||
|
{
|
||
|
return strike;
|
||
|
}
|
||
|
|
||
|
bool gFont::underline()
|
||
|
{
|
||
|
return uline;
|
||
|
}
|
||
|
|
||
|
|
||
|
void gFont::setResolution(long vl)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void gFont::setStrikeOut(bool vl)
|
||
|
{
|
||
|
//stub("setStrikeOut(): partially working");
|
||
|
strike=vl;
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
void gFont::setUnderline(bool vl)
|
||
|
{
|
||
|
//stub("setUnderline(): partially working");
|
||
|
uline=vl;
|
||
|
//updateWidget();
|
||
|
}
|
||
|
|
||
|
|
||
|
|