ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/Utils/src/TDocDirective.cxx
Revision: 1.1
Committed: Tue Aug 11 23:09:28 2009 UTC (15 years, 8 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_029b, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012h, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, HEAD
Branch point for: Mit_025c_branch
Error occurred while calculating annotation data.
Log Message:
Added THtml from ROOT

File Contents

# Content
1 #include "MitAna/Utils/interface/TDocDirective.h"
2
3 #include "TApplication.h"
4 #include "TClass.h"
5 #include "MitAna/Utils/interface/TDocInfo.h"
6 #include "MitAna/Utils/interface/TDocOutput.h"
7 #include "MitAna/Utils/interface/TDocParser.h"
8 #include "MitAna/Utils/interface/THtml.h"
9 #include "TInterpreter.h"
10 #include "TLatex.h"
11 #include "TMacro.h"
12 #include "TObjString.h"
13 #include "TPRegexp.h"
14 #include "TROOT.h"
15 #include "TStyle.h"
16 #include "TSystem.h"
17 #include "TVirtualPad.h"
18 #include "TVirtualMutex.h"
19 #include <fstream>
20 #include <sstream>
21 #include <stdlib.h>
22
23 //______________________________________________________________________________
24 //
25 // When THtml parses documentation (through TDocParser), it checks for special
26 // words ("begin_something", "end_something", where the begin and end are the
27 // significant part). THtml then searches for a TDocDirective which can handle
28 // these tags ("whatever" in the example), passes the text enclosed by these
29 // tags to the directive, which in turn processes it.
30 //
31 // That way, HTML, latex, and C++ macros can be processed by THtml, e.g. to
32 // generate plain HTML or GIF pictures. The classes reposinsible for parsing
33 // that are TDocHtmlDirective, TDocLatexDirective, and TDocMacroDirective,
34 // respecively.
35 //
36 // Directives can have optional parameters; these are passed as paranthesis
37 // enclosed, comma delimited name=value pairs; see SetParameters().
38 //
39 // You can implement your own directive simply by deriving from TDocDirective;
40 // the tag corresponds to TDocDirective's name (e.g. "HTML" for "begin_html" /
41 // "end_html").
42 //______________________________________________________________________________
43
44 ClassImp(TDocDirective)
45
46 //______________________________________________________________________________
47 void TDocDirective::DeleteOutputFiles(const char* ext) const
48 {
49 // Delete all output generated by the directive beginning
50 // with Name() and ending with ext
51 TString basename;
52 GetName(basename);
53 basename += "_";
54 TString dirname(GetOutputDir());
55 void* hDir = gSystem->OpenDirectory(dirname);
56 const char* entry = 0;
57 while ((entry = gSystem->GetDirEntry(hDir))) {
58 TString sEntry(entry);
59 if (sEntry.BeginsWith(basename) && isdigit(sEntry[basename.Length()]) && (!ext || sEntry.EndsWith(ext)))
60 gSystem->Unlink((dirname + "/" + entry).Data());
61 }
62 gSystem->FreeDirectory(hDir);
63 }
64
65 //______________________________________________________________________________
66 void TDocDirective::GetName(TString& name) const
67 {
68 // Get the full name, based on fName, fTitle, fDocParser's tag.
69
70 name = fName;
71 if (fDocParser && fDocParser->GetCurrentClass()) {
72 name += "_";
73 TString outfilename;
74 GetHtml()->GetHtmlFileName(fDocParser->GetCurrentClass(), outfilename);
75 outfilename = gSystem->BaseName(outfilename);
76 Ssiz_t posExt = outfilename.Last('.');
77 outfilename.Remove(posExt, outfilename.Length() - posExt);
78 name += outfilename;
79 }
80 if (GetTitle() && strlen(GetTitle())) {
81 name += "_";
82 name += GetTitle();
83 }
84 if (fCounter != -1) {
85 name += "_";
86 name += fCounter;
87 }
88 }
89
90 //______________________________________________________________________________
91 const char* TDocDirective::GetOutputDir() const
92 {
93 // Get the directory for documentation output.
94
95 return fHtml ? fHtml->GetOutputDir().Data() : 0;
96 }
97
98 //______________________________________________________________________________
99 void TDocDirective::SetParameters(const char* params)
100 {
101 // Given a string containing parameters in params,
102 // we call AddParameter() for each of them.
103 // This function splits the parameter names and
104 // extracts their values if they are given.
105 // Parameters are separated by ",", values are
106 // separated from parameter names by "=".
107 // params being
108 // a = "a, b, c", b='d,e'
109 // will issue two calls to AddParameter(), one for
110 // a with value "a, b, c" and one for b with value
111 // "d,e" (each without the quotation marks).
112
113 fParameters = params;
114
115 if (!fParameters.Length())
116 return;
117
118 TString param;
119 Ssiz_t pos = 0;
120 while (fParameters.Tokenize(param, pos, ",")) {
121 param = param.Strip(TString::kBoth);
122 if (!param.Length())
123 continue;
124
125 Ssiz_t posAssign = param.Index('=');
126 if (posAssign != kNPOS) {
127 TString value(param(posAssign + 1, param.Length()));
128 value = value.Strip(TString::kBoth);
129 if (value[0] == '\'')
130 value = value.Strip(TString::kBoth, '\'');
131 else if (value[0] == '"')
132 value = value.Strip(TString::kBoth, '"');
133 param.Remove(posAssign, param.Length());
134 param = param.Strip(TString::kBoth);
135 AddParameter(param, value);
136 } else {
137 param = param.Strip(TString::kBoth);
138 AddParameter(param, 0);
139 }
140 }
141 }
142
143 //______________________________________________________________________________
144 void TDocDirective::SetParser(TDocParser* parser)
145 {
146 // Set the parser, and fDocOutput, fHtml from that
147 fDocParser = parser;
148 fDocOutput = parser ? parser->GetDocOutput() : 0;
149 fHtml = fDocOutput? fDocOutput->GetHtml() : 0;
150 }
151
152
153 //______________________________________________________________________________
154 //
155 // Process a "begin_html" / "end_html" block. Stop linking keywords and simply
156 // copy the text enclosed by the directive to the output HTML file.
157 //______________________________________________________________________________
158
159 ClassImp(TDocHtmlDirective)
160
161 //______________________________________________________________________________
162 void TDocHtmlDirective::AddLine(const TSubString& line)
163 {
164 // Add a line of HTML
165
166 if (line.Start() == -1) return;
167
168 TPRegexp pretag("</?[pP][rR][eE][ >]");
169 TSubString iLine(line);
170 Ssiz_t posPre = iLine.String().Index(pretag, iLine.Start());
171 if (posPre == kNPOS)
172 fText += line;
173 else {
174 // remove <pre> in fVerbatim environments, and
175 // </pre> in !fVerbatim environments.
176 while (posPre != kNPOS && posPre > 0) {
177 Bool_t isOpen = line[posPre + 1 - line.Start()] != '/';
178 Ssiz_t posClose = iLine.String().Index(">", posPre);
179 if (posClose ==kNPOS) break; // aka oops.
180 Ssiz_t len = posClose - posPre;
181
182 if (fVerbatim) {
183 if (isOpen) {
184 // skip
185 fText += iLine.String()(iLine.Start(), posPre - iLine.Start());
186 } else {
187 // write it out
188 fText += iLine.String()(iLine.Start(), posPre + len - iLine.Start());
189 fVerbatim = kFALSE;
190 }
191 } else {
192 if (!isOpen) {
193 // skip
194 fText += iLine.String()(iLine.Start(), posPre - iLine.Start());
195 } else {
196 // write it out
197 fText += iLine.String()(iLine.Start(), posPre + len - iLine.Start());
198 fVerbatim = kTRUE;
199 }
200 }
201
202 iLine = iLine.String()(posPre + len, iLine.Length());
203 posPre = iLine.String().Index(pretag, iLine.Start());
204 }
205
206 fText += iLine;
207 }
208 fText += "\n";
209 }
210
211 //______________________________________________________________________________
212 Bool_t TDocHtmlDirective::GetResult(TString& result)
213 {
214 // Set result to the HTML code that was passed in via AddLine().
215 // Prepend a closing </pre>, append an opening <pre>
216
217 result = "</pre><!-- TDocHtmlDirective start -->";
218 result += fText + "<!-- TDocHtmlDirective end --><pre>";
219 return kTRUE;
220 }
221
222
223
224 //______________________________________________________________________________
225 //
226 // Process a "begin_macro" / "end_macro" block. The block can be a file name
227 // or a CINT script (i.e. even ".x file.C" is allowed). See AddParameter() for
228 // supported options. Example (the quotes prevent THtml from expanding the
229 // example):
230 //
231 // "BEGIN_MACRO"
232 // .x $ROOTSYS/tutorials/hsimple.C
233 // "END_MACRO"
234 //
235 // The macro is meant to create an object that can be saved as a GIF file by
236 // calling object->SaveAs(outputfile.gif). The macro is expected to return that
237 // object as a TObject*; if it does not, gPad is used and saved. The object
238 // is deleted by TDocMacroDirective once saved.
239 //______________________________________________________________________________
240
241 ClassImp(TDocMacroDirective)
242
243 //______________________________________________________________________________
244 TDocMacroDirective::~TDocMacroDirective()
245 {
246 // Destructor
247 delete fMacro;
248 }
249
250 //______________________________________________________________________________
251 void TDocMacroDirective::AddLine(const TSubString& line)
252 {
253 // Add a macro line.
254 // Lines ending on "*HIDE*" will be executed as part of the
255 // macro, but not shown in the source tab if the parameter
256 // source is supplied.
257
258 if (!fMacro) {
259 TString name;
260 GetName(name);
261 fMacro = new TMacro(name);
262 }
263
264 // return if no line - or if there was an intentinal line-break,
265 // i.e. an empty line
266 if (line.Start() == -1 && const_cast<TSubString&>(line).String().Length()) return;
267
268 TString sLine(line);
269 fMacro->AddLine(sLine);
270 fIsFilename &= !sLine.Contains('{');
271 }
272 //______________________________________________________________________________
273 Bool_t TDocMacroDirective::GetResult(TString& result)
274 {
275 // Get the result (i.e. an HTML img tag) for the macro invocation.
276 // If fShowSource is set, a second tab will be created which shows
277 // the source.
278
279 if (!fMacro)
280 return kFALSE;
281
282 if (!fMacro->GetListOfLines()
283 || !fMacro->GetListOfLines()->First()) {
284 Warning("GetResult", "Empty directive found!");
285 return kTRUE;
286 }
287
288 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
289
290 if (gDebug > 3)
291 Info("HandleDirective_Macro", "executing macro \"%s\" with %d lines.",
292 fMacro->GetName(), fMacro->GetListOfLines() ? fMacro->GetListOfLines()->GetEntries() + 1 : 0);
293
294 Bool_t wasBatch = gROOT->IsBatch();
295 if (!wasBatch && !fNeedGraphics)
296 gROOT->SetBatch();
297 else if (fNeedGraphics) {
298 if (fHtml->IsBatch()) {
299 Warning("GetResult()", "Will not initialize the graphics system; skipping macro %s!", GetName());
300 result = "";
301 return kFALSE;
302 }
303 gROOT->SetBatch(0);
304 TApplication::NeedGraphicsLibs();
305 gApplication->InitializeGraphics();
306 if (gROOT->IsBatch()) {
307 Warning("GetResult()", "Cannot initialize the graphics system; skipping macro %s!", GetName());
308 result = "";
309 return kFALSE;
310 }
311 }
312
313 TVirtualPad* padSave = gPad;
314
315 Int_t error = TInterpreter::kNoError;
316 Long_t ret = 0;
317 if (fIsFilename) {
318 TString filename;
319 TIter iLine(fMacro->GetListOfLines());
320 while (filename.Length() == 0)
321 filename = ((TObjString*)iLine())->String().Strip(TString::kBoth);
322
323 TString macroPath;
324 TString modulename;
325 if (GetHtml() && GetDocParser()) {
326 if (GetDocParser()->GetCurrentClass())
327 GetHtml()->GetModuleNameForClass(modulename, GetDocParser()->GetCurrentClass());
328 else GetDocParser()->GetCurrentModule(modulename);
329 }
330 if (modulename.Length()) {
331 GetHtml()->GetModuleMacroPath(modulename, macroPath);
332 } else macroPath = gSystem->pwd();
333
334 const char* pathDelimiter = ":"; // use ":" even on windows
335 TObjArray* arrDirs(macroPath.Tokenize(pathDelimiter));
336 TIter iDir(arrDirs);
337 TObjString* osDir = 0;
338 macroPath = "";
339 TString filenameDirPart(gSystem->DirName(filename));
340 filenameDirPart.Prepend('/'); // as dir delimiter, not as root dir
341 while ((osDir = (TObjString*)iDir())) {
342 if (osDir->String().EndsWith("\\"))
343 osDir->String().Remove(osDir->String().Length() - 1);
344 osDir->String() += filenameDirPart;
345 macroPath += osDir->String() + pathDelimiter;
346 }
347
348 TString plusplus;
349 while (filename.EndsWith("+")) {
350 plusplus += '+';
351 filename.Remove(filename.Length() - 1);
352 }
353
354 TString params;
355 if (filename.EndsWith(")")) {
356 Ssiz_t posOpen = filename.Last('(');
357 if (posOpen != kNPOS) {
358 params = filename(posOpen, filename.Length());
359 filename.Remove(posOpen, filename.Length());
360 }
361 }
362
363 TString fileSysName(gSystem->BaseName(filename));
364 if (!gSystem->FindFile(macroPath, fileSysName)) {
365 Error("GetResult", "Cannot find macro '%s' in path '%s'!",
366 gSystem->BaseName(filename), macroPath.Data());
367 result = "";
368 return kFALSE;
369 }
370
371 if (fShowSource) {
372 // copy macro into fMacro - before running it, in case the macro blocks its file
373 std::ifstream ifMacro(fileSysName);
374 fMacro->GetListOfLines()->Delete();
375 TString line;
376 while (ifMacro) {
377 if (!line.ReadLine(ifMacro, kFALSE) || ifMacro.eof())
378 break;
379 fMacro->AddLine(line);
380 }
381 }
382
383 fileSysName.Prepend(".x ");
384 fileSysName += params;
385 fileSysName += plusplus;
386 gInterpreter->SaveContext();
387 gInterpreter->SaveGlobalsContext();
388 ret = gROOT->ProcessLine(fileSysName, &error);
389 } else {
390 gInterpreter->SaveContext();
391 gInterpreter->SaveGlobalsContext();
392 ret = fMacro->Exec(0, &error);
393 }
394
395 if (fShowSource) {
396 // convert the macro source
397 TIter iLine(fMacro->GetListOfLines());
398 TObjString* osLine = 0;
399 std::stringstream ssRaw;
400 while ((osLine = (TObjString*)iLine()))
401 ssRaw << osLine->String() << std::endl;
402
403 TDocParser *dparser = 0;
404 if (GetDocParser()->GetCurrentClass())
405 dparser = new TDocParser(*(TClassDocOutput*)GetDocOutput(), GetDocParser()->GetCurrentClass());
406 else dparser = new TDocParser(*GetDocOutput());
407 std::stringstream ssConverted;
408 dparser->Convert(ssConverted, ssRaw, "./", kFALSE /*no code*/);
409 delete dparser;
410
411 fMacro->GetListOfLines()->Delete();
412 TString line;
413 while (!ssConverted.fail()) {
414 if (!line.ReadLine(ssConverted, kFALSE) || ssConverted.eof())
415 break;
416 fMacro->AddLine(line);
417 }
418 }
419
420 Int_t sleepCycles = 50; // 50 = 5 seconds
421 while (error == TInterpreter::kProcessing && --sleepCycles > 0)
422 gSystem->Sleep(100);
423
424 gSystem->ProcessEvents(); // in case ret needs to handle some events first
425
426 if (error != TInterpreter::kNoError)
427 Error("HandleDirective_Macro", "Error processing macro %s!", fMacro->GetName());
428 else if (ret) {
429 const TObject* objRet = (const TObject*)ret;
430 try {
431 typeid(*objRet).name(); // needed to test whether ret is indeed an object with a vtable!
432 objRet = dynamic_cast<const TObject*>(objRet);
433 }
434 catch (...) {
435 objRet = 0;
436 }
437 if (objRet) {
438 TString filename;
439 GetName(filename);
440
441 if (objRet->GetName() && strlen(objRet->GetName())) {
442 filename += "_";
443 filename += objRet->GetName();
444 }
445 filename.ReplaceAll(" ", "_");
446
447 result = "<span class=\"macro\"><img class=\"macro\" alt=\"output of ";
448 result += filename;
449
450 GetDocOutput()->NameSpace2FileName(filename);
451 TString id(filename);
452 filename += ".gif";
453 TString basename(filename);
454
455 result += "\" title=\"MACRO\" src=\"";
456 result += basename;
457 result += "\" /></span>";
458
459 gSystem->PrependPathName(GetOutputDir(), filename);
460
461 if (gDebug > 3)
462 Info("HandleDirective_Macro", "Saving returned %s to file %s.",
463 objRet->IsA()->GetName(), filename.Data());
464
465 if (fNeedGraphics) {
466 // to get X11 to sync :-( gVirtualX->Update()/Sync() don't do it
467 gSystem->Sleep(1000);
468 gVirtualX->Update(0);
469 gVirtualX->Update(1);
470 }
471
472 gSystem->ProcessEvents();
473 if (fNeedGraphics) {
474 gVirtualX->Update(0);
475 gVirtualX->Update(1);
476 }
477
478 objRet->SaveAs(filename);
479 gSystem->ProcessEvents(); // SaveAs triggers an event
480
481 // ensure objRet is not e.g. the TGMainFrame of a new TCanvas: require padSave == gPad
482 if (objRet != gPad && padSave == gPad)
483 delete objRet;
484
485 if (fShowSource) {
486 // TODO: we need an accessible version of the source, i.e. visible w/o javascript
487 TString tags("</pre><div class=\"tabs\">\n"
488 "<a id=\"" + id + "_A0\" class=\"tabsel\" href=\"" + basename + "\" onclick=\"javascript:return SetDiv('" + id + "',0);\">Picture</a>\n"
489 "<a id=\"" + id + "_A1\" class=\"tab\" href=\"#\" onclick=\"javascript:return SetDiv('" + id + "',1);\">Source</a>\n"
490 "<br /></div><div class=\"tabcontent\">\n"
491 "<div id=\"" + id + "_0\" class=\"tabvisible\">" + result + "</div>\n"
492 "<div id=\"" + id + "_1\" class=\"tabhidden\"><div class=\"code\"><pre class=\"code\">");
493 TIter iLine(fMacro->GetListOfLines());
494 TObjString* osLine = 0;
495 while ((osLine = (TObjString*) iLine()))
496 if (!TString(osLine->String().Strip()).EndsWith("*HIDE*"))
497 tags += osLine->String() + "\n";
498 if (tags.EndsWith("\n"))
499 tags.Remove(tags.Length()-1); // trailing line break
500 tags += "</pre></div></div><div class=\"clear\"></div></div><pre>";
501 result = tags;
502 }
503 }
504 }
505
506 // Remove interpreter vars first, so we can check whether we need to delete
507 // gPad ourselves or whether it was a global var in the interpreter.
508 gInterpreter->ResetGlobals();
509 gInterpreter->Reset();
510
511 if (!wasBatch)
512 gROOT->SetBatch(kFALSE);
513 if (padSave != gPad) {
514 delete gPad;
515 gPad = padSave;
516 }
517
518 // in case ret's or gPad's deletion provoke events that should be handled
519 gSystem->ProcessEvents();
520
521 return kTRUE;
522 }
523
524 //______________________________________________________________________________
525 void TDocMacroDirective::AddParameter(const TString& name, const char* /*value=0*/)
526 {
527 // Setting fNeedGraphics if name is "GUI",
528 // setting fShowSource if name is "SOURCE"
529
530 if (!name.CompareTo("gui", TString::kIgnoreCase))
531 fNeedGraphics = kTRUE;
532 else if (!name.CompareTo("source", TString::kIgnoreCase))
533 fShowSource = kTRUE;
534 else Warning("AddParameter", "Unknown option %s!", name.Data());
535 }
536
537
538
539 namespace {
540 Float_t gLinePadding = 10.; //px
541 Float_t gColumnPadding = 10.; //px
542
543 class TLatexLine {
544 private:
545 std::vector<Float_t> fWidths;
546 Float_t fHeight;
547 TObjArray* fColumns; // of TObjString*
548
549 public:
550 TLatexLine(TObjArray* columns = 0):
551 fHeight(0.), fColumns(columns) { if (columns) fWidths.resize(Size());}
552
553 Float_t& Width(UInt_t col) {return fWidths[col];}
554 Float_t& Height() {return fHeight;}
555 TString* operator[](Int_t column) {
556 if (fColumns && fColumns->GetEntriesFast() > column)
557 return &(((TObjString*)fColumns->At(column))->String());
558 return 0;
559 }
560 UInt_t Size() const { return fColumns ? fColumns->GetEntries() : 0; }
561 void Delete() { delete fColumns; }
562 };
563 }
564
565 //______________________________________________________________________________
566 //
567 // Handle a "Begin_Latex"/"End_Latex" directive.
568 // called as
569 // "Begin_Latex(fontsize=10, separator='=,', rseparator='=|,', align=lcl)"
570 // will create and include a TLatex-processed image, with a given fontsize
571 // in pixels (defaults to 16). If (r)separator is given, the formulas on the
572 // following lines will be grouped into columns; a new column starts with
573 // (regexp) match of the separator; by default there is only one column.
574 // separator matches any character, rseparator matches as regexp with one
575 // column per pattern match. Only one of separator or rseparator can be given.
576 // align defines the alignment for each columns; be default, all columns
577 // are right aligned. NOTE that the column separator counts as a column itself!
578 //______________________________________________________________________________
579
580
581 ClassImp(TDocLatexDirective)
582
583 //______________________________________________________________________________
584 TDocLatexDirective::~TDocLatexDirective()
585 {
586 // Destructor
587 gSystem->ProcessEvents();
588 delete fLatex;
589 delete fBBCanvas;
590 gSystem->ProcessEvents();
591 }
592
593 //______________________________________________________________________________
594 void TDocLatexDirective::AddLine(const TSubString& line)
595 {
596 // Add a latex line
597
598 if (line.Length() == 0)
599 return;
600
601 if (!fLatex) {
602 TString name;
603 GetName(name);
604 fLatex = new TMacro(name);
605 }
606
607 TString sLine(line);
608 GetDocParser()->Strip(sLine);
609 if (sLine.Length() == 0)
610 return;
611
612 fLatex->AddLine(sLine);
613 }
614
615 //______________________________________________________________________________
616 void TDocLatexDirective::CreateLatex(const char* filename)
617 {
618 // Create a gif file named filename from a latex expression in fLatex.
619 // Called when "Begin_Latex"/"End_Latex" is processed.
620
621 if (!fLatex
622 || !fLatex->GetListOfLines()
623 || !fLatex->GetListOfLines()->First())
624 return;
625
626 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
627
628 TVirtualPad* oldPad = gPad;
629
630 Bool_t wasBatch = gROOT->IsBatch();
631 if (!wasBatch)
632 gROOT->SetBatch();
633
634 const Float_t canvSize = 1200.;
635 if (!fBBCanvas)
636 // add magic batch vs. gui canvas sizes (4, 28)
637 fBBCanvas = (TVirtualPad*)gROOT->ProcessLineFast(
638 Form("new TCanvas(\"R__TDocLatexDirective_BBCanvas\",\"fBBCanvas\",%g,%g);", -(canvSize + 4.), canvSize + 28.));
639 fBBCanvas->SetBorderMode(0);
640 fBBCanvas->SetFillColor(kWhite);
641
642 gSystem->ProcessEvents();
643
644 std::list<TLatexLine> latexLines;
645 std::vector<Float_t> maxWidth(20);
646 UInt_t numColumns = 0;
647 Float_t totalHeight = gLinePadding;
648
649 TLatex latex;
650 latex.SetTextFont(43);
651 latex.SetTextSize((Float_t)fFontSize);
652 latex.SetTextAlign(12);
653
654 // calculate positions
655 TIter iterLine(fLatex->GetListOfLines());
656 TObjString* line = 0;
657 TPRegexp regexp;
658 if (fSeparator.Length()) {
659 if (fSepIsRegexp)
660 regexp = TPRegexp(fSeparator);
661 } else fSepIsRegexp = kFALSE;
662
663 while ((line = (TObjString*) iterLine())) {
664 const TString& str = line->String();
665 TObjArray* split = 0;
666 if (!fSepIsRegexp) {
667 split = new TObjArray();
668 split->SetOwner();
669 }
670 if (!fSeparator.Length())
671 split->Add(new TObjString(str));
672 else {
673 if (fSepIsRegexp)
674 split = regexp.MatchS(str);
675 else {
676 Ssiz_t prevStart = 0;
677 for (Ssiz_t pos = 0; pos < str.Length(); ++pos) {
678 if (fSeparator.Index(str[pos]) != kNPOS) {
679 split->Add(new TObjString(TString(str(prevStart, pos - prevStart))));
680 split->Add(new TObjString(TString(str(pos, 1))));
681 prevStart = pos + 1;
682 }
683 }
684 split->Add(new TObjString(TString(str(prevStart, str.Length() - prevStart))));
685 }
686 }
687
688 latexLines.push_back(TLatexLine(split));
689 if (numColumns < (UInt_t)split->GetEntries())
690 numColumns = split->GetEntries();
691
692 Float_t heightLine = -1.;
693 for (UInt_t col = 0; col < (UInt_t)split->GetEntries(); ++col) {
694 Float_t widthLatex = 0.;
695 Float_t heightLatex = 0.;
696 TString* strCol = latexLines.back()[col];
697 if (strCol)
698 GetBoundingBox(latex, *strCol, widthLatex, heightLatex);
699 if (heightLine < heightLatex) heightLine = heightLatex;
700 if (maxWidth.size() < col)
701 maxWidth.resize(col * 2);
702 if (maxWidth[col] < widthLatex)
703 maxWidth[col] = widthLatex;
704 latexLines.back().Width(col) = widthLatex;
705 }
706 latexLines.back().Height() = heightLine;
707 totalHeight += heightLine + gLinePadding;
708 } // while next line
709
710 std::vector<Float_t> posX(numColumns + 1);
711 for (UInt_t col = 0; col <= numColumns; ++col) {
712 if (col == 0) posX[col] = gColumnPadding;
713 else posX[col] = posX[col - 1] + maxWidth[col - 1] + gColumnPadding;
714 }
715 Float_t totalWidth = posX[numColumns];
716
717 // draw
718 fBBCanvas->Clear();
719 fBBCanvas->cd();
720 Float_t padSizeX = totalWidth;
721 Float_t padSizeY = totalHeight + 8.;
722 // add magic batch vs. gui canvas sizes (4, 28) + rounding
723 TVirtualPad* padImg = (TVirtualPad*)gROOT->ProcessLineFast(
724 Form("new TCanvas(\"R__TDocLatexDirective_padImg\",\"padImg\",-(Int_t)%g,(Int_t)%g);",
725 padSizeX + 4.5, padSizeY + 28.5));
726 padImg->SetBorderMode(0);
727 padImg->SetFillColor(kWhite);
728 padImg->cd();
729
730 Float_t posY = 0.;
731 for (std::list<TLatexLine>::iterator iLine = latexLines.begin();
732 iLine != latexLines.end(); ++iLine) {
733 posY += iLine->Height()/2. + gLinePadding;
734 for (UInt_t iCol = 0; iCol < iLine->Size(); ++iCol) {
735 TString* str = (*iLine)[iCol];
736 if (!str) continue;
737 char align = 'l';
738 if ((UInt_t)fAlignment.Length() > iCol)
739 align = fAlignment[(Int_t)iCol];
740 Float_t x = posX[iCol];
741 switch (align) {
742 case 'l': break;
743 case 'r': x += maxWidth[iCol] - iLine->Width(iCol); break;
744 case 'c': x += 0.5*(maxWidth[iCol] - iLine->Width(iCol)); break;
745 default:
746 if (iLine == latexLines.begin())
747 Error("CreateLatex", "Invalid alignment character '%c'!", align);
748 }
749 latex.DrawLatex( x / padSizeX, 1. - posY / padSizeY, str->Data());
750 }
751 posY += iLine->Height()/2.;
752 }
753
754 padImg->Print(filename);
755
756 // delete the latex objects
757 for (std::list<TLatexLine>::iterator iLine = latexLines.begin();
758 iLine != latexLines.end(); ++iLine) {
759 iLine->Delete();
760 }
761
762 delete padImg;
763
764 if (!wasBatch)
765 gROOT->SetBatch(kFALSE);
766
767 gPad = oldPad;
768 }
769
770 //______________________________________________________________________________
771 void TDocLatexDirective::GetBoundingBox(TLatex& latex, const char* text, Float_t& width, Float_t& height)
772 {
773 // Determines the bounding box for text as height and width.
774 // Assumes that we are in batch mode.
775
776 UInt_t uiWidth = 0;
777 UInt_t uiHeight = 0;
778 fBBCanvas->cd();
779 latex.SetText(0.1, 0.5, text);
780 latex.GetBoundingBox(uiWidth, uiHeight);
781
782 width = uiWidth;
783 height = uiHeight;
784 }
785
786 //______________________________________________________________________________
787 TList* TDocLatexDirective::GetListOfLines() const
788 {
789 // Get the list of lines as TObjStrings
790 return fLatex ? fLatex->GetListOfLines() : 0;
791 }
792
793 //______________________________________________________________________________
794 Bool_t TDocLatexDirective::GetResult(TString& result)
795 {
796 // convert fLatex to a gif by creating a TLatex, drawing it on a
797 // temporary canvas, and saving that to a filename in the output
798 // directory.
799
800 TString filename;
801 GetName(filename);
802 filename.ReplaceAll(" ", "_");
803 const TString& firstLine = ((TObjString*)fLatex->GetListOfLines()->First())->String();
804 TString latexFilename(firstLine);
805 for (Ssiz_t namepos = 0; namepos < latexFilename.Length(); ++namepos)
806 if (!GetDocParser()->IsWord(latexFilename[namepos])) {
807 latexFilename.Remove(namepos, 1);
808 --namepos;
809 }
810 filename += "_";
811 filename += latexFilename;
812
813 GetDocOutput()->NameSpace2FileName(filename);
814 filename += ".gif";
815
816 TString altText(firstLine);
817 GetDocOutput()->ReplaceSpecialChars(altText);
818 altText.ReplaceAll("\"", "&quot;");
819 result = "<span class=\"latex\"><img class=\"latex\" alt=\"";
820 result += altText;
821 result += "\" title=\"LATEX\" src=\"";
822 result += filename;
823 result += "\" /></span>";
824
825 gSystem->PrependPathName(GetOutputDir(), filename);
826
827 if (gDebug > 3)
828 Info("HandleDirective_Latex", "Writing Latex \"%s\" to file %s.",
829 fLatex->GetName(), filename.Data());
830
831 CreateLatex(filename);
832
833 return kTRUE;
834 }
835
836 //______________________________________________________________________________
837 void TDocLatexDirective::AddParameter(const TString& name, const char* value /*=0*/)
838 {
839 // Parse fParameters, setting fFontSize, fAlignment, and fSeparator
840
841 if (!name.CompareTo("fontsize", TString::kIgnoreCase)) {
842 if (!value || !strlen(value))
843 Error("AddParameter", "Option \"fontsize\" needs a value!");
844 else fFontSize = atol(value);
845 } else if (!name.CompareTo("separator", TString::kIgnoreCase)) {
846 if (!value || !strlen(value))
847 Error("AddParameter", "Option \"separator\" needs a value!");
848 else fSeparator = value;
849 } else if (!name.CompareTo("align", TString::kIgnoreCase)) {
850 if (!value || !strlen(value))
851 Error("AddParameter", "Option \"align\" needs a value!");
852 else fAlignment = value;
853 } else
854 Warning("AddParameter", "Unknown option %s!", name.Data());
855 }