From ba94d85cb861c27e85590ac28fa7559e67f5db1a Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 10:32:36 +0200 Subject: [PATCH 01/12] [virtualx] mark no longer used methods --- core/base/inc/TVirtualX.h | 6 ++++-- graf2d/x11/inc/TGX11.h | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/base/inc/TVirtualX.h b/core/base/inc/TVirtualX.h index 70a0884432bec..b0152d3e66a55 100644 --- a/core/base/inc/TVirtualX.h +++ b/core/base/inc/TVirtualX.h @@ -63,12 +63,13 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void ClearWindow(); virtual void ClosePixmap(); virtual void CloseWindow(); - virtual void CopyPixmap(Int_t wid, Int_t xpos, Int_t ypos); virtual void CreateOpenGLContext(Int_t wid=0); virtual void DeleteOpenGLContext(Int_t wid=0); - //---- Old graphics interface ----- + //---- Old, no longer used graphics interface ----- + + virtual void CopyPixmap(Int_t wid, Int_t xpos, Int_t ypos); void SetFillColor(Color_t cindex) override; void SetFillStyle(Style_t style) override; @@ -101,6 +102,7 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode); + //---- New graphics interface ----- virtual WinContext_t GetWindowContext(Int_t wid); diff --git a/graf2d/x11/inc/TGX11.h b/graf2d/x11/inc/TGX11.h index f3c8af94f29e1..bda1740520c7f 100644 --- a/graf2d/x11/inc/TGX11.h +++ b/graf2d/x11/inc/TGX11.h @@ -126,13 +126,16 @@ friend struct XWindow_t; Bool_t AllocColor(Colormap cmap, RXColor *color); void QueryColors(Colormap cmap, RXColor *colors, Int_t ncolors); - void *GetGC(Int_t which) const; Window_t GetWindow(WinContext_t wctxt) const; void *GetGCW(WinContext_t wctxt, Int_t which) const; EAlign GetTextAlignW(WinContext_t wctxt) const; XColor_t &GetColor(Int_t cid); + //---- Methods used for old graphics ----- + void *GetGC(Int_t which) const; + + TGX11(TGX11 &&org); TGX11(const TGX11 &org) = delete; From 06f80611e03367e1e5fb89adb2b8e7264fd82788 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:03:25 +0200 Subject: [PATCH 02/12] Add TAttText::GetTextSizePixels() Very often used method to calculate text size in pixels for specified pad. Important that now pad is used as parameter --- core/base/inc/TAttText.h | 3 ++- core/base/src/TAttText.cxx | 37 ++++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/core/base/inc/TAttText.h b/core/base/inc/TAttText.h index d857a257facc0..792fed075d826 100644 --- a/core/base/inc/TAttText.h +++ b/core/base/inc/TAttText.h @@ -37,7 +37,8 @@ class TAttText { virtual Color_t GetTextColor() const {return fTextColor;} ///< Return the text color virtual Font_t GetTextFont() const {return fTextFont;} ///< Return the text font virtual Float_t GetTextSize() const {return fTextSize;} ///< Return the text size - virtual Float_t GetTextSizePercent(Float_t size); ///< Return the text in percent of the pad size + virtual Float_t GetTextSizePercent(Float_t size); ///< Return the text in percent of the pad size + virtual Float_t GetTextSizePixels(TVirtualPad &pad) const; ///< Return the text size in pixels for specified pad virtual void Modify(); virtual void ModifyOn(TVirtualPad &pad); virtual void ResetAttText(Option_t *toption=""); diff --git a/core/base/src/TAttText.cxx b/core/base/src/TAttText.cxx index 2e078add3b152..853c90e141799 100644 --- a/core/base/src/TAttText.cxx +++ b/core/base/src/TAttText.cxx @@ -16,6 +16,7 @@ #include "TVirtualPad.h" #include "TVirtualPadPainter.h" #include "TVirtualPadEditor.h" +#include "TMathBase.h" #include "TStyle.h" #include "TError.h" #include "TColor.h" @@ -301,7 +302,7 @@ void TAttText::Copy(TAttText &atttext) const } //////////////////////////////////////////////////////////////////////////////// -/// Return the text in percent of the pad size. +/// Return the text size in percent of the pad size. /// /// If the font precision is greater than 2, the text size returned is the size in pixel /// converted into percent of the pad size, otherwise the size returned is the same as the @@ -311,16 +312,31 @@ Float_t TAttText::GetTextSizePercent(Float_t size) { Float_t rsize = size; if (fTextFont%10 > 2 && gPad) { - UInt_t w = gPad->WtoAbsPixel(gPad->GetX1(), gPad->GetX2()); - UInt_t h = gPad->HtoAbsPixel(gPad->GetY1(), gPad->GetY2()); - if (w < h) - rsize = rsize/w; - else - rsize = rsize/h; + auto ww = gPad->WtoAbsPixel(gPad->GetX1(), gPad->GetX2()); + auto hh = gPad->HtoAbsPixel(gPad->GetY1(), gPad->GetY2()); + rsize = rsize / TMath::Max(1, TMath::Min(ww, hh)); } return rsize; } + +//////////////////////////////////////////////////////////////////////////////// +/// Return the text size in pixels for the specified pad +/// +/// If the font precision less than 2 size defined as percent of pad size and +/// scaled to minimal pad size + +Float_t TAttText::GetTextSizePixels(TVirtualPad &pad) const +{ + Float_t tsize = GetTextSize(); + if (GetTextFont() % 10 <= 2) { + auto wh = pad.XtoPixel(pad.GetX2()); + auto hh = pad.YtoPixel(pad.GetY1()); + tsize *= TMath::Min(wh, hh); + } + return tsize; +} + //////////////////////////////////////////////////////////////////////////////// /// Change current text attributes if necessary. @@ -344,12 +360,7 @@ void TAttText::ModifyOn(TVirtualPad &pad) // there was difference in text size handling, keep it in one place if (pp->IsNative()) { - if (fTextFont % 10 <= 2) { - auto wh = pad.XtoPixel(pad.GetX2()); - auto hh = pad.YtoPixel(pad.GetY1()); - if (wh < hh) tsize *= wh; - else tsize *= hh; - } + tsize = GetTextSizePixels(pad); } else { if (fTextFont % 10 > 2) { Float_t wh = pad.XtoPixel(pad.GetX2()); From ce13b8c6b831bb3a8e77d6efd1f0eae2da87406f Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:23:43 +0200 Subject: [PATCH 03/12] [tvirtualx] introduce new methods for text extension Old methods relies on global attributes which normally related to current window. But text handling does not uses window context. Add new methods where text font and size provided directly. --- core/base/inc/TVirtualX.h | 17 +++++++++++------ core/base/src/TVirtualX.cxx | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/core/base/inc/TVirtualX.h b/core/base/inc/TVirtualX.h index b0152d3e66a55..f85e1503a3fa3 100644 --- a/core/base/inc/TVirtualX.h +++ b/core/base/inc/TVirtualX.h @@ -102,6 +102,13 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode); + virtual void GetTextExtent(UInt_t &w, UInt_t &h, char *mess); + virtual void GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *mess); + virtual Int_t GetFontAscent() const; + virtual Int_t GetFontAscent(const char *mess) const; + virtual Int_t GetFontDescent() const; + virtual Int_t GetFontDescent(const char *mess) const; + //---- New graphics interface ----- @@ -127,6 +134,10 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode); virtual Int_t WriteGIFW(WinContext_t wctxt, const char *name); + virtual Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess); + virtual Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const wchar_t *mess); + virtual Bool_t GetFontAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *mess); + //---- OpenGL related stuff, required only with R__HAS_COCOA ---- virtual Double_t GetOpenGLScalingFactor(); @@ -146,12 +157,6 @@ class TVirtualX : public TNamed, public TAttLine, public TAttFill, public TAttTe virtual ULong_t GetPixel(Color_t cindex); virtual void GetPlanes(Int_t &nplanes); virtual void GetRGB(Int_t index, Float_t &r, Float_t &g, Float_t &b); - virtual void GetTextExtent(UInt_t &w, UInt_t &h, char *mess); - virtual void GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *mess); - virtual Int_t GetFontAscent() const; - virtual Int_t GetFontAscent(const char *mess) const; - virtual Int_t GetFontDescent() const; - virtual Int_t GetFontDescent(const char *mess) const; virtual Float_t GetTextMagnitude(); virtual Window_t GetWindowID(Int_t wid); virtual Bool_t HasTTFonts() const; diff --git a/core/base/src/TVirtualX.cxx b/core/base/src/TVirtualX.cxx index 1fbf1e8616d37..a92cc5ec99193 100644 --- a/core/base/src/TVirtualX.cxx +++ b/core/base/src/TVirtualX.cxx @@ -651,6 +651,34 @@ void TVirtualX::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t * /*mess*/) w = h = 0; } +//////////////////////////////////////////////////////////////////////////////// +/// Returns the size of the specified character string "mess" for font and size. + +Bool_t TVirtualX::GetTextExtentA(Font_t, Double_t, UInt_t &w, UInt_t &h, const char *) +{ + w = h = 0; + return kFALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns the size of the specified character string "mess" for font and size. + +Bool_t TVirtualX::GetTextExtentA(Font_t, Double_t, UInt_t &w, UInt_t &h, const wchar_t *) +{ + w = h = 0; + return kFALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns ascent/descent for specified character string "mess" with font and size. + + +Bool_t TVirtualX::GetFontAscentDescent(Font_t, Double_t, UInt_t &a, UInt_t &d, const char *) +{ + a = d = 0; + return kFALSE; +} + //////////////////////////////////////////////////////////////////////////////// /// Returns the ascent of the current font (in pixels). /// The ascent of a font is the distance from the baseline From 505969fdf0de3e1d057a7204142ee902e472b20d Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:26:01 +0200 Subject: [PATCH 04/12] [x11] implement new methods for text extension Used only when plain X11 without TTF fonts are involved - which is normally not a case. --- graf2d/x11/inc/TGX11.h | 9 ++++++--- graf2d/x11/src/TGX11.cxx | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/graf2d/x11/inc/TGX11.h b/graf2d/x11/inc/TGX11.h index bda1740520c7f..924d81218ac99 100644 --- a/graf2d/x11/inc/TGX11.h +++ b/graf2d/x11/inc/TGX11.h @@ -157,8 +157,6 @@ friend struct XWindow_t; ULong_t GetPixel(Color_t cindex) override; void GetPlanes(Int_t &nplanes) override; void GetRGB(Int_t index, Float_t &r, Float_t &g, Float_t &b) override; - void GetTextExtent(UInt_t &w, UInt_t &h, char *mess) override; - void GetTextExtent(UInt_t &, UInt_t &, wchar_t *) override {} Float_t GetTextMagnitude() override { return fTextMagnitude; } Window_t GetWindowID(Int_t wid) override; Bool_t HasTTFonts() const override { return fHasTTFonts; } @@ -224,6 +222,8 @@ friend struct XWindow_t; void DrawPolyMarker(Int_t n, TPoint *xy) override; void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; void DrawText(Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) override; + void GetTextExtent(UInt_t &w, UInt_t &h, char *mess) override; + void GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *mess) override; //---- Methods used for new graphics ----- WinContext_t GetWindowContext(Int_t wid) override; @@ -239,7 +239,6 @@ friend struct XWindow_t; void CopyPixmapW(WinContext_t wctxt, Int_t wid, Int_t xpos, Int_t ypos) override; Int_t WriteGIFW(WinContext_t wctxt, const char *name) override; - void DrawBoxW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2, EBoxMode mode) override; void DrawFillAreaW(WinContext_t wctxt, Int_t n, TPoint *xy) override; void DrawLineW(WinContext_t wctxt, Int_t x1, Int_t y1, Int_t x2, Int_t y2) override; @@ -249,6 +248,10 @@ friend struct XWindow_t; void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; void DrawTextW(WinContext_t, Int_t, Int_t, Float_t, Float_t, const wchar_t *, ETextMode) override {} + Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess) override; + Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const wchar_t *mess) override; + + //---- Methods used for GUI ----- void GetWindowAttributes(Window_t id, WindowAttributes_t &attr) override; void MapWindow(Window_t id) override; diff --git a/graf2d/x11/src/TGX11.cxx b/graf2d/x11/src/TGX11.cxx index d0e67b47b32a9..c847f1406056f 100644 --- a/graf2d/x11/src/TGX11.cxx +++ b/graf2d/x11/src/TGX11.cxx @@ -1181,19 +1181,47 @@ void TGX11::GetRGB(int index, float &r, float &g, float &b) void TGX11::GetTextExtent(UInt_t &w, UInt_t &h, char *mess) { - w=0; h=0; - if (strlen(mess)==0) return; + w = h = 0; + if (!mess || !*mess) + return; - XPoint *cBox; XRotSetMagnification(fTextMagnitude); - cBox = XRotTextExtents((Display*)fDisplay, gTextFont, 0., 0, 0, mess, 0); + XPoint *cBox = XRotTextExtents((Display*)fDisplay, gTextFont, 0., 0, 0, mess, 0); if (cBox) { w = cBox[2].x; h = -cBox[2].y; - free((char *)cBox); + free(cBox); } } +//////////////////////////////////////////////////////////////////////////////// +/// Return the size of a wcharacter string - not implemented + +void TGX11::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *) +{ + w = h = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return the size of a character string for specified font and size +/// On plain X11 font and size is ignored - just some default font is used + +Bool_t TGX11::GetTextExtentA(Font_t, Double_t, UInt_t &w, UInt_t &h, const char *mess) +{ + GetTextExtent(w, h, (char *)mess); + return kTRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return the size of a wcharacter string - not implemented +/// On plain X11 font and size is ignored - just some default font is used + +Bool_t TGX11::GetTextExtentA(Font_t, Double_t, UInt_t &w, UInt_t &h, const wchar_t *) +{ + w = h = 0; + return kFALSE; +} + //////////////////////////////////////////////////////////////////////////////// /// Return the X11 window identifier. /// From ab31e8d7b3fd36b4f117843d8b460763444516a3 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:27:00 +0200 Subject: [PATCH 05/12] [ttf] use const char and const wchar_t as arguments --- graf2d/graf/inc/TTF.h | 6 +++--- graf2d/graf/src/TTF.cxx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/graf2d/graf/inc/TTF.h b/graf2d/graf/inc/TTF.h index 088d447c39e8a..1663f3d45f148 100644 --- a/graf2d/graf/inc/TTF.h +++ b/graf2d/graf/inc/TTF.h @@ -119,9 +119,9 @@ TTF helper class containing glyphs description. static void SetHinting(Bool_t state); static void SetKerning(Bool_t state); static void SetSmoothing(Bool_t state); - static void GetTextExtent(UInt_t &w, UInt_t &h, char *text); - static void GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *text); - static void GetTextAdvance(UInt_t &a, char *text); + static void GetTextExtent(UInt_t &w, UInt_t &h, const char *text); + static void GetTextExtent(UInt_t &w, UInt_t &h, const wchar_t *text); + static void GetTextAdvance(UInt_t &a, const char *text); static void SetTextFont(Font_t fontnumber); static Int_t SetTextFont(const char *fontname, Int_t italic=0); static void SetTextSize(Float_t textsize); diff --git a/graf2d/graf/src/TTF.cxx b/graf2d/graf/src/TTF.cxx index b7158d7857170..38af54bcd5312 100644 --- a/graf2d/graf/src/TTF.cxx +++ b/graf2d/graf/src/TTF.cxx @@ -161,7 +161,7 @@ void TTF::ComputeTrailingBlanksWidth(Int_t n) //////////////////////////////////////////////////////////////////////////////// /// Get width (w) and height (h) when text is horizontal. -void TTF::GetTextExtent(UInt_t &w, UInt_t &h, char *text) +void TTF::GetTextExtent(UInt_t &w, UInt_t &h, const char *text) { Init(); @@ -178,7 +178,7 @@ void TTF::GetTextExtent(UInt_t &w, UInt_t &h, char *text) //////////////////////////////////////////////////////////////////////////////// /// Get advance (a) when text is horizontal. -void TTF::GetTextAdvance(UInt_t &a, char *text) +void TTF::GetTextAdvance(UInt_t &a, const char *text) { Init(); @@ -192,7 +192,7 @@ void TTF::GetTextAdvance(UInt_t &a, char *text) //////////////////////////////////////////////////////////////////////////////// /// Get width (w) and height (h) when text is horizontal. -void TTF::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *text) +void TTF::GetTextExtent(UInt_t &w, UInt_t &h, const wchar_t *text) { Init(); From 6ec7c96ae4112a8846d486c876de516c73628266 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:27:52 +0200 Subject: [PATCH 06/12] [win32] implement old text extension methods for wchar Anyway TTF is involved --- graf2d/win32gdk/inc/TGWin32.h | 4 ++-- graf2d/win32gdk/src/TGWin32.cxx | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/graf2d/win32gdk/inc/TGWin32.h b/graf2d/win32gdk/inc/TGWin32.h index b7f65541241c2..c6c4bc8df186e 100644 --- a/graf2d/win32gdk/inc/TGWin32.h +++ b/graf2d/win32gdk/inc/TGWin32.h @@ -155,8 +155,6 @@ class TGWin32 : public TVirtualX { ULong_t GetPixel(Color_t cindex) override; void GetPlanes(Int_t &nplanes) override; void GetRGB(Int_t index, Float_t &r, Float_t &g, Float_t &b) override; - virtual void GetTextExtent(UInt_t &w, UInt_t &h, char *mess) override; - virtual void GetTextExtent(UInt_t &, UInt_t &, wchar_t *) override {} Float_t GetTextMagnitude() override {return fTextMagnitude;} Window_t GetWindowID(Int_t wid) override; Bool_t HasTTFonts() const override { return fHasTTFonts; } @@ -204,6 +202,8 @@ class TGWin32 : public TVirtualX { Int_t WriteGIF(char *name) override; void WritePixmap(Int_t wid, UInt_t w, UInt_t h, char *pxname) override; Window_t GetCurrentWindow() const override; + void GetTextExtent(UInt_t &w, UInt_t &h, char *mess) override; + void GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *mess) override; //---- Methods used for new graphics ----- WinContext_t GetWindowContext(Int_t wid) override; diff --git a/graf2d/win32gdk/src/TGWin32.cxx b/graf2d/win32gdk/src/TGWin32.cxx index b79d4e7e0eaa3..32653b5e0db31 100644 --- a/graf2d/win32gdk/src/TGWin32.cxx +++ b/graf2d/win32gdk/src/TGWin32.cxx @@ -2055,6 +2055,16 @@ void TGWin32::GetTextExtent(UInt_t &w, UInt_t &h, char *mess) TTF::GetTextExtent(w, h, mess); } +//////////////////////////////////////////////////////////////////////////////// +/// Return the size of a wcharacter string - use TTF + +void TGWin32::GetTextExtent(UInt_t &w, UInt_t &h, wchar_t *mess) +{ + TTF::SetTextFont(gTextFont); + TTF::SetTextSize(fTextSize); + TTF::GetTextExtent(w, h, mess); +} + //////////////////////////////////////////////////////////////////////////////// /// Return the X11 window identifier. /// wid : Workstation identifier (input) From 6043189cc18f7dda8e8e3a612864fb9a46419a42 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:30:25 +0200 Subject: [PATCH 07/12] [cocoa] implement new methods for text extensions This is special platform where TTF is not used by default. So all methods must be correctly implemented Adjust internal methods to avoid dependency from selected font. Now font and size provided directly - one can directly use selected font handle as method argument, also in old methods Provide shortcut method to extract unichars for greek and math symbols --- graf2d/cocoa/inc/FontCache.h | 16 ++-- graf2d/cocoa/inc/TGQuartz.h | 4 + graf2d/cocoa/src/FontCache.mm | 48 +++++----- graf2d/cocoa/src/TGQuartz.mm | 159 ++++++++++++++++++++++------------ 4 files changed, 141 insertions(+), 86 deletions(-) diff --git a/graf2d/cocoa/inc/FontCache.h b/graf2d/cocoa/inc/FontCache.h index 52184ac892342..1096eb5103854 100644 --- a/graf2d/cocoa/inc/FontCache.h +++ b/graf2d/cocoa/inc/FontCache.h @@ -58,15 +58,15 @@ class FontCache { //Typographical bounds (whatever it means), //for the current selected font and text. - void GetTextBounds(UInt_t &w, UInt_t &h, const char *text)const; - void GetTextBounds(UInt_t &w, UInt_t &h, const std::vector & unichars)const; + void GetTextBounds(CTFontRef fontref, UInt_t &w, UInt_t &h, const char *text)const; + void GetTextBounds(CTFontRef fontref, UInt_t &w, UInt_t &h, const std::vector & unichars)const; // - double GetAscent()const; - double GetAscent(const char *text)const; - double GetAscent(const std::vector & unichars)const; - double GetDescent()const; - double GetDescent(const char *text)const; - double GetDescent(const std::vector & unichars)const; + double GetAscent(CTFontRef fontref) const; + double GetAscent(CTFontRef fontref, const char *text) const; + double GetAscent(CTFontRef fontref, const std::vector &unichars) const; + double GetDescent(CTFontRef fontref) const; + double GetDescent(CTFontRef fontref, const char *text) const; + double GetDescent(CTFontRef fontref, const std::vector &unichars) const; double GetLeading()const; private: diff --git a/graf2d/cocoa/inc/TGQuartz.h b/graf2d/cocoa/inc/TGQuartz.h index b1bdaec556722..9664482a5fbd3 100644 --- a/graf2d/cocoa/inc/TGQuartz.h +++ b/graf2d/cocoa/inc/TGQuartz.h @@ -73,6 +73,7 @@ class TGQuartz : public TGCocoa { Int_t GetFontAscent(const char *text) const override; Int_t GetFontDescent() const override; Int_t GetFontDescent(const char *text) const override; + Float_t GetTextMagnitude() override; //---- Methods used for new graphics ----- @@ -91,6 +92,9 @@ class TGQuartz : public TGCocoa { void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const char *text, ETextMode mode) override; void DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t angle, Float_t mgn, const wchar_t *text, ETextMode mode) override; + Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess) override; + Bool_t GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const wchar_t *mess) override; + Bool_t GetFontAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *mess) override; private: diff --git a/graf2d/cocoa/src/FontCache.mm b/graf2d/cocoa/src/FontCache.mm index 0466fa2f65dcf..ec9a347cb929b 100644 --- a/graf2d/cocoa/src/FontCache.mm +++ b/graf2d/cocoa/src/FontCache.mm @@ -537,12 +537,12 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -void FontCache::GetTextBounds(UInt_t &w, UInt_t &h, const char *text)const +void FontCache::GetTextBounds(CTFontRef fontref, UInt_t &w, UInt_t &h, const char *text)const { - assert(fSelectedFont != 0 && "GetTextBounds: no font was selected"); + assert(fontref != 0 && "GetTextBounds: no font was selected"); try { - const Quartz::TextLine ctLine(text, fSelectedFont); + const Quartz::TextLine ctLine(text, fontref); ctLine.GetBounds(w, h); h += 2; } catch (const std::exception &) { @@ -551,12 +551,12 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -void FontCache::GetTextBounds(UInt_t &w, UInt_t &h, const std::vector &unichars)const +void FontCache::GetTextBounds(CTFontRef fontref, UInt_t &w, UInt_t &h, const std::vector &unichars)const { - assert(fSelectedFont != 0 && "GetTextBounds: no font was selected"); + assert(fontref != 0 && "GetTextBounds: no font was selected"); try { - const Quartz::TextLine ctLine(unichars, fSelectedFont); + const Quartz::TextLine ctLine(unichars, fontref); ctLine.GetBounds(w, h); h += 2; } catch (const std::exception &) { @@ -565,20 +565,20 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -double FontCache::GetAscent()const +double FontCache::GetAscent(CTFontRef fontref) const { - assert(fSelectedFont != 0 && "GetAscent, no font was selected"); - return CTFontGetAscent(fSelectedFont) + 1; + assert(fontref != 0 && "GetAscent, no font was selected"); + return CTFontGetAscent(fontref) + 1; } //_________________________________________________________________ -double FontCache::GetAscent(const char *text)const +double FontCache::GetAscent(CTFontRef fontref, const char *text) const { assert(text != 0 && "GetAscent, parameter 'text' is null"); - assert(fSelectedFont != 0 && "GetAscent, no font was selected"); + assert(fontref != 0 && "GetAscent, no font was selected"); try { - const Quartz::TextLine ctLine(text, fSelectedFont); + const Quartz::TextLine ctLine(text, fontref); Int_t ascent = 0, descent = 0; ctLine.GetAscentDescent(ascent, descent); return ascent; @@ -588,12 +588,12 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -double FontCache::GetAscent(const std::vector &unichars)const +double FontCache::GetAscent(CTFontRef fontref, const std::vector &unichars) const { - assert(fSelectedFont != 0 && "GetAscent, no font was selected"); + assert(fontref != 0 && "GetAscent, no font was selected"); try { - const Quartz::TextLine ctLine(unichars, fSelectedFont); + const Quartz::TextLine ctLine(unichars, fontref); Int_t ascent = 0, descent = 0; ctLine.GetAscentDescent(ascent, descent); return ascent; @@ -603,20 +603,20 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -double FontCache::GetDescent()const +double FontCache::GetDescent(CTFontRef fontref) const { - assert(fSelectedFont != 0 && "GetDescent, no font was selected"); - return CTFontGetDescent(fSelectedFont) + 1; + assert(fontref != 0 && "GetDescent, no font was selected"); + return CTFontGetDescent(fontref) + 1; } //_________________________________________________________________ -double FontCache::GetDescent(const char *text)const +double FontCache::GetDescent(CTFontRef fontref, const char *text) const { assert(text != 0 && "GetDescent, parameter 'text' is null"); - assert(fSelectedFont != 0 && "GetDescent, no font was selected"); + assert(fontref != 0 && "GetDescent, no font was selected"); try { - const Quartz::TextLine ctLine(text, fSelectedFont); + const Quartz::TextLine ctLine(text, fontref); Int_t ascent = 0, descent = 0; ctLine.GetAscentDescent(ascent, descent); return descent; @@ -626,12 +626,12 @@ const CTFontGuard_t font(CTFontCreateWithFontDescriptorAndOptions(fontDesc, fixe } //_________________________________________________________________ -double FontCache::GetDescent(const std::vector &unichars)const +double FontCache::GetDescent(CTFontRef fontref, const std::vector &unichars) const { - assert(fSelectedFont != 0 && "GetDescent, no font was selected"); + assert(fontref != 0 && "GetDescent, no font was selected"); try { - const Quartz::TextLine ctLine(unichars, fSelectedFont); + const Quartz::TextLine ctLine(unichars, fontref); Int_t ascent = 0, descent = 0; ctLine.GetAscentDescent(ascent, descent); return descent; diff --git a/graf2d/cocoa/src/TGQuartz.mm b/graf2d/cocoa/src/TGQuartz.mm index bacea9a6fa4ef..736b4007c6f37 100644 --- a/graf2d/cocoa/src/TGQuartz.mm +++ b/graf2d/cocoa/src/TGQuartz.mm @@ -451,6 +451,21 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector quartz_get_greek_unicars(const char *text) +{ + //This is a hack. Correct way is to extract glyphs from symbol.ttf, + //find correct mapping, place this glyphs. This requires manual layout though (?), + //and as usually, I have to many things to do, may be, one day I'll fix text rendering also. + //This hack work only on MacOSX 10.7.3, does not work on iOS and I'm not sure about future/previous + //versions of MacOSX. + std::vector unichars(std::strlen(text)); + for (std::size_t i = 0; i < unichars.size(); ++i) + unichars[i] = 0xF000 + (unsigned char)text[i]; + return unichars; +} + //______________________________________________________________________________ void TGQuartz::DrawTextW(WinContext_t wctxt, Int_t x, Int_t y, Float_t /* angle */ , Float_t /* mgn */, const char *text, ETextMode /* mode */) @@ -483,18 +498,9 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(atttext.GetTextFont(), kScale * atttext.GetTextSize())) { const unsigned fontIndex = atttext.GetTextFont() / 10; - if (fontIndex == 12 || fontIndex == 15) {//Greek and math symbols. - //This is a hack. Correct way is to extract glyphs from symbol.ttf, - //find correct mapping, place this glyphs. This requires manual layout though (?), - //and as usually, I have to many things to do, may be, one day I'll fix text rendering also. - //This hack work only on MacOSX 10.7.3, does not work on iOS and I'm not sure about future/previous - //versions of MacOSX. - typedef std::vector::size_type size_type; - - std::vector unichars(std::strlen(text)); - for (size_type i = 0, len = unichars.size(); i < len; ++i) - unichars[i] = 0xF000 + (unsigned char)text[i]; - + if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); Quartz::TextLine ctLine(unichars, currentFont, atttext.GetTextColor()); ctLine.DrawLine(ctx, x, X11::LocalYROOTToCocoa(drawable, y), atttext); } else { @@ -553,36 +559,65 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(GetTextFont(), kScale*GetTextSize()); + if (!fontref) return; + const unsigned fontIndex = GetTextFont() / 10; + if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); + fPimpl->fFontManager.GetTextBounds(fontref, w, h, unichars); + } else { + fPimpl->fFontManager.GetTextBounds(fontref, w, h, text); } +} - if (fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { - const unsigned fontIndex = GetTextFont() / 10; - if (fontIndex == 12 || fontIndex == 15) {//Greek and math symbols. - typedef std::vector::size_type size_type; +//______________________________________________________________________________ +Bool_t TGQuartz::GetTextExtentA(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *text) +{ + if (!text || !*text) { + w = h = 0; + return kTRUE; + } - std::vector unichars(std::strlen(text)); - for (size_type i = 0, len = unichars.size(); i < len; ++i) - unichars[i] = 0xF000 + (unsigned char)text[i]; + auto fontref = fPimpl->fFontManager.SelectFont(font, kScale * size); + if (!fontref) + return kFALSE; - fPimpl->fFontManager.GetTextBounds(w, h, unichars); - } else { - fPimpl->fFontManager.GetTextBounds(w, h, text); - } + const unsigned fontIndex = font / 10; + if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); + fPimpl->fFontManager.GetTextBounds(fontref, w, h, unichars); + } else { + fPimpl->fFontManager.GetTextBounds(fontref, w, h, text); } + + return kTRUE; } +//______________________________________________________________________________ +Bool_t TGQuartz::GetTextExtentA(Font_t, Double_t, UInt_t &w, UInt_t &h, const wchar_t *) +{ + // do not handle wchar, pad painter will switch to TTF + w = h = 0; + return kFALSE; +} + + //______________________________________________________________________________ Int_t TGQuartz::GetFontAscent() const { // Returns the ascent of the current font (in pixels). // The ascent of a font is the distance from the baseline // to the highest position characters extend to. - if (fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) - return Int_t(fPimpl->fFontManager.GetAscent()); + if (auto fontref = fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) + return Int_t(fPimpl->fFontManager.GetAscent(fontref)); return 0; } @@ -595,22 +630,17 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { + if (auto fontref = fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { const unsigned fontIndex = GetTextFont() / 10; - if (fontIndex == 12 || fontIndex == 15) {//Greek and math symbols. - //That's an ugly hack :) - typedef std::vector::size_type size_type; - - std::vector unichars(std::strlen(text)); - for (size_type i = 0, len = unichars.size(); i < len; ++i) - unichars[i] = 0xF000 + (unsigned char)text[i]; - - return Int_t(fPimpl->fFontManager.GetAscent(unichars)); + if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); + return Int_t(fPimpl->fFontManager.GetAscent(fontref, unichars)); } else - return Int_t(fPimpl->fFontManager.GetAscent(text)); + return Int_t(fPimpl->fFontManager.GetAscent(fontref, text)); } return 0; @@ -622,8 +652,8 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) - return Int_t(fPimpl->fFontManager.GetDescent()); + if (auto fontref = fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) + return Int_t(fPimpl->fFontManager.GetDescent(fontref)); return 0; } @@ -636,27 +666,48 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorfFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { + if (auto fontref = fPimpl->fFontManager.SelectFont(GetTextFont(), kScale*GetTextSize())) { const unsigned fontIndex = GetTextFont() / 10; - if (fontIndex == 12 || fontIndex == 15) {//Greek and math symbols. - //That's an ugly hack :) - typedef std::vector::size_type size_type; - - std::vector unichars(std::strlen(text)); - for (size_type i = 0, len = unichars.size(); i < len; ++i) - unichars[i] = 0xF000 + (unsigned char)text[i]; - - return Int_t(fPimpl->fFontManager.GetDescent(unichars)); + if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); + return Int_t(fPimpl->fFontManager.GetDescent(fontref, unichars)); } else - return Int_t(fPimpl->fFontManager.GetDescent(text)); + return Int_t(fPimpl->fFontManager.GetDescent(fontref, text)); } return 0; } +//______________________________________________________________________________ +Bool_t TGQuartz::GetFontAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *text) +{ + a = d = 0; + + auto fontref = fPimpl->fFontManager.SelectFont(font, kScale * size); + if (!fontref) + return kFALSE; + + const unsigned fontIndex = font / 10; + if (!text || !*text) { + a = fPimpl->fFontManager.GetAscent(fontref); + d = fPimpl->fFontManager.GetDescent(fontref); + } else if (fontIndex == 12 || fontIndex == 15) { + //Greek and math symbols. + auto unichars = quartz_get_greek_unicars(text); + a = fPimpl->fFontManager.GetAscent(fontref, unichars); + a = fPimpl->fFontManager.GetDescent(fontref, unichars); + } else { + a = fPimpl->fFontManager.GetAscent(fontref, text); + d = fPimpl->fFontManager.GetDescent(fontref, text); + } + + return kTRUE; +} + //______________________________________________________________________________ Float_t TGQuartz::GetTextMagnitude() From 27d63804cfc6840b74743bf331bc2e03baefd103 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:31:32 +0200 Subject: [PATCH 08/12] Introduce new text methods in TVirtualPadPainter They let decouple graphics classes from gVirtualX --- core/base/inc/TVirtualPadPainter.h | 9 +++++++++ core/base/src/TVirtualPadPainter.cxx | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/core/base/inc/TVirtualPadPainter.h b/core/base/inc/TVirtualPadPainter.h index 778047cc7f8ba..f70f0127d753d 100644 --- a/core/base/inc/TVirtualPadPainter.h +++ b/core/base/inc/TVirtualPadPainter.h @@ -115,6 +115,15 @@ class TVirtualPadPainter { virtual void LockPainter(); virtual void NewPage() {} + //Methods for text dimensions handling + virtual Bool_t HasTTFonts() const; + virtual void GetTextExtent(Font_t /* font */, Double_t /* size */, UInt_t & /* w */, UInt_t & /* h */, const char * /* mess */) {} + virtual void GetTextExtent(Font_t /* font */, Double_t /* size */, UInt_t & /* w */, UInt_t & /* h */, const wchar_t * /* mess */) {} + virtual void GetTextAscentDescent(Font_t /* font */, Double_t /* size */, UInt_t & /* w */, UInt_t & /* h */, const char * /* mess */) {} + virtual void GetTextAscentDescent(Font_t /* font */, Double_t /* size */, UInt_t & /* w */, UInt_t & /* h */, const wchar_t * /* mess */) {} + virtual UInt_t GetTextAdvance(Font_t /* font */, Double_t /* size */, const char * /* text */, Bool_t /* kern */ ) { return 0; } + + //Now, drawing primitives. virtual void DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) = 0; virtual void DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) = 0; diff --git a/core/base/src/TVirtualPadPainter.cxx b/core/base/src/TVirtualPadPainter.cxx index 5b78bee5d9655..49b061e546957 100644 --- a/core/base/src/TVirtualPadPainter.cxx +++ b/core/base/src/TVirtualPadPainter.cxx @@ -211,3 +211,11 @@ void TVirtualPadPainter::SetCursor(Int_t device, ECursor cursor) if (gVirtualX) gVirtualX->SetCursor(device, cursor); } + +//////////////////////////////////////////////////////////////////////////////// +/// Return true if TTF font can be used + +Bool_t TVirtualPadPainter::HasTTFonts() const +{ + return gVirtualX ? gVirtualX->HasTTFonts() : kFALSE; +} From da535a8eb8b986f54408e42423370b9da74d43af Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:32:47 +0200 Subject: [PATCH 09/12] Implement new text methods in TPadPainterBase Here TTF handling performed when HasTTFonts are enabled. It also used when gVirtualX cannot provide font information for any reason --- graf2d/gpad/inc/TPadPainterBase.h | 6 ++ graf2d/gpad/src/TPadPainterBase.cxx | 107 ++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/graf2d/gpad/inc/TPadPainterBase.h b/graf2d/gpad/inc/TPadPainterBase.h index 06809da6542de..cd9347d7962a9 100644 --- a/graf2d/gpad/inc/TPadPainterBase.h +++ b/graf2d/gpad/inc/TPadPainterBase.h @@ -105,6 +105,12 @@ class TPadPainterBase : public TVirtualPadPainter { att.Copy(fAttText); } + void GetTextExtent(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess) override; + void GetTextExtent(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const wchar_t *mess) override; + void GetTextAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *mess) override; + void GetTextAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const wchar_t *mess) override; + UInt_t GetTextAdvance(Font_t font, Double_t size, const char *text, Bool_t kern) override; + ClassDefOverride(TPadPainterBase, 0)//Pad painter with attributes handling }; diff --git a/graf2d/gpad/src/TPadPainterBase.cxx b/graf2d/gpad/src/TPadPainterBase.cxx index ca93ae13088d8..48f85bab21588 100644 --- a/graf2d/gpad/src/TPadPainterBase.cxx +++ b/graf2d/gpad/src/TPadPainterBase.cxx @@ -12,11 +12,16 @@ #include "TPadPainterBase.h" #include "TColor.h" +#include "TTF.h" +#include "TVirtualX.h" +#include "TMathBase.h" /** \class TPadPainterBase \ingroup gpad Extends TVirtualPadPainter interface to simplify work with graphical attributes + +Plus for now central place for TTF handling */ //////////////////////////////////////////////////////////////////////////////// @@ -39,3 +44,105 @@ TAttFill TPadPainterBase::GetAttFillInternal(Bool_t with_transparency) return { color, style }; } + +//////////////////////////////////////////////////////////////////////////////// +/// Returns text extend + +void TPadPainterBase::GetTextExtent(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const char *mess) +{ + Bool_t res = kFALSE; + + if (!HasTTFonts() && gVirtualX) + res = gVirtualX->GetTextExtentA(font, size, w, h, mess); + + if (!res) { + TTF::SetTextFont(font); + TTF::SetTextSize(size); + TTF::GetTextExtent(w, h, mess); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns text extend + +void TPadPainterBase::GetTextExtent(Font_t font, Double_t size, UInt_t &w, UInt_t &h, const wchar_t *mess) +{ + Bool_t res = kFALSE; + + if (!HasTTFonts() && gVirtualX) + res = gVirtualX->GetTextExtentA(font, size, w, h, mess); + + if (!res) { + TTF::SetTextFont(font); + TTF::SetTextSize(size); + TTF::GetTextExtent(w, h, mess); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns text accent / descent + +void TPadPainterBase::GetTextAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const char *mess) +{ + Bool_t res = kFALSE; + + if (!HasTTFonts() && gVirtualX) { + res = gVirtualX->GetFontAscentDescent(font, size, a, d, mess); + if (res & !a) { + UInt_t w = 0; + gVirtualX->GetTextExtentA(font, size, w, a, mess); + } + } + + if (!res) { + TTF::SetTextFont(font); + TTF::SetTextSize(size); + a = TTF::GetBox().yMax; + d = TMath::Abs(TTF::GetBox().yMin); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns text accent / descent + +void TPadPainterBase::GetTextAscentDescent(Font_t font, Double_t size, UInt_t &a, UInt_t &d, const wchar_t *mess) +{ + Bool_t res = kFALSE; + + // special use case for MacOS - directly use TTF + if (!HasTTFonts() && !IsCocoa() && gVirtualX) { + res = gVirtualX->GetFontAscentDescent(font, size, a, d, ""); + if (res & !a) { + UInt_t w = 0; + gVirtualX->GetTextExtentA(font, size, w, a, mess); + } + } + + if (!res) { + TTF::SetTextFont(font); + TTF::SetTextSize(size); + a = TTF::GetBox().yMax; + d = TMath::Abs(TTF::GetBox().yMin); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Returns text advance + +UInt_t TPadPainterBase::GetTextAdvance(Font_t font, Double_t size, const char *mess, Bool_t kern) +{ + if (!HasTTFonts() && gVirtualX) { + UInt_t a = 0, h; + if (gVirtualX->GetTextExtentA(font, size, a, h, mess)) + return a; + } + + Bool_t kernsave = TTF::GetKerning(); + TTF::SetKerning(kern); + TTF::SetTextFont(font); + TTF::SetTextSize(size); + UInt_t a = 0; + TTF::GetTextAdvance(a, mess); + TTF::SetKerning(kernsave); + return a; +} From de64867a99f68ac5e074e6736966a77daba951c6 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:33:35 +0200 Subject: [PATCH 10/12] Mark PS and Web painter as using TTF For these classes TTF will be used directly without involving of gVirtualX --- graf2d/gpad/inc/TPadPainterPS.h | 3 +++ gui/webgui6/inc/TWebPadPainter.h | 1 + 2 files changed, 4 insertions(+) diff --git a/graf2d/gpad/inc/TPadPainterPS.h b/graf2d/gpad/inc/TPadPainterPS.h index 76fe33a213044..64b7a33c6f1da 100644 --- a/graf2d/gpad/inc/TPadPainterPS.h +++ b/graf2d/gpad/inc/TPadPainterPS.h @@ -48,6 +48,9 @@ class TPadPainterPS : public TPadPainterBase { void DestroyDrawable(Int_t device) override; void SelectDrawable(Int_t device) override; + + Bool_t HasTTFonts() const override { return kTRUE; } + void NewPage() override; //TASImage support (noop for a non-gl pad). diff --git a/gui/webgui6/inc/TWebPadPainter.h b/gui/webgui6/inc/TWebPadPainter.h index 90a81773ea734..4d0af7f005a2a 100644 --- a/gui/webgui6/inc/TWebPadPainter.h +++ b/gui/webgui6/inc/TWebPadPainter.h @@ -37,6 +37,7 @@ friend class TWebCanvas; void SetPainting(TWebPainting *p) { fPainting = p; } + Bool_t HasTTFonts() const override { return kTRUE; } void SetOpacity(Int_t percent) override; From 09c617d65f03c5edfc358007907994b9198c2ee6 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 15:34:48 +0200 Subject: [PATCH 11/12] Use new TPadPainter methods in TText Remove there dependency from gVirtualX. One can potentially configure any other text engine --- graf2d/graf/src/TText.cxx | 167 ++++++++++---------------------------- 1 file changed, 45 insertions(+), 122 deletions(-) diff --git a/graf2d/graf/src/TText.cxx b/graf2d/graf/src/TText.cxx index 7a72bd89c5d7b..ad0410d198e5f 100644 --- a/graf2d/graf/src/TText.cxx +++ b/graf2d/graf/src/TText.cxx @@ -14,10 +14,7 @@ #include "TROOT.h" #include "TBuffer.h" #include "TVirtualPad.h" -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include "TTF.h" +#include "TVirtualPadPainter.h" #include "TVirtualX.h" #include "TMath.h" #include "TPoint.h" @@ -478,7 +475,8 @@ void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) return; } - if (!gPad) return; + if (!gPad) + return; if (angle) { Int_t cBoxX[4], cBoxY[4]; Int_t ptx, pty; @@ -503,16 +501,10 @@ void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) w = x2-x1; h = y2-y1; } else { - if ((gVirtualX->HasTTFonts() && TTF::IsInitialized()) || gPad->IsBatch()) { - TTF::GetTextExtent(w, h, (char*)GetTitle()); - } else { - const Font_t oldFont = gVirtualX->GetTextFont(); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(fTextFont); - gVirtualX->GetTextExtent(w, h, (char*)GetTitle()); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(oldFont); - } + Double_t tsize = GetTextSizePixels(*gPad); + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextExtent(GetTextFont(), tsize, w, h, GetTitle()); } } @@ -523,32 +515,14 @@ void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const { - if (!gPad) return; - Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); - Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); - Double_t tsize; - if (wh < hh) tsize = fTextSize*wh; - else tsize = fTextSize*hh; - - if (gVirtualX->HasTTFonts() || gPad->IsBatch()) { - TTF::SetTextFont(fTextFont); - TTF::SetTextSize(tsize); - a = TTF::GetBox().yMax; - d = TMath::Abs(TTF::GetBox().yMin); - } else { - const Font_t oldFont = gVirtualX->GetTextFont(); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(fTextFont); - gVirtualX->SetTextSize(tsize); - a = gVirtualX->GetFontAscent(text); - if (!a) { - UInt_t w; - gVirtualX->GetTextExtent(w, a, (char*)text); - } - d = gVirtualX->GetFontDescent(text); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(oldFont); - } + if (!gPad) + return; + + Double_t tsize = GetTextSizePixels(*gPad); + + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextAscentDescent(GetTextFont(), tsize, a, d, text); } @@ -559,27 +533,14 @@ void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d, const char *text) const void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d, const wchar_t *text) const { - if (!gPad) return; - Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); - Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); - Double_t tsize; - if (wh < hh) tsize = fTextSize*wh; - else tsize = fTextSize*hh; - - if (gVirtualX->HasTTFonts() || gPad->IsBatch() || gVirtualX->InheritsFrom("TGCocoa")) { - TTF::SetTextFont(fTextFont); - TTF::SetTextSize(tsize); - a = TTF::GetBox().yMax; - d = TMath::Abs(TTF::GetBox().yMin); - } else { - gVirtualX->SetTextSize(tsize); - a = gVirtualX->GetFontAscent(); - if (!a) { - UInt_t w; - gVirtualX->GetTextExtent(w, a, (wchar_t*)text); - } - d = gVirtualX->GetFontDescent(); - } + if (!gPad) + return; + + Double_t tsize = GetTextSizePixels(*gPad); + + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextAscentDescent(GetTextFont(), tsize, a, d, text); } //////////////////////////////////////////////////////////////////////////////// @@ -589,26 +550,14 @@ void TText::GetTextAscentDescent(UInt_t &a, UInt_t &d, const wchar_t *text) cons void TText::GetTextExtent(UInt_t &w, UInt_t &h, const char *text) const { - if (!gPad) return; - Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); - Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); - Double_t tsize; - if (wh < hh) tsize = fTextSize*wh; - else tsize = fTextSize*hh; - - if (gVirtualX->HasTTFonts() || gPad->IsBatch()) { - TTF::SetTextFont(fTextFont); - TTF::SetTextSize(tsize); - TTF::GetTextExtent(w, h, (char*)text); - } else { - const Font_t oldFont = gVirtualX->GetTextFont(); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(fTextFont); - gVirtualX->SetTextSize(tsize); - gVirtualX->GetTextExtent(w, h, (char*)text); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(oldFont); - } + if (!gPad) + return; + + Double_t tsize = GetTextSizePixels(*gPad); + + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextExtent(GetTextFont(), tsize, w, h, text); } //////////////////////////////////////////////////////////////////////////////// @@ -618,33 +567,14 @@ void TText::GetTextExtent(UInt_t &w, UInt_t &h, const char *text) const void TText::GetTextAdvance(UInt_t &a, const char *text, const Bool_t kern) const { - if (!gPad) return; - Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); - Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); - Double_t tsize; - if (wh < hh) tsize = fTextSize*wh; - else tsize = fTextSize*hh; - - if (gVirtualX->HasTTFonts() || gPad->IsBatch()) { - Bool_t kernsave = TTF::GetKerning(); - TTF::SetKerning(kern); - TTF::SetTextFont(fTextFont); - TTF::SetTextSize(tsize); - TTF::GetTextAdvance(a, (char*)text); - TTF::SetKerning(kernsave); - } else { - UInt_t h; - const Font_t oldFont = gVirtualX->GetTextFont(); - //how do I know what to calculate without a font??? - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(fTextFont); + if (!gPad) + return; - gVirtualX->SetTextSize(tsize); - gVirtualX->GetTextExtent(a, h, (char*)text); + Double_t tsize = GetTextSizePixels(*gPad); - if (gVirtualX->InheritsFrom("TGCocoa")) - gVirtualX->SetTextFont(oldFont); - } + auto pp = gPad->GetPainter(); + if (pp) + a = pp->GetTextAdvance(GetTextFont(), tsize, text, kern); } //////////////////////////////////////////////////////////////////////////////// @@ -654,21 +584,14 @@ void TText::GetTextAdvance(UInt_t &a, const char *text, const Bool_t kern) const void TText::GetTextExtent(UInt_t &w, UInt_t &h, const wchar_t *text) const { - if (!gPad) return; - Double_t wh = (Double_t)gPad->XtoPixel(gPad->GetX2()); - Double_t hh = (Double_t)gPad->YtoPixel(gPad->GetY1()); - Double_t tsize; - if (wh < hh) tsize = fTextSize*wh; - else tsize = fTextSize*hh; - - if (gVirtualX->HasTTFonts() || gPad->IsBatch() || gVirtualX->InheritsFrom("TGCocoa")) { - TTF::SetTextFont(fTextFont); - TTF::SetTextSize(tsize); - TTF::GetTextExtent(w, h, (wchar_t*)text); - } else { - gVirtualX->SetTextSize(tsize); - gVirtualX->GetTextExtent(w, h, (wchar_t*)text); - } + if (!gPad) + return; + + Double_t tsize = GetTextSizePixels(*gPad); + + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextExtent(GetTextFont(), tsize, w, h, text); } //////////////////////////////////////////////////////////////////////////////// From 52087edf172a1c16f870cc5f68651211be0a434f Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Fri, 24 Apr 2026 16:35:30 +0200 Subject: [PATCH 12/12] Introduce TAttText::GetTextSizeRelative() It returns text size in relative units for specified pad Use this method when apply to pad painter attributes --- core/base/inc/TAttText.h | 1 + core/base/src/TAttText.cxx | 59 +++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/core/base/inc/TAttText.h b/core/base/inc/TAttText.h index 792fed075d826..ab2a4d47c936c 100644 --- a/core/base/inc/TAttText.h +++ b/core/base/inc/TAttText.h @@ -39,6 +39,7 @@ class TAttText { virtual Float_t GetTextSize() const {return fTextSize;} ///< Return the text size virtual Float_t GetTextSizePercent(Float_t size); ///< Return the text in percent of the pad size virtual Float_t GetTextSizePixels(TVirtualPad &pad) const; ///< Return the text size in pixels for specified pad + virtual Float_t GetTextSizeRelative(TVirtualPad &pad) const; ///< Return the text size in relative units virtual void Modify(); virtual void ModifyOn(TVirtualPad &pad); virtual void ResetAttText(Option_t *toption=""); diff --git a/core/base/src/TAttText.cxx b/core/base/src/TAttText.cxx index 853c90e141799..22b9c09495202 100644 --- a/core/base/src/TAttText.cxx +++ b/core/base/src/TAttText.cxx @@ -148,7 +148,7 @@ If the text precision (see next paragraph) is smaller than 3, the text size (`textsize`) is a fraction of the current pad size. Therefore the same `textsize` value can generate text outputs with different absolute sizes in two different pads. -The text size in pixels (`charheight`) is computed the following way: +The text size in pixels (`charheight`) computed in the following way: ~~~ {.cpp} pad_width = gPad->XtoPixel(gPad->GetX2()); @@ -157,6 +157,13 @@ The text size in pixels (`charheight`) is computed the following way: else charheight = textsize*pad_height; ~~~ +This value can be obtained using GetTextSizePixels() method: + +~~~ {.cpp} + TText txt; + auto charheight = text.GetTextSizePixels(*gPad); +~~~ + If the text precision is equal to 3, the text size doesn't depend on the pad's dimensions. A given `textsize` value always generates the same absolute size. The text size (`charheight`) is given in pixels: @@ -310,20 +317,36 @@ void TAttText::Copy(TAttText &atttext) const Float_t TAttText::GetTextSizePercent(Float_t size) { - Float_t rsize = size; - if (fTextFont%10 > 2 && gPad) { - auto ww = gPad->WtoAbsPixel(gPad->GetX1(), gPad->GetX2()); - auto hh = gPad->HtoAbsPixel(gPad->GetY1(), gPad->GetY2()); - rsize = rsize / TMath::Max(1, TMath::Min(ww, hh)); + if ((GetTextFont() % 2 < 3) || !gPad) + return size; + + auto size0 = fTextSize; + fTextSize = size; + size = GetTextSizeRelative(*gPad); + fTextSize = size0; + return size; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Return the text size in relative units +/// +/// If the font precision grater then 2 use pad dimensions to get value + +Float_t TAttText::GetTextSizeRelative(TVirtualPad &pad) const +{ + Float_t rsize = GetTextSize(); + if (GetTextFont() % 10 > 2) { + auto wh = pad.XtoPixel(pad.GetX2()); + auto hh = pad.YtoPixel(pad.GetY1()); + rsize = rsize / TMath::Max(1, TMath::Min(wh, hh)); } return rsize; } - //////////////////////////////////////////////////////////////////////////////// /// Return the text size in pixels for the specified pad /// -/// If the font precision less than 2 size defined as percent of pad size and +/// If the font precision less than 3 size defined as percent of pad size and /// scaled to minimal pad size Float_t TAttText::GetTextSizePixels(TVirtualPad &pad) const @@ -356,24 +379,9 @@ void TAttText::ModifyOn(TVirtualPad &pad) return; Float_t tsize0 = fTextSize; - Float_t tsize = fTextSize; - // there was difference in text size handling, keep it in one place - if (pp->IsNative()) { - tsize = GetTextSizePixels(pad); - } else { - if (fTextFont % 10 > 2) { - Float_t wh = pad.XtoPixel(pad.GetX2()); - Float_t hh = pad.YtoPixel(pad.GetY1()); - if (wh < hh) { - Float_t dy = pad.AbsPixeltoX(Int_t(tsize)) - pad.AbsPixeltoX(0); - tsize = dy/(pad.GetX2() - pad.GetX1()); - } else { - Float_t dy = pad.AbsPixeltoY(0) - pad.AbsPixeltoY(Int_t(tsize)); - tsize = dy/(pad.GetY2() - pad.GetY1()); - } - } - } + // PS-based painter uses relative size, gVirtualX - pixels + Float_t tsize = pp->GetPS() ? GetTextSizeRelative(pad) : GetTextSizePixels(pad); fTextSize = tsize; @@ -382,7 +390,6 @@ void TAttText::ModifyOn(TVirtualPad &pad) fTextSize = tsize0; } - //////////////////////////////////////////////////////////////////////////////// /// Reset this text attributes to default values.