Open rageworx opened 11 months ago
/** \enum Fl_RGB_Scaling
The scaling algorithm to use for RGB images.
*/
enum Fl_RGB_Scaling {
FL_RGB_SCALING_NEAREST = 0, ///< default RGB image scaling algorithm
#ifndef FLTK_EXT_VERSION
FL_RGB_SCALING_BILINEAR ///< more accurate, but slower RGB image scaling algorithm
#else
FL_RGB_SCALING_BILINEAR = 1,
FL_RGB_SCALING_USER
#endif /// of FLTK_EXT_VERSION
};
/ User scaling callback type definition for FL_RGB_SCALING_USER / typedef void (Fl_Image_UserScale)(Fl_RGB_Image, int, int, int, int, Fl_RGB_Image); typedef Fl_Image_UserScale* Fl_Image_UserScale_p; // needed for BORLAND
* and in a Fl_Image.H class
class FL_EXPORT Fl_Image { friend class Fl_Graphics_Driver; public: static const int ERR_NO_IMAGE = -1; static const int ERR_FILE_ACCESS = -2; static const int ERR_FORMAT = -3; static const int ERR_MEMORY_ACCESS = -4;
private: int w, h, d, ld, count_; int dataw, datah; const char const data_; static Fl_RGB_Scaling RGBscaling; // method used when copying RGB images static Fl_RGB_Scaling scalingalgorithm; // method used to rescale RGB source images before drawing
static Fl_Image_UserScale_p userscaling; /// user scaling callback method.
... /* Sets what algorithm is used when resizing a source image to draw it. The default algorithm is FL_RGB_SCALING_BILINEAR. Drawing an Fl_Image is sometimes performed by first resizing the source image and then drawing the resized copy. This occurs, e.g., when drawing to screen under X11 without Xrender support after having called scale(). This function controls what method is used when the image to be resized is an Fl_RGB_Image. \version 1.4 /
static void scaling_algorithm(Fl_RGB_Scaling algorithm) {scalingalgorithm = algorithm; }
/* In version of FLTK-custom provides FL_RGB_SCALING_USER with userscale callback method, to better image quality. userscale only needed when algorithm set to FL_RGB_SCALING_USER. / static void scaling_algorithm(Fl_RGB_Scaling algorithm, Fl_Image_UserScale* userscale = NULL) { scalingalgorithm = algorithm; userscaling = userscale; }
static Fl_Image_UserScale* user_scaling_algorithm() { return userscaling; }
function draw_rgb()
void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) {
if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) {
return;
}
if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) {
Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy);
return;
}
if (!*Fl_Graphics_Driver::id(rgb)) {
cache(rgb);
}
push_clip(XP, YP, WP, HP);
XP -= cx; YP -= cy;
WP = rgb->w(); HP = rgb->h();
cache_size(rgb, WP, HP);
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
#ifdef FLTK_EXT_VERSION
int sclsucc = 0;
Fl_Image_UserScale_p usrscl = Fl_Image::user_scaling_algorithm();
if ( (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_USER) && (usrscl != NULL ) ) {
Fl_RGB_Image* sclrgb = NULL;
usrscl( rgb, this->floor(XP), this->floor(YP), WP, HP, &sclrgb );
if ( sclrgb != NULL ) {
cache(sclrgb);
WP = sclrgb->w();
HP = sclrgb->h();
cache_size(rgb, WP, HP);
SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(sclrgb));
if ( (sclrgb->d() % 2) == 0 ) {
alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, sclrgb->data_w(), sclrgb->data_h());
} else {
SetStretchBltMode(gc_, HALFTONE);
StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, sclrgb->data_w(), sclrgb->data_h(), SRCCOPY);
}
delete sclrgb;
sclsucc = 1;
}
}
if (sclsucc == 0)
{
#endif /// of FLTK_EXT_VERSION
if ( (rgb->d() % 2) == 0 ) {
alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h());
} else {
SetStretchBltMode(gc_, HALFTONE);
StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY);
}
#ifdef FLTK_EXT_VERSION
}
#endif /// of FLTK_EXT_VERSION
RestoreDC(new_gc, save);
DeleteDC(new_gc);
pop_clip();
}
void usr_scale(Fl_RGB_Image* s, int x, int y, int w, int h, Fl_RGB_Image** o)
{
printf( "(debug)usr_scale( %p, %d, %d, %d, %d, .. );\n",
s, x, y, w, h );
if ( s != NULL )
{
printf( "(debug)s->w() = %d, s->h() = %d\n", s->w(), s->h() );
Fl_RGB_Image* r = fl_imgtk::rescale( s, w, h, fl_imgtk::BICUBIC );
printf( "(debug)o->w() = %d, o->h() = %d\n", r->w(), r->h() );
*o = r;
}
fflush( stdout );
}
void presetFLTKenv()
{
Fl::set_font( FL_FREE_FONT, convLng );
Fl_Double_Window::default_xclass( DEF_APP_CLSNAME );
#ifdef FLTK_EXT_VERSION
Fl::scheme( "flat" );
Fl_Image:: scaling_algorithm( FL_RGB_SCALING_USER, usr_scale );
#else
Fl::scheme( "gtk+" );
// Default RGB image scaling for high-DPI, but not works on Windows.
Fl_Image::scaling_algorithm( FL_RGB_SCALING_BILINEAR );
#endif /// of FLTK_EXT_VERSION
}
void Fl_GDI_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP, int HP, int cx, int cy) {
if (Fl_Graphics_Driver::start_image(rgb, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) {
return;
}
if ((rgb->d() % 2) == 0 && !fl_can_do_alpha_blending()) {
Fl_Graphics_Driver::draw_rgb(rgb, XP, YP, WP, HP, cx, cy);
return;
}
if (!*Fl_Graphics_Driver::id(rgb)) {
cache(rgb);
}
push_clip(XP, YP, WP, HP);
XP -= cx; YP -= cy;
WP = rgb->w(); HP = rgb->h();
cache_size(rgb, WP, HP);
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
#ifdef FLTK_EXT_VERSION
int sclsucc = 0;
Fl_Image_UserScale_p usrscl = Fl_Image::user_scaling_algorithm();
if ( (Fl_Image::scaling_algorithm() == FL_RGB_SCALING_USER) && (usrscl != NULL ) ) {
Fl_RGB_Image* sclrgb = NULL;
usrscl( rgb, this->floor(XP), this->floor(YP), WP, HP, &sclrgb );
if ( sclrgb != NULL ) {
cache(sclrgb);
//WP = sclrgb->w();
//HP = sclrgb->h();
//cache_size(rgb, WP, HP);
SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(sclrgb));
if ( (sclrgb->d() % 2) == 0 ) {
alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, sclrgb->data_w(), sclrgb->data_h());
} else {
SetStretchBltMode(gc_, HALFTONE);
StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, sclrgb->data_w(), sclrgb->data_h(), SRCCOPY);
}
delete sclrgb;
DeleteObject(new_gc);
sclsucc = 1;
}
}
if (sclsucc == 0)
{
#endif /// of FLTK_EXT_VERSION
if ( (rgb->d() % 2) == 0 ) {
alpha_blend_(this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h());
} else {
SetStretchBltMode(gc_, HALFTONE);
StretchBlt(gc_, this->floor(XP), this->floor(YP), WP, HP, new_gc, 0, 0, rgb->data_w(), rgb->data_h(), SRCCOPY);
}
#ifdef FLTK_EXT_VERSION
}
#endif /// of FLTK_EXT_VERSION
RestoreDC(new_gc, save);
DeleteDC(new_gc);
pop_clip();
}
Fl_GDI_Graphcs_Driver::cache(Fl_RGB_Image* img)
.Fl_GDI_Graphcs_Driver::cache(Fl_RGB_Image* img)
,
Fl_Offscreen
,*Fl_Graphics_Driver::id(img)
to offscreen.*Fl_Graphics_Driver::id()
?Sources are being updated to branch of https://github.com/rageworx/fltk-custom/tree/1.4.0-dev-usr-scaling.
at https://github.com/rageworx/fltk-custom/commit/ce086caecd4689ba7ed258d5f7ab41bf527dedcc.
Thread 1 received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img)
.void Fl_GDI_Graphics_Driver::cache(Fl_RGB_Image *img)
don't test Fl_Image_Surface* surface
as NULL. if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) {
fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
} else {
fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d(), img->ld());
if (img->d() == 2 || img->d() == 4) {
*Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)create_alphamask(img->data_w(), img->data_h(), img->d(), img->ld(), img->array);
}
}
from ...
cache->1,2,3,4,5,done
usr_scale, 0, 0, 1109, 50 ...
(debug)s(0000013d526a6c80, 1109x50x3) ->scaled?(0) : o(1109x50x3) == 0000013d526a6da0
(debug)draw_rgb, user scale debug ...
(debug) .. caching Fl_RGB_Image(0000013d526a6da0) ...
cache->1,2,3,4,5,done
(debug) ... step #2
(debug) ... step #3
(debug) ... step #4
(debug) ... step #5
(debug) ... step #6
(debug) ... step #7
cache->1,2,3,4,5,done
usr_scale, 22, 12, 25, 25 ...
(debug)s(0000013d5269b870, 25x25x4) ->scaled?(0) : o(25x25x4) == 0000013d526b5fe0
(debug)draw_rgb, user scale debug ...
(debug) .. caching Fl_RGB_Image(0000013d526b5fe0) ...
cache->1,2,%
fl_draw_image(img->array, 0, 0, img->data_w(), img->data_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
and it calls to ...
void Fl_Scalable_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) {
if (scale() == 1) {
draw_image_unscaled(buf, X,Y,W,H,D,L);
} else {
draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false);
}
}
in Fl_Graphics_Driver -> Fl_GDI_Graphics_Driver_Image, innards().
Segment fault caused by null buffer reference in innards().
(debug)void innards( 0000000000000000, 0, 0, 25, 25, delta=4, ld=0, d=4, 0000000000000000, 0000000000000000, HDC=2181115365
25x25 image may a SVG, and it must be converted to RGBA, but why not contains array ?
Error fixed, to check sclrgb->array
has pointer.
Final testing almost completed in another commercial project that runs on Windows GDI( and GDI+) and fl_imgtk fixed bug library for refer to Fl_RGB_Image data width and height. Most of changes committed to v1.4.0-dev-user-scaling branch.
According to this issue, https://github.com/fltk/fltk/issues/742 Windows don't provided any scaling method when high DPI case.
Looks a custom version may have this type of callback,