Skip to main content

The FormulaManager Class Reference

Declaration

class FormulaManager { ... }

Included Headers

#include <src/formula.h>

Private Constructors Index

FormulaManager ()

Private Member Functions Index

voidcreateFormulasTexFile (Dir &d, Format format, HighDPI hd, Mode mode)
voidcreateLatexFile (const QCString &fileName, Format format, Mode mode, IntVector &formulasToGenerate)

Private Member Attributes Index

std::unique_ptr< Private >p

Public Static Functions Index

static FormulaManager &instance ()

generator functions Index

enum classFormat { ... }
enum classHighDPI { ... }
enum classMode { ... }
voidgenerateImages (const QCString &outputDir, Format format, HighDPI hd=HighDPI::Off)

repository functions Index

voidinitFromRepository (const QCString &dir)
voidcheckRepositories ()

formula functions Index

voidclear ()
intaddFormula (const std::string &formulaText, int width=-1, int height=-1)
const Formula *findFormula (int formulaId) const
boolhasFormulas () const

Description

Manager class to handle formulas

Definition at line 58 of file formula.h.

Private Constructors

FormulaManager()

FormulaManager::FormulaManager ()

Declaration at line 88 of file formula.h, definition at line 50 of file formula.cpp.

50FormulaManager::FormulaManager() : p(std::make_unique<Private>())
51{
52}

Reference p.

Referenced by instance.

Private Member Functions

createFormulasTexFile()

void FormulaManager::createFormulasTexFile (Dir & d, Format format, HighDPI hd, Mode mode)

Declaration at line 86 of file formula.h, definition at line 553 of file formula.cpp.

554{
555 IntVector formulasToGenerate;
556 QCString formulaFileName = mode==Mode::Light ? "_formulas" : "_formulas_dark";
557 createLatexFile(formulaFileName,format,mode,formulasToGenerate);
558
559 if (!formulasToGenerate.empty()) // there are new formulas
560 {
561 if (!createDVIFile(formulaFileName)) return;
562
563 auto getFormula = [this](int pageNum) -> Formula *
564 {
565 auto it = p->formulaIdMap.find(pageNum);
566 if (it!=p->formulaIdMap.end())
567 {
568 return it->second;
569 }
570 return nullptr;
571 };
572
573 int pageIndex=1;
574 std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS));
575 if (numThreads>1) // multi-threaded version
576 {
577 ThreadPool threadPool(numThreads);
578 std::vector< std::future< StringVector > > results;
579 for (int pageNum : formulasToGenerate)
580 {
581 // create images for each formula.
582 auto formula = getFormula(pageNum);
583 auto processFormula = [=]() -> StringVector
584 {
585 return generateFormula(thisDir,formulaFileName,formula,pageNum,pageIndex,format,hd,mode);
586 };
587 results.emplace_back(threadPool.queue(processFormula));
588 pageIndex++;
589 }
590 for (auto &f : results)
591 {
592 auto tf = f.get();
593 p->tempFiles.insert(p->tempFiles.end(),tf.begin(),tf.end()); // append tf to p->tempFiles
594 }
595 }
596 else // single threaded version
597 {
598 for (int pageNum : formulasToGenerate)
599 {
600 // create images for each formula.
601 auto formula = getFormula(pageNum);
602 StringVector tf = generateFormula(thisDir,formulaFileName,formula,pageNum,pageIndex,format,hd,mode);
603 p->tempFiles.insert(p->tempFiles.end(),tf.begin(),tf.end()); // append tf to p->tempFiles
604
605 pageIndex++;
606 }
607 }
608 // remove intermediate files produced by latex
609 p->tempFiles.push_back(formulaFileName.str()+".dvi");
610 p->tempFiles.push_back(formulaFileName.str()+".log");
611 p->tempFiles.push_back(formulaFileName.str()+".aux");
612 }
613 // remove the latex file itself
614 p->tempFiles.push_back(formulaFileName.str()+".tex");
615
616 // write/update the formula repository so we know what text the
617 // generated images represent (we use this next time to avoid regeneration
618 // of the images, and to avoid forcing the user to delete all images in order
619 // to let a browser refresh the images).
620 std::ofstream f = Portable::openOutputStream("formula.repository");
621 if (f.is_open())
622 {
623 TextStream t(&f);
624 for (const auto &formula : p->formulas)
625 {
626 t << "\\_form#" << formula->id();
627 if (formula->width()!=-1 && formula->height()!=-1)
628 {
629 t << "=" << formula->width() << "x" << formula->height();
630 }
631 t << ":" << formula->text() << "\n";
632 }
633 }
634}

