Fl_Cairo_Graphics_Driver: simpler way to construct the PangoLayout object.

This commit is contained in:
ManoloFLTK 2022-07-18 22:58:02 +02:00
parent 3560ff450f
commit 536c32ee99
3 changed files with 40 additions and 48 deletions

View File

@ -25,12 +25,13 @@
#include <cairo/cairo.h>
typedef struct _PangoLayout PangoLayout;
typedef struct _PangoContext PangoContext;
typedef struct _PangoFontDescription PangoFontDescription;
class Fl_Cairo_Font_Descriptor : public Fl_Font_Descriptor {
public:
Fl_Cairo_Font_Descriptor(const char* fontname, Fl_Fontsize size);
Fl_Cairo_Font_Descriptor(const char* fontname, Fl_Fontsize size, PangoContext *context);
FL_EXPORT ~Fl_Cairo_Font_Descriptor();
PangoFontDescription *fontref;
int **width; // array of arrays of character widths
@ -42,12 +43,12 @@ class FL_EXPORT Fl_Cairo_Graphics_Driver : public Fl_Graphics_Driver {
private:
bool *needs_commit_tag_; // NULL or points to whether cairo surface was drawn to
cairo_t *dummy_cairo_; // used to measure text width before showing a window
cairo_t *pango_layout_cairo_;
PangoLayout *pango_layout_;
int linestyle_;
int width_unscaled_(unsigned int c);
protected:
cairo_t *cairo_;
PangoContext *pango_context_;
PangoLayout *pango_layout_;
public:
Fl_Cairo_Graphics_Driver();
virtual ~Fl_Cairo_Graphics_Driver();

View File

@ -69,7 +69,7 @@ static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver() : Fl_Graphics_Driver() {
cairo_ = NULL;
pango_layout_ = NULL;
pango_layout_cairo_ = NULL;
pango_context_ = NULL;
dummy_cairo_ = NULL;
linestyle_ = FL_SOLID;
clip_ = NULL;
@ -81,6 +81,7 @@ Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver() : Fl_Graphics_Driver() {
Fl_Cairo_Graphics_Driver::~Fl_Cairo_Graphics_Driver() {
if (pango_layout_) g_object_unref(pango_layout_);
if (pango_context_) g_object_unref(pango_context_);
}
const cairo_format_t Fl_Cairo_Graphics_Driver::cairo_format = CAIRO_FORMAT_ARGB32;
@ -88,8 +89,6 @@ const cairo_format_t Fl_Cairo_Graphics_Driver::cairo_format = CAIRO_FORMAT_ARGB3
void Fl_Cairo_Graphics_Driver::set_cairo(cairo_t *cr, float s) {
if (dummy_cairo_) {
g_object_unref(pango_layout_);
pango_layout_ = NULL;
cairo_destroy(dummy_cairo_);
dummy_cairo_ = NULL;
}
@ -1070,22 +1069,20 @@ int Fl_Cairo_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
}
Fl_Cairo_Font_Descriptor::Fl_Cairo_Font_Descriptor(const char* name, Fl_Fontsize size) : Fl_Font_Descriptor(name, size) {
char string[70];
Fl_Cairo_Font_Descriptor::Fl_Cairo_Font_Descriptor(const char* name, Fl_Fontsize size,
PangoContext *context) :
Fl_Font_Descriptor(name, size) {
char *string = new char[strlen(name) + 10];
strcpy(string, name);
// The factor of 0.75 below gives cairo-produced text the same size as
// Xft-produced text for the same FLTK font size.
sprintf(string + strlen(string), " %d", int(size * 0.75 + 0.5) );
//A PangoFontDescription describes a font in an implementation-independent manner.
fontref = pango_font_description_from_string(string);
delete[] string;
width = NULL;
//A PangoFontMap represents the set of fonts available for a particular rendering system.
static PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10
//A PangoContext stores global information used to control the itemization process.
static PangoContext *pango_context = pango_font_map_create_context(def_font_map); // 1.22
static PangoLanguage *language = pango_language_get_default(); // 1.16
//A PangoFontset represents a set of PangoFont to use when rendering text.
PangoFontset *fontset = pango_font_map_load_fontset(def_font_map, pango_context, fontref, language);
PangoFontset *fontset = pango_font_map_load_fontset(pango_cairo_font_map_get_default(), context, fontref, pango_language_get_default());
PangoFontMetrics *metrics = pango_fontset_get_metrics(fontset);
ascent = pango_font_metrics_get_ascent(metrics);
descent = pango_font_metrics_get_descent(metrics);
@ -1109,13 +1106,13 @@ Fl_Cairo_Font_Descriptor::~Fl_Cairo_Font_Descriptor() {
}
static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, PangoContext *context) {
Fl_Fontdesc* s = fl_fonts+fnum;
if (!s->name) s = fl_fonts; // use 0 if fnum undefined
Fl_Font_Descriptor* f;
for (f = s->first; f; f = f->next)
if (f->size == size) return f;
f = new Fl_Cairo_Font_Descriptor(s->name, size);
f = new Fl_Cairo_Font_Descriptor(s->name, size, context);
f->next = s->first;
s->first = f;
return f;
@ -1123,45 +1120,34 @@ static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
/* Implementation note :
* The pango_layout_ object is created relatively to the unscaled cairo context (scale() == 1).
* Therefore, the cairo context is unscaled before calling pango_cairo_create_layout(),
* pango_cairo_show_layout(), and pango_cairo_update_layout().
* This way, the pixel width of a drawn string equals the sum of the widths of its
* The pixel width of a drawn string equals the sum of the widths of its
* characters, except when kerning occurs.
*/
void Fl_Cairo_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize s) {
if (!font_descriptor()) fl_open_display();
if (!pango_layout_) {
bool needs_dummy = (cairo_ == NULL);
if (!cairo_) {
cairo_surface_t *surf = cairo_image_surface_create(Fl_Cairo_Graphics_Driver::cairo_format, 100, 100);
cairo_ = cairo_create(surf);
cairo_surface_destroy(surf);
}
cairo_save(cairo_);
double f = scale(); cairo_scale(cairo_, 1/f, 1/f);
pango_layout_ = pango_cairo_create_layout(cairo_); // 1.10
cairo_restore(cairo_);
pango_layout_cairo_ = cairo_;
if (needs_dummy) {
dummy_cairo_ = cairo_;
}
} else if (pango_layout_cairo_ != cairo_) {
cairo_save(cairo_);
double f = scale(); cairo_scale(cairo_, 1/f, 1/f);
pango_cairo_update_layout(cairo_, pango_layout_);
cairo_restore(cairo_);
pango_layout_cairo_ = cairo_;
if (!cairo_) {
cairo_surface_t *surf = cairo_image_surface_create(Fl_Cairo_Graphics_Driver::cairo_format, 100, 100);
cairo_ = cairo_create(surf);
cairo_surface_destroy(surf);
dummy_cairo_ = cairo_;
}
if (s == 0) return;
if (font() == fnum && size() == s) return;
if (fnum == -1) {
Fl_Graphics_Driver::font(0, 0);
return;
}
Fl_Graphics_Driver::font(fnum, s);
font_descriptor( find(fnum, int(s * scale() + 0.5)) );
pango_layout_set_font_description(pango_layout_, ((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref);
if (!pango_context_) {
//A PangoFontMap represents the set of fonts available for a particular rendering system.
PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10
//A PangoContext stores global information used to control the itemization process.
pango_context_ = pango_font_map_create_context(def_font_map); // 1.22
pango_layout_ = pango_layout_new(pango_context_);
}
font_descriptor( find(fnum, int(s * scale() + 0.5), pango_context_) );
//If no font description is set on the layout, the font description from the layouts context is used.
pango_context_set_font_description(pango_context_,
((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref);
}

View File

@ -1506,18 +1506,23 @@ int Fl_PostScript_Graphics_Driver::start_eps(int width, int height) {
void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
if (!n) return;
if (!pango_context_) {
PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10
pango_context_ = pango_font_map_create_context(def_font_map); // 1.22
pango_layout_ = pango_layout_new(pango_context_);
}
PangoFontDescription *pfd = Fl_Graphics_Driver::default_driver().pango_font_description(font());
pango_layout_set_font_description(pango_layout(), pfd);
pango_layout_set_font_description(pango_layout_, pfd);
int pwidth, pheight;
cairo_save(cairo_);
pango_layout_set_text(pango_layout(), str, n);
pango_layout_get_size(pango_layout(), &pwidth, &pheight);
pango_layout_set_text(pango_layout_, str, n);
pango_layout_get_size(pango_layout_, &pwidth, &pheight);
if (pwidth > 0) {
double s = width(str, n);
cairo_translate(cairo_, x, y - height() + descent());
s = (s/pwidth) * PANGO_SCALE;
cairo_scale(cairo_, s, s);
pango_cairo_show_layout(cairo_, pango_layout());
pango_cairo_show_layout(cairo_, pango_layout_);
}
cairo_restore(cairo_);
check_status();