Complete class Fl_Cairo_Graphics_Driver using Fl_Wayland_Graphics_Driver
This commit is contained in:
parent
272bc2560c
commit
f8db18597a
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Support for Cairo graphics for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2021 by Bill Spitzak and others.
|
||||
// Copyright 2021-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -22,16 +22,28 @@
|
||||
# define FL_CAIRO_GRAPHICS_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
typedef struct _cairo cairo_t;
|
||||
typedef struct _PangoLayout PangoLayout;
|
||||
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_EXPORT ~Fl_Cairo_Font_Descriptor();
|
||||
PangoFontDescription *fontref;
|
||||
int **width; // array of arrays of character widths
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
protected:
|
||||
cairo_t *cairo_;
|
||||
PangoLayout *pango_layout_;
|
||||
void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
int linestyle_;
|
||||
public:
|
||||
Fl_Cairo_Graphics_Driver();
|
||||
virtual ~Fl_Cairo_Graphics_Driver();
|
||||
@ -63,8 +75,12 @@ public:
|
||||
float angle;
|
||||
int left_margin;
|
||||
int top_margin;
|
||||
static const cairo_format_t cairo_format;
|
||||
|
||||
void transformed_draw(const char* s, int n, double x, double y); //precise text placing
|
||||
void surface_needs_commit() {
|
||||
if (needs_commit_tag_) *needs_commit_tag_ = true;
|
||||
}
|
||||
void needs_commit_tag(bool *tag) { needs_commit_tag_ = tag; }
|
||||
|
||||
// implementation of drawing methods
|
||||
void color(Fl_Color c);
|
||||
@ -95,6 +111,11 @@ public:
|
||||
void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void point(int x, int y);
|
||||
void overlay_rect(int x, int y, int w , int h);
|
||||
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
|
||||
void restore_clip();
|
||||
int not_clipped(int x, int y, int w, int h);
|
||||
|
||||
void begin_points();
|
||||
void begin_line();
|
||||
@ -118,20 +139,40 @@ public:
|
||||
void draw_image_mono(const uchar* d, int x,int y,int w,int h, int delta=1, int ld=0);
|
||||
void draw_image(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=3);
|
||||
void draw_image_mono(Fl_Draw_Image_Cb call, void* data, int x,int y, int w, int h, int delta=1);
|
||||
|
||||
void draw(const char* s, int nBytes, int x, int y) { transformed_draw(s,nBytes,x,y); }
|
||||
void draw(const char* s, int nBytes, float x, float y) { transformed_draw(s,nBytes,x,y); }
|
||||
void draw(int angle, const char *str, int n, int x, int y);
|
||||
void rtl_draw(const char* s, int n, int x, int y);
|
||||
void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// ---
|
||||
Fl_Bitmask create_bitmask(int /*w*/, int /*h*/, const uchar */*array*/) { return 0L; }
|
||||
|
||||
void ps_origin(int x, int y);
|
||||
void ps_translate(int, int);
|
||||
void ps_untranslate();
|
||||
|
||||
void draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy);
|
||||
void draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD);
|
||||
void draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void cache(Fl_RGB_Image *rgb);
|
||||
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
|
||||
void draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void cache(Fl_Bitmap *img);
|
||||
void delete_bitmask(Fl_Bitmask bm);
|
||||
void cache(Fl_Pixmap *pxm);
|
||||
void draw_pixmap(Fl_Pixmap *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void uncache_pixmap(fl_uintptr_t p);
|
||||
|
||||
void font(Fl_Font fnum, Fl_Fontsize s);
|
||||
Fl_Font font() { return Fl_Graphics_Driver::font(); }
|
||||
void draw(const char* s, int nBytes, int x, int y) { draw(s, nBytes, float(x), float(y)); }
|
||||
void draw(const char* s, int nBytes, float x, float y);
|
||||
void draw(int angle, const char *str, int n, int x, int y);
|
||||
void rtl_draw(const char* str, int n, int x, int y);
|
||||
int height();
|
||||
int descent();
|
||||
double width(const char *str, int n);
|
||||
double width(unsigned c);
|
||||
void text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h);
|
||||
virtual PangoFontDescription* pango_font_description(Fl_Font /*fnum*/) {
|
||||
return ((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // FL_CAIRO_GRAPHICS_DRIVER_H
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Support for Cairo graphics for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2021 by Bill Spitzak and others.
|
||||
// Copyright 2021-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -29,6 +29,7 @@
|
||||
#include <stdlib.h> // abs(int)
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
|
||||
// duplicated from Fl_PostScript.cxx
|
||||
struct callback_data {
|
||||
const uchar *data;
|
||||
@ -71,21 +72,26 @@ Fl_Cairo_Graphics_Driver::Fl_Cairo_Graphics_Driver() : Fl_Graphics_Driver() {
|
||||
scale_x = scale_y = 1;
|
||||
angle = 0;
|
||||
left_margin = top_margin = 0;
|
||||
needs_commit_tag_ = NULL;
|
||||
}
|
||||
|
||||
Fl_Cairo_Graphics_Driver::~Fl_Cairo_Graphics_Driver() {}
|
||||
|
||||
const cairo_format_t Fl_Cairo_Graphics_Driver::cairo_format = CAIRO_FORMAT_ARGB32;
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::rectf(int x, int y, int w, int h) {
|
||||
cairo_rectangle(cairo_, x-0.5, y-0.5, w, h);
|
||||
cairo_fill(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::rect(int x, int y, int w, int h) {
|
||||
cairo_rectangle(cairo_, x, y, w-1, h-1);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
|
||||
@ -93,6 +99,7 @@ void Fl_Cairo_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
|
||||
cairo_move_to(cairo_, x1, y1);
|
||||
cairo_line_to(cairo_, x2, y2);
|
||||
cairo_stroke(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
@ -101,6 +108,7 @@ void Fl_Cairo_Graphics_Driver::line(int x0, int y0, int x1, int y1, int x2, int
|
||||
cairo_line_to(cairo_, x1, y1);
|
||||
cairo_line_to(cairo_, x2, y2);
|
||||
cairo_stroke(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1) {
|
||||
@ -108,6 +116,7 @@ void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1) {
|
||||
cairo_line_to(cairo_, x1, y);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
|
||||
@ -116,6 +125,7 @@ void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
|
||||
cairo_line_to(cairo_, x1, y2);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
|
||||
@ -125,6 +135,7 @@ void Fl_Cairo_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
|
||||
cairo_line_to(cairo_, x3, y2);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1) {
|
||||
@ -132,6 +143,7 @@ void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1) {
|
||||
cairo_line_to(cairo_, x, y1);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
|
||||
@ -140,6 +152,7 @@ void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
|
||||
cairo_line_to(cairo_, x2, y1);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
|
||||
@ -149,6 +162,7 @@ void Fl_Cairo_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
|
||||
cairo_line_to(cairo_, x2, y3);
|
||||
cairo_stroke(cairo_);
|
||||
check_status();
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
@ -160,6 +174,7 @@ void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int
|
||||
cairo_close_path(cairo_);
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
@ -172,7 +187,7 @@ void Fl_Cairo_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int
|
||||
cairo_close_path(cairo_);
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
@ -184,6 +199,7 @@ void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, i
|
||||
cairo_close_path(cairo_);
|
||||
cairo_fill(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
@ -196,9 +212,11 @@ void Fl_Cairo_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, i
|
||||
cairo_close_path(cairo_);
|
||||
cairo_fill(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::line_style(int style, int width, char* dashes) {
|
||||
linestyle_ = style;
|
||||
if(dashes){
|
||||
if(dashes != linedash_)
|
||||
strcpy(linedash_,dashes);
|
||||
@ -275,37 +293,6 @@ void Fl_Cairo_Graphics_Driver::color(Fl_Color c) {
|
||||
|
||||
Fl_Color Fl_Cairo_Graphics_Driver::color() { return Fl_Graphics_Driver::color(); }
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y)
|
||||
{
|
||||
cairo_save(cairo_);
|
||||
cairo_translate(cairo_, x, y);
|
||||
cairo_rotate(cairo_, -rotation * M_PI / 180);
|
||||
this->transformed_draw(str, n, 0, 0);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
|
||||
if (!n) return;
|
||||
pango_layout_set_font_description(pango_layout_, pango_font_description(Fl_Graphics_Driver::font()));
|
||||
int pwidth, pheight;
|
||||
cairo_save(cairo_);
|
||||
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_);
|
||||
}
|
||||
cairo_restore(cairo_);
|
||||
check_status();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
|
||||
int w = (int)width(str, n);
|
||||
transformed_draw(str, n, x - w, y);
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::concat(){
|
||||
cairo_matrix_t mat = {fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y};
|
||||
@ -354,31 +341,37 @@ void Fl_Cairo_Graphics_Driver::begin_polygon() {
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::vertex(double x, double y) {
|
||||
if(shape_==POINTS){
|
||||
if (shape_==POINTS){
|
||||
cairo_move_to(cairo_, x, y);
|
||||
gap_=1;
|
||||
return;
|
||||
}
|
||||
if(gap_){
|
||||
if (gap_){
|
||||
cairo_move_to(cairo_, x, y);
|
||||
gap_=0;
|
||||
}else
|
||||
} else {
|
||||
cairo_line_to(cairo_, x, y);
|
||||
surface_needs_commit();
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3)
|
||||
{
|
||||
if(shape_==NONE) return;
|
||||
if (shape_ == POINTS) Fl_Graphics_Driver::curve(x, y, x1, y1, x2, y2, x3, y3);
|
||||
else {
|
||||
if(gap_)
|
||||
cairo_move_to(cairo_, x, y);
|
||||
else
|
||||
cairo_line_to(cairo_, x, y);
|
||||
gap_=0;
|
||||
cairo_curve_to(cairo_, x1 , y1 , x2 , y2 , x3 , y3);
|
||||
}
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::circle(double x, double y, double r){
|
||||
if (shape_==NONE){
|
||||
if (shape_ == NONE){
|
||||
cairo_save(cairo_);
|
||||
concat();
|
||||
cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
|
||||
@ -386,6 +379,7 @@ void Fl_Cairo_Graphics_Driver::circle(double x, double y, double r){
|
||||
cairo_restore(cairo_);
|
||||
} else
|
||||
cairo_arc(cairo_, x, y, r, 0, 2*M_PI);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::arc(double x, double y, double r, double start, double a){
|
||||
@ -395,6 +389,7 @@ void Fl_Cairo_Graphics_Driver::arc(double x, double y, double r, double start, d
|
||||
cairo_arc(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
|
||||
else
|
||||
cairo_arc_negative(cairo_, x, y, r, -start*M_PI/180, -a*M_PI/180);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
|
||||
@ -408,6 +403,7 @@ void Fl_Cairo_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double
|
||||
cairo_translate(cairo_, -x - w/2.0 +0.5 , -y - h/2.0 +0.5);
|
||||
end_line();
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) {
|
||||
@ -419,6 +415,7 @@ void Fl_Cairo_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double
|
||||
arc(0.0,0.0, 1, a2, a1);
|
||||
end_polygon();
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::end_points() {
|
||||
@ -431,6 +428,7 @@ void Fl_Cairo_Graphics_Driver::end_line() {
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
shape_=NONE;
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::end_loop(){
|
||||
@ -440,6 +438,7 @@ void Fl_Cairo_Graphics_Driver::end_loop(){
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
shape_=NONE;
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::end_polygon() {
|
||||
@ -449,16 +448,24 @@ void Fl_Cairo_Graphics_Driver::end_polygon() {
|
||||
cairo_fill(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
shape_=NONE;
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::transformed_vertex(double x, double y) {
|
||||
reconcat();
|
||||
if (shape_ == POINTS){
|
||||
cairo_move_to(cairo_, x, y);
|
||||
point(x, y);
|
||||
gap_ = 1;
|
||||
} else {
|
||||
reconcat();
|
||||
if(gap_){
|
||||
cairo_move_to(cairo_, x, y);
|
||||
gap_=0;
|
||||
}else
|
||||
cairo_line_to(cairo_, x, y);
|
||||
surface_needs_commit();
|
||||
concat();
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::push_clip(int x, int y, int w, int h) {
|
||||
@ -538,6 +545,7 @@ void Fl_Cairo_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int
|
||||
rgb->alloc_array = 1;
|
||||
draw_rgb(rgb, ix, iy, iw, ih, 0, 0);
|
||||
delete rgb;
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD)
|
||||
@ -550,6 +558,7 @@ void Fl_Cairo_Graphics_Driver::draw_image_mono(const uchar *data, int ix, int iy
|
||||
cb_data.D = D;
|
||||
cb_data.LD = LD;
|
||||
draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D)
|
||||
@ -557,76 +566,260 @@ void Fl_Cairo_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void *data
|
||||
draw_image(call, data, ix, iy, iw, ih, D);
|
||||
}
|
||||
|
||||
static void destroy_BGRA(void *data) {
|
||||
|
||||
int Fl_Cairo_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
|
||||
if (!clip_) return 1;
|
||||
if (clip_->w < 0) return 1;
|
||||
int X = 0, Y = 0, W = 0, H = 0;
|
||||
clip_box(x, y, w, h, X, Y, W, H);
|
||||
if (W) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Cairo_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) {
|
||||
if (!clip_) {
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 0;
|
||||
}
|
||||
if (clip_->w < 0) {
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 1;
|
||||
}
|
||||
int ret = 0;
|
||||
if (x > (X=clip_->x)) {X=x; ret=1;}
|
||||
if (y > (Y=clip_->y)) {Y=y; ret=1;}
|
||||
if ((x+w) < (clip_->x+clip_->w)) {
|
||||
W=x+w-X;
|
||||
|
||||
ret=1;
|
||||
|
||||
}else
|
||||
W = clip_->x + clip_->w - X;
|
||||
if(W<0){
|
||||
W=0;
|
||||
return 1;
|
||||
}
|
||||
if ((y+h) < (clip_->y+clip_->h)) {
|
||||
H=y+h-Y;
|
||||
ret=1;
|
||||
}else
|
||||
H = clip_->y + clip_->h - Y;
|
||||
if(H<0){
|
||||
W=0;
|
||||
H=0;
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::restore_clip() {
|
||||
if (cairo_) cairo_reset_clip(cairo_);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::point(int x, int y) {
|
||||
rectf(x, y, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
|
||||
if (abs(D)<3){ //mono
|
||||
draw_image_mono(data, ix, iy, iw, ih, D, LD);
|
||||
return;
|
||||
}
|
||||
struct callback_data cb_data;
|
||||
if (!LD) LD = iw*abs(D);
|
||||
if (D<0) data += iw*abs(D);
|
||||
cb_data.data = data;
|
||||
cb_data.D = D;
|
||||
cb_data.LD = LD;
|
||||
Fl_Cairo_Graphics_Driver::draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
|
||||
cairo_save(cairo_);
|
||||
cairo_matrix_t mat;
|
||||
cairo_get_matrix(cairo_, &mat);
|
||||
float s = (float)mat.xx;
|
||||
cairo_matrix_init_identity(&mat);
|
||||
cairo_set_matrix(cairo_, &mat); // use drawing units
|
||||
int lwidth = s < 1 ? 1 : int(s);
|
||||
cairo_set_line_width(cairo_, lwidth);
|
||||
cairo_translate(cairo_, lwidth/2., lwidth/2.); // translate by half of line width
|
||||
double ddash = (lwidth > 2 ? lwidth : 2);
|
||||
if (linestyle_ == FL_DOT){
|
||||
cairo_set_dash(cairo_, &ddash, 1, 0); // dash size = line width
|
||||
}
|
||||
// rectangle in drawing units
|
||||
int Xs = Fl_Scalable_Graphics_Driver::floor(x, s);
|
||||
int Ws = Fl_Scalable_Graphics_Driver::floor(x+w-1, s) - Xs;
|
||||
int Ys = Fl_Scalable_Graphics_Driver::floor(y, s);
|
||||
int Hs = Fl_Scalable_Graphics_Driver::floor(y+h-1, s) - Ys;
|
||||
cairo_move_to(cairo_, Xs, Ys);
|
||||
cairo_line_to(cairo_, Xs+Ws, Ys);
|
||||
cairo_line_to(cairo_, Xs+Ws, Ys+Hs);
|
||||
cairo_line_to(cairo_, Xs, Ys+Hs);
|
||||
cairo_close_path(cairo_);
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy) {
|
||||
// compute size of output image in drawing units
|
||||
cairo_matrix_t matrix;
|
||||
cairo_get_matrix(cairo_, &matrix);
|
||||
float s = (float)matrix.xx;
|
||||
int Xs = Fl_Scalable_Graphics_Driver::floor(X - cx, s);
|
||||
int Ws = Fl_Scalable_Graphics_Driver::floor(X - cx + img->w(), s) - Xs ;
|
||||
int Ys = Fl_Scalable_Graphics_Driver::floor(Y - cy, s);
|
||||
int Hs = Fl_Scalable_Graphics_Driver::floor(Y - cy + img->h(), s) - Ys;
|
||||
if (Ws == 0 || Hs == 0) return;
|
||||
cairo_save(cairo_);
|
||||
if (cx || cy || W < img->w() || H < img->h()) { // clip when necessary
|
||||
cairo_rectangle(cairo_, X-0.5, Y-0.5, W+1, H+1);
|
||||
cairo_clip(cairo_);
|
||||
}
|
||||
// remove any scaling and the current "0.5" translation useful for lines but bad for images
|
||||
matrix.xx = matrix.yy = 1;
|
||||
matrix.x0 -= 0.5 * s; matrix.y0 -= 0.5 * s;
|
||||
cairo_set_matrix(cairo_, &matrix);
|
||||
if (img->d() >= 1) cairo_set_source(cairo_, pat);
|
||||
int offset = 0;
|
||||
if (Ws >= img->data_w()*1.09 || Hs >= img->data_h()*1.09) {
|
||||
// When enlarging while drawing, 1 pixel around target area seems unpainted,
|
||||
// so we increase a bit the target area and move it int(s) pixels to left and top.
|
||||
Ws = (img->w()+2)*s, Hs = (img->h()+2)*s;
|
||||
offset = int(s);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"WHs=%dx%d dataWH=%dx%d s=%.1f offset=%d\n",Ws,Hs,img->data_w(),img->data_h(),s,offset);
|
||||
cairo_matrix_init_scale(&matrix, double(img->data_w())/Ws, double(img->data_h())/Hs);
|
||||
cairo_matrix_translate(&matrix, -Xs + offset, -Ys + offset);
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
// Don't draw an empty image...
|
||||
if (!rgb->d() || !rgb->array) {
|
||||
Fl_Graphics_Driver::draw_empty(rgb, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(rgb, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
|
||||
return;
|
||||
}
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
|
||||
if (!pat) {
|
||||
cache(rgb);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
|
||||
}
|
||||
draw_cached_pattern_(rgb, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
static cairo_user_data_key_t data_key_for_surface = {};
|
||||
|
||||
static void dealloc_surface_data(void *data) {
|
||||
delete[] (uchar*)data;
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
|
||||
draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy);
|
||||
}
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy)
|
||||
{
|
||||
cairo_surface_t *surf;
|
||||
cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1);
|
||||
int stride = cairo_format_stride_for_width(format, img->data_w());
|
||||
uchar *BGRA = new uchar[stride * img->data_h()];
|
||||
memset(BGRA, 0, stride * img->data_h());
|
||||
if (img->d() >= 1) { // process Fl_RGB_Image of all depths
|
||||
Fl_RGB_Image *rgb = (Fl_RGB_Image*)img;
|
||||
int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
|
||||
uchar A = 0xff, R,G,B, *q;
|
||||
const uchar *r;
|
||||
float f = 1;
|
||||
if (rgb->d() >= 3) { // color images
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
R = *r;
|
||||
G = *(r+1);
|
||||
B = *(r+2);
|
||||
if (rgb->d() == 4) {
|
||||
A = *(r+3);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*q = B * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = R * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
} else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
G = *r;
|
||||
if (rgb->d() == 2) {
|
||||
A = *(r+1);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*(q) = G * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = G * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
void Fl_Cairo_Graphics_Driver::cache(Fl_RGB_Image *rgb) {
|
||||
int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, rgb->data_w());
|
||||
uchar *BGRA = new uchar[stride * rgb->data_h()];
|
||||
memset(BGRA, 0, stride * rgb->data_h());
|
||||
int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
|
||||
uchar A = 0xff, R,G,B, *q;
|
||||
const uchar *r;
|
||||
float f = 1;
|
||||
if (rgb->d() >= 3) { // color images
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
R = *r;
|
||||
G = *(r+1);
|
||||
B = *(r+2);
|
||||
if (rgb->d() == 4) {
|
||||
A = *(r+3);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*q = B * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = R * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Fl_Bitmap *bm = (Fl_Bitmap*)img;
|
||||
} else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
G = *r;
|
||||
if (rgb->d() == 2) {
|
||||
A = *(r+1);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*(q) = G * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = G * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, Fl_Cairo_Graphics_Driver::cairo_format, rgb->data_w(), rgb->data_h(), stride);
|
||||
if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) return;
|
||||
(void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
*Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)pat;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)id_;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
id_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
if (!bm->array) {
|
||||
draw_empty(bm, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(bm, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return;
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
|
||||
if (!pat) {
|
||||
cache(bm);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
|
||||
}
|
||||
if (pat) {
|
||||
draw_cached_pattern_(bm, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::cache(Fl_Bitmap *bm) {
|
||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, bm->data_w());
|
||||
uchar *BGRA = new uchar[stride * bm->data_h()];
|
||||
memset(BGRA, 0, stride * bm->data_h());
|
||||
uchar *r, p;
|
||||
unsigned *q;
|
||||
for (int j = 0; j < bm->data_h(); j++) {
|
||||
@ -641,26 +834,211 @@ void Fl_Cairo_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, in
|
||||
if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
|
||||
}
|
||||
}
|
||||
}
|
||||
surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride);
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, CAIRO_FORMAT_A1, bm->data_w(), bm->data_h(), stride);
|
||||
if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
|
||||
static cairo_user_data_key_t key = {};
|
||||
(void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA);
|
||||
(void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_save(cairo_);
|
||||
cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1);
|
||||
cairo_clip(cairo_);
|
||||
if (img->d() >= 1) cairo_set_source(cairo_, pat);
|
||||
cairo_matrix_t matrix;
|
||||
cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1));
|
||||
cairo_matrix_translate(&matrix, -XP+0.5+cx, -YP+0.5+cy);
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
cairo_restore(cairo_);
|
||||
check_status();
|
||||
*Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)pat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
// Don't draw an empty image...
|
||||
if (!pxm->data() || !pxm->w()) {
|
||||
Fl_Graphics_Driver::draw_empty(pxm, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
|
||||
return;
|
||||
}
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
|
||||
if (!pat) {
|
||||
cache(pxm);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
|
||||
}
|
||||
draw_cached_pattern_(pxm, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::cache(Fl_Pixmap *pxm) {
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
|
||||
cache(rgb);
|
||||
*Fl_Graphics_Driver::id(pxm) = *Fl_Graphics_Driver::id(rgb);
|
||||
*Fl_Graphics_Driver::id(rgb) = 0;
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)p;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)bm;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Fl_Cairo_Graphics_Driver::height() {
|
||||
if (!font_descriptor()) font(0, 12);
|
||||
return (font_descriptor()->ascent + font_descriptor()->descent)*1.1 /*1.15 scale=1*/;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Cairo_Graphics_Driver::descent() {
|
||||
return font_descriptor()->descent;
|
||||
}
|
||||
|
||||
extern Fl_Fontdesc *fl_fonts;
|
||||
|
||||
|
||||
Fl_Cairo_Font_Descriptor::Fl_Cairo_Font_Descriptor(const char* name, Fl_Fontsize size) : Fl_Font_Descriptor(name, size) {
|
||||
char string[70];
|
||||
strcpy(string, name);
|
||||
sprintf(string + strlen(string), " %d", int(size * 0.7 + 0.5) ); // why reduce size?
|
||||
fontref = pango_font_description_from_string(string);
|
||||
width = NULL;
|
||||
static PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10
|
||||
static PangoContext *pango_context = pango_font_map_create_context(def_font_map); // 1.22
|
||||
static PangoLanguage *language = pango_language_get_default(); // 1.16
|
||||
PangoFontset *fontset = pango_font_map_load_fontset(def_font_map, pango_context, fontref, language);
|
||||
PangoFontMetrics *metrics = pango_fontset_get_metrics(fontset);
|
||||
ascent = pango_font_metrics_get_ascent(metrics)/PANGO_SCALE;
|
||||
descent = pango_font_metrics_get_descent(metrics)/PANGO_SCALE;
|
||||
q_width = pango_font_metrics_get_approximate_char_width(metrics)/PANGO_SCALE;
|
||||
pango_font_metrics_unref(metrics);
|
||||
g_object_unref(fontset);
|
||||
//fprintf(stderr, "[%s](%d) ascent=%d descent=%d q_width=%d\n", name, size, ascent, descent, q_width);
|
||||
}
|
||||
|
||||
|
||||
Fl_Cairo_Font_Descriptor::~Fl_Cairo_Font_Descriptor() {
|
||||
pango_font_description_free(fontref);
|
||||
if (width) {
|
||||
for (int i = 0; i < 64; i++) delete[] width[i];
|
||||
}
|
||||
delete[] width;
|
||||
}
|
||||
|
||||
|
||||
static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
|
||||
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->next = s->first;
|
||||
s->first = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize s) {
|
||||
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, s) );
|
||||
pango_layout_set_font_description(pango_layout_, ((Fl_Cairo_Font_Descriptor*)font_descriptor())->fontref);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw(const char* str, int n, float x, float y) {
|
||||
if (!n) return;
|
||||
cairo_save(cairo_);
|
||||
cairo_translate(cairo_, x, y - height() + descent() -1);
|
||||
pango_layout_set_text(pango_layout_, str, n);
|
||||
pango_cairo_show_layout(cairo_, pango_layout_);
|
||||
cairo_restore(cairo_);
|
||||
surface_needs_commit();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y)
|
||||
{
|
||||
cairo_save(cairo_);
|
||||
cairo_translate(cairo_, x, y);
|
||||
cairo_rotate(cairo_, -rotation * M_PI / 180);
|
||||
this->draw(str, n, 0, 0);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
|
||||
int w = (int)width(str, n);
|
||||
draw(str, n, x - w, y);
|
||||
}
|
||||
|
||||
|
||||
double Fl_Cairo_Graphics_Driver::width(const char* c, int n) {
|
||||
if (!font_descriptor()) return -1.0;
|
||||
int i = 0, w = 0, l;
|
||||
const char *end = c + n;
|
||||
unsigned int ucs;
|
||||
while (i < n) {
|
||||
ucs = fl_utf8decode(c + i, end, &l);
|
||||
i += l;
|
||||
w += width(ucs);
|
||||
}
|
||||
return (double)w;
|
||||
}
|
||||
|
||||
|
||||
double Fl_Cairo_Graphics_Driver::width(unsigned int c) {
|
||||
unsigned int r = 0;
|
||||
Fl_Cairo_Font_Descriptor *desc = NULL;
|
||||
if (c <= 0xFFFF) { // when inside basic multilingual plane
|
||||
desc = (Fl_Cairo_Font_Descriptor*)font_descriptor();
|
||||
r = (c & 0xFC00) >> 10;
|
||||
if (!desc->width) {
|
||||
desc->width = (int**)new int*[64];
|
||||
memset(desc->width, 0, 64*sizeof(int*));
|
||||
}
|
||||
if (!desc->width[r]) {
|
||||
desc->width[r] = (int*)new int[0x0400];
|
||||
for (int i = 0; i < 0x0400; i++) desc->width[r][i] = -1;
|
||||
} else {
|
||||
if ( desc->width[r][c & 0x03FF] >= 0 ) { // already cached
|
||||
return (double) desc->width[r][c & 0x03FF];
|
||||
}
|
||||
}
|
||||
}
|
||||
char buf[4];
|
||||
int n = fl_utf8encode(c, buf);
|
||||
pango_layout_set_text(pango_layout_, buf, n);
|
||||
int W = 0, H;
|
||||
pango_layout_get_pixel_size(pango_layout_, &W, &H);
|
||||
if (c <= 0xFFFF) desc->width[r][c & 0x03FF] = W;
|
||||
return (double)W;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Cairo_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) {
|
||||
pango_layout_set_text(pango_layout_, txt, n);
|
||||
PangoRectangle ink_rect;
|
||||
pango_layout_get_pixel_extents(pango_layout_, &ink_rect, NULL);
|
||||
dx = ink_rect.x;
|
||||
dy = ink_rect.y - height() + descent();
|
||||
w = ink_rect.width;
|
||||
h = ink_rect.height;
|
||||
}
|
||||
|
||||
|
||||
#endif // USE_PANGO
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Classes Fl_PostScript_File_Device and Fl_PostScript_Graphics_Driver for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2020 by Bill Spitzak and others.
|
||||
// Copyright 2010-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -1499,8 +1499,24 @@ int Fl_PostScript_Graphics_Driver::start_eps(int width, int height) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PangoFontDescription* Fl_PostScript_Graphics_Driver::pango_font_description(Fl_Font fnum) {
|
||||
return Fl_Graphics_Driver::default_driver().pango_font_description(fnum);
|
||||
|
||||
void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, double x, double y) {
|
||||
if (!n) return;
|
||||
PangoFontDescription *pfd = Fl_Graphics_Driver::default_driver().pango_font_description(font());
|
||||
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);
|
||||
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_);
|
||||
}
|
||||
cairo_restore(cairo_);
|
||||
check_status();
|
||||
}
|
||||
|
||||
#endif // USE_PANGO
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Support for graphics output to PostScript file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2020 by Bill Spitzak and others.
|
||||
// Copyright 2010-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -70,17 +70,27 @@ public:
|
||||
int height();
|
||||
int descent();
|
||||
void text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h);
|
||||
// draw text at width measured on display
|
||||
void transformed_draw(const char* s, int n, double x, double y);
|
||||
void draw(const char* s, int nBytes, int x, int y) {transformed_draw(s,nBytes,x,y); }
|
||||
void draw(const char* s, int nBytes, float x, float y) {transformed_draw(s,nBytes,x,y); }
|
||||
void draw(int angle, const char *str, int n, int x, int y) {Fl_Cairo_Graphics_Driver::draw(angle, str, n, x, y);}
|
||||
|
||||
void color(Fl_Color c);
|
||||
void color(uchar r, uchar g, uchar b) {Fl_Cairo_Graphics_Driver::color(r,g,b);}
|
||||
Fl_Color color();
|
||||
void point(int x, int y);
|
||||
int not_clipped(int x, int y, int w, int h);
|
||||
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
|
||||
virtual PangoFontDescription* pango_font_description(Fl_Font fnum);
|
||||
virtual int has_feature(driver_feature feature_mask) { return feature_mask & PRINTER; }
|
||||
// draw image classes without caching them
|
||||
void draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_pixmap(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_bitmap(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_rgb(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
};
|
||||
|
||||
#else // USE_PANGO
|
||||
#else // ! USE_PANGO
|
||||
|
||||
class FL_EXPORT Fl_PostScript_Graphics_Driver : public Fl_Graphics_Driver {
|
||||
private:
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Postscript image drawing implementation for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -25,8 +25,10 @@
|
||||
#include <stdlib.h> // abs(int)
|
||||
#include <string.h> // memcpy()
|
||||
|
||||
#if ! USE_PANGO
|
||||
#include <stdio.h> // fprintf()
|
||||
#if USE_PANGO
|
||||
# include <cairo/cairo.h>
|
||||
#else
|
||||
# include <stdio.h> // fprintf()
|
||||
#endif
|
||||
|
||||
struct callback_data {
|
||||
@ -66,7 +68,119 @@ void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy
|
||||
draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
|
||||
}
|
||||
|
||||
#if ! USE_PANGO
|
||||
#if USE_PANGO
|
||||
|
||||
static void destroy_BGRA(void *data) {
|
||||
delete[] (uchar*)data;
|
||||
}
|
||||
|
||||
|
||||
void Fl_PostScript_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
|
||||
draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
|
||||
void Fl_PostScript_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
draw_rgb_bitmap_(rgb, XP, YP, WP, HP, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PostScript_Graphics_Driver::draw_bitmap(Fl_Bitmap *bitmap,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
draw_rgb_bitmap_(bitmap, XP, YP, WP, HP, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PostScript_Graphics_Driver::draw_rgb_bitmap_(Fl_Image *img,int XP, int YP, int WP, int HP, int cx, int cy)
|
||||
{
|
||||
cairo_surface_t *surf;
|
||||
cairo_format_t format = (img->d() >= 1 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A1);
|
||||
int stride = cairo_format_stride_for_width(format, img->data_w());
|
||||
uchar *BGRA = new uchar[stride * img->data_h()];
|
||||
memset(BGRA, 0, stride * img->data_h());
|
||||
if (img->d() >= 1) { // process Fl_RGB_Image of all depths
|
||||
Fl_RGB_Image *rgb = (Fl_RGB_Image*)img;
|
||||
int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
|
||||
uchar A = 0xff, R,G,B, *q;
|
||||
const uchar *r;
|
||||
float f = 1;
|
||||
if (rgb->d() >= 3) { // color images
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
R = *r;
|
||||
G = *(r+1);
|
||||
B = *(r+2);
|
||||
if (rgb->d() == 4) {
|
||||
A = *(r+3);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*q = B * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = R * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
} else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
G = *r;
|
||||
if (rgb->d() == 2) {
|
||||
A = *(r+1);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*(q) = G * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = G * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Fl_Bitmap *bm = (Fl_Bitmap*)img;
|
||||
uchar *r, p;
|
||||
unsigned *q;
|
||||
for (int j = 0; j < bm->data_h(); j++) {
|
||||
r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
|
||||
q = (unsigned*)(BGRA + j * stride);
|
||||
unsigned k = 0, mask32 = 1;
|
||||
p = *r;
|
||||
for (int i = 0; i < bm->data_w(); i++) {
|
||||
if (p&1) (*q) |= mask32;
|
||||
k++;
|
||||
if (k % 8 != 0) p >>= 1; else p = *(++r);
|
||||
if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
|
||||
}
|
||||
}
|
||||
}
|
||||
surf = cairo_image_surface_create_for_data(BGRA, format, img->data_w(), img->data_h(), stride);
|
||||
if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
|
||||
static cairo_user_data_key_t key = {};
|
||||
(void)cairo_surface_set_user_data(surf, &key, BGRA, destroy_BGRA);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_save(cairo_);
|
||||
cairo_rectangle(cairo_, XP-0.5, YP-0.5, WP+1, HP+1);
|
||||
cairo_clip(cairo_);
|
||||
if (img->d() >= 1) cairo_set_source(cairo_, pat);
|
||||
cairo_matrix_t matrix;
|
||||
cairo_matrix_init_scale(&matrix, double(img->data_w())/(img->w()+1), double(img->data_h())/(img->h()+1));
|
||||
cairo_matrix_translate(&matrix, -XP+0.5+cx, -YP+0.5+cy);
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
cairo_restore(cairo_);
|
||||
check_status();
|
||||
}
|
||||
}
|
||||
|
||||
#else // USE_PANGO
|
||||
|
||||
//
|
||||
// Implementation of the /ASCII85Encode PostScript filter
|
||||
|
@ -1,33 +0,0 @@
|
||||
//
|
||||
// Font definitions for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2021 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#ifndef FL_FONT_
|
||||
#define FL_FONT_
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Wayland_Graphics_Driver.H"
|
||||
|
||||
class Fl_Wayland_Font_Descriptor : public Fl_Font_Descriptor {
|
||||
public:
|
||||
Fl_Wayland_Font_Descriptor(const char* fontname, Fl_Fontsize size);
|
||||
FL_EXPORT ~Fl_Wayland_Font_Descriptor();
|
||||
PangoFontDescription *fontref;
|
||||
int **width; // array of arrays of character widths
|
||||
};
|
||||
|
||||
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
|
||||
|
||||
#endif // FL_FONT_
|
@ -42,22 +42,16 @@
|
||||
gives the stride of this buffer;
|
||||
- size_t data_size
|
||||
gives the total buffer size in bytes (thus, data_size / stride gives the buffer height);
|
||||
- bool draw_buffer_needs_commit
|
||||
is TRUE when draw_buffer has been modified and needs being committed for display, and
|
||||
FALSE after having been committed but before having been modified;
|
||||
- struct wl_callback *cb
|
||||
is used to synchronize drawing with the compositor during progressive drawing.
|
||||
|
||||
When a graphics scene is to be committed, the data_size bytes of draw_buffer are copied by memcpy()
|
||||
starting at data, and wl_buffer is attached to the wl_surface which is committed for display
|
||||
by wl_surface_commit(). Finally, draw_buffer_needs_commit is set to FALSE.
|
||||
|
||||
All drawing functions have Cairo write to draw_buffer and turn draw_buffer_needs_commit to TRUE.
|
||||
*/
|
||||
by wl_surface_commit().
|
||||
*/
|
||||
|
||||
|
||||
#include "../Cairo/Fl_Cairo_Graphics_Driver.H"
|
||||
#include <cairo/cairo.h>
|
||||
#include <stdint.h> // for uint32_t
|
||||
typedef struct _PangoLayout PangoLayout;
|
||||
|
||||
@ -75,34 +69,19 @@ struct fl_wld_buffer {
|
||||
};
|
||||
struct wld_window;
|
||||
|
||||
|
||||
class FL_EXPORT Fl_Wayland_Graphics_Driver : public Fl_Cairo_Graphics_Driver {
|
||||
private:
|
||||
struct fl_wld_buffer *buffer_;
|
||||
PangoLayout *dummy_pango_layout_; // used to measure text width before showing a window
|
||||
int linestyle_;
|
||||
void draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy);
|
||||
public:
|
||||
Fl_Wayland_Graphics_Driver();
|
||||
~Fl_Wayland_Graphics_Driver();
|
||||
static const uint32_t wld_format;
|
||||
static const cairo_format_t cairo_format;
|
||||
void activate(struct fl_wld_buffer *buffer, float scale);
|
||||
void font(Fl_Font fnum, Fl_Fontsize s);
|
||||
Fl_Font font() { return Fl_Graphics_Driver::font(); }
|
||||
void draw(const char* s, int nBytes, int x, int y) { draw(s, nBytes, float(x), float(y)); }
|
||||
void draw(const char* s, int nBytes, float x, float y);
|
||||
void draw(int angle, const char *str, int n, int x, int y);
|
||||
void rtl_draw(const char* str, int n, int x, int y);
|
||||
int height();
|
||||
int descent();
|
||||
double width(const char *str, int n);
|
||||
double width(unsigned c);
|
||||
void text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h);
|
||||
int not_clipped(int x, int y, int w, int h);
|
||||
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
|
||||
void restore_clip();
|
||||
void clip_region(Fl_Region r);
|
||||
void line_style(int style, int width=0, char* dashes=0);
|
||||
Fl_Region XRectangleRegion(int x, int y, int w, int h);
|
||||
void add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H);
|
||||
void XDestroyRegion(Fl_Region r);
|
||||
@ -112,45 +91,12 @@ public:
|
||||
void font_name(int num, const char *name);
|
||||
const char* get_font_name(Fl_Font fnum, int* ap);
|
||||
int get_font_sizes(Fl_Font fnum, int*& sizep);
|
||||
void point(int x, int y);
|
||||
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy);
|
||||
void draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD);
|
||||
void curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3);
|
||||
void begin_points();
|
||||
void end_points();
|
||||
void transformed_vertex(double x, double y);
|
||||
void draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void cache(Fl_RGB_Image *rgb);
|
||||
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
|
||||
void draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void cache(Fl_Bitmap *img);
|
||||
void delete_bitmask(Fl_Bitmask bm);
|
||||
void cache(Fl_Pixmap *pxm);
|
||||
void draw_pixmap(Fl_Pixmap *rgb,int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void uncache_pixmap(fl_uintptr_t p);
|
||||
void overlay_rect(int x, int y, int w , int h);
|
||||
static void init_built_in_fonts();
|
||||
static struct fl_wld_buffer *create_shm_buffer(int width, int height);
|
||||
static void buffer_release(struct wld_window *window);
|
||||
static void buffer_commit(struct wld_window *window);
|
||||
static void cairo_init(struct fl_wld_buffer *buffer, int width, int height, int stride, cairo_format_t format);
|
||||
void line(int x1, int y1, int x2, int y2);
|
||||
void line(int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void xyline(int x, int y, int x1);
|
||||
void xyline(int x, int y, int x1, int y2);
|
||||
void xyline(int x, int y, int x1, int y2, int x3);
|
||||
void yxline(int x, int y, int y1);
|
||||
void yxline(int x, int y, int y1, int x2);
|
||||
void yxline(int x, int y, int y1, int x2, int y3);
|
||||
void loop(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void rect(int x, int y, int w, int h);
|
||||
void rectf(int x, int y, int w, int h);
|
||||
void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void end_loop();
|
||||
void end_line();
|
||||
void end_polygon();
|
||||
void set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win);
|
||||
void reset_spot();
|
||||
};
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "Fl_Wayland_Graphics_Driver.H"
|
||||
#include "Fl_Wayland_Screen_Driver.H"
|
||||
#include "Fl_Wayland_Window_Driver.H"
|
||||
#include "Fl_Font.H"
|
||||
#include "text-input-client-protocol.h"
|
||||
#include <pango/pangocairo.h>
|
||||
#if ! PANGO_VERSION_CHECK(1,22,0)
|
||||
@ -63,7 +62,7 @@ static int create_anonymous_file(int size, char **pshared)
|
||||
struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, int height)
|
||||
{
|
||||
struct fl_wld_buffer *buffer;
|
||||
int stride = cairo_format_stride_for_width(Fl_Wayland_Graphics_Driver::cairo_format, width);
|
||||
int stride = cairo_format_stride_for_width(Fl_Cairo_Graphics_Driver::cairo_format, width);
|
||||
int size = stride * height;
|
||||
static char *pool_memory = NULL;
|
||||
static int pool_size = 10000000; // gets increased if necessary
|
||||
@ -91,7 +90,7 @@ struct fl_wld_buffer *Fl_Wayland_Graphics_Driver::create_shm_buffer(int width, i
|
||||
buffer->draw_buffer = new uchar[buffer->data_size];
|
||||
buffer->draw_buffer_needs_commit = false;
|
||||
//fprintf(stderr, "create_shm_buffer: %dx%d = %d\n", width, height, size);
|
||||
cairo_init(buffer, width, height, stride, Fl_Wayland_Graphics_Driver::cairo_format);
|
||||
cairo_init(buffer, width, height, stride, Fl_Cairo_Graphics_Driver::cairo_format);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -146,7 +145,6 @@ void Fl_Wayland_Graphics_Driver::buffer_release(struct wld_window *window)
|
||||
|
||||
// these 2 refer to the same memory layout for pixel data
|
||||
const uint32_t Fl_Wayland_Graphics_Driver::wld_format = WL_SHM_FORMAT_ARGB8888;
|
||||
const cairo_format_t Fl_Wayland_Graphics_Driver::cairo_format = CAIRO_FORMAT_ARGB32;
|
||||
|
||||
|
||||
Fl_Wayland_Graphics_Driver::Fl_Wayland_Graphics_Driver () : Fl_Cairo_Graphics_Driver() {
|
||||
@ -213,75 +211,26 @@ static Fl_Fontdesc built_in_table[] = { // Pango font names
|
||||
|
||||
FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table;
|
||||
|
||||
|
||||
static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
|
||||
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_Wayland_Font_Descriptor(s->name, size);
|
||||
f->next = s->first;
|
||||
s->first = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
Fl_Wayland_Font_Descriptor::Fl_Wayland_Font_Descriptor(const char* name, Fl_Fontsize size) : Fl_Font_Descriptor(name, size) {
|
||||
char string[70];
|
||||
strcpy(string, name);
|
||||
sprintf(string + strlen(string), " %d", int(size * 0.7 + 0.5) ); // why reduce size?
|
||||
fontref = pango_font_description_from_string(string);
|
||||
width = NULL;
|
||||
static PangoFontMap *def_font_map = pango_cairo_font_map_get_default(); // 1.10
|
||||
static PangoContext *pango_context = pango_font_map_create_context(def_font_map); // 1.22
|
||||
static PangoLanguage *language = pango_language_get_default(); // 1.16
|
||||
PangoFontset *fontset = pango_font_map_load_fontset(def_font_map, pango_context, fontref, language);
|
||||
PangoFontMetrics *metrics = pango_fontset_get_metrics(fontset);
|
||||
ascent = pango_font_metrics_get_ascent(metrics)/PANGO_SCALE;
|
||||
descent = pango_font_metrics_get_descent(metrics)/PANGO_SCALE;
|
||||
q_width = pango_font_metrics_get_approximate_char_width(metrics)/PANGO_SCALE;
|
||||
pango_font_metrics_unref(metrics);
|
||||
g_object_unref(fontset);
|
||||
//fprintf(stderr, "[%s](%d) ascent=%d descent=%d q_width=%d\n", name, size, ascent, descent, q_width);
|
||||
}
|
||||
|
||||
|
||||
Fl_Wayland_Font_Descriptor::~Fl_Wayland_Font_Descriptor() {
|
||||
pango_font_description_free(fontref);
|
||||
if (width) {
|
||||
for (int i = 0; i < 64; i++) delete[] width[i];
|
||||
void Fl_Wayland_Graphics_Driver::init_built_in_fonts() {
|
||||
static int i = 0;
|
||||
if (!i) {
|
||||
while (i < FL_FREE_FONT) {
|
||||
i++;
|
||||
Fl::set_font((Fl_Font)i-1, built_in_table[i-1].name);
|
||||
}
|
||||
}
|
||||
delete[] width;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Wayland_Graphics_Driver::height() {
|
||||
return (font_descriptor()->ascent + font_descriptor()->descent)*1.1 /*1.15 scale=1*/;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Wayland_Graphics_Driver::descent() {
|
||||
return font_descriptor()->descent;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize s) {
|
||||
if (font() == fnum && size() == s) return;
|
||||
if (!font_descriptor()) fl_open_display();
|
||||
if (!pango_layout_) {
|
||||
cairo_surface_t *surf = cairo_image_surface_create(Fl_Wayland_Graphics_Driver::cairo_format, 100, 100);
|
||||
cairo_surface_t *surf = cairo_image_surface_create(Fl_Cairo_Graphics_Driver::cairo_format, 100, 100);
|
||||
cairo_ = cairo_create(surf);
|
||||
dummy_pango_layout_ = pango_cairo_create_layout(cairo_);
|
||||
pango_layout_ = dummy_pango_layout_;
|
||||
}
|
||||
if (fnum == -1) {
|
||||
Fl_Graphics_Driver::font(0, 0);
|
||||
return;
|
||||
}
|
||||
Fl_Graphics_Driver::font(fnum, s);
|
||||
font_descriptor( find(fnum, s) );
|
||||
pango_layout_set_font_description(pango_layout_, ((Fl_Wayland_Font_Descriptor*)font_descriptor())->fontref);
|
||||
Fl_Cairo_Graphics_Driver::font(fnum, s);
|
||||
}
|
||||
|
||||
|
||||
@ -339,17 +288,6 @@ Fl_Font Fl_Wayland_Graphics_Driver::set_fonts(const char* pattern_name)
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::init_built_in_fonts() {
|
||||
static int i = 0;
|
||||
if (!i) {
|
||||
while (i < FL_FREE_FONT) {
|
||||
i++;
|
||||
Fl::set_font((Fl_Font)i-1, built_in_table[i-1].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *Fl_Wayland_Graphics_Driver::font_name(int num) {
|
||||
return fl_fonts[num].name;
|
||||
}
|
||||
@ -403,136 +341,6 @@ int Fl_Wayland_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw(const char* str, int n, float x, float y) {
|
||||
if (!n) return;
|
||||
cairo_save(cairo_);
|
||||
cairo_translate(cairo_, x, y - height() + descent() -1);
|
||||
pango_layout_set_text(pango_layout_, str, n);
|
||||
pango_cairo_show_layout(cairo_, pango_layout_);
|
||||
cairo_restore(cairo_);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw(int rotation, const char *str, int n, int x, int y)
|
||||
{
|
||||
cairo_save(cairo_);
|
||||
cairo_translate(cairo_, x, y);
|
||||
cairo_rotate(cairo_, -rotation * M_PI / 180);
|
||||
this->draw(str, n, 0, 0);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
|
||||
int w = (int)width(str, n);
|
||||
draw(str, n, x - w, y);
|
||||
}
|
||||
|
||||
|
||||
double Fl_Wayland_Graphics_Driver::width(const char* c, int n) {
|
||||
if (!font_descriptor()) return -1.0;
|
||||
int i = 0, w = 0, l;
|
||||
const char *end = c + n;
|
||||
unsigned int ucs;
|
||||
while (i < n) {
|
||||
ucs = fl_utf8decode(c + i, end, &l);
|
||||
i += l;
|
||||
w += width(ucs);
|
||||
}
|
||||
return (double)w;
|
||||
}
|
||||
|
||||
|
||||
double Fl_Wayland_Graphics_Driver::width(unsigned int c) {
|
||||
unsigned int r = 0;
|
||||
Fl_Wayland_Font_Descriptor *desc = NULL;
|
||||
if (c <= 0xFFFF) { // when inside basic multilingual plane
|
||||
desc = (Fl_Wayland_Font_Descriptor*)font_descriptor();
|
||||
r = (c & 0xFC00) >> 10;
|
||||
if (!desc->width) {
|
||||
desc->width = (int**)new int*[64];
|
||||
memset(desc->width, 0, 64*sizeof(int*));
|
||||
}
|
||||
if (!desc->width[r]) {
|
||||
desc->width[r] = (int*)new int[0x0400];
|
||||
for (int i = 0; i < 0x0400; i++) desc->width[r][i] = -1;
|
||||
} else {
|
||||
if ( desc->width[r][c & 0x03FF] >= 0 ) { // already cached
|
||||
return (double) desc->width[r][c & 0x03FF];
|
||||
}
|
||||
}
|
||||
}
|
||||
char buf[4];
|
||||
int n = fl_utf8encode(c, buf);
|
||||
pango_layout_set_text(pango_layout_, buf, n);
|
||||
int W = 0, H;
|
||||
pango_layout_get_pixel_size(pango_layout_, &W, &H);
|
||||
if (c <= 0xFFFF) desc->width[r][c & 0x03FF] = W;
|
||||
return (double)W;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::text_extents(const char* txt, int n, int& dx, int& dy, int& w, int& h) {
|
||||
pango_layout_set_text(pango_layout_, txt, n);
|
||||
PangoRectangle ink_rect;
|
||||
pango_layout_get_pixel_extents(pango_layout_, &ink_rect, NULL);
|
||||
dx = ink_rect.x;
|
||||
dy = ink_rect.y - height() + descent();
|
||||
w = ink_rect.width;
|
||||
h = ink_rect.height;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Wayland_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
|
||||
if (!clip_) return 1;
|
||||
if (clip_->w < 0) return 1;
|
||||
int X = 0, Y = 0, W = 0, H = 0;
|
||||
clip_box(x, y, w, h, X, Y, W, H);
|
||||
if (W) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fl_Wayland_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) {
|
||||
if (!clip_) {
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 0;
|
||||
}
|
||||
if (clip_->w < 0) {
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 1;
|
||||
}
|
||||
int ret = 0;
|
||||
if (x > (X=clip_->x)) {X=x; ret=1;}
|
||||
if (y > (Y=clip_->y)) {Y=y; ret=1;}
|
||||
if ((x+w) < (clip_->x+clip_->w)) {
|
||||
W=x+w-X;
|
||||
|
||||
ret=1;
|
||||
|
||||
}else
|
||||
W = clip_->x + clip_->w - X;
|
||||
if(W<0){
|
||||
W=0;
|
||||
return 1;
|
||||
}
|
||||
if ((y+h) < (clip_->y+clip_->h)) {
|
||||
H=y+h-Y;
|
||||
ret=1;
|
||||
}else
|
||||
H = clip_->y + clip_->h - Y;
|
||||
if(H<0){
|
||||
W=0;
|
||||
H=0;
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::restore_clip() {
|
||||
if (cairo_) cairo_reset_clip(cairo_);
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::clip_region(Fl_Region r) {
|
||||
if (cairo_) {
|
||||
cairo_reset_clip(cairo_);
|
||||
@ -590,357 +398,6 @@ void Fl_Wayland_Graphics_Driver::set_color(Fl_Color i, unsigned c) {
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::point(int x, int y) {
|
||||
rectf(x, y, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) {
|
||||
// draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
|
||||
int height = osrc->data_size / osrc->stride;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_get_matrix(cairo_, &matrix);
|
||||
double s = matrix.xx;
|
||||
cairo_save(cairo_);
|
||||
cairo_rectangle(cairo_, x, y, w, h);
|
||||
cairo_clip(cairo_);
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(osrc->draw_buffer, Fl_Wayland_Graphics_Driver::cairo_format, osrc->width, height, osrc->stride);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_set_source(cairo_, pat);
|
||||
cairo_matrix_init_scale(&matrix, s, s);
|
||||
cairo_matrix_translate(&matrix, -(x - srcx), -(y - srcy));
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
|
||||
struct callback_data {
|
||||
const uchar *data;
|
||||
int D, LD;
|
||||
};
|
||||
|
||||
|
||||
static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) {
|
||||
struct callback_data *cb_data;
|
||||
const uchar *curdata;
|
||||
|
||||
cb_data = (struct callback_data*)data;
|
||||
int last = x+w;
|
||||
const size_t aD = abs(cb_data->D);
|
||||
curdata = cb_data->data + x*cb_data->D + y*cb_data->LD;
|
||||
for (; x<last; x++) {
|
||||
memcpy(buf, curdata, aD);
|
||||
buf += aD;
|
||||
curdata += cb_data->D;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) {
|
||||
if (abs(D)<3){ //mono
|
||||
draw_image_mono(data, ix, iy, iw, ih, D, LD);
|
||||
return;
|
||||
}
|
||||
struct callback_data cb_data;
|
||||
if (!LD) LD = iw*abs(D);
|
||||
if (D<0) data += iw*abs(D);
|
||||
cb_data.data = data;
|
||||
cb_data.D = D;
|
||||
cb_data.LD = LD;
|
||||
Fl_Cairo_Graphics_Driver::draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, abs(D));
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3) {
|
||||
if (shape_ == POINTS) Fl_Graphics_Driver::curve(x, y, x1, y1, x2, y2, x3, y3);
|
||||
else Fl_Cairo_Graphics_Driver::curve(x, y, x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::begin_points() {
|
||||
cairo_save(cairo_);
|
||||
gap_=1;
|
||||
shape_=POINTS;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::end_points() {
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::transformed_vertex(double x, double y) {
|
||||
if (shape_ == POINTS){
|
||||
cairo_move_to(cairo_, x, y);
|
||||
point(x, y);
|
||||
gap_ = 1;
|
||||
} else {
|
||||
Fl_Cairo_Graphics_Driver::transformed_vertex(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::line_style(int style, int width, char* dashes) {
|
||||
linestyle_ = style;
|
||||
Fl_Cairo_Graphics_Driver::line_style(style, width, dashes);
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
|
||||
cairo_save(cairo_);
|
||||
cairo_matrix_t mat;
|
||||
cairo_get_matrix(cairo_, &mat);
|
||||
float s = (float)mat.xx;
|
||||
cairo_matrix_init_identity(&mat);
|
||||
cairo_set_matrix(cairo_, &mat); // use drawing units
|
||||
int lwidth = s < 1 ? 1 : int(s);
|
||||
cairo_set_line_width(cairo_, lwidth);
|
||||
cairo_translate(cairo_, lwidth/2., lwidth/2.); // translate by half of line width
|
||||
double ddash = (lwidth > 2 ? lwidth : 2);
|
||||
if (linestyle_ == FL_DOT){
|
||||
cairo_set_dash(cairo_, &ddash, 1, 0); // dash size = line width
|
||||
}
|
||||
// rectangle in drawing units
|
||||
int Xs = Fl_Scalable_Graphics_Driver::floor(x, s);
|
||||
int Ws = Fl_Scalable_Graphics_Driver::floor(x+w-1, s) - Xs;
|
||||
int Ys = Fl_Scalable_Graphics_Driver::floor(y, s);
|
||||
int Hs = Fl_Scalable_Graphics_Driver::floor(y+h-1, s) - Ys;
|
||||
cairo_move_to(cairo_, Xs, Ys);
|
||||
cairo_line_to(cairo_, Xs+Ws, Ys);
|
||||
cairo_line_to(cairo_, Xs+Ws, Ys+Hs);
|
||||
cairo_line_to(cairo_, Xs, Ys+Hs);
|
||||
cairo_close_path(cairo_);
|
||||
cairo_stroke(cairo_);
|
||||
cairo_restore(cairo_);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw_cached_pattern_(Fl_Image *img, cairo_pattern_t *pat, int X, int Y, int W, int H, int cx, int cy) {
|
||||
// compute size of output image in drawing units
|
||||
cairo_matrix_t matrix;
|
||||
cairo_get_matrix(cairo_, &matrix);
|
||||
float s = (float)matrix.xx;
|
||||
int Xs = Fl_Scalable_Graphics_Driver::floor(X - cx, s);
|
||||
int Ws = Fl_Scalable_Graphics_Driver::floor(X - cx + img->w(), s) - Xs ;
|
||||
int Ys = Fl_Scalable_Graphics_Driver::floor(Y - cy, s);
|
||||
int Hs = Fl_Scalable_Graphics_Driver::floor(Y - cy + img->h(), s) - Ys;
|
||||
if (Ws == 0 || Hs == 0) return;
|
||||
cairo_save(cairo_);
|
||||
if (cx || cy || W < img->w() || H < img->h()) { // clip when necessary
|
||||
cairo_rectangle(cairo_, X-0.5, Y-0.5, W+1, H+1);
|
||||
cairo_clip(cairo_);
|
||||
}
|
||||
// remove any scaling and the current "0.5" translation useful for lines but bad for images
|
||||
matrix.xx = matrix.yy = 1;
|
||||
matrix.x0 -= 0.5 * s; matrix.y0 -= 0.5 * s;
|
||||
cairo_set_matrix(cairo_, &matrix);
|
||||
if (img->d() >= 1) cairo_set_source(cairo_, pat);
|
||||
int offset = 0;
|
||||
if (Ws >= img->data_w()*1.09 || Hs >= img->data_h()*1.09) {
|
||||
// When enlarging while drawing, 1 pixel around target area seems unpainted,
|
||||
// so we increase a bit the target area and move it int(s) pixels to left and top.
|
||||
Ws = (img->w()+2)*s, Hs = (img->h()+2)*s;
|
||||
offset = int(s);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"WHs=%dx%d dataWH=%dx%d s=%.1f offset=%d\n",Ws,Hs,img->data_w(),img->data_h(),s,offset);
|
||||
cairo_matrix_init_scale(&matrix, double(img->data_w())/Ws, double(img->data_h())/Hs);
|
||||
cairo_matrix_translate(&matrix, -Xs + offset, -Ys + offset);
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_restore(cairo_);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
// Don't draw an empty image...
|
||||
if (!rgb->d() || !rgb->array) {
|
||||
Fl_Graphics_Driver::draw_empty(rgb, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(rgb, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
|
||||
return;
|
||||
}
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
|
||||
if (!pat) {
|
||||
cache(rgb);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(rgb);
|
||||
}
|
||||
draw_cached_pattern_(rgb, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
static cairo_user_data_key_t data_key_for_surface = {};
|
||||
|
||||
static void dealloc_surface_data(void *data) {
|
||||
delete[] (uchar*)data;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::cache(Fl_RGB_Image *rgb) {
|
||||
int stride = cairo_format_stride_for_width(Fl_Wayland_Graphics_Driver::cairo_format, rgb->data_w());
|
||||
uchar *BGRA = new uchar[stride * rgb->data_h()];
|
||||
memset(BGRA, 0, stride * rgb->data_h());
|
||||
int lrgb = rgb->ld() ? rgb->ld() : rgb->data_w() * rgb->d();
|
||||
uchar A = 0xff, R,G,B, *q;
|
||||
const uchar *r;
|
||||
float f = 1;
|
||||
if (rgb->d() >= 3) { // color images
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
R = *r;
|
||||
G = *(r+1);
|
||||
B = *(r+2);
|
||||
if (rgb->d() == 4) {
|
||||
A = *(r+3);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*q = B * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = R * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
} else if (rgb->d() == 1 || rgb->d() == 2) { // B&W
|
||||
for (int j = 0; j < rgb->data_h(); j++) {
|
||||
r = rgb->array + j * lrgb;
|
||||
q = BGRA + j * stride;
|
||||
for (int i = 0; i < rgb->data_w(); i++) {
|
||||
G = *r;
|
||||
if (rgb->d() == 2) {
|
||||
A = *(r+1);
|
||||
f = float(A)/0xff;
|
||||
}
|
||||
*(q) = G * f;
|
||||
*(q+1) = G * f;
|
||||
*(q+2) = G * f;
|
||||
*(q+3) = A;
|
||||
r += rgb->d(); q += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, Fl_Wayland_Graphics_Driver::cairo_format, rgb->data_w(), rgb->data_h(), stride);
|
||||
if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) return;
|
||||
(void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
*Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)pat;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)id_;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
id_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw_bitmap(Fl_Bitmap *bm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
if (!bm->array) {
|
||||
draw_empty(bm, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(bm, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return;
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
|
||||
if (!pat) {
|
||||
cache(bm);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(bm);
|
||||
}
|
||||
if (pat) {
|
||||
draw_cached_pattern_(bm, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::cache(Fl_Bitmap *bm) {
|
||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1, bm->data_w());
|
||||
uchar *BGRA = new uchar[stride * bm->data_h()];
|
||||
memset(BGRA, 0, stride * bm->data_h());
|
||||
uchar *r, p;
|
||||
unsigned *q;
|
||||
for (int j = 0; j < bm->data_h(); j++) {
|
||||
r = (uchar*)bm->array + j * ((bm->data_w() + 7)/8);
|
||||
q = (unsigned*)(BGRA + j * stride);
|
||||
unsigned k = 0, mask32 = 1;
|
||||
p = *r;
|
||||
for (int i = 0; i < bm->data_w(); i++) {
|
||||
if (p&1) (*q) |= mask32;
|
||||
k++;
|
||||
if (k % 8 != 0) p >>= 1; else p = *(++r);
|
||||
if (k % 32 != 0) mask32 <<= 1; else {q++; mask32 = 1;}
|
||||
}
|
||||
}
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(BGRA, CAIRO_FORMAT_A1, bm->data_w(), bm->data_h(), stride);
|
||||
if (cairo_surface_status(surf) == CAIRO_STATUS_SUCCESS) {
|
||||
(void)cairo_surface_set_user_data(surf, &data_key_for_surface, BGRA, dealloc_surface_data);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
*Fl_Graphics_Driver::id(bm) = (fl_uintptr_t)pat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)bm;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::draw_pixmap(Fl_Pixmap *pxm,int XP, int YP, int WP, int HP, int cx, int cy) {
|
||||
int X, Y, W, H;
|
||||
// Don't draw an empty image...
|
||||
if (!pxm->data() || !pxm->w()) {
|
||||
Fl_Graphics_Driver::draw_empty(pxm, XP, YP);
|
||||
return;
|
||||
}
|
||||
if (start_image(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
|
||||
return;
|
||||
}
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
|
||||
if (!pat) {
|
||||
cache(pxm);
|
||||
pat = (cairo_pattern_t*)*Fl_Graphics_Driver::id(pxm);
|
||||
}
|
||||
draw_cached_pattern_(pxm, pat, X, Y, W, H, cx, cy);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::cache(Fl_Pixmap *pxm) {
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(pxm);
|
||||
cache(rgb);
|
||||
*Fl_Graphics_Driver::id(pxm) = *Fl_Graphics_Driver::id(rgb);
|
||||
*Fl_Graphics_Driver::id(rgb) = 0;
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) {
|
||||
cairo_pattern_t *pat = (cairo_pattern_t*)p;
|
||||
if (pat) {
|
||||
cairo_surface_t *surf;
|
||||
cairo_pattern_get_surface(pat, &surf);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win) {
|
||||
Fl_Wayland_Screen_Driver::insertion_point_location(x, y, height);
|
||||
}
|
||||
@ -953,87 +410,23 @@ void Fl_Wayland_Graphics_Driver::reset_spot() {
|
||||
}
|
||||
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::line(int x1, int y1, int x2, int y2) {
|
||||
Fl_Cairo_Graphics_Driver::line(x1, y1, x2, y2);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::line(int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
Fl_Cairo_Graphics_Driver::line(x1, y1, x2, y2, x3, y3);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::xyline(int x, int y, int x1) {
|
||||
Fl_Cairo_Graphics_Driver::xyline(x, y, x1);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
|
||||
Fl_Cairo_Graphics_Driver::xyline(x, y, x1, y2);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
|
||||
Fl_Cairo_Graphics_Driver::xyline(x, y, x1, y2, x3);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::yxline(int x, int y, int y1) {
|
||||
Fl_Cairo_Graphics_Driver::yxline(x, y, y1);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
|
||||
Fl_Cairo_Graphics_Driver::yxline(x, y, y1, x2);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
|
||||
Fl_Cairo_Graphics_Driver::yxline(x, y, y1, x2, y3);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
Fl_Cairo_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
Fl_Cairo_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::rectf(int x, int y, int w, int h) {
|
||||
Fl_Cairo_Graphics_Driver::rectf(x, y, w, h);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::rect(int x, int y, int w, int h) {
|
||||
Fl_Cairo_Graphics_Driver::rect(x, y, w, h);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
|
||||
Fl_Cairo_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
|
||||
Fl_Cairo_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::end_line() {
|
||||
Fl_Cairo_Graphics_Driver::end_line();
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::end_loop(){
|
||||
Fl_Cairo_Graphics_Driver::end_loop();
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
}
|
||||
|
||||
void Fl_Wayland_Graphics_Driver::end_polygon() {
|
||||
Fl_Cairo_Graphics_Driver::end_polygon();
|
||||
buffer_->draw_buffer_needs_commit = true;
|
||||
void Fl_Wayland_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) {
|
||||
// draw portion srcx,srcy,w,h of osrc to position x,y (top-left) of the graphics driver's surface
|
||||
int height = osrc->data_size / osrc->stride;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_get_matrix(cairo_, &matrix);
|
||||
double s = matrix.xx;
|
||||
cairo_save(cairo_);
|
||||
cairo_rectangle(cairo_, x, y, w, h);
|
||||
cairo_clip(cairo_);
|
||||
cairo_surface_t *surf = cairo_image_surface_create_for_data(osrc->draw_buffer, Fl_Cairo_Graphics_Driver::cairo_format, osrc->width, height, osrc->stride);
|
||||
cairo_pattern_t *pat = cairo_pattern_create_for_surface(surf);
|
||||
cairo_set_source(cairo_, pat);
|
||||
cairo_matrix_init_scale(&matrix, s, s);
|
||||
cairo_matrix_translate(&matrix, -(x - srcx), -(y - srcy));
|
||||
cairo_pattern_set_matrix(pat, &matrix);
|
||||
cairo_mask(cairo_, pat);
|
||||
cairo_pattern_destroy(pat);
|
||||
cairo_surface_destroy(surf);
|
||||
cairo_restore(cairo_);
|
||||
}
|
||||
|
@ -396,6 +396,10 @@ void Fl_Wayland_Window_Driver::make_current() {
|
||||
|
||||
struct wld_window *window = fl_xid(pWindow);
|
||||
float scale = Fl::screen_scale(pWindow->screen_num()) * window->scale;
|
||||
if (window && window->buffer) {
|
||||
((Fl_Cairo_Graphics_Driver*)fl_graphics_driver)->needs_commit_tag(
|
||||
&window->buffer->draw_buffer_needs_commit);
|
||||
}
|
||||
|
||||
// to support progressive drawing
|
||||
if ( (!Fl_Wayland_Window_Driver::in_flush) && window && window->buffer && (!window->buffer->cb)) {
|
||||
|
Loading…
Reference in New Issue
Block a user