00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "TGClient.h"
00022 #include "TGGC.h"
00023 #include "TVirtualX.h"
00024 #include "THashTable.h"
00025 #include "TColor.h"
00026 #include "TROOT.h"
00027 #include "Riostream.h"
00028 #include <string.h>
00029
00030
00031 ClassImp(TGGC)
00032
00033
00034 TGGC::TGGC(GCValues_t *values, Bool_t)
00035 {
00036
00037
00038 fContext = 0;
00039 if (values) {
00040 fValues = *values;
00041 fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), values);
00042 if (values->fMask & kGCDashList) {
00043 if (values->fDashLen > (Int_t)sizeof(fValues.fDashes))
00044 Warning("TGGC", "dash list can have only up to %ld elements",
00045 (Long_t)sizeof(fValues.fDashes));
00046 fValues.fDashLen = TMath::Min(values->fDashLen, (Int_t)sizeof(fValues.fDashes));
00047 gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
00048 fValues.fDashLen);
00049 }
00050 } else {
00051 memset(&fValues, 0, sizeof(GCValues_t));
00052 fContext = 0;
00053 }
00054 SetRefCount(1);
00055 }
00056
00057
00058 TGGC::TGGC(GCValues_t *values)
00059 {
00060
00061
00062 fContext = 0;
00063
00064 if (!values) {
00065 memset(&fValues, 0, sizeof(GCValues_t));
00066 fContext = 0;
00067 SetRefCount(1);
00068 return;
00069 }
00070
00071 if (gClient)
00072 gClient->GetGC(values, kTRUE);
00073 else {
00074 fContext = 0;
00075 Error("TGGC", "TGClient not yet initialized, should never happen");
00076 }
00077 }
00078
00079
00080 TGGC::TGGC(const TGGC &g) : TObject(g), TRefCnt()
00081 {
00082
00083
00084 fValues = g.fValues;
00085 if (g.fContext) {
00086 fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &fValues);
00087 if (fValues.fMask & kGCDashList)
00088 gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
00089 fValues.fDashLen);
00090 } else
00091 fContext = 0;
00092 SetRefCount(1);
00093
00094 if (gClient)
00095 gClient->GetGCPool()->fList->Add(this);
00096 }
00097
00098
00099 TGGC::~TGGC()
00100 {
00101
00102
00103 if (gClient)
00104 gClient->GetGCPool()->ForceFreeGC(this);
00105
00106 if (fContext)
00107 gVirtualX->DeleteGC(fContext);
00108 }
00109
00110
00111 TGGC &TGGC::operator=(const TGGC &rhs)
00112 {
00113
00114
00115 if (this != &rhs) {
00116 if (!fContext && gClient) {
00117 TGGC *gc = gClient->GetGCPool()->FindGC(this);
00118 if (!gc)
00119 gClient->GetGCPool()->fList->Add(this);
00120 }
00121 if (fContext)
00122 gVirtualX->DeleteGC(fContext);
00123 TObject::operator=(rhs);
00124 fValues = rhs.fValues;
00125 fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &fValues);
00126 if (fValues.fMask & kGCDashList)
00127 gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
00128 fValues.fDashLen);
00129 }
00130 return *this;
00131 }
00132
00133
00134 GContext_t TGGC::operator()() const
00135 {
00136
00137
00138 return fContext;
00139 }
00140
00141
00142 void TGGC::UpdateValues(GCValues_t *values)
00143 {
00144
00145
00146 fValues.fMask |= values->fMask;
00147
00148 for (Mask_t bit = 1; bit <= fValues.fMask; bit <<= 1) {
00149 switch (bit & values->fMask) {
00150 default:
00151 case 0:
00152 continue;
00153 case kGCFunction:
00154 fValues.fFunction = values->fFunction;
00155 break;
00156 case kGCPlaneMask:
00157 fValues.fPlaneMask = values->fPlaneMask;
00158 break;
00159 case kGCForeground:
00160 fValues.fForeground = values->fForeground;
00161 break;
00162 case kGCBackground:
00163 fValues.fBackground = values->fBackground;
00164 break;
00165 case kGCLineWidth:
00166 fValues.fLineWidth = values->fLineWidth;
00167 break;
00168 case kGCLineStyle:
00169 fValues.fLineStyle = values->fLineStyle;
00170 break;
00171 case kGCCapStyle:
00172 fValues.fCapStyle = values->fCapStyle;
00173 break;
00174 case kGCJoinStyle:
00175 fValues.fJoinStyle = values->fJoinStyle;
00176 break;
00177 case kGCFillStyle:
00178 fValues.fFillStyle = values->fFillStyle;
00179 break;
00180 case kGCFillRule:
00181 fValues.fFillRule = values->fFillRule;
00182 break;
00183 case kGCTile:
00184 fValues.fTile = values->fTile;
00185 break;
00186 case kGCStipple:
00187 fValues.fStipple = values->fStipple;
00188 break;
00189 case kGCTileStipXOrigin:
00190 fValues.fTsXOrigin = values->fTsXOrigin;
00191 break;
00192 case kGCTileStipYOrigin:
00193 fValues.fTsYOrigin = values->fTsYOrigin;
00194 break;
00195 case kGCFont:
00196 fValues.fFont = values->fFont;
00197 break;
00198 case kGCSubwindowMode:
00199 fValues.fSubwindowMode = values->fSubwindowMode;
00200 break;
00201 case kGCGraphicsExposures:
00202 fValues.fGraphicsExposures = values->fGraphicsExposures;
00203 break;
00204 case kGCClipXOrigin:
00205 fValues.fClipXOrigin = values->fClipXOrigin;
00206 break;
00207 case kGCClipYOrigin:
00208 fValues.fClipYOrigin = values->fClipYOrigin;
00209 break;
00210 case kGCClipMask:
00211 fValues.fClipMask = values->fClipMask;
00212 break;
00213 case kGCDashOffset:
00214 fValues.fDashOffset = values->fDashOffset;
00215 break;
00216 case kGCDashList:
00217 if (values->fDashLen > (Int_t)sizeof(fValues.fDashes))
00218 Warning("UpdateValues", "dash list can have only up to %ld elements",
00219 (Long_t)sizeof(fValues.fDashes));
00220 fValues.fDashLen = TMath::Min(values->fDashLen, (Int_t)sizeof(fValues.fDashes));
00221 memcpy(fValues.fDashes, values->fDashes, fValues.fDashLen);
00222 break;
00223 case kGCArcMode:
00224 fValues.fArcMode = values->fArcMode;
00225 break;
00226 }
00227 }
00228 }
00229
00230
00231 void TGGC::SetAttributes(GCValues_t *values)
00232 {
00233
00234
00235 if (!fContext && gClient) {
00236 TGGC *gc = gClient->GetGCPool()->FindGC(this);
00237 if (!gc)
00238 gClient->GetGCPool()->fList->Add(this);
00239 }
00240
00241 if (fContext)
00242 gVirtualX->ChangeGC(fContext, values);
00243 else
00244 fContext = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), values);
00245 UpdateValues(values);
00246 if (values->fMask & kGCDashList)
00247 gVirtualX->SetDashes(fContext, fValues.fDashOffset, fValues.fDashes,
00248 fValues.fDashLen);
00249 }
00250
00251
00252 void TGGC::SetFunction(EGraphicsFunction v)
00253 {
00254
00255
00256 GCValues_t values;
00257 values.fFunction = v;
00258 values.fMask = kGCFunction;
00259 SetAttributes(&values);
00260 }
00261
00262
00263 void TGGC::SetPlaneMask(ULong_t v)
00264 {
00265
00266
00267 GCValues_t values;
00268 values.fPlaneMask = v;
00269 values.fMask = kGCPlaneMask;
00270 SetAttributes(&values);
00271 }
00272
00273
00274 void TGGC::SetForeground(ULong_t v)
00275 {
00276
00277
00278 GCValues_t values;
00279 values.fForeground = v;
00280 values.fMask = kGCForeground;
00281 SetAttributes(&values);
00282 }
00283
00284
00285 void TGGC::SetBackground(ULong_t v)
00286 {
00287
00288
00289 GCValues_t values;
00290 values.fBackground = v;
00291 values.fMask = kGCBackground;
00292 SetAttributes(&values);
00293 }
00294
00295
00296 void TGGC::SetLineWidth(Int_t v)
00297 {
00298
00299
00300 GCValues_t values;
00301 values.fLineWidth = v;
00302 values.fMask = kGCLineWidth;
00303 SetAttributes(&values);
00304 }
00305
00306
00307 void TGGC::SetLineStyle(Int_t v)
00308 {
00309
00310
00311 GCValues_t values;
00312 values.fLineStyle = v;
00313 values.fMask = kGCLineStyle;
00314 SetAttributes(&values);
00315 }
00316
00317
00318 void TGGC::SetCapStyle(Int_t v)
00319 {
00320
00321
00322 GCValues_t values;
00323 values.fCapStyle = v;
00324 values.fMask = kGCCapStyle;
00325 SetAttributes(&values);
00326 }
00327
00328
00329 void TGGC::SetJoinStyle(Int_t v)
00330 {
00331
00332
00333 GCValues_t values;
00334 values.fJoinStyle = v;
00335 values.fMask = kGCJoinStyle;
00336 SetAttributes(&values);
00337 }
00338
00339
00340 void TGGC::SetFillStyle(Int_t v)
00341 {
00342
00343
00344
00345 GCValues_t values;
00346 values.fFillStyle = v;
00347 values.fMask = kGCFillStyle;
00348 SetAttributes(&values);
00349 }
00350
00351
00352 void TGGC::SetFillRule(Int_t v)
00353 {
00354
00355
00356 GCValues_t values;
00357 values.fFillRule = v;
00358 values.fMask = kGCFillRule;
00359 SetAttributes(&values);
00360 }
00361
00362
00363 void TGGC::SetTile(Pixmap_t v)
00364 {
00365
00366
00367 GCValues_t values;
00368 values.fTile = v;
00369 values.fMask = kGCTile;
00370 SetAttributes(&values);
00371 }
00372
00373
00374 void TGGC::SetStipple(Pixmap_t v)
00375 {
00376
00377
00378 GCValues_t values;
00379 values.fStipple = v;
00380 values.fMask = kGCStipple;
00381 SetAttributes(&values);
00382 }
00383
00384
00385 void TGGC::SetTileStipXOrigin(Int_t v)
00386 {
00387
00388
00389 GCValues_t values;
00390 values.fTsXOrigin = v;
00391 values.fMask = kGCTileStipXOrigin;
00392 SetAttributes(&values);
00393 }
00394
00395
00396 void TGGC::SetTileStipYOrigin(Int_t v)
00397 {
00398
00399
00400 GCValues_t values;
00401 values.fTsYOrigin = v;
00402 values.fMask = kGCTileStipYOrigin;
00403 SetAttributes(&values);
00404 }
00405
00406
00407 void TGGC::SetFont(FontH_t v)
00408 {
00409
00410
00411 GCValues_t values;
00412 values.fFont = v;
00413 values.fMask = kGCFont;
00414 SetAttributes(&values);
00415 }
00416
00417
00418 void TGGC::SetSubwindowMode(Int_t v)
00419 {
00420
00421
00422 GCValues_t values;
00423 values.fSubwindowMode = v;
00424 values.fMask = kGCSubwindowMode;
00425 SetAttributes(&values);
00426 }
00427
00428
00429 void TGGC::SetGraphicsExposures(Bool_t v)
00430 {
00431
00432
00433 GCValues_t values;
00434 values.fGraphicsExposures = v;
00435 values.fMask = kGCGraphicsExposures;
00436 SetAttributes(&values);
00437 }
00438
00439
00440 void TGGC::SetClipXOrigin(Int_t v)
00441 {
00442
00443
00444 GCValues_t values;
00445 values.fClipXOrigin = v;
00446 values.fMask = kGCClipXOrigin;
00447 SetAttributes(&values);
00448 }
00449
00450
00451 void TGGC::SetClipYOrigin(Int_t v)
00452 {
00453
00454
00455 GCValues_t values;
00456 values.fClipYOrigin = v;
00457 values.fMask = kGCClipYOrigin;
00458 SetAttributes(&values);
00459 }
00460
00461
00462 void TGGC::SetClipMask(Pixmap_t v)
00463 {
00464
00465
00466 GCValues_t values;
00467 values.fClipMask = v;
00468 values.fMask = kGCClipMask;
00469 SetAttributes(&values);
00470 }
00471
00472
00473 void TGGC::SetDashOffset(Int_t v)
00474 {
00475
00476
00477 GCValues_t values;
00478 values.fDashOffset = v;
00479 values.fMask = kGCDashOffset;
00480 SetAttributes(&values);
00481 }
00482
00483
00484 void TGGC::SetDashList(const char v[], Int_t len)
00485 {
00486
00487
00488 GCValues_t values;
00489 if (len > (Int_t)sizeof(values.fDashes))
00490 Warning("SetDashList", "dash list can have only up to %ld elements",
00491 (Long_t)sizeof(values.fDashes));
00492 values.fDashLen = TMath::Min(len, (Int_t)sizeof(values.fDashes));
00493 memcpy(values.fDashes, v, values.fDashLen);
00494 values.fMask = kGCDashList;
00495 SetAttributes(&values);
00496 }
00497
00498
00499 void TGGC::SetArcMode(Int_t v)
00500 {
00501
00502
00503 GCValues_t values;
00504 values.fArcMode = v;
00505 values.fMask = kGCArcMode;
00506 SetAttributes(&values);
00507 }
00508
00509
00510 void TGGC::Print(Option_t *) const
00511 {
00512
00513
00514 Printf("TGGC: mask = %x, handle = %lx, ref cnt = %u", fValues.fMask,
00515 fContext, References());
00516 }
00517
00518
00519 TString TGGC::GetMaskString() const
00520 {
00521
00522
00523 TString mask;
00524
00525 Mask_t fmask = GetMask();
00526
00527 if (fmask & kGCFunction) {
00528 if (mask.Length() == 0) mask = "kGCFunction";
00529 else mask += " | kGCFunction";
00530 }
00531 if (fmask & kGCPlaneMask) {
00532 if (mask.Length() == 0) mask = "kGCPlaneMask";
00533 else mask += " | kGCPlaneMask";
00534 }
00535 if (fmask & kGCForeground) {
00536 if (mask.Length() == 0) mask = "kGCForeground";
00537 else mask += " | kGCForeground";
00538 }
00539 if (fmask & kGCBackground) {
00540 if (mask.Length() == 0) mask = "kGCBackground";
00541 else mask += " | kGCBackground";
00542 }
00543 if (fmask & kGCLineWidth) {
00544 if (mask.Length() == 0) mask = "kGCLineWidth";
00545 else mask += " | kGCLineWidth";
00546 }
00547 if (fmask & kGCLineStyle) {
00548 if (mask.Length() == 0) mask = "kGCLineStyle";
00549 else mask += " | kGCLineStyle";
00550 }
00551 if (fmask & kGCCapStyle) {
00552 if (mask.Length() == 0) mask = "kGCCapStyle";
00553 else mask += " | kGCCapStyle";
00554 }
00555 if (fmask & kGCJoinStyle) {
00556 if (mask.Length() == 0) mask = "kGCJoinStyle";
00557 else mask += " | kGCJoinStyle";
00558 }
00559 if (fmask & kGCFillStyle) {
00560 if (mask.Length() == 0) mask = "kGCFillStyle";
00561 else mask += " | kGCFillStyle";
00562 }
00563 if (fmask & kGCFillRule) {
00564 if (mask.Length() == 0) mask = "kGCFillRule";
00565 else mask += " | kGCFillRule";
00566 }
00567 if (fmask & kGCTile) {
00568 if (mask.Length() == 0) mask = "kGCTile";
00569 else mask += " | kGCTile";
00570 }
00571 if (fmask & kGCStipple) {
00572 if (mask.Length() == 0) mask = "kGCStipple";
00573 else mask += " | kGCStipple";
00574 }
00575 if (fmask & kGCTileStipXOrigin) {
00576 if (mask.Length() == 0) mask = "kGCTileStipXOrigin";
00577 else mask += " | kGCTileStipXOrigin";
00578 }
00579 if (fmask & kGCTileStipYOrigin) {
00580 if (mask.Length() == 0) mask = "kGCTileStipYOrigin";
00581 else mask += " | kGCTileStipYOrigin";
00582 }
00583 if (fmask & kGCFont) {
00584 if (mask.Length() == 0) mask = "kGCFont";
00585 else mask += " | kGCFont";
00586 }
00587 if (fmask & kGCSubwindowMode) {
00588 if (mask.Length() == 0) mask = "kGCSubwindowMode";
00589 else mask += " | kGCSubwindowMode";
00590 }
00591 if (fmask & kGCGraphicsExposures) {
00592 if (mask.Length() == 0) mask = "kGCGraphicsExposures";
00593 else mask += " | kGCGraphicsExposures";
00594 }
00595 if (fmask & kGCClipXOrigin) {
00596 if (mask.Length() == 0) mask = "kGCClipXOrigin";
00597 else mask += " | kGCClipXOrigin";
00598 }
00599 if (fmask & kGCClipYOrigin) {
00600 if (mask.Length() == 0) mask = "kGCClipYOrigin";
00601 else mask += " | kGCClipYOrigin";
00602 }
00603 if (fmask & kGCClipMask) {
00604 if (mask.Length() == 0) mask = "kGCClipMask";
00605 else mask += " | kGCClipMask";
00606 }
00607 if (fmask & kGCDashOffset) {
00608 if (mask.Length() == 0) mask = "kGCDashOffset";
00609 else mask += " | kGCDashOffset";
00610 }
00611 if (fmask & kGCDashList) {
00612 if (mask.Length() == 0) mask = "kGCDashList";
00613 else mask += " | kGCDashList";
00614 }
00615 if (fmask & kGCArcMode) {
00616 if (mask.Length() == 0) mask = "kGCArcMode";
00617 else mask += " | kGCArcMode";
00618 }
00619 return mask;
00620 }
00621
00622
00623 void TGGC::SavePrimitive(ostream &out, Option_t *option )
00624 {
00625
00626
00627 if (gROOT->ClassSaved(TGGC::Class())) {
00628 out << endl;
00629 } else {
00630
00631 out << endl;
00632 out << " TGGC *uGC; // will reflect user GC changes" << endl;
00633 }
00634
00635 Mask_t fmask = GetMask();
00636
00637 const char *colorname;
00638 TString valname;
00639 char quote ='"';
00640 ULong_t color;
00641
00642 valname = TString::Format("val%s", option);
00643
00644 out << " // graphics context changes" << endl;
00645
00646 out << " GCValues_t " << valname.Data() << ";" << endl;
00647 out << " " << valname.Data() << ".fMask = " << GetMaskString() << ";" << endl;
00648
00649 for (Mask_t bit = 1; bit <= fmask; bit <<= 1) {
00650 switch (bit & fmask) {
00651 default:
00652 case 0:
00653 continue;
00654 case kGCFunction:
00655 out << " " << valname.Data() << ".fFunction = ";
00656 switch (GetFunction()) {
00657 case kGXclear:
00658 out << "kGXclear";
00659 break;
00660 case kGXand:
00661 out << "kGXand";
00662 break;
00663 case kGXandReverse:
00664 out << "kGXandReverse";
00665 break;
00666 case kGXcopy:
00667 out << "kGXcopy";
00668 break;
00669 case kGXandInverted:
00670 out << "kGXandInverted";
00671 break;
00672 case kGXnoop:
00673 out << "kGXnoop";
00674 break;
00675 case kGXxor:
00676 out << "kGXxor";
00677 break;
00678 case kGXor:
00679 out << "kGXor";
00680 break;
00681 case kGXnor:
00682 out << "kGXnor";
00683 break;
00684 case kGXequiv:
00685 out << "kGXequiv";
00686 break;
00687 case kGXinvert:
00688 out << "kGXinvert";
00689 break;
00690 case kGXorReverse:
00691 out << "kGXorReverse";
00692 break;
00693 case kGXcopyInverted:
00694 out << "kGXcopyInverted";
00695 break;
00696 case kGXorInverted:
00697 out << "kGXorInverted";
00698 break;
00699 case kGXnand:
00700 out << "kGXnand";
00701 break;
00702 case kGXset:
00703 out << "kGXset";
00704 break;
00705 }
00706 out << ";" << endl;
00707 break;
00708 case kGCPlaneMask:
00709 out << " " << valname.Data() << ".fPlaneMask = " << GetPlaneMask() << ";" << endl;
00710 break;
00711 case kGCForeground:
00712 color = GetForeground();
00713 colorname = TColor::PixelAsHexString(color);
00714 out << " gClient->GetColorByName(" << quote << colorname << quote
00715 << "," << valname.Data() << ".fForeground);" << endl;
00716 break;
00717 case kGCBackground:
00718 color = GetBackground();
00719 colorname = TColor::PixelAsHexString(color);
00720 out << " gClient->GetColorByName(" << quote << colorname << quote
00721 << "," << valname.Data() << ".fBackground);" << endl;
00722 break;
00723 case kGCLineWidth:
00724 out << " " << valname.Data() << ".fLineWidth = " << GetLineWidth() << ";" << endl;
00725 break;
00726 case kGCLineStyle:
00727 out << " " << valname.Data() << ".fLineStyle = ";
00728 switch (GetLineStyle()) {
00729 case kLineSolid:
00730 out << "kLineSolid";
00731 break;
00732 case kLineOnOffDash:
00733 out << "kLineOnOffDash";
00734 break;
00735 case kLineDoubleDash:
00736 out << "kLineDoubleDash";
00737 break;
00738 }
00739 out << ";" << endl;
00740 break;
00741 case kGCCapStyle:
00742 out << " " << valname.Data() << ".fCapStyle = ";
00743 switch (GetCapStyle()) {
00744 case kCapNotLast:
00745 out << "kCapNotLast";
00746 break;
00747 case kCapButt:
00748 out << "kCapButt";
00749 break;
00750 case kCapRound:
00751 out << "kCapRound";
00752 break;
00753 case kCapProjecting:
00754 out << "kCapProjecting";
00755 break;
00756 }
00757 out << ";" << endl;
00758 break;
00759 case kGCJoinStyle:
00760 out << " " << valname.Data() << ".fJoinStyle = ";
00761 switch (GetJoinStyle()) {
00762 case kJoinMiter:
00763 out << "kJoinMiter";
00764 break;
00765 case kJoinRound:
00766 out << "kJoinRound";
00767 break;
00768 case kJoinBevel:
00769 out << "kJoinBevel";
00770 break;
00771 }
00772 out << ";" << endl;
00773 break;
00774 case kGCFillStyle:
00775 out << " " << valname.Data() << ".fFillStyle = ";
00776 switch (GetFillStyle()) {
00777 case kFillSolid:
00778 out << "kFillSolid";
00779 break;
00780 case kFillTiled:
00781 out << "kFillTiled";
00782 break;
00783 case kFillStippled:
00784 out << "kFillStippled";
00785 break;
00786 case kFillOpaqueStippled:
00787 out << "kFillOpaqueStippled";
00788 break;
00789 }
00790 out << ";" << endl;
00791 break;
00792 case kGCFillRule:
00793 out << " " << valname.Data() << ".fFillRule = ";
00794 switch (GetFillRule()) {
00795 case kEvenOddRule:
00796 out << "kEvenOddRule";
00797 break;
00798 case kWindingRule:
00799 out << "kWindingRule";
00800 break;
00801 }
00802 out << ";" << endl;
00803 break;
00804 case kGCTile:
00805 out << " " << valname.Data() << ".fTile = " << GetTile() << ";" << endl;
00806 break;
00807 case kGCStipple:
00808 out << " " << valname.Data() << ".fStipple = " << GetStipple() << ";" << endl;
00809 break;
00810 case kGCTileStipXOrigin:
00811 out << " " << valname.Data() << ".fTsXOrigin = " << GetTileStipXOrigin() << ";" << endl;
00812 break;
00813 case kGCTileStipYOrigin:
00814 out << " " << valname.Data() << ".fTsYOrigin = " << GetTileStipYOrigin() << ";" << endl;
00815 break;
00816 case kGCFont:
00817 out << " " << valname.Data() << ".fFont = ufont->GetFontHandle();" << endl;
00818 break;
00819 case kGCSubwindowMode:
00820 out << " " << valname.Data() << ".fSubwindowMode = ";
00821 switch (GetSubwindowMode()) {
00822 case kClipByChildren:
00823 out << "kClipByChildren";
00824 break;
00825 case kIncludeInferiors:
00826 out << "kIncludeInferiors";
00827 break;
00828 }
00829 out << ";" << endl;
00830 break;
00831 case kGCGraphicsExposures:
00832 out << " " << valname.Data() << ".fGraphicsExposures = ";
00833 if (GetGraphicsExposures())
00834 out << "kTRUE";
00835 else
00836 out << "kFALSE";
00837 out << ";" << endl;
00838 break;
00839 case kGCClipXOrigin:
00840 out << " " << valname.Data() << ".fClipXOrigin = " << GetClipXOrigin() << ";" << endl;
00841 break;
00842 case kGCClipYOrigin:
00843 out << " " << valname.Data() << ".fClipYOrigin = " << GetClipYOrigin() << ";" << endl;
00844 break;
00845 case kGCClipMask:
00846 out << " " << valname.Data() << ".fClipMask = " << GetClipMask() << ";" << endl;
00847 break;
00848 case kGCDashOffset:
00849 out << " " << valname.Data() << ".fDashOffset = " << GetDashOffset() << ";" << endl;
00850 break;
00851 case kGCDashList:
00852 if (GetDashLen() > (Int_t)sizeof(GetDashes()))
00853 Warning("TGGC::SavePrimitive", "dash list can have only up to %ld elements",
00854 (Long_t)sizeof(GetDashes()));
00855 out << " " << valname.Data() << ".fDashLen = "
00856 << TMath::Min(GetDashLen(),(Int_t)sizeof(GetDashes())) << ";" << endl;
00857 out << " memcpy(GetDashes()," << valname.Data() << ".fDashes,"
00858 << valname.Data() << ".fDashLen);" << endl;
00859 break;
00860 case kGCArcMode:
00861 out << " " << valname.Data() << ".fArcMode = ";
00862 switch (GetArcMode()) {
00863 case kArcChord:
00864 out << "kArcChord";
00865 break;
00866 case kArcPieSlice:
00867 out << "kArcPieSlice";
00868 break;
00869 }
00870 out << ";" << endl;
00871 break;
00872 }
00873 }
00874 out << " uGC = gClient->GetGC(&" << valname.Data() << ", kTRUE);" << endl;
00875 }
00876
00877
00878 ClassImp(TGGCPool)
00879
00880
00881 TGGCPool::TGGCPool(TGClient *client)
00882 {
00883
00884
00885 fClient = client;
00886 fList = new THashTable;
00887 fList->SetOwner();
00888 }
00889
00890
00891 TGGCPool::~TGGCPool()
00892 {
00893
00894
00895 delete fList;
00896 }
00897
00898
00899 void TGGCPool::ForceFreeGC(const TGGC *gct)
00900 {
00901
00902
00903 TGGC *gc = (TGGC *) fList->FindObject(gct);
00904
00905 if (gc) {
00906 if (gc->References() > 1)
00907 Error("ForceFreeGC", "removed a shared graphics context\n"
00908 "best to use graphics contexts via the TGGCPool()");
00909 fList->Remove(gc);
00910 }
00911 }
00912
00913
00914 void TGGCPool::FreeGC(const TGGC *gct)
00915 {
00916
00917
00918 TGGC *gc = (TGGC *) fList->FindObject(gct);
00919
00920 if (gc) {
00921 if (gc->RemoveReference() == 0) {
00922 fList->Remove(gc);
00923 delete gc;
00924 }
00925 }
00926 }
00927
00928
00929 void TGGCPool::FreeGC(GContext_t gct)
00930 {
00931
00932
00933 TIter next(fList);
00934
00935 while (TGGC *gc = (TGGC *) next()) {
00936 if (gc->fContext == gct) {
00937 if (gc->RemoveReference() == 0) {
00938 fList->Remove(gc);
00939 delete gc;
00940 return;
00941 }
00942 }
00943 }
00944 }
00945
00946
00947 TGGC *TGGCPool::FindGC(const TGGC *gct)
00948 {
00949
00950
00951 return (TGGC*) fList->FindObject(gct);
00952 }
00953
00954
00955 TGGC *TGGCPool::FindGC(GContext_t gct)
00956 {
00957
00958
00959
00960 TIter next(fList);
00961
00962 while (TGGC *gc = (TGGC *) next()) {
00963 if (gc->fContext == gct)
00964 return gc;
00965 }
00966 return 0;
00967 }
00968
00969
00970 TGGC *TGGCPool::GetGC(GContext_t gct)
00971 {
00972
00973
00974 GCValues_t gval;
00975 gVirtualX->GetGCValues(gct, gval);
00976 return GetGC(&gval, kTRUE);
00977 }
00978
00979
00980 TGGC *TGGCPool::GetGC(GCValues_t *values, Bool_t rw)
00981 {
00982
00983
00984
00985
00986
00987 TGGC *gc, *best_match = 0;
00988 Int_t matching_bits, best_matching_bits = -1;
00989 Bool_t exact = kFALSE;
00990
00991 if (!values)
00992 rw = kTRUE;
00993
00994 if (!rw) {
00995
00996
00997
00998
00999 TIter next(fList);
01000
01001 while ((gc = (TGGC *) next())) {
01002 matching_bits = MatchGC(gc, values);
01003 if (matching_bits > best_matching_bits) {
01004 best_matching_bits = matching_bits;
01005 best_match = gc;
01006 if ((gc->fValues.fMask & values->fMask) == values->fMask) {
01007 exact = kTRUE;
01008 break;
01009 }
01010 }
01011 }
01012
01013 if (best_match) {
01014 if (gDebug > 0)
01015 Printf("<TGGCPool::GetGC>: %smatching GC found\n", exact ? "exact " : "");
01016 best_match->AddReference();
01017 if (!exact) {
01018
01019 UpdateGC(best_match, values);
01020 }
01021 return best_match;
01022 }
01023 }
01024
01025 gc = new TGGC(values, kTRUE);
01026
01027 fList->Add(gc);
01028
01029 return gc;
01030 }
01031
01032
01033 Int_t TGGCPool::MatchGC(const TGGC *gc, GCValues_t *values)
01034 {
01035
01036
01037
01038
01039 Mask_t bit, common_bits;
01040 Int_t matching_bits = -1;
01041 Bool_t match = kFALSE;
01042 const GCValues_t *gcv = &gc->fValues;
01043
01044 common_bits = values->fMask & gcv->fMask;
01045
01046 if (common_bits == 0) return 0;
01047
01048
01049
01050
01051
01052
01053
01054 if (gcv->fMask & kGCTile)
01055 if ((gcv->fTile != kNone) && !(values->fMask & kGCTile)) return -1;
01056 if (values->fMask & kGCTile)
01057 if ((values->fTile != kNone) && !(gcv->fMask & kGCTile)) return -1;
01058 if (gcv->fMask & kGCStipple)
01059 if ((gcv->fStipple != kNone) && !(values->fMask & kGCStipple)) return -1;
01060 if (values->fMask & kGCStipple)
01061 if ((values->fStipple != kNone) && !(gcv->fMask & kGCStipple)) return -1;
01062
01063 for (bit = 1; bit <= common_bits; bit <<= 1) {
01064 switch (bit & common_bits) {
01065 default:
01066 case 0:
01067 continue;
01068 case kGCFunction:
01069 match = (values->fFunction == gcv->fFunction);
01070 break;
01071 case kGCPlaneMask:
01072 match = (values->fPlaneMask == gcv->fPlaneMask);
01073 break;
01074 case kGCForeground:
01075 match = (values->fForeground == gcv->fForeground);
01076 break;
01077 case kGCBackground:
01078 match = (values->fBackground == gcv->fBackground);
01079 break;
01080 case kGCLineWidth:
01081 match = (values->fLineWidth == gcv->fLineWidth);
01082 break;
01083 case kGCLineStyle:
01084 match = (values->fLineStyle == gcv->fLineStyle);
01085 break;
01086 case kGCCapStyle:
01087 match = (values->fCapStyle == gcv->fCapStyle);
01088 break;
01089 case kGCJoinStyle:
01090 match = (values->fJoinStyle == gcv->fJoinStyle);
01091 break;
01092 case kGCFillStyle:
01093 match = (values->fFillStyle == gcv->fFillStyle);
01094 break;
01095 case kGCFillRule:
01096 match = (values->fFillRule == gcv->fFillRule);
01097 break;
01098 case kGCTile:
01099 match = (values->fTile == gcv->fTile);
01100 break;
01101 case kGCStipple:
01102 match = (values->fStipple == gcv->fStipple);
01103 break;
01104 case kGCTileStipXOrigin:
01105 match = (values->fTsXOrigin == gcv->fTsXOrigin);
01106 break;
01107 case kGCTileStipYOrigin:
01108 match = (values->fTsYOrigin == gcv->fTsYOrigin);
01109 break;
01110 case kGCFont:
01111 match = (values->fFont == gcv->fFont);
01112 break;
01113 case kGCSubwindowMode:
01114 match = (values->fSubwindowMode == gcv->fSubwindowMode);
01115 break;
01116 case kGCGraphicsExposures:
01117 match = (values->fGraphicsExposures == gcv->fGraphicsExposures);
01118 break;
01119 case kGCClipXOrigin:
01120 match = (values->fClipXOrigin == gcv->fClipXOrigin);
01121 break;
01122 case kGCClipYOrigin:
01123 match = (values->fClipYOrigin == gcv->fClipYOrigin);
01124 break;
01125 case kGCClipMask:
01126 match = (values->fClipMask == gcv->fClipMask);
01127 break;
01128 case kGCDashOffset:
01129 match = (values->fDashOffset == gcv->fDashOffset);
01130 break;
01131 case kGCDashList:
01132 if (values->fDashLen == gcv->fDashLen)
01133 match = (strncmp(values->fDashes, gcv->fDashes, gcv->fDashLen) == 0);
01134 break;
01135 case kGCArcMode:
01136 match = (values->fArcMode == gcv->fArcMode);
01137 break;
01138 }
01139 if (!match)
01140 return -1;
01141 matching_bits++;
01142 match = kFALSE;
01143 }
01144
01145 return matching_bits;
01146 }
01147
01148
01149 void TGGCPool::UpdateGC(TGGC *gc, GCValues_t *values)
01150 {
01151
01152
01153 gc->SetAttributes(values);
01154 }
01155
01156
01157 void TGGCPool::Print(Option_t *) const
01158 {
01159
01160
01161 fList->Print();
01162 }