References Config_getInt, createDVIFile, createLatexFile, generateFormula, Light, Portable::openOutputStream, p, ThreadPool::queue and QCString::str.

Referenced by generateImages.

createLatexFile()

void FormulaManager::createLatexFile (const QCString & fileName, Format format, Mode mode, IntVector & formulasToGenerate)

Declaration at line 87 of file formula.h, definition at line 184 of file formula.cpp.

184void FormulaManager::createLatexFile(const QCString &fileName,Format format,Mode mode,IntVector &formulasToGenerate)
185{
186 // generate a latex file containing one formula per page.
187 QCString texName=fileName+".tex";
188 std::ofstream f = Portable::openOutputStream(texName);
189 if (f.is_open())
190 {
191 TextStream t(&f);
192 t << "\\documentclass{article}\n";
193 t << "\\usepackage{iftex}\n";
194 t << "\\usepackage{ifthen}\n";
195 t << "\\usepackage{epsfig}\n"; // for those who want to include images
196 t << "\\usepackage[utf8]{inputenc}\n"; // looks like some older distributions with newunicode package 1.1 need this option.
197 t << "\\usepackage{xcolor}\n";
198
199 if (mode==Mode::Dark) // invert page and text colors
200 {
201 t << "\\color{white}\n";
202 t << "\\pagecolor{black}\n";
203 }
204
207
208 QCString macroFile = Config_getString(FORMULA_MACROFILE);
209 if (!macroFile.isEmpty())
210 {
211 FileInfo fi(macroFile.str());
212 QCString stripMacroFile = fi.fileName();
213 t << "\\input{" << stripMacroFile << "}\n";
214 }
215
216 t << "\\pagestyle{empty}\n";
217 t << "\\begin{document}\n";
218 for (const auto &formula : p->formulas)
219 {
220 int id = formula->id();
221 // only formulas for which no image is cached are generated
222 //printf("check formula %d: cached=%d cachedDark=%d\n",formula->id(),formula->isCached(),formula->isCachedDark());
223 if ((mode==Mode::Light && !formula->isCached()) ||
224 (mode==Mode::Dark && !formula->isCachedDark())
225 )
226 {
227 // we force a pagebreak after each formula
228 t << formula->text() << "\n\\pagebreak\n\n";
229 formulasToGenerate.push_back(id);
230 }
231 QCString resultName;
232 resultName.sprintf("form_%d%s.%s",id, mode==Mode::Light?"":"_dark", format==Format::Vector?"svg":"png");
233 Doxygen::indexList->addImageFile(resultName);
234 }
235 t << "\\end{document}\n";
236 t.flush();
237 f.close();
238 }
239}

References Config_getString, Dark, FileInfo::fileName, TextStream::flush, Doxygen::indexList, QCString::isEmpty, Light, Portable::openOutputStream, p, QCString::sprintf, QCString::str, Vector, writeExtraLatexPackages and writeLatexSpecialFormulaChars.

Referenced by createFormulasTexFile.

Private Member Attributes

p

std::unique_ptr<Private> FormulaManager::p

Public Static Functions

instance()

FormulaManager & FormulaManager::instance ()
static

Declaration at line 61 of file formula.h, definition at line 54 of file formula.cpp.

55{
56 static FormulaManager fm;
57 return fm;
58}

Reference FormulaManager.

Referenced by addFormula, cleanUpDoxygen, clearAll, DocFormula::DocFormula, generateOutput, HtmlDocVisitor::operator() and parseInput.

generator functions

Format

enum class FormulaManager::Format
strong
Enumeration values
Bitmap
Vector

Definition at line 79 of file formula.h.

79 enum class Format { Bitmap, Vector };

generateImages

void FormulaManager::generateImages (const QCString & outputDir, Format format, HighDPI hd=HighDPI::Off)

Declaration at line 82 of file formula.h, definition at line 636 of file formula.cpp.

637{
638 Dir d(path.str());
639 // store the original directory
640 if (!d.exists())
641 {
642 term("Output directory '{}' does not exist!\n",path);
643 }
644 std::string oldDir = Dir::currentDirPath();
645
646 QCString macroFile = Config_getString(FORMULA_MACROFILE);
647 QCString stripMacroFile;
648 if (!macroFile.isEmpty())
649 {
650 FileInfo fi(macroFile.str());
651 macroFile=fi.absFilePath();
652 stripMacroFile = fi.fileName();
653 }
654
655 // go to the html output directory (i.e. path)
657 Dir thisDir;
658
659 if (!macroFile.isEmpty())
660 {
661 copyFile(macroFile,stripMacroFile);
662 }
663
664 createFormulasTexFile(thisDir,format,hd,Mode::Light);
665 if (Config_getEnum(HTML_COLORSTYLE)!=HTML_COLORSTYLE_t::LIGHT) // all modes other than light need a dark version
666 {
667 // note that the dark version reuses the bounding box of the light version so it needs to be
668 // created after the light version.
669 createFormulasTexFile(thisDir,format,hd,Mode::Dark);
670 }
671
672 // clean up temporary files
674 {
675 for (const auto &file : p->tempFiles)
676 {
677 thisDir.remove(file);
678 }
679 }
680
681 // reset the directory to the original location.
682 Dir::setCurrent(oldDir);
683}

References FileInfo::absFilePath, Dir::absPath, Config_getEnum, Config_getString, copyFile, createFormulasTexFile, Dir::currentDirPath, Dark, Dir::exists, FileInfo::fileName, Debug::Formula, QCString::isEmpty, Debug::isFlagSet, Light, p, Dir::remove, Dir::setCurrent, QCString::str and term.

Referenced by generateOutput.

HighDPI

enum class FormulaManager::HighDPI
strong
Enumeration values
On
Off

Definition at line 80 of file formula.h.

80 enum class HighDPI { On, Off };

Mode

enum class FormulaManager::Mode
strong
Enumeration values
Dark
Light

Definition at line 81 of file formula.h.

81 enum class Mode { Dark, Light };

repository functions

checkRepositories

void FormulaManager::checkRepositories ()

Declaration at line 66 of file formula.h, definition at line 173 of file formula.cpp.

174{
175 //printf("checkRepositories valid=%d\n",p->repositoriesValid);
176 if (!p->repositoriesValid)
177 {
178 clear(); // clear cached formulas, so the corresponding images and repository files
179 // are regenerated
180 p->repositoriesValid = true;
181 }
182}

References clear and p.

Referenced by parseInput.

initFromRepository

void FormulaManager::initFromRepository (const QCString & dir)

Declaration at line 65 of file formula.h, definition at line 60 of file formula.cpp.

61{
62 std::ifstream f = Portable::openInputStream(dir+"/formula.repository");
63 if (f.is_open())
64 {
65 uint32_t formulaCount=0;
66 msg("Reading formula repository...\n");
67 std::string readLine;
68 std::string line;
69 std::string prefix("\\_form#");
70 int nextLineNr=1;
71 bool hasNextLine = !getline(f,readLine).fail();
72 while (hasNextLine)
73 {
74 line = readLine;
75 int lineNr = nextLineNr;
76
77 // look ahead a bit because a formula can be spread over several lines
78 while ((hasNextLine = !getline(f,readLine).fail()))
79 {
80 nextLineNr+=1;
81 if (!readLine.compare(0, prefix.size(), prefix)) break;
82 line += "\n" + readLine;
83 }
84
85 // new format: \_form#<digits>=<digits>x<digits>:formula
86 static const reg::Ex re_new(R"(\\_form#(\d+)=(\d+)x(\d+):)");
87 // old format: \_form#<digits>:formula
88 static const reg::Ex re_old(R"(\\_form#(\d+):)");
89
90 reg::Match match;
91 int id = -1;
92 int width = -1;
93 int height = -1;
94 std::string text;
95 if (reg::search(line,match,re_new)) // try new format first
96 {
97 id = std::stoi(match[1].str());
98 width = std::stoi(match[2].str());
99 height = std::stoi(match[3].str());
100 text = line.substr(match.position()+match.length());
101 //printf("new format found id=%d width=%d height=%d text=%s\n",id,width,height,text.c_str());
102 }
103 else if (reg::search(line,match,re_old)) // check for old format
104 {
105 //id = std::stoi(match[1].str());
106 //text = line.substr(match.position()+match.length());
107 //printf("old format found id=%d text=%s\n",id,text.c_str());
108 msg("old formula.repository format detected; forcing upgrade.\n");
109 p->repositoriesValid = false;
110 break;
111 }
112 else // unexpected content
113 {
114 warn_uncond("{}/formula.repository contains invalid content at line {}: found: '{}'\n",dir,lineNr,line);
115 p->repositoriesValid = false;
116 break;
117 }
118
119 auto it = p->formulaIdMap.find(id);
120 Formula *formula=nullptr;
121 if (it!=p->formulaIdMap.end()) // formula already found in a repository for another output format
122 {
123 formula = it->second;
124 if (formula->text().str()!=text) // inconsistency between repositories detected
125 {
126 msg("differences detected between formula.repository files; forcing upgrade.\n");
127 p->repositoriesValid = false;
128 break;
129 }
130 formulaCount++;
131 }
132 else // create new formula from cache
133 {
134 //printf("formula not found adding it under id=%d\n",id);
135 formula = p->formulas.add(text.c_str(),id,width,height);
136 p->formulaIdMap.emplace(id,formula);
137 }
138
139 if (formula) // if an entry in the repository exists also check if there is a generated image
140 {
141 QCString formImgName;
142 formImgName.sprintf("form_%d",formula->id());
143 FileInfo fiPng((dir+"/"+formImgName+".png").str());
144 FileInfo fiSvg((dir+"/"+formImgName+".svg").str());
145 // mark formula as cached, so we do not need to regenerate the images
146 bool isCached = fiPng.exists() || fiSvg.exists();
147 formula->setCached(isCached);
148 //printf("formula %d: cached=%d\n",formula->id(),isCached);
149
150 FileInfo fiPngDark((dir+"/"+formImgName+"_dark.png").str());
151 FileInfo fiSvgDark((dir+"/"+formImgName+"_dark.svg").str());
152 bool isCachedDark = fiPngDark.exists() || fiSvgDark.exists();
153 formula->setCachedDark(isCachedDark);
154 //printf("formula %d: cachedDark=%d\n",formula->id(),isCachedDark);
155 }
156 }
157
158 // For the first repository all formulas should be new (e.g. formulaCount==0).
159 // For the other repositories the same number of formulas should be found
160 // (and number of formulas should be the same for all repositories, content is already check above)
161 if (formulaCount>0 && formulaCount!=p->formulas.size()) // inconsistency between repositories
162 {
163 msg("differences detected between formula.repository files; forcing upgrade.\n");
164 p->repositoriesValid = false;
165 }
166 }
167 else // no repository found for an output format
168 {
169 p->repositoriesValid = false;
170 }
171}

References FileInfo::exists, Formula::id, msg, Portable::openInputStream, p, prefix, reg::search, Formula::setCached, Formula::setCachedDark, QCString::sprintf, QCString::str, Formula::text and warn_uncond.

Referenced by parseInput.

formula functions

addFormula

int FormulaManager::addFormula (const std::string & formulaText, int width=-1, int height=-1)

Declaration at line 72 of file formula.h, definition at line 691 of file formula.cpp.

691int FormulaManager::addFormula(const std::string &formulaText,int width,int height)
692{
693 Formula *formula = p->formulas.find(formulaText);
694 if (formula) // same formula already stored
695 {
696 return formula->id();
697 }
698 // add new formula
699 int id = static_cast<int>(p->formulas.size());
700 formula = p->formulas.add(formulaText.c_str(),id,width,height);
701 p->formulaIdMap.emplace(id,formula);
702 return id;
703}

References Formula::id and p.

Referenced by addFormula.

clear

void FormulaManager::clear ()

Declaration at line 71 of file formula.h, definition at line 685 of file formula.cpp.

686{
687 p->formulas.clear();
688 p->formulaIdMap.clear();
689}

Reference p.

Referenced by checkRepositories, cleanUpDoxygen and clearAll.

findFormula

const Formula * FormulaManager::findFormula (int formulaId)

Declaration at line 73 of file formula.h, definition at line 705 of file formula.cpp.

705const Formula *FormulaManager::findFormula(int formulaId) const
706{
707 auto it = p->formulaIdMap.find(formulaId);
708 return it != p->formulaIdMap.end() ? it->second : nullptr;
709}

Reference p.

Referenced by DocFormula::DocFormula and HtmlDocVisitor::operator().

hasFormulas

bool FormulaManager::hasFormulas ()

Declaration at line 74 of file formula.h, definition at line 720 of file formula.cpp.

721{
722 return !p->formulas.empty();
723}

Reference p.

Referenced by generateOutput.


The documentation for this class was generated from the following files:


Generated via doxygen2docusaurus by Doxygen 1.14.0.