From 542cfb4f0bafcba63c3831d17be7adebfe9c4457 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 15 Oct 2026 13:36:31 +0200 Subject: [PATCH 01/21] [asimage] introduce protected FromGradient method Used by TASPaletteEditor to display gradient palette One then can use directly TASImage::Paint to paint created palette This let avoid direct usage of special methods --- graf2d/asimage/inc/TASImage.h | 5 ++++ graf2d/asimage/src/TASImage.cxx | 16 ++++++++++ graf2d/asimage/src/TASPaletteEditor.cxx | 40 +++++++++++-------------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/graf2d/asimage/inc/TASImage.h b/graf2d/asimage/inc/TASImage.h index 3fad702ba1f0f..ba4989f59c89f 100644 --- a/graf2d/asimage/inc/TASImage.h +++ b/graf2d/asimage/inc/TASImage.h @@ -28,9 +28,12 @@ struct ASVisual; class TBrowser; class THashTable; class TTFhandle; +class TASPaletteEditor; class TASImage : public TImage { +friend class TASPaletteEditor; // to access FromGradient method + private: enum { kNoZoom = 0, kZoom = 1, kZoomOps = -1 }; enum { kReadWritePNG, kReadWriteVector }; @@ -82,6 +85,8 @@ class TASImage : public TImage { static Bool_t InitVisual(); Bool_t InitImage(const char *caller); + void FromGradient(struct ASGradient *as_gradient, UInt_t width, UInt_t height); + public: TASImage(); TASImage(UInt_t w, UInt_t h); diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index fd12225042217..60a956e416c5e 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -6396,6 +6396,22 @@ void TASImage::FromBitmap(const UChar_t *buf, UInt_t width, UInt_t height) fImage = bitmap2asimage(const_cast(buf), width, height, 0, nullptr); } + +//////////////////////////////////////////////////////////////////////////////// +/// Creates an image from ASGradient + +void TASImage::FromGradient(ASGradient *as_gradient, UInt_t width, UInt_t height) +{ + DestroyImage(); + DestroyScaledImage(); + + if (!InitVisual()) + Warning("FromGradient", "Visual not initiated"); + else + fImage = make_gradient(fgVisual, as_gradient, width, height, SCL_DO_COLOR, ASA_ARGB32, 0, GetImageQuality()); +} + + //////////////////////////////////////////////////////////////////////////////// /// Switch on/off the image palette. /// That also invokes calling vectorization of image. diff --git a/graf2d/asimage/src/TASPaletteEditor.cxx b/graf2d/asimage/src/TASPaletteEditor.cxx index eaf2c23c7de89..97fd87f77f2d8 100644 --- a/graf2d/asimage/src/TASPaletteEditor.cxx +++ b/graf2d/asimage/src/TASPaletteEditor.cxx @@ -891,36 +891,30 @@ void TASPaletteEditor::UpdateRange() void TASPaletteEditor::PaintPalette::Paint(Option_t *) { - // get geometry of pad - Int_t to_w = TMath::Abs(gPad->XtoPixel(gPad->GetX2()) - - gPad->XtoPixel(gPad->GetX1())); - Int_t to_h = TMath::Abs(gPad->YtoPixel(gPad->GetY2()) - - gPad->YtoPixel(gPad->GetY1())); + auto &pal = **fPalette; ASGradient grad; + grad.npoints = pal.fNumPoints - 2; + std::vector color(grad.npoints); + std::vector offset(grad.npoints); - grad.npoints = (*fPalette)->fNumPoints - 2; - grad.type = GRADIENT_Left2Right; - grad.color = new ARGB32[grad.npoints]; - grad.offset = new double[grad.npoints]; for (Int_t pt = 0; pt < grad.npoints; pt++) { - grad.offset[pt] = ((*fPalette)->fPoints[pt + 1] - (*fPalette)->fPoints[1]) / - ((*fPalette)->fPoints[(*fPalette)->fNumPoints - 2] - (*fPalette)->fPoints[1]); - grad.color[pt] = (((ARGB32)((*fPalette)->fColorBlue[pt + 1] & 0xff00)) >> 8) | - (((ARGB32)((*fPalette)->fColorGreen[pt + 1] & 0xff00)) ) | - (((ARGB32)((*fPalette)->fColorRed[pt + 1] & 0xff00)) << 8) | - (((ARGB32)((*fPalette)->fColorAlpha[pt + 1] & 0xff00)) << 16); + offset[pt] = (pal.fPoints[pt + 1] - pal.fPoints[1]) / + (pal.fPoints[pal.fNumPoints - 2] - pal.fPoints[1]); + color[pt] = (((ARGB32)(pal.fColorBlue[pt + 1] & 0xff00)) >> 8) | + (((ARGB32)(pal.fColorGreen[pt + 1] & 0xff00)) ) | + (((ARGB32)(pal.fColorRed[pt + 1] & 0xff00)) << 8) | + (((ARGB32)(pal.fColorAlpha[pt + 1] & 0xff00)) << 16); } - ASImage * grad_im = make_gradient((ASVisual*)TASImage::GetVisual(), &grad , to_w, to_h, - SCL_DO_COLOR, ASA_ARGB32, 0, - fAttImage->GetImageQuality()); - delete [] grad.color; - delete [] grad.offset; + grad.color = color.data(); + grad.offset = offset.data(); + grad.type = GRADIENT_Left2Right; - Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID()); - TASImage::Image2Drawable(grad_im, wid, 0, 0); - destroy_asimage(&grad_im); + TASImage img; + img.SetImageQuality(fAttImage->GetImageQuality()); + img.FromGradient(&grad, gPad->GetPadWidth(), gPad->GetPadHeight()); + img.Paint("x"); // x mean expand to full pad } //////////////////////////////////////////////////////////////////////////////// From 66baa963fe1aa6924ff01a903e05b91e8f8365c1 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 15 Oct 2026 16:23:27 +0200 Subject: [PATCH 02/21] [asimage] keep batch and bormal ASVisual separately Let return selected ASVisual as return value of TASImage::InitVisual(). Use batch for first time in Mirror method --- graf2d/asimage/inc/TASImage.h | 3 ++- graf2d/asimage/src/TASImage.cxx | 34 ++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/graf2d/asimage/inc/TASImage.h b/graf2d/asimage/inc/TASImage.h index ba4989f59c89f..269f04cf63495 100644 --- a/graf2d/asimage/inc/TASImage.h +++ b/graf2d/asimage/inc/TASImage.h @@ -75,6 +75,7 @@ friend class TASPaletteEditor; // to access FromGradient method static THashTable *fgPlugList; ///dpy was set to nullptr @@ -82,7 +83,7 @@ friend class TASPaletteEditor; // to access FromGradient method void MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas = kTRUE); void MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas = kTRUE); - static Bool_t InitVisual(); + static ASVisual *InitVisual(Bool_t plain = kFALSE); Bool_t InitImage(const char *caller); void FromGradient(struct ASGradient *as_gradient, UInt_t width, UInt_t height); diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index 60a956e416c5e..27d26c8dcdd7b 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -117,6 +117,7 @@ extern "C" { ASVisual *TASImage::fgVisual = nullptr; +ASVisual *TASImage::fgBatchVisual = nullptr; Bool_t TASImage::fgInit = kFALSE; Bool_t TASImage::fgBatch = kFALSE; @@ -2001,7 +2002,8 @@ void TASImage::Mirror(Bool_t vert) return; } - if (!InitVisual()) { + auto vis = InitVisual(true); + if (!vis) { Warning("Mirror", "Visual not initiated"); return; } @@ -2011,7 +2013,7 @@ void TASImage::Mirror(Bool_t vert) return; } - ASImage *img = mirror_asimage(fgVisual, fImage, 0, 0, + ASImage *img = mirror_asimage(vis, fImage, 0, 0, fImage->width, fImage->height, vert, ASA_ASImage, GetImageCompression(), GetImageQuality()); @@ -2069,14 +2071,19 @@ void TASImage::GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const } //////////////////////////////////////////////////////////////////////////////// -/// Static function to initialize the ASVisual. +/// Static internal method to initialize the ASVisual +/// Many operations do not require X11 display so plain "batch" visual can be used -Bool_t TASImage::InitVisual() +ASVisual *TASImage::InitVisual(Bool_t plain) { - Bool_t noX = gROOT->IsBatch() || !gVirtualX->InheritsFrom("TGX11"); + // this is new API, means return value must be used + if (fgBatchVisual && plain) + return fgBatchVisual; + + Bool_t noX = plain || gROOT->IsBatch() || !gVirtualX->InheritsFrom("TGX11"); - if (fgVisual && (noX == fgBatch)) - return kTRUE; + if (fgVisual && !noX && !fgBatch) + return fgVisual; fgVisual = nullptr; fgBatch = false; @@ -2100,20 +2107,17 @@ Bool_t TASImage::InitVisual() #endif #endif - static ASVisual *vis_batch = nullptr; - if (!fgVisual) { - if (!vis_batch) { + if (!fgBatchVisual) { // create dummy visual for batch mode - vis_batch = create_asvisual(nullptr, 0, 0, nullptr); - vis_batch->dpy = nullptr; // fake (not used) + fgBatchVisual = create_asvisual(nullptr, 0, 0, nullptr); + fgBatchVisual->dpy = nullptr; // fake (not used) } - - fgVisual = vis_batch; + fgVisual = fgBatchVisual; fgBatch = true; } - return kTRUE; + return fgVisual; } //////////////////////////////////////////////////////////////////////////////// From 9ea7c2fd6a7a830e9451f8a72bc82327b42e1280 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 09:44:31 +0200 Subject: [PATCH 03/21] [asimage] introduce TASUtils class It will be place for special TASImage methods which require X11 and gVirtualX functionality. In ROOT7 old deprecated methods will be removed from TASImage itself. --- graf2d/asimage/CMakeLists.txt | 17 ++++ graf2d/asimage/inc/LinkDefUtils.h | 19 +++++ graf2d/asimage/inc/TASImage.h | 2 + graf2d/asimage/inc/TASUtils.h | 34 ++++++++ graf2d/asimage/src/TASUtils.cxx | 126 ++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 graf2d/asimage/inc/LinkDefUtils.h create mode 100644 graf2d/asimage/inc/TASUtils.h create mode 100644 graf2d/asimage/src/TASUtils.cxx diff --git a/graf2d/asimage/CMakeLists.txt b/graf2d/asimage/CMakeLists.txt index 48a3143979bee..74e1c5b7b233c 100644 --- a/graf2d/asimage/CMakeLists.txt +++ b/graf2d/asimage/CMakeLists.txt @@ -34,6 +34,23 @@ if (x11) target_link_libraries(ASImage PRIVATE X11::X11) endif() +ROOT_STANDARD_LIBRARY_PACKAGE(ASImageUtils + NO_INSTALL_HEADERS + HEADERS + TASUtils.h + SOURCES + TASUtils.cxx + LINKDEF + LinkDefUtils.h + DICTIONARY_OPTIONS + -writeEmptyRootPCM + LIBRARIES + libAfterImage + DEPENDENCIES + ASImage +) + + ROOT_STANDARD_LIBRARY_PACKAGE(ASImageGui NO_INSTALL_HEADERS HEADERS diff --git a/graf2d/asimage/inc/LinkDefUtils.h b/graf2d/asimage/inc/LinkDefUtils.h new file mode 100644 index 0000000000000..0abd290f2d1e3 --- /dev/null +++ b/graf2d/asimage/inc/LinkDefUtils.h @@ -0,0 +1,19 @@ +/* @(#)root/asimage:$Id$ */ + +/************************************************************************* + * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms seeg $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TASUtils; + +#endif diff --git a/graf2d/asimage/inc/TASImage.h b/graf2d/asimage/inc/TASImage.h index 269f04cf63495..93d086974b6f1 100644 --- a/graf2d/asimage/inc/TASImage.h +++ b/graf2d/asimage/inc/TASImage.h @@ -29,10 +29,12 @@ class TBrowser; class THashTable; class TTFhandle; class TASPaletteEditor; +class TASUtils; class TASImage : public TImage { friend class TASPaletteEditor; // to access FromGradient method +friend class TASUtils; // to implement gVirtualX-specific methods private: enum { kNoZoom = 0, kZoom = 1, kZoomOps = -1 }; diff --git a/graf2d/asimage/inc/TASUtils.h b/graf2d/asimage/inc/TASUtils.h new file mode 100644 index 0000000000000..fe9f55e558e97 --- /dev/null +++ b/graf2d/asimage/inc/TASUtils.h @@ -0,0 +1,34 @@ +// @(#)root/asimage:$Id$ +// Author: Sergey Linev 16/10/2026 + +/************************************************************************* + * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TASUtils +#define ROOT_TASUtils + +////////////////////////////////////////////////////////////////////////// +// // +// TASUtils // +// // +// Extra functions for TASImage requiring gVirtualX and X11 usage // +// // +////////////////////////////////////////////////////////////////////////// + +#include "Rtypes.h" +#include "GuiTypes.h" + +class TImage; + +class TASUtils { +public: + static Pixmap_t GetX11Pixmap(TImage *img); + static Bool_t FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height); +}; + +#endif diff --git a/graf2d/asimage/src/TASUtils.cxx b/graf2d/asimage/src/TASUtils.cxx new file mode 100644 index 0000000000000..801f31da74dcf --- /dev/null +++ b/graf2d/asimage/src/TASUtils.cxx @@ -0,0 +1,126 @@ +// @(#)root/asimage:$Id$ +// Author: Sergey Linev 16/10/2026 + +/************************************************************************* + * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#include "TASUtils.h" +#include "RConfigure.h" +#include "TASImage.h" +#include "TVirtualX.h" +#include "TSystem.h" +#include "TVirtualPad.h" +#include "TError.h" + +#ifdef WIN32 +#define X_DISPLAY_MISSING 1 +#include "Windows4root.h" +#else +#ifdef R__HAS_COCOA +#define X_DISPLAY_MISSING 1 +#endif +#endif + +#include "afterbase.h" +#include "afterimage.h" +#include "bmp.h" + +const unsigned long kAllPlanes = ~0; + +// Holder of ASVisual instance, destroyed when application closed +class ASVisualHolder { + ASVisual *fVisual = nullptr; + public: + + ASVisual *operator()() + { + if (!fVisual) { +#ifndef WIN32 +#ifndef R__HAS_COCOA + Display *disp = (Display*) gVirtualX->GetDisplay(); + Int_t screen = gVirtualX->GetScreen(); + Int_t depth = gVirtualX->GetDepth(); + Visual *vis = (Visual*) gVirtualX->GetVisual(); + Colormap cmap = (Colormap) gVirtualX->GetColormap(); + + if (vis && cmap) + fVisual = create_asvisual_for_id(disp, screen, depth, XVisualIDFromVisual(vis), cmap, nullptr); +#endif +#endif + if (!fVisual) { + fVisual = create_asvisual(nullptr, 0, 0, nullptr); + fVisual->dpy = nullptr; // fake (not used) + } + } + + return fVisual; + } + + ~ASVisualHolder() + { + if (fVisual) { + destroy_asvisual(fVisual, 0); + fVisual = nullptr; + } + } +}; + + +thread_local ASVisualHolder holder; + +//////////////////////////////////////////////////////////////////////////////// +/// Returns image X11 pixmap. +/// Workrs only on the platforms with support of X11 +/// The pixmap must deleted by user. + +Pixmap_t TASUtils::GetX11Pixmap(TImage *timg) +{ + auto asimg = dynamic_cast(timg); + if (!asimg) { + ::Warning("TASUtils::GetX11Pixmap", "Image not provided"); + return 0; + } + + auto vis = holder(); + + if (!vis) { + ::Warning("TASUtils::GetX11Pixmap", "Visual not initiated"); + return 0; + } + + ASImage *img = asimg->fScaledImage ? asimg->fScaledImage->fImage : asimg->fImage; + + return (Pixmap_t)asimage2pixmap(vis, gVirtualX->GetDefaultRootWindow(), img, nullptr, kTRUE); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Create an image from the given X11 window +/// Can only be used on platforms where X11 is supported + +Bool_t TASUtils::FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height) +{ + auto asimg = dynamic_cast(timg); + if (!asimg) { + ::Warning("TASUtils::FromX11Window", "Image not provided"); + return kFALSE; + } + + auto vis = holder(); + + if (!vis) { + ::Warning("TASUtils::FromX11Window", "Visual not initiated"); + return kFALSE; + } + + asimg->DestroyImage(); + asimg->DestroyScaledImage(); + + asimg->fImage = pixmap2asimage(vis, win, x, y, width, height, kAllPlanes, 0, 0); + + return asimg->fImage != nullptr; +} From eb4b54c63fb89efe60e040239cfb1c79bcdea42c Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 11:14:39 +0200 Subject: [PATCH 04/21] [gui] use new TASUtils methods These are TASImage methods which require gVirtualX and X11, therefore they are extracted --- gui/gui/CMakeLists.txt | 1 + gui/gui/src/TGWindow.cxx | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gui/gui/CMakeLists.txt b/gui/gui/CMakeLists.txt index b25f7c0ddbf8a..303836a2950b7 100644 --- a/gui/gui/CMakeLists.txt +++ b/gui/gui/CMakeLists.txt @@ -204,6 +204,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gui Gpad Graf MathCore + ASImageUtils ROOTNTupleBrowse ) diff --git a/gui/gui/src/TGWindow.cxx b/gui/gui/src/TGWindow.cxx index 4306e9031c835..ab35d66c2d920 100644 --- a/gui/gui/src/TGWindow.cxx +++ b/gui/gui/src/TGWindow.cxx @@ -37,6 +37,7 @@ ROOT GUI Window base class. #include "TError.h" #include "TSystem.h" #include "TImage.h" +#include "TASUtils.h" Int_t TGWindow::fgCounter = 0; @@ -387,7 +388,10 @@ std::unique_ptr TGWindow::CreateImageFromWindow(Drawable_t wid) static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); if (x11) { - img->FromX11Window(wid, 0, 0, w, h); + if (!TASUtils::FromX11Window(img.get(), wid, 0, 0, w, h)) { + ::Error("TGWindow::CreateImageFromWindow", "Fail to create image from X11 window"); + return nullptr; + } } else { unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h); if (!bits) { @@ -415,7 +419,7 @@ Pixmap_t TGWindow::GetImagePixmap(TImage *img) static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); if (x11) - return img->GetX11Pixmap(gVirtualX->GetDefaultRootWindow()); + return TASUtils::GetX11Pixmap(img); auto argb = img->GetArgbArray(); if (!argb) { From d6dbd7012f88035f83d48fdef1b38b08e48c88d6 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 12:31:10 +0200 Subject: [PATCH 05/21] [canvas] move TPadPainter to separate ROOTPadPainter library Main reason that it uses ASImage and TVirtualX and is main source of gVirtualX dependency in Gpad. Plus new ASImageUtils library now implement extra X11-related and gVirtualX-related methods which need to be used by pad painter. Register plugin "native" for pad painter - as it was forseen from the very beginning. TRootCanvas now links to new library and returns instance of TPadPainter. --- .../TVirtualPadPainter/P020_TPadPainter.C | 5 +++ graf2d/CMakeLists.txt | 1 + graf2d/asimage/CMakeLists.txt | 2 +- graf2d/gpad/CMakeLists.txt | 2 -- graf2d/gpad/inc/LinkDef.h | 1 - graf2d/gpad/src/TCanvas.cxx | 16 +++++----- graf2d/padpainter/CMakeLists.txt | 31 +++++++++++++++++++ graf2d/padpainter/inc/LinkDef.h | 19 ++++++++++++ graf2d/{gpad => padpainter}/inc/TPadPainter.h | 0 .../{gpad => padpainter}/src/TPadPainter.cxx | 16 +++++++--- gui/gui/CMakeLists.txt | 1 + gui/gui/inc/TRootCanvas.h | 2 ++ gui/gui/src/TRootCanvas.cxx | 11 ++++++- 13 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 etc/plugins/TVirtualPadPainter/P020_TPadPainter.C create mode 100644 graf2d/padpainter/CMakeLists.txt create mode 100644 graf2d/padpainter/inc/LinkDef.h rename graf2d/{gpad => padpainter}/inc/TPadPainter.h (100%) rename graf2d/{gpad => padpainter}/src/TPadPainter.cxx (98%) diff --git a/etc/plugins/TVirtualPadPainter/P020_TPadPainter.C b/etc/plugins/TVirtualPadPainter/P020_TPadPainter.C new file mode 100644 index 0000000000000..9e8e2ba4ee369 --- /dev/null +++ b/etc/plugins/TVirtualPadPainter/P020_TPadPainter.C @@ -0,0 +1,5 @@ +void P020_TPadPainter() +{ + gPluginMgr->AddHandler("TVirtualPadPainter", "native", "TPadPainter", + "ROOTPadPainter", "TPadPainter()"); +} diff --git a/graf2d/CMakeLists.txt b/graf2d/CMakeLists.txt index 3fcb56483a917..8d993e59f9682 100644 --- a/graf2d/CMakeLists.txt +++ b/graf2d/CMakeLists.txt @@ -20,6 +20,7 @@ endif() if(asimage) add_subdirectory(asimage) # special CMakeLists.txt endif() +add_subdirectory(padpainter) if(gviz) add_subdirectory(gviz) endif() diff --git a/graf2d/asimage/CMakeLists.txt b/graf2d/asimage/CMakeLists.txt index 74e1c5b7b233c..6ef9aa0e6007e 100644 --- a/graf2d/asimage/CMakeLists.txt +++ b/graf2d/asimage/CMakeLists.txt @@ -48,9 +48,9 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ASImageUtils libAfterImage DEPENDENCIES ASImage + Gpad ) - ROOT_STANDARD_LIBRARY_PACKAGE(ASImageGui NO_INSTALL_HEADERS HEADERS diff --git a/graf2d/gpad/CMakeLists.txt b/graf2d/gpad/CMakeLists.txt index 1a2e979e53138..96e3d868fe8da 100644 --- a/graf2d/gpad/CMakeLists.txt +++ b/graf2d/gpad/CMakeLists.txt @@ -25,7 +25,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gpad TInspectCanvas.h TPad.h TPadPainterBase.h - TPadPainter.h TPadPainterPS.h TPaveClass.h TRatioPlot.h @@ -48,7 +47,6 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gpad src/TInspectCanvas.cxx src/TPad.cxx src/TPadPainterBase.cxx - src/TPadPainter.cxx src/TPadPainterPS.cxx src/TPaveClass.cxx src/TRatioPlot.cxx diff --git a/graf2d/gpad/inc/LinkDef.h b/graf2d/gpad/inc/LinkDef.h index eeb1d68c513ff..956f3aed9f08e 100644 --- a/graf2d/gpad/inc/LinkDef.h +++ b/graf2d/gpad/inc/LinkDef.h @@ -32,7 +32,6 @@ #pragma link C++ class TView+; #pragma link C++ class TViewer3DPad; #pragma link C++ class TPadPainterBase; -#pragma link C++ class TPadPainter; #pragma link C++ class TPadPainterPS; #pragma link C++ class TRatioPlot+; diff --git a/graf2d/gpad/src/TCanvas.cxx b/graf2d/gpad/src/TCanvas.cxx index d046ecba0a8ff..f5ecc92314ec2 100644 --- a/graf2d/gpad/src/TCanvas.cxx +++ b/graf2d/gpad/src/TCanvas.cxx @@ -36,7 +36,6 @@ #include "TObjArray.h" #include "TVirtualPadEditor.h" #include "TVirtualViewer3D.h" -#include "TPadPainter.h" #include "TPadPainterPS.h" #include "TVirtualGL.h" #include "TVirtualPS.h" @@ -2659,18 +2658,21 @@ void TCanvas::CreatePainter() { //Even for batch mode painter is still required, just to delegate //some calls to batch "virtual X". - if (!UseGL() || fBatch || IsWeb()) { - fPainter = nullptr; - if (fCanvasImp) fPainter = fCanvasImp->CreatePadPainter(); - if (!fPainter) fPainter = new TPadPainter; // Do not need plugin manager for this! - } else { + + fPainter = nullptr; + if (UseGL() && !IsBatch() && !IsWeb()) { fPainter = TVirtualPadPainter::PadPainter("gl"); if (!fPainter) { Error("CreatePainter", "GL Painter creation failed! Will use default!"); - fPainter = new TPadPainter; fUseGL = kFALSE; } } + if (!fPainter && fCanvasImp) + fPainter = fCanvasImp->CreatePadPainter(); + if (!fPainter) + fPainter = TVirtualPadPainter::PadPainter("native"); + if (!fPainter) + Error("CreatePainter", "Fail to create any pad painter"); } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/padpainter/CMakeLists.txt b/graf2d/padpainter/CMakeLists.txt new file mode 100644 index 0000000000000..2553f0411cda1 --- /dev/null +++ b/graf2d/padpainter/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. +# All rights reserved. +# +# For the licensing terms see $ROOTSYS/LICENSE. +# For the list of contributors see $ROOTSYS/README/CREDITS. + +############################################################################ +# CMakeLists.txt file for building ROOT graf2d/padpainter package +# @author Sergey Linev, GSI +############################################################################ + +ROOT_STANDARD_LIBRARY_PACKAGE(ROOTPadPainter + NO_INSTALL_HEADERS + HEADERS + TPadPainter.h + SOURCES + TPadPainter.cxx + DICTIONARY_OPTIONS + -writeEmptyRootPCM + DEPENDENCIES + Gpad +) + + +if(asimage) + target_link_libraries(ROOTPadPainter PUBLIC ASImageUtils) + target_compile_definitions(ROOTPadPainter PRIVATE USE_ASIMAGEUTILS) +endif() + + +ROOT_INSTALL_HEADERS() diff --git a/graf2d/padpainter/inc/LinkDef.h b/graf2d/padpainter/inc/LinkDef.h new file mode 100644 index 0000000000000..5649423ad6fe5 --- /dev/null +++ b/graf2d/padpainter/inc/LinkDef.h @@ -0,0 +1,19 @@ +/* @(#)root/padpainter:$Id$ */ + +/************************************************************************* + * Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms seeg $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifdef __CLING__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class TPadPainter; + +#endif diff --git a/graf2d/gpad/inc/TPadPainter.h b/graf2d/padpainter/inc/TPadPainter.h similarity index 100% rename from graf2d/gpad/inc/TPadPainter.h rename to graf2d/padpainter/inc/TPadPainter.h diff --git a/graf2d/gpad/src/TPadPainter.cxx b/graf2d/padpainter/src/TPadPainter.cxx similarity index 98% rename from graf2d/gpad/src/TPadPainter.cxx rename to graf2d/padpainter/src/TPadPainter.cxx index aa0d87d6db32e..8e38f328d490f 100644 --- a/graf2d/gpad/src/TPadPainter.cxx +++ b/graf2d/padpainter/src/TPadPainter.cxx @@ -25,6 +25,10 @@ #include "TMath.h" #include "TPad.h" +#ifdef USE_ASIMAGEUTILS +#include "TASUtils.h" +#endif + namespace { //Typedef is fine, but let's pretend we look cool and modern: @@ -594,10 +598,15 @@ Bool_t TPadPainter::FillImageFromPad(TImage *image, TVirtualPad *pad) const Int_t wid = (pad == pad->GetCanvas()) ? pad->GetCanvasID() : pad->GetPixmapID(); gVirtualX->SelectWindow(wid); - Window_t wd = (Window_t)gVirtualX->GetCurrentWindow(); + Window_t wd = gVirtualX->GetCurrentWindow(); - if (IsX11()) { //use built-in optimized version - image->FromX11Window(wd, 0, 0, width, height); + if (IsX11()) { +#ifdef USE_ASIMAGEUTILS + if (!TASUtils::FromX11Window(image, gVirtualX->GetCurrentWindow(), 0, 0, pad->GetPadWidth(), pad->GetPadHeight())) + return kFALSE; +#else + return kFALSE; +#endif } else { unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, width, height); if (!bits) @@ -610,7 +619,6 @@ Bool_t TPadPainter::FillImageFromPad(TImage *image, TVirtualPad *pad) const return image->IsValid(); } - //Aux. private functions. namespace { diff --git a/gui/gui/CMakeLists.txt b/gui/gui/CMakeLists.txt index 303836a2950b7..1bf64a8f34e2f 100644 --- a/gui/gui/CMakeLists.txt +++ b/gui/gui/CMakeLists.txt @@ -205,6 +205,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gui Graf MathCore ASImageUtils + ROOTPadPainter ROOTNTupleBrowse ) diff --git a/gui/gui/inc/TRootCanvas.h b/gui/gui/inc/TRootCanvas.h index c151bc456d0a8..d01b18ff1d7ca 100644 --- a/gui/gui/inc/TRootCanvas.h +++ b/gui/gui/inc/TRootCanvas.h @@ -99,6 +99,8 @@ friend class TRootContainer; Atom_t HandleDNDEnter(Atom_t * typelist) override; Bool_t HandleDNDLeave() override; + TVirtualPadPainter *CreatePadPainter() override; + public: TRootCanvas(TCanvas *c = nullptr, const char *name = "ROOT Canvas", UInt_t width = 500, UInt_t height = 300); TRootCanvas(TCanvas *c, const char *name, Int_t x, Int_t y, UInt_t width, UInt_t height); diff --git a/gui/gui/src/TRootCanvas.cxx b/gui/gui/src/TRootCanvas.cxx index 6eda74b953c29..82485e25e0f5b 100644 --- a/gui/gui/src/TRootCanvas.cxx +++ b/gui/gui/src/TRootCanvas.cxx @@ -49,6 +49,7 @@ drawing area. The widgets used are the new native ROOT GUI widgets. #include "TMath.h" #include #include "TGDockableFrame.h" +#include "TPadPainter.h" #include "TG3DLine.h" #include "TGToolBar.h" @@ -57,6 +58,7 @@ drawing area. The widgets used are the new native ROOT GUI widgets. #include "TRootControlBar.h" #include "TGuiBuilder.h" #include "TImage.h" +#include "TASUtils.h" #include "TError.h" #include "TGDNDManager.h" #include "TBufferFile.h" @@ -2216,7 +2218,6 @@ void TRootCanvas::UpdateDisplay(Int_t mode, Bool_t sleep) gSystem->Sleep(30); } - //////////////////////////////////////////////////////////////////////////////// /// Save a canvas container as a C++ statement(s) on output stream out. @@ -2231,3 +2232,11 @@ void TRootContainer::SavePrimitive(std::ostream &out, Option_t * /*= ""*/) } +//////////////////////////////////////////////////////////////////////////////// +/// Create pad painter instance + +TVirtualPadPainter *TRootCanvas::CreatePadPainter() +{ + return new TPadPainter(); +} + From 58ed39e4a7b08312c14319c93bc62efbcc4ca7b4 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 16:21:29 +0200 Subject: [PATCH 06/21] [roottest] adjust several ref files after new libs reorganisation Default canvas no longer created automatically but only when obj->Draw() is invoked --- roottest/root/treeformula/string/execAliasString.ref | 2 +- roottest/root/treeproxy/execsearch.ref | 2 +- roottest/root/treeproxy/valdim3.ref | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/roottest/root/treeformula/string/execAliasString.ref b/roottest/root/treeformula/string/execAliasString.ref index ddc2ca9f31a38..bd4733bc5aed1 100644 --- a/roottest/root/treeformula/string/execAliasString.ref +++ b/roottest/root/treeformula/string/execAliasString.ref @@ -1,11 +1,11 @@ Processing execAliasString.C... -Info in : created default TCanvas with name c1 ************************************** * Row * name.name * count.count * ************************************** * 0 * 16A * 3 * * 1 * 17B * 2 * ************************************** +Info in : created default TCanvas with name c1 *********************************** * Row * first?name:"not f... * *********************************** diff --git a/roottest/root/treeproxy/execsearch.ref b/roottest/root/treeproxy/execsearch.ref index 16aaf476e1419..25dd2554f9997 100644 --- a/roottest/root/treeproxy/execsearch.ref +++ b/roottest/root/treeproxy/execsearch.ref @@ -2,7 +2,7 @@ Processing execsearch.C... Warning in : no dictionary for class ND::P0D::NueEvtInfo is available Warning in : no dictionary for class ND::P0D::TVertex is available Warning in : no dictionary for class ND::P0D::TPID is available -Info in : created default TCanvas with name c1 trajPos.fP.fX[1]=635.86 trajPos.fP[1].fX=635.86 trajPos[1].fP.fX=635.86 +Info in : created default TCanvas with name c1 diff --git a/roottest/root/treeproxy/valdim3.ref b/roottest/root/treeproxy/valdim3.ref index f49e2513144c9..0f585d9a53fe3 100644 --- a/roottest/root/treeproxy/valdim3.ref +++ b/roottest/root/treeproxy/valdim3.ref @@ -1,5 +1,4 @@ Processing runvaldim3.C... -Info in : created default TCanvas with name c1 ntracks = 2 trs[0].a = 0 trs[0].bb[0] = 0.000000 @@ -60,3 +59,4 @@ a[1][2][0] = 120 a[1][2][1] = 121 a[1][2][2] = 122 a[1][2][3] = 123 +Info in : created default TCanvas with name c1 From f83e544142cdae5297e9228187199e75c4424feb Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 12:50:15 +0200 Subject: [PATCH 07/21] [image] remove X11-specific methods from API These methods were introduced recently and replaced by special TASUtils methods. Only there X11 and gVirtualX should be used --- graf2d/asimage/inc/TASImage.h | 2 -- graf2d/asimage/src/TASImage.cxx | 44 +++++++-------------------------- graf2d/graf/inc/TImage.h | 4 --- 3 files changed, 9 insertions(+), 41 deletions(-) diff --git a/graf2d/asimage/inc/TASImage.h b/graf2d/asimage/inc/TASImage.h index 93d086974b6f1..405d1f8f8ffd0 100644 --- a/graf2d/asimage/inc/TASImage.h +++ b/graf2d/asimage/inc/TASImage.h @@ -112,7 +112,6 @@ friend class TASUtils; // to implement gVirtualX-specific methods void FromBitmap(const UChar_t *buf, UInt_t width, UInt_t height) override; void FromPad(TVirtualPad *pad, Int_t x = 0, Int_t y = 0, UInt_t w = 0, UInt_t h = 0) override; - void FromX11Window(Window_t win , Int_t x, Int_t y, Int_t width, Int_t height) override; void FromWindow(Drawable_t wid, Int_t x = 0, Int_t y = 0, UInt_t w = 0, UInt_t h = 0) override; void FromGLBuffer(UChar_t *buf, UInt_t width, UInt_t height) override; @@ -201,7 +200,6 @@ friend class TASUtils; // to implement gVirtualX-specific methods ASImage *GetImage() const { return fImage; } void SetImage(ASImage *image) { DestroyImage(); fImage = image; } TImage *GetScaledImage() const override { return fScaledImage; } - Pixmap_t GetX11Pixmap(Window_t root_window) override; Pixmap_t GetPixmap() override; Bool_t GetMaskBits(UInt_t &width, UInt_t &height, std::vector &bits) override; Pixmap_t GetMask() override; diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index 27d26c8dcdd7b..f22bfddba7137 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -1076,23 +1076,6 @@ void TASImage::SetImage(const TVectorD &imageData, UInt_t width, TImagePalette * imageData.GetNoElements() / width, palette); } -//////////////////////////////////////////////////////////////////////////////// -/// Create an image from the given X11 window -/// Can only be used on platforms where X11 is supported - -void TASImage::FromX11Window(Window_t win, Int_t x, Int_t y, Int_t width, Int_t height) -{ - DestroyImage(); - DestroyScaledImage(); - - if (!InitVisual()) { - Warning("FromX11Window", "Visual not initiated"); - return; - } - - fImage = pixmap2asimage(fgVisual, win, x, y, width, height, kAllPlanes, 0, 0); -} - //////////////////////////////////////////////////////////////////////////////// /// Create an image from the given pad, afterwards this image can be /// saved in any of the supported image formats. @@ -2165,33 +2148,24 @@ void TASImage::StartPaletteEditor() //////////////////////////////////////////////////////////////////////////////// -/// Returns image X11 pixmap. -/// Workrs only on the platforms with support of X11 +/// DEPRECATED. Method left for backward compatibility and will be removed in ROOT7! +/// Returns image pixmap. /// The pixmap must deleted by user. -Pixmap_t TASImage::GetX11Pixmap(Window_t root_window) +Pixmap_t TASImage::GetPixmap() { if (!InitVisual()) { - Warning("GetX11Pixmap", "Visual not initiated"); + Warning("GetPixmap", "Visual not initiated"); return 0; } - ASImage *img = fScaledImage ? fScaledImage->fImage : fImage; - - return (Pixmap_t)asimage2pixmap(fgVisual, root_window, img, nullptr, kTRUE); -} - -//////////////////////////////////////////////////////////////////////////////// -/// DEPRECATED. Method left for backward compatibility and will be removed in ROOT7! -/// Returns image pixmap. -/// The pixmap must deleted by user. - -Pixmap_t TASImage::GetPixmap() -{ static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); - if (x11) - return GetX11Pixmap(gVirtualX->GetDefaultRootWindow()); + if (x11) { + ASImage *img = fScaledImage ? fScaledImage->fImage : fImage; + + return (Pixmap_t)asimage2pixmap(fgVisual, gVirtualX->GetDefaultRootWindow(), img, nullptr, kTRUE); + } auto argb = GetArgbArray(); if (!argb) { diff --git a/graf2d/graf/inc/TImage.h b/graf2d/graf/inc/TImage.h index 59b2af21a8553..29f1fbe47f958 100644 --- a/graf2d/graf/inc/TImage.h +++ b/graf2d/graf/inc/TImage.h @@ -129,9 +129,6 @@ friend TImage operator/(const TImage &i1, const TImage &s2); // Create an image from the given pad. (See TASImage::FromPad) virtual void FromPad(TVirtualPad * /*pad*/, Int_t /*x*/ = 0, Int_t /*y*/ = 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) {} - // Create an image from X11 window handle. (See TASImage::FromX11Window) - virtual void FromX11Window(Window_t /* win */ , Int_t /* x */, Int_t /* y */, Int_t /* width */, Int_t /* height */) {} - // Create an image from gVirtualX window. (See TASImage::FromWindow) virtual void R__DEPRECATED(7,00, "Use TGWindow::CreateImageFromWindow instead") FromWindow(Drawable_t /*wid*/, Int_t /*x*/ = 0, Int_t /*y*/ = 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) {} @@ -252,7 +249,6 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual TArrayL *GetPixels(Int_t /*x*/= 0, Int_t /*y*/= 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) { return nullptr; } virtual TArrayD *GetArray(UInt_t /*w*/ = 0, UInt_t /*h*/ = 0, TImagePalette * = gWebImagePalette) { return nullptr; } - virtual Pixmap_t GetX11Pixmap(Window_t /* root_window */) { return 0; } virtual Pixmap_t R__DEPRECATED(7,00, "Use TGWindow::GetImagePixmap instead") GetPixmap() { return 0; } virtual Bool_t GetMaskBits(UInt_t & /* width */, UInt_t & /* height */, std::vector & /* bits */) { return kFALSE; } virtual Pixmap_t R__DEPRECATED(7,00, "Use TGWindow::GetImageMask instead") GetMask() { return 0; } From 86d1ceb3c15d366839e8421cd45c206f6811cb49 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 13:56:04 +0200 Subject: [PATCH 08/21] [asutils] provide FromPixmap method Create TASImage and fill content with gVirtualX pixmap data Use also speicalized X11 method - when runs on correspondent platform Replacement for TASImage::SetImage() functionality --- graf2d/asimage/inc/TASUtils.h | 6 ++- graf2d/asimage/src/TASUtils.cxx | 93 ++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 26 deletions(-) diff --git a/graf2d/asimage/inc/TASUtils.h b/graf2d/asimage/inc/TASUtils.h index fe9f55e558e97..4dd4941344a71 100644 --- a/graf2d/asimage/inc/TASUtils.h +++ b/graf2d/asimage/inc/TASUtils.h @@ -22,13 +22,15 @@ #include "Rtypes.h" #include "GuiTypes.h" +#include class TImage; class TASUtils { public: - static Pixmap_t GetX11Pixmap(TImage *img); - static Bool_t FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height); + static Pixmap_t GetX11Pixmap(TImage *timg); + static Bool_t FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height); + static std::unique_ptr FromPixmap(Pixmap_t pxm, Pixmap_t mask); }; #endif diff --git a/graf2d/asimage/src/TASUtils.cxx b/graf2d/asimage/src/TASUtils.cxx index 801f31da74dcf..6b8b0372233d6 100644 --- a/graf2d/asimage/src/TASUtils.cxx +++ b/graf2d/asimage/src/TASUtils.cxx @@ -30,36 +30,37 @@ #include "afterimage.h" #include "bmp.h" +#ifndef X_DISPLAY_MISSING const unsigned long kAllPlanes = ~0; +#endif // Holder of ASVisual instance, destroyed when application closed class ASVisualHolder { - ASVisual *fVisual = nullptr; - public: - - ASVisual *operator()() - { - if (!fVisual) { -#ifndef WIN32 -#ifndef R__HAS_COCOA - Display *disp = (Display*) gVirtualX->GetDisplay(); - Int_t screen = gVirtualX->GetScreen(); - Int_t depth = gVirtualX->GetDepth(); - Visual *vis = (Visual*) gVirtualX->GetVisual(); - Colormap cmap = (Colormap) gVirtualX->GetColormap(); - - if (vis && cmap) - fVisual = create_asvisual_for_id(disp, screen, depth, XVisualIDFromVisual(vis), cmap, nullptr); -#endif + ASVisual *fVisual = nullptr; + +public: + + ASVisual *operator()() + { +#ifndef X_DISPLAY_MISSING + if (!fVisual) { + Display *disp = (Display*) gVirtualX->GetDisplay(); + Int_t screen = gVirtualX->GetScreen(); + Int_t depth = gVirtualX->GetDepth(); + Visual *vis = (Visual*) gVirtualX->GetVisual(); + Colormap cmap = (Colormap) gVirtualX->GetColormap(); + + if (vis && cmap) + fVisual = create_asvisual_for_id(disp, screen, depth, XVisualIDFromVisual(vis), cmap, nullptr); + } #endif - if (!fVisual) { - fVisual = create_asvisual(nullptr, 0, 0, nullptr); - fVisual->dpy = nullptr; // fake (not used) - } - } + if (!fVisual) { + fVisual = create_asvisual(nullptr, 0, 0, nullptr); + fVisual->dpy = nullptr; // fake (not used) + } - return fVisual; - } + return fVisual; + } ~ASVisualHolder() { @@ -124,3 +125,47 @@ Bool_t TASUtils::FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int return asimg->fImage != nullptr; } + +//////////////////////////////////////////////////////////////////////////////// +/// Set image data from pixmap. + +std::unique_ptr TASUtils::FromPixmap(Pixmap_t pxm, Pixmap_t mask) +{ + auto asimg = std::make_unique(); + + Int_t xy; + UInt_t w, h; + gVirtualX->GetWindowSize(pxm, xy, xy, w, h); + + asimg->SetName(TString::Format("img_%dx%d",w, h)); + + if (gVirtualX->InheritsFrom("TGX11")) { //use built-in optimized version + auto vis = holder(); + + if (!vis) { + ::Warning("TASUtils::FromPixmap", "Visual not initiated"); + return nullptr; + } + +#ifndef X_DISPLAY_MISSING + asimg->fImage = picture2asimage(vis, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0); +#endif + } else { + unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h); + if (!bits) // error + return nullptr; + + unsigned char *mask_bits = mask ? gVirtualX->GetColorBits(mask, 0, 0, w, h) : nullptr; + + asimg->fImage = bitmap2asimage(bits, w, h, 0, mask_bits); + + if (mask_bits) + delete [] mask_bits; + delete [] bits; + } + + if (!asimg->IsValid()) + return nullptr; + + return asimg; +} From 1e5879bb999a533d442311d02beb8f040d8ede8b Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 13:57:30 +0200 Subject: [PATCH 09/21] [gui] use TASUtils::FromPixmap in gui classes Typically used generate different icons. Adjust methods where pic->SetImage(pixmap, mask) was used. Use std::unique_ptr in all touched methods to ensure ownership --- gui/gui/src/TGButton.cxx | 31 ++++++++++++++----------------- gui/gui/src/TGFSContainer.cxx | 33 +++++++++++++-------------------- gui/gui/src/TGFileBrowser.cxx | 19 +++++++++---------- gui/gui/src/TGScrollBar.cxx | 21 +++++++++------------ gui/gui/src/TGSlider.cxx | 23 ++++++++++------------- 5 files changed, 55 insertions(+), 72 deletions(-) diff --git a/gui/gui/src/TGButton.cxx b/gui/gui/src/TGButton.cxx index ede2fe0b66382..610fd7241af1e 100644 --- a/gui/gui/src/TGButton.cxx +++ b/gui/gui/src/TGButton.cxx @@ -143,6 +143,7 @@ by calling the SetSplit(Bool_t) method. #include "TGResourcePool.h" #include "TSystem.h" #include "TImage.h" +#include "TASUtils.h" #include "TEnv.h" #include "TClass.h" #include "TGMenu.h" @@ -1101,26 +1102,22 @@ void TGPictureButton::DoRedraw() void TGPictureButton::CreateDisabledPicture() { - TImage *img = TImage::Create(); - if (!img) return; - TImage *img2 = TImage::Create(); - if (!img2) { - if (img) delete img; + std::unique_ptr img2(TImage::Create()); + if (!img2) return; - } TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0"); img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight()); - img->SetImage(fPic->GetPicture(), fPic->GetMask()); - Pixmap_t mask = GetImageMask(img); - img2->Merge(img, "overlay"); - - TString name = "disbl_"; - name += fPic->GetName(); - fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2), - mask); - fOwnDisabledPic = kTRUE; - delete img; - delete img2; + auto img = TASUtils::FromPixmap(fPic->GetPicture(), fPic->GetMask()); + if (img) { + Pixmap_t mask = GetImageMask(img.get()); + img2->Merge(img.get(), "overlay"); + + TString name = "disbl_"; + name += fPic->GetName(); + fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), + mask); + fOwnDisabledPic = kTRUE; + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/gui/gui/src/TGFSContainer.cxx b/gui/gui/src/TGFSContainer.cxx index 3d2e23578fd3c..e340fc78032d2 100644 --- a/gui/gui/src/TGFSContainer.cxx +++ b/gui/gui/src/TGFSContainer.cxx @@ -54,6 +54,7 @@ Utility class used by the file selection dialog (TGFSDialog). #include "TRemoteObject.h" #include "TBufferFile.h" #include "TImage.h" +#include "TASUtils.h" #include #include @@ -692,36 +693,28 @@ void TGFileContainer::GetFilePictures(const TGPicture **pic, } } if (is_link) { - TImage *img1, *img2; if (*pic && *lpic) { - TString lnk_name; - img1 = TImage::Create(); + auto img1 = TASUtils::FromPixmap((*pic)->GetPicture(), (*pic)->GetMask()); if (img1) { - img1->SetImage(((const TGPicture *)*pic)->GetPicture(), - ((const TGPicture *)*pic)->GetMask()); - img2 = TImage::Open("slink_t.xpm"); - if (img2) img1->Merge(img2); - lnk_name = ((const TGPicture *)*pic)->GetName(); + std::unique_ptr img2(TImage::Open("slink_t.xpm")); + if (img2) + img1->Merge(img2.get()); + TString lnk_name = (*pic)->GetName(); lnk_name.Prepend("lnk_"); *pic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(), - GetImagePixmap(img1), GetImageMask(img1)); + GetImagePixmap(img1.get()), GetImageMask(img1.get())); fCleanups->Add(((TObject *)*pic)); - if (img2) delete img2; - delete img1; } - img1 = TImage::Create(); + img1 = TASUtils::FromPixmap((*lpic)->GetPicture(), (*lpic)->GetMask()); if (img1) { - img1->SetImage(((const TGPicture *)*lpic)->GetPicture(), - ((const TGPicture *)*lpic)->GetMask()); - img2 = TImage::Open("slink_s.xpm"); - if (img2) img1->Merge(img2); - lnk_name = ((const TGPicture *)*lpic)->GetName(); + std::unique_ptr img2(TImage::Open("slink_s.xpm")); + if (img2) + img1->Merge(img2.get()); + TString lnk_name = (*lpic)->GetName(); lnk_name.Prepend("lnk_"); *lpic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(), - GetImagePixmap(img1), GetImageMask(img1)); + GetImagePixmap(img1.get()), GetImageMask(img1.get())); fCleanups->Add(((TObject *)*lpic)); - if (img2) delete img2; - delete img1; } } else { diff --git a/gui/gui/src/TGFileBrowser.cxx b/gui/gui/src/TGFileBrowser.cxx index b2aa57e018d42..162dbc992f936 100644 --- a/gui/gui/src/TGFileBrowser.cxx +++ b/gui/gui/src/TGFileBrowser.cxx @@ -30,6 +30,7 @@ #include "TRegexp.h" #include "TEnv.h" #include "TImage.h" +#include "TASUtils.h" #include "TBrowser.h" #include "TRemoteObject.h" #include "TKey.h" @@ -1161,18 +1162,16 @@ static Bool_t IsTextFile(const char *candidate) static const TGPicture *MakeLinkPic(const TGPicture *pic) { if (pic) { - auto img1 = TImage::Create(); - if (!img1) return pic; - img1->SetImage(((const TGPicture *)pic)->GetPicture(), - ((const TGPicture *)pic)->GetMask()); - auto img2 = TImage::Open("slink_t.xpm"); - if (img2) img1->Merge(img2); - TString lnk_name = ((const TGPicture *)pic)->GetName(); + auto img1 = TASUtils::FromPixmap(pic->GetPicture(), pic->GetMask()); + if (!img1) + return pic; + std::unique_ptr img2(TImage::Open("slink_t.xpm")); + if (img2) + img1->Merge(img2.get()); + TString lnk_name = pic->GetName(); lnk_name.Prepend("lnk_"); auto merged = gClient->GetPicturePool()->GetPicture(lnk_name.Data(), - TGWindow::GetImagePixmap(img1), TGWindow::GetImageMask(img1)); - if (img2) delete img2; - delete img1; + TGWindow::GetImagePixmap(img1.get()), TGWindow::GetImageMask(img1.get())); return merged; } return pic; diff --git a/gui/gui/src/TGScrollBar.cxx b/gui/gui/src/TGScrollBar.cxx index 707e145e7ea3a..593587baa4f08 100644 --- a/gui/gui/src/TGScrollBar.cxx +++ b/gui/gui/src/TGScrollBar.cxx @@ -51,6 +51,7 @@ kC_VSCROLL, kSB_SLIDERTRACK, position, 0 #include "TGResourcePool.h" #include "TGPicture.h" #include "TImage.h" +#include "TASUtils.h" #include "TSystem.h" #include "TTimer.h" #include "TEnv.h" @@ -157,25 +158,21 @@ void TGScrollBarElement::SetEnabled(Bool_t on) SetState(kButtonDisabled); if (!fPicD) { - TImage *img = TImage::Create(); - if (!img) return; - TImage *img2 = TImage::Create(); - if (!img2) { - if (img) delete img; + std::unique_ptr img2(TImage::Create()); + if (!img2) return; - } TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0"); img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight()); - img->SetImage(fPicN->GetPicture(), fPicN->GetMask()); - Pixmap_t mask = GetImageMask(img); - img2->Merge(img, "overlay"); + auto img = TASUtils::FromPixmap(fPicN->GetPicture(), fPicN->GetMask()); + if (!img) + return; + Pixmap_t mask = GetImageMask(img.get()); + img2->Merge(img.get(), "overlay"); TString name = "disbl_"; name += fPic->GetName(); - fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2), + fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), mask); - delete img; - delete img2; } fPic = fPicD; } diff --git a/gui/gui/src/TGSlider.cxx b/gui/gui/src/TGSlider.cxx index 5ed270c90188e..529b238b37750 100644 --- a/gui/gui/src/TGSlider.cxx +++ b/gui/gui/src/TGSlider.cxx @@ -64,6 +64,7 @@ Releasing the mouse will generate the event: #include "TGSlider.h" #include "TGPicture.h" #include "TImage.h" +#include "TASUtils.h" #include "TEnv.h" #include "TVirtualX.h" @@ -129,25 +130,21 @@ void TGSlider::CreateDisabledPicture() { if (!fSliderPic) return; - TImage *img = TImage::Create(); - if (!img) return; - TImage *img2 = TImage::Create(); - if (!img2) { - if (img) delete img; + std::unique_ptr img2(TImage::Create()); + if (!img2) return; - } TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0"); img2->FillRectangle(back.Data(), 0, 0, fSliderPic->GetWidth(), fSliderPic->GetHeight()); - img->SetImage(fSliderPic->GetPicture(), fSliderPic->GetMask()); - Pixmap_t mask = GetImageMask(img); - img2->Merge(img, "overlay"); + auto img = TASUtils::FromPixmap(fSliderPic->GetPicture(), fSliderPic->GetMask()); + if (!img) + return; + Pixmap_t mask = GetImageMask(img.get()); + img2->Merge(img.get(), "overlay"); TString name = "disbl_"; - name += fSliderPic->GetName(); - fDisabledPic = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2), mask); - delete img; - delete img2; + name.Append(fSliderPic->GetName()); + fDisabledPic = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), mask); } //////////////////////////////////////////////////////////////////////////////// From abaee8a1f8c7ca852bf74a5fdd4e8934d7ec97ff Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 14:03:16 +0200 Subject: [PATCH 10/21] [image] mark SetImage(pixmap, mask) as deprecated Functionality provided in TASUtils and TGWindow classes Method will be removed in ROOT7 --- graf2d/asimage/src/TASImage.cxx | 9 ++++++--- graf2d/graf/inc/TImage.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index f22bfddba7137..b9992487e900f 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -2247,6 +2247,7 @@ Pixmap_t TASImage::GetMask() } //////////////////////////////////////////////////////////////////////////////// +/// DEPRECATED. Method left for backward compatibility and will be removed in ROOT7! /// Create image from pixmap. void TASImage::SetImage(Pixmap_t pxm, Pixmap_t mask) @@ -2263,10 +2264,10 @@ void TASImage::SetImage(Pixmap_t pxm, Pixmap_t mask) UInt_t w, h; gVirtualX->GetWindowSize(pxm, xy, xy, w, h); - if (fName.IsNull()) fName.Form("img_%dx%d",w, h); + if (fName.IsNull()) + fName.Form("img_%dx%d",w, h); - static int x11 = -1; - if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11"); + static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); if (x11) { //use built-in optimized version fImage = picture2asimage(fgVisual, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0); @@ -6297,6 +6298,7 @@ void TASImage::Gray(Bool_t on) } //////////////////////////////////////////////////////////////////////////////// +/// DEPRECATED. Method left for backward compatibility and will be removed in ROOT7! /// Create an image (screenshot) from specified window. void TASImage::FromWindow(Drawable_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h) @@ -6348,6 +6350,7 @@ void TASImage::FromWindow(Drawable_t wid, Int_t x, Int_t y, UInt_t w, UInt_t h) } //////////////////////////////////////////////////////////////////////////////// +/// DEPRECATED. Method left for backward compatibility and will be removed in ROOT7! /// Creates an image (screenshot) from a RGBA buffer provided by GL. void TASImage::FromGLBuffer(UChar_t* buf, UInt_t w, UInt_t h) diff --git a/graf2d/graf/inc/TImage.h b/graf2d/graf/inc/TImage.h index 29f1fbe47f958..cf9dafd103539 100644 --- a/graf2d/graf/inc/TImage.h +++ b/graf2d/graf/inc/TImage.h @@ -120,7 +120,7 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual void SetImage(const Double_t * /*imageData*/, UInt_t /*width*/, UInt_t /*height*/, TImagePalette * /*palette*/ = nullptr) {} virtual void SetImage(const TArrayD & /*imageData*/, UInt_t /*width*/, TImagePalette * /*palette*/ = nullptr) {} virtual void SetImage(const TVectorD & /*imageData*/, UInt_t /*width*/, TImagePalette * /*palette*/ = nullptr) {} - virtual void SetImage(Pixmap_t /*pxm*/, Pixmap_t /*mask*/ = 0) {} + virtual void R__DEPRECATED(7,00, "Use TASUtil::FromPixmap instead") SetImage(Pixmap_t /*pxm*/, Pixmap_t /*mask*/ = 0) {} // Create an image from bitmap. (See TASImage::FromBitmap) From a2b15d2176d3d81847fe5b2b1a5ccfd807be603e Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 15:52:56 +0200 Subject: [PATCH 11/21] [asutils] provide PaintImage method It should replace TASImage::PaintImage(), but without selection of paint region. Therefore only full image can be painted Use holder object to preserve created GC context, will be deleted at the end --- graf2d/asimage/inc/TASUtils.h | 1 + graf2d/asimage/src/TASUtils.cxx | 84 ++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/graf2d/asimage/inc/TASUtils.h b/graf2d/asimage/inc/TASUtils.h index 4dd4941344a71..c14300e81d06a 100644 --- a/graf2d/asimage/inc/TASUtils.h +++ b/graf2d/asimage/inc/TASUtils.h @@ -31,6 +31,7 @@ class TASUtils { static Pixmap_t GetX11Pixmap(TImage *timg); static Bool_t FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height); static std::unique_ptr FromPixmap(Pixmap_t pxm, Pixmap_t mask); + static Bool_t PaintImage(TImage *timg, Drawable_t wid, Int_t x, Int_t y, Bool_t opaque = kFALSE); }; #endif diff --git a/graf2d/asimage/src/TASUtils.cxx b/graf2d/asimage/src/TASUtils.cxx index 6b8b0372233d6..225189c4b2e95 100644 --- a/graf2d/asimage/src/TASUtils.cxx +++ b/graf2d/asimage/src/TASUtils.cxx @@ -40,6 +40,8 @@ class ASVisualHolder { public: + GContext_t fGC = 0; // context used in PaintImage + ASVisual *operator()() { #ifndef X_DISPLAY_MISSING @@ -68,10 +70,11 @@ class ASVisualHolder { destroy_asvisual(fVisual, 0); fVisual = nullptr; } + if (fGC && gVirtualX) + gVirtualX->DeleteGC(fGC); } }; - thread_local ASVisualHolder holder; //////////////////////////////////////////////////////////////////////////////// @@ -169,3 +172,82 @@ std::unique_ptr TASUtils::FromPixmap(Pixmap_t pxm, Pixmap_t mask) return asimg; } + +//////////////////////////////////////////////////////////////////////////////// +/// Paint image on specified window + +Bool_t TASUtils::PaintImage(TImage *timg, Drawable_t wid, Int_t x, Int_t y, Bool_t opaque) +{ + auto asimg = dynamic_cast(timg); + if (!asimg) { + ::Warning("TASUtils::PaintImage", "Image not provided"); + return kFALSE; + } + + Pixmap_t mask = kNone; + + Bool_t isX11 = gVirtualX->InheritsFrom("TGX11"); + + if (isX11) { + UInt_t mwidth = 0, mheight = 0; + std::vector bits; + if (asimg->GetMaskBits(mwidth, mheight, bits)) + mask = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), bits.data(), mwidth, mheight); + } + + GCValues_t gv; + gv.fMask = kGCClipMask | kGCClipXOrigin | kGCClipYOrigin; + gv.fClipMask = mask; + gv.fClipXOrigin = x; + gv.fClipYOrigin = y; + + if (!holder.fGC) { + holder.fGC = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &gv); + } else { + gVirtualX->ChangeGC(holder.fGC, &gv); + } + + UInt_t width = asimg->GetScaledWidth(); + UInt_t height = asimg->GetScaledHeight(); + + Bool_t res = kTRUE; + + if (isX11) { //use built-in optimized version + #ifndef X_DISPLAY_MISSING + ASImage *im = asimg->fScaledImage ? asimg->fScaledImage->fImage : asimg->fImage; + auto vis = holder(); + if (vis && im) + asimage2drawable(vis, wid, im, (GC)holder.fGC, 0, 0, x, y, width, height, 1); + else + res = kFALSE; + #else + ::Error("TASUtils::PaintImage", "Invoke X11-specific methods on unsupported platforms"); + res = kFALSE; + #endif + } else { + auto argb = asimg->GetArgbArray(); + + Pixmap_t pic = argb ? gVirtualX->CreatePixmapFromData((unsigned char *) argb, width, height) : 0; + + if (pic) { + if (!opaque) { + SETBIT(width, 31); + SETBIT(height, 31); + } + gVirtualX->CopyArea(pic, wid, holder.fGC, 0, 0, width, height, x, y); + gVirtualX->DeletePixmap(pic); + } else + res = kFALSE; + } + + // free mask pixmap + if (mask != kNone) + gVirtualX->DeletePixmap(mask); + + gv.fMask = kGCClipMask; + gv.fClipMask = kNone; + if (holder.fGC) + gVirtualX->ChangeGC(holder.fGC, &gv); + + return res; +} From 062ada72610ce2b65aa352243a9a4ce414b562b9 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 16:51:50 +0200 Subject: [PATCH 12/21] [padpainter] use new TASUtils::PaintImage --- graf2d/padpainter/src/TPadPainter.cxx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/graf2d/padpainter/src/TPadPainter.cxx b/graf2d/padpainter/src/TPadPainter.cxx index 8e38f328d490f..50f243c9160d8 100644 --- a/graf2d/padpainter/src/TPadPainter.cxx +++ b/graf2d/padpainter/src/TPadPainter.cxx @@ -230,9 +230,21 @@ Bool_t TPadPainter::HasTTFonts() const void TPadPainter::DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags) { - Window_t wid = (Window_t)gVirtualX->GetWindowID(fPad->GetPixmapID()); + Window_t wid = gVirtualX->GetWindowID(fPad->GetPixmapID()); + // use old API to draw image on gVirtualX window - img->PaintImage(wid, x, y, 0, 0, 0, 0, flags ? "" : "opaque"); + // img->PaintImage(wid, x, y, 0, 0, 0, 0, flags ? "" : "opaque"); +#ifdef USE_ASIMAGEUTILS + // new API invokes + TASUtils::PaintImage(img, wid, x, y, !flags); +#else + ::Error("TPadPainter::DrawImage", "TASImage not compiled, image painting is not possible"); + (void) wid; + (void) img; + (void) x; + (void) y; + (void) flags; +#endif } //////////////////////////////////////////////////////////////////////////////// From a5d76b0b98f74b428b23361f2c9b48e385dc29e9 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 16 Oct 2026 17:01:30 +0200 Subject: [PATCH 13/21] [speedo] Use TASUtils::PaintImage Also use unique_ptr to avoid memory leaks --- gui/gui/src/TGSpeedo.cxx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/gui/gui/src/TGSpeedo.cxx b/gui/gui/src/TGSpeedo.cxx index b0373e4169d05..0ed2e8f13f0db 100644 --- a/gui/gui/src/TGSpeedo.cxx +++ b/gui/gui/src/TGSpeedo.cxx @@ -31,6 +31,7 @@ Two signals are available: #include "TSystem.h" #include "TGResourcePool.h" #include "TImage.h" +#include "TASUtils.h" #include "TMath.h" #include "TVirtualX.h" #include "TGSpeedo.h" @@ -527,8 +528,9 @@ void TGSpeedo::DrawNeedle() if (fImage2 && fImage2->IsValid()) { // First clone original image. - TImage *img = (TImage*)fImage2->Clone("img"); - if (!img || !img->IsValid()) return; + std::unique_ptr img((TImage*)fImage2->Clone("img")); + if (!img || !img->IsValid()) + return; if (fPeakMark) { img->DrawLine(xpk0, ypk0, xpk1, ypk1, "#00ff00", 3); img->DrawLine(xpk0, ypk0, xpk1, ypk1, "#ffffff", 1); @@ -539,10 +541,9 @@ void TGSpeedo::DrawNeedle() } // draw line (used to render the needle) directly on the image img->DrawLine(xch0, ych0, xch1, ych1, "#ff0000", 2); + // finally paint image to the widget - img->PaintImage(fId, 0, 0, 0, 0, 0, 0, "opaque"); - // and finally, to avoid memory leaks - delete img; + TASUtils::PaintImage(img.get(), fId, 0, 0, kTRUE); } gVirtualX->Update(); } @@ -645,7 +646,8 @@ void TGSpeedo::DoRedraw() if (fImage2 && fImage2->IsValid()) delete fImage2; fImage2 = (TImage*)fImage->Clone("fImage2"); - if (!fImage2 || !fImage2->IsValid()) return; + if (!fImage2 || !fImage2->IsValid()) + return; TString ar = "arialbd.ttf"; // format counter value Int_t nexe = 0; @@ -678,8 +680,9 @@ void TGSpeedo::DoRedraw() // second line strSize = gVirtualX->TextWidth(fTextFS, fDisplay2.Data(), fDisplay2.Length()) - 6; fImage2->DrawText((Int_t)xc - (strSize / 2), (Int_t)yc + 38, fDisplay2.Data(), 8, "#ffffff", ar); - TImage *img = (TImage*)fImage2->Clone("img"); - if (!img || !img->IsValid()) return; + std::unique_ptr img((TImage*)fImage2->Clone("img")); + if (!img || !img->IsValid()) + return; if (fPeakMark) { img->DrawLine(xpk0, ypk0, xpk1, ypk1, "#00ff00", 3); img->DrawLine(xpk0, ypk0, xpk1, ypk1, "#ffffff", 1); @@ -690,9 +693,8 @@ void TGSpeedo::DoRedraw() } // draw line (used to render the needle) directly on the image img->DrawLine(xch0, ych0, xch1, ych1, "#ff0000", 2); + // finally paint image to the widget - img->PaintImage(fId, 0, 0, 0, 0, 0, 0, "opaque"); - // and finally, to avoid memory leaks - delete img; + TASUtils::PaintImage(img.get(), fId, 0, 0, kTRUE); } } From 9586919a252aa2ca574886e5e83cece2b3efbe0e Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 10:21:37 +0200 Subject: [PATCH 14/21] [ghtml] fix image painting Do not call img->PaintImage() when no any part of image visible in currently drawing region. --- gui/guihtml/src/TGHtmlDraw.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gui/guihtml/src/TGHtmlDraw.cxx b/gui/guihtml/src/TGHtmlDraw.cxx index e275c017d75e9..4da4d84bf2bd1 100644 --- a/gui/guihtml/src/TGHtmlDraw.cxx +++ b/gui/guihtml/src/TGHtmlDraw.cxx @@ -572,10 +572,12 @@ void TGHtml::DrawImage(TGHtmlImageMarkup *image, Drawable_t drawable, imageX = 0; } - TImage *img = image->fPImage->fImage; + // no need to paint if any visisble dimension is not-positive + // this happens when image is not shown on currently painted region + if ((imageH <= 0) || (imageW <= 0)) + return; - imageH = imageH < 0 ? -imageH : imageH; - imageW = imageW < 0 ? -imageW : imageW; + TImage *img = image->fPImage->fImage; img->PaintImage(drawable, x, y, imageX, imageY, imageW, imageH); //gVirtualX->Update(kFALSE); From 2c502d30fb14960c78fc4990b03441cd405afaa2 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 10:40:03 +0200 Subject: [PATCH 15/21] [ghtml] use ASUtils to paint image on X11 drawable Use Image::Crop to extract visible part of image. Avoid usage of complex and error-prone img->Paint with too many arguments --- gui/guihtml/CMakeLists.txt | 1 + gui/guihtml/src/TGHtmlDraw.cxx | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gui/guihtml/CMakeLists.txt b/gui/guihtml/CMakeLists.txt index b010bb6d8f668..ce5669b9b5ce2 100644 --- a/gui/guihtml/CMakeLists.txt +++ b/gui/guihtml/CMakeLists.txt @@ -29,4 +29,5 @@ ROOT_STANDARD_LIBRARY_PACKAGE(GuiHtml DEPENDENCIES Gui Graf + ASImageUtils ) diff --git a/gui/guihtml/src/TGHtmlDraw.cxx b/gui/guihtml/src/TGHtmlDraw.cxx index 4da4d84bf2bd1..eb7ce7804ef4d 100644 --- a/gui/guihtml/src/TGHtmlDraw.cxx +++ b/gui/guihtml/src/TGHtmlDraw.cxx @@ -38,6 +38,7 @@ #include "TGHtml.h" #include "TImage.h" +#include "TASUtils.h" #include "TVirtualX.h" #include "strlcpy.h" @@ -578,8 +579,17 @@ void TGHtml::DrawImage(TGHtmlImageMarkup *image, Drawable_t drawable, return; TImage *img = image->fPImage->fImage; + if (!img) + return; + + if ((imageX == 0) && (imageY == 0) && (imageW == image->fW) && (imageH == image->fH)) { + TASUtils::PaintImage(img, drawable, x, y); + } else { + std::unique_ptr cloned((TImage *) img->Clone("crop_img")); + cloned->Crop(imageX, imageY, imageW, imageH); + TASUtils::PaintImage(cloned.get(), drawable, x, y); + } - img->PaintImage(drawable, x, y, imageX, imageY, imageW, imageH); //gVirtualX->Update(kFALSE); image->fRedrawNeeded = 0; From 2215ecfb138623a28a7413fac51acd00b20ac32a Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 10:43:30 +0200 Subject: [PATCH 16/21] [eve] use ASUtils for X11 PaintImage Direct method in TImage will be deprectaed --- tutorials/visualisation/eve/SplitGLView.C | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tutorials/visualisation/eve/SplitGLView.C b/tutorials/visualisation/eve/SplitGLView.C index 71beecc3e41ad..24fb03c97e666 100644 --- a/tutorials/visualisation/eve/SplitGLView.C +++ b/tutorials/visualisation/eve/SplitGLView.C @@ -299,7 +299,8 @@ void TGShapedToolTip::Refresh() nlines++; img->DrawText(fTextX, fTextY + (nlines * size), s, size, fTextCol, ar); } - img->PaintImage(fId, 0, 0, 0, 0, 0, 0, "opaque"); + // use instead deprecated img->PaintImage() + TASUtils::PaintImage(img, fId, 0, 0, kTRUE); free(string); delete img; gVirtualX->Update(); From f51dd022138cd62b4f0e2eb25dcd59eaf513c378 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 10:46:02 +0200 Subject: [PATCH 17/21] [image] deprecate TImage::PaintImage method It uses X11 functionality and was replaced by TASUtils::PaintImage() method --- graf2d/graf/inc/TImage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graf2d/graf/inc/TImage.h b/graf2d/graf/inc/TImage.h index cf9dafd103539..62065aa515854 100644 --- a/graf2d/graf/inc/TImage.h +++ b/graf2d/graf/inc/TImage.h @@ -258,7 +258,7 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual UInt_t *GetScanline(UInt_t /*y*/) { return nullptr; } virtual void GetImageBuffer(char ** /*buffer*/, int* /*size*/, EImageFileTypes /*type*/ = TImage::kPng) {} virtual Bool_t SetImageBuffer(char ** /*buffer*/, EImageFileTypes /*type*/ = TImage::kPng) { return kFALSE; } - virtual void PaintImage(Drawable_t /*wid*/, Int_t /*x*/, Int_t /*y*/, Int_t /*xsrc*/ = 0, Int_t /*ysrc*/ = 0, UInt_t /*wsrc*/ = 0, UInt_t /*hsrc*/ = 0, Option_t * /*opt*/ = "") { } + virtual void R__DEPRECATED(7,00, "Use TASUtils::PaintImage instead") PaintImage(Drawable_t /*wid*/, Int_t /*x*/, Int_t /*y*/, Int_t /*xsrc*/ = 0, Int_t /*ysrc*/ = 0, UInt_t /*wsrc*/ = 0, UInt_t /*hsrc*/ = 0, Option_t * /*opt*/ = "") { } static EImageFileTypes GetImageFileTypeFromFilename(const char* opt); static TImage *Create(); From b9a5166e2fc29053ac695ff63205ffcd3fddf6a1 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 11:13:47 +0200 Subject: [PATCH 18/21] [glpainter] provide direct DrawImage implementation Instead calling DrawPixels just implement method, deprecate DrawPixels in gl painter --- graf3d/gl/src/TGLPadPainter.cxx | 129 ++++++++++++++------------------ 1 file changed, 55 insertions(+), 74 deletions(-) diff --git a/graf3d/gl/src/TGLPadPainter.cxx b/graf3d/gl/src/TGLPadPainter.cxx index 605bbf803f48c..8fdc67371554f 100644 --- a/graf3d/gl/src/TGLPadPainter.cxx +++ b/graf3d/gl/src/TGLPadPainter.cxx @@ -872,13 +872,60 @@ void TGLPadPainter::RestoreViewport() //////////////////////////////////////////////////////////////////////////////// /// Draw image on the GL window -void TGLPadPainter::DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags) +void TGLPadPainter::DrawImage(TImage *img, Int_t dstX, Int_t dstY, Int_t flags) { - Int_t width = img->GetWidth(); - Int_t height = img->GetHeight(); - auto bits = img->GetArgbArray(); - if (bits) - DrawPixels((unsigned char *)bits, width, height, x, y, flags); + if (fLocked) + return; + + auto width = img->GetWidth(); + auto height = img->GetHeight(); + auto pixelData = (unsigned char *) img->GetArgbArray(); + + if (!pixelData) { + ::Error("TGLPadPainter::DrawImage", "pixel data is null"); + return; + } + + if (!width || !height) { + //Assert is better. + ::Error("TGLPadPainter::DrawImage", "invalid image dimentsion"); + return; + } + + if (!gPad) { + ::Error("TGLPadPainter::DrawImage", "pad is not provided"); + return; + } + + const Double_t rasterX = Double_t(dstX) / gPad->GetPadWidth() * (gPad->GetX2() - gPad->GetX1()) + gPad->GetX1(); + + const Double_t yRange = gPad->GetY2() - gPad->GetY1(); + const Double_t rasterY = yRange - Double_t(dstY + height) / gPad->GetPadHeight() * yRange + gPad->GetY1(); + + GLdouble oldPos[4] = {}; + // Save the previous raster pos. + glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos); + + glRasterPos2d(rasterX, rasterY); + // Stupid asimage provides us upside-down image. + std::vector upsideDownImage(4 * width * height); + const unsigned char *srcLine = pixelData + 4 * width * (height - 1); + unsigned char *dstLine = &upsideDownImage[0]; + for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width) + std::copy(srcLine, srcLine + 4 * width, dstLine); + + if (flags) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]); + + if (flags) + glDisable(GL_BLEND); + + //Restore raster pos. + glRasterPos2d(oldPos[0], oldPos[1]); } //////////////////////////////////////////////////////////////////////////////// @@ -957,75 +1004,9 @@ Bool_t TGLPadPainter::FillImageFromPad(TImage *image, TVirtualPad *pad) const //////////////////////////////////////////////////////////////////////////////// -void TGLPadPainter::DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, - Int_t dstX, Int_t dstY, Bool_t enableBlending) +void TGLPadPainter::DrawPixels(const unsigned char *, UInt_t, UInt_t, + Int_t, Int_t, Bool_t) { - if (fLocked) - return; - - if (!pixelData) { - //I'd prefer an assert. - ::Error("TGLPadPainter::DrawPixels", "pixel data is null"); - return; - } - - if (std::numeric_limits::digits >= 32) { - //TASImage uses bit 31 as ... - //alpha channel flag! FUUUUUUUUUUUUU ..... !!! - CLRBIT(width, 31); - CLRBIT(height, 31); - } - - if (!width) { - //Assert is better. - ::Error("TGLPadPainter::DrawPixels", "invalid width"); - return; - } - - if (!height) { - //Assert is better. - ::Error("TGLPadPainter::DrawPixels", "invalid height"); - return; - } - - if (TPad *pad = dynamic_cast(gPad)) { - //TASImage passes pixel coordinates in pad's pixmap coordinate space. - //While glRasterPosX said to work with 'window' coordinates, - //that's a lie :) it does not :) - - const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) * - (pad->GetX2() - pad->GetX1()) + pad->GetX1(); - - const Double_t yRange = pad->GetY2() - pad->GetY1(); - const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange + - pad->GetY1(); - - GLdouble oldPos[4] = {}; - //Save the previous raster pos. - glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos); - - glRasterPos2d(rasterX, rasterY); - //Stupid asimage provides us upside-down image. - std::vector upsideDownImage(4 * width * height); - const unsigned char *srcLine = pixelData + 4 * width * (height - 1); - unsigned char *dstLine = &upsideDownImage[0]; - for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width) - std::copy(srcLine, srcLine + 4 * width, dstLine); - - if (enableBlending) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]); - - if (enableBlending) - glDisable(GL_BLEND); - - //Restore raster pos. - glRasterPos2d(oldPos[0], oldPos[1]); - } else - ::Error("TGLPadPainter::DrawPixels", "no pad found to draw"); } //Aux. functions - gradient and solid fill of arbitrary area. From 7f50be902b801dfddabc90eb015860a2ab6fa7ca Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 11:14:39 +0200 Subject: [PATCH 19/21] [padpainter] deprecate DrawPixels which no longer used Functionality everywhere replaced by DrawImage, method will be removed in ROOT7 --- core/base/inc/TVirtualPadPainter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/base/inc/TVirtualPadPainter.h b/core/base/inc/TVirtualPadPainter.h index a3cebc2efdd73..5d01110bb0e8c 100644 --- a/core/base/inc/TVirtualPadPainter.h +++ b/core/base/inc/TVirtualPadPainter.h @@ -109,8 +109,8 @@ class TVirtualPadPainter { //TASImage support. - virtual void DrawPixels(const unsigned char *pixelData, UInt_t width, UInt_t height, - Int_t dstX, Int_t dstY, Bool_t enableAlphaBlending) = 0; + virtual void R__DEPRECATED(7,00, "Use DrawImage instead") DrawPixels(const unsigned char * /* pixelData */, UInt_t /* width */, UInt_t /* height */, + Int_t /* dstX */, Int_t /* dstY */, Bool_t /* enableAlphaBlending */) {} // //These functions are not required by X11/GDI. virtual void InitPainter(); From 4d7e4727b7e5fa755b9658e7b02abc17e12252ae Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 12:41:26 +0200 Subject: [PATCH 20/21] [image] fix TASImage::Crop() With start_image_decoding in the TASImage::Crop() created decorder was released wrongly. Instaed `delete[] imdec` one have to use `stop_image_decoding(&imdec);` Also check input parameters - if x or y larger than width or height large negative values converted to unsigned causing segfault or memory allocation problems. Adjust also GetScanline where array not need to be created --- graf2d/asimage/src/TASImage.cxx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/graf2d/asimage/src/TASImage.cxx b/graf2d/asimage/src/TASImage.cxx index b9992487e900f..25f6eae466271 100644 --- a/graf2d/asimage/src/TASImage.cxx +++ b/graf2d/asimage/src/TASImage.cxx @@ -3312,13 +3312,19 @@ void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height) x = x < 0 ? 0 : x; y = y < 0 ? 0 : y; + if ((x >= (Int_t) fImage->width) || (y >= (Int_t) fImage->height)) { + Warning("Crop", "specified x/y position larger than image"); + return; + } + width = x + width > fImage->width ? fImage->width - x : width; height = y + height > fImage->height ? fImage->height - y : height; if ((width == fImage->width) && (height == fImage->height)) { - Warning("Crop", "input size larger than image"); + Warning("Crop", "specified size larger than image"); return; } + ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL, x, y, width, height, nullptr); @@ -3330,7 +3336,7 @@ void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height) ASImage *img = create_asimage(width, height, 0); if (!img) { - delete [] imdec; + stop_image_decoding(&imdec); Warning("Crop", "Failed to create image"); return; } @@ -3341,7 +3347,7 @@ void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height) if (!imout) { Warning("Crop", "Failed to start image output"); destroy_asimage(&img); - if (imdec) delete [] imdec; + stop_image_decoding(&imdec); return; } @@ -3549,23 +3555,23 @@ UInt_t *TASImage::GetRgbaArray() UInt_t *TASImage::GetScanline(UInt_t y) { - if (!fImage) { + ASImage *img = fScaledImage ? fScaledImage->fImage : fImage; + + if (!img) { Warning("GetScanline", "no image"); return nullptr; } - ASImage *img = fScaledImage ? fScaledImage->fImage : fImage; - CARD32 *ret = new CARD32[img->width]; - ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL, 0, y, img->width, 1, nullptr); if (!imdec) { - delete [] ret; Warning("GetScanline", "Failed to start image decoding"); return nullptr; } + CARD32 *ret = new CARD32[img->width]; + #ifdef HAVE_MMX mmx_init(); #endif From dfbc33e317da05e9e285c430f61b10487a4b42fb Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 19 Oct 2026 14:30:45 +0200 Subject: [PATCH 21/21] [asutils] move methods from TGWindow It was intermediate solution to avoid creation of extra library Now ASUtils library is exists, therefore all specialized methods used in GUI can be moved there. --- graf2d/asimage/inc/TASUtils.h | 10 +- graf2d/asimage/src/TASUtils.cxx | 144 ++++++++++++++++---- graf2d/graf/inc/TImage.h | 8 +- graf2d/padpainter/src/TPadPainter.cxx | 31 +---- gui/gui/inc/TGWindow.h | 5 - gui/gui/src/TGButton.cxx | 4 +- gui/gui/src/TGFSContainer.cxx | 4 +- gui/gui/src/TGFileBrowser.cxx | 6 +- gui/gui/src/TGFrame.cxx | 5 +- gui/gui/src/TGIcon.cxx | 7 +- gui/gui/src/TGObject.cxx | 3 +- gui/gui/src/TGPicture.cxx | 7 +- gui/gui/src/TGScrollBar.cxx | 4 +- gui/gui/src/TGShapedFrame.cxx | 3 +- gui/gui/src/TGSlider.cxx | 4 +- gui/gui/src/TGSpeedo.cxx | 2 +- gui/gui/src/TGWindow.cxx | 92 ------------- gui/gui/src/TRootBrowserLite.cxx | 13 +- gui/guibuilder/CMakeLists.txt | 1 + gui/guibuilder/src/TGuiBldDragManager.cxx | 5 +- gui/guibuilder/src/TRootGuiBuilder.cxx | 5 +- gui/guihtml/src/TGHtmlDraw.cxx | 2 +- gui/guihtml/src/TGHtmlSizer.cxx | 5 +- test/CMakeLists.txt | 2 +- test/stressGUI.cxx | 3 +- tutorials/visualisation/gui/drag_and_drop.C | 4 +- tutorials/visualisation/gui/exec_macro.C | 2 +- 27 files changed, 186 insertions(+), 195 deletions(-) diff --git a/graf2d/asimage/inc/TASUtils.h b/graf2d/asimage/inc/TASUtils.h index c14300e81d06a..90dbf6fb2bc57 100644 --- a/graf2d/asimage/inc/TASUtils.h +++ b/graf2d/asimage/inc/TASUtils.h @@ -28,10 +28,14 @@ class TImage; class TASUtils { public: - static Pixmap_t GetX11Pixmap(TImage *timg); - static Bool_t FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height); - static std::unique_ptr FromPixmap(Pixmap_t pxm, Pixmap_t mask); + static Pixmap_t GetPixmap(TImage *timg); + static Pixmap_t GetMask(TImage *timg); + static Bool_t PaintImage(TImage *timg, Drawable_t wid, Int_t x, Int_t y, Bool_t opaque = kFALSE); + static Bool_t FillImageFromWindow(TImage *img, Window_t wid, Int_t width, Int_t height); + + static std::unique_ptr FromWindow(Window_t wid); + static std::unique_ptr FromPixmap(Pixmap_t pxm, Pixmap_t mask); }; #endif diff --git a/graf2d/asimage/src/TASUtils.cxx b/graf2d/asimage/src/TASUtils.cxx index 225189c4b2e95..dd01c8d3a9e76 100644 --- a/graf2d/asimage/src/TASUtils.cxx +++ b/graf2d/asimage/src/TASUtils.cxx @@ -77,60 +77,148 @@ class ASVisualHolder { thread_local ASVisualHolder holder; + //////////////////////////////////////////////////////////////////////////////// -/// Returns image X11 pixmap. -/// Workrs only on the platforms with support of X11 +/// Returns image pixmap. /// The pixmap must deleted by user. +/// Replacement for deprecated TImage::GetPixmap method +/// Special handling for X11-based displays where ASImage has optimized implementation -Pixmap_t TASUtils::GetX11Pixmap(TImage *timg) +Pixmap_t TASUtils::GetPixmap(TImage *timg) { - auto asimg = dynamic_cast(timg); - if (!asimg) { - ::Warning("TASUtils::GetX11Pixmap", "Image not provided"); + if (!timg) { + ::Error("TASUtils::GetPixmap", "Image not provided"); return 0; } + static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); + + if (x11) { +#ifndef X_DISPLAY_MISSING + auto asimg = dynamic_cast(timg); + if (!asimg) { + ::Warning("TASUtils::GetPixmap", "ASImage not provided"); + return 0; + } - auto vis = holder(); + auto vis = holder(); - if (!vis) { - ::Warning("TASUtils::GetX11Pixmap", "Visual not initiated"); + if (!vis) { + ::Warning("TASUtils::GetPixmap", "Visual not initiated"); + return 0; + } + + ASImage *img = asimg->fScaledImage ? asimg->fScaledImage->fImage : asimg->fImage; + + return (Pixmap_t)asimage2pixmap(vis, gVirtualX->GetDefaultRootWindow(), img, nullptr, kTRUE); +#else + ::Error("TASUtils::GetPixmap", "Invoke X11-specific methods on unsupported platform"); return 0; +#endif } - ASImage *img = asimg->fScaledImage ? asimg->fScaledImage->fImage : asimg->fImage; + auto argb = timg->GetArgbArray(); + if (!argb) { + ::Error("TASUtils::GetPixmap", "ARGB array is not exists"); + return 0; + } - return (Pixmap_t)asimage2pixmap(vis, gVirtualX->GetDefaultRootWindow(), img, nullptr, kTRUE); + return gVirtualX->CreatePixmapFromData((unsigned char*) argb, timg->GetScaledWidth(), timg->GetScaledHeight()); } //////////////////////////////////////////////////////////////////////////////// -/// Create an image from the given X11 window -/// Can only be used on platforms where X11 is supported +/// Returns image mask pixmap (alpha channel). +/// The pixmap must deleted by user. +/// Replacement for deprecated TImage::GetMask() method -Bool_t TASUtils::FromX11Window(TImage *timg, Window_t win, Int_t x, Int_t y, Int_t width, Int_t height) +Pixmap_t TASUtils::GetMask(TImage *img) { - auto asimg = dynamic_cast(timg); - if (!asimg) { - ::Warning("TASUtils::FromX11Window", "Image not provided"); - return kFALSE; - } + Pixmap_t pixmap = 0; + + UInt_t width = 0, height = 0; + std::vector bits; - auto vis = holder(); + if (!img) + ::Error("TGWindow::GetImageMask", "Image not provided"); + else if (img->GetMaskBits(width, height, bits)) + pixmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), bits.data(), width, height); + + return pixmap; +} - if (!vis) { - ::Warning("TASUtils::FromX11Window", "Visual not initiated"); +//////////////////////////////////////////////////////////////////////////////// +/// Create an image from the given window + +Bool_t TASUtils::FillImageFromWindow(TImage *img, Window_t wid, Int_t width, Int_t height) +{ + auto asimg = dynamic_cast (img); + if (!asimg) return kFALSE; - } asimg->DestroyImage(); asimg->DestroyScaledImage(); - asimg->fImage = pixmap2asimage(vis, win, x, y, width, height, kAllPlanes, 0, 0); + gVirtualX->Update(1); + if (!gThreadXAR) { + gSystem->Sleep(10); + gSystem->ProcessEvents(); + gSystem->Sleep(10); + gSystem->ProcessEvents(); + } + + static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); - return asimg->fImage != nullptr; + if (x11) { + auto vis = holder(); + + if (!vis) { + ::Error("TASUtils::FillImageFromWindow", "Visual not initiated"); + return kFALSE; + } + +#ifndef X_DISPLAY_MISSING + asimg->fImage = pixmap2asimage(vis, wid, 0, 0, width, height, kAllPlanes, 0, 0); +#else + ::Error("TASUtils::FillImageFromWindow", "Invoke X11-specific methods on unsupported platform"); +#endif + } else { + unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, width, height); + if (!bits) { + ::Error("TASUtils::FillImageFromWindow", "Fail to extract color bits for specified window"); + return kFALSE; + } + asimg->FromBitmap(bits, width, height); + delete [] bits; + } + + if (!asimg->IsValid()) + return kFALSE; + + return kTRUE; } //////////////////////////////////////////////////////////////////////////////// -/// Set image data from pixmap. +/// Create an image from the given window + +std::unique_ptr TASUtils::FromWindow(Window_t wid) +{ + Int_t x = 0, y = 0; + UInt_t w = 0, h = 0; + + gVirtualX->GetWindowSize(wid, x, y, w, h); + + (void) x; // position of window is not used + (void) y; + + auto asimg = std::make_unique(); + + if (!FillImageFromWindow(asimg.get(), wid, w, h)) + return nullptr; + + return asimg; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Create image from pixmap. std::unique_ptr TASUtils::FromPixmap(Pixmap_t pxm, Pixmap_t mask) { @@ -152,6 +240,8 @@ std::unique_ptr TASUtils::FromPixmap(Pixmap_t pxm, Pixmap_t mask) #ifndef X_DISPLAY_MISSING asimg->fImage = picture2asimage(vis, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0); +#else + ::Error("TASUtils::FromPixmap", "Invoke X11-specific methods on unsupported platform"); #endif } else { unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h); @@ -221,7 +311,7 @@ Bool_t TASUtils::PaintImage(TImage *timg, Drawable_t wid, Int_t x, Int_t y, Bool else res = kFALSE; #else - ::Error("TASUtils::PaintImage", "Invoke X11-specific methods on unsupported platforms"); + ::Error("TASUtils::PaintImage", "Invoke X11-specific methods on unsupported platform"); res = kFALSE; #endif } else { diff --git a/graf2d/graf/inc/TImage.h b/graf2d/graf/inc/TImage.h index 62065aa515854..4bab2fd8fa545 100644 --- a/graf2d/graf/inc/TImage.h +++ b/graf2d/graf/inc/TImage.h @@ -120,7 +120,7 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual void SetImage(const Double_t * /*imageData*/, UInt_t /*width*/, UInt_t /*height*/, TImagePalette * /*palette*/ = nullptr) {} virtual void SetImage(const TArrayD & /*imageData*/, UInt_t /*width*/, TImagePalette * /*palette*/ = nullptr) {} virtual void SetImage(const TVectorD & /*imageData*/, UInt_t /*width*/, TImagePalette * /*palette*/ = nullptr) {} - virtual void R__DEPRECATED(7,00, "Use TASUtil::FromPixmap instead") SetImage(Pixmap_t /*pxm*/, Pixmap_t /*mask*/ = 0) {} + virtual void R__DEPRECATED(7,00, "Use TASUtils::FromPixmap instead") SetImage(Pixmap_t /*pxm*/, Pixmap_t /*mask*/ = 0) {} // Create an image from bitmap. (See TASImage::FromBitmap) @@ -130,7 +130,7 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual void FromPad(TVirtualPad * /*pad*/, Int_t /*x*/ = 0, Int_t /*y*/ = 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) {} // Create an image from gVirtualX window. (See TASImage::FromWindow) - virtual void R__DEPRECATED(7,00, "Use TGWindow::CreateImageFromWindow instead") FromWindow(Drawable_t /*wid*/, Int_t /*x*/ = 0, Int_t /*y*/ = 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) {} + virtual void R__DEPRECATED(7,00, "Use TASUtils::FromWindow instead") FromWindow(Drawable_t /*wid*/, Int_t /*x*/ = 0, Int_t /*y*/ = 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) {} // Create an image from GL buffer. (See TASImage::FromGLBuffer) virtual void R__DEPRECATED(7,00, "Use FromBitmap instead") FromGLBuffer(UChar_t * /*buf*/, UInt_t /*w*/, UInt_t /*h*/) {} @@ -249,9 +249,9 @@ friend TImage operator/(const TImage &i1, const TImage &s2); virtual TArrayL *GetPixels(Int_t /*x*/= 0, Int_t /*y*/= 0, UInt_t /*w*/ = 0, UInt_t /*h*/ = 0) { return nullptr; } virtual TArrayD *GetArray(UInt_t /*w*/ = 0, UInt_t /*h*/ = 0, TImagePalette * = gWebImagePalette) { return nullptr; } - virtual Pixmap_t R__DEPRECATED(7,00, "Use TGWindow::GetImagePixmap instead") GetPixmap() { return 0; } + virtual Pixmap_t R__DEPRECATED(7,00, "Use TASUtils::GetPixmap instead") GetPixmap() { return 0; } virtual Bool_t GetMaskBits(UInt_t & /* width */, UInt_t & /* height */, std::vector & /* bits */) { return kFALSE; } - virtual Pixmap_t R__DEPRECATED(7,00, "Use TGWindow::GetImageMask instead") GetMask() { return 0; } + virtual Pixmap_t R__DEPRECATED(7,00, "Use TASUtils::GetMask instead") GetMask() { return 0; } virtual UInt_t *GetArgbArray() { return nullptr; } virtual UInt_t *GetRgbaArray() { return nullptr; } virtual Double_t *GetVecArray() { return nullptr; } diff --git a/graf2d/padpainter/src/TPadPainter.cxx b/graf2d/padpainter/src/TPadPainter.cxx index 50f243c9160d8..071a0866e7440 100644 --- a/graf2d/padpainter/src/TPadPainter.cxx +++ b/graf2d/padpainter/src/TPadPainter.cxx @@ -589,21 +589,14 @@ TVirtualPadPainter::ESaveImageResult TPadPainter::SaveAsImage(TVirtualPad *pad, //////////////////////////////////////////////////////////////////////////////// /// Fill image object with the pixel data from the pad -/// Implements special handling for X11 where ASImage has native implementation +/// Use TASUtils::FillImageFromWindow method which provides native X11 handling Bool_t TPadPainter::FillImageFromPad(TImage *image, TVirtualPad *pad) const { if (!image || !pad) return kFALSE; - gVirtualX->Update(1); - if (!gThreadXAR) { - gSystem->Sleep(10); - gSystem->ProcessEvents(); - gSystem->Sleep(10); - gSystem->ProcessEvents(); - } - +#ifdef USE_ASIMAGEUTILS auto width = pad->GetPadWidth(); auto height = pad->GetPadHeight(); @@ -612,23 +605,13 @@ Bool_t TPadPainter::FillImageFromPad(TImage *image, TVirtualPad *pad) const Window_t wd = gVirtualX->GetCurrentWindow(); - if (IsX11()) { -#ifdef USE_ASIMAGEUTILS - if (!TASUtils::FromX11Window(image, gVirtualX->GetCurrentWindow(), 0, 0, pad->GetPadWidth(), pad->GetPadHeight())) - return kFALSE; + return TASUtils::FillImageFromWindow(image, wd, width, height); #else - return kFALSE; + ::Error("TPadPainter::FillImageFromPad", "Cannot work without TASImage class"); + (void) image; + (void) pad; + return kFALSE; #endif - } else { - unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, width, height); - if (!bits) - return kFALSE; - - image->FromBitmap(bits, width, height); - delete [] bits; - } - - return image->IsValid(); } //Aux. private functions. diff --git a/gui/gui/inc/TGWindow.h b/gui/gui/inc/TGWindow.h index ce65b8a825300..96e2e0fcba6f9 100644 --- a/gui/gui/inc/TGWindow.h +++ b/gui/gui/inc/TGWindow.h @@ -19,7 +19,6 @@ class TGClient; class TGIdleHandler; -class TImage; class TGWindow : public TGObject { @@ -126,10 +125,6 @@ friend class TGClient; static Int_t GetCounter(); - static std::unique_ptr CreateImageFromWindow(Drawable_t wid); - static Pixmap_t GetImagePixmap(TImage *img); - static Pixmap_t GetImageMask(TImage *img); - ClassDefOverride(TGWindow, 0); // GUI Window base class }; diff --git a/gui/gui/src/TGButton.cxx b/gui/gui/src/TGButton.cxx index 610fd7241af1e..3661c47d10cf1 100644 --- a/gui/gui/src/TGButton.cxx +++ b/gui/gui/src/TGButton.cxx @@ -1109,12 +1109,12 @@ void TGPictureButton::CreateDisabledPicture() img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight()); auto img = TASUtils::FromPixmap(fPic->GetPicture(), fPic->GetMask()); if (img) { - Pixmap_t mask = GetImageMask(img.get()); + Pixmap_t mask = TASUtils::GetMask(img.get()); img2->Merge(img.get(), "overlay"); TString name = "disbl_"; name += fPic->GetName(); - fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), + fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), TASUtils::GetPixmap(img2.get()), mask); fOwnDisabledPic = kTRUE; } diff --git a/gui/gui/src/TGFSContainer.cxx b/gui/gui/src/TGFSContainer.cxx index e340fc78032d2..fb1b9e3e4a5a7 100644 --- a/gui/gui/src/TGFSContainer.cxx +++ b/gui/gui/src/TGFSContainer.cxx @@ -702,7 +702,7 @@ void TGFileContainer::GetFilePictures(const TGPicture **pic, TString lnk_name = (*pic)->GetName(); lnk_name.Prepend("lnk_"); *pic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(), - GetImagePixmap(img1.get()), GetImageMask(img1.get())); + TASUtils::GetPixmap(img1.get()), TASUtils::GetMask(img1.get())); fCleanups->Add(((TObject *)*pic)); } img1 = TASUtils::FromPixmap((*lpic)->GetPicture(), (*lpic)->GetMask()); @@ -713,7 +713,7 @@ void TGFileContainer::GetFilePictures(const TGPicture **pic, TString lnk_name = (*lpic)->GetName(); lnk_name.Prepend("lnk_"); *lpic = fClient->GetPicturePool()->GetPicture(lnk_name.Data(), - GetImagePixmap(img1.get()), GetImageMask(img1.get())); + TASUtils::GetPixmap(img1.get()), TASUtils::GetMask(img1.get())); fCleanups->Add(((TObject *)*lpic)); } } diff --git a/gui/gui/src/TGFileBrowser.cxx b/gui/gui/src/TGFileBrowser.cxx index 162dbc992f936..660423f87e558 100644 --- a/gui/gui/src/TGFileBrowser.cxx +++ b/gui/gui/src/TGFileBrowser.cxx @@ -1170,8 +1170,8 @@ static const TGPicture *MakeLinkPic(const TGPicture *pic) img1->Merge(img2.get()); TString lnk_name = pic->GetName(); lnk_name.Prepend("lnk_"); - auto merged = gClient->GetPicturePool()->GetPicture(lnk_name.Data(), - TGWindow::GetImagePixmap(img1.get()), TGWindow::GetImageMask(img1.get())); + auto merged = gClient->GetPicturePool()->GetPicture(lnk_name.Data(), TASUtils::GetPixmap(img1.get()), + TASUtils::GetMask(img1.get())); return merged; } return pic; @@ -1613,7 +1613,7 @@ void TGFileBrowser::GetObjPicture(const TGPicture **pic, TObject *obj) if (!(*pic) && xpm) { if (im && im->SetImageBuffer((char**)&name, TImage::kXpm)) { im->Scale(im->GetWidth()/4, im->GetHeight()/4); - *pic = gClient->GetPicturePool()->GetPicture(iconname, TGWindow::GetImagePixmap(im), TGWindow::GetImageMask(im)); + *pic = gClient->GetPicturePool()->GetPicture(iconname, TASUtils::GetPixmap(im), TASUtils::GetMask(im)); } gClient->GetMimeTypeList()->AddType("[thumbnail]", iconname, iconname, iconname, "->Browse()"); return; diff --git a/gui/gui/src/TGFrame.cxx b/gui/gui/src/TGFrame.cxx index 625101cbb7d44..04fdb1a84bd8a 100644 --- a/gui/gui/src/TGFrame.cxx +++ b/gui/gui/src/TGFrame.cxx @@ -102,6 +102,7 @@ in a list view. Used to have resizable column headers. #include "TGSplitter.h" #include "TGDNDManager.h" #include "TImage.h" +#include "TASUtils.h" #include "TObjectSpy.h" #include "TVirtualX.h" @@ -1579,7 +1580,7 @@ Bool_t TGMainFrame::SaveFrameAsCodeOrImage(const TString &fileName) Int_t saver = gErrorIgnoreLevel; gErrorIgnoreLevel = kFatal; RaiseWindow(); - auto img = TGWindow::CreateImageFromWindow(GetId()); + auto img = TASUtils::FromWindow(GetId()); if (img) img->WriteImage(fname, gtype); gErrorIgnoreLevel = saver; @@ -1833,7 +1834,7 @@ void TGMainFrame::SetIconPixmap(char **xpm_array) TImage *img = TImage::Create(); if (!img) return; img->SetImageBuffer(xpm_array, TImage::kXpm); - Pixmap_t pic = GetImagePixmap(img); + Pixmap_t pic = TASUtils::GetPixmap(img); if (pic) { gVirtualX->SetIconPixmap(fId, pic); } else { diff --git a/gui/gui/src/TGIcon.cxx b/gui/gui/src/TGIcon.cxx index 9547eda7f6654..6f02d124042f3 100644 --- a/gui/gui/src/TGIcon.cxx +++ b/gui/gui/src/TGIcon.cxx @@ -33,6 +33,7 @@ This class handles GUI icons. #include "TGPicture.h" #include "TSystem.h" #include "TImage.h" +#include "TASUtils.h" #include "TVirtualDragManager.h" #include "TVirtualX.h" @@ -57,7 +58,7 @@ TGIcon::TGIcon(const TGWindow *p, const char *image) : TGFrame(p, 1, 1) fImage = TImage::Open(path); if (fImage) { fPic = fClient->GetPicturePool()->GetPicture(gSystem->BaseName(path), - GetImagePixmap(fImage), GetImageMask(fImage)); + TASUtils::GetPixmap(fImage), TASUtils::GetMask(fImage)); TGFrame::Resize(fImage->GetWidth(), fImage->GetHeight()); } SetWindowName(); @@ -154,8 +155,8 @@ void TGIcon::Resize(UInt_t w, UInt_t h) (GetOptions() & kDoubleBorder); fImage->Scale(w - 2*border, h - 2*border); - fPic = fClient->GetPicturePool()->GetPicture(fImage->GetName(), - GetImagePixmap(fImage), GetImageMask(fImage)); + fPic = + fClient->GetPicturePool()->GetPicture(fImage->GetName(), TASUtils::GetPixmap(fImage), TASUtils::GetMask(fImage)); DoRedraw(); } diff --git a/gui/gui/src/TGObject.cxx b/gui/gui/src/TGObject.cxx index a62534698b0ea..1ef7b329483e2 100644 --- a/gui/gui/src/TGObject.cxx +++ b/gui/gui/src/TGObject.cxx @@ -34,6 +34,7 @@ is based on the XClass'95 code (see Copyleft in source). #include "TGObject.h" #include "TGWindow.h" #include "TImage.h" +#include "TASUtils.h" #include "TROOT.h" @@ -55,7 +56,7 @@ void TGObject::SaveAs(const char* filename /*= ""*/, Option_t* option /*= ""*/) { TImage::EImageFileTypes type = TImage::GetImageFileTypeFromFilename(filename); if (type != TImage::kUnknown) { - auto img = TGWindow::CreateImageFromWindow(GetId()); + auto img = TASUtils::FromWindow(GetId()); if (img) img->WriteImage(filename, type); return; diff --git a/gui/gui/src/TGPicture.cxx b/gui/gui/src/TGPicture.cxx index 2dced4a815938..ffddb91aa160d 100644 --- a/gui/gui/src/TGPicture.cxx +++ b/gui/gui/src/TGPicture.cxx @@ -40,6 +40,7 @@ destroyed by the TGPicturePool. #include "TGWindow.h" #include "TVirtualX.h" #include "TImage.h" +#include "TASUtils.h" #include "TROOT.h" #include @@ -116,7 +117,7 @@ const TGPicture *TGPicturePool::GetPicture(const char *name) return nullptr; } - pic = new TGPicture(pname, TGWindow::GetImagePixmap(img), TGWindow::GetImageMask(img)); + pic = new TGPicture(pname, TASUtils::GetPixmap(img), TASUtils::GetMask(img)); delete img; fPicList->Add(pic); return pic; @@ -192,7 +193,7 @@ const TGPicture *TGPicturePool::GetPicture(const char *name, img->Scale(new_width, new_height); - pic = new TGPicture(hname, TGWindow::GetImagePixmap(img), TGWindow::GetImageMask(img)); + pic = new TGPicture(hname, TASUtils::GetPixmap(img), TASUtils::GetMask(img)); delete [] picnam; delete img; fPicList->Add(pic); @@ -271,7 +272,7 @@ const TGPicture *TGPicturePool::GetPicture(const char *name, char **xpm) return 0; } - pic = new TGPicture(hname, TGWindow::GetImagePixmap(img), TGWindow::GetImageMask(img)); + pic = new TGPicture(hname, TASUtils::GetPixmap(img), TASUtils::GetMask(img)); delete img; return pic; } diff --git a/gui/gui/src/TGScrollBar.cxx b/gui/gui/src/TGScrollBar.cxx index 593587baa4f08..f8558a07749c9 100644 --- a/gui/gui/src/TGScrollBar.cxx +++ b/gui/gui/src/TGScrollBar.cxx @@ -166,12 +166,12 @@ void TGScrollBarElement::SetEnabled(Bool_t on) auto img = TASUtils::FromPixmap(fPicN->GetPicture(), fPicN->GetMask()); if (!img) return; - Pixmap_t mask = GetImageMask(img.get()); + Pixmap_t mask = TASUtils::GetMask(img.get()); img2->Merge(img.get(), "overlay"); TString name = "disbl_"; name += fPic->GetName(); - fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), + fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), TASUtils::GetPixmap(img2.get()), mask); } fPic = fPicD; diff --git a/gui/gui/src/TGShapedFrame.cxx b/gui/gui/src/TGShapedFrame.cxx index 3a425258353dd..c6439f5ccf90e 100644 --- a/gui/gui/src/TGShapedFrame.cxx +++ b/gui/gui/src/TGShapedFrame.cxx @@ -12,6 +12,7 @@ #include "TGLayout.h" #include "TString.h" #include "TImage.h" +#include "TASUtils.h" #include "TGShapedFrame.h" #include "TVirtualX.h" @@ -50,7 +51,7 @@ TGShapedFrame::TGShapedFrame(const char *pname, const TGWindow *p, UInt_t w, Error("TGShapedFrame", "%s not found", picName.Data()); return; } - fBgnd = fClient->GetPicturePool()->GetPicture(picName.Data(), GetImagePixmap(fImage), GetImageMask(fImage)); + fBgnd = fClient->GetPicturePool()->GetPicture(picName.Data(), TASUtils::GetPixmap(fImage), TASUtils::GetMask(fImage)); // shape the window with the picture mask gVirtualX->ShapeCombineMask(fId, 0, 0, fBgnd->GetMask()); // and finally set the background picture diff --git a/gui/gui/src/TGSlider.cxx b/gui/gui/src/TGSlider.cxx index 529b238b37750..3432597a5ba43 100644 --- a/gui/gui/src/TGSlider.cxx +++ b/gui/gui/src/TGSlider.cxx @@ -139,12 +139,12 @@ void TGSlider::CreateDisabledPicture() auto img = TASUtils::FromPixmap(fSliderPic->GetPicture(), fSliderPic->GetMask()); if (!img) return; - Pixmap_t mask = GetImageMask(img.get()); + Pixmap_t mask = TASUtils::GetMask(img.get()); img2->Merge(img.get(), "overlay"); TString name = "disbl_"; name.Append(fSliderPic->GetName()); - fDisabledPic = fClient->GetPicturePool()->GetPicture(name.Data(), GetImagePixmap(img2.get()), mask); + fDisabledPic = fClient->GetPicturePool()->GetPicture(name.Data(), TASUtils::GetPixmap(img2.get()), mask); } //////////////////////////////////////////////////////////////////////////////// diff --git a/gui/gui/src/TGSpeedo.cxx b/gui/gui/src/TGSpeedo.cxx index 0ed2e8f13f0db..06da3dba25a4d 100644 --- a/gui/gui/src/TGSpeedo.cxx +++ b/gui/gui/src/TGSpeedo.cxx @@ -137,7 +137,7 @@ void TGSpeedo::Build() if (fImage && fImage->IsValid()) { fBase = fClient->GetPicturePool()->GetPicture(gSystem->BaseName(fPicName.Data()), - GetImagePixmap(fImage), GetImageMask(fImage)); + TASUtils::GetPixmap(fImage), TASUtils::GetMask(fImage)); // center of the image Float_t xc = (Float_t)(fBase ? (fBase->GetWidth() + 1) / 2 : 96.0); Float_t yc = (Float_t)(fBase ? (fBase->GetHeight() + 1) / 2 : 96.0); diff --git a/gui/gui/src/TGWindow.cxx b/gui/gui/src/TGWindow.cxx index ab35d66c2d920..cd977d1842dd9 100644 --- a/gui/gui/src/TGWindow.cxx +++ b/gui/gui/src/TGWindow.cxx @@ -357,95 +357,3 @@ const char *TGWindow::GetName()const return fName.Data(); } - - -//////////////////////////////////////////////////////////////////////////////// -/// Create TImage object with content of displayed window - -std::unique_ptr TGWindow::CreateImageFromWindow(Drawable_t wid) -{ - std::unique_ptr img(TImage::Create()); - if (!img) { - ::Error("TGWindow::CreateImageFromWindow", "Fail to create TImage object"); - return nullptr; - } - gVirtualX->Update(1); - if (!gThreadXAR) { - gSystem->Sleep(10); - gSystem->ProcessEvents(); - gSystem->Sleep(10); - gSystem->ProcessEvents(); - } - - Int_t x = 0, y = 0; - UInt_t w = 0, h = 0; - - gVirtualX->GetWindowSize(wid, x, y, w, h); - - (void) x; // position of window is not used - (void) y; - - static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); - - if (x11) { - if (!TASUtils::FromX11Window(img.get(), wid, 0, 0, w, h)) { - ::Error("TGWindow::CreateImageFromWindow", "Fail to create image from X11 window"); - return nullptr; - } - } else { - unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h); - if (!bits) { - ::Error("TGWindow::CreateImageFromWindow", "Fail to extract color bits for specified window"); - return nullptr; - } - img->FromBitmap(bits, w, h); - delete [] bits; - } - - return img; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Returns image pixmap. -/// The pixmap must deleted by user. -/// Replacement for deprecated TImage::GetPixmap method - -Pixmap_t TGWindow::GetImagePixmap(TImage *img) -{ - if (!img) { - ::Error("TGWindow::GetImagePixmap", "Image not provided"); - return 0; - } - static Bool_t x11 = gVirtualX->InheritsFrom("TGX11"); - - if (x11) - return TASUtils::GetX11Pixmap(img); - - auto argb = img->GetArgbArray(); - if (!argb) { - ::Error("TGWindow::GetImagePixmap", "ARGB array is not exists"); - return 0; - } - - return gVirtualX->CreatePixmapFromData((unsigned char*) argb, img->GetScaledWidth(), img->GetScaledHeight()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Returns image mask pixmap (alpha channel). -/// The pixmap must deleted by user. -/// Replacement for deprecated TImage::GetMask() method - -Pixmap_t TGWindow::GetImageMask(TImage *img) -{ - Pixmap_t pixmap = 0; - - UInt_t width = 0, height = 0; - std::vector bits; - - if (!img) - ::Error("TGWindow::GetImageMask", "Image not provided"); - else if (img->GetMaskBits(width, height, bits)) - pixmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), bits.data(), width, height); - - return pixmap; -} diff --git a/gui/gui/src/TRootBrowserLite.cxx b/gui/gui/src/TRootBrowserLite.cxx index 41d8190a9c31d..bdd460ab79838 100644 --- a/gui/gui/src/TRootBrowserLite.cxx +++ b/gui/gui/src/TRootBrowserLite.cxx @@ -58,6 +58,7 @@ Explorer). The widgets used are the new native ROOT GUI widgets. #include "TInterpreter.h" #include "TGuiBuilder.h" #include "TImage.h" +#include "TASUtils.h" #include "TVirtualPad.h" #include "KeySymbols.h" #include "THashTable.h" @@ -503,11 +504,11 @@ void TRootIconBox::GetObjPictures(const TGPicture **pic, const TGPicture **spic, if (!(*pic) && xpm) { if (im && im->SetImageBuffer((char**)&name, TImage::kXpm)) { - *pic = fClient->GetPicturePool()->GetPicture(iconname, GetImagePixmap(im), - GetImageMask(im)); + *pic = fClient->GetPicturePool()->GetPicture(iconname, TASUtils::GetPixmap(im), + TASUtils::GetMask(im)); im->Scale(im->GetWidth()/2, im->GetHeight()/2); - *spic = fClient->GetPicturePool()->GetPicture(iconname, GetImagePixmap(im), - GetImageMask(im)); + *spic = fClient->GetPicturePool()->GetPicture(iconname, TASUtils::GetPixmap(im), + TASUtils::GetMask(im)); } fClient->GetMimeTypeList()->AddType("[thumbnail]", iconname, iconname, iconname, "->Browse()"); @@ -1746,9 +1747,9 @@ void TRootBrowserLite::ExecuteDefaultAction(TObject *obj) img->Merge(img, "tint"); // contrasting img->DrawBox(0, 0, w, h, "#ffff00", 1); // yellow frame - pic = fClient->GetPicturePool()->GetPicture(path.Data(), GetImagePixmap(img), 0); + pic = fClient->GetPicturePool()->GetPicture(path.Data(), TASUtils::GetPixmap(img), 0); img->Scale(w/3, h/3); - spic = fClient->GetPicturePool()->GetPicture(path.Data(), GetImagePixmap(img), 0); + spic = fClient->GetPicturePool()->GetPicture(path.Data(), TASUtils::GetPixmap(img), 0); thumb = new TIconBoxThumb(path.Data(), spic, pic); fIconBox->fThumbnails->Add(thumb); diff --git a/gui/guibuilder/CMakeLists.txt b/gui/guibuilder/CMakeLists.txt index d468d540881bc..063dca47863b6 100644 --- a/gui/guibuilder/CMakeLists.txt +++ b/gui/guibuilder/CMakeLists.txt @@ -29,4 +29,5 @@ ROOT_STANDARD_LIBRARY_PACKAGE(GuiBld Gui Graf MathCore + ASImageUtils ) diff --git a/gui/guibuilder/src/TGuiBldDragManager.cxx b/gui/guibuilder/src/TGuiBldDragManager.cxx index 86272f37864ce..ca03f64174751 100644 --- a/gui/guibuilder/src/TGuiBldDragManager.cxx +++ b/gui/guibuilder/src/TGuiBldDragManager.cxx @@ -21,6 +21,7 @@ #include "TROOT.h" #include "TColor.h" #include "TImage.h" +#include "TASUtils.h" #include "TError.h" #include "TClassMenuItem.h" @@ -3296,7 +3297,7 @@ Bool_t TGuiBldDragManager::Save(const char *file) static std::unique_ptr img; - img = TGWindow::CreateImageFromWindow(main->GetId()); + img = TASUtils::FromWindow(main->GetId()); if (!file || !file[0]) { static TString dir("."); @@ -3362,7 +3363,7 @@ Bool_t TGuiBldDragManager::SaveFrame(const char *file) static std::unique_ptr img; - img = TGWindow::CreateImageFromWindow(frame->GetId()); + img = TASUtils::FromWindow(frame->GetId()); static TString dir("."); static Bool_t overwr = kFALSE; diff --git a/gui/guibuilder/src/TRootGuiBuilder.cxx b/gui/guibuilder/src/TRootGuiBuilder.cxx index af371cf6c0505..cef94f8af2d71 100644 --- a/gui/guibuilder/src/TRootGuiBuilder.cxx +++ b/gui/guibuilder/src/TRootGuiBuilder.cxx @@ -35,6 +35,7 @@ #include "TRootHelpDialog.h" #include "TGListTree.h" #include "TImage.h" +#include "TASUtils.h" #include "TGTextEdit.h" #include "TGTab.h" #include "TGListBox.h" @@ -1601,7 +1602,7 @@ Bool_t TRootGuiBuilder::SaveProject(Event_t *event) static std::unique_ptr img; - img = TGWindow::CreateImageFromWindow(savfr->GetParent()->GetId()); + img = TASUtils::FromWindow(savfr->GetParent()->GetId()); TGWindow *root = (TGWindow*)fClient->GetRoot(); TGFileInfo fi; @@ -1690,7 +1691,7 @@ void TRootGuiBuilder::AddMacro(const char *macro, TImage *img) static int i = 0; const TGPicture *pic = fClient->GetPicturePool()->GetPicture( TString::Format("%s;%d", macro, i++), - GetImagePixmap(img), GetImageMask(img)); + TASUtils::GetPixmap(img), TASUtils::GetMask(img)); const char *name = gSystem->BaseName(macro); TGButton *btn = FindActionButton(name, "User's Macros"); diff --git a/gui/guihtml/src/TGHtmlDraw.cxx b/gui/guihtml/src/TGHtmlDraw.cxx index eb7ce7804ef4d..c506c54f333e5 100644 --- a/gui/guihtml/src/TGHtmlDraw.cxx +++ b/gui/guihtml/src/TGHtmlDraw.cxx @@ -903,7 +903,7 @@ void TGHtml::DrawTableBgnd(int l, int t, int w, int h, w -= sw; } #else - auto img_pixmap = TGWindow::GetImagePixmap(image); + auto img_pixmap = TASUtils::GetPixmap(image); if (!img_pixmap) return; GContext_t gc = GetAnyGC(); GCValues_t gcv; diff --git a/gui/guihtml/src/TGHtmlSizer.cxx b/gui/guihtml/src/TGHtmlSizer.cxx index 46dff10b952fb..433c2c2db4a9e 100644 --- a/gui/guihtml/src/TGHtmlSizer.cxx +++ b/gui/guihtml/src/TGHtmlSizer.cxx @@ -27,6 +27,7 @@ #include "TGHtml.h" #include "TImage.h" +#include "TASUtils.h" #include "TVirtualX.h" #include @@ -353,10 +354,10 @@ void TGHtml::AddStyle(TGHtmlElement *p) // unsigned int mask; // mask = kGCTile | kGCFillStyle | kGCGraphicsExposures; - gcv.fTile = TGWindow::GetImagePixmap(img); + gcv.fTile = TASUtils::GetPixmap(img); gcv.fFillStyle = kFillTiled; gcv.fGraphicsExposures = kTRUE; - fCanvas->SetBackgroundPixmap(TGWindow::GetImagePixmap(img)); + fCanvas->SetBackgroundPixmap(TASUtils::GetPixmap(img)); gVirtualX->ChangeGC(fWhiteGC.GetGC(), &gcv); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2eebde410858f..c4d75e93b327a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -207,7 +207,7 @@ ROOT_ADD_TEST(test-stresshistogram-interpreted COMMAND ${root_exe} -b -q ${CMAKE #--stressGUI--------------------------------------------------------------------------------------- if(asimage) - ROOT_EXECUTABLE(stressGUI stressGUI.cxx LIBRARIES Gui Recorder GuiHtml ASImageGui) + ROOT_EXECUTABLE(stressGUI stressGUI.cxx LIBRARIES Gui Recorder GuiHtml ASImageUtils ASImageGui) find_program(XVFB_RUN_EXECUTABLE NAMES xvfb-run) diff --git a/test/stressGUI.cxx b/test/stressGUI.cxx index 52f9b4b407b72..3556d867a7e8f 100644 --- a/test/stressGUI.cxx +++ b/test/stressGUI.cxx @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -175,7 +176,7 @@ void ProcessFrame(TGFrame *f, const char *title) outfile.Form("sgui_%02d.png", gTestNum); f->RaiseWindow(); - auto img = TGWindow::CreateImageFromWindow(f->GetId()); + auto img = TASUtils::FromWindow(f->GetId()); if (img) img->WriteImage(outfile); diff --git a/tutorials/visualisation/gui/drag_and_drop.C b/tutorials/visualisation/gui/drag_and_drop.C index 63bdaded3acdb..ce35f6eb84352 100644 --- a/tutorials/visualisation/gui/drag_and_drop.C +++ b/tutorials/visualisation/gui/drag_and_drop.C @@ -195,7 +195,7 @@ DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) : TGMainFrame(p, w, if (img) { // create a 16x16 icon from the original picture img->Scale(16, 16); - pic = gClient->GetPicturePool()->GetPicture("rose512", TGWindow::GetImagePixmap(img), TGWindow::GetImageMask(img)); + pic = gClient->GetPicturePool()->GetPicture("rose512", TASUtils::GetPixmap(img), TASUtils::GetMask(img)); delete img; } else pic = gClient->GetPicture("psp_t.xpm"); @@ -284,7 +284,7 @@ void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data) TImage *img2 = TImage::Open("slink_t.xpm"); if (img1 && img2) { img1->Merge(img2); - pic = gClient->GetPicturePool()->GetPicture("doc_lnk", TGWindow::GetImagePixmap(img1), TGWindow::GetImageMask(img1)); + pic = gClient->GetPicturePool()->GetPicture("doc_lnk", TASUtils::GetPixmap(img1), TASUtils::GetMask(img1)); delete img2; delete img1; } else diff --git a/tutorials/visualisation/gui/exec_macro.C b/tutorials/visualisation/gui/exec_macro.C index da6ad424c73db..67bf8f0214463 100644 --- a/tutorials/visualisation/gui/exec_macro.C +++ b/tutorials/visualisation/gui/exec_macro.C @@ -61,7 +61,7 @@ Int_t exec_macro(const char *macro, Bool_t comp = kFALSE, Bool_t save = kTRUE) outfile.ReplaceAll(".C", TString::Format("_%d.png", ++nMainFrames)); win->RaiseWindow(); - auto img = TGWindow::CreateImageFromWindow(win->GetId()); + auto img = TASUtils::FromWindow(win->GetId()); if (img) img->WriteImage(outfile.Data()); }