ctai/3rdparty/MicroTeX/src/latex.cpp
JackLee 5247485491 1-调整类名和类文件名
2-给公式显示svg增加边距
3-增加字体和字号功能(未实装)
2025-03-09 18:29:30 +08:00

152 lines
4.0 KiB
C++

#include "latex.h"
#include "core/core.h"
#include "core/formula.h"
#include "core/macro.h"
#include "fonts/fonts.h"
#if CLATEX_CXX17
#include <filesystem>
#endif
using namespace std;
using namespace tex;
string tex::RES_BASE = "res";
static string CHECK_FILE = ".clatexmath-res_root";
#ifdef _WIN32
static char PATH_SEPERATOR = ';';
#else
static char PATH_SEPERATOR = ':';
#endif
Formula* LaTeX::_formula = nullptr;
TeXRenderBuilder* LaTeX::_builder = nullptr;
string LaTeX::queryResourceLocation(string& custom_path) {
queue<string> paths;
paths.push(custom_path);
// checks if CLM_DEVEL exists. If it does, it pushes it to potential paths.
char* devel = getenv("CLM_DEVEL");
if (devel != NULL && *devel != '\0') {
paths.push(string(devel));
}
// checks if XDG_DATA_HOME exists. If it does, it pushes it to potential paths.
char* userdata = getenv("XDG_DATA_HOME");
if (userdata != NULL && strcmp(userdata, "") != 0) {
paths.push(string(userdata) + "/clatexmath/");
}
// checks if XDG_DATA_DIRS is set. If it is, it splits XDG_DATA_DIRS at : (or
// ; on windows) and pushes each part of it to potential paths.
char* xdg = getenv("XDG_DATA_DIRS");
if (xdg != NULL && strcmp(xdg, "") != 0) {
stringstream xdg_paths(xdg);
string xdg_path;
while (getline(xdg_paths, xdg_path, PATH_SEPERATOR)) {
paths.push(xdg_path + "/clatexmath/");
}
}
#ifndef _WIN32
// checks if HOME env var is unset. if it isn't it pushes ~/.local/share/clatexmath
// to potential paths.
char* home = getenv("HOME");
if (home != NULL && strcmp(home, "") != 0) {
char* userdata_fallback;
asprintf(&userdata_fallback, "%s/.local/share/clatexmath/", home);
paths.push(string(userdata_fallback));
delete userdata_fallback;
}
paths.push("/usr/share/clatexmath/");
paths.push("/usr/local/share/clatexmath/");
#endif
// goes through the list of potential paths. if it finds a path that contains
// .clatexmath-res_root, it returns it. Otherwise return an empty string.
while (!paths.empty()) {
#if CLATEX_CXX17
filesystem::path p = paths.front();
p.append(CHECK_FILE);
if (filesystem::exists(p)) {
p.remove_filename();
return p.string();
}
#elif defined(_MSC_VER)
std::string path = paths.front();
std::string file = path + "/" + CHECK_FILE;
FILE* fp = NULL;
errno_t err = fopen_s(&fp, file.c_str(), "rb");
if (err == 0 && fp) {
fclose(fp);
return path;
}
#else
std::string path = paths.front();
std::string file = path + "/" + CHECK_FILE;
FILE* fp = fopen(file.c_str(), "rb");
if (fp) {
fclose(fp);
return path;
}
#endif
paths.pop();
}
return "";
}
void LaTeX::init(string res_root_path) {
try {
auto path = queryResourceLocation(res_root_path);
if (!path.empty()) {
RES_BASE = path;
}
} catch (std::exception&) {
}
if (_formula != nullptr) return;
NewCommandMacro::_init_();
DefaultTeXFont::_init_();
Formula::_init_();
TextRenderingBox::_init_();
_formula = new Formula();
_builder = new TeXRenderBuilder();
}
void LaTeX::release() {
DefaultTeXFont::_free_();
Formula::_free_();
MacroInfo::_free_();
NewCommandMacro::_free_();
TextRenderingBox::_free_();
if (_formula != nullptr) delete _formula;
if (_builder != nullptr) delete _builder;
}
const string& LaTeX::getResRootPath() {
return RES_BASE;
}
void LaTeX::setDebug(bool debug) {
Formula::setDEBUG(debug);
}
TeXRender* LaTeX::parse(const wstring& latex, int width, float textSize, float lineSpace, color fg) {
bool lined = true;
// if (startswith(latex, L"$$") || startswith(latex, L"\\[")) {
// lined = false;
// }
Alignment align = lined ? Alignment::left : Alignment::center;
_formula->setLaTeX(latex);
TeXRender* render =
_builder->setStyle(TexStyle::display)
.setTextSize(textSize)
.setWidth(UnitType::pixel, width, align)
.setIsMaxWidth(lined)
.setLineSpace(UnitType::pixel, lineSpace)
.setForeground(fg)
.build(*_formula);
return render;
}