Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9153412
[x11] small fix in TGX11::SetAttText
linev Apr 15, 2026
9a142b4
[win32] add proper comment to new methods
linev Apr 15, 2026
c2d25f4
[virtualx] add SetOpacityW and CopyPixmapW methods
linev Apr 15, 2026
79e2c07
[tgx11] implement SetOpacityW and CopyPixmapW methods
linev Apr 15, 2026
16ebb79
[mac] implement SetOpacityW and CopyPixmapW methods
linev Apr 15, 2026
e155eaa
[win32] implement SetOpacityW and CopyPixmapW methods
linev Apr 15, 2026
6c93063
[pad] use new methods to set opacity and copy pixmap
linev Apr 15, 2026
a00a46f
[pad] move special fill attributes handling to TPad::PaintBorder
linev Apr 15, 2026
1e45fe9
[pad] handle fill styles 4000..4100 in Cocoa and GL
linev Apr 16, 2026
728503e
[padpainterbase] add method to handle fill styles 4000..4100
linev Apr 17, 2026
55a0543
[pspainter] support fill styles 4000..4100
linev Apr 17, 2026
3299b79
[glpainter] support fill styles 4000..4100
linev Apr 17, 2026
729b893
[padpainter] support fill styles 4000..4100
linev Apr 17, 2026
61a067c
[pad] allow fill styles 4000..4100 for all pad painters
linev Apr 17, 2026
65b666b
[pad] adjust PaintBox
linev Apr 17, 2026
d5542d3
Extend TAttFill docu for supported styles 4000..4100
linev Apr 17, 2026
9d5e05f
Adjust transparentpad.C demo
linev Apr 17, 2026
cf594b4
Adjust stressGraphics_web.ref fillpatterns
linev Apr 17, 2026
e7c3446
[tgx11] use pad fill color to create opacity
linev Apr 20, 2026
8586f11
[tpad] set fill attributes when create pad opacity
linev Apr 20, 2026
6efe71b
[tgx11] remove CollectImageColors and FindColor methods
linev Apr 20, 2026
f272018
[tgx11] use std::vector for new colors
linev Apr 20, 2026
ab9a7c9
[tgwin32] use pad fill color to create opacity
linev Apr 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/base/inc/TVirtualX.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe
virtual EDrawMode GetDrawModeW(WinContext_t wctxt);
virtual void ClearWindowW(WinContext_t wctxt);
virtual void UpdateWindowW(WinContext_t wctxt, Int_t mode);
virtual void SetOpacityW(WinContext_t wctxt, Int_t percent);
virtual void CopyPixmapW(WinContext_t wctxt, Int_t wid, Int_t xpos, Int_t ypos);

virtual void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode);
virtual void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy);
Expand Down
18 changes: 9 additions & 9 deletions core/base/src/TAttFill.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,13 @@ method `GetFillStyle`.

- 0 : hollow
- 1001 : Solid
- 3000+pattern_number (see below)
- For TPad only:
- 3000 + pattern_number (see below)
- 4000..4100: 100% transparent .. 100% opaque

- 4000 :the window is transparent.
- 4000 to 4100 the window is 100% transparent to 100% opaque.

The pad transparency is visible in binary outputs files like gif, jpg, png etc ..
but not in vector graphics output files like PS, PDF and SVG. This convention
(fill style > 4000) is kept for backward compatibility. It is better to use
the color transparency instead.
Historically the styles between 4000 and 4100 were introduced to implement pad
transparency on platforms like X11 which does not support alpha channel in color.
Since ROOT 6.40 any objects can use such fill styles. On supported platforms like
Cocoa or GL or PS/PDF/SVG output style will be automatically converted to transparent colors.

pattern_number can have any value from 1 to 25 (see table), or any
value from 100 to 999. For the latest the numbering convention is the following:
Expand Down Expand Up @@ -268,6 +265,9 @@ void TAttFill::SetFillColorAlpha(Color_t fcolor, Float_t falpha)
fFillColor = TColor::GetColorTransparent(fcolor, falpha);
}

////////////////////////////////////////////////////////////////////////////////
/// Set a fill color.

void TAttFill::SetFillColor(TColorNumber lcolor)
{
SetFillColor(lcolor.number());
Expand Down
16 changes: 16 additions & 0 deletions core/base/src/TVirtualX.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,22 @@ void TVirtualX::UpdateWindowW(WinContext_t /* wctxt */, Int_t mode)
UpdateWindow(mode);
}

////////////////////////////////////////////////////////////////////////////////
/// Set opactity for specified window

void TVirtualX::SetOpacityW(WinContext_t /* wctxt */, Int_t percent)
{
SetOpacity(percent);
}

////////////////////////////////////////////////////////////////////////////////
/// Copy pixmap to specified window

void TVirtualX::CopyPixmapW(WinContext_t /* wctxt */, Int_t wid, Int_t xpos, Int_t ypos)
{
CopyPixmap(wid, xpos, ypos);
}

////////////////////////////////////////////////////////////////////////////////
/// Draw box on specified window

Expand Down
1 change: 1 addition & 0 deletions graf2d/cocoa/inc/TGCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ class TGCocoa : public TVirtualX {
EDrawMode GetDrawModeW(WinContext_t wctxt) override;
void ClearWindowW(WinContext_t wctxt) override;
void UpdateWindowW(WinContext_t wctxt, Int_t mode) override;
void CopyPixmapW(WinContext_t wctxt, Int_t wid, Int_t xpos, Int_t ypos) override;

//-Functions used by GUI.
Window_t CreateWindow(Window_t parent, Int_t x, Int_t y,
Expand Down
1 change: 1 addition & 0 deletions graf2d/cocoa/inc/TGQuartz.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class TGQuartz : public TGCocoa {
Float_t GetTextMagnitude() override;

//---- Methods used for new graphics -----
void SetOpacityW(WinContext_t wctxt, Int_t percent) override;
void SetAttFill(WinContext_t wctxt, const TAttFill &att) override;
void SetAttLine(WinContext_t wctxt, const TAttLine &att) override;
void SetAttMarker(WinContext_t wctxt, const TAttMarker &att) override;
Expand Down
17 changes: 12 additions & 5 deletions graf2d/cocoa/src/TGCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2430,27 +2430,34 @@ void FixAscii(std::vector<UniChar> &text)
//______________________________________________________________________________
void TGCocoa::CopyPixmap(Int_t pixmapID, Int_t x, Int_t y)
{
assert(pixmapID > (Int_t)fPimpl->GetRootWindowID() &&
"CopyPixmap, parameter 'pixmapID' is not a valid id");
assert(fSelectedDrawable > fPimpl->GetRootWindowID() &&
"CopyPixmap, fSelectedDrawable is not a valid window id");

CopyPixmapW((WinContext_t) fPimpl->GetDrawable(fSelectedDrawable), pixmapID, x, y);
}

//______________________________________________________________________________
void TGCocoa::CopyPixmapW(WinContext_t wctxt, Int_t pixmapID, Int_t x, Int_t y)
{
assert(pixmapID > (Int_t)fPimpl->GetRootWindowID() &&
"CopyPixmapW, parameter 'pixmapID' is not a valid id");

NSObject<X11Drawable> * const source = fPimpl->GetDrawable(pixmapID);
assert([source isKindOfClass : [QuartzPixmap class]] &&
"CopyPixmap, source is not a pixmap");
QuartzPixmap * const pixmap = (QuartzPixmap *)source;

NSObject<X11Drawable> * const drawable = fPimpl->GetDrawable(fSelectedDrawable);
auto drawable = (NSObject<X11Drawable> * const) wctxt;
NSObject<X11Drawable> * destination = nil;

if (drawable.fIsPixmap) {
destination = drawable;
} else {
NSObject<X11Window> * const window = fPimpl->GetWindow(fSelectedDrawable);
NSObject<X11Window> * const window = (NSObject<X11Window> * const) drawable;
if (window.fBackBuffer) {
destination = window.fBackBuffer;
} else {
Warning("CopyPixmap", "Operation skipped, since destination"
Warning("CopyPixmapW", "Operation skipped, since destination"
" window is not double buffered");
return;
}
Expand Down
4 changes: 4 additions & 0 deletions graf2d/cocoa/src/TGQuartz.mm
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,10 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector<TPoin
// colors).
}

//______________________________________________________________________________
void TGQuartz::SetOpacityW(WinContext_t /* wctxt */, Int_t /* percent */)
{
}

//______________________________________________________________________________
void TGQuartz::SetAttFill(WinContext_t wctxt, const TAttFill &att)
Expand Down
1 change: 1 addition & 0 deletions graf2d/gpad/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(Gpad
src/TGroupButton.cxx
src/TInspectCanvas.cxx
src/TPad.cxx
src/TPadPainterBase.cxx
src/TPadPainter.cxx
src/TPadPainterPS.cxx
src/TPaveClass.cxx
Expand Down
3 changes: 1 addition & 2 deletions graf2d/gpad/inc/TPad.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,7 @@ friend class TWebCanvas;
TPad(const TPad &pad) = delete;
TPad &operator=(const TPad &rhs) = delete;

void CopyBackgroundPixmap(Int_t x, Int_t y);
void CopyBackgroundPixmaps(TPad *start, TPad *stop, Int_t x, Int_t y);
void CopyBackgroundPixmaps(TPad *stop, Int_t x, Int_t y);
void DrawDist(Rectangle_t aBBox, Rectangle_t bBBox, char mode);

Bool_t Collide(Int_t i, Int_t j, Int_t w, Int_t h);
Expand Down
3 changes: 3 additions & 0 deletions graf2d/gpad/inc/TPadPainterBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class TPadPainterBase : public TVirtualPadPainter {
TAttLine fAttLine; ///< current line attributes
TAttMarker fAttMarker; ///< current marker attributes
TAttText fAttText; ///< current text attributes
Bool_t fFullyTransparent = kFALSE; ///< if transformed fill attributes fully transparent

TAttFill GetAttFillInternal(Bool_t with_transparency);

public:

Expand Down
163 changes: 57 additions & 106 deletions graf2d/gpad/src/TPad.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -744,13 +744,9 @@ void TPad::Clear(Option_t *option)
}

auto pp = GetPainter();
// If pad painter uses PS, ClearDrawable() start new page
if (pp) {
if (pp->IsNative())
pp->ClearDrawable();
else if (this == GetCanvas())
pp->NewPage();
}
// If pad painter uses PS, TPad::Clear() start new page
if (pp && pp->GetPS())
pp->NewPage();

PaintBorder(GetFillColor(), kTRUE);
fCrosshairPos = 0;
Expand Down Expand Up @@ -3660,23 +3656,40 @@ void TPad::PaintBorder(Color_t color, Bool_t /* tops */)
pp->OnPad(this);

if (color >= 0) {
TAttLine::Modify(); //Change line attributes only if necessary
TAttFill::Modify(); //Change fill area attributes only if necessary

//With Cocoa we have a transparency. But we also have
//pixmaps, and if you just paint a new content over the old one
//with alpha < 1., you'll be able to see the old content.
if (pp->IsNative() && pp->IsCocoa())
Bool_t do_paint_box = kTRUE;

Style_t style = GetFillStyle();
if (!IsBatch() && (pp->IsCocoa() || (pp->IsNative() && (style > 3000) && (style < 3026))))
pp->ClearDrawable();

PaintBox(fX1, fY1, fX2, fY2);
}
if (color < 0)
// special only for transparent pads in plain X11;
// Cocoa, GL, Web and PS implement transparency different
if ((style >= 4000) && (style <= 4100) && pp->IsNative() && !pp->IsCocoa() && !pp->GetPS() && !(fCanvas && fCanvas->UseGL()) && !IsWeb() && !IsBatch()) {
if (this == fMother) {
style = 1001;
} else {
// copy all pixmaps
do_paint_box = kFALSE;
Int_t px, py;
XYtoAbsPixel(GetX1(), GetY2(), px, py);
if (fMother)
fMother->CopyBackgroundPixmaps(this, px, py);
pp->SetAttFill({color, 1001}); // use fill color producing opacity
pp->SetOpacity(style - 4000);
}
} else if ((color == 10) && (style > 3000) && (style < 3100))
color = 1;

if (do_paint_box) {
pp->SetAttFill({color, style});
pp->SetAttLine(*this);
PaintBox(fX1, fY1, fX2, fY2);
}
} else
color = -color;
if (IsTransparent())
return;

if (fBorderMode == 0)
if (IsTransparent() || (fBorderMode == 0))
return;

// then paint 3d frame (depending on bordermode)
Expand Down Expand Up @@ -3802,14 +3815,8 @@ void TPad::PaintModified()
fPadPaint = 1;
{
TContext ctxt(this, kTRUE);
if (IsModified() || IsTransparent()) {
if ((fFillStyle < 3026) && (fFillStyle > 3000)) {
auto pp = GetPainter();
if (pp && pp->IsNative())
pp->ClearDrawable();
}
if (IsModified() || IsTransparent())
PaintBorder(GetFillColor(), kTRUE);
}

PaintDate();

Expand Down Expand Up @@ -3868,113 +3875,57 @@ void TPad::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t

pp->OnPad(this);

TAttFill att = pp->GetAttFill();

Int_t style0 = -1111, style = att.GetFillStyle();
Bool_t draw_border = kFALSE, draw_fill = kFALSE;
if (option && *option == 's') {
style0 = style;
att.SetFillStyle(0);
pp->SetAttFill(att);
style = 0;
draw_border = kTRUE;
} else if (option && *option == 'l')
Style_t style = pp->GetAttFill().GetFillStyle();
Bool_t draw_border = kFALSE, draw_fill = kFALSE, skip_fill = kFALSE;
if (option && *option == 's')
skip_fill = draw_border = kTRUE;
else if (option && *option == 'l')
draw_border = kTRUE;

if (style >= 3100 && style < 4000) {
Double_t xb[4] = {x1, x1, x2, x2};
Double_t yb[4] = {y1, y2, y2, y1};
PaintFillAreaHatches(4, xb, yb, style);
} else if (pp->GetPS()) {
draw_fill = kTRUE;
if (style == 0)
draw_border = kFALSE;
} else if ((style > 0) && (style < 1000)) {
} else if (style >= 0 && style < 1000) {
draw_border = kTRUE;
} else if ((style >= 1000) && (style < 2000)) {
} else if (style >= 1000 && style < 2000) {
draw_fill = kTRUE;
} else if (style > 3000 && style < 3100) {
if (style < 3026)
pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
//special case for TAttFillCanvas on real display
if (att.GetFillColor() == 10) {
// SL: reproduce old sequence of painting calls, can have some side effects on opaque pads
att.SetFillColor(1);
pp->SetAttFill(att);
pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);
att.SetFillColor(10);
pp->SetAttFill(att);
}
draw_fill = style < 3026;
} else if (style >= 4000 && style <= 4100) {
// For style >=4000 we make the window transparent.
// From 4000 to 4100 the window is 100% transparent to 100% opaque

//ignore this style option when this is the canvas itself
if (this == fMother) {
//It's clear, that virtual X checks a style (4000) and will render a hollow rect!
if (pp->IsCocoa()) {
style0 = style;
att.SetFillStyle(1000);
pp->SetAttFill(att);
}
draw_fill = kTRUE;
} else {
//draw background by blitting all bottom pads
int px, py;
XYtoAbsPixel(fX1, fY2, px, py);

if (fMother) {
fMother->CopyBackgroundPixmap(px, py);
CopyBackgroundPixmaps(fMother, this, px, py);
}

pp->SetOpacity(style - 4000);
}
// transparency styles, supported now by all painters
draw_fill = style > 4000;
} else if (style > 0)
draw_border = kTRUE;

if (draw_fill)
if (draw_fill && !skip_fill)
pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kFilled);

if (draw_border)
pp->DrawBox(x1, y1, x2, y2, TVirtualPadPainter::kHollow);

if (style0 != -1111) {
att.SetFillStyle(style0);
pp->SetAttFill(att);
}

Modified();
}

////////////////////////////////////////////////////////////////////////////////
/// Copy pixmaps of pads laying below pad "stop" into pad "stop". This
/// gives the effect of pad "stop" being transparent.

void TPad::CopyBackgroundPixmaps(TPad *start, TPad *stop, Int_t x, Int_t y)
void TPad::CopyBackgroundPixmaps(TPad *stop, Int_t x, Int_t y)
{
if (!start) return;
TObject *obj;
if (!fPrimitives) fPrimitives = new TList;
TIter next(start->GetListOfPrimitives());
while ((obj = next())) {
if (obj->InheritsFrom(TPad::Class())) {
if (obj == stop) break;
((TPad*)obj)->CopyBackgroundPixmap(x, y);
((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
}
}
}

////////////////////////////////////////////////////////////////////////////////
/// Copy pixmap of this pad as background of the current pad.
Int_t px, py;
XYtoAbsPixel(GetX1(), GetY2(), px, py);
/// Copy pixmap of this pad as background of the current pad.
if (auto pp = GetPainter())
pp->CopyDrawable(GetPixmapID(), px - x, py - y);

void TPad::CopyBackgroundPixmap(Int_t x, Int_t y)
{
int px, py;
XYtoAbsPixel(fX1, fY2, px, py);
if (GetPainter())
GetPainter()->CopyDrawable(GetPixmapID(), px-x, py-y);
TIter next(GetListOfPrimitives());
while (auto obj = next()) {
if (obj == stop)
break;
if (auto pad = dynamic_cast<TPad *>(obj))
pad->CopyBackgroundPixmaps(stop, x, y);
}
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading
Loading