#include <stdexcept>
#include <iostream>
#include "TAttMarker.h"
#include "TVirtualX.h"
#include "TPad.h"
#include "TGLPadPainter.h"
#include "TGLIncludes.h"
#include "TGLUtil.h"
#include "TError.h"
ClassImp(TGLPadPainter)
TGLPadPainter::TGLPadPainter()
: fIsHollowArea(kFALSE),
fLocked(kTRUE)
{
}
Color_t TGLPadPainter::GetLineColor() const
{
return gVirtualX->GetLineColor();
}
Style_t TGLPadPainter::GetLineStyle() const
{
return gVirtualX->GetLineStyle();
}
Width_t TGLPadPainter::GetLineWidth() const
{
return gVirtualX->GetLineWidth();
}
void TGLPadPainter::SetLineColor(Color_t lcolor)
{
gVirtualX->SetLineColor(lcolor);
}
void TGLPadPainter::SetLineStyle(Style_t lstyle)
{
gVirtualX->SetLineStyle(lstyle);
}
void TGLPadPainter::SetLineWidth(Width_t lwidth)
{
gVirtualX->SetLineWidth(lwidth);
}
Color_t TGLPadPainter::GetFillColor() const
{
return gVirtualX->GetFillColor();
}
Style_t TGLPadPainter::GetFillStyle() const
{
return gVirtualX->GetFillStyle();
}
Bool_t TGLPadPainter::IsTransparent() const
{
return gVirtualX->IsTransparent();
}
void TGLPadPainter::SetFillColor(Color_t fcolor)
{
gVirtualX->SetFillColor(fcolor);
}
void TGLPadPainter::SetFillStyle(Style_t fstyle)
{
gVirtualX->SetFillStyle(fstyle);
}
void TGLPadPainter::SetOpacity(Int_t percent)
{
gVirtualX->SetOpacity(percent);
}
Short_t TGLPadPainter::GetTextAlign() const
{
return gVirtualX->GetTextAlign();
}
Float_t TGLPadPainter::GetTextAngle() const
{
return gVirtualX->GetTextAngle();
}
Color_t TGLPadPainter::GetTextColor() const
{
return gVirtualX->GetTextColor();
}
Font_t TGLPadPainter::GetTextFont() const
{
return gVirtualX->GetTextFont();
}
Float_t TGLPadPainter::GetTextSize() const
{
return gVirtualX->GetTextSize();
}
Float_t TGLPadPainter::GetTextMagnitude() const
{
return gVirtualX->GetTextMagnitude();
}
void TGLPadPainter::SetTextAlign(Short_t align)
{
gVirtualX->SetTextAlign(align);
}
void TGLPadPainter::SetTextAngle(Float_t tangle)
{
gVirtualX->SetTextAngle(tangle);
}
void TGLPadPainter::SetTextColor(Color_t tcolor)
{
gVirtualX->SetTextColor(tcolor);
}
void TGLPadPainter::SetTextFont(Font_t tfont)
{
gVirtualX->SetTextFont(tfont);
}
void TGLPadPainter::SetTextSize(Float_t tsize)
{
gVirtualX->SetTextSize(tsize);
}
void TGLPadPainter::SetTextSizePixels(Int_t npixels)
{
gVirtualX->SetTextSizePixels(npixels);
}
Int_t TGLPadPainter::CreateDrawable(UInt_t, UInt_t)
{
return 0;
}
void TGLPadPainter::ClearDrawable()
{
}
void TGLPadPainter::CopyDrawable(Int_t , Int_t , Int_t )
{
}
void TGLPadPainter::DestroyDrawable()
{
}
void TGLPadPainter::SelectDrawable(Int_t )
{
if (fLocked)
return;
if (TPad *pad = dynamic_cast<TPad *>(gPad)) {
Int_t px = 0, py = 0;
pad->XYtoAbsPixel(pad->GetX1(), pad->GetY1(), px, py);
py = gPad->GetWh() - py;
glViewport(px, py, GLsizei(gPad->GetWw() * pad->GetAbsWNDC()), GLsizei(gPad->GetWh() * pad->GetAbsHNDC()));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(pad->GetX1(), pad->GetX2(), pad->GetY1(), pad->GetY2(), -10., 10.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0., 0., -1.);
} else {
Error("TGLPadPainter::SelectDrawable", "function was called not from TPad or TCanvas code\n");
throw std::runtime_error("");
}
}
void TGLPadPainter::InitPainter()
{
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glViewport(0, 0, GLsizei(gPad->GetWw()), GLsizei(gPad->GetWh()));
glDepthMask(GL_TRUE);
glClearColor(1.,1.,1.,1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_FALSE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0., 0., -1.);
fLocked = kFALSE;
}
void TGLPadPainter::InvalidateCS()
{
if (fLocked)
return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(gPad->GetX1(), gPad->GetX2(), gPad->GetY1(), gPad->GetY2(), -10., 10.);
glMatrixMode(GL_MODELVIEW);
}
void TGLPadPainter::LockPainter()
{
if (fLocked)
return;
glFinish();
fLocked = kTRUE;
}
const Double_t lineWidthTS = 3.;
void TGLPadPainter::DrawLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
{
if (fLocked) {
if (gVirtualX->GetDrawMode() == TVirtualX::kInvert) {
gVirtualX->DrawLine(gPad->XtoAbsPixel(x1), gPad->YtoAbsPixel(y1),
gPad->XtoAbsPixel(x2), gPad->YtoAbsPixel(y2));
}
return;
}
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
glBegin(GL_LINES);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glEnd();
if (gVirtualX->GetLineWidth() > lineWidthTS) {
Double_t pointSize = gVirtualX->GetLineWidth();
if (pointSize > fLimits.GetMaxPointSize())
pointSize = fLimits.GetMaxPointSize();
glPointSize((GLfloat)pointSize);
const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glBegin(GL_POINTS);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glEnd();
glPointSize(1.f);
}
}
void TGLPadPainter::DrawLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2)
{
if (fLocked)
return;
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
const Double_t xRange = gPad->GetX2() - gPad->GetX1();
const Double_t yRange = gPad->GetY2() - gPad->GetY1();
glBegin(GL_LINES);
glVertex2d(gPad->GetX1() + u1 * xRange, gPad->GetY1() + v1 * yRange);
glVertex2d(gPad->GetX1() + u2 * xRange, gPad->GetY1() + v2 * yRange);
glEnd();
}
void TGLPadPainter::DrawBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, EBoxMode mode)
{
if (fLocked)
return;
if (mode == kHollow) {
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, 0, fLimits.GetMaxLineWidth(), kTRUE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glRectd(x1, y1, x2, y2);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
} else {
const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
glRectd(x1, y1, x2, y2);
}
}
void TGLPadPainter::DrawFillArea(Int_t n, const Double_t *x, const Double_t *y)
{
if (fLocked)
return;
if (!gVirtualX->GetFillStyle()) {
fIsHollowArea = kTRUE;
return DrawPolyLine(n, x, y);
}
fVs.resize(n * 3);
for (Int_t i = 0; i < n; ++i) {
fVs[i * 3] = x[i];
fVs[i * 3 + 1] = y[i];
fVs[i * 3 + 2] = 0.;
}
const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
gluBeginPolygon(t);
gluNextContour(t, (GLenum)GLU_UNKNOWN);
for (Int_t i = 0; i < n; ++i)
gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
gluEndPolygon(t);
}
void TGLPadPainter::DrawFillArea(Int_t n, const Float_t *x, const Float_t *y)
{
if (fLocked)
return;
if (!gVirtualX->GetFillStyle()) {
fIsHollowArea = kTRUE;
return DrawPolyLine(n, x, y);
}
fVs.resize(n * 3);
for (Int_t i = 0; i < n; ++i) {
fVs[i * 3] = x[i];
fVs[i * 3 + 1] = y[i];
}
const Rgl::Pad::FillAttribSet fillAttribs(fSSet, kFALSE);
GLUtesselator *t = (GLUtesselator *)fTess.GetTess();
gluBeginPolygon(t);
gluNextContour(t, (GLenum)GLU_UNKNOWN);
for (Int_t i = 0; i < n; ++i)
gluTessVertex(t, &fVs[i * 3], &fVs[i * 3]);
gluEndPolygon(t);
}
void TGLPadPainter::DrawPolyLine(Int_t n, const Double_t *x, const Double_t *y)
{
if (fLocked)
return;
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
glBegin(GL_LINE_STRIP);
for (Int_t i = 0; i < n; ++i)
glVertex2d(x[i], y[i]);
if (fIsHollowArea) {
glVertex2d(x[0], y[0]);
fIsHollowArea = kFALSE;
}
glEnd();
if (gVirtualX->GetLineWidth() > lineWidthTS) {
Double_t pointSize = gVirtualX->GetLineWidth();
if (pointSize > fLimits.GetMaxPointSize())
pointSize = fLimits.GetMaxPointSize();
glPointSize((GLfloat)pointSize);
const TGLEnableGuard pointSmooth(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glBegin(GL_POINTS);
for (Int_t i = 0; i < n; ++i)
glVertex2d(x[i], y[i]);
glEnd();
glPointSize(1.f);
}
}
void TGLPadPainter::DrawPolyLine(Int_t n, const Float_t *x, const Float_t *y)
{
if (fLocked)
return;
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
glBegin(GL_LINE_STRIP);
for (Int_t i = 0; i < n; ++i)
glVertex2f(x[i], y[i]);
if (fIsHollowArea) {
glVertex2f(x[0], y[0]);
fIsHollowArea = kFALSE;
}
glEnd();
}
void TGLPadPainter::DrawPolyLineNDC(Int_t n, const Double_t *u, const Double_t *v)
{
if (fLocked)
return;
const Rgl::Pad::LineAttribSet lineAttribs(kTRUE, gVirtualX->GetLineStyle(), fLimits.GetMaxLineWidth(), kTRUE);
const Double_t xRange = gPad->GetX2() - gPad->GetX1();
const Double_t yRange = gPad->GetY2() - gPad->GetY1();
const Double_t x1 = gPad->GetX1(), y1 = gPad->GetY1();
glBegin(GL_LINE_STRIP);
for (Int_t i = 0; i < n; ++i)
glVertex2d(x1 + u[i] * xRange, y1 + v[i] * yRange);
glEnd();
}
namespace {
template<class ValueType>
void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & dst);
}
void TGLPadPainter::DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y)
{
if (fLocked)
return;
ConvertMarkerPoints(n, x, y, fPoly);
DrawPolyMarker();
}
void TGLPadPainter::DrawPolyMarker(Int_t n, const Float_t *x, const Float_t *y)
{
if (fLocked)
return;
ConvertMarkerPoints(n, x, y, fPoly);
DrawPolyMarker();
}
void TGLPadPainter::DrawPolyMarker()
{
if (fLocked)
return;
SaveProjectionMatrix();
glLoadIdentity();
glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
glMatrixMode(GL_MODELVIEW);
Float_t rgba[3] = {};
Rgl::Pad::ExtractRGB(gVirtualX->GetMarkerColor(), rgba);
glColor3fv(rgba);
const TPoint *xy = &fPoly[0];
const Style_t markerStyle = gVirtualX->GetMarkerStyle();
const UInt_t n = UInt_t(fPoly.size());
switch (markerStyle) {
case kDot:
fMarker.DrawDot(n, xy);
break;
case kPlus:
fMarker.DrawPlus(n, xy);
break;
case kStar:
fMarker.DrawStar(n, xy);
break;
case kCircle:
case kOpenCircle:
fMarker.DrawCircle(n, xy);
break;
case kMultiply:
fMarker.DrawX(n, xy);
break;
case kFullDotSmall:
fMarker.DrawFullDotSmall(n, xy);
break;
case kFullDotMedium:
fMarker.DrawFullDotMedium(n, xy);
break;
case kFullDotLarge:
case kFullCircle:
fMarker.DrawFullDotLarge(n, xy);
break;
case kFullSquare:
fMarker.DrawFullSquare(n, xy);
break;
case kFullTriangleUp:
fMarker.DrawFullTrianlgeUp(n, xy);
break;
case kFullTriangleDown:
fMarker.DrawFullTrianlgeDown(n, xy);
break;
case kOpenSquare:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
fMarker.DrawFullSquare(n, xy);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case kOpenTriangleUp:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
fMarker.DrawFullTrianlgeUp(n, xy);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
case kOpenDiamond:
fMarker.DrawDiamond(n, xy);
break;
case kOpenCross:
fMarker.DrawCross(n, xy);
break;
case kFullStar:
fMarker.DrawFullStar(n, xy);
break;
case kOpenStar:
fMarker.DrawOpenStar(n, xy);
}
RestoreProjectionMatrix();
glMatrixMode(GL_MODELVIEW);
}
void TGLPadPainter::DrawText(Double_t x, Double_t y, const char *text, ETextMode )
{
if (fLocked)
return;
SaveProjectionMatrix();
glLoadIdentity();
glOrtho(0, gPad->GetAbsWNDC() * gPad->GetWw(), 0, gPad->GetAbsHNDC() * gPad->GetWh(), -10., 10.);
glMatrixMode(GL_MODELVIEW);
Float_t rgba[3] = {};
Rgl::Pad::ExtractRGB(gVirtualX->GetTextColor(), rgba);
glColor3fv(rgba);
fFM.RegisterFont(Int_t(gVirtualX->GetTextSize()) - 1,
TGLFontManager::GetFontNameFromId(gVirtualX->GetTextFont()),
TGLFont::kTexture, fF);
fF.PreRender();
const UInt_t padH = UInt_t(gPad->GetAbsHNDC() * gPad->GetWh());
fF.Render(text, gPad->XtoPixel(x), padH - gPad->YtoPixel(y), GetTextAngle(), GetTextMagnitude());
fF.PostRender();
RestoreProjectionMatrix();
glMatrixMode(GL_MODELVIEW);
}
void TGLPadPainter::DrawTextNDC(Double_t u, Double_t v, const char *text, ETextMode mode)
{
if (fLocked)
return;
const Double_t xRange = gPad->GetX2() - gPad->GetX1();
const Double_t yRange = gPad->GetY2() - gPad->GetY1();
DrawText(gPad->GetX1() + u * xRange, gPad->GetY1() + v * yRange, text, mode);
}
void TGLPadPainter::SaveProjectionMatrix()const
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
}
void TGLPadPainter::RestoreProjectionMatrix()const
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void TGLPadPainter::SaveModelviewMatrix()const
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
}
void TGLPadPainter::RestoreModelviewMatrix()const
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void TGLPadPainter::SaveViewport()
{
glGetIntegerv(GL_VIEWPORT, fVp);
}
void TGLPadPainter::RestoreViewport()
{
glViewport(fVp[0], fVp[1], fVp[2], fVp[3]);
}
namespace {
template<class ValueType>
void ConvertMarkerPoints(Int_t n, const ValueType *x, const ValueType *y, std::vector<TPoint> & 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]);
}
}
}