38 bool IsGradientFill(Color_t fillColorIndex)
 
   40    return dynamic_cast<TColorGradient *
>(gROOT->GetColor(fillColorIndex));
 
   56 ClassImp(TGLPadPainter);
 
   60 TGLPadPainter::TGLPadPainter()
 
   61                   : fIsHollowArea(kFALSE),
 
   64    fVp[0] = fVp[1] = fVp[2] = fVp[3] = 0;
 
   71 Color_t TGLPadPainter::GetLineColor()
 const 
   73    return gVirtualX->GetLineColor();
 
   79 Style_t TGLPadPainter::GetLineStyle()
 const 
   81    return gVirtualX->GetLineStyle();
 
   87 Width_t TGLPadPainter::GetLineWidth()
 const 
   89    return gVirtualX->GetLineWidth();
 
   95 void TGLPadPainter::SetLineColor(Color_t lcolor)
 
   97    gVirtualX->SetLineColor(lcolor);
 
  103 void TGLPadPainter::SetLineStyle(Style_t lstyle)
 
  105    gVirtualX->SetLineStyle(lstyle);
 
  111 void TGLPadPainter::SetLineWidth(Width_t lwidth)
 
  113    gVirtualX->SetLineWidth(lwidth);
 
  119 Color_t TGLPadPainter::GetFillColor()
 const 
  121    return gVirtualX->GetFillColor();
 
  127 Style_t TGLPadPainter::GetFillStyle()
 const 
  129    return gVirtualX->GetFillStyle();
 
  136 Bool_t TGLPadPainter::IsTransparent()
 const 
  138    return gVirtualX->IsTransparent();
 
  144 void TGLPadPainter::SetFillColor(Color_t fcolor)
 
  146    gVirtualX->SetFillColor(fcolor);
 
  152 void TGLPadPainter::SetFillStyle(Style_t fstyle)
 
  154    gVirtualX->SetFillStyle(fstyle);
 
  160 void TGLPadPainter::SetOpacity(Int_t percent)
 
  162    gVirtualX->SetOpacity(percent);
 
  168 Short_t TGLPadPainter::GetTextAlign()
 const 
  170    return gVirtualX->GetTextAlign();
 
  176 Float_t TGLPadPainter::GetTextAngle()
 const 
  178    return gVirtualX->GetTextAngle();
 
  184 Color_t TGLPadPainter::GetTextColor()
 const 
  186    return gVirtualX->GetTextColor();
 
  192 Font_t TGLPadPainter::GetTextFont()
 const 
  194    return gVirtualX->GetTextFont();
 
  200 Float_t TGLPadPainter::GetTextSize()
 const 
  202    return gVirtualX->GetTextSize();
 
  208 Float_t TGLPadPainter::GetTextMagnitude()
 const 
  210    return gVirtualX->GetTextMagnitude();
 
  216 void TGLPadPainter::SetTextAlign(Short_t align)
 
  218    gVirtualX->SetTextAlign(align);
 
  224 void TGLPadPainter::SetTextAngle(Float_t tangle)
 
  226    gVirtualX->SetTextAngle(tangle);
 
  232 void TGLPadPainter::SetTextColor(Color_t tcolor)
 
  234    gVirtualX->SetTextColor(tcolor);
 
  240 void TGLPadPainter::SetTextFont(Font_t tfont)
 
  242    gVirtualX->SetTextFont(tfont);
 
  248 void TGLPadPainter::SetTextSize(Float_t tsize)
 
  250    gVirtualX->SetTextSize(tsize);
 
  256 void TGLPadPainter::SetTextSizePixels(Int_t npixels)
 
  258    gVirtualX->SetTextSizePixels(npixels);
 
  268 Int_t TGLPadPainter::CreateDrawable(UInt_t, UInt_t)
 
  276 void TGLPadPainter::ClearDrawable()
 
  283 void TGLPadPainter::CopyDrawable(Int_t , Int_t , Int_t )
 
  290 void TGLPadPainter::DestroyDrawable(Int_t )
 
  300 void TGLPadPainter::SelectDrawable(Int_t )
 
  305    if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
 
  306       Int_t px = 0, py = 0;
 
  308       pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
 
  310       py = gPad->GetWh() - py;
 
  312       TGLUtil::InitializeIfNeeded();
 
  313       const Float_t scale = TGLUtil::GetScreenScalingFactor();
 
  315       glViewport(GLint(px * scale), GLint(py * scale),
 
  316                  GLsizei(gPad->GetWw() * pad->GetAbsWNDC() * scale),
 
  317                  GLsizei(gPad->GetWh() * pad->GetAbsHNDC() * scale));
 
  319       glMatrixMode(GL_PROJECTION);
 
  321       glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
 
  323       glMatrixMode(GL_MODELVIEW);
 
  325       glTranslated(0., 0., -1.);
 
  327       ::Error(
"TGLPadPainter::SelectDrawable",
 
  328                "function was called not from TPad or TCanvas code\n");
 
  329       throw std::runtime_error(
"");
 
  343 void TGLPadPainter::InitPainter()
 
  345    glDisable(GL_DEPTH_TEST);
 
  346    glDisable(GL_CULL_FACE);
 
  347    glDisable(GL_LIGHTING);
 
  350    glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
 
  352    glDepthMask(GL_TRUE);
 
  353    glClearColor(1.,1.,1.,1.);
 
  354    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
  355    glDepthMask(GL_FALSE);
 
  357    glMatrixMode(GL_PROJECTION);
 
  360    glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
 
  362    glMatrixMode(GL_MODELVIEW);
 
  364    glTranslated(0., 0., -1.);
 
  373 void TGLPadPainter::InvalidateCS()
 
  377    glMatrixMode(GL_PROJECTION);
 
  380    glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
 
  382    glMatrixMode(GL_MODELVIEW);
 
  390 void TGLPadPainter::LockPainter()
 
  402 const Double_t lineWidthTS = 3.;
 
  407 void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
 
  415       if (gVirtualX->GetDrawMode() == TVirtualX::kInvert) {
 
  416          gVirtualX->DrawLine(gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
 
  417                              gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
 
  423    const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
 
  430    if (gVirtualX->GetLineWidth() > lineWidthTS) {
 
  431       Double_t pointSize = gVirtualX->GetLineWidth();
 
  432       if (pointSize > fLimits.GetMaxPointSize())
 
  433          pointSize = fLimits.GetMaxPointSize();
 
  434       glPointSize((GLfloat)pointSize);
 
  435       const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
 
  436       glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
 
  451 void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2)
 
  455    const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
 
  456    const Double_t xRange = gPad->GetX2() - gPad->GetX1();
 
  457    const Double_t yRange = gPad->GetY2() - gPad->GetY1();
 
  460    glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
 
  461    glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
 
  468 void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode)
 
  472    if (IsGradientFill(gVirtualX->GetFillColor())) {
 
  473       Double_t xs[] = {x1, x2, x2, x1};
 
  474       Double_t ys[] = {y1, y1, y2, y2};
 
  475       DrawPolygonWithGradient(4, xs, ys);
 
  479    if (mode == kHollow) {
 
  480       const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, 0, fLimits.GetMaxLineWidth(), kTRUE);
 
  482       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
  483       glRectd(x1, y1, x2, y2);
 
  484       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
  487       const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
 
  488       glRectd(x1, y1, x2, y2);
 
  495 void TGLPadPainter::DrawFillArea(Int_t n, 
const Double_t *x, 
const Double_t *y)
 
  497    assert(x != 0 && 
"DrawFillArea, parameter 'x' is null");
 
  498    assert(y != 0 && 
"DrawFillArea, parameter 'y' is null");
 
  504       ::Error(
"TGLPadPainter::DrawFillArea",
 
  505               "invalid number of points in a polygon");
 
  509    if (IsGradientFill(gVirtualX->GetFillColor()))
 
  510       return DrawPolygonWithGradient(n, x, y);
 
  512    if (!gVirtualX->GetFillStyle()) {
 
  513       fIsHollowArea = kTRUE;
 
  514       return DrawPolyLine(n, x, y);
 
  517    const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
 
  518    DrawTesselation(n, x, y);
 
  525 void TGLPadPainter::DrawFillArea(Int_t n, 
const Float_t *x, 
const Float_t *y)
 
  529    if (!gVirtualX->GetFillStyle()) {
 
  530       fIsHollowArea = kTRUE;
 
  531       return DrawPolyLine(n, x, y);
 
  536    for (Int_t i = 0; i < n; ++i) {
 
  538       fVs[i * 3 + 1] = y[i];
 
  541    const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
 
  543    GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
 
  545    gluNextContour(t, (GLenum)GLU_UNKNOWN);
 
  547    for (Int_t i = 0; i < n; ++i)
 
  548       gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
 
  557 void TGLPadPainter::DrawPolyLine(Int_t n, 
const Double_t *x, 
const Double_t *y)
 
  561    const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
 
  563    glBegin(GL_LINE_STRIP);
 
  565    for (Int_t i = 0; i < n; ++i)
 
  566       glVertex2d(x[i], y[i]);
 
  569       glVertex2d(x[0], y[0]);
 
  570       fIsHollowArea = kFALSE;
 
  574    if (gVirtualX->GetLineWidth() > lineWidthTS) {
 
  575       Double_t pointSize = gVirtualX->GetLineWidth();
 
  576       if (pointSize > fLimits.GetMaxPointSize())
 
  577          pointSize = fLimits.GetMaxPointSize();
 
  578       glPointSize((GLfloat)pointSize);
 
  579       const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
 
  580       glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
 
  583       for (Int_t i = 0; i < n; ++i)
 
  584          glVertex2d(x[i], y[i]);
 
  594 void TGLPadPainter::DrawPolyLine(Int_t n, 
const Float_t *x, 
const Float_t *y)
 
  598    const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
 
  600    glBegin(GL_LINE_STRIP);
 
  602    for (Int_t i = 0; i < n; ++i)
 
  603       glVertex2f(x[i], y[i]);
 
  606       glVertex2f(x[0], y[0]);
 
  607       fIsHollowArea = kFALSE;
 
  616 void TGLPadPainter::DrawPolyLineNDC(Int_t n, 
const Double_t *u, 
const Double_t *v)
 
  620    const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
 
  621    const Double_t xRange = gPad->GetX2() - gPad->GetX1();
 
  622    const Double_t yRange = gPad->GetY2() - gPad->GetY1();
 
  623    const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
 
  625    glBegin(GL_LINE_STRIP);
 
  627    for (Int_t i = 0; i < n; ++i)
 
  628       glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
 
  636 template<
class ValueType>
 
  637 void ConvertMarkerPoints(Int_t n, 
const ValueType *x, 
const ValueType *y, std::vector<TPoint> & dst);
 
  644 void TGLPadPainter::DrawPolyMarker(Int_t n, 
const Double_t *x, 
const Double_t *y)
 
  648    ConvertMarkerPoints(n, x, y, fPoly);
 
  655 void TGLPadPainter::DrawPolyMarker(Int_t n, 
const Float_t *x, 
const Float_t *y)
 
  659    ConvertMarkerPoints(n, x, y, fPoly);
 
  666 void TGLPadPainter::DrawPolyMarker()
 
  670    SaveProjectionMatrix();
 
  673    glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
 
  675    glMatrixMode(GL_MODELVIEW);
 
  677    const TGLEnableGuard blendGuard(GL_BLEND);
 
  679    Float_t rgba[4] = {};
 
  680    Rgl::Pad::ExtractRGBA(gVirtualX->GetMarkerColor(), rgba);
 
  681    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
  684    const TPoint *xy = &fPoly[0];
 
  685    const Style_t markerStyle = gVirtualX->GetMarkerStyle();
 
  686    const UInt_t n = UInt_t(fPoly.size());
 
  687    switch (markerStyle) {
 
  689       fMarker.DrawDot(n, xy);
 
  692       fMarker.DrawPlus(n, xy);
 
  696       fMarker.DrawStar(n, xy);
 
  700       fMarker.DrawCircle(n, xy);
 
  703       fMarker.DrawX(n, xy);
 
  706       fMarker.DrawFullDotSmall(n, xy);
 
  709       fMarker.DrawFullDotMedium(n, xy);
 
  713       fMarker.DrawFullDotLarge(n, xy);
 
  716       fMarker.DrawFullSquare(n, xy);
 
  718    case kFullTriangleUp:
 
  719       fMarker.DrawFullTrianlgeUp(n, xy);
 
  721    case kFullTriangleDown:
 
  722       fMarker.DrawFullTrianlgeDown(n, xy);
 
  725       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
  726       fMarker.DrawFullSquare(n, xy);
 
  727       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
  729    case kOpenTriangleUp:
 
  730       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 
  731       fMarker.DrawFullTrianlgeUp(n, xy);
 
  732       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
  735       fMarker.DrawDiamond(n, xy);
 
  738       fMarker.DrawOpenCross(n, xy);
 
  741       fMarker.DrawFullStar(n, xy);
 
  744       fMarker.DrawOpenStar(n, xy);
 
  746    case kOpenTriangleDown:
 
  747       fMarker.DrawOpenTrianlgeDown(n, xy);
 
  750       fMarker.DrawFullDiamond(n, xy);
 
  753       fMarker.DrawFullCross(n, xy);
 
  755    case kOpenDiamondCross:
 
  756       fMarker.DrawOpenDiamondCross(n, xy);
 
  758    case kOpenSquareDiagonal:
 
  759       fMarker.DrawOpenSquareDiagonal(n, xy);
 
  761    case kOpenThreeTriangles:
 
  762       fMarker.DrawOpenThreeTriangles(n, xy);
 
  765       fMarker.DrawOctagonCross(n, xy);
 
  767    case kFullThreeTriangles:
 
  768       fMarker.DrawFullThreeTriangles(n, xy);
 
  770    case kOpenFourTrianglesX:
 
  771       fMarker.DrawOpenFourTrianglesX(n, xy);
 
  773    case kFullFourTrianglesX:
 
  774       fMarker.DrawFullFourTrianglesX(n, xy);
 
  776    case kOpenDoubleDiamond:
 
  777       fMarker.DrawOpenDoubleDiamond(n, xy);
 
  779    case kFullDoubleDiamond:
 
  780       fMarker.DrawFullDoubleDiamond(n, xy);
 
  782    case kOpenFourTrianglesPlus:
 
  783       fMarker.DrawOpenFourTrianglesPlus(n, xy);
 
  785    case kFullFourTrianglesPlus:
 
  786       fMarker.DrawFullFourTrianglesPlus(n, xy);
 
  789       fMarker.DrawOpenCrossX(n, xy);
 
  792       fMarker.DrawFullCrossX(n, xy);
 
  795       fMarker.DrawFourSquaresX(n, xy);
 
  797    case kFourSquaresPlus:
 
  798       fMarker.DrawFourSquaresPlus(n, xy);
 
  802    RestoreProjectionMatrix();
 
  803    glMatrixMode(GL_MODELVIEW);
 
  809 void TGLPadPainter::DrawTextHelper(Double_t x, Double_t y, 
const Char *text, ETextMode )
 
  811    SaveProjectionMatrix();
 
  815    glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
 
  817    glMatrixMode(GL_MODELVIEW);
 
  819    Float_t rgba[4] = {};
 
  820    Rgl::Pad::ExtractRGBA(gVirtualX->GetTextColor(), rgba);
 
  826    const Int_t shift = TGLFontManager::GetExtendedFontStartIndex();
 
  828    Int_t fontIndex = TMath::Max(Short_t(10), gVirtualX->GetTextFont());
 
  829    if (fontIndex / 10 + shift > TGLFontManager::GetFontFileArray()->GetEntries())
 
  830       fontIndex = 20 + shift * 10;
 
  832       fontIndex += shift * 10;
 
  834    fFM.RegisterFont(TMath::Max(Int_t(gVirtualX->GetTextSize()) - 1, 10),
 
  835                                TGLFontManager::GetFontNameFromId(fontIndex),
 
  836                                TGLFont::kTexture, fF);
 
  839    const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
 
  840    fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
 
  843    RestoreProjectionMatrix();
 
  845    glMatrixMode(GL_MODELVIEW);
 
  854 void TGLPadPainter::DrawText(Double_t x, Double_t y, 
const char *text, ETextMode mode)
 
  858    if (!gVirtualX->GetTextSize())
 
  861    DrawTextHelper(x, y, text, mode);
 
  870 void TGLPadPainter::DrawText(Double_t x, Double_t y, 
const wchar_t *text, ETextMode mode)
 
  874    if (!gVirtualX->GetTextSize())
 
  877    DrawTextHelper(x, y, text, mode);
 
  886 void TGLPadPainter::DrawTextNDC(Double_t u, Double_t v, 
const char *text, ETextMode mode)
 
  890    const Double_t xRange = gPad->GetX2() - gPad->GetX1();
 
  891    const Double_t yRange = gPad->GetY2() - gPad->GetY1();
 
  892    DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
 
  901 void TGLPadPainter::DrawTextNDC(Double_t u, Double_t v, 
const wchar_t *text, ETextMode mode)
 
  905    const Double_t xRange = gPad->GetX2() - gPad->GetX1();
 
  906    const Double_t yRange = gPad->GetY2() - gPad->GetY1();
 
  907    DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
 
  915 void TGLPadPainter::SaveProjectionMatrix()
const 
  917    glMatrixMode(GL_PROJECTION);
 
  926 void TGLPadPainter::RestoreProjectionMatrix()
const 
  928    glMatrixMode(GL_PROJECTION);
 
  937 void TGLPadPainter::SaveModelviewMatrix()
const 
  939    glMatrixMode(GL_MODELVIEW);
 
  948 void TGLPadPainter::RestoreModelviewMatrix()
const 
  950    glMatrixMode(GL_MODELVIEW);
 
  957 void TGLPadPainter::SaveViewport()
 
  959    glGetIntegerv(GL_VIEWPORT, fVp);
 
  965 void TGLPadPainter::RestoreViewport()
 
  967    glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
 
  973 void TGLPadPainter::SaveImage(TVirtualPad *pad, 
const char *fileName, Int_t type)
 const 
  975    TVirtualPad *canvas = (TVirtualPad *)pad->GetCanvas();
 
  979    gROOT->ProcessLine(Form(
"((TCanvas *)0x%lx)->Flush();", (ULong_t)canvas));
 
  981    std::vector<unsigned> buff(canvas->GetWw() * canvas->GetWh());
 
  982    glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
  983    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
  986    glReadPixels(0, 0, canvas->GetWw(), canvas->GetWh(), GL_RGBA, GL_UNSIGNED_BYTE, (
char *)&buff[0]);
 
  988    std::unique_ptr<TImage> image(TImage::Create());
 
  990       ::Error(
"TGLPadPainter::SaveImage", 
"TImage creation failed");
 
  994    image->DrawRectangle(0, 0, canvas->GetWw(), canvas->GetWh());
 
  995    UInt_t *argb = image->GetArgbArray();
 
  998       ::Error(
"TGLPadPainter::SaveImage", 
"null argb array in TImage object");
 
 1002    const Int_t nLines  = canvas->GetWh();
 
 1003    const Int_t nPixels = canvas->GetWw();
 
 1005    for (Int_t i = 0; i < nLines; ++i) {
 
 1006      Int_t base = (nLines - 1 - i) * nPixels;
 
 1007      for (Int_t j = 0; j < nPixels; ++j, ++base) {
 
 1010         const UInt_t pix  = buff[base];
 
 1011         const UInt_t bgra = ((pix & 0xff) << 16) | (pix & 0xff00) |
 
 1012                             ((pix & 0xff0000) >> 16) | (pix & 0xff000000);
 
 1015         argb[i * nPixels + j] = bgra;
 
 1019    image->WriteImage(fileName, (TImage::EImageFileTypes)type);
 
 1024 void TGLPadPainter::DrawPixels(
const unsigned char *pixelData, UInt_t width, UInt_t height,
 
 1025                                Int_t dstX, Int_t dstY, Bool_t enableBlending)
 
 1032       ::Error(
"TGLPadPainter::DrawPixels", 
"pixel data is null");
 
 1036    if (std::numeric_limits<UInt_t>::digits >= 32) {
 
 1045       ::Error(
"TGLPadPainter::DrawPixels", 
"invalid width");
 
 1051       ::Error(
"TGLPadPainter::DrawPixels", 
"invalid height");
 
 1055    if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
 
 1060       const Double_t rasterX = Double_t(dstX) / (pad->GetAbsWNDC() * pad->GetWw()) *
 
 1061                                 (pad->GetX2() - pad->GetX1()) + pad->GetX1();
 
 1063       const Double_t yRange = pad->GetY2() - pad->GetY1();
 
 1064       const Double_t rasterY = yRange - Double_t(dstY + height) / (pad->GetAbsHNDC() * pad->GetWh()) * yRange +
 
 1067       GLdouble oldPos[4] = {};
 
 1069       glGetDoublev(GL_CURRENT_RASTER_POSITION, oldPos);
 
 1071       glRasterPos2d(rasterX, rasterY);
 
 1073       std::vector<unsigned char> upsideDownImage(4 * width * height);
 
 1074       const unsigned char *srcLine = pixelData + 4 * width * (height - 1);
 
 1075       unsigned char *dstLine = &upsideDownImage[0];
 
 1076       for (UInt_t i = 0; i < height; ++i, srcLine -= 4 * width, dstLine += 4 * width)
 
 1077          std::copy(srcLine, srcLine + 4 * width, dstLine);
 
 1079       if (enableBlending) {
 
 1081          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
 1084       glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, &upsideDownImage[0]);
 
 1087          glDisable(GL_BLEND);
 
 1090       glRasterPos2d(oldPos[0], oldPos[1]);
 
 1092       ::Error(
"TGLPadPainter::DrawPixels", 
"no pad found to draw");
 
 1102 void TGLPadPainter::DrawPolygonWithGradient(Int_t n, 
const Double_t *x, 
const Double_t *y)
 
 1104    assert(n > 2 && 
"DrawPolygonWithGradient, invalid number of points");
 
 1105    assert(x != 0 && 
"DrawPolygonWithGradient, parameter 'x' is null");
 
 1106    assert(y != 0 && 
"DrawPolygonWithGradient, parameter 'y' is null");
 
 1108    assert(dynamic_cast<TColorGradient *>(gROOT->GetColor(gVirtualX->GetFillColor())) != 0 &&
 
 1109           "DrawPolygonWithGradient, the current fill color is not a gradient fill");
 
 1110    const TColorGradient * 
const grad =
 
 1111          dynamic_cast<TColorGradient *
>(gROOT->GetColor(gVirtualX->GetFillColor()));
 
 1117    const TGLEnableGuard stencilGuard(GL_STENCIL_TEST);
 
 1122    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
 
 1124    glStencilFunc(GL_NEVER, 1, 0xFF);
 
 1125    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
 
 1127    glStencilMask(0xFF);
 
 1128    glClear(GL_STENCIL_BUFFER_BIT);
 
 1131    DrawTesselation(n, x, y);
 
 1133    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
 1134    glStencilMask(0x00);
 
 1136    glStencilFunc(GL_EQUAL, 0, 0xFF);
 
 1138    glStencilFunc(GL_EQUAL, 1, 0xFF);
 
 1144    const TRadialGradient * 
const rGrad = 
dynamic_cast<const TRadialGradient *
>(grad);
 
 1146       DrawGradient(rGrad, n, x, y);
 
 1148       const TLinearGradient * 
const lGrad = 
dynamic_cast<const TLinearGradient *
>(grad);
 
 1149       assert(lGrad != 0 && 
"DrawPolygonWithGradient, unknown gradient type");
 
 1150       DrawGradient(lGrad, n, x, y);
 
 1156 void TGLPadPainter::DrawGradient(
const TRadialGradient *grad, Int_t nPoints,
 
 1157                                  const Double_t *xs, 
const Double_t *ys)
 
 1159    assert(grad != 0 && 
"DrawGradient, parameter 'grad' is null");
 
 1160    assert(nPoints > 2 && 
"DrawGradient, invalid number of points");
 
 1161    assert(xs != 0 && 
"DrawGradient, parameter 'xs' is null");
 
 1162    assert(ys != 0 && 
"DrawGradient, parameter 'ys' is null");
 
 1164    if (grad->GetGradientType() != TRadialGradient::kSimple) {
 
 1165       ::Warning(
"TGLPadPainter::DrawGradient",
 
 1166                 "extended radial gradient is not supported");
 
 1171    const auto &bbox = Rgl::Pad::FindBoundingRect(nPoints, xs, ys);
 
 1173    auto center = grad->GetCenter();
 
 1174    auto radius = grad->GetRadius();
 
 1176    if (grad->GetCoordinateMode() == TColorGradient::kObjectBoundingMode) {
 
 1177       radius *= TMath::Max(bbox.fWidth, bbox.fHeight);
 
 1178       center.fX = bbox.fWidth * center.fX + bbox.fXMin;
 
 1179       center.fY = bbox.fHeight * center.fY + bbox.fYMin;
 
 1181       const auto w = gPad->GetX2() - gPad->GetX1();
 
 1182       const auto h = gPad->GetY2() - gPad->GetY1();
 
 1184       radius *= TMath::Max(w, h);
 
 1189    const auto pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
 
 1190    const auto pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
 
 1192    SaveProjectionMatrix();
 
 1193    SaveModelviewMatrix();
 
 1195    glMatrixMode(GL_PROJECTION);
 
 1198    glOrtho(0., pixelW, 0., pixelH, -10., 10.);
 
 1200    radius *= TMath::Max(pixelH, pixelW);
 
 1201    center.fX = gPad->XtoPixel(center.fX);
 
 1202    center.fY = pixelH - gPad->YtoPixel(center.fY);
 
 1206    const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
 
 1207    const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
 
 1208    const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
 
 1209    const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
 
 1212    const Double_t maxDistX = TMath::Max(TMath::Abs(center.fX - xMin),
 
 1213                                         TMath::Abs(center.fX - xMax));
 
 1214    const Double_t maxDistY = TMath::Max(TMath::Abs(center.fY - yMin),
 
 1215                                         TMath::Abs(center.fY - yMax));
 
 1216    maxR = TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY);
 
 1221    const Bool_t solidFillAfter = maxR > radius;
 
 1224    const UInt_t nSlices = 500;
 
 1226    const auto nColors = grad->GetNumberOfSteps();
 
 1229    const auto nCircles = nColors + 1 + solidFillAfter;
 
 1233    const auto locations = grad->GetColorPositions();
 
 1235    std::vector<Double_t> circles(nSlices * nCircles * 2);
 
 1236    const Double_t angle = TMath::TwoPi() / nSlices;
 
 1239    for (UInt_t i = 0; i < nColors; ++i) {
 
 1240       const auto circle = &circles[i * nSlices * 2];
 
 1242       const auto r = radius * locations[i];
 
 1243       for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
 
 1244          circle[j] = center.fX + r * TMath::Cos(angle * j);
 
 1245          circle[j + 1] = center.fY + r * TMath::Sin(angle * j);
 
 1248       circle[(nSlices - 1) * 2] = circle[0];
 
 1249       circle[(nSlices - 1) * 2 + 1] = circle[1];
 
 1254    const auto circle = &circles[nColors * nSlices * 2];
 
 1255    for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
 
 1256       circle[j] = center.fX + radius * TMath::Cos(angle * j);
 
 1257       circle[j + 1] = center.fY + radius * TMath::Sin(angle * j);
 
 1260    circle[(nSlices - 1) * 2] = circle[0];
 
 1261    circle[(nSlices - 1) * 2 + 1] = circle[1];
 
 1264    if (solidFillAfter) {
 
 1266       const auto circle = &circles[(nCircles - 1) * nSlices * 2];
 
 1267       for (UInt_t j = 0, e = nSlices * 2 - 2; j < e; j += 2) {
 
 1268          circle[j] = center.fX + maxR * TMath::Cos(angle * j);
 
 1269          circle[j + 1] = center.fY + maxR * TMath::Sin(angle * j);
 
 1272       circle[(nSlices - 1) * 2] = circle[0];
 
 1273       circle[(nSlices - 1) * 2 + 1] = circle[1];
 
 1284    const auto rgba = grad->GetColors();
 
 1286    const TGLEnableGuard alphaGuard(GL_BLEND);
 
 1288    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
 1291    glBegin(GL_TRIANGLE_FAN);
 
 1293    glVertex2d(center.fX, center.fY);
 
 1295    for (UInt_t i = 0, e = nSlices * 2; i < e; i += 2)
 
 1296       glVertex2dv(&circles[i]);
 
 1301    for (UInt_t i = 0; i < nColors - 1; ++i) {
 
 1302       const Double_t * 
const inner = &circles[i * nSlices * 2];
 
 1303       const auto innerRGBA = rgba + i * 4;
 
 1304       const auto outerRGBA = rgba + (i + 1) * 4;
 
 1305       const Double_t * 
const outer = &circles[(i + 1) * nSlices * 2];
 
 1307       Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, innerRGBA, outer, outerRGBA);
 
 1312    glBegin(GL_QUAD_STRIP);
 
 1313    const Double_t * 
const inner = &circles[nSlices * (nColors - 1) * 2];
 
 1314    const auto solidRGBA = rgba + (nColors - 1) * 4;
 
 1315    const Double_t * 
const outer = &circles[nSlices * nColors * 2];
 
 1317    Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
 
 1320    if (solidFillAfter) {
 
 1321       glBegin(GL_QUAD_STRIP);
 
 1322       const Double_t * 
const inner = &circles[nSlices * nColors * 2];
 
 1323       const auto solidRGBA = rgba + (nColors - 1) * 4;
 
 1324       const Double_t * 
const outer = &circles[nSlices * (nColors + 1) * 2];
 
 1326       Rgl::DrawQuadStripWithRadialGradientFill(nSlices, inner, solidRGBA, outer, solidRGBA);
 
 1329    RestoreProjectionMatrix();
 
 1330    RestoreModelviewMatrix();
 
 1335 void TGLPadPainter::DrawGradient(
const TLinearGradient *grad, Int_t n,
 
 1336                                  const Double_t *x, 
const Double_t *y)
 
 1338    assert(grad != 0 && 
"DrawGradient, parameter 'grad' is null");
 
 1339    assert(n > 2 && 
"DrawGradient, invalid number of points");
 
 1340    assert(x != 0 && 
"DrawGradient, parameter 'x' is null");
 
 1341    assert(y != 0 && 
"DrawGradient, parameter 'y' is null");
 
 1348    const auto &bbox = Rgl::Pad::FindBoundingRect(n, x, y);
 
 1353    SaveProjectionMatrix();
 
 1354    SaveModelviewMatrix();
 
 1357    glMatrixMode(GL_PROJECTION);
 
 1360    const Double_t pixelW = gPad->GetAbsWNDC() * gPad->GetWw();
 
 1361    const Double_t pixelH = gPad->GetAbsHNDC() * gPad->GetWh();
 
 1362    glOrtho(0., pixelW, 0., pixelH, -10., 10.);
 
 1365    glMatrixMode(GL_MODELVIEW);
 
 1368    TColorGradient::Point start = grad->GetStart();
 
 1369    TColorGradient::Point end   = grad->GetEnd();
 
 1372    if (grad->GetCoordinateMode() == TColorGradient::kPadMode)
 
 1374       const Double_t w = gPad->GetX2() - gPad->GetX1();
 
 1375       const Double_t h = gPad->GetY2() - gPad->GetY1();
 
 1377       start.fX = start.fX * w;
 
 1378       start.fY = start.fY * h;
 
 1379       end.fX   = end.fX * w;
 
 1380       end.fY   = end.fY * h;
 
 1382       start.fX = start.fX * bbox.fWidth + bbox.fXMin;
 
 1383       start.fY = start.fY * bbox.fHeight + bbox.fYMin;
 
 1384       end.fX   = end.fX * bbox.fWidth + bbox.fXMin;
 
 1385       end.fY   = end.fY * bbox.fHeight + bbox.fYMin;
 
 1392    start.fX = gPad->XtoPixel(start.fX);
 
 1393    start.fY = pixelH - gPad->YtoPixel(start.fY);
 
 1394    end.fX = gPad->XtoPixel(end.fX);
 
 1395    end.fY = pixelH - gPad->YtoPixel(end.fY);
 
 1396    const Double_t xMin = gPad->XtoPixel(bbox.fXMin);
 
 1397    const Double_t xMax = gPad->XtoPixel(bbox.fXMax);
 
 1398    const Double_t yMin = pixelH - gPad->YtoPixel(bbox.fYMin);
 
 1399    const Double_t yMax = pixelH - gPad->YtoPixel(bbox.fYMax);
 
 1405    const Double_t maxDistX = TMath::Max(TMath::Abs(start.fX - xMin), TMath::Abs(start.fX - xMax));
 
 1406    const Double_t maxDistY = TMath::Max(TMath::Abs(start.fY - yMin), TMath::Abs(start.fY - yMax));
 
 1408    const Double_t startEndLength = TMath::Sqrt((end.fX - start.fX) * (end.fX - start.fX) +
 
 1409                                                (end.fY - start.fY) * (end.fY - start.fY));
 
 1410    const Double_t h = TMath::Max(TMath::Sqrt(maxDistX * maxDistX + maxDistY * maxDistY),
 
 1414    const Double_t * 
const colorPositions = grad->GetColorPositions();
 
 1415    std::vector<Double_t> gradBoxes(grad->GetNumberOfSteps() + 2);
 
 1416    gradBoxes[0] = start.fY - h;
 
 1417    for (
unsigned i = 1; i <= grad->GetNumberOfSteps(); ++i)
 
 1418       gradBoxes[i] = startEndLength * colorPositions[i - 1] + start.fY;
 
 1420    gradBoxes[grad->GetNumberOfSteps() + 1] = start.fY + h;
 
 1423    Double_t angle = TMath::ACos((startEndLength * (end.fY - start.fY)) /
 
 1424                                 (startEndLength * startEndLength)) * TMath::RadToDeg();
 
 1425    if (end.fX > start.fX)
 
 1428    glTranslated(start.fX, start.fY, 0.);
 
 1429    glRotated(angle, 0., 0., 1.);
 
 1430    glTranslated(-start.fX, -start.fY, 0.);
 
 1432    const Double_t * 
const rgba = grad->GetColors();
 
 1434    const unsigned nEdges = gradBoxes.size();
 
 1435    const unsigned nColors = grad->GetNumberOfSteps();
 
 1436    const Double_t xLeft = start.fX - h, xRight = start.fX + h;
 
 1438    const TGLEnableGuard alphaGuard(GL_BLEND);
 
 1440    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
 1442    Rgl::DrawBoxWithGradientFill(gradBoxes[0], gradBoxes[1], xLeft, xRight, rgba, rgba);
 
 1443    Rgl::DrawBoxWithGradientFill(gradBoxes[nEdges - 2], gradBoxes[nEdges - 1], xLeft, xRight,
 
 1444                            rgba + (nColors - 1) * 4, rgba + (nColors - 1) * 4);
 
 1446    for (
unsigned i = 1; i < nEdges - 2; ++i)
 
 1447       Rgl::DrawBoxWithGradientFill(gradBoxes[i], gradBoxes[i + 1], xLeft,
 
 1448                                    xRight, rgba + (i - 1) * 4, rgba + i * 4);
 
 1450    RestoreProjectionMatrix();
 
 1451    RestoreModelviewMatrix();
 
 1456 void TGLPadPainter::DrawTesselation(Int_t n, 
const Double_t *x, 
const Double_t *y)
 
 1458    assert(n > 2 && 
"DrawTesselation, invalid number of points");
 
 1459    assert(x != 0 && 
"DrawTesselation, parameter 'x' is null");
 
 1460    assert(y != 0 && 
"DrawTesselation, parameter 'y' is null");
 
 1465    for (Int_t i = 0; i < n; ++i) {
 
 1467       fVs[i * 3 + 1] = y[i];
 
 1468       fVs[i * 3 + 2] = 0.;
 
 1473    GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
 
 1475    gluNextContour(t, (GLenum)GLU_UNKNOWN);
 
 1477    for (Int_t i = 0; i < n; ++i)
 
 1478       gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
 
 1487 template<
class ValueType>
 
 1488 void ConvertMarkerPoints(Int_t n, 
const ValueType *x, 
const ValueType *y, std::vector<TPoint> & dst)
 
 1490    const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
 
 1493    for (Int_t i = 0; i < n; ++i) {
 
 1494       dst[i].fX = gPad->XtoPixel(x[i]);
 
 1495       dst[i].fY = padH - gPad->YtoPixel(y[i]);