diff --git a/core/base/inc/TAttBBox2D.h b/core/base/inc/TAttBBox2D.h index f4f36e26be86c..4ca16c776b618 100644 --- a/core/base/inc/TAttBBox2D.h +++ b/core/base/inc/TAttBBox2D.h @@ -20,8 +20,8 @@ class TAttBBox2D { protected: - Double_t GetXCoord(const Int_t x, Bool_t is_ndc = kFALSE); - Double_t GetYCoord(const Int_t y, Bool_t is_ndc = kFALSE); + Double_t GetXCoord(const Int_t x, Bool_t is_ndc = kFALSE, Bool_t is_absolute = kFALSE); + Double_t GetYCoord(const Int_t y, Bool_t is_ndc = kFALSE, Bool_t is_absolute = kFALSE); public: virtual ~TAttBBox2D(); diff --git a/core/base/src/TAttBBox2D.cxx b/core/base/src/TAttBBox2D.cxx index 95b95f02e074f..874eb290f06df 100644 --- a/core/base/src/TAttBBox2D.cxx +++ b/core/base/src/TAttBBox2D.cxx @@ -54,34 +54,48 @@ void TAttBBox2D::SetBBoxCenter(const TPoint &p) } //////////////////////////////////////////////////////////////////////////////// -// Return user X coordinate for pixel X value -// Used in derived classes to implement SetBBox... methods +/// Return user X coordinate for pixel X value +/// Can return ndc or normal values +/// Also one can specify to use absolute coordinates for input parameter x +/// Used in derived classes to implement SetBBox... methods -Double_t TAttBBox2D::GetXCoord(const Int_t x, Bool_t is_ndc) +Double_t TAttBBox2D::GetXCoord(const Int_t x, Bool_t is_ndc, Bool_t is_absolute) { if (!gPad) return 0.; if (!is_ndc) - return gPad->PadtoX(gPad->PixeltoX(x)); + return gPad->PadtoX(is_absolute ? gPad->AbsPixeltoX(x) : gPad->PixeltoX(x)); + if (is_absolute) { + Double_t ww = gPad->GetWw(); + Double_t wndc = gPad->GetAbsWNDC(); + return ww > 0 && wndc > 0 ? (x / ww - gPad->GetAbsXlowNDC()) / wndc : 0.; + } Int_t pw = gPad->GetPadWidth(); return pw > 0 ? 1. * x / pw : 0.; } //////////////////////////////////////////////////////////////////////////////// // Return user Y coordinate for pixel Y value +/// Can return ndc or normal values +/// Also one can specify to use absolute coordinates for input parameter x // Used in derived classes to implement SetBBox... methods -Double_t TAttBBox2D::GetYCoord(const Int_t y, Bool_t is_ndc) +Double_t TAttBBox2D::GetYCoord(const Int_t y, Bool_t is_ndc, Bool_t is_absolute) { if (!gPad) return 0.; if (!is_ndc) - return gPad->PadtoY(gPad->PixeltoY(y - gPad->VtoPixel(0))); + return gPad->PadtoY(is_absolute ? gPad->AbsPixeltoY(y) : gPad->PixeltoY(y - gPad->VtoPixel(0))); - Int_t ph = gPad->GetPadHeight(); + if (is_absolute) { + Double_t wh = gPad->GetWh(); + Double_t hndc = gPad->GetAbsHNDC(); + return wh > 0 && hndc > 0 ? ((1. - y / wh) - gPad->GetAbsYlowNDC()) / hndc : 0.; + } + Int_t ph = gPad->GetPadHeight(); return ph > 0 ? 1. - 1. * y / ph : 0.; } diff --git a/graf2d/cocoa/inc/QuartzWindow.h b/graf2d/cocoa/inc/QuartzWindow.h index 79c5c3c0d999e..aab99954186fd 100644 --- a/graf2d/cocoa/inc/QuartzWindow.h +++ b/graf2d/cocoa/inc/QuartzWindow.h @@ -19,6 +19,9 @@ #include "X11Events.h" #include "GuiTypes.h" +class TAttMarker; +class TAttLine; + namespace ROOT { namespace MacOSX { namespace X11 { @@ -134,6 +137,8 @@ class Command; - (void) removeXorWindow; - (void) addXorLine : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2; - (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 : (Int_t) y2; +- (void) addXorPolyLine : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttLine &) att; +- (void) addXorMarker : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttMarker &) att; - (void) setDrawMode : (TVirtualX::EDrawMode) newMode; - (TVirtualX::EDrawMode) getDrawMode; diff --git a/graf2d/cocoa/inc/TGQuartz.h b/graf2d/cocoa/inc/TGQuartz.h index e64fe08adcdb3..325046ab70ec1 100644 --- a/graf2d/cocoa/inc/TGQuartz.h +++ b/graf2d/cocoa/inc/TGQuartz.h @@ -95,10 +95,6 @@ class TGQuartz : public TGCocoa { private: - //Unfortunately, I have to convert from - //top-left to bottom-left corner system. - std::vector fConvertedPoints; - //Lines with AA can be quite different //from what we always had with X11. //Now this is a switch in our configuration file (system.rootrc), diff --git a/graf2d/cocoa/inc/X11Buffer.h b/graf2d/cocoa/inc/X11Buffer.h index 75c52cc3b7bde..be7792274b9e7 100644 --- a/graf2d/cocoa/inc/X11Buffer.h +++ b/graf2d/cocoa/inc/X11Buffer.h @@ -19,6 +19,9 @@ #include "CocoaGuiTypes.h" #include "GuiTypes.h" +#include "TAttMarker.h" +#include "TAttLine.h" +#include "TPoint.h" ////////////////////////////////////////////////////////////////////////////////// // // @@ -54,11 +57,11 @@ class Command { Command(Drawable_t wid, const GCValues_t &gc); virtual ~Command(); - virtual bool HasOperand(Drawable_t drawable)const; - virtual bool IsGraphicsCommand()const;//By-default - false. + virtual bool HasOperand(Drawable_t drawable) const; + virtual bool IsGraphicsCommand() const;//By-default - false. - virtual void Execute()const = 0; - virtual void Execute(CGContextRef /*ctx*/)const; + virtual void Execute() const = 0; + virtual void Execute(CGContextRef /*ctx*/) const; void setView(NSView *v) { @@ -76,8 +79,8 @@ class DrawLine : public Command { public: DrawLine(Drawable_t wid, const GCValues_t &gc, const Point &p1, const Point &p2); - void Execute()const; - bool IsGraphicsCommand()const + void Execute() const override; + bool IsGraphicsCommand() const override { return true; } @@ -89,8 +92,8 @@ class DrawSegments : public Command { public: DrawSegments(Drawable_t wid, const GCValues_t &gc, const Segment_t *segments, Int_t nSegments); - void Execute()const; - bool IsGraphicsCommand()const + void Execute() const override; + bool IsGraphicsCommand() const override { return true; } @@ -102,8 +105,8 @@ class ClearArea : public Command { public: ClearArea(Window_t wid, const Rectangle_t &area); - void Execute()const; - bool IsGraphicsCommand()const + void Execute() const override; + bool IsGraphicsCommand() const override { return true; } @@ -118,13 +121,13 @@ class CopyArea : public Command { public: CopyArea(Drawable_t src, Drawable_t dst, const GCValues_t &gc, const Rectangle_t &area, const Point &dstPoint); - bool HasOperand(Drawable_t drawable)const; - bool IsGraphicsCommand()const + bool HasOperand(Drawable_t drawable) const override; + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; @@ -136,12 +139,12 @@ class DrawString : public Command { public: DrawString(Drawable_t wid, const GCValues_t &gc, const Point &point, const std::string &text); - bool IsGraphicsCommand()const + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; class FillRectangle : public Command { @@ -151,12 +154,12 @@ class FillRectangle : public Command { public: FillRectangle(Drawable_t wid, const GCValues_t &gc, const Rectangle_t &rectangle); - bool IsGraphicsCommand()const + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; class FillPolygon : public Command { @@ -166,12 +169,12 @@ class FillPolygon : public Command { public: FillPolygon(Drawable_t wid, const GCValues_t &gc, const Point_t *points, Int_t nPoints); - bool IsGraphicsCommand()const + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; class DrawRectangle : public Command { @@ -181,12 +184,12 @@ class DrawRectangle : public Command { public: DrawRectangle(Drawable_t wid, const GCValues_t &gc, const Rectangle_t &rectangle); - bool IsGraphicsCommand()const + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; class UpdateWindow : public Command { @@ -196,18 +199,18 @@ class UpdateWindow : public Command { public: UpdateWindow(QuartzView *view); - bool IsGraphicsCommand()const + bool IsGraphicsCommand() const override { return true; } - void Execute()const; + void Execute() const override; }; class DeletePixmap : public Command { public: DeletePixmap(Pixmap_t pixmap); - void Execute()const; + void Execute() const override; }; //Set of 'xor' operations, required by TCanvas and ExecuteEvent's machinery. @@ -219,8 +222,8 @@ class DrawBoxXor : public Command { public: DrawBoxXor(Window_t windowID, const Point &p1, const Point &p2); - void Execute()const; - void Execute(CGContextRef ctx)const; + void Execute() const override {} + void Execute(CGContextRef ctx) const override; }; class DrawLineXor : public Command { @@ -231,13 +234,45 @@ class DrawLineXor : public Command { public: DrawLineXor(Window_t windowID, const Point &p1, const Point &p2); - void Execute()const; - void Execute(CGContextRef ctx)const; + void Execute() const override {} + void Execute(CGContextRef ctx) const override; - Point start() const {return fP1;} - Point end() const {return fP2;} + Point start() const { return fP1; } + Point end() const { return fP2; } }; +class DrawPolyLineXor : public Command { +private: + std::vector fPnts; + TAttLine fAtt; + float fScaleFactor = 1.; + +public: + DrawPolyLineXor(Window_t windowID, const TAttLine &att) : + Command(windowID, GCValues_t()), fAtt(att) {} + void setPoints(Int_t n, TPoint *xy); + + void Execute() const override {} + void Execute(CGContextRef ctx) const override; +}; + + +class DrawMarkerXor : public Command { +private: + std::vector fPnts; + TAttMarker fAtt; + float fScaleFactor = 1.; + +public: + DrawMarkerXor(Window_t windowID, const TAttMarker &att) : + Command(windowID, GCValues_t()), fAtt(att) {} + void setPoints(Int_t n, TPoint *xy); + + void Execute() const override {} + void Execute(CGContextRef ctx) const override; +}; + + class CommandBuffer { private: CommandBuffer(const CommandBuffer &rhs); diff --git a/graf2d/cocoa/src/QuartzWindow.mm b/graf2d/cocoa/src/QuartzWindow.mm index 46a260a6fde8e..e4d8b0a8d0d51 100644 --- a/graf2d/cocoa/src/QuartzWindow.mm +++ b/graf2d/cocoa/src/QuartzWindow.mm @@ -1559,7 +1559,7 @@ - (void) addXorLine : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 auto xorWindow = [self addXorWindow]; try { - std::unique_ptr cmd(new ROOT::MacOSX::X11::DrawLineXor(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2))); + auto cmd = std::make_unique(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2)); cmd->setView(view); auto cv = (XorDrawingView *)xorWindow.contentView; @@ -1578,7 +1578,7 @@ - (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 auto xorWindow = [self addXorWindow]; try { - std::unique_ptr cmd(new ROOT::MacOSX::X11::DrawBoxXor(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2))); + auto cmd = std::make_unique(-1, ROOT::MacOSX::X11::Point(x1, y1), ROOT::MacOSX::X11::Point(x2, y2)); cmd->setView(view); auto cv = (XorDrawingView *)xorWindow.contentView; @@ -1590,6 +1590,45 @@ - (void) addXorBox : (QuartzView *) view : (Int_t) x1 : (Int_t) y1 : (Int_t) x2 } } +//______________________________________________________________________________ +- (void) addXorPolyLine : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttLine &) att +{ + auto xorWindow = [self addXorWindow]; + + try { + auto cmd = std::make_unique(-1, att); + cmd->setView(view); + cmd->setPoints(n, pnts); + + auto cv = (XorDrawingView *)xorWindow.contentView; + [cv addXorCommand : cmd.get()]; + cmd.release(); + [cv setNeedsDisplay : YES]; + + } catch (const std::exception &) { + throw; + } +} + +//______________________________________________________________________________ +- (void) addXorMarker : (QuartzView *) view : (Int_t) n : (TPoint *) pnts : (const TAttMarker &) att +{ + auto xorWindow = [self addXorWindow]; + + try { + auto cmd = std::make_unique(-1, att); + cmd->setView(view); + cmd->setPoints(n, pnts); + + auto cv = (XorDrawingView *)xorWindow.contentView; + [cv addXorCommand : cmd.get()]; + cmd.release(); + [cv setNeedsDisplay : YES]; + + } catch (const std::exception &) { + throw; + } +} //______________________________________________________________________________ - (void) setDrawMode : (TVirtualX::EDrawMode) newMode diff --git a/graf2d/cocoa/src/TGQuartz.mm b/graf2d/cocoa/src/TGQuartz.mm index c85d39c7a9f95..7ee0508a2c785 100644 --- a/graf2d/cocoa/src/TGQuartz.mm +++ b/graf2d/cocoa/src/TGQuartz.mm @@ -203,8 +203,10 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector pnts; + //Convert points to bottom-left system: - ConvertPointsROOTToCocoa(n, xy, fConvertedPoints, drawable); + ConvertPointsROOTToCocoa(n, xy, pnts, drawable); const Quartz::CGStateGuard ctxGuard(ctx); //AA flag is not a part of a state. @@ -223,7 +225,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector(fillColor)) { Quartz::DrawPolygonWithGradientFill(ctx, gradient, CGSizeMake(drawable.fWidth, drawable.fHeight), - n, &fConvertedPoints[0], kFALSE);//kFALSE == don't draw a shadow. + pnts.size(), pnts.data(), kFALSE);//kFALSE == don't draw a shadow. } else { unsigned patternIndex = 0; if (!Quartz::SetFillAreaParameters(ctx, &patternIndex, attfill)) { @@ -233,7 +235,7 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vectorGetWindow(drawable0.fID).fContentView; + if (!view) { + ::Warning("DrawPolyLineW", "Invalid view/window for XOR-mode"); + return; + } - auto &attline = GetAttLine(wctxt); + [view.fQuartzWindow addXorPolyLine: view : n : xy : attline ]; + } + + return; + } auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawPolyLineW"); if (!drawable) @@ -339,13 +352,15 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector pnts; + //Convert to bottom-left-corner system. - ConvertPointsROOTToCocoa(n, xy, fConvertedPoints, drawable); + ConvertPointsROOTToCocoa(n, xy, pnts, drawable); if (drawable.fScaleFactor > 1.) CGContextScaleCTM(ctx, 1. / drawable.fScaleFactor, 1. / drawable.fScaleFactor); - Quartz::DrawPolyLine(ctx, n, &fConvertedPoints[0]); + Quartz::DrawPolyLine(ctx, pnts.size(), pnts.data()); // CTM (current transformation matrix) is restored by 'ctxGuard's dtor. } @@ -372,57 +387,41 @@ void ConvertPointsROOTToCocoa(Int_t nPoints, const TPoint *xy, std::vector * const) wctxt; if (!drawable0) return; - //Do some checks first. - if ([drawable0 isDirectDraw]) - return; - auto &attmark = GetAttMarker(wctxt); + if ([drawable0 isDirectDraw]) { + if (!drawable0.fIsPixmap) { + QuartzView * const view = (QuartzView *)fPimpl->GetWindow(drawable0.fID).fContentView; + if (!view) { + ::Warning("DrawPolyMarkerW", "Invalid view/window for XOR-mode"); + return; + } + + [view.fQuartzWindow addXorMarker: view : n : xy : attmark ]; + } + + return; + } auto drawable = (NSObject * const) GetPixmapDrawable(drawable0, "DrawPolyMarkerW"); if (!drawable) return; + std::vector pnts; + + ConvertPointsROOTToCocoa(n, xy, pnts, drawable); + CGContextRef ctx = drawable.fContext; const Quartz::CGStateGuard ctxGuard(ctx); //AA flag is not a part of a state. const Quartz::CGAAStateGuard aaCtxGuard(ctx, fUseAA); - if (!Quartz::SetFillColor(ctx, attmark.GetMarkerColor())) { - Error("DrawPolyMarker", "Could not find TColor for index %d", attmark.GetMarkerColor()); - return; - } - - Quartz::SetLineColor(ctx, attmark.GetMarkerColor());//Can not fail (for coverity). - Quartz::SetLineStyle(ctx, 1); - Quartz::SetLineWidth(ctx, TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(attmark.GetMarkerStyle())))); - - ConvertPointsROOTToCocoa(n, xy, fConvertedPoints, drawable); - - if (drawable.fScaleFactor > 1.) - CGContextScaleCTM(ctx, 1. / drawable.fScaleFactor, 1. / drawable.fScaleFactor); - - Style_t markerstyle = TAttMarker::GetMarkerStyleBase(attmark.GetMarkerStyle()); - - // The fast pixel markers need to be treated separately - if (markerstyle == 1 || markerstyle == 6 || markerstyle == 7) { - CGContextSetLineJoin(ctx, kCGLineJoinMiter); - CGContextSetLineCap(ctx, kCGLineCapButt); - } else { - CGContextSetLineJoin(ctx, kCGLineJoinRound); - CGContextSetLineCap(ctx, kCGLineCapRound); - } - - Float_t MarkerSizeReduced = GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(attmark.GetMarkerStyle())/2.)/4.; - Quartz::DrawPolyMarker(ctx, n, &fConvertedPoints[0], MarkerSizeReduced * drawable.fScaleFactor, markerstyle); - - CGContextSetLineJoin(ctx, kCGLineJoinMiter); - CGContextSetLineCap(ctx, kCGLineCapButt); + Quartz::DrawPolyMarker(ctx, pnts.size(), pnts.data(), attmark, drawable.fScaleFactor); } //______________________________________________________________________________ diff --git a/graf2d/cocoa/src/X11Buffer.mm b/graf2d/cocoa/src/X11Buffer.mm index 76cc0ed250f1e..77ad33109e51f 100644 --- a/graf2d/cocoa/src/X11Buffer.mm +++ b/graf2d/cocoa/src/X11Buffer.mm @@ -22,9 +22,11 @@ #include "ROOTOpenGLView.h" #include "CocoaPrivate.h" #include "QuartzWindow.h" +#include "QuartzMarker.h" #include "QuartzPixmap.h" #include "QuartzUtils.h" #include "X11Drawable.h" +#include "QuartzLine.h" #include "X11Buffer.h" #include "TGWindow.h" #include "TGClient.h" @@ -274,10 +276,6 @@ } //______________________________________________________________________________ -void DrawBoxXor::Execute()const -{ - //Noop. -} const auto rootToNs = [](Point rp) { return NSPoint{CGFloat(rp.fX), CGFloat(rp.fY)}; @@ -303,13 +301,7 @@ } //______________________________________________________________________________ -void DrawLineXor::Execute()const -{ - //Noop. -} - -//______________________________________________________________________________ -void DrawLineXor::Execute(CGContextRef ctx)const +void DrawLineXor::Execute(CGContextRef ctx) const { assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'"); @@ -326,6 +318,59 @@ CGContextStrokePath(ctx); } +//______________________________________________________________________________ +void DrawPolyLineXor::setPoints(Int_t n, TPoint *xy) +{ + fPnts.resize(n); + for (Int_t i = 0; i < n; ++i) { + auto point = NSPoint{CGFloat(xy[i].fX), CGFloat(xy[i].fY)}; + point = [view convertPoint : point toView : nil]; + fPnts[i].fX = (SCoord_t) point.x; + fPnts[i].fY = (SCoord_t) point.y; + } +} + +//______________________________________________________________________________ +void DrawPolyLineXor::Execute(CGContextRef ctx) const +{ + assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'"); + + const Quartz::CGStateGuard ctxGuard(ctx); + + if (!Quartz::SetLineColor(ctx, fAtt.GetLineColor())) + return; + + Quartz::SetLineStyle(ctx, fAtt.GetLineStyle()); + Quartz::SetLineWidth(ctx, fAtt.GetLineWidth()); + + if (fScaleFactor > 1.) + CGContextScaleCTM(ctx, 1. / fScaleFactor, 1. / fScaleFactor); + + Quartz::DrawPolyLine(ctx, fPnts.size(), fPnts.data()); +} + +//______________________________________________________________________________ +void DrawMarkerXor::setPoints(Int_t n, TPoint *xy) +{ + fPnts.resize(n); + for (Int_t i = 0; i < n; ++i) { + auto point = NSPoint{CGFloat(xy[i].fX), CGFloat(xy[i].fY)}; + point = [view convertPoint : point toView : nil]; + fPnts[i].fX = (SCoord_t) point.x; + fPnts[i].fY = (SCoord_t) point.y; + } +} + +//______________________________________________________________________________ +void DrawMarkerXor::Execute(CGContextRef ctx) const +{ + assert(ctx && "Execute, invalid (nullptr) parameter 'ctx'"); + + const Quartz::CGStateGuard ctxGuard(ctx); + + Quartz::DrawPolyMarker(ctx, fPnts.size(), fPnts.data(), fAtt, fScaleFactor); +} + //______________________________________________________________________________ CommandBuffer::CommandBuffer() { diff --git a/graf2d/gpad/src/TPadPainter.cxx b/graf2d/gpad/src/TPadPainter.cxx index f39bcb95fe2b3..827104b5a74e6 100644 --- a/graf2d/gpad/src/TPadPainter.cxx +++ b/graf2d/gpad/src/TPadPainter.cxx @@ -31,7 +31,7 @@ using size_type = std::vector::size_type; template void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *xs, const T *ys, - std::vector &dst); + std::vector &dst, Bool_t absCoord = kFALSE); inline void MergePointsX(std::vector &points, unsigned nMerged, SCoord_t yMin, SCoord_t yMax, SCoord_t yLast); @@ -50,7 +50,7 @@ template void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Int_t nPoints, const T *xs, const T *ys, Bool_t add_first_point); template -void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys); +void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys); template void DrawPolyMarkerAux(TVirtualPad *pad, WinContext_t cont, Bool_t double_buffer, unsigned nPoints, const T *xs, const T *ys); @@ -365,7 +365,7 @@ void TPadPainter::DrawPolyLine(Int_t n, const Double_t *xs, const Double_t *ys) return; } - DrawPolyLineAux(gPad, fWinContext, n, xs, ys); + DrawPolyLineAux(gPad, fWinContext, !fDoubleBuffer, n, xs, ys); } @@ -382,7 +382,7 @@ void TPadPainter::DrawPolyLine(Int_t n, const Float_t *xs, const Float_t *ys) return; } - DrawPolyLineAux(gPad, fWinContext, n, xs, ys); + DrawPolyLineAux(gPad, fWinContext, !fDoubleBuffer, n, xs, ys); } @@ -628,16 +628,23 @@ namespace { template void ConvertPoints(TVirtualPad *pad, unsigned nPoints, const T *x, const T *y, - std::vector &dst) + std::vector &dst, Bool_t absCoord) { if (!nPoints) return; dst.resize(nPoints); - for (unsigned i = 0; i < nPoints; ++i) { - dst[i].fX = (SCoord_t)pad->XtoPixel(x[i]); - dst[i].fY = (SCoord_t)pad->YtoPixel(y[i]); + if (absCoord) { + for (unsigned i = 0; i < nPoints; ++i) { + dst[i].fX = (SCoord_t) pad->XtoAbsPixel(x[i]); + dst[i].fY = (SCoord_t) pad->YtoAbsPixel(y[i]); + } + } else { + for (unsigned i = 0; i < nPoints; ++i) { + dst[i].fX = (SCoord_t) pad->XtoPixel(x[i]); + dst[i].fY = (SCoord_t) pad->YtoPixel(y[i]); + } } } @@ -846,27 +853,25 @@ void DrawFillAreaAux(TVirtualPad *pad, WinContext_t cont, Int_t nPoints, const T //////////////////////////////////////////////////////////////////////////////// -template -void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, unsigned nPoints, const T *xs, const T *ys) +template +void DrawPolyLineAux(TVirtualPad *pad, WinContext_t cont, Bool_t absCoord, unsigned nPoints, const T *xs, const T *ys) { std::vector xy; - const Int_t threshold = Int_t(TMath::Min(pad->GetWw() * pad->GetAbsWNDC(), - pad->GetWh() * pad->GetAbsHNDC())) * 2; + const UInt_t threshold = TMath::Min(pad->GetPadWidth(), pad->GetPadHeight()) * 2; - if (threshold <= 0) {//Ooops, pad is invisible or something really bad and stupid happened. + if (threshold == 0) {//Ooops, pad is invisible or something really bad and stupid happened. ::Error("DrawPolyLineAux", "invalid pad's geometry"); return; } - if (nPoints < (unsigned)threshold) - ConvertPoints(pad, nPoints, xs, ys, xy); + if (absCoord || (nPoints < threshold)) + ConvertPoints(pad, nPoints, xs, ys, xy, absCoord); else ConvertPointsAndMerge(pad, threshold, nPoints, xs, ys, xy); if (xy.size() > 1) gVirtualX->DrawPolyLineW(cont, xy.size(), &xy[0]); - } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/graf/inc/TCurlyArc.h b/graf2d/graf/inc/TCurlyArc.h index 0bbebf394e0c0..c365b2cab2ed7 100644 --- a/graf2d/graf/inc/TCurlyArc.h +++ b/graf2d/graf/inc/TCurlyArc.h @@ -53,7 +53,6 @@ class TCurlyArc : public TCurlyLine { Rectangle_t GetBBox() override; TPoint GetBBoxCenter() override; - void SetBBoxCenter(const TPoint &p) override; void SetBBoxCenterX(const Int_t x) override; void SetBBoxCenterY(const Int_t y) override; void SetBBoxX1(const Int_t x) override; diff --git a/graf2d/graf/inc/TCurlyLine.h b/graf2d/graf/inc/TCurlyLine.h index e40d496766f79..9104279cfefe2 100644 --- a/graf2d/graf/inc/TCurlyLine.h +++ b/graf2d/graf/inc/TCurlyLine.h @@ -64,8 +64,6 @@ class TCurlyLine : public TPolyLine, public TAttBBox2D { static Bool_t GetDefaultIsCurly (); Rectangle_t GetBBox() override; - TPoint GetBBoxCenter() override; - void SetBBoxCenter(const TPoint &p) override; void SetBBoxCenterX(const Int_t x) override; void SetBBoxCenterY(const Int_t y) override; void SetBBoxX1(const Int_t x) override; diff --git a/graf2d/graf/inc/TEllipse.h b/graf2d/graf/inc/TEllipse.h index f54f54336b3cf..9de88ee3f9f19 100644 --- a/graf2d/graf/inc/TEllipse.h +++ b/graf2d/graf/inc/TEllipse.h @@ -17,6 +17,7 @@ #include "TAttLine.h" #include "TAttFill.h" #include "TAttBBox2D.h" +#include class TPoint; @@ -31,6 +32,9 @@ class TEllipse : public TObject, public TAttLine, public TAttFill, public TAttBB Double_t fPhimax; ///< Maximum angle (degrees) Double_t fTheta; ///< Rotation angle (degrees) + Bool_t FillPoints(TVirtualPad &pad, std::vector &x, std::vector &y, + Double_t x1, Double_t y1, Double_t r1, Double_t r2, Double_t phimin, Double_t phimax, Double_t theta); + public: // TEllipse status bits enum { @@ -69,7 +73,6 @@ class TEllipse : public TObject, public TAttLine, public TAttFill, public TAttBB virtual void SetY1(Double_t y1) {fY1=y1;} // *MENU* Rectangle_t GetBBox() override; TPoint GetBBoxCenter() override; - void SetBBoxCenter(const TPoint &p) override; void SetBBoxCenterX(const Int_t x) override; void SetBBoxCenterY(const Int_t y) override; void SetBBoxX1(const Int_t x) override; diff --git a/graf2d/graf/inc/TText.h b/graf2d/graf/inc/TText.h index e4dcc853aefba..78a5ce4c861ce 100644 --- a/graf2d/graf/inc/TText.h +++ b/graf2d/graf/inc/TText.h @@ -78,13 +78,12 @@ class TText : public TNamed, public TAttText, public TAttBBox2D { Rectangle_t GetBBox() override; TPoint GetBBoxCenter() override; - void SetBBoxCenter(const TPoint &p) override; void SetBBoxCenterX(const Int_t x) override; void SetBBoxCenterY(const Int_t y) override; - void SetBBoxX1(const Int_t) override; //Not Implemented - void SetBBoxX2(const Int_t) override; //Not Implemented - void SetBBoxY1(const Int_t) override; //Not Implemented - void SetBBoxY2(const Int_t) override; //Not Implemented + void SetBBoxX1(const Int_t) override {} //Not Implemented + void SetBBoxX2(const Int_t) override {} //Not Implemented + void SetBBoxY1(const Int_t) override {} //Not Implemented + void SetBBoxY2(const Int_t) override {} //Not Implemented ClassDefOverride(TText,3) //Text }; diff --git a/graf2d/graf/src/TCurlyArc.cxx b/graf2d/graf/src/TCurlyArc.cxx index 6225794716ec0..4e29fc4dc6200 100644 --- a/graf2d/graf/src/TCurlyArc.cxx +++ b/graf2d/graf/src/TCurlyArc.cxx @@ -29,7 +29,8 @@ End_Macro #include "TCurlyArc.h" #include "TROOT.h" #include "TVirtualPad.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" +#include "TAttMarker.h" #include "TMath.h" #include "TPoint.h" @@ -77,10 +78,8 @@ void TCurlyArc::Build() Double_t pixeltoY = 1; Double_t rPix = fR1; if (gPad) { - Double_t ww = (Double_t)gPad->GetWw(); - Double_t wh = (Double_t)gPad->GetWh(); - Double_t pxrange = gPad->GetAbsWNDC()*ww; - Double_t pyrange = - gPad->GetAbsHNDC()*wh; + Double_t pxrange = gPad->GetPadWidth(); + Double_t pyrange = -1. * gPad->GetPadHeight(); Double_t xrange = gPad->GetX2() - gPad->GetX1(); Double_t yrange = gPad->GetY2() - gPad->GetY1(); pixeltoX = xrange / pxrange; @@ -110,7 +109,8 @@ void TCurlyArc::Build() xv[i] = xx + fX1; yv[i] = yy + fY1; } - if (gPad) gPad->Modified(); + if (gPad) + gPad->Modified(); } //////////////////////////////////////////////////////////////////////////////// @@ -123,8 +123,8 @@ Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py) { if (!gPad) return 9999; // Compute distance of point to center of arc - Int_t pxc = gPad->XtoAbsPixel(fX1); - Int_t pyc = gPad->YtoAbsPixel(fY1); + Int_t pxc = gPad->XtoAbsPixel(gPad->XtoPad(fX1)); + Int_t pyc = gPad->YtoAbsPixel(gPad->YtoPad(fY1)); Double_t dist = TMath::Sqrt(Long64_t(pxc-px)*(pxc-px)+Long64_t(pyc-py)*(pyc-py)); Double_t cosa = (px - pxc)/dist; Double_t sina = (pyc - py)/dist; @@ -136,9 +136,10 @@ Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py) } else { if (phi > fPhimin && phi < fPhimax) return 9999; } - Int_t pxr = gPad->XtoPixel(fR1)- gPad->XtoPixel(0); - Double_t distr = TMath::Abs(dist-pxr); - return Int_t(distr); + Int_t pxa = gPad->XtoAbsPixel(gPad->XtoPad(fX1 + cosa*fR1)); + Int_t pya = gPad->YtoAbsPixel(gPad->YtoPad(fY1 + sina*fR1)); + Double_t dista = TMath::Sqrt(Long64_t(pxc-pxa)*(pxc-pxa)+Long64_t(pyc-pya)*(pyc-pya)); + return (Int_t) TMath::Abs(dist - dista); } //////////////////////////////////////////////////////////////////////////////// @@ -154,255 +155,140 @@ Int_t TCurlyArc::DistancetoPrimitive(Int_t px, Int_t py) void TCurlyArc::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; - - Int_t kMaxDiff = 10; - const Int_t np = 10; - const Double_t pi = TMath::Pi(); - static Int_t x[np+3], y[np+3]; - static Int_t px1,py1,npe,r1; - static Int_t pxold, pyold; - Int_t i, dpx, dpy; - Double_t angle,dx,dy,dphi,rLx,rRx; - Double_t phi0; - static Bool_t pTop, pL, pR, pBot, pINSIDE; - static Int_t pTx,pTy,pLx,pLy,pRx,pRy,pBx,pBy; - - Bool_t opaque = gPad->OpaqueMoving(); + if (!gPad || !gPad->IsEditable()) return; + + auto &parent = *gPad; + + constexpr Int_t kMaxDiff = 10; + static enum { pNone, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static Int_t sdx = 0, sdy = 0; + static Bool_t first_move = kTRUE; + + auto paint_hollow = [this, &parent]() { + int np = 10; + std::vector x(np+3), y(np+3); + + Double_t dphi = (fPhimax - fPhimin) * TMath::Pi() / 180; + if (dphi < 0) + dphi += 2 * TMath::Pi(); + Double_t phi0 = fPhimin * TMath::Pi() / 180; + for (int i = 0; i <= np; i++) { + Double_t angle = phi0 + i*dphi/np; + x[i] = parent.XtoPad(fX1 + fR1*TMath::Cos(angle)); + y[i] = parent.YtoPad(fY1 + fR1*TMath::Sin(angle)); + } + if (fPhimax - fPhimin < 360) { + ++np; + x[np] = parent.XtoPad(fX1); + y[np] = parent.YtoPad(fY1); + } + ++np; + x[np] = x[0]; + y[np] = y[0]; + + auto pp = parent.GetPainter(); + pp->SetAttLine(*this); + pp->DrawPolyLine(np + 1, x.data(), y.data()); + + Double_t xm[4] = { fX1, fX1, fX1 - fR1, fX1 + fR1 }; + Double_t ym[4] = { fY1 + fR1, fY1 - fR1, fY1, fY1 }; + for (Int_t i = 0; i < 4; ++i) { + xm[i] = parent.XtoPad(xm[i]); + ym[i] = parent.YtoPad(ym[i]); + } + pp->SetAttMarker({GetLineColor(), 25, 2}); + pp->DrawPolyMarker(4, xm, ym); + }; + + Bool_t opaque = parent.OpaqueMoving(); switch (event) { case kArrowKeyPress: case kButton1Down: - if (!opaque) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - dphi = (fPhimax-fPhimin) * pi / 180; - if (dphi<0) dphi += 2 * pi; - dphi /= np; - phi0 = fPhimin * pi / 180; - for (i=0;i<=np;i++) { - angle = Double_t(i)*dphi + phi0; - dx = fR1*TMath::Cos(angle); - dy = fR1*TMath::Sin(angle); - Int_t rpixY = gPad->XtoAbsPixel(dy) - gPad->XtoAbsPixel(0); - x[i] = gPad->XtoAbsPixel(fX1 + dx); - y[i] = gPad->YtoAbsPixel(fY1) + rpixY; - } - if (fPhimax-fPhimin >= 360 ) { - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np; - } else { - x[np+1] = gPad->XtoAbsPixel(fX1); - y[np+1] = gPad->YtoAbsPixel(fY1); - x[np+2] = x[0]; - y[np+2] = y[0]; - npe = np + 2; - } - } - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - pTx = pBx = px1; - pLy = pRy = py1; - pLx = gPad->XtoAbsPixel(-fR1+fX1); - pRx = gPad->XtoAbsPixel( fR1+fX1); - r1 = TMath::Abs(pLx-pRx)/2; - // a circle in pixels, radius measured along X - pTy = gPad->YtoAbsPixel(fY1) + r1; - pBy = gPad->YtoAbsPixel(fY1) - r1; - - if (!opaque) { - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); - } // No break !!! - - case kMouseMotion: - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - pTx = pBx = px1; - pLy = pRy = py1; - pLx = gPad->XtoAbsPixel(-fR1+fX1); - pRx = gPad->XtoAbsPixel( fR1+fX1); - - pTy = gPad->YtoAbsPixel(fY1) + TMath::Abs(pLx-pRx)/2; - pBy = gPad->YtoAbsPixel(fY1) - TMath::Abs(pLx-pRx)/2; - - pTop = pL = pR = pBot = pINSIDE = kFALSE; - if ((TMath::Abs(px - pTx) < kMaxDiff) && - (TMath::Abs(py - pTy) < kMaxDiff)) { // top edge - pTop = kTRUE; - gPad->SetCursor(kTopSide); - } - else - if ((TMath::Abs(px - pBx) < kMaxDiff) && - (TMath::Abs(py - pBy) < kMaxDiff)) { // bottom edge - pBot = kTRUE; - gPad->SetCursor(kBottomSide); - } - else - if ((TMath::Abs(py - pLy) < kMaxDiff) && - (TMath::Abs(px - pLx) < kMaxDiff)) { // left edge - pL = kTRUE; - gPad->SetCursor(kLeftSide); - } - else - if ((TMath::Abs(py - pRy) < kMaxDiff) && - (TMath::Abs(px - pRx) < kMaxDiff)) { // right edge - pR = kTRUE; - gPad->SetCursor(kRightSide); + case kMouseMotion: { + Int_t px1 = parent.XtoAbsPixel(parent.XtoPad(fX1)); + Int_t py1 = parent.YtoAbsPixel(parent.YtoPad(fY1)); + Int_t pLx = parent.XtoAbsPixel(parent.XtoPad(fX1 - fR1)); + Int_t pRx = parent.XtoAbsPixel(parent.XtoPad(fX1 + fR1)); + Int_t pTy = parent.YtoAbsPixel(parent.YtoPad(fY1 + fR1)); + Int_t pBy = parent.YtoAbsPixel(parent.YtoPad(fY1 - fR1)); + + if ((abs(px - px1) < kMaxDiff) && (abs(py - pTy) < kMaxDiff)) { + mode = pTop; + parent.SetCursor(kTopSide); + } else if ((abs(px - px1) < kMaxDiff) && (abs(py - pBy) < kMaxDiff)) { + mode = pBot; + parent.SetCursor(kBottomSide); + } else if ((abs(py - py1) < kMaxDiff) && (abs(px - pLx) < kMaxDiff)) { + mode = pL; + parent.SetCursor(kLeftSide); + } else if ((abs(py - py1) < kMaxDiff) && (abs(px - pRx) < kMaxDiff)) { + mode = pR; + parent.SetCursor(kRightSide); + } else { + mode = pINSIDE; + sdx = px1 - px; + sdy = py1 - py; + parent.SetCursor(kMove); } - else {pINSIDE= kTRUE; gPad->SetCursor(kMove); } - pxold = px; pyold = py; + first_move = kTRUE; break; + } case kArrowKeyRelease: - case kButton1Motion: - if (!opaque) { - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } - if (pTop) { - r1 += (py - pyold); - } - if (pBot) { - r1 -= (py - pyold); - } - if (pL) { - r1 -= (px - pxold); - } - if (pR) { - r1 += (px - pxold); - } - if (pTop || pBot || pL || pR) { - if (!opaque) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - dphi = (fPhimax-fPhimin) * pi / 180; - if (dphi<0) dphi += 2 * pi; - dphi /= np; - phi0 = fPhimin * pi / 180; - Double_t ur1 = r1; - Int_t pX1 = gPad->XtoAbsPixel(fX1); - Int_t pY1 = gPad->YtoAbsPixel(fY1); - for (i=0;i<=np;i++) { - angle = Double_t(i)*dphi + phi0; - dx = ur1 * TMath::Cos(angle); - dy = ur1 * TMath::Sin(angle); - x[i] = pX1 + (Int_t)dx; - y[i] = pY1 + (Int_t)dy; - } - if (fPhimax-fPhimin >= 360 ) { - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np; - } else { - x[np+1] = pX1; - y[np+1] = pY1; - x[np+2] = x[0]; - y[np+2] = y[0]; - npe = np + 2; - } - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } - } - else { - this->SetStartPoint(gPad->AbsPixeltoX(px1), gPad->AbsPixeltoY(py1)); - this->SetRadius(TMath::Abs(gPad->AbsPixeltoX(px1-r1)-gPad->AbsPixeltoX(px1+r1))/2); - if (pTop) gPad->ShowGuidelines(this, event, 't', true); - if (pBot) gPad->ShowGuidelines(this, event, 'b', true); - if (pL) gPad->ShowGuidelines(this, event, 'l', true); - if (pR) gPad->ShowGuidelines(this, event, 'r', true); - gPad->Modified(kTRUE); - gPad->Update(); - } + case kButton1Motion: { + if (!opaque && !first_move) + paint_hollow(); + char guide = 0; + switch (mode) { + case pNone: + break; + case pTop: + fR1 = GetYCoord(py, kFALSE, kTRUE) - fY1; + guide = 't'; + break; + case pBot: + fR1 = fY1 - GetYCoord(py, kFALSE, kTRUE); + guide = 'b'; + break; + case pL: + fR1 = fX1 - GetXCoord(px, kFALSE, kTRUE); + guide = 'l'; + break; + case pR: + fR1 = GetXCoord(px, kFALSE, kTRUE) - fX1; + guide = 'r'; + break; + case pINSIDE: + fX1 = GetXCoord(px + sdx, kFALSE, kTRUE); + fY1 = GetYCoord(py + sdy, kFALSE, kTRUE); + guide = 'i'; + break; } - if (pINSIDE) { - dpx = px-pxold; dpy = py-pyold; - px1 += dpx; py1 += dpy; - if (!opaque) { - for (i=0;i<=npe;i++) { x[i] += dpx; y[i] += dpy;} - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } else { - this->SetStartPoint(gPad->AbsPixeltoX(px1), gPad->AbsPixeltoY(py1)); - gPad->ShowGuidelines(this, event, 'i', true); - gPad->Modified(kTRUE); - gPad->Update(); - } - } - pTx = pBx = px1; - pRx = px1+r1; - pLx = px1-r1; - pRy = pLy = py1; - pTy = py1-r1; - pBy = py1+r1; - if (!opaque) { - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); + + first_move = kFALSE; + + if (!opaque) + paint_hollow(); + else { + if (guide) + parent.ShowGuidelines(this, event, guide, true); + Build(); + parent.ModifiedUpdate(); } - pxold = px; - pyold = py; break; + } case kButton1Up: if (opaque) { - gPad->ShowGuidelines(this, event); + parent.ShowGuidelines(this, event); } else { - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - rLx = gPad->AbsPixeltoX(px1+r1); - rRx = gPad->AbsPixeltoX(px1-r1); - fR1 = TMath::Abs(rRx-rLx)/2; + Build(); + parent.Modified(kTRUE); } - Build(); - gPad->Modified(kTRUE); - if (!opaque) gVirtualX->SetLineColor(-1); } } @@ -512,15 +398,15 @@ Bool_t TCurlyArc::GetDefaultIsCurly() Rectangle_t TCurlyArc::GetBBox() { - Rectangle_t BBox{0, 0, 0, 0}; + Rectangle_t bbox{0, 0, 0, 0}; if (gPad) { Double_t R2 = fR1 * TMath::Abs(gPad->GetY2() - gPad->GetY1()) / TMath::Abs(gPad->GetX2() - gPad->GetX1()); - BBox.fX = gPad->XtoPixel(fX1 - fR1); - BBox.fY = gPad->YtoPixel(fY1 + R2); - BBox.fWidth = gPad->XtoPixel(fX1 + fR1) - gPad->XtoPixel(fX1 - fR1); - BBox.fHeight = gPad->YtoPixel(fY1 - R2) - gPad->YtoPixel(fY1 + R2); + bbox.fX = gPad->XtoPixel(fX1 - fR1); + bbox.fY = gPad->YtoPixel(fY1 + R2); + bbox.fWidth = gPad->XtoPixel(fX1 + fR1) - bbox.fX; + bbox.fHeight = gPad->YtoPixel(fY1 - R2) - bbox.fY; } - return BBox; + return bbox; } //////////////////////////////////////////////////////////////////////////////// @@ -536,24 +422,12 @@ TPoint TCurlyArc::GetBBoxCenter() return p; } -//////////////////////////////////////////////////////////////////////////////// -/// Set center of the BoundingBox - -void TCurlyArc::SetBBoxCenter(const TPoint &p) -{ - if (!gPad) return; - fX1 = gPad->PixeltoX(p.GetX()); - fY1 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0)); - Build(); -} - //////////////////////////////////////////////////////////////////////////////// /// Set X coordinate of the center of the BoundingBox void TCurlyArc::SetBBoxCenterX(const Int_t x) { - if (!gPad) return; - fX1 = gPad->PixeltoX(x); + fX1 = GetXCoord(x); Build(); } @@ -562,8 +436,7 @@ void TCurlyArc::SetBBoxCenterX(const Int_t x) void TCurlyArc::SetBBoxCenterY(const Int_t y) { - if (!gPad) return; - fY1 = gPad->PixeltoY(y-gPad->VtoPixel(0)); + fY1 = GetYCoord(y); Build(); } @@ -573,12 +446,7 @@ void TCurlyArc::SetBBoxCenterY(const Int_t y) void TCurlyArc::SetBBoxX1(const Int_t x) { - if (!gPad) return; - Double_t x1 = gPad->PixeltoX(x); - if (x1>fX1+fR1) return; - - fR1 = (fX1+fR1-x1)*0.5; - fX1 = x1 + fR1; + fR1 = fX1 - GetXCoord(x); } //////////////////////////////////////////////////////////////////////////////// @@ -587,12 +455,7 @@ void TCurlyArc::SetBBoxX1(const Int_t x) void TCurlyArc::SetBBoxX2(const Int_t x) { - if (!gPad) return; - Double_t x2 = gPad->PixeltoX(x); - if (x2GetY2()-gPad->GetY1())/TMath::Abs(gPad->GetX2()-gPad->GetX1()); - - Double_t y1 = gPad->PixeltoY(y-gPad->VtoPixel(0)); - if (y1GetY2()-gPad->GetY1())/TMath::Abs(gPad->GetX2()-gPad->GetX1())); - fY1 = y1-R2; + fR1 = GetYCoord(y) - fY1; } //////////////////////////////////////////////////////////////////////////////// @@ -616,13 +472,5 @@ void TCurlyArc::SetBBoxY1(const Int_t y) void TCurlyArc::SetBBoxY2(const Int_t y) { - if (!gPad) return; - Double_t R2 = fR1 * TMath::Abs(gPad->GetY2()-gPad->GetY1())/TMath::Abs(gPad->GetX2()-gPad->GetX1()); - - Double_t y2 = gPad->PixeltoY(y-gPad->VtoPixel(0)); - - if (y2>fY1+R2) return; - - fR1 = (fY1+R2-y2)*0.5 / (TMath::Abs(gPad->GetY2()-gPad->GetY1())/TMath::Abs(gPad->GetX2()-gPad->GetX1())); - fY1 = y2+R2; + fR1 = fY1 - GetYCoord(y); } diff --git a/graf2d/graf/src/TCurlyLine.cxx b/graf2d/graf/src/TCurlyLine.cxx index a2ee829179ffa..a66a71d8ba877 100644 --- a/graf2d/graf/src/TCurlyLine.cxx +++ b/graf2d/graf/src/TCurlyLine.cxx @@ -27,7 +27,7 @@ End_Macro #include "TCurlyLine.h" #include "TVirtualPad.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" #include "TMath.h" #include "TPoint.h" @@ -79,21 +79,19 @@ void TCurlyLine::Build() Double_t wavelengthPix,amplitudePix, lengthPix, hPix; Double_t px1, py1, px2, py2; + if (gPad) { - Double_t ww = (Double_t)gPad->GetWw(); - Double_t wh = (Double_t)gPad->GetWh(); - Double_t pxrange = gPad->GetAbsWNDC()*ww; - Double_t pyrange = - gPad->GetAbsHNDC()*wh; + Double_t pxrange = gPad->GetPadWidth(); + Double_t pyrange = -1. * gPad->GetPadHeight(); Double_t xrange = gPad->GetX2() - gPad->GetX1(); Double_t yrange = gPad->GetY2() - gPad->GetY1(); pixeltoX = xrange / pxrange; - pixeltoY = yrange/pyrange; - hPix = TMath::Max(gPad->GetAbsHNDC() * gPad->GetWh(), gPad->GetAbsWNDC() * gPad->GetWw()); + pixeltoY = yrange / pyrange; + hPix = TMath::Max(pxrange, -pyrange); px1 = gPad->XtoAbsPixel(fX1); py1 = gPad->YtoAbsPixel(fY1); px2 = gPad->XtoAbsPixel(fX2); py2 = gPad->YtoAbsPixel(fY2); - lengthPix = TMath::Sqrt((px2-px1)*(px2-px1) + (py1-py2)*(py1-py2)); wavelengthPix = hPix*fWaveLength; amplitudePix = hPix*fAmplitude; @@ -182,153 +180,101 @@ Int_t TCurlyLine::DistancetoPrimitive(Int_t px, Int_t py) void TCurlyLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; + if (!gPad || !gPad->IsEditable()) return; + + constexpr Int_t kMaxDiff = 20; + static Int_t sdx = 0, sdy = 0, selectPoint; + + auto &parent = *gPad; + + Bool_t opaque = parent.OpaqueMoving(); + + auto paint = [this, &parent]() { + auto pp = parent.GetPainter(); + pp->SetAttLine(*this); + pp->DrawLine(parent.XtoPad(fX1), parent.YtoPad(fY1), parent.XtoPad(fX2), parent.YtoPad(fY2)); + }; - Int_t kMaxDiff = 20; - static Int_t d1,d2,px1,px2,py1,py2; - static Int_t pxold, pyold, px1old, py1old, px2old, py2old; - static Bool_t p1, p2, pL; - Int_t dx, dy; + auto set_coord = [this](Int_t _x1, Int_t _y1, Int_t _x2, Int_t _y2) { + if (selectPoint & 1) { + fX1 = GetXCoord(_x1, kFALSE, kTRUE); + fY1 = GetYCoord(_y1, kFALSE, kTRUE); + } + if (selectPoint & 2) { + fX2 = GetXCoord(_x2, kFALSE, kTRUE); + fY2 = GetYCoord(_y2, kFALSE, kTRUE); + } + }; - Bool_t opaque = gPad->OpaqueMoving(); + Int_t px1 = parent.XtoAbsPixel(parent.XtoPad(fX1)); + Int_t py1 = parent.YtoAbsPixel(parent.YtoPad(fY1)); + Int_t px2 = parent.XtoAbsPixel(parent.XtoPad(fX2)); + Int_t py2 = parent.YtoAbsPixel(parent.YtoPad(fY2)); switch (event) { case kArrowKeyPress: case kButton1Down: - if (!opaque) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); //Change line attributes only if necessary - } // No break !!! case kMouseMotion: - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - px2 = gPad->XtoAbsPixel(fX2); - py2 = gPad->YtoAbsPixel(fY2); - - p1 = p2 = pL = kFALSE; - - d1 = TMath::Abs(px1 - px) + TMath::Abs(py1-py); //simply take sum of pixels differences - if (d1 < kMaxDiff) { //*-*================>OK take point number 1 - px1old = px1; py1old = py1; - p1 = kTRUE; - gPad->SetCursor(kPointer); - return; - } - d2 = TMath::Abs(px2 - px) + TMath::Abs(py2-py); //simply take sum of pixels differences - if (d2 < kMaxDiff) { //*-*================>OK take point number 2 - px2old = px2; py2old = py2; - p2 = kTRUE; - gPad->SetCursor(kPointer); - return; + if (abs(px1 - px) + abs(py1 - py) < kMaxDiff) { + selectPoint = 1; + parent.SetCursor(kPointer); + } else if (abs(px2 - px) + abs(py2 - py) < kMaxDiff) { + selectPoint = 2; + parent.SetCursor(kPointer); + } else { + selectPoint = 3; + sdx = px1 - px; + sdy = py1 - py; + parent.SetCursor(kMove); } - pL = kTRUE; - pxold = px; pyold = py; - gPad->SetCursor(kMove); - break; case kArrowKeyRelease: case kButton1Motion: - - if (p1) { - if (!opaque) { - gVirtualX->DrawLine(px1old, py1old, px2, py2); - gVirtualX->DrawLine(px, py, px2, py2); - } - else this->SetStartPoint(gPad->AbsPixeltoX(px),gPad->AbsPixeltoY(py)); - px1old = px; - py1old = py; - } - if (p2) { - if (!opaque) { - gVirtualX->DrawLine(px1, py1, px2old, py2old); - gVirtualX->DrawLine(px1, py1, px, py); - } - else this->SetEndPoint(gPad->AbsPixeltoX(px), gPad->AbsPixeltoY(py)); - px2old = px; - py2old = py; + if (!opaque) + paint(); + if (selectPoint == 1) { + set_coord(px, py, 0, 0); + } else if (selectPoint == 2) { + set_coord(0, 0, px, py); + } else if (selectPoint == 3) { + set_coord(px + sdx, py + sdy, px + sdx + px2 - px1, py + sdy + py2 - py1); } - if (pL) { - if (!opaque) gVirtualX->DrawLine(px1, py1, px2, py2); - dx = px-pxold; dy = py-pyold; - px1 += dx; py1 += dy; px2 += dx; py2 += dy; - if (!opaque) gVirtualX->DrawLine(px1, py1, px2, py2); - pxold = px; - pyold = py; - if (opaque) { - this->SetStartPoint(gPad->AbsPixeltoX(px1),gPad->AbsPixeltoY(py1)); - this->SetEndPoint(gPad->AbsPixeltoX(px2), gPad->AbsPixeltoY(py2)); + if (!opaque) + paint(); + else { + char guide = selectPoint == 3 ? 'i' : '\0'; + if ((selectPoint == 1) || (selectPoint == 2)) { + static const char GUIDES[2][2][2] = { + { { '4', '1' }, { '3', '2' } }, + { { '2', '3' }, { '1', '4' } } + }; + int x_idx = fX1 > fX2 ? 1 : 0; + int y_idx = fY1 > fY2 ? 1 : 0; + guide = GUIDES[selectPoint-1][x_idx][y_idx]; } - } + if (guide) + parent.ShowGuidelines(this, event, guide, true); - if (opaque) { - if (p1) { - //check in which corner the BBox is edited - if (fX1>fX2) { - if (fY1>fY2) - gPad->ShowGuidelines(this, event, '2', true); - else - gPad->ShowGuidelines(this, event, '3', true); - } - else { - if (fY1>fY2) - gPad->ShowGuidelines(this, event, '1', true); - else - gPad->ShowGuidelines(this, event, '4', true); - } - } - if (p2) { - //check in which corner the BBox is edited - if (fX1>fX2) { - if (fY1>fY2) - gPad->ShowGuidelines(this, event, '4', true); - else - gPad->ShowGuidelines(this, event, '1', true); - } - else { - if (fY1>fY2) - gPad->ShowGuidelines(this, event, '3', true); - else - gPad->ShowGuidelines(this, event, '2', true); - } - } - if (pL) { - gPad->ShowGuidelines(this, event, 'i', true); - } - gPad->Modified(kTRUE); - gPad->Update(); + Build(); + parent.ModifiedUpdate(); } break; case kButton1Up: - if (opaque) { - gPad->ShowGuidelines(this, event); - } else { - if (p1) { - fX1 = gPad->AbsPixeltoX(px); - fY1 = gPad->AbsPixeltoY(py); - } - if (p2) { - fX2 = gPad->AbsPixeltoX(px); - fY2 = gPad->AbsPixeltoY(py); - } - if (pL) { - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - fX2 = gPad->AbsPixeltoX(px2); - fY2 = gPad->AbsPixeltoY(py2); - } + if (opaque) + parent.ShowGuidelines(this, event); + else { + Build(); + parent.ModifiedUpdate(); } - Build(); - gPad->Modified(); - if (!opaque) gVirtualX->SetLineColor(-1); } } @@ -457,71 +403,24 @@ Bool_t TCurlyLine::GetDefaultIsCurly() Rectangle_t TCurlyLine::GetBBox() { - Rectangle_t BBox{0,0,0,0}; + Rectangle_t bbox{0,0,0,0}; if (gPad) { Int_t px1 = gPad->XtoPixel(fX1); Int_t px2 = gPad->XtoPixel(fX2); Int_t py1 = gPad->YtoPixel(fY1); Int_t py2 = gPad->YtoPixel(fY2); - if (px1 > px2) { - Int_t tmp = px1; - px1 = px2; - px2 = tmp; - } - if (py1 > py2) { - Int_t tmp = py1; - py1 = py2; - py2 = tmp; - } - - BBox.fX = px1; - BBox.fY = py1; - BBox.fWidth = px2 - px1; - BBox.fHeight = py2 - py1; - } - return BBox; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Return the center of the BoundingBox as TPoint in pixels - -TPoint TCurlyLine::GetBBoxCenter() -{ - TPoint p(0,0); - if (gPad) { - p.SetX(gPad->XtoPixel(TMath::Min(fX1, fX2) + 0.5 * (TMath::Max(fX1, fX2) - TMath::Min(fX1, fX2)))); - p.SetY(gPad->YtoPixel(TMath::Min(fY1, fY2) + 0.5 * (TMath::Max(fY1, fY2) - TMath::Min(fY1, fY2)))); - } - return p; -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set center of the BoundingBox + if (px1 > px2) + std::swap(px1, px2); + if (py1 > py2) + std::swap(py1, py2); -void TCurlyLine::SetBBoxCenter(const TPoint &p) -{ - if (!gPad) return; - Double_t w = TMath::Max(fX1, fX2)-TMath::Min(fX1, fX2); - Double_t h = TMath::Max(fY1, fY2)-TMath::Min(fY1, fY2); - Double_t x1, x2, y1, y2; - - if (fX2 > fX1) { - x1 = gPad->PixeltoX(p.GetX())-0.5*w; - x2 = gPad->PixeltoX(p.GetX())+0.5*w; - } else { - x2 = gPad->PixeltoX(p.GetX())-0.5*w; - x1 = gPad->PixeltoX(p.GetX())+0.5*w; + bbox.fX = px1; + bbox.fY = py1; + bbox.fWidth = px2 - px1; + bbox.fHeight = py2 - py1; } - if (fY2 > fY1) { - y1 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))-0.5*h; - y2 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))+0.5*h; - } else { - y2 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))-0.5*h; - y1 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))+0.5*h; - } - this->SetStartPoint(x1, y1); - this->SetEndPoint(x2, y2); + return bbox; } //////////////////////////////////////////////////////////////////////////////// @@ -529,16 +428,10 @@ void TCurlyLine::SetBBoxCenter(const TPoint &p) void TCurlyLine::SetBBoxCenterX(const Int_t x) { - if (!gPad) return; - Double_t w = TMath::Max(fX1, fX2)-TMath::Min(fX1, fX2); - if (fX2>fX1) { - this->SetStartPoint(gPad->PixeltoX(x)-0.5*w, fY1); - this->SetEndPoint(gPad->PixeltoX(x)+0.5*w, fY2); - } - else { - this->SetEndPoint(gPad->PixeltoX(x)-0.5*w, fY2); - this->SetStartPoint(gPad->PixeltoX(x)+0.5*w, fY1); - } + Double_t w2 = 0.5 * (fX2 - fX1); + Double_t midx = GetXCoord(x); + SetStartPoint(midx - w2, fY1); + SetEndPoint(midx + w2, fY2); } //////////////////////////////////////////////////////////////////////////////// @@ -546,16 +439,10 @@ void TCurlyLine::SetBBoxCenterX(const Int_t x) void TCurlyLine::SetBBoxCenterY(const Int_t y) { - if (!gPad) return; - Double_t h = TMath::Max(fY1, fY2)-TMath::Min(fY1, fY2); - if (fY2>fY1) { - this->SetStartPoint(fX1, gPad->PixeltoY(y-gPad->VtoPixel(0))-0.5*h); - this->SetEndPoint(fX2, gPad->PixeltoY(y-gPad->VtoPixel(0))+0.5*h); - } - else { - this->SetEndPoint(fX2, gPad->PixeltoY(y-gPad->VtoPixel(0))-0.5*h); - this->SetStartPoint(fX1, gPad->PixeltoY(y-gPad->VtoPixel(0))+0.5*h); - } + Double_t h2 = 0.5 * (fY2 - fY1); + Double_t midy = GetYCoord(y); + SetStartPoint(fX1, midy - h2); + SetEndPoint(fX2, midy + h2); } //////////////////////////////////////////////////////////////////////////////// @@ -564,11 +451,10 @@ void TCurlyLine::SetBBoxCenterY(const Int_t y) void TCurlyLine::SetBBoxX1(const Int_t x) { - if (!gPad) return; - if (fX2>fX1) - this->SetStartPoint(gPad->PixeltoX(x), fY1); + if (fX2 > fX1) + SetStartPoint(GetXCoord(x), fY1); else - this->SetEndPoint(gPad->PixeltoX(x), fY2); + SetEndPoint(GetXCoord(x), fY2); } //////////////////////////////////////////////////////////////////////////////// @@ -577,11 +463,10 @@ void TCurlyLine::SetBBoxX1(const Int_t x) void TCurlyLine::SetBBoxX2(const Int_t x) { - if (!gPad) return; - if (fX2>fX1) - this->SetEndPoint(gPad->PixeltoX(x), fY2); + if (fX2 > fX1) + SetEndPoint(GetXCoord(x), fY2); else - this->SetStartPoint(gPad->PixeltoX(x), fY1); + SetStartPoint(GetXCoord(x), fY1); } //////////////////////////////////////////////////////////////////////////////// @@ -589,11 +474,10 @@ void TCurlyLine::SetBBoxX2(const Int_t x) void TCurlyLine::SetBBoxY1(const Int_t y) { - if (!gPad) return; - if (fY2>fY1) - this->SetEndPoint(fX2, gPad->PixeltoY(y - gPad->VtoPixel(0))); + if (fY2 > fY1) + SetEndPoint(fX2, GetYCoord(y)); else - this->SetStartPoint(fX1, gPad->PixeltoY(y - gPad->VtoPixel(0))); + SetStartPoint(fX1, GetYCoord(y)); } //////////////////////////////////////////////////////////////////////////////// @@ -602,9 +486,8 @@ void TCurlyLine::SetBBoxY1(const Int_t y) void TCurlyLine::SetBBoxY2(const Int_t y) { - if (!gPad) return; - if (fY2>fY1) - this->SetStartPoint(fX1, gPad->PixeltoY(y - gPad->VtoPixel(0))); + if (fY2 > fY1) + SetStartPoint(fX1, GetYCoord(y)); else - this->SetEndPoint(fX2, gPad->PixeltoY(y - gPad->VtoPixel(0))); + SetEndPoint(fX2, GetYCoord(y)); } diff --git a/graf2d/graf/src/TEllipse.cxx b/graf2d/graf/src/TEllipse.cxx index 2002b0f5b3025..d56251034a593 100644 --- a/graf2d/graf/src/TEllipse.cxx +++ b/graf2d/graf/src/TEllipse.cxx @@ -16,6 +16,7 @@ #include "TBuffer.h" #include "TEllipse.h" #include "TVirtualPad.h" +#include "TVirtualPadPainter.h" #include "TMath.h" #include "TPoint.h" #include "TVirtualX.h" @@ -199,311 +200,155 @@ TEllipse *TEllipse::DrawEllipse(Double_t x1, Double_t y1,Double_t r1,Double_t r2 void TEllipse::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; + if (!gPad || !gPad->IsEditable()) return; - Int_t kMaxDiff = 10; - - Int_t i, dpx, dpy; - Double_t angle,dx,dy,dphi,ct,st,fTy,fBy,fLx,fRx; - static Int_t px1,py1,npe,r1,r2,sav1,sav2; - const Int_t kMinSize = 25; - const Int_t np = 40; - static Bool_t pTop, pL, pR, pBot, pINSIDE; - static Int_t pTx,pTy,pLx,pLy,pRx,pRy,pBx,pBy; - static Int_t x[np+2], y[np+2]; - static Int_t pxold, pyold; - static Int_t sig,impair; - static Double_t sdx, sdy; - static Double_t oldX1, oldY1, oldR1, oldR2; + auto &parent = *gPad; - Bool_t opaque = gPad->OpaqueMoving(); + constexpr Int_t kMaxDiff = 10; - if (!gPad->IsEditable()) return; + static enum { pNone, pTop, pL, pR, pBot, pINSIDE } mode = pNone; + static Int_t sdx = 0, sdy = 0; + static Double_t oldX1, oldY1, oldR1, oldR2; + static Bool_t first_move = kTRUE; + + auto paint_hollow = [this,&parent]() { + auto pp = parent.GetPainter(); + pp->SetAttLine(*this); + std::vector x, y; + FillPoints(parent, x, y, GetX1(), GetY1(), GetR1(), GetR2(), GetPhimin(), GetPhimax(), GetTheta()); + pp->DrawPolyLine(x.size(), x.data(), y.data()); + pp->SetAttMarker({GetLineColor(), 25, 2}); + Double_t xm[4] = { GetX1(), GetX1(), GetX1() - GetR1(), GetX1() + GetR1() }; + Double_t ym[4] = { GetY1() + GetR2(), GetY1() - GetR2(), GetY1(), GetY1() }; + for (Int_t i = 0; i < 4; ++i) { + xm[i] = parent.XtoPad(xm[i]); + ym[i] = parent.YtoPad(ym[i]); + } + pp->DrawPolyMarker(4, xm, ym); + }; + + auto changeX = [this](Int_t px1, Int_t px2) { + auto x1 = GetXCoord(px1, kFALSE, kTRUE); + auto x2 = GetXCoord(px2, kFALSE, kTRUE); + SetX1((x1 + x2) * 0.5); + SetR1(TMath::Abs((x2 - x1) * 0.5)); + if (x2 < x1) + mode = (mode == pL) ? pR : pL; + }; + + auto changeY = [this](Int_t py1, Int_t py2) { + auto y1 = GetYCoord(py1, kFALSE, kTRUE); + auto y2 = GetYCoord(py2, kFALSE, kTRUE); + SetY1((y1 + y2) * 0.5); + SetR2(TMath::Abs((y1 - y2) * 0.5)); + if (y1 < y2) + mode = (mode == pTop) ? pBot : pTop; + }; + + Bool_t opaque = parent.OpaqueMoving(); + Int_t px1 = parent.XtoAbsPixel(parent.XtoPad(GetX1())); + Int_t py1 = parent.YtoAbsPixel(parent.YtoPad(GetY1())); + Int_t pLx = parent.XtoAbsPixel(parent.XtoPad(GetX1() - GetR1())); + Int_t pRx = parent.XtoAbsPixel(parent.XtoPad(GetX1() + GetR1())); + Int_t pBy = parent.YtoAbsPixel(parent.YtoPad(GetY1() - GetR2())); + Int_t pTy = parent.YtoAbsPixel(parent.YtoPad(GetY1() + GetR2())); switch (event) { case kArrowKeyPress: case kButton1Down: - oldX1 = fX1; - oldY1 = fY1; - oldR1 = fR1; - oldR2 = fR2; - dphi = (fPhimax-fPhimin)*kPI/(180*np); - ct = TMath::Cos(kPI*fTheta/180); - st = TMath::Sin(kPI*fTheta/180); - for (i=0;iXtoAbsPixel(fX1 + dx*ct - dy*st); - y[i] = gPad->YtoAbsPixel(fY1 + dx*st + dy*ct); - } - if (fPhimax-fPhimin >= 360 ) { - x[np] = x[0]; - y[np] = y[0]; - npe = np; - } else { - x[np] = gPad->XtoAbsPixel(fX1); - y[np] = gPad->YtoAbsPixel(fY1); - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np + 1; - } - impair = 0; - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - pTx = pBx = px1; - pLy = pRy = py1; - pTy = gPad->YtoAbsPixel(fR2+fY1); - pBy = gPad->YtoAbsPixel(-fR2+fY1); - pLx = gPad->XtoAbsPixel(-fR1+fX1); - pRx = gPad->XtoAbsPixel(fR1+fX1); - r2 = (pBy-pTy)/2; - r1 = (pRx-pLx)/2; - if (!opaque) { - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); - } - else { - sdx = this->GetX1()-gPad->AbsPixeltoX(px); - sdy = this->GetY1()-gPad->AbsPixeltoY(py); - } + oldX1 = GetX1(); + oldY1 = GetY1(); + oldR1 = GetR1(); + oldR2 = GetR2(); + + sdx = px1 - px; + sdy = py1 - py; + // No break !!! - case kMouseMotion: - px1 = gPad->XtoAbsPixel(fX1); - py1 = gPad->YtoAbsPixel(fY1); - pTx = pBx = px1; - pLy = pRy = py1; - pTy = gPad->YtoAbsPixel(fR2+fY1); - pBy = gPad->YtoAbsPixel(-fR2+fY1); - pLx = gPad->XtoAbsPixel(-fR1+fX1); - pRx = gPad->XtoAbsPixel(fR1+fX1); - pTop = pL = pR = pBot = pINSIDE = kFALSE; - if ((TMath::Abs(px - pTx) < kMaxDiff) && - (TMath::Abs(py - pTy) < kMaxDiff)) { // top edge - pTop = kTRUE; - gPad->SetCursor(kTopSide); - } - else - if ((TMath::Abs(px - pBx) < kMaxDiff) && - (TMath::Abs(py - pBy) < kMaxDiff)) { // bottom edge - pBot = kTRUE; - gPad->SetCursor(kBottomSide); - } - else - if ((TMath::Abs(py - pLy) < kMaxDiff) && - (TMath::Abs(px - pLx) < kMaxDiff)) { // left edge - pL = kTRUE; - gPad->SetCursor(kLeftSide); - } - else - if ((TMath::Abs(py - pRy) < kMaxDiff) && - (TMath::Abs(px - pRx) < kMaxDiff)) { // right edge - pR = kTRUE; - gPad->SetCursor(kRightSide); + case kMouseMotion: { + mode = pNone; + if ((TMath::Abs(px - px1) < kMaxDiff) && (TMath::Abs(py - pTy) < kMaxDiff)) { + mode = pTop; // top edge + parent.SetCursor(kTopSide); + } else if ((TMath::Abs(px - px1) < kMaxDiff) && (TMath::Abs(py - pBy) < kMaxDiff)) { + mode = pBot; // bottom edge + parent.SetCursor(kBottomSide); + } else if ((TMath::Abs(py - py1) < kMaxDiff) && (TMath::Abs(px - pLx) < kMaxDiff)) { + mode = pL; // left edge + parent.SetCursor(kLeftSide); + } else if ((TMath::Abs(py - py1) < kMaxDiff) && (TMath::Abs(px - pRx) < kMaxDiff)) { + mode = pR; // right edge + parent.SetCursor(kRightSide); + } else { + mode = pINSIDE; + parent.SetCursor(kMove); } - else {pINSIDE= kTRUE; gPad->SetCursor(kMove); } - pxold = px; pyold = py; - + first_move = kTRUE; break; + } case kArrowKeyRelease: - case kButton1Motion: - if (!opaque) - { - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } - if (pTop) { - sav1 = py1; - sav2 = r2; - py1 += (py - pyold)/2; - r2 -= (py - pyold)/2; - if (TMath::Abs(pyold-py)%2==1) impair++; - if (py-pyold>0) sig=+1; - else sig=-1; - if (impair==2) { impair = 0; py1 += sig; r2 -= sig;} - if (py1 > pBy-kMinSize) {py1 = sav1; r2 = sav2; py = pyold;} - } - if (pBot) { - sav1 = py1; - sav2 = r2; - py1 += (py - pyold)/2; - r2 += (py - pyold)/2; - if (TMath::Abs(pyold-py)%2==1) impair++; - if (py-pyold>0) sig=+1; - else sig=-1; - if (impair==2) { impair = 0; py1 += sig; r2 += sig;} - if (py1 < pTy+kMinSize) {py1 = sav1; r2 = sav2; py = pyold;} - } - if (pL) { - sav1 = px1; - sav2 = r1; - px1 += (px - pxold)/2; - r1 -= (px - pxold)/2; - if (TMath::Abs(pxold-px)%2==1) impair++; - if (px-pxold>0) sig=+1; - else sig=-1; - if (impair==2) { impair = 0; px1 += sig; r1 -= sig;} - if (px1 > pRx-kMinSize) {px1 = sav1; r1 = sav2; px = pxold;} - } - if (pR) { - sav1 = px1; - sav2 = r1; - px1 += (px - pxold)/2; - r1 += (px - pxold)/2; - if (TMath::Abs(pxold-px)%2==1) impair++; - if (px-pxold>0) sig=+1; - else sig=-1; - if (impair==2) { impair = 0; px1 += sig; r1 += sig;} - if (px1 < pLx+kMinSize) {px1 = sav1; r1 = sav2; px = pxold;} - } - if (pTop || pBot || pL || pR) { - if (!opaque) { - dphi = (fPhimax-fPhimin)*kPI/(180*np); - ct = TMath::Cos(kPI*fTheta/180); - st = TMath::Sin(kPI*fTheta/180); - for (i=0;i= 360 ) { - x[np] = x[0]; - y[np] = y[0]; - npe = np; - } else { - x[np] = px1; - y[np] = py1; - x[np+1] = x[0]; - y[np+1] = y[0]; - npe = np + 1; - } - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } - else - { - this->SetX1(gPad->AbsPixeltoX(px1)); - this->SetY1(gPad->AbsPixeltoY(py1)); - this->SetR1(TMath::Abs(gPad->AbsPixeltoX(px1-r1)-gPad->AbsPixeltoX(px1+r1))/2); - this->SetR2(TMath::Abs(gPad->AbsPixeltoY(py1-r2)-gPad->AbsPixeltoY(py1+r2))/2); - if (pTop) gPad->ShowGuidelines(this, event, 't', true); - if (pBot) gPad->ShowGuidelines(this, event, 'b', true); - if (pL) gPad->ShowGuidelines(this, event, 'l', true); - if (pR) gPad->ShowGuidelines(this, event, 'r', true); - gPad->Modified(kTRUE); - gPad->Update(); - } - } - if (pINSIDE) { - if (!opaque){ - dpx = px-pxold; dpy = py-pyold; - px1 += dpx; py1 += dpy; - for (i=0;i<=npe;i++) { x[i] += dpx; y[i] += dpy;} - for (i=0;iDrawLine(x[i], y[i], x[i+1], y[i+1]); - } - else { - this->SetX1(gPad->AbsPixeltoX(px)+sdx); - this->SetY1(gPad->AbsPixeltoY(py)+sdy); - gPad->ShowGuidelines(this, event, 'i', true); - gPad->Modified(kTRUE); - gPad->Update(); - } - } - if (!opaque){ - pTx = pBx = px1; - pRx = px1+r1; - pLx = px1-r1; - pRy = pLy = py1; - pTy = py1-r2; - pBy = py1+r2; - gVirtualX->DrawLine(pRx+4, py1+4, pRx-4, py1+4); - gVirtualX->DrawLine(pRx-4, py1+4, pRx-4, py1-4); - gVirtualX->DrawLine(pRx-4, py1-4, pRx+4, py1-4); - gVirtualX->DrawLine(pRx+4, py1-4, pRx+4, py1+4); - gVirtualX->DrawLine(pLx+4, py1+4, pLx-4, py1+4); - gVirtualX->DrawLine(pLx-4, py1+4, pLx-4, py1-4); - gVirtualX->DrawLine(pLx-4, py1-4, pLx+4, py1-4); - gVirtualX->DrawLine(pLx+4, py1-4, pLx+4, py1+4); - gVirtualX->DrawLine(px1+4, pBy+4, px1-4, pBy+4); - gVirtualX->DrawLine(px1-4, pBy+4, px1-4, pBy-4); - gVirtualX->DrawLine(px1-4, pBy-4, px1+4, pBy-4); - gVirtualX->DrawLine(px1+4, pBy-4, px1+4, pBy+4); - gVirtualX->DrawLine(px1+4, pTy+4, px1-4, pTy+4); - gVirtualX->DrawLine(px1-4, pTy+4, px1-4, pTy-4); - gVirtualX->DrawLine(px1-4, pTy-4, px1+4, pTy-4); - gVirtualX->DrawLine(px1+4, pTy-4, px1+4, pTy+4); + case kButton1Motion: { + if (mode == pNone) + break; + if (!opaque && !first_move) + paint_hollow(); + char guide = 'i'; + switch (mode) { + case pNone: + break; + case pL: + changeX(px, pRx); + guide = 'l'; + break; + case pR: + changeX(pLx, px); + guide = 'r'; + break; + case pTop: + changeY(py, pBy); + guide = 't'; + break; + case pBot: + changeY(pTy, py); + guide = 'b'; + break; + case pINSIDE: + SetX1(GetXCoord(px + sdx, kFALSE, kTRUE)); + SetY1(GetYCoord(py + sdy, kFALSE, kTRUE)); + guide = 'i'; + break; } - pxold = px; - pyold = py; + first_move = kFALSE; + if (opaque) { + parent.ShowGuidelines(this, event, guide, true); + parent.ModifiedUpdate(); + } else + paint_hollow(); break; + } case kButton1Up: if (gROOT->IsEscaped()) { gROOT->SetEscape(kFALSE); if (opaque) { - gPad->ShowGuidelines(this, event); - this->SetX1(oldX1); - this->SetY1(oldY1); - this->SetR1(oldR1); - this->SetR2(oldR2); - gPad->Modified(kTRUE); - gPad->Update(); + parent.ShowGuidelines(this, event); + SetX1(oldX1); + SetY1(oldY1); + SetR1(oldR1); + SetR2(oldR2); + parent.ModifiedUpdate(); } break; } - if (opaque) { - gPad->ShowGuidelines(this, event); - } else { - fX1 = gPad->AbsPixeltoX(px1); - fY1 = gPad->AbsPixeltoY(py1); - fBy = gPad->AbsPixeltoY(py1+r2); - fTy = gPad->AbsPixeltoY(py1-r2); - fLx = gPad->AbsPixeltoX(px1+r1); - fRx = gPad->AbsPixeltoX(px1-r1); - fR1 = TMath::Abs(fRx-fLx)/2; - fR2 = TMath::Abs(fTy-fBy)/2; - gPad->Modified(kTRUE); - gVirtualX->SetLineColor(-1); - } + if (opaque) + parent.ShowGuidelines(this, event); + else + parent.Modified(kTRUE); + mode = pNone; } } @@ -553,56 +398,74 @@ void TEllipse::ls(Option_t *) const void TEllipse::Paint(Option_t *option) { - PaintEllipse(fX1,fY1,fR1,fR2,fPhimin,fPhimax,fTheta,option); + PaintEllipse(fX1, fY1, fR1, fR2, fPhimin, fPhimax, fTheta, option); } //////////////////////////////////////////////////////////////////////////////// -/// Draw this ellipse with new coordinates. +/// Fill points which can be used for the painting +/// Return true if full 360 ellipse is created -void TEllipse::PaintEllipse(Double_t x1, Double_t y1, Double_t r1, Double_t r2, - Double_t phimin, Double_t phimax, Double_t theta, - Option_t *option) +Bool_t TEllipse::FillPoints(TVirtualPad &pad, std::vector &x, std::vector &y, + Double_t x1, Double_t y1, Double_t r1, Double_t r2, Double_t phimin, Double_t phimax, Double_t theta) { - if (!gPad) return; const Int_t np = 200; - static Double_t x[np+3], y[np+3]; - TAttLine::Modify(); //Change line attributes only if necessary - TAttFill::Modify(); //Change fill attributes only if necessary - Double_t phi1 = TMath::Min(phimin,phimax); - Double_t phi2 = TMath::Max(phimin,phimax); + Double_t phi1 = TMath::Min(phimin, phimax); + Double_t phi2 = TMath::Max(phimin, phimax); //set number of points approximatively proportional to the ellipse circumference Double_t circ = kPI*(r1+r2)*(phi2-phi1)/360; - Int_t n = (Int_t)(np*circ/((gPad->GetX2()-gPad->GetX1())+(gPad->GetY2()-gPad->GetY1()))); - if (n < 8) n= 8; - if (n > np) n = np; - Double_t angle,dx,dy; + Int_t n = (Int_t)(np*circ/((pad.GetX2() - pad.GetX1())+(pad.GetY2()-pad.GetY1()))); + Bool_t full_circle = phi2-phi1 >= 360; + n = TMath::Min(np, TMath::Max(n, (Int_t) (full_circle ? 36 : 8))); + + x.resize(n + (full_circle ? 1 : 3)); + y.resize(n + (full_circle ? 1 : 3)); + Double_t dphi = (phi2-phi1)*kPI/(180*n); Double_t ct = TMath::Cos(kPI*theta/180); Double_t st = TMath::Sin(kPI*theta/180); - for (Int_t i=0;i<=n;i++) { - angle = phi1*kPI/180 + Double_t(i)*dphi; - dx = r1*TMath::Cos(angle); - dy = r2*TMath::Sin(angle); - x[i] = gPad->XtoPad(x1 + dx*ct - dy*st); - y[i] = gPad->YtoPad(y1 + dx*st + dy*ct); + for (Int_t i = 0; i <= n; i++) { + Double_t angle = phi1*kPI/180 + i*dphi; + Double_t dx = r1*TMath::Cos(angle); + Double_t dy = r2*TMath::Sin(angle); + x[i] = pad.XtoPad(x1 + dx*ct - dy*st); + y[i] = pad.YtoPad(y1 + dx*st + dy*ct); } - TString opt = option; - opt.ToLower(); - if (phi2-phi1 >= 360 ) { - if (GetFillStyle()) gPad->PaintFillArea(n,x,y); - if (GetLineStyle()) gPad->PaintPolyLine(n+1,x,y); - } else { - x[n+1] = gPad->XtoPad(x1); - y[n+1] = gPad->YtoPad(y1); + if (!full_circle) { + x[n+1] = pad.XtoPad(x1); + y[n+1] = pad.YtoPad(y1); x[n+2] = x[0]; y[n+2] = y[0]; - if (GetFillStyle()) gPad->PaintFillArea(n+2,x,y); - if (GetLineStyle()) { - if (TestBit(kNoEdges) || opt.Contains("only")) gPad->PaintPolyLine(n+1,x,y); - else gPad->PaintPolyLine(n+3,x,y); - } + } + + return full_circle; +} + + +//////////////////////////////////////////////////////////////////////////////// +/// Draw this ellipse with new coordinates. + +void TEllipse::PaintEllipse(Double_t x1, Double_t y1, Double_t r1, Double_t r2, + Double_t phimin, Double_t phimax, Double_t theta, + Option_t *option) +{ + if (!gPad) return; + + std::vector x, y; + Bool_t full_circle = FillPoints(*gPad, x, y, x1, y1, r1, r2, phimin, phimax, theta); + + TAttFill::ModifyOn(*gPad); //Change fill attributes only if necessary + TAttLine::ModifyOn(*gPad); //Change line attributes only if necessary + + if (GetFillStyle() > 0) + gPad->PaintFillArea(x.size() - 1, x.data(), y.data()); + + if (GetLineStyle() > 0) { + TString opt = option; + opt.ToLower(); + Bool_t less_points = !full_circle && (TestBit(kNoEdges) || opt.Contains("only")); + gPad->PaintPolyLine(x.size() - (less_points ? 2 : 0), x.data(), y.data()); } } @@ -716,23 +579,12 @@ TPoint TEllipse::GetBBoxCenter() return p; } -//////////////////////////////////////////////////////////////////////////////// -/// Set center of the Ellipse - -void TEllipse::SetBBoxCenter(const TPoint &p) -{ - if (!gPad) return; - fX1 = gPad->PixeltoX(p.GetX()); - fY1 = gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0)); -} - //////////////////////////////////////////////////////////////////////////////// /// Set X coordinate of the center of the Ellipse void TEllipse::SetBBoxCenterX(const Int_t x) { - if (!gPad) return; - fX1 = gPad->PixeltoX(x); + SetX1(GetXCoord(x)); } //////////////////////////////////////////////////////////////////////////////// @@ -740,8 +592,7 @@ void TEllipse::SetBBoxCenterX(const Int_t x) void TEllipse::SetBBoxCenterY(const Int_t y) { - if (!gPad) return; - fY1 = gPad->PixeltoY(y-gPad->VtoPixel(0)); + SetY1(GetYCoord(y)); } //////////////////////////////////////////////////////////////////////////////// @@ -750,12 +601,11 @@ void TEllipse::SetBBoxCenterY(const Int_t y) void TEllipse::SetBBoxX1(const Int_t x) { - if (!gPad) return; - Double_t x1 = gPad->PixeltoX(x); - if (x1>fX1+fR1) return; + Double_t x1 = GetXCoord(x); + if (x1 > fX1+fR1) return; - fR1 = (fX1+fR1-x1)*0.5; - fX1 = x1 + fR1; + SetR1((fX1+fR1-x1)*0.5); + SetX1(x1 + fR1); } //////////////////////////////////////////////////////////////////////////////// @@ -764,12 +614,11 @@ void TEllipse::SetBBoxX1(const Int_t x) void TEllipse::SetBBoxX2(const Int_t x) { - if (!gPad) return; - Double_t x2 = gPad->PixeltoX(x); - if (x2PixeltoY(y-gPad->VtoPixel(0)); - if (y1PixeltoY(y-gPad->VtoPixel(0)); - - if (y2>fY1+fR2) return; + Double_t y2 = GetYCoord(y); + if (y2 > fY1+fR2) return; - fR2 = (fY1+fR2-y2)*0.5; - fY1 = y2+fR2; + SetR2((fY1+fR2-y2)*0.5); + SetY1(y2 + fR2); } diff --git a/graf2d/graf/src/TLine.cxx b/graf2d/graf/src/TLine.cxx index b0401e31abe3e..939d1eb8d4e15 100644 --- a/graf2d/graf/src/TLine.cxx +++ b/graf2d/graf/src/TLine.cxx @@ -134,68 +134,60 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) if (!gPad || !gPad->IsEditable()) return; constexpr Int_t kMaxDiff = 20; - static Int_t px1,px2,py1,py2,pxold,pyold; static Double_t oldX1, oldY1, oldX2, oldY2; - static Int_t selectPoint; + static Int_t pxold,pyold, selectPoint; auto &parent = *gPad; Bool_t opaque = parent.OpaqueMoving(); - auto action = [this, &parent](Int_t code, Int_t _x1, Int_t _y1, Int_t _x2 = 0, Int_t _y2 = 0) { - Double_t x1, y1, x2, y2; + auto paint = [this, &parent]() { + auto pp = parent.GetPainter(); + pp->SetAttLine(*this); + if (TestBit(kLineNDC)) + pp->DrawLineNDC(GetX1(), GetY1(), GetX2(), GetY2()); + else + pp->DrawLine(parent.XtoPad(GetX1()), parent.YtoPad(GetY1()), parent.XtoPad(GetX2()), parent.YtoPad(GetY2())); + }; + auto set_coord = [this](Int_t _x1, Int_t _y1, Int_t _x2, Int_t _y2) { Bool_t isndc = TestBit(kLineNDC); - - if (isndc) { - x1 = (1. * _x1 / parent.GetWw() - parent.GetAbsXlowNDC()) / parent.GetAbsWNDC(); - y1 = ((1 - 1. * _y1 / parent.GetWh()) - parent.GetAbsYlowNDC()) / parent.GetAbsHNDC(); - x2 = (1. * _x2 / parent.GetWw() - parent.GetAbsXlowNDC()) / parent.GetAbsWNDC(); - y2 = ((1 - 1. * _y2 / parent.GetWh()) - parent.GetAbsYlowNDC()) / parent.GetAbsHNDC(); - } else { - x1 = parent.AbsPixeltoX(_x1); - y1 = parent.AbsPixeltoY(_y1); - x2 = parent.AbsPixeltoX(_x2); - y2 = parent.AbsPixeltoY(_y2); + if (selectPoint & 1) { + SetX1(GetXCoord(_x1, isndc, kTRUE)); + SetY1(GetYCoord(_y1, isndc, kTRUE)); + } + if (selectPoint & 2) { + SetX2(GetXCoord(_x2, isndc, kTRUE)); + SetY2(GetYCoord(_y2, isndc, kTRUE)); } - if (code == 0) { - auto pp = parent.GetPainter(); - pp->SetAttLine(*this); - if (isndc) - pp->DrawLineNDC(x1, y1, x2, y2); + if (TestBit(kVertical)) { + if (selectPoint & 1) + SetX2(GetX1()); else - pp->DrawLine(x1, y1, x2, y2); - } else { - if (!isndc) { - x1 = parent.PadtoX(x1); - x2 = parent.PadtoX(x2); - y1 = parent.PadtoY(y1); - y2 = parent.PadtoY(y2); - } - - if (code & 1) { - SetX1(x1); - SetY1(y1); - } - if (code & 2) { - SetX2(x2); - SetY2(y2); - } - if (TestBit(kVertical)) { - if (code & 1) - SetX2(GetX1()); - else - SetX1(GetX2()); - } - if (TestBit(kHorizontal)) { - if (code & 1) - SetY2(GetY1()); - else - SetY1(GetY2()); - } + SetX1(GetX2()); + } + if (TestBit(kHorizontal)) { + if (selectPoint & 1) + SetY2(GetY1()); + else + SetY1(GetY2()); } }; + Int_t px1, py1, px2, py2; + + if (TestBit(kLineNDC)) { + px1 = parent.UtoAbsPixel(GetX1()); + py1 = parent.VtoAbsPixel(GetY1()); + px2 = parent.UtoAbsPixel(GetX2()); + py2 = parent.VtoAbsPixel(GetY2()); + } else { + px1 = parent.XtoAbsPixel(parent.XtoPad(GetX1())); + py1 = parent.YtoAbsPixel(parent.YtoPad(GetY1())); + px2 = parent.XtoAbsPixel(parent.XtoPad(GetX2())); + py2 = parent.YtoAbsPixel(parent.YtoPad(GetY2())); + } + switch (event) { case kArrowKeyPress: @@ -207,25 +199,12 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) // No break !!! - case kMouseMotion: - - if (TestBit(kLineNDC)) { - px1 = parent.UtoAbsPixel(GetX1()); - py1 = parent.VtoAbsPixel(GetY1()); - px2 = parent.UtoAbsPixel(GetX2()); - py2 = parent.VtoAbsPixel(GetY2()); - } else { - px1 = parent.XtoAbsPixel(parent.XtoPad(GetX1())); - py1 = parent.YtoAbsPixel(parent.YtoPad(GetY1())); - px2 = parent.XtoAbsPixel(parent.XtoPad(GetX2())); - py2 = parent.YtoAbsPixel(parent.YtoPad(GetY2())); - } - + case kMouseMotion: { //simply take sum of pixels differences - if (abs(px1 - px) + abs(py1 - py) < kMaxDiff) { //*-*================>OK take point number 1 + if (abs(px1 - px) + abs(py1 - py) < kMaxDiff) { selectPoint = 1; parent.SetCursor(kPointer); - } else if (abs(px2 - px) + abs(py2 - py) < kMaxDiff) { //*-*================>OK take point number 2 + } else if (abs(px2 - px) + abs(py2 - py) < kMaxDiff) { selectPoint = 2; parent.SetCursor(kPointer); } else { @@ -236,42 +215,38 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) } break; + } case kArrowKeyRelease: case kButton1Motion: if (!opaque) - action(0, px1, py1, px2, py2); + paint(); if (selectPoint == 1) { - px1 = px; - py1 = py; + set_coord(px, py, 0, 0); } else if (selectPoint == 2) { + set_coord(0, 0, px, py); px2 = px; py2 = py; } else if (selectPoint == 3) { - px1 += px - pxold; - py1 += py - pyold; - px2 += px - pxold; - py2 += py -pyold; + set_coord(px1 + px - pxold, py1 + py - pyold, px2 + px - pxold, py2 + py - pyold); pxold = px; pyold = py; } - action(!opaque ? 0 : selectPoint, px1, py1, px2, py2); - if (opaque) { - if (selectPoint == 1) { - //check in which corner the BBox is edited - if (GetX1() > GetX2()) - parent.ShowGuidelines(this, event, GetY1() > GetY2() ? '2' : '3', true); - else - parent.ShowGuidelines(this, event, GetY1() > GetY2() ? '1' : '4', true); - } else if (selectPoint == 2) { - //check in which corner the BBox is edited - if (GetX1() > GetX2()) - parent.ShowGuidelines(this, event, GetY1() > GetY2() ? '4' : '1', true); - else - parent.ShowGuidelines(this, event, GetY1() > GetY2() ? '3' : '2', true); - } else if (selectPoint == 3) { - parent.ShowGuidelines(this, event, 'i', true); + if (!opaque) + paint(); + else { + char guide = selectPoint == 3 ? 'i' : '\0'; + if ((selectPoint == 1) || (selectPoint == 2)) { + static const char GUIDES[2][2][2] = { + { { '4', '1' }, { '3', '2' } }, + { { '2', '3' }, { '1', '4' } } + }; + int x_idx = GetX1() > GetX2() ? 1 : 0; + int y_idx = GetY1() > GetY2() ? 1 : 0; + guide = GUIDES[selectPoint-1][x_idx][y_idx]; } + if (guide) + parent.ShowGuidelines(this, event, guide, true); parent.ModifiedUpdate(); } break; @@ -290,17 +265,14 @@ void TLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) } break; } - if (opaque) { + if (opaque) parent.ShowGuidelines(this, event); - } else { - action(selectPoint, px1, py1, px2, py2); + else parent.ModifiedUpdate(); - } selectPoint = 0; break; case kButton1Locate: - // Sergey: code is never used, has to be removed in ROOT7 ExecuteEvent(kButton1Down, px, py); while (true) { @@ -516,24 +488,24 @@ void TLine::Streamer(TBuffer &R__b) Rectangle_t TLine::GetBBox() { - Rectangle_t BBox{0, 0, 0, 0}; + Rectangle_t bbox{0, 0, 0, 0}; if (gPad) { - Int_t px1 = gPad->XtoPixel(fX1); - Int_t px2 = gPad->XtoPixel(fX2); - Int_t py1 = gPad->YtoPixel(fY1); - Int_t py2 = gPad->YtoPixel(fY2); + Int_t px1 = TestBit(kLineNDC) ? gPad->UtoPixel(fX1) : gPad->XtoPixel(fX1); + Int_t px2 = TestBit(kLineNDC) ? gPad->UtoPixel(fX2) : gPad->XtoPixel(fX2); + Int_t py1 = TestBit(kLineNDC) ? gPad->VtoPixel(fY1) : gPad->YtoPixel(fY1); + Int_t py2 = TestBit(kLineNDC) ? gPad->VtoPixel(fY2) : gPad->YtoPixel(fY2); if (px1 > px2) std::swap(px1, px2); if (py1 > py2) std::swap(py1, py2); - BBox.fX = px1; - BBox.fY = py1; - BBox.fWidth = px2 - px1; - BBox.fHeight = py2 - py1; + bbox.fX = px1; + bbox.fY = py1; + bbox.fWidth = px2 - px1; + bbox.fHeight = py2 - py1; } - return BBox; + return bbox; } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/graf/src/TMarker.cxx b/graf2d/graf/src/TMarker.cxx index c336155f6f619..5f6531d107c22 100644 --- a/graf2d/graf/src/TMarker.cxx +++ b/graf2d/graf/src/TMarker.cxx @@ -300,14 +300,12 @@ void TMarker::ls(Option_t *) const void TMarker::Paint(Option_t *) { - if (!gPad) return; - if (TestBit(kMarkerNDC)) { - Double_t u = gPad->GetX1() + fX*(gPad->GetX2()-gPad->GetX1()); - Double_t v = gPad->GetY1() + fY*(gPad->GetY2()-gPad->GetY1()); - PaintMarker(u,v); - } else { - PaintMarker(gPad->XtoPad(fX),gPad->YtoPad(fY)); - } + if (!gPad) + return; + if (TestBit(kMarkerNDC)) + PaintMarkerNDC(GetX(), GetY()); + else + PaintMarker(gPad->XtoPad(GetX()), gPad->YtoPad(GetY())); } //////////////////////////////////////////////////////////////////////////////// @@ -316,14 +314,17 @@ void TMarker::Paint(Option_t *) void TMarker::PaintMarker(Double_t x, Double_t y) { TAttMarker::Modify(); //Change line attributes only if necessary - if (gPad) gPad->PaintPolyMarker(-1,&x,&y,""); + if (gPad) gPad->PaintPolyMarker(-1, &x, &y, ""); } //////////////////////////////////////////////////////////////////////////////// /// Draw this marker with new coordinates in NDC. -void TMarker::PaintMarkerNDC(Double_t, Double_t) +void TMarker::PaintMarkerNDC(Double_t u, Double_t v) { + Double_t x = gPad->GetX1() + u * (gPad->GetX2() - gPad->GetX1()); + Double_t y = gPad->GetY1() + v * (gPad->GetY2() - gPad->GetY1()); + PaintMarker(x, y); } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/graf/src/TPolyLine.cxx b/graf2d/graf/src/TPolyLine.cxx index a9fe3b7e4c407..c50fe518030ae 100644 --- a/graf2d/graf/src/TPolyLine.cxx +++ b/graf2d/graf/src/TPolyLine.cxx @@ -15,7 +15,8 @@ #include "TBuffer.h" #include "TMath.h" #include "TVirtualPad.h" -#include "TVirtualX.h" +#include "TVirtualPadPainter.h" +#include "TAttMarker.h" #include "TPolyLine.h" @@ -243,222 +244,138 @@ TPolyLine *TPolyLine::DrawPolyLine(Int_t n, Double_t *x, Double_t *y, Option_t * void TPolyLine::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; + if (!gPad || !gPad->IsEditable()) return; - Int_t i, d; - Double_t xmin, xmax, ymin, ymax, dx, dy, dxr, dyr; - const Int_t kMaxDiff = 10; - static Bool_t middle; - static Int_t ipoint, pxp, pyp; - static Int_t px1,px2,py1,py2; - static Int_t pxold, pyold, px1old, py1old, px2old, py2old; - static Int_t dpx, dpy; - static std::vector x, y; - Bool_t opaque = gPad->OpaqueMoving(); + auto &parent = *gPad; - if (!gPad->IsEditable()) return; + constexpr Int_t kMaxDiff = 10; + Bool_t opaque = parent.OpaqueMoving(); + static Int_t sdx, sdy, ipoint; + static Bool_t first_move; Int_t np = Size(); + Bool_t is_last_same = (np > 1) && (fX[0] == fX[np-1]) && (fY[0] == fY[np-1]); + if (is_last_same) + np--; + + auto paint_hollow = [this,&parent,is_last_same] () { + auto pp = parent.GetPainter(); + pp->SetAttLine({1,1,GetLineWidth()}); + Double_t *x = fX, *y = fY; + if (TestBit(kPolyLineNDC)) { + pp->DrawPolyLineNDC(Size(), x, y); + } else { + std::vector xx, yy; + if (parent.GetLogx()) { + xx.resize(Size()); + for (Int_t ix = 0; ix < Size(); ix++) + xx[ix] = parent.XtoPad(x[ix]); + x = xx.data(); + } + if (parent.GetLogy()) { + yy.resize(Size()); + for (Int_t iy = 0; iy < Size(); iy++) + yy[iy] = parent.YtoPad(y[iy]); + y = yy.data(); + } + pp->DrawPolyLine(Size(), x, y); - switch (event) { - - case kButton1Down: - gVirtualX->SetLineColor(-1); - TAttLine::Modify(); //Change line attributes only if necessary - px1 = gPad->XtoAbsPixel(gPad->GetX1()); - py1 = gPad->YtoAbsPixel(gPad->GetY1()); - px2 = gPad->XtoAbsPixel(gPad->GetX2()); - py2 = gPad->YtoAbsPixel(gPad->GetY2()); - ipoint = -1; - + pp->SetAttMarker({1,25,1}); + pp->DrawPolyMarker(is_last_same ? Size()-1 : Size(), x, y); + } + }; - if (!x.empty() || !y.empty()) break; - x.resize(np+1, 0); - y.resize(np+1, 0); - for (i=0;iXtoAbsPixel(gPad->XtoPad(fX[i])); - pyp = gPad->YtoAbsPixel(gPad->YtoPad(fY[i])); - if (!opaque) { - gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4); - gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4); - gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4); - gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4); - } - x[i] = pxp; - y[i] = pyp; - d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py); - if (d < kMaxDiff) ipoint =i; + auto get_point = [this, &parent](Int_t i, Int_t &pntx, Int_t &pnty) { + if (TestBit(kPolyLineNDC)) { + pntx = parent.UtoAbsPixel(fX[i]); + pnty = parent.VtoAbsPixel(fY[i]); + } else { + pntx = parent.XtoAbsPixel(parent.XtoPad(fX[i])); + pnty = parent.YtoAbsPixel(parent.YtoPad(fY[i])); } - dpx = 0; - dpy = 0; - pxold = px; - pyold = py; - if (ipoint < 0) return; - if (ipoint == 0) { - px1old = 0; - py1old = 0; - px2old = gPad->XtoAbsPixel(fX[1]); - py2old = gPad->YtoAbsPixel(fY[1]); - } else if (ipoint == fN-1) { - px1old = gPad->XtoAbsPixel(gPad->XtoPad(fX[fN-2])); - py1old = gPad->YtoAbsPixel(gPad->YtoPad(fY[fN-2])); - px2old = 0; - py2old = 0; + }; + + auto set_point = [this, &parent](Int_t i, Int_t pntx, Int_t pnty) { + if (TestBit(kPolyLineNDC)) { + Double_t ww = parent.GetWw(); + Double_t wndc = parent.GetAbsWNDC(); + Double_t wh = parent.GetWh(); + Double_t hndc = parent.GetAbsHNDC(); + fX[i] = ww > 0 && wndc > 0 ? (pntx / ww - parent.GetAbsXlowNDC()) / wndc : 0.; + fY[i] = wh > 0 && hndc > 0 ? ((1. - pnty / wh) - parent.GetAbsYlowNDC()) / hndc : 0.; } else { - px1old = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint-1])); - py1old = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint-1])); - px2old = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint+1])); - py2old = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint+1])); + fX[i] = parent.PadtoX(parent.AbsPixeltoX(pntx)); + fY[i] = parent.PadtoY(parent.AbsPixeltoY(pnty)); } - pxold = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint])); - pyold = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint])); - - break; + }; + switch (event) { - case kMouseMotion: + case kArrowKeyPress: + case kButton1Down: + // No break !!! + case kMouseMotion: { - middle = kTRUE; - for (i=0;iXtoAbsPixel(gPad->XtoPad(fX[i])); - pyp = gPad->YtoAbsPixel(gPad->YtoPad(fY[i])); - d = TMath::Abs(pxp-px) + TMath::Abs(pyp-py); - if (d < kMaxDiff) middle = kFALSE; + Int_t minDiff = kMaxDiff; + ipoint = -1; + for (Int_t i = 0; i < np; i++) { + Int_t pxp, pyp; + get_point(i, pxp, pyp); + if (i == 0) { + sdx = pxp - px; + sdy = pyp - py; + } + Int_t d = TMath::Abs(pxp - px) + TMath::Abs(pyp - py); + if (d < minDiff) { + ipoint = i; + minDiff = d; + sdx = pxp - px; + sdy = pyp - py; + } } - - - // check if point is close to an axis - if (middle) gPad->SetCursor(kMove); - else gPad->SetCursor(kHand); + first_move = kTRUE; + if (ipoint < 0) + parent.SetCursor(kMove); + else + parent.SetCursor(kHand); break; + } case kButton1Motion: - if (!opaque) { - if (middle) { - for(i=0;iDrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy); - pxp = x[i]+dpx; - pyp = y[i]+dpy; - gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4); - gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4); - gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4); - gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4); - } - pxp = x[np-1]+dpx; - pyp = y[np-1]+dpy; - gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4); - gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4); - gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4); - gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4); - dpx += px - pxold; - dpy += py - pyold; - pxold = px; - pyold = py; - for(i=0;iDrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy); - pxp = x[i]+dpx; - pyp = y[i]+dpy; - gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4); - gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4); - gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4); - gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4); + if (!opaque && !first_move) + paint_hollow(); + + if (ipoint < 0) { + Int_t pxp0, pyp0, pxp, pyp; + // move all points + for (Int_t i = 0; i < np; i++) { + get_point(i, pxp, pyp); + if (i == 0) { + pxp0 = pxp; + pyp0 = pyp; } - pxp = x[np-1]+dpx; - pyp = y[np-1]+dpy; - gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4, pyp-4); - gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4, pyp+4); - gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4, pyp+4); - gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4, pyp-4); - } else { - if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold); - if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old); - gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4, pyold-4); - gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4, pyold+4); - gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4, pyold+4); - gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4, pyold-4); - pxold = px; - pxold = TMath::Max(pxold, px1); - pxold = TMath::Min(pxold, px2); - pyold = py; - pyold = TMath::Max(pyold, py2); - pyold = TMath::Min(pyold, py1); - if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold); - if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old); - gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4, pyold-4); - gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4, pyold+4); - gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4, pyold+4); - gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4, pyold-4); + set_point(i, px + sdx + pxp - pxp0, py + sdy + pyp - pyp0); } } else { - if (middle) { - for(i=0;iPadtoX(gPad->AbsPixeltoX(x[i]+dpx)); - fY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy)); - } - } else { - fX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold)); - fY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold)); - } - } - gPad->Modified(kTRUE); + // move only selected point + set_point(ipoint, px + sdx, py + sdy); + } + if (is_last_same) { + fX[np] = fX[0]; + fY[np] = fY[0]; } + + first_move = kFALSE; + if (!opaque) + paint_hollow(); + else + parent.ModifiedUpdate(); break; case kButton1Up: - - // Compute x,y range - xmin = gPad->GetUxmin(); - xmax = gPad->GetUxmax(); - ymin = gPad->GetUymin(); - ymax = gPad->GetUymax(); - dx = xmax-xmin; - dy = ymax-ymin; - dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin()); - dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin()); - - // Range() could change the size of the pad pixmap and therefore should - // be called before the other paint routines - gPad->Range(xmin - dxr*gPad->GetLeftMargin(), - ymin - dyr*gPad->GetBottomMargin(), - xmax + dxr*gPad->GetRightMargin(), - ymax + dyr*gPad->GetTopMargin()); - gPad->RangeAxis(xmin, ymin, xmax, ymax); - - if (!x.empty() && !y.empty()) { - if (middle) { - for(i=0;iPadtoX(gPad->AbsPixeltoX(x[i]+dpx)); - fY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy)); - } - } else { - fX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold)); - fY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold)); - } - x.clear(); - y.clear(); - } - gPad->Modified(kTRUE); - gVirtualX->SetLineColor(-1); + if (!opaque) + parent.ModifiedUpdate(); + break; } } @@ -513,13 +430,10 @@ Int_t TPolyLine::Merge(TCollection *li) void TPolyLine::Paint(Option_t *option) { - if (TestBit(kPolyLineNDC)) { - if (option && strlen(option)) PaintPolyLineNDC(fLastPoint+1, fX, fY, option); - else PaintPolyLineNDC(fLastPoint+1, fX, fY, fOption.Data()); - } else { - if (option && strlen(option)) PaintPolyLine(fLastPoint+1, fX, fY, option); - else PaintPolyLine(fLastPoint+1, fX, fY, fOption.Data()); - } + if (TestBit(kPolyLineNDC)) + PaintPolyLineNDC(fLastPoint+1, fX, fY, option && *option ? option : fOption.Data()); + else + PaintPolyLine(fLastPoint+1, fX, fY, option && *option ? option : fOption.Data()); } //////////////////////////////////////////////////////////////////////////////// @@ -533,24 +447,23 @@ void TPolyLine::PaintPolyLine(Int_t n, Double_t *x, Double_t *y, Option_t *optio if (!gPad || n <= 0) return; TAttLine::Modify(); //Change line attributes only if necessary TAttFill::Modify(); //Change fill area attributes only if necessary - Double_t *xx = x; - Double_t *yy = y; + std::vector xx, yy; if (gPad->GetLogx()) { - xx = new Double_t[n]; - for (Int_t ix=0;ixXtoPad(x[ix]); + xx.resize(n); + for (Int_t ix = 0; ix < n; ix++) + xx[ix] = gPad->XtoPad(x[ix]); + x = xx.data(); } if (gPad->GetLogy()) { - yy = new Double_t[n]; - for (Int_t iy=0;iyYtoPad(y[iy]); + yy.resize(n); + for (Int_t iy = 0; iy < n; iy++) + yy[iy] = gPad->YtoPad(y[iy]); + y = yy.data(); } if (option && (*option == 'f' || *option == 'F')) - gPad->PaintFillArea(n, xx, yy, option); + gPad->PaintFillArea(n, x, y, option); else - gPad->PaintPolyLine(n, xx, yy, option); - if (x != xx) - delete[] xx; - if (y != yy) - delete[] yy; + gPad->PaintPolyLine(n, x, y, option); } //////////////////////////////////////////////////////////////////////////////// @@ -558,10 +471,12 @@ void TPolyLine::PaintPolyLine(Int_t n, Double_t *x, Double_t *y, Option_t *optio void TPolyLine::PaintPolyLineNDC(Int_t n, Double_t *x, Double_t *y, Option_t *option) { - TAttLine::Modify(); //Change line attributes only if necessary - TAttFill::Modify(); //Change fill area attributes only if necessary - if (*option == 'f' || *option == 'F') gPad->PaintFillAreaNDC(n,x,y,option); - else gPad->PaintPolyLineNDC(n,x,y,option); + TAttLine::Modify(); // Change line attributes only if necessary + TAttFill::Modify(); // Change fill area attributes only if necessary + if (option && (*option == 'f' || *option == 'F')) + gPad->PaintFillAreaNDC(n, x, y, option); + else + gPad->PaintPolyLineNDC(n, x, y, option); } //////////////////////////////////////////////////////////////////////////////// diff --git a/graf2d/graf/src/TText.cxx b/graf2d/graf/src/TText.cxx index ad0410d198e5f..b736c94e91af8 100644 --- a/graf2d/graf/src/TText.cxx +++ b/graf2d/graf/src/TText.cxx @@ -15,8 +15,9 @@ #include "TBuffer.h" #include "TVirtualPad.h" #include "TVirtualPadPainter.h" -#include "TVirtualX.h" +#include "TCanvasImp.h" #include "TMath.h" +#include "TAttMarker.h" #include "TPoint.h" #include @@ -142,11 +143,9 @@ Int_t TText::DistancetoPrimitive(Int_t px, Int_t py) if (!gPad) return 9999; Int_t ptx, pty; - TAttText::Modify(); // change text attributes only if necessary - if (TestBit(kTextNDC)) { - ptx = gPad->UtoPixel(fX); - pty = gPad->VtoPixel(fY); + ptx = gPad->UtoAbsPixel(fX); + pty = gPad->VtoAbsPixel(fY); } else { ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX)); pty = gPad->YtoAbsPixel(gPad->YtoPad(fY)); @@ -220,91 +219,91 @@ TText *TText::DrawTextNDC(Double_t x, Double_t y, const wchar_t *text) void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py) { - if (!gPad) return; + if (!gPad || !gPad->IsEditable()) + return; + + auto &parent = *gPad; static Int_t px1, py1, pxold, pyold, Size, height, width; static Bool_t resize,turn; Int_t dx, dy; const char *text = GetTitle(); Int_t len = strlen(text); - Double_t sizetowin = gPad->GetAbsHNDC()*Double_t(gPad->GetWh()); + Double_t sizetowin = parent.GetAbsHNDC()*Double_t(parent.GetWh()); Double_t fh = (fTextSize*sizetowin); Int_t h = Int_t(fh/2); Int_t w = h*len; Short_t halign = fTextAlign/10; Short_t valign = fTextAlign - 10*halign; Double_t co, si, dtheta, norm; - static Bool_t right, ndcsav; + static Bool_t right; static Double_t theta; - Int_t ax, ay, bx, by, cx, cy; - ax = ay = 0; + Int_t ax = 0, ay = 0, bx, by, cx, cy; Double_t lambda, x2,y2; - Double_t dpx,dpy,xp1,yp1; Int_t cBoxX[4], cBoxY[4], part; Double_t div = 0; - Bool_t opaque = gPad->OpaqueMoving(); + Bool_t opaque = parent.OpaqueMoving(); - if (!gPad->IsEditable()) return; switch (event) { case kArrowKeyPress: case kButton1Down: - ndcsav = TestBit(kTextNDC); - // No break !!! - case kMouseMotion: if (TestBit(kTextNDC)) { - px1 = gPad->UtoPixel(fX); - py1 = gPad->VtoPixel(fY); + px1 = parent.UtoAbsPixel(fX); + py1 = parent.VtoAbsPixel(fY); } else { - px1 = gPad->XtoAbsPixel(gPad->XtoPad(fX)); - py1 = gPad->YtoAbsPixel(gPad->YtoPad(fY)); + px1 = parent.XtoAbsPixel(parent.XtoPad(fX)); + py1 = parent.YtoAbsPixel(parent.YtoPad(fY)); } - theta = fTextAngle; + theta = GetTextAngle(); Size = 0; pxold = px; pyold = py; - co = TMath::Cos(fTextAngle*0.017453293); - si = TMath::Sin(fTextAngle*0.017453293); + co = TMath::Cos(theta*0.017453293); + si = TMath::Sin(theta*0.017453293); resize = kFALSE; turn = kFALSE; GetControlBox(px1, py1, -theta, cBoxX, cBoxY); div = ((cBoxX[3]-cBoxX[0])*co-(cBoxY[3]-cBoxY[0])*si); - if (TMath::Abs(div) > 1e-8) part = (Int_t)(3*((px-cBoxX[0])*co-(py-cBoxY[0])*si)/ div); - else part = 0; + if (TMath::Abs(div) > 1e-8) + part = (Int_t)(3*((px-cBoxX[0])*co-(py-cBoxY[0])*si)/ div); + else + part = 0; switch (part) { case 0: if (halign == 3) { turn = kTRUE; right = kTRUE; - gPad->SetCursor(kRotate); + parent.SetCursor(kRotate); } else { resize = kTRUE; height = valign; width = halign; - gPad->SetCursor(kArrowVer); + parent.SetCursor(kArrowVer); } break; case 1: - gPad->SetCursor(kMove); + parent.SetCursor(kMove); break; case 2: if (halign == 3) { resize = kTRUE; height = valign; width = halign; - gPad->SetCursor(kArrowVer); + parent.SetCursor(kArrowVer); } else { turn = kTRUE; right = kFALSE; - gPad->SetCursor(kRotate); + parent.SetCursor(kRotate); } } break; case kArrowKeyRelease: case kButton1Motion: - if (!opaque) PaintControlBox(px1, py1, -theta); + if (!opaque) + PaintControlBox(px1, py1, -theta); if (turn) { norm = TMath::Sqrt(Double_t((py-py1)*(py-py1)+(px-px1)*(px-px1))); if (norm>0) { @@ -316,7 +315,6 @@ void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py) if (right) {theta = theta+180; if (theta>=360) theta -= 360;} } } else if (resize) { - co = TMath::Cos(fTextAngle*0.017453293); si = TMath::Sin(fTextAngle*0.017453293); if (width == 1) { @@ -340,8 +338,13 @@ void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py) case 3 : ax = px1-Int_t(co*w+si*h*3/2); ay = py1+Int_t(si*w+co*h*3/2); break; } } - if (height == 3) {bx = ax-Int_t(si*h); by = ay-Int_t(co*h);} - else {bx = ax; by = ay;} + if (height == 3) { + bx = ax-Int_t(si*h); + by = ay-Int_t(co*h); + } else { + bx = ax; + by = ay; + } cx = bx+Int_t(co*w); cy = by-Int_t(si*w); lambda = Double_t(((px-bx)*(cx-bx)+(py-by)*(cy-by)))/Double_t(((cx-bx)*(cx-bx)+(cy-by)*(cy-by))); x2 = Double_t(px) - lambda*Double_t(cx-bx)-Double_t(bx); @@ -350,49 +353,35 @@ void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py) if (Size<4) Size = 4; SetTextSize(Size/sizetowin); - TAttText::Modify(); } else { dx = px - pxold; px1 += dx; dy = py - pyold; py1 += dy; } if (opaque) { - if (ndcsav) this->SetNDC(kFALSE); - this->SetX(gPad->PadtoX(gPad->AbsPixeltoX(px1))); - this->SetY(gPad->PadtoY(gPad->AbsPixeltoY(py1))); - if (resize) gPad->ShowGuidelines(this, event, 't', false); - if ((!resize)&&(!turn)) gPad->ShowGuidelines(this, event, 'i', true); - gPad->ShowGuidelines(this, event, !resize&!turn); - this->SetTextAngle(theta); - gPad->Modified(kTRUE); - gPad->Update(); + SetX(GetXCoord(px1, TestBit(kTextNDC), kTRUE)); + SetY(GetYCoord(py1, TestBit(kTextNDC), kTRUE)); + if (resize) + parent.ShowGuidelines(this, event, 't', false); + if (!resize && !turn) + parent.ShowGuidelines(this, event, 'i', true); + parent.ShowGuidelines(this, event, !resize && !turn); + SetTextAngle(theta); + parent.ModifiedUpdate(); } - if (!opaque) PaintControlBox(px1, py1, -theta); + if (!opaque) + PaintControlBox(px1, py1, -theta); pxold = px; pyold = py; break; case kButton1Up: if (opaque) { - if (ndcsav && !this->TestBit(kTextNDC)) { - this->SetX((fX - gPad->GetX1())/(gPad->GetX2()-gPad->GetX1())); - this->SetY((fY - gPad->GetY1())/(gPad->GetY2()-gPad->GetY1())); - this->SetNDC(); - } - gPad->ShowGuidelines(this, event, !resize&!turn); + parent.ShowGuidelines(this, event, !resize && !turn); } else { - if (TestBit(kTextNDC)) { - dpx = gPad->GetX2() - gPad->GetX1(); - dpy = gPad->GetY2() - gPad->GetY1(); - xp1 = gPad->GetX1(); - yp1 = gPad->GetY1(); - fX = (gPad->AbsPixeltoX(px1)-xp1)/dpx; - fY = (gPad->AbsPixeltoY(py1)-yp1)/dpy; - } else { - fX = gPad->PadtoX(gPad->AbsPixeltoX(px1)); - fY = gPad->PadtoY(gPad->AbsPixeltoY(py1)); - } - fTextAngle = theta; + SetX(GetXCoord(px1, TestBit(kTextNDC), kTRUE)); + SetY(GetYCoord(py1, TestBit(kTextNDC), kTRUE)); + SetTextAngle(theta); } - gPad->Modified(kTRUE); + parent.Modified(kTRUE); break; case kButton1Locate: @@ -400,7 +389,7 @@ void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py) while (1) { px = py = 0; - event = gVirtualX->RequestLocator(1, 1, px, py); + event = parent.GetCanvasImp()->RequestLocator(px, py); ExecuteEvent(kButton1Motion, px, py); @@ -422,10 +411,15 @@ void TText::GetControlBox(Int_t x, Int_t y, Double_t theta, { Short_t halign = fTextAlign/10; // horizontal alignment Short_t valign = fTextAlign - 10*halign; // vertical alignment - UInt_t cBoxW, cBoxH; // control box width and heigh + UInt_t cBoxW = 0, cBoxH = 0; // control box width and heigh UInt_t Dx = 0, Dy = 0; // delta along x and y to align the box - GetBoundingBox(cBoxW, cBoxH); + if (gPad) { + Double_t tsize = GetTextSizePixels(*gPad); + auto pp = gPad->GetPainter(); + if (pp) + pp->GetTextExtent(GetTextFont(), tsize, cBoxW, cBoxH, GetTitle()); + } // compute the translations (Dx, Dy) required by the alignments switch (halign) { @@ -481,8 +475,8 @@ void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) Int_t cBoxX[4], cBoxY[4]; Int_t ptx, pty; if (TestBit(kTextNDC)) { - ptx = gPad->UtoPixel(fX); - pty = gPad->VtoPixel(fY); + ptx = gPad->UtoAbsPixel(fX); + pty = gPad->VtoAbsPixel(fY); } else { ptx = gPad->XtoAbsPixel(gPad->XtoPad(fX)); pty = gPad->YtoAbsPixel(gPad->YtoPad(fY)); @@ -498,8 +492,8 @@ void TText::GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle) if (cBoxY[i] < y1) y1 = cBoxY[i]; if (cBoxY[i] > y2) y2 = cBoxY[i]; } - w = x2-x1; - h = y2-y1; + w = x2 - x1; + h = y2 - y1; } else { Double_t tsize = GetTextSizePixels(*gPad); auto pp = gPad->GetPainter(); @@ -625,14 +619,20 @@ void TText::PaintControlBox(Int_t x, Int_t y, Double_t theta) Short_t valign = fTextAlign - 10*halign; // vertical alignment GetControlBox(x, y, theta, cBoxX, cBoxY); + + auto pp = gPad->GetPainter(); + if (!pp) + return; + // Draw the text control box outline - gVirtualX->SetLineStyle((Style_t)1); - gVirtualX->SetLineWidth(1); - gVirtualX->SetLineColor(1); - gVirtualX->DrawLine(cBoxX[0], cBoxY[0], cBoxX[1], cBoxY[1]); - gVirtualX->DrawLine(cBoxX[1], cBoxY[1], cBoxX[2], cBoxY[2]); - gVirtualX->DrawLine(cBoxX[2], cBoxY[2], cBoxX[3], cBoxY[3]); - gVirtualX->DrawLine(cBoxX[3], cBoxY[3], cBoxX[0], cBoxY[0]); + pp->SetAttLine({(Style_t)1, 1, 1}); + for (int p1 = 0; p1 < 4; ++p1) { + int p2 = (p1 + 1) % 4; + pp->DrawLine(gPad->AbsPixeltoX(cBoxX[p1]), + gPad->AbsPixeltoY(cBoxY[p1]), + gPad->AbsPixeltoX(cBoxX[p2]), + gPad->AbsPixeltoY(cBoxY[p2])); + } // Draw a symbol at the text starting point TPoint p; @@ -660,12 +660,10 @@ void TText::PaintControlBox(Int_t x, Int_t y, Double_t theta) } break; } - p.fX = (cBoxX[ix]+cBoxX[iy])/2; - p.fY = (cBoxY[ix]+cBoxY[iy])/2; - gVirtualX->SetMarkerColor(1); - gVirtualX->SetMarkerStyle(24); - gVirtualX->SetMarkerSize(0.7); - gVirtualX->DrawPolyMarker(1, &p); + Double_t mX = gPad->AbsPixeltoX((cBoxX[ix]+cBoxX[iy])/2); + Double_t mY = gPad->AbsPixeltoY((cBoxY[ix]+cBoxY[iy])/2); + pp->SetAttMarker({(Color_t)1, 24, 0.7}); + pp->DrawPolyMarker(1, &mX, &mY); } //////////////////////////////////////////////////////////////////////////////// @@ -787,7 +785,7 @@ void TText::Streamer(TBuffer &R__b) Rectangle_t TText::GetBBox() { - Rectangle_t BBox{0, 0, 0, 0}; + Rectangle_t bbox{0, 0, 0, 0}; if (gPad) { UInt_t w, h; Int_t Dx = 0, Dy = 0; @@ -807,13 +805,17 @@ Rectangle_t TText::GetBBox() case 2: Dy = h / 2; break; case 3: Dy = 0; break; } - - BBox.fX = gPad->XtoPixel(fX) - Dx; - BBox.fY = gPad->YtoPixel(fY) - Dy; - BBox.fWidth = w; - BBox.fHeight = h; + if (TestBit(kTextNDC)) { + bbox.fX = gPad->UtoPixel(GetX()) - Dx; + bbox.fY = gPad->VtoPixel(GetY()) - Dy; + } else { + bbox.fX = gPad->XtoPixel(gPad->XtoPad(GetX())) - Dx; + bbox.fY = gPad->YtoPixel(gPad->YtoPad(GetY())) - Dy; + } + bbox.fWidth = w; + bbox.fHeight = h; } - return BBox; + return bbox; } //////////////////////////////////////////////////////////////////////////////// @@ -823,29 +825,23 @@ TPoint TText::GetBBoxCenter() { TPoint p(0, 0); if (gPad) { - p.SetX(gPad->XtoPixel(fX)); - p.SetY(gPad->YtoPixel(fY)); + if (TestBit(kTextNDC)) { + p.SetX(gPad->UtoPixel(GetX())); + p.SetY(gPad->VtoPixel(GetY())); + } else { + p.SetX(gPad->XtoPixel(gPad->XtoPad(GetX()))); + p.SetY(gPad->YtoPixel(gPad->YtoPad(GetY()))); + } } return p; } -//////////////////////////////////////////////////////////////////////////////// -/// Set the point given by Alignment as 'center' - -void TText::SetBBoxCenter(const TPoint &p) -{ - if (!gPad) return; - this->SetX(gPad->PixeltoX(p.GetX())); - this->SetY(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))); -} - //////////////////////////////////////////////////////////////////////////////// /// Set X coordinate of the point given by Alignment as 'center' void TText::SetBBoxCenterX(const Int_t x) { - if (!gPad) return; - this->SetX(gPad->PixeltoX(x)); + SetX(GetXCoord(x, TestBit(kTextNDC))); } //////////////////////////////////////////////////////////////////////////////// @@ -853,41 +849,5 @@ void TText::SetBBoxCenterX(const Int_t x) void TText::SetBBoxCenterY(const Int_t y) { - if (!gPad) return; - this->SetY(gPad->PixeltoY(y - gPad->VtoPixel(0))); -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set left hand side of BoundingBox to a value -/// (resize in x direction on left) - -void TText::SetBBoxX1(const Int_t /*x*/) -{ - //NOT IMPLEMENTED -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set right hand side of BoundingBox to a value -/// (resize in x direction on right) - -void TText::SetBBoxX2(const Int_t /*x*/) -{ - //NOT IMPLEMENTED -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set top of BoundingBox to a value (resize in y direction on top) - -void TText::SetBBoxY1(const Int_t /*y*/) -{ - //NOT IMPLEMENTED -} - -//////////////////////////////////////////////////////////////////////////////// -/// Set bottom of BoundingBox to a value -/// (resize in y direction on bottom) - -void TText::SetBBoxY2(const Int_t /*y*/) -{ - //NOT IMPLEMENTED + SetY(GetYCoord(y, TestBit(kTextNDC))); } diff --git a/graf2d/quartz/inc/QuartzLine.h b/graf2d/quartz/inc/QuartzLine.h index cff6c96459af6..762f82f669c1e 100644 --- a/graf2d/quartz/inc/QuartzLine.h +++ b/graf2d/quartz/inc/QuartzLine.h @@ -34,7 +34,7 @@ void SetLineStyle(CGContextRef ctx, Int_t lstyle); void SetLineWidth(CGContextRef ctx, Int_t width); void DrawLine(CGContextRef ctx, Int_t x1, Int_t y1, Int_t x2, Int_t y2); -void DrawPolyLine(CGContextRef ctx, Int_t n, TPoint * xy); +void DrawPolyLine(CGContextRef ctx, Int_t n, const TPoint *xy); } } diff --git a/graf2d/quartz/inc/QuartzMarker.h b/graf2d/quartz/inc/QuartzMarker.h index 9191799fcc4d6..533a85d9e1594 100644 --- a/graf2d/quartz/inc/QuartzMarker.h +++ b/graf2d/quartz/inc/QuartzMarker.h @@ -27,14 +27,13 @@ #include "Rtypes.h" #include "TPoint.h" +#include "TAttMarker.h" namespace ROOT { namespace Quartz { -void DrawPolyMarker(CGContextRef ctx, const std::vector &marker, - Size_t markerSize, Style_t markerStyle); void DrawPolyMarker(CGContextRef ctx, unsigned nPoints, const TPoint *marker, - Size_t markerSize, Style_t markerStyle); + const TAttMarker &attmark, float scaleFactor); } } diff --git a/graf2d/quartz/src/QuartzLine.mm b/graf2d/quartz/src/QuartzLine.mm index 36e33e7c133d7..9568073919a5d 100644 --- a/graf2d/quartz/src/QuartzLine.mm +++ b/graf2d/quartz/src/QuartzLine.mm @@ -133,7 +133,7 @@ void DrawLine(CGContextRef ctx, Int_t x1, Int_t y1, Int_t x2, Int_t y2) //______________________________________________________________________________ -void DrawPolyLine(CGContextRef ctx, Int_t n, TPoint * xy) +void DrawPolyLine(CGContextRef ctx, Int_t n, const TPoint *xy) { // Draw a line through all points. // n : number of points diff --git a/graf2d/quartz/src/QuartzMarker.mm b/graf2d/quartz/src/QuartzMarker.mm index 87af296b0cb6a..ee2cd6771c785 100644 --- a/graf2d/quartz/src/QuartzMarker.mm +++ b/graf2d/quartz/src/QuartzMarker.mm @@ -12,6 +12,9 @@ #include "TAttMarker.h" #include "QuartzMarker.h" +#include "QuartzLine.h" +#include "QuartzFillArea.h" +#include "TMath.h" namespace ROOT { namespace Quartz { @@ -906,8 +909,32 @@ void DrawMarkerFourSquaresPlus(CGContextRef ctx, unsigned n, const TPoint *xy, //______________________________________________________________________________ void DrawPolyMarker(CGContextRef ctx, unsigned nPoints, const TPoint *xy, - Size_t markerSize, Style_t markerStyle) + const TAttMarker &attmark, float scaleFactor) { + if (!Quartz::SetFillColor(ctx, attmark.GetMarkerColor())) + return; + + Quartz::SetLineColor(ctx, attmark.GetMarkerColor());//Can not fail (for coverity). + Quartz::SetLineStyle(ctx, 1); + Quartz::SetLineWidth(ctx, TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(attmark.GetMarkerStyle())))); + + if (scaleFactor > 1.) + CGContextScaleCTM(ctx, 1. / scaleFactor, 1. / scaleFactor); + + Style_t markerStyle = TAttMarker::GetMarkerStyleBase(attmark.GetMarkerStyle()); + + // The fast pixel markers need to be treated separately + if (markerStyle == 1 || markerStyle == 6 || markerStyle == 7) { + CGContextSetLineJoin(ctx, kCGLineJoinMiter); + CGContextSetLineCap(ctx, kCGLineCapButt); + } else { + CGContextSetLineJoin(ctx, kCGLineJoinRound); + CGContextSetLineCap(ctx, kCGLineCapRound); + } + + Float_t markerSize = attmark.GetMarkerSize() - TMath::Floor(TAttMarker::GetMarkerLineWidth(attmark.GetMarkerStyle())/2.)/4.; + markerSize *= scaleFactor; + switch (markerStyle) { case kDot: DrawMarkerDot(ctx, nPoints, xy, markerSize); @@ -1018,15 +1045,11 @@ void DrawPolyMarker(CGContextRef ctx, unsigned nPoints, const TPoint *xy, DrawMarkerFourSquaresPlus(ctx, nPoints, xy, markerSize); break; } -} - -//______________________________________________________________________________ -void DrawPolyMarker(CGContextRef ctx, const std::vector &xy, - Size_t markerSize, Style_t markerStyle) -{ - DrawPolyMarker(ctx, xy.size(), &xy[0], markerSize, markerStyle); + CGContextSetLineJoin(ctx, kCGLineJoinMiter); + CGContextSetLineCap(ctx, kCGLineCapButt); } + }//namespace Quartz }//namespace ROOT diff --git a/graf3d/gl/inc/TGLPadPainter.h b/graf3d/gl/inc/TGLPadPainter.h index b77c8a6178baf..082534627c988 100644 --- a/graf3d/gl/inc/TGLPadPainter.h +++ b/graf3d/gl/inc/TGLPadPainter.h @@ -43,13 +43,20 @@ class TGLPadPainter : public TPadPainterBase { Int_t fVp[4]; - std::vector fPoly; Bool_t fIsHollowArea; Bool_t fLocked; + Bool_t IsInvertMode(); + void SelectGLFont(Font_t font, Float_t size); + template + void DrawPolyMarkerHelper(Int_t n, const ValueType *x, const ValueType *y); + + template + void DrawPolyLineHelper(Int_t n, const ValueType *x, const ValueType *y); + template void DrawTextHelper(Double_t x, Double_t y, const Char_t *text, ETextMode mode); @@ -144,8 +151,6 @@ class TGLPadPainter : public TPadPainterBase { void SaveViewport(); void RestoreViewport(); - void DrawPolyMarker(); - //Aux. functions for a gradient and solid fill: void DrawPolygonWithGradient(Int_t n, const Double_t *x, const Double_t *y); // diff --git a/graf3d/gl/src/TGLPadPainter.cxx b/graf3d/gl/src/TGLPadPainter.cxx index 83e4ebca52504..58649477b6453 100644 --- a/graf3d/gl/src/TGLPadPainter.cxx +++ b/graf3d/gl/src/TGLPadPainter.cxx @@ -355,11 +355,10 @@ void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) //that TView3D wants to draw itself in a XOR mode, via //gVirtualX. // TODO: only here set line attributes to virtual x - if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + if (IsInvertMode()) gVirtualX->DrawLineW(fWinContext, gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2)); - } return; } @@ -395,13 +394,11 @@ void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2) void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2) { if (fLocked) { - // this code used when crosshair cursor is drawn - if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { - // TODO: only here set line attributes to virtual x + // this code used when crosshair cursor is drawn or interactive objects move + if (IsInvertMode()) gVirtualX->DrawLineW(fWinContext, gPad->UtoAbsPixel(u1), gPad->VtoAbsPixel(v1), gPad->UtoAbsPixel(u2), gPad->VtoAbsPixel(v2)); - } return; } @@ -427,12 +424,11 @@ void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, //that TView3D wants to draw itself in a XOR mode, via //gVirtualX. // TODO: only here set line attributes to virtual x - if (fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert)) { + if (IsInvertMode()) gVirtualX->DrawBoxW(fWinContext, gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1), gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2), (TVirtualX::EBoxMode) mode); - } return; } @@ -445,11 +441,12 @@ void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, if (mode == kHollow) { const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, 0, fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); - // - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glRectd(x1, y1, x2, y2); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glLineWidth(1.f); + glBegin(GL_LINE_LOOP); + glVertex2d(x1, y1); + glVertex2d(x2, y1); + glVertex2d(x2, y2); + glVertex2d(x1, y2); + glEnd(); } else { const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE, &fGlFillAtt);//Set filling parameters. glRectd(x1, y1, x2, y2); @@ -521,9 +518,20 @@ void TGLPadPainter::DrawFillArea(Int_t n, const Float_t *x, const Float_t *y) //////////////////////////////////////////////////////////////////////////////// ///Draw poly-line in user coordinates. -void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) +template +void TGLPadPainter::DrawPolyLineHelper(Int_t n, const ValueType *x, const ValueType *y) { - if (fLocked) return; + if (fLocked) { + if (IsInvertMode() && (n > 1)) { + std::vector xy(n); + for (Int_t i = 0; i < n; ++i) { + xy[i].fX = (SCoord_t) gPad->XtoAbsPixel(x[i]); + xy[i].fY = (SCoord_t) gPad->YtoAbsPixel(y[i]); + } + gVirtualX->DrawPolyLineW(fWinContext, xy.size(), xy.data()); + } + return; + } const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); @@ -556,25 +564,19 @@ void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) } //////////////////////////////////////////////////////////////////////////////// -///Never called? +/// Draw poly-line in user coordinates. -void TGLPadPainter::DrawPolyLine(Int_t n, const Float_t *x, const Float_t *y) +void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y) { - if (fLocked) return; - - const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, GetAttLine().GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE, &GetAttLine()); - - glBegin(GL_LINE_STRIP); - - for (Int_t i = 0; i < n; ++i) - glVertex2f(x[i], y[i]); + DrawPolyLineHelper(n, x, y); +} - if (fIsHollowArea) { - glVertex2f(x[0], y[0]); - fIsHollowArea = kFALSE; - } +//////////////////////////////////////////////////////////////////////////////// +/// Draw poly-line in user coordinates. - glEnd(); +void TGLPadPainter::DrawPolyLine(Int_t n, const Float_t *x, const Float_t *y) +{ + DrawPolyLineHelper(n, x, y); } //////////////////////////////////////////////////////////////////////////////// @@ -597,47 +599,45 @@ void TGLPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t * glEnd(); } -namespace { - -//Aux. function. -template -void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector & dst); - -} - //////////////////////////////////////////////////////////////////////////////// -///Poly-marker. +/// Returns true when invert mode is configured and painter in locked state +/// Used when non-opaque of objects moving is involved -void TGLPadPainter::DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) +Bool_t TGLPadPainter::IsInvertMode() { - if (fLocked) return; - - ConvertMarkerPoints(n, x, y, fPoly); - DrawPolyMarker(); + return fWinContext && (gVirtualX->GetDrawModeW(fWinContext) == TVirtualX::kInvert); } //////////////////////////////////////////////////////////////////////////////// -///Poly-marker. +///Poly-marker drawing -void TGLPadPainter::DrawPolyMarker(Int_t n, const Float_t *x, const Float_t *y) +template +void TGLPadPainter::DrawPolyMarkerHelper(Int_t n, const ValueType *x, const ValueType *y) { - if (fLocked) return; + std::vector poly(n); - ConvertMarkerPoints(n, x, y, fPoly); - DrawPolyMarker(); -} + if (fLocked) { + if (IsInvertMode()) { + for (Int_t i = 0; i < n; ++i) { + poly[i].fX = gPad->XtoAbsPixel(x[i]); + poly[i].fY = gPad->YtoAbsPixel(y[i]); + } + gVirtualX->DrawPolyMarkerW(fWinContext, poly.size(), poly.data()); + } + return; + } -//////////////////////////////////////////////////////////////////////////////// -///Poly-marker. + const UInt_t padH = gPad->GetPadHeight(); -void TGLPadPainter::DrawPolyMarker() -{ - if (fLocked) return; + for (Int_t i = 0; i < n; ++i) { + poly[i].fX = gPad->XtoPixel(x[i]); + poly[i].fY = padH - gPad->YtoPixel(y[i]); + } SaveProjectionMatrix(); glLoadIdentity(); // - glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.); + glOrtho(0, gPad->GetPadWidth(), 0, gPad->GetPadHeight(), -10., 10.); // glMatrixMode(GL_MODELVIEW); // @@ -648,127 +648,124 @@ void TGLPadPainter::DrawPolyMarker() glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4fv(rgba); - const Width_t w = TMath::Max(1, Int_t(TAttMarker::GetMarkerLineWidth(GetAttMarker().GetMarkerStyle()))); glLineWidth(w > fLimits.GetMaxLineWidth() ? fLimits.GetMaxLineWidth() : !w ? 1.f : w); fMarker.SetMarkerSizeWidth(GetAttMarker().GetMarkerSize(), w); - const TPoint *xy = &fPoly[0]; const Style_t markerStyle = TAttMarker::GetMarkerStyleBase(GetAttMarker().GetMarkerStyle()); - const UInt_t n = UInt_t(fPoly.size()); switch (markerStyle) { case kDot: - fMarker.DrawDot(n, xy); + fMarker.DrawDot(n, poly.data()); break; case kPlus: - fMarker.DrawPlus(n, xy); + fMarker.DrawPlus(n, poly.data()); break; case kStar: case 31: - fMarker.DrawStar(n, xy); + fMarker.DrawStar(n, poly.data()); break; case kCircle: case kOpenCircle: - fMarker.DrawCircle(n, xy); + fMarker.DrawCircle(n, poly.data()); break; case kMultiply: - fMarker.DrawX(n, xy); + fMarker.DrawX(n, poly.data()); break; case kFullDotSmall://"Full dot small" - fMarker.DrawFullDotSmall(n, xy); + fMarker.DrawFullDotSmall(n, poly.data()); break; case kFullDotMedium: - fMarker.DrawFullDotMedium(n, xy); + fMarker.DrawFullDotMedium(n, poly.data()); break; case kFullDotLarge: case kFullCircle: - fMarker.DrawFullDotLarge(n, xy); + fMarker.DrawFullDotLarge(n, poly.data()); break; case kFullSquare: - fMarker.DrawFullSquare(n, xy); + fMarker.DrawFullSquare(n, poly.data()); break; case kFullTriangleUp: - fMarker.DrawFullTrianlgeUp(n, xy); + fMarker.DrawFullTrianlgeUp(n, poly.data()); break; case kFullTriangleDown: - fMarker.DrawFullTrianlgeDown(n, xy); + fMarker.DrawFullTrianlgeDown(n, poly.data()); break; case kOpenSquare: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - fMarker.DrawFullSquare(n, xy); + fMarker.DrawFullSquare(n, poly.data()); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case kOpenTriangleUp: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - fMarker.DrawFullTrianlgeUp(n, xy); + fMarker.DrawFullTrianlgeUp(n, poly.data()); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case kOpenDiamond: - fMarker.DrawDiamond(n, xy); + fMarker.DrawDiamond(n, poly.data()); break; case kOpenCross: - fMarker.DrawOpenCross(n, xy); + fMarker.DrawOpenCross(n, poly.data()); break; case kFullStar: - fMarker.DrawFullStar(n, xy); + fMarker.DrawFullStar(n, poly.data()); break; case kOpenStar: - fMarker.DrawOpenStar(n, xy); + fMarker.DrawOpenStar(n, poly.data()); break; case kOpenTriangleDown: - fMarker.DrawOpenTrianlgeDown(n, xy); + fMarker.DrawOpenTrianlgeDown(n, poly.data()); break; case kFullDiamond: - fMarker.DrawFullDiamond(n, xy); + fMarker.DrawFullDiamond(n, poly.data()); break; case kFullCross: - fMarker.DrawFullCross(n, xy); + fMarker.DrawFullCross(n, poly.data()); break; case kOpenDiamondCross: - fMarker.DrawOpenDiamondCross(n, xy); + fMarker.DrawOpenDiamondCross(n, poly.data()); break; case kOpenSquareDiagonal: - fMarker.DrawOpenSquareDiagonal(n, xy); + fMarker.DrawOpenSquareDiagonal(n, poly.data()); break; case kOpenThreeTriangles: - fMarker.DrawOpenThreeTriangles(n, xy); + fMarker.DrawOpenThreeTriangles(n, poly.data()); break; case kOctagonCross: - fMarker.DrawOctagonCross(n, xy); + fMarker.DrawOctagonCross(n, poly.data()); break; case kFullThreeTriangles: - fMarker.DrawFullThreeTriangles(n, xy); + fMarker.DrawFullThreeTriangles(n, poly.data()); break; case kOpenFourTrianglesX: - fMarker.DrawOpenFourTrianglesX(n, xy); + fMarker.DrawOpenFourTrianglesX(n, poly.data()); break; case kFullFourTrianglesX: - fMarker.DrawFullFourTrianglesX(n, xy); + fMarker.DrawFullFourTrianglesX(n, poly.data()); break; case kOpenDoubleDiamond: - fMarker.DrawOpenDoubleDiamond(n, xy); + fMarker.DrawOpenDoubleDiamond(n, poly.data()); break; case kFullDoubleDiamond: - fMarker.DrawFullDoubleDiamond(n, xy); + fMarker.DrawFullDoubleDiamond(n, poly.data()); break; case kOpenFourTrianglesPlus: - fMarker.DrawOpenFourTrianglesPlus(n, xy); + fMarker.DrawOpenFourTrianglesPlus(n, poly.data()); break; case kFullFourTrianglesPlus: - fMarker.DrawFullFourTrianglesPlus(n, xy); + fMarker.DrawFullFourTrianglesPlus(n, poly.data()); break; case kOpenCrossX: - fMarker.DrawOpenCrossX(n, xy); + fMarker.DrawOpenCrossX(n, poly.data()); break; case kFullCrossX: - fMarker.DrawFullCrossX(n, xy); + fMarker.DrawFullCrossX(n, poly.data()); break; case kFourSquaresX: - fMarker.DrawFourSquaresX(n, xy); + fMarker.DrawFourSquaresX(n, poly.data()); break; case kFourSquaresPlus: - fMarker.DrawFourSquaresPlus(n, xy); + fMarker.DrawFourSquaresPlus(n, poly.data()); break; } @@ -777,6 +774,22 @@ void TGLPadPainter::DrawPolyMarker() glLineWidth(1.f); } +//////////////////////////////////////////////////////////////////////////////// +///Poly-marker. + +void TGLPadPainter::DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) +{ + DrawPolyMarkerHelper(n, x, y); +} + +//////////////////////////////////////////////////////////////////////////////// +///Poly-marker. + +void TGLPadPainter::DrawPolyMarker(Int_t n, const Float_t *x, const Float_t *y) +{ + DrawPolyMarkerHelper(n, x, y); +} + //////////////////////////////////////////////////////////////////////////////// /// Select specified font/size @@ -1540,21 +1553,3 @@ void TGLPadPainter::DrawTesselation(Int_t n, const Double_t *x, const Double_t * gluEndPolygon(t); } - -//Aux. functions. -namespace { - -template -void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector & dst) -{ - const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh()); - - dst.resize(n); - for (Int_t i = 0; i < n; ++i) { - dst[i].fX = gPad->XtoPixel(x[i]); - dst[i].fY = padH - gPad->YtoPixel(y[i]); - } -} - -} - diff --git a/hist/hist/src/TPolyMarker.cxx b/hist/hist/src/TPolyMarker.cxx index 7fcc0073f97d6..b28e63a910600 100644 --- a/hist/hist/src/TPolyMarker.cxx +++ b/hist/hist/src/TPolyMarker.cxx @@ -270,21 +270,23 @@ void TPolyMarker::Paint(Option_t *option) void TPolyMarker::PaintPolyMarker(Int_t n, Double_t *x, Double_t *y, Option_t *option) { - if (n <= 0) return; - TAttMarker::Modify(); //Change marker attributes only if necessary - Double_t *xx = x; - Double_t *yy = y; + if ((n <= 0) || !gPad) + return; + std::vector xx, yy; if (gPad->GetLogx()) { - xx = new Double_t[n]; - for (Int_t ix=0;ixXtoPad(x[ix]); + xx.resize(n); + for (Int_t ix = 0; ix < n; ix++) + xx[ix] = gPad->XtoPad(x[ix]); + x = xx.data(); } if (gPad->GetLogy()) { - yy = new Double_t[n]; - for (Int_t iy=0;iyYtoPad(y[iy]); + yy.resize(n); + for (Int_t iy = 0; iy < n; iy++) + yy[iy] = gPad->YtoPad(y[iy]); + y = yy.data(); } - gPad->PaintPolyMarker(n,xx,yy,option); - if (x != xx) delete [] xx; - if (y != yy) delete [] yy; + TAttMarker::ModifyOn(*gPad); //Change marker attributes only if necessary + gPad->PaintPolyMarker(n, x, y, option); } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/stressGraphics.ref b/test/stressGraphics.ref index c94bd663a397f..fe80e763bd830 100644 --- a/test/stressGraphics.ref +++ b/test/stressGraphics.ref @@ -9,7 +9,7 @@ piechart 67345 200 77066 200 32180 15000 29168 15000 66962 200 ttext1 1025 150 12862 200 33468 9900 30846 5000 1072 200 ttext2 430 50 12729 50 9558 100 5325 700 471 50 - tlatex0 6857 50 15580 50 47722 7000 64693 12000 6890 70 + tlatex0 9558 50 19030 70 47722 7000 64693 12000 9683 70 tlatex1 5130 50 14090 50 16143 1300 12230 500 5170 70 tlatex2 5442 80 13533 50 18430 700 12398 300 5469 80 tlatex3 9253 100 14437 150 19851 2400 12199 900 9283 100 diff --git a/test/stressGraphics_zlibng.ref b/test/stressGraphics_zlibng.ref index da4ccbd7b3a72..1aa4af2beee9b 100644 --- a/test/stressGraphics_zlibng.ref +++ b/test/stressGraphics_zlibng.ref @@ -9,7 +9,7 @@ piechart 67345 200 74560 3000 32180 15000 29168 15000 66962 200 ttext1 1025 150 12866 150 32266 9900 29901 5000 1072 200 ttext2 432 50 12743 50 9517 150 5306 700 473 50 - tlatex0 6857 50 15570 100 47722 7000 64693 12000 6890 70 + tlatex0 9558 50 19030 70 47722 7000 64693 12000 9683 70 tlatex1 5140 50 14050 50 16377 1300 12462 500 5170 70 tlatex2 5488 80 13507 100 18439 700 12061 500 5502 80 tlatex3 9154 100 14323 150 20441 2400 12143 900 9283 100 diff --git a/test/svg_ref/tlatex0.svg b/test/svg_ref/tlatex0.svg index 44ca63a6a96ea..891bbb0afb702 100644 --- a/test/svg_ref/tlatex0.svg +++ b/test/svg_ref/tlatex0.svg @@ -12,72 +12,120 @@ tlatex0.svg stroke-dasharray=" 1.000, 2.0"/> Font 42 - - + + Align 11 - - + + Align 21 - - + + Align 31 - - + + Align 12 - - + + Align 22 - - + + Align 32 - - + + Align 13 - - + + Align 23 - - + + Align 33 - - + + Align 11 - - + + Align 21 - - + + Align 31 @@ -88,72 +136,120 @@ tlatex0.svg stroke-dasharray=" 1.000, 2.0"/> Font 43 - - + + Align 11 - - + + Align 21 - - + + Align 31 - - + + Align 12 - - + + Align 22 - - + + Align 32 - - + + Align 13 - - + + Align 23 - - + + Align 33 - - + + Align 11 - - + + Align 21 - - + + Align 31 diff --git a/test/svg_ref/waves.svg b/test/svg_ref/waves.svg index 5376057b833e6..47a0d1e4546d9 100644 --- a/test/svg_ref/waves.svg +++ b/test/svg_ref/waves.svg @@ -40055,12 +40055,12 @@ waves.svg 350 - - - - - - + + + + + +