// @(#)root/gui:$Name: $:$Id: TGGC.cxx,v 1.4 2001/06/22 16:10:17 rdm Exp $
// Author: Fons Rademakers 20/9/2000
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TGGC and TGGCPool //
// //
// Encapsulate a graphics context used in the low level graphics. //
// TGGCPool provides a pool of graphics contexts. //
// //
//////////////////////////////////////////////////////////////////////////
#include "TGGC.h"
#include "TVirtualX.h"
#include "TList.h"
#include <string.h>
ClassImp(TGGC)
//______________________________________________________________________________
TGGC::TGGC(GCValues_t *values)
{
// Create a graphics context.
if (values) {
fValues = *values;
fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), values);
if (values->fMask & kGCDashList) {
if (values->fDashLen > (Int_t)sizeof(fValues.fDashes))
Warning("TGGC", "dash list can have only up to %d elements",
sizeof(fValues.fDashes));
fValues.fDashLen = TMath::Min(values->fDashLen, (Int_t)sizeof(fValues.fDashes));
gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
fValues.fDashLen);
}
} else {
memset(&fValues, 0, sizeof(GCValues_t));
fContext = 0;
}
fDelete = kTRUE;
}
//______________________________________________________________________________
TGGC::TGGC(const TGGC &g) : TObject(g)
{
// Copy a graphics context.
fValues = g.fValues;
if (g.fContext) {
fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &fValues);
if (fValues.fMask & kGCDashList)
gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
fValues.fDashLen);
} else
fContext = 0;
fDelete = kTRUE;
}
//______________________________________________________________________________
TGGC::~TGGC()
{
// Delete graphics context.
if (fContext && fDelete)
gVirtualX->DeleteGC(fContext);
}
//______________________________________________________________________________
TGGC &TGGC::operator=(const TGGC &rhs)
{
// Graphics context assignment operator. Use this operator to share
// a graphics context. Using this operator you will not get a copy of the
// context.
if (this != &rhs) {
if (fContext && fDelete)
gVirtualX->DeleteGC(fContext);
TObject::operator=(rhs);
fValues = rhs.fValues;
fContext = rhs.fContext;
if (fContext)
fDelete = kFALSE;
else
fDelete = kTRUE;
}
return *this;
}
//______________________________________________________________________________
GContext_t TGGC::operator()() const
{
// Not inline due to a bug in g++ 2.96 20000731 (Red Hat Linux 7.0)
return fContext;
}
//______________________________________________________________________________
void TGGC::UpdateValues(GCValues_t *values)
{
// Update values + mask.
fValues.fMask |= values->fMask;
for (Mask_t bit = 1; bit <= kGCArcMode; bit <<= 1) {
switch (bit & values->fMask) {
default:
case 0:
continue;
case kGCFunction:
fValues.fFunction = values->fFunction;
break;
case kGCPlaneMask:
fValues.fPlaneMask = values->fPlaneMask;
break;
case kGCForeground:
fValues.fForeground = values->fForeground;
break;
case kGCBackground:
fValues.fBackground = values->fBackground;
break;
case kGCLineWidth:
fValues.fLineWidth = values->fLineWidth;
break;
case kGCLineStyle:
fValues.fLineStyle = values->fLineStyle;
break;
case kGCCapStyle:
fValues.fCapStyle = values->fCapStyle;
break;
case kGCJoinStyle:
fValues.fJoinStyle = values->fJoinStyle;
break;
case kGCFillStyle:
fValues.fFillStyle = values->fFillStyle;
break;
case kGCFillRule:
fValues.fFillRule = values->fFillRule;
break;
case kGCTile:
fValues.fTile = values->fTile;
break;
case kGCStipple:
fValues.fStipple = values->fStipple;
break;
case kGCTileStipXOrigin:
fValues.fTsXOrigin = values->fTsXOrigin;
break;
case kGCTileStipYOrigin:
fValues.fTsYOrigin = values->fTsYOrigin;
break;
case kGCFont:
fValues.fFont = values->fFont;
break;
case kGCSubwindowMode:
fValues.fSubwindowMode = values->fSubwindowMode;
break;
case kGCGraphicsExposures:
fValues.fGraphicsExposures = values->fGraphicsExposures;
break;
case kGCClipXOrigin:
fValues.fClipXOrigin = values->fClipXOrigin;
break;
case kGCClipYOrigin:
fValues.fClipYOrigin = values->fClipYOrigin;
break;
case kGCClipMask:
fValues.fClipMask = values->fClipMask;
break;
case kGCDashOffset:
fValues.fDashOffset = values->fDashOffset;
break;
case kGCDashList:
if (values->fDashLen > (Int_t)sizeof(fValues.fDashes))
Warning("UpdateValues", "dash list can have only up to %d elements",
sizeof(fValues.fDashes));
fValues.fDashLen = TMath::Min(values->fDashLen, (Int_t)sizeof(fValues.fDashes));
memcpy(fValues.fDashes, values->fDashes, fValues.fDashLen);
break;
case kGCArcMode:
fValues.fArcMode = values->fArcMode;
break;
}
}
}
//______________________________________________________________________________
void TGGC::SetAttributes(GCValues_t *values)
{
// Set attributes as specified in the values structure.
if (fContext)
gVirtualX->ChangeGC(fContext, values);
else
fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), values);
UpdateValues(values);
if (values->fMask & kGCDashList)
gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
fValues.fDashLen);
}
//______________________________________________________________________________
void TGGC::SetFunction(EGraphicsFunction v)
{
// Set graphics context drawing function.
GCValues_t values;
values.fFunction = v;
values.fMask = kGCFunction;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetPlaneMask(ULong_t v)
{
// Set plane mask.
GCValues_t values;
values.fPlaneMask = v;
values.fMask = kGCPlaneMask;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetForeground(ULong_t v)
{
// Set foreground color.
GCValues_t values;
values.fForeground = v;
values.fMask = kGCForeground;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetBackground(ULong_t v)
{
// Set background color.
GCValues_t values;
values.fBackground = v;
values.fMask = kGCBackground;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetLineWidth(Int_t v)
{
// Set line width.
GCValues_t values;
values.fLineWidth = v;
values.fMask = kGCLineWidth;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetLineStyle(Int_t v)
{
// Set line style (kLineSolid, kLineOnOffDash, kLineDoubleDash).
GCValues_t values;
values.fLineStyle = v;
values.fMask = kGCLineStyle;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetCapStyle(Int_t v)
{
// Set cap style (kCapNotLast, kCapButt, kCapRound, kCapProjecting).
GCValues_t values;
values.fCapStyle = v;
values.fMask = kGCCapStyle;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetJoinStyle(Int_t v)
{
// Set line join style (kJoinMiter, kJoinRound, kJoinBevel).
GCValues_t values;
values.fJoinStyle = v;
values.fMask = kGCJoinStyle;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetFillStyle(Int_t v)
{
// Set fill style (kFillSolid, kFillTiled, kFillStippled,
// kFillOpaeueStippled).
GCValues_t values;
values.fFillStyle = v;
values.fMask = kGCFillStyle;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetFillRule(Int_t v)
{
// Set fill rule (kEvenOddRule, kWindingRule).
GCValues_t values;
values.fFillRule = v;
values.fMask = kGCFillRule;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetTile(Pixmap_t v)
{
// Set tile pixmap for tiling operations.
GCValues_t values;
values.fTile = v;
values.fMask = kGCTile;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetStipple(Pixmap_t v)
{
// Set 1 plane pixmap for stippling.
GCValues_t values;
values.fStipple = v;
values.fMask = kGCStipple;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetTileStipXOrigin(Int_t v)
{
// X offset for tile or stipple operations.
GCValues_t values;
values.fTsXOrigin = v;
values.fMask = kGCTileStipXOrigin;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetTileStipYOrigin(Int_t v)
{
// Y offset for tile or stipple operations.
GCValues_t values;
values.fTsYOrigin = v;
values.fMask = kGCTileStipYOrigin;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetFont(FontH_t v)
{
// Set font.
GCValues_t values;
values.fFont = v;
values.fMask = kGCFont;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetSubwindowMode(Int_t v)
{
// Set sub window mode (kClipByChildren, kIncludeInferiors).
GCValues_t values;
values.fSubwindowMode = v;
values.fMask = kGCSubwindowMode;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetGraphicsExposures(Bool_t v)
{
// True if graphics exposure should be generated.
GCValues_t values;
values.fGraphicsExposures = v;
values.fMask = kGCGraphicsExposures;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetClipXOrigin(Int_t v)
{
// X origin for clipping.
GCValues_t values;
values.fClipXOrigin = v;
values.fMask = kGCClipXOrigin;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetClipYOrigin(Int_t v)
{
// Y origin for clipping.
GCValues_t values;
values.fClipYOrigin = v;
values.fMask = kGCClipYOrigin;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetClipMask(Pixmap_t v)
{
// Bitmap for clipping.
GCValues_t values;
values.fClipMask = v;
values.fMask = kGCClipMask;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetDashOffset(Int_t v)
{
// Patterned/dashed line offset.
GCValues_t values;
values.fDashOffset = v;
values.fMask = kGCDashOffset;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetDashList(const char v[], Int_t len)
{
// Set dash pattern. First use SetDashOffset() if not 0.
GCValues_t values;
if (len > (Int_t)sizeof(values.fDashes))
Warning("SetDashList", "dash list can have only up to %d elements",
sizeof(values.fDashes));
values.fDashLen = TMath::Min(len, (Int_t)sizeof(values.fDashes));
memcpy(values.fDashes, v, values.fDashLen);
values.fMask = kGCDashList;
SetAttributes(&values);
}
//______________________________________________________________________________
void TGGC::SetArcMode(Int_t v)
{
// Set arc mode (kArcChord, kArcPieSlice).
GCValues_t values;
values.fArcMode = v;
values.fMask = kGCArcMode;
SetAttributes(&values);
}
ClassImp(TGGCPool)
//______________________________________________________________________________
TGGCPool::TGGCPool(TGClient *client)
{
// Create graphics context pool.
fClient = client;
fList = new TList;
fList->SetOwner();
}
//______________________________________________________________________________
TGGCPool::~TGGCPool()
{
// Delete graphics context pool.
delete fList;
}
//______________________________________________________________________________
void TGGCPool::FreeGC(TGGC *gc)
{
// Delete graphics context if it not used anymore.
TGGCElement *el = (TGGCElement *) fList->FindObject(gc);
if (el) {
el->RemoveReference();
if (!el->References()) {
fList->Remove(gc);
delete el;
}
}
}
//______________________________________________________________________________
TGGC *TGGCPool::GetGC(GCValues_t *values)
{
// Get the best matching graphics context depending on values.
TGGCElement *el, *best_match = 0;
Int_t matching_bits, best_matching_bits = -1;
Bool_t exact = kFALSE;
// First, try to find an exact matching GC.
// If no one found, then use the closest one.
TIter next(fList);
while ((el = (TGGCElement *) next())) {
matching_bits = MatchGC(el->fContext, values);
if (matching_bits > best_matching_bits) {
best_matching_bits = matching_bits;
best_match = el;
if ((el->fContext->fValues.fMask & values->fMask) == values->fMask) {
exact = kTRUE;
break;
}
}
}
if (best_match) {
if (gDebug > 0)
Printf("<TGGCPool::GetGC>: %smatching GC foundn", exact ? "exact " : "");
best_match->AddReference();
if (!exact) {
// add missing values to the best_match'ing GC...
UpdateGC(best_match->fContext, values);
}
return best_match->fContext;
}
TGGC *gc = new TGGC(values);
el = new TGGCElement;
el->fContext = gc;
fList->Add(el);
return gc;
}
//______________________________________________________________________________
Int_t TGGCPool::MatchGC(TGGC *gc, GCValues_t *values)
{
// Try to find matching graphics context. On success returns the amount
// of matching bits (which may be zero if masks have no common bits),
// -1 on failure (when there are common bits but not a single match).
Mask_t bit, common_bits;
Int_t matching_bits = -1;
Bool_t match = kFALSE;
GCValues_t *gcv = &gc->fValues;
common_bits = values->fMask & gcv->fMask;
if (common_bits == 0) return 0; // no common bits, a possible
// candidate anyway.
for (bit = 1; bit <= common_bits; bit <<= 1) {
switch (bit & common_bits) {
default:
case 0:
continue;
case kGCFunction:
match = (values->fFunction == gcv->fFunction);
break;
case kGCPlaneMask:
match = (values->fPlaneMask == gcv->fPlaneMask);
break;
case kGCForeground:
match = (values->fForeground == gcv->fForeground);
break;
case kGCBackground:
match = (values->fBackground == gcv->fBackground);
break;
case kGCLineWidth:
match = (values->fLineWidth == gcv->fLineWidth);
break;
case kGCLineStyle:
match = (values->fLineStyle == gcv->fLineStyle);
break;
case kGCCapStyle:
match = (values->fCapStyle == gcv->fCapStyle);
break;
case kGCJoinStyle:
match = (values->fJoinStyle == gcv->fJoinStyle);
break;
case kGCFillStyle:
match = (values->fFillStyle == gcv->fFillStyle);
break;
case kGCFillRule:
match = (values->fFillRule == gcv->fFillRule);
break;
case kGCTile:
match = (values->fTile == gcv->fTile);
break;
case kGCStipple:
match = (values->fStipple == gcv->fStipple);
break;
case kGCTileStipXOrigin:
match = (values->fTsXOrigin == gcv->fTsXOrigin);
break;
case kGCTileStipYOrigin:
match = (values->fTsYOrigin == gcv->fTsYOrigin);
break;
case kGCFont:
match = (values->fFont == gcv->fFont);
break;
case kGCSubwindowMode:
match = (values->fSubwindowMode == gcv->fSubwindowMode);
break;
case kGCGraphicsExposures:
match = (values->fGraphicsExposures == gcv->fGraphicsExposures);
break;
case kGCClipXOrigin:
match = (values->fClipXOrigin == gcv->fClipXOrigin);
break;
case kGCClipYOrigin:
match = (values->fClipYOrigin == gcv->fClipYOrigin);
break;
case kGCClipMask:
match = (values->fClipMask == gcv->fClipMask);
break;
case kGCDashOffset:
match = (values->fDashOffset == gcv->fDashOffset);
break;
case kGCDashList:
if (values->fDashLen == gcv->fDashLen)
match = (strncmp(values->fDashes, gcv->fDashes, gcv->fDashLen) == 0);
break;
case kGCArcMode:
match = (values->fArcMode == gcv->fArcMode);
break;
}
if (!match)
return -1;
matching_bits++;
match = kFALSE;
}
return matching_bits;
}
//______________________________________________________________________________
void TGGCPool::UpdateGC(TGGC *gc, GCValues_t *values)
{
// Update graphics context with the values spcified in values->fMask.
gc->SetAttributes(values);
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.