Title and Label size scaling inconsistent behaviour

Documentation says that font size scale is proportional to pad size.. whatever this mean.

So I run a small demo (attached as MWE). I choose a base size of 300 px, and made four canvases with width and height being:

  • 1x1 of base size
  • 1x2 of base size
  • 2x1 of base size
  • 2x2 of base size

I use the 1x1 as a reference. For 2x1 it seems like x and y title is of the same size, although pad is twice larger. For 1x2, the pad is also twice large but now x and y titles are slightly larger. For 2x2 canvas, which is four times larger, the titles are twice larger (or four times in surface).

For 1x2 canvas also label offset on the x axis is larger than in other three canvases. All boxes for axis titles are of the same size. Same goes for the histogram title.

So there is some inconsistency, perhaps some buggy behaviour? Can you comment on that and perhaps update the documentation about how the canvas-size scaling works?


Please read tips for efficient and successful posting and posting code

To Reproduce

font_size.C (944 Bytes)

Setup

ROOT v6.36.04
Built for linuxx8664gcc on Sep 05 2025, 08:28:36
From tags/6-36-04@6-36-04
With 
Binary directory: /usr/bin

Hi,

For text scaling pad size is used - which is minimal value from pad width and height.

Regards,
Sergey

To get the same text size among various pads you need to use pixel size (text precision =3)

I know I need to change precision to pixel level. But comment by Sergey made me checking the pad size and this surprises me that, when I specify eg TCanvas with size 300x300, I would expect to have true 300x300 drawing canvas. But the pad itself is smaller and not rectangular. So apparently the menu bar is included in the 300px height.

With that, also my histogram is not squared, and I might need perfectly squared one.

So that means if I want to have true square pad 300x300 I need to specify canvas of size 302x329, which is blah. Twice larger TCanvas of 600x600 is actually not twice larger, because it is always fixed (W-2, H-29) size.

Is it something that you would consider to be fixed?

In the picture below, in the center there is square green box. Histogram clearly is not squared.
The filled green should mark equal margins which are all set to 0.15.
The number in the middle are: gPad->GetWw() x gPad->GetWh().

See the explanation in the TCanvas doc header.

Thanks to pointing me to this, I must have missed that completely. I don’t like this however (it’s mess, honestly) because I must then store the width and height separately, and this is a lot of boilerplate code for things which actually should work from scratch.

I was thinking if I could avoid saving the width/height or hardcode it.

The constructor TCanvas::TCanvas(const char *name, const char *title, Int_t ww, Int_t wh) ROOT: TCanvas Class Reference
calls void TCanvas::Constructor(const char *name, const char *title, Int_t ww, Int_t wh) ROOT: TCanvas Class Reference
which sets:

   fCw       = ww;
   fCh       = wh;

and in the header:

UInt_t GetWw() const override { return fCw; }
UInt_t GetWh() const override { return fCh; }

but the values I am receiving here are not equal to what I put into constructor.
Then I found void TCanvas::Build() ROOT: TCanvas Class Reference which does this magic:

      fCw -= 4;
      fCh -= 28;

in the batch mode (what about not batch mode), but this even does not match the numbers I am receiving, because for 300x300 canvas I am getting 298x271, not 296x272.

OK, anyway reading the constructor, surprise for me, the parameters are not canvas size but windows size… who would thought.

So actually now TCanvas::GetWindowWidth() and TCanvas::GetWindowHeight() work. So the example you are pointing out could be also shown as:

auto c = new TCanvas("c", "c", 600, 600);
c->SetWindowSize(c->GetWindowWidth() + (c->GetWindowWidth() - c->GetWw()),
                 c->GetWindowHeight() + (c->GetWindowHeight() - c->GetWh()));

And sorry I am dissing this, but the interface logic is just poor. If I create a canvas I expect to determine the canvas size, and the window should be adjusted to it. Not that I define window and canvas is adjusted. Now one need to make additional step to get what he wants.

I still think this is a bug and not feature, but for sake of backward compatibility, it rather won’t be fixed, right?

You huys do great job with root, but sometimes some design decision are hard to understand.

In short, from the Documentation linked by couet, the key method is TCanvas::SetCanvasSize(); with which you’ll get the size you want, independently of the canvas window size (see also the example here).

Ok, some solution but also not great. I would like to have a canvas of specific size and window adjusted to it. No some scroll bars.

The interface and logic is just bad.

Well, I think the problem is that every desktop environment (not just different OSes –Windows, MacOS, Linux…– but even their versions, flavours, etc,… not to mention different themes!) has different window decoration sizes, so to create a window of a specific size does not guarantee that the area inside the window will have a given size, unless you know all the widths of the 4 window frame sides; there may or may not be a way to get that info from the system, I don’t know :slight_smile: and I don’t know either whether one can ask the system’s window manager to create a window with a specific “contents” area size.

I understand that those can be issues and perhaps the order must be that you first make the window and then you see what is left for canvas (but I am pretty sure the GUI allows you to get the expected decorations size prior to creating the window) but then the procedure of adjusting the canvas size like suggested in the doc should be just a part of the canvas constructing, that you get the canvas you requested.