33 #include <QCoreApplication> 37 #include <QTextStream> 41 #include <QTextDocument> 42 #include <QImageWriter> 44 #include <QTemporaryDir> 51 #include "klffilterprocess.h" 52 #include "klfuserscript.h" 54 #include "klfbackend_p.h" 84 #ifdef KLF_EXTRA_SEARCH_PATHS 85 # define EXTRA_PATHS_PRE KLF_EXTRA_SEARCH_PATHS , 88 # define EXTRA_PATHS_PRE 93 #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) 98 static const char * standard_extra_paths[] = {
100 "C:\\Program Files*\\MiKTeX*\\miktex\\bin",
101 "C:\\texlive\\*\\bin\\win*",
102 "C:\\Program Files*\\gs*\\gs*\\bin",
105 #elif defined(KLF_WS_MAC) 110 static const char * standard_extra_paths[] = {
112 "/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/opt/local/bin:/sw/bin:/sw/usr/bin",
120 static const char * standard_extra_paths[] = {
130 KLFAbstractLatexMetaInfo::KLFAbstractLatexMetaInfo()
133 KLFAbstractLatexMetaInfo::~KLFAbstractLatexMetaInfo()
143 saveField(
"Application",
144 QObject::tr(
"Created with KLatexFormula version %1",
"KLFBackend::saveOutputToFile")
145 .arg(KLF_VERSION_STRING));
147 saveField(
"InputLatex", in.
latex);
148 saveField(
"InputMathMode", in.
mathmode);
149 saveField(
"InputPreamble", in.
preamble);
151 saveField(
"InputFgColor",
QString(
"rgb(%1, %2, %3)").arg(qRed(in.fg_color))
152 .
arg(qGreen(in.fg_color)).
arg(qBlue(in.fg_color)));
153 saveField(
"InputBgColor",
QString(
"rgba(%1, %2, %3, %4)").arg(qRed(in.
bg_color))
158 saveField(
"InputBypassTemplate", boolstr[(
int)in.
bypassTemplate]);
162 saveField(
"InputUserScriptParams", usparams);
167 saveField(
"SettingsOutlineFonts", boolstr[(
int)settings.
outlineFonts]);
169 saveField(
"SettingsWantRaw", boolstr[(
int)settings.
wantRaw]);
170 saveField(
"SettingsWantPDF", boolstr[(
int)settings.
wantPDF]);
171 saveField(
"SettingsWantSVG", boolstr[(
int)settings.
wantSVG]);
173 klfDbg(
"saved meta-info.") ;
177 KLFImageLatexMetaInfo::KLFImageLatexMetaInfo(
QImage *imgwrite) : _w(imgwrite) { }
179 void KLFImageLatexMetaInfo::saveField(
const QString& k,
const QString& v)
196 for (i = 0; i < v.
length(); ++i) {
197 if (v[i] < 0 || v[i] > 126) {
207 for (i = 0; i < vdata.
size(); ++i) {
210 if (
QChar(vdata[i]).isLetterOrNumber() || c ==
' ' || c ==
'.' || c ==
',' || c ==
'/')
225 klfDbg(
"escaping char: (int)c="<<(
int)c<<
" (uint)c="<<uint(c)<<
", octal="<<
klfFmtCC(
"%03o", (uint)c));
230 return "("+escaped+
")";
240 for (i = 0; i < (vdata.
size()-1); i += 2) {
241 hex +=
klfFmt(
"%02x%02x ", (
unsigned int)(
unsigned char)vdata[i], (
unsigned int)(
unsigned char)vdata[i+1]);
243 return "<" + hex +
">";
248 KLFPdfmarksWriteLatexMetaInfo::KLFPdfmarksWriteLatexMetaInfo(
QByteArray *
string)
256 "/pdfmark where { pop } { /globaldict where { pop globaldict } { userdict } ifelse " 257 "/pdfmark /cleartomark load put } ifelse\n" 267 void KLFPdfmarksWriteLatexMetaInfo::saveField(
const QString& k,
const QString& v)
271 void KLFPdfmarksWriteLatexMetaInfo::finish()
273 _s->
append(
" /DOCINFO pdfmark\n");
277 QByteArray datavalue = klf_escape_ps_string(v);
279 _s->
append(
" /"+k+
" " + datavalue +
"\n");
317 KLFBackend::TemplateGenerator::TemplateGenerator()
320 KLFBackend::TemplateGenerator::~TemplateGenerator()
324 KLFBackend::DefaultTemplateGenerator::DefaultTemplateGenerator()
327 KLFBackend::DefaultTemplateGenerator::~DefaultTemplateGenerator()
341 s +=
"\\documentclass{article}\n" 342 "\\usepackage[dvips]{color}\n";
345 "\\begin{document}\n" 346 "\\thispagestyle{empty}\n";
350 s +=
QString(
"\\definecolor{klffgcolor}{rgb}{%1,%2,%3}\n").
arg(qRed(in.fg_color)/255.0)
351 .
arg(qGreen(in.fg_color)/255.0).
arg(qBlue(in.fg_color)/255.0);
352 s +=
QString(
"\\definecolor{klfbgcolor}{rgb}{%1,%2,%3}\n").
arg(qRed(in.
bg_color)/255.0)
355 s +=
"\\pagecolor{klfbgcolor}\n";
356 s +=
"{\\color{klffgcolor} ";
370 KLFBackend::KLFBackend()
377 #define D_RX "([0-9eE.-]+)" 381 double x1, x2, y1, y2;
386 static bool calculate_gs_eps_bbox(
const QByteArray& epsdata,
const QString& epsFile, klfbbox *bbox,
390 static void correct_eps_bbox(
const QByteArray& epsdata,
391 const klfbbox& bbox_corrected,
const klfbbox& bbox_orig,
392 double vectorscale, QRgb bgcolor,
QByteArray * epsdatacorrected);
394 static void replace_svg_width_or_height(
QByteArray *svgdata,
const char * attr,
double val);
411 <<
"latex" <<
"dvi" <<
"eps-raw" <<
"eps-bbox" <<
"eps-processed" 412 <<
"png" <<
"pdf" <<
"svg-gs" <<
"svg" ;
420 klfWarning(
"Dependency loop detected for format "<<fmt) ;
437 s <<
"eps-processed";
439 s <<
"eps-processed";
441 s <<
"eps-processed";
453 foreach (
QString str, basedeps) {
454 KLFStringSet subdeps = klfbackend_dependencies(str,
true);
455 foreach (
QString subdep, subdeps) {
467 KLFStringSet fmtlist = klfbackend_dependencies(forwhat);
470 klfWarning(
"User Script Skipped format "<<s<<
" which is necessary for "<<forwhat) ;
477 #define ASSERT_HAVE_FORMATS_FOR(forwhat) \ 478 { if (!assert_have_formats_for(us_outputs, us_skipfmts, forwhat)) { \ 479 res.status = KLFERR_USERSCRIPT_BADSKIPFORMATS; \ 480 res.errorstr = QObject::tr("User Script broke dependencies in skip-formats list", "KLFBackend"); \ 497 settings = usersettings;
508 klfDbg(
"current environment is "<<curenv) ;
510 QStringList() <<
"PATH" <<
"TEXINPUTS" <<
"BIBINPUTS",
514 klfDbg(
"execution environment for sub-processes is "<<settings.
execenv) ;
533 initGsInfo(&settings, isMainThread);
534 if (!gsInfo.contains(settings.
gsexec)) {
536 res.
errorstr =
QObject::tr(
"Can't query version of ghostscript located at `%1'.",
"KLFBackend")
541 const GsInfo thisGsInfo = gsInfo.value(settings.
gsexec);
548 QRgb bgcolor_when_correcting_bbox = qRgba(0,0,0,0);
554 qAlpha(in.
bg_color) != 0 && (in.
bg_color & qRgb(255,255,255)) != qRgb(255,255,255)) {
555 bgcolor_when_correcting_bbox = in.
bg_color;
604 QString ver = KLF_VERSION_STRING;
609 QString temptemplate = settings.
tempdir +
"/klftmp"+ver+
"-XXXXXX";
624 klfDbg(
"Temp location base name is "<<tempfname) ;
626 QString fnTex = tempfname +
".tex";
627 QString fnDvi = tempfname +
".dvi";
628 QString fnRawEps = tempfname +
".eps";
629 QString fnBBoxEps = tempfname +
"-bbox.eps";
630 QString fnProcessedEps = tempfname +
"-processed.eps";
631 QString fnRawPng = tempfname +
"-raw.png";
632 QString fnPdfMarks = tempfname +
".pdfmarks";
633 QString fnPdf = tempfname +
".pdf";
634 QString fnGsSvg = tempfname +
"-gs.svg";
637 QString fnSvg = tempfname +
".svg";
646 if (latexsimplified.
isEmpty()) {
663 bool r = file.
open(QIODevice::WriteOnly);
674 klfDbg(
"using custom template generator") ;
680 stream << t->generateTemplate(in, settings);
696 res.
status = scriptinfo.scriptInfoError();
697 res.
errorstr = scriptinfo.scriptInfoErrorString();
701 if ( (!scriptinfo.klfMinVersion().
isEmpty()
703 (!scriptinfo.klfMaxVersion().
isEmpty()
705 res.
status = KLFERR_USERSCRIPT_BADKLFVERSION;
706 res.
errorstr =
QObject::tr(
"User Script `%1' is not compatible with current version of KLatexFormula.",
707 "KLFBackend").
arg(scriptinfo.name());
711 if (scriptinfo.category() !=
QLatin1String(
"klf-backend-engine")) {
712 res.
status = KLFERR_USERSCRIPT_BADCATEGORY;
714 "KLFBackend").
arg(scriptinfo.name());
722 <<
"KLF_TEMPDIR=" + settings.
tempdir 725 <<
"KLF_GS=" + settings.
gsexec 726 <<
"KLF_GS_VERSION=" + thisGsInfo.version
727 <<
"KLF_GS_DEVICES=" +
QStringList(thisGsInfo.availdevices.toList()).join(
",")
729 << klfInputToEnvironmentForUserScript(in)
731 << klfSettingsToEnvironmentForUserScript(settings)
733 <<
"KLF_TEMPFNAME=" + tempfname
734 <<
"KLF_FN_TEX=" + fnTex
735 <<
"KLF_FN_LATEX=" + fnTex
736 <<
"KLF_FN_DVI=" + fnDvi
737 <<
"KLF_FN_EPS_RAW=" + fnRawEps
738 <<
"KLF_FN_EPS_BBOX=" + fnBBoxEps
739 <<
"KLF_FN_EPS_PROCESSED=" + fnProcessedEps
740 <<
"KLF_FN_PNG=" + fnRawPng
741 <<
"KLF_FN_PDFMARKS=" + fnPdfMarks
742 <<
"KLF_FN_PDF=" + fnPdf
743 <<
"KLF_FN_SVG_GS=" + fnGsSvg
744 <<
"KLF_FN_SVG=" + fnSvg
750 p.addExecEnviron(addenv);
752 p.setProcessAppEvents(
false);
756 p.collectStderrTo(&stderrdata);
757 p.collectStdoutTo(&stdoutdata);
763 foreach (
QString fmt, outfmts) {
773 outdata[fnRawEps] = &rawepsdata;
775 outdata[fnBBoxEps] = &bboxepsdata;
777 outdata[fnProcessedEps] = &res.
epsdata;
789 outdata[fnGsSvg] = & gssvgdata;
795 klfWarning(
"Can't handle output format from user script: "<<fmt) ;
809 outdata.
remove(fnBBoxEps);
815 if ((tempi = skipfmts.
indexOf(
"ALL_EXCEPT")) >= 0) {
818 foreach (
QString f, klfbackend_fmts) { us_skipfmts << f; }
820 foreach (
QString fmt, skipfmts) {
821 if (!klfbackend_fmts.
contains(fmt)) {
822 klfWarning(
"User Script Info: Unknown format to skip: "<<fmt) ;
830 our_skipfmts = us_skipfmts;
831 foreach (
QString fmt, outfmts) {
833 klfWarning(
"User Script Info: format " << fmt <<
" provided by script is also marked " 834 "as to be skipped!") ;
839 our_skipfmts <<
"eps-bbox";
842 our_skipfmts <<
"eps-raw";
845 our_skipfmts <<
"svg-gs";
848 klfDbg(
"us_skipfmts = " << us_skipfmts) ;
853 res.
errorstr = p.resultErrorString();
854 switch (p.resultStatus()) {
856 case KLFFP_NOEXIT: res.
status = KLFERR_USERSCRIPT_NONORMALEXIT;
break;
858 case KLFFP_NODATA: res.
status = KLFERR_USERSCRIPT_NOOUTPUT;
break;
859 case KLFFP_DATAREADFAIL: res.
status = KLFERR_USERSCRIPT_OUTPUTREADFAIL;
break;
861 res.
status = p.resultStatus();
867 foreach (
QString fmt, outfmts) {
874 corrfname = fnRawEps;
876 corrfname = fnBBoxEps;
878 corrfname = fnProcessedEps;
880 corrfname = fnRawPng;
892 klfWarning(
"Promised format " << fmt <<
" did not appear after calling user script.") ;
898 klfDbg(
"our_skipfmts = " << our_skipfmts) ;
901 if (!has_userscript_output(us_outputs,
"dvi") && !our_skipfmts.
contains(
"dvi")) {
903 klfDbg(
"preparing to launch latex.") ;
911 KLFBackendFilterProgram p(
QLatin1String(
"LaTeX"), &settings, isMainThread, tempdir.
path());
922 ok = p.run(userinputforerrors, fnDvi, &res.
dvidata);
924 p.errorToOutput(&res);
929 if (!has_userscript_output(us_outputs,
"eps-raw") && !our_skipfmts.
contains(
"eps-raw")) {
931 ASSERT_HAVE_FORMATS_FOR(
"eps-raw") ;
940 KLFBackendFilterProgram p(
QLatin1String(
"dvips"), &settings, isMainThread, tempdir.
path());
960 ok = p.run(fnRawEps, &rawepsdata);
963 p.errorToOutput(&res);
966 klfDbg(
"read raw EPS; rawepsdata/length="<<rawepsdata.
size()) ;
977 if (!has_userscript_output(us_outputs,
"eps-bbox") && !our_skipfmts.
contains(
"eps-bbox")) {
981 ASSERT_HAVE_FORMATS_FOR(
"eps-bbox") ;
983 klfbbox bbox, bbox_corrected;
986 bool ok = calculate_gs_eps_bbox(
QByteArray(), fnRawEps, &bbox, &res, settings, isMainThread);
990 bool ok = read_eps_bbox(rawepsdata, &bbox, &res);
1005 bbox_corrected.x1 = 0;
1006 bbox_corrected.y1 = 0;
1012 correct_eps_bbox(rawepsdata, bbox_corrected, bbox, in.
vectorscale,
1013 bgcolor_when_correcting_bbox, &bboxepsdata);
1015 klfDbg(
"corrected bbox to "<<bbox.x1<<
","<<bbox.y1<<
","<<bbox.x2<<
","<<bbox.y2);
1016 }
else if (!our_skipfmts.
contains(
"eps-bbox")) {
1025 if (us_outputs.
contains(
"eps-processed")) {
1026 fn = fnProcessedEps;
1034 bool ok = calculate_gs_eps_bbox(
QByteArray(), fn, &bb, &res, settings, isMainThread);
1038 bool ok = read_eps_bbox(bboxepsdata, &bb, &res);
1051 if (!has_userscript_output(us_outputs,
"eps-processed") && !our_skipfmts.
contains(
"eps-processed")) {
1054 ASSERT_HAVE_FORMATS_FOR(
"eps-processed") ;
1065 KLFBackendFilterProgram p(
QLatin1String(
"gs (EPS Post-Processing Outline Fonts)"), &settings, isMainThread,
1075 const char *env_gs_device = getenv(
"KLFBACKEND_GS_PS_DEVICE");
1076 if (env_gs_device != NULL) {
1078 gsoptions =
QStringList() <<
"-dNOCACHE -dNoOutputFonts";
1079 }
else if (thisGsInfo.version_maj < 9 ||
1080 (thisGsInfo.version_maj == 9 && thisGsInfo.version_min <= 7)) {
1084 }
else if (thisGsInfo.version_maj > 9 ||
1085 (thisGsInfo.version_maj == 9 && thisGsInfo.version_min >= 15)) {
1094 res.
errorstr =
QObject::tr(
"Installed Ghostscript version %1 may not be used to create font outlines." 1095 " Please upgrade to gs >= 9.15 (or downgrade to gs <= 9.07).",
1096 "KLFBackend").
arg(thisGsInfo.version);
1100 p.addArgv(settings.
gsexec);
1102 <<
"-dNOPAUSE" <<
"-dSAFER" <<
"-dEPSCrop" <<
QString::fromLatin1(
"-sDEVICE=%1").arg(psdevice)
1104 <<
"-q" <<
"-dBATCH" <<
"-");
1106 ok = p.run(bboxepsdata, fnProcessedEps, &res.
epsdata);
1108 p.errorToOutput(&res);
1120 if (!has_userscript_output(us_outputs,
"png") && !our_skipfmts.
contains(
"png")) {
1122 ASSERT_HAVE_FORMATS_FOR(
"png") ;
1131 KLFBackendFilterProgram p(
QLatin1String(
"gs (PNG)"), &settings, isMainThread, tempdir.
path());
1145 <<
"-dNOPAUSE" <<
"-dSAFER" <<
"-dTextAlphaBits=4" <<
"-dGraphicsAlphaBits=4" 1148 p.addArgv(
"-sDEVICE=png16m");
1150 p.addArgv(
"-sDEVICE=pngalpha");
1154 ok = p.run(bboxepsdata, fnRawPng, &res.
pngdata_raw);
1156 p.errorToOutput(&res);
1164 klfWarning(
"PNG format was skipped by user script. The QImage object will be invalid.") ;
1169 if (!has_userscript_output(us_outputs,
"png") || !
QFile::exists(fnRawPng)) {
1170 klfWarning(
"PNG format is required to initialize the QImage object, but was not generated by user script.") ;
1178 if (!our_skipfmts.
contains(
"png")) {
1182 metainfo.saveMetaInfo(in, settings);
1186 buf.
open(QIODevice::WriteOnly);
1190 klfWarning(
"Can't save \"final\" PNG data.") ;
1195 klfDbg(
"prepared final PNG data.") ;
1198 if ( settings.
wantPDF && !has_userscript_output(us_outputs,
"pdf") && !our_skipfmts.
contains(
"pdf") ) {
1200 ASSERT_HAVE_FORMATS_FOR(
"pdf") ;
1203 {
QFile fpdfmarks(fnPdfMarks);
1204 bool r = fpdfmarks.
open(QIODevice::WriteOnly);
1213 pdfmetainfo.
savePDFField(
"Keywords",
"KLatexFormula KLF LaTeX equation formula");
1214 pdfmetainfo.
savePDFField(
"Creator",
"KLatexFormula " KLF_VERSION_STRING);
1215 pdfmetainfo.saveMetaInfo(in, settings);
1216 pdfmetainfo.finish();
1217 fpdfmarks.
write(pdfmarkstr);
1228 KLFBackendFilterProgram p(
QLatin1String(
"gs (PDF)"), &settings, isMainThread, tempdir.
path());
1236 <<
"-dNOPAUSE" <<
"-dSAFER" <<
"-sDEVICE=pdfwrite" 1238 <<
"-q" <<
"-dBATCH" <<
"-" << fnPdfMarks);
1243 p.errorToOutput(&res);
1250 if (!has_userscript_output(us_outputs,
"svg-gs") &&
1251 !our_skipfmts.
contains(
"svg-gs")) {
1253 ASSERT_HAVE_FORMATS_FOR(
"svg-gs") ;
1256 if (!thisGsInfo.availdevices.contains(
"svg")) {
1270 KLFBackendFilterProgram p(
QLatin1String(
"gs (SVG)"), &settings, isMainThread, tempdir.
path());
1277 p.addArgv(settings.
gsexec);
1279 p.addArgv(
QStringList() <<
"-dNOCACHE" <<
"-dNOPAUSE" <<
"-dSAFER" <<
"-dEPSCrop" <<
"-sDEVICE=svg" 1281 <<
"-q" <<
"-dBATCH" <<
"-");
1284 ok = p.run(bboxepsdata, fnGsSvg, &gssvgdata);
1286 p.errorToOutput(&res);
1291 if (!has_userscript_output(us_outputs,
"svg") && !our_skipfmts.
contains(
"svg")) {
1293 ASSERT_HAVE_FORMATS_FOR(
"svg") ;
1301 replace_svg_width_or_height(&gssvgdata,
"width=", res.
width_pt);
1302 replace_svg_width_or_height(&gssvgdata,
"height=", res.
height_pt);
1310 klfDbg(
"end of function.") ;
1317 static bool calculate_gs_eps_bbox(
const QByteArray& epsData,
const QString& epsFile, klfbbox *bbox,
1332 KLFBackendFilterProgram p(
QLatin1String(
"GhostScript (bbox)"), &settings, isMainThread, settings.
tempdir);
1339 p.setOutputStdout(
true);
1340 p.setOutputStderr(
true);
1344 p.setArgv(
QStringList() << settings.
gsexec <<
"-dNOPAUSE" <<
"-dSAFER" <<
"-sDEVICE=bbox" <<
"-q" <<
"-dBATCH" 1347 bool ok = p.run(epsData ,
QString() , &bboxdata);
1349 p.errorToOutput(resError);
1353 klfDbg(
"gs provided output:\n"<<bboxdata);
1356 QRegExp rx_gsbbox(
"%%HiResBoundingBox\\s*:\\s+" D_RX
"\\s+" D_RX
"\\s+" D_RX
"\\s+" D_RX
"");
1360 resError->
errorstr =
QObject::tr(
"Ghostscript did not provide parsable BBox output!",
"KLFBackend");
1363 bbox->x1 = rx_gsbbox.cap(1).toDouble();
1364 bbox->y1 = rx_gsbbox.cap(2).toDouble();
1365 bbox->x2 = rx_gsbbox.cap(3).toDouble();
1366 bbox->y2 = rx_gsbbox.cap(4).toDouble();
1372 static bool parse_bbox_values(
const QString& str, klfbbox *bbox)
1375 QRegExp rx_bbvalues(
"" D_RX
"\\s+" D_RX
"\\s+" D_RX
"\\s+" D_RX
"");
1376 int i = rx_bbvalues.indexIn(str);
1380 bbox->x1 = rx_bbvalues.cap(1).toDouble();
1381 bbox->y1 = rx_bbvalues.cap(2).toDouble();
1382 bbox->x2 = rx_bbvalues.cap(3).toDouble();
1383 bbox->y2 = rx_bbvalues.cap(4).toDouble();
1387 static bool s_starts_with(
const char * x,
int len_x,
const char *test,
int len_test)
1389 if (len_x < len_test)
1391 return !strncmp(x, test, len_test);
1398 static const char * hibboxtag =
"%%HiResBoundingBox:";
1399 static const char * bboxtag =
"%%BoundingBox:";
1400 static const int hibboxtaglen = strlen(hibboxtag);
1401 static const int bboxtaglen = strlen(bboxtag);
1406 bool r = buf.
open(QIODevice::ReadOnly | QIODevice::Text);
1408 klfWarning(
"What's going on!!?! can't open buffer for reading? Will Fail!!!") ;
1412 QObject::tr(
"DVIPS did not provide parsable %%BoundingBox: in its output!",
"KLFBackend");
1414 char linebuffer[512];
1416 bool gotepsbbox =
false;
1417 int still_look_for_hiresbbox_lines = 5;
1418 while ((n = buf.
readLine(linebuffer,
sizeof(linebuffer)-1)) > 0) {
1419 if (gotepsbbox && still_look_for_hiresbbox_lines-- < 0) {
1422 klfDbg(
"stopped looking for hires-bbox.") ;
1425 if (s_starts_with(linebuffer, n, hibboxtag, hibboxtaglen)) {
1435 klfDbg(
"got hires-bbox.") ;
1439 if (s_starts_with(linebuffer, n, bboxtag, bboxtaglen)) {
1447 klfDbg(
"got normal bbox.") ;
1470 static void correct_eps_bbox(
const QByteArray& rawepsdata,
const klfbbox& bbox_corrected,
1471 const klfbbox& bbox_orig,
double vectorscale, QRgb bgcolor,
1476 static const char * bboxdecl =
"%%BoundingBox:";
1477 static int bboxdecl_len = strlen(bboxdecl);
1479 double offx = bbox_corrected.x1 - bbox_orig.x1;
1480 double offy = bbox_corrected.y1 - bbox_orig.y1;
1484 char nl[] =
"\0\0\0";
1485 i = rawepsdata.
indexOf(bboxdecl);
1490 int j = i+bboxdecl_len;
1491 while (j < (
int)rawepsdata.
size() && rawepsdata[j] !=
'\r' && rawepsdata[j] !=
'\n')
1494 if (rawepsdata[j] ==
'\r' && j < (
int)rawepsdata.
size()-1 && rawepsdata[j+1] ==
'\n') {
1495 nl[0] =
'\r', nl[1] =
'\n';
1497 nl[0] = rawepsdata[j];
1501 double dwi = bbox_corrected.x2 * vectorscale;
1502 double dhi = bbox_corrected.y2 * vectorscale;
1503 int wi = (int)(dwi + 0.99999) ;
1504 int hi = (int)(dhi + 0.99999) ;
1508 snprintf(buffer,
sizeof(buffer)-1,
1509 "%%%%BoundingBox: 0 0 %d %d%s" 1510 "%%%%HiResBoundingBox: 0 0 %s %s%s",
1513 buffer_len = strlen(buffer);
1515 char backgroundfillps[1024] =
"";
1516 if (qAlpha(bgcolor) > 0) {
1517 klfDbg(
"we have a bg color, so draw the background. bgcolor="<<
klfFmt(
"%#10x", (uint)bgcolor));
1518 snprintf(backgroundfillps,
sizeof(backgroundfillps)-1,
1527 "%s %s %s setrgbcolor " 1543 snprintf(buffer2,
sizeof(buffer2)-1,
1546 "%%%%PageBoundingBox 0 0 %d %d%s" 1547 "<< /PageSize [%d %d] >> setpagedevice%s" 1564 klfDbg(
"buffer is `"<<buffer<<
"', length="<<buffer_len) ;
1565 klfDbg(
"rawepsdata has length="<<rawepsdata.
size()) ;
1569 neweps = rawepsdata;
1570 neweps.
replace(i, len, buffer);
1572 const char * endsetupstr =
"%%EndSetup";
1573 int i2 = neweps.
indexOf(endsetupstr);
1575 i2 = i + buffer_len;
1577 i2 += strlen(endsetupstr);
1579 neweps.replace(i2, 0, buffer2);
1581 klfDbg(
"neweps has now length="<<neweps.size());
1582 klfDebugf((
"New eps bbox is [0 0 %.6g %.6g] with translate [%.6g %.6g] and scale %.6g.",
1583 dwi, dhi, offx, offy, vectorscale));
1585 *epsdatacorrected = neweps;
1589 static void replace_svg_width_or_height(
QByteArray *svgdata,
const char * attreq,
double val)
1593 int i = svgdataref.
indexOf(attreq);
1595 while (j < (
int)svgdataref.
size() && (!isspace(svgdataref[j]) && svgdataref[j] !=
'>'))
1599 snprintf(buffer,
sizeof(buffer)-1,
"%s'%s'", attreq,
klfFmtDoubleCC(val,
'f', 3));
1601 svgdata->
replace(i, j-i, buffer);
1614 a.fg_color == b.fg_color &&
1650 fmts <<
"PNG" <<
"PS" <<
"EPS" <<
"DVI" <<
"PDF" <<
"SVG";
1675 formats <<
"PS" <<
"EPS";
1701 }
else if (
format ==
"DVI") {
1703 }
else if (
format ==
"PDF") {
1706 "KLFBackend::saveOutputToFile");
1707 qWarning(
"%s", qPrintable(error));
1708 if (errorStringPtr != NULL)
1709 errorStringPtr->operator=(error);
1713 }
else if (
format ==
"SVG") {
1716 "KLFBackend::saveOutputToFile");
1717 qWarning(
"%s", qPrintable(error));
1718 if (errorStringPtr != NULL)
1719 errorStringPtr->operator=(error);
1727 "KLFBackend::saveOutputToDevice").
arg(
format);
1728 qWarning(
"%s", qPrintable(errstr));
1729 if (errorStringPtr != NULL)
1730 *errorStringPtr = errstr;
1753 if (fileName.
isEmpty() || fileName ==
"-") {
1754 if ( ! fout.
open(stdout, QIODevice::WriteOnly) ) {
1756 "KLFBackend::saveOutputToFile").
arg(fout.
error());
1757 qWarning(
"%s", qPrintable(error));
1758 if (errorStringPtr != NULL)
1759 *errorStringPtr = error;
1764 if ( ! fout.
open(QIODevice::WriteOnly) ) {
1766 "KLFBackend::saveOutputToFile")
1768 qWarning(
"%s", qPrintable(error));
1769 if (errorStringPtr != NULL)
1770 *errorStringPtr = error;
1785 for (k = 0; standard_extra_paths[k] != NULL; ++k) {
1786 stdextrapaths.
append(standard_extra_paths[k]);
1812 { & settings->
gsexec, progGS },
1817 klfDbg(
klfFmtCC(
"Our base extra paths are: %s", qPrintable(extra_paths))) ;
1818 QString ourextrapaths = extra_paths;
1819 ourextrapaths.
replace(
"@executable_path", qApp->applicationDirPath());
1820 klfDbg(
klfFmtCC(
"Our extra paths are: %s", qPrintable(ourextrapaths))) ;
1822 for (k = 0; progs_to_find[k].target_setting != NULL; ++k) {
1823 klfDbg(
"Looking for "+progs_to_find[k].prog_names.join(
" or ")) ;
1824 for (j = 0; j < (int)progs_to_find[k].prog_names.size(); ++j) {
1825 klfDbg(
"Testing `"+progs_to_find[k].prog_names[j]+
"'") ;
1826 *progs_to_find[k].target_setting
1827 =
klfSearchPath(progs_to_find[k].prog_names[j], ourextrapaths);
1828 if (!progs_to_find[k].target_setting->isEmpty()) {
1829 klfDbg(
"Found! at `"+ *progs_to_find[k].target_setting+
"'") ;
1837 bool result_failure =
1841 return !result_failure;
1857 initGsInfo(settings, isMainThread);
1858 if (!gsInfo.contains(settings->
gsexec)) {
1859 klfWarning(
"Cannot get 'gs' devices information with "<<(settings->
gsexec+
" --version/--help"));
1861 }
else if (gsInfo[settings->
gsexec].availdevices.contains(
"svg")) {
1876 if (gsfi.
fileName() ==
"mgs.exe") {
1882 klfDbg(
"Adjusting environment for mgs.exe: `MIKTEX_GS_LIB="+mgsenv+
"'") ;
1896 if (gsInfo.contains(settings->
gsexec))
1906 KLFBackendFilterProgram p(
QLatin1String(
"gs (test version)"), settings, isMainThread, settings->
tempdir);
1913 p.setExecEnviron(settings->
execenv);
1916 p.setProcessAppEvents(
false);
1921 bool ok = p.run(
QString(), &ba_gsver);
1924 klfDbg(
"gs version text (untrimmed): "<<gsver) ;
1933 KLFBackendFilterProgram p(
QLatin1String(
"gs (query help)"), settings, isMainThread, settings->
tempdir);
1943 p.setExecEnviron(ee);
1946 p.setProcessAppEvents(
false);
1951 bool ok = p.run(
QString(), &ba_gshelp);
1955 klfDbg(
"gs help text: "<<gshelp) ;
1957 const char * availdevstr =
"Available devices:";
1958 int k = gshelp.
indexOf(availdevstr, 0, Qt::CaseInsensitive) ;
1960 klfWarning(
"Unable to parse gs' available devices.") ;
1962 k += strlen(availdevstr);
1970 klfDbg(
"Detected devices: "<<availdevices) ;
1977 QRegExp rx_version(
"^(\\d+)\\.(\\d+)");
1978 int foundver = rx_version.indexIn(gsver);
1979 if (foundver >= 0) {
1980 gsvermaj = rx_version.cap(1).toInt();
1981 gsvermin = rx_version.cap(2).toInt();
1984 klfDbg(
"GS Version: "<<gsver<<
" = "<<gsvermaj<<
"."<<gsvermin);
1988 i.version_maj = gsvermaj;
1989 i.version_min = gsvermin;
1991 i.availdevices = availdevices;
1993 gsInfo[settings->
gsexec] = i;
2003 env <<
"KLF_SETTINGS_BORDEROFFSET=" +
klfFmt(
"%.3g,%.3g,%.3g,%.3g pt", settings.
tborderoffset,
2017 .
arg(qGreen(in.fg_color)).
arg(qBlue(in.fg_color)).
arg(qAlpha(in.fg_color));
2020 env <<
"KLF_INPUT_LATEX=" + in.
latex 2021 <<
"KLF_INPUT_MATHMODE=" + in.
mathmode 2022 <<
"KLF_INPUT_PREAMBLE=" + in.
preamble 2024 <<
"KLF_INPUT_FG_COLOR_WEB=" +
QColor(in.fg_color).
name()
2025 <<
"KLF_INPUT_FG_COLOR_RGBA=" + fgcol
2028 <<
"KLF_INPUT_BG_COLOR_RGBA=" + bgcol
2038 env <<
"KLF_ARG_"+cit.
key() +
"=" + cit.
value();
QStringList skipFormats() const
List of formats that klfbackend should not attempt to generate.
#define KLFERR_LATEX_NORUN
Error while launching the given latex program.
QByteArray fromUnicode(const QString &str) const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
#define KLFERR_PROGERR_GSPDF
gs exited with non-zero status while producing PDF
bool loadFromData(const uchar *data, int len, const char *format)
QString toNativeSeparators(const QString &pathName)
Defines the KLFBlockProcess class.
bool load(QIODevice *device, const char *format)
#define KLFERR_GSPDF_OUTPUTREADFAIL
Failed to read PDF file produced by 'gs'.
KLF_EXPORT QByteArray klfSaveVariantToText(const QVariant &value, bool saveListAndMapsAsXML, QByteArray *savedType, QByteArray *savedListOrMapType)
#define KLFERR_PROGERR_LATEX
latex exited with a non-zero status
bool contains(const Key &key) const
#define KLFERR_USERSCRIPT_NORUN
Failed to execute user wrapper script.
QString fromNativeSeparators(const QString &pathName)
#define KLFERR_GSSVG_NOSVG
This version of gs cannot produce SVG.
QByteArray trimmed() const
#define KLFERR_TEXWRITEFAIL
Error while opening .tex file for writing.
KLF_EXPORT void klfSetEnvironmentVariable(QStringList *env, const QString &var, const QString &value)
#define KLFERR_GSPOSTPROC_NOOUTPUT
Program 'gs' didn't provide any data after post-processing EPS file.
#define KLFERR_MISSINGMATHMODETHREEDOTS
The "..." is missing in math mode string.
bool save(const QString &fileName, const char *format, int quality) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
KLF_EXPORT QByteArray klfFmt(const char *fmt, va_list pp)
#define KLFERR_GSPNG_NOOUTPUT
No PNG file appeared after running 'gs'.
void klfMergeEnvironment(QStringList *env, const QStringList &addvars, const QStringList &pathvars, uint actions)
#define KLFERR_PROGERR_GSBBOX
gs exited with non-zero status while calculating bbox of EPS file generated by dvips ...
#define KLFERR_GSPNG_OUTPUTREADFAIL
Failed to read PNG file produced by 'gs'.
#define KLFERR_GSSVG_NOOUTPUT
No SVG file appeared after running 'gs'.
#define KLFERR_DVIPS_NORUN
Error while launching the given dvips program.
static bool detectSettings(klfSettings *settings, const QString &extraPath=QString(), bool isMainThread=true)
Detects the system settings and stores the guessed values in settings.
const_iterator constBegin() const
QByteArray pdfdata
data for a pdf file
QByteArray toUpper() const
bool contains(const QString &str, Qt::CaseSensitivity cs) const
void setData(const QByteArray &data)
#define KLFERR_LATEX_OUTPUTREADFAIL
Error while opening .dvi file for reading.
KLF_EXPORT QString klfSearchPath(const QString &programName, const QString &extra_path)
void setFileName(const QString &name)
#define klfDbg(streamableItems)
#define KLF_DEBUG_BLOCK(msg)
double width_pt
Width in points of the resulting equation.
#define KLFERR_NOERROR
No Error.
QString join(const QString &separator) const
#define KLFERR_NOLATEXPROG
obsolete, same as KLFERR_LATEX_NORUN
#define KLFERR_GSPDF_NORUN
Program 'gs' couldn't be executed to generate PDF.
QString text(const QString &key) const
static klfOutput getLatexFormula(const klfInput &in, const klfSettings &settings, bool isMainThread=true)
The function that processes everything.
int status
A code describing the status of the request.
KLF_EXPORT QByteArray klfEscapedToData(const QByteArray &data, char escapechar)
QString tr(const char *sourceText, const char *disambiguation, int n)
klfSettings settings
The settings that this output was generated with.
QStringList spitsOut() const
List of formats that this script will generate.
QString value(const QString &name, const QString &defaultValue) const
#define KLF_ASSERT_NOT_NULL(ptr, msg, failaction)
#define KLFERR_DVIPS_NONORMALEXIT
dvips program did not exit properly (program killed) (see also KLFERR_PROGERR_DVIPS) ...
QByteArray pngdata
the data for a png file (re-processed with meta information)
TemplateGenerator * templateGenerator
QByteArray pngdata_raw
the data for a png file (exact gs output content)
KLF_EXPORT int klfVersionCompare(const QString &v1, const QString &v2)
void setText(const QString &key, const QString &text)
QString userScriptPath() const
e.g. "/path/to/klffeynmf.klfuserscript"
int indexOf(char ch, int from) const
klfInput input
The input parameters used to generate this output.
QString number(int n, int base)
void append(const T &value)
QString fromUtf8(const char *str, int size)
static bool saveOutputToDevice(const klfOutput &output, QIODevice *device, const QString &format=QString("PNG"), QString *errorString=NULL)
Saves the given output into the given device.
#define klfWarning(streamableItems)
#define KLFERR_GSPDF_NOOUTPUT
No PDF file appeared after running 'gs'.
QString absoluteFilePath() const
virtual QString generateTemplate(const klfInput &input, const klfSettings &settings)
const_iterator constEnd() const
#define KLFERR_PDFMARKSWRITEFAIL
Error while opening pdfmarks file for writing.
#define KLFERR_TEMPDIR_FAIL
Failed to create the temporary directory.
QByteArray & replace(int pos, int len, const char *after)
#define KLFERR_GSBBOX_NOOUTPUT
Program 'gs' didn't provide any output.
QVariantMap klfMapToVariantMap(const QMap< QString, T > &map)
#define KLFERR_GSPOSTPROC_NOOUTLINEFONTS
'gs' cannot outline fonts: need version <= 9.07 (pswrite -dNOCACHE) or >= 9.15 (ps2write -dNoOutputFo...
#define KLFERR_LATEX_NONORMALEXIT
latex program did not exit properly (program killed) (see also KLFERR_PROGERR_LATEX) ...
QByteArray epsdata
data for an (eps-)postscript file.
#define KLFERR_GSPNG_NORUN
Program 'gs' couldn't be executed to generate PNG.
virtual bool open(OpenMode flags)
#define KLFERR_GSBBOX_NORUN
Program 'gs' cannot be executed to calculate bounding box.
virtual bool open(OpenMode mode)
QByteArray epsdata_raw
data for an (eps-)postscript file.
double height_pt
Width in points of the resulting equation.
#define KLF_DEBUG_TIME_BLOCK(msg)
static QStringList availableSaveFormats(const klfOutput *output=NULL)
Get a list of available output formats.
QByteArray & append(char ch)
#define KLFERR_PROGERR_GSPNG
gs exited with a non-zero status while producing PNG
#define KLFERR_PROGERR_GSPOSTPROC
gs exited with non-zero status while post-processing EPS file (page size, font outlines) ...
#define klfDebugf(arglist)
bool contains(QChar ch, Qt::CaseSensitivity cs) const
#define KLFERR_PROGERR_USERSCRIPT
user wrapper script exited with non-zero status
#define KLFERR_DVIPS_OUTPUTNOBBOX
Error while reading/parsing %BoundingBox: in dvips output.
#define KLFERR_PROGERR_DVIPS
dvips exited with a non-zero status
bool contains(const T &value) const
Definition of class KLFBackend.
const Key key(const T &value, const Key &defaultKey) const
#define KLFERR_NOGSVERSION
Failed to query gs version.
QString & replace(int position, int n, QChar after)
QByteArray toLatin1() const
QString mid(int position, int n) const
bool remove(const T &value)
QImage result
The actual resulting image.
#define KLFERR_GSSVG_OUTPUTREADFAIL
Failed to read SVG file produced by 'gs'.
#define KLFERR_PROGERR_GSSVG
gs exited with non-zero status while producing SVG
#define KLFERR_MISSINGLATEXFORMULA
No LaTeX formula is specified (empty string)
#define KLFERR_NODVIPSPROG
obsolete, same as KLFERR_DVIPS_NORUN
KLF_EXPORT bool operator==(const KLFBackend::klfInput &a, const KLFBackend::klfInput &b)
QString errorstr
An explicit error string.
QTextCodec * codecForName(const QByteArray &name)
KLFBackend::getLatexFormula() result.
QSet< T > fromList(const QList< T > &list)
#define KLFERR_DVIPS_NOOUTPUT
no .eps file appeared after running dvips program
#define KLFERR_GSPDF_NONORMALEXIT
Program 'gs' didn't exit noramally (crashed) while generating PDF (see also KLFERR_PROGERR_GSPDF) ...
#define KLFERR_NOGSPROG
obsolete, same as KLFERR_GSPNG_NORUN
qint64 write(const char *data, qint64 maxSize)
QString fromLatin1(const char *str, int size)
#define KLFERR_GSPOSTPROC_NONORMALEXIT
Program 'gs' crashed while post-processing EPS file (see also KLFERR_PROGERR_GSPOSTPROC) ...
#define KLFERR_GSSVG_NONORMALEXIT
Program 'gs' didn't exit noramally (crashed) while generating SVG (see also KLFERR_PROGERR_GSSVG) ...
int indexOf(const QRegExp &rx, int from) const
#define KLFERR_LATEX_NOOUTPUT
No .dvi file appeared after runnig latex program.
KLF_EXPORT QByteArray klfDataToEscaped(const QByteArray &value_ba, char escapechar)
static bool detectOptionSettings(klfSettings *settings, bool isMainThread=true)
Detects additional options (e.g. klfSettings::wantSVG) that depend on specific program versions...
QProcessEnvironment systemEnvironment()
QByteArray dvidata
The DVI file data outputted by latex executable.
QByteArray epsdata_bbox
data for an (eps-)postscript file.
KLF_EXPORT bool klf_detect_execenv(KLFBackend::klfSettings *settings)
detects any additional settings to environment variables
#define KLF_ASSERT_CONDITION(expr, msg, failaction)
#define KLFERR_GSPOSTPROC_OUTPUTREADFAIL
Couldn't read output provided by 'gs' program after post-processing EPS file.
#define KLFERR_GSBBOX_NOBBOX
Program 'gs' calculating bbox didn't provide parsable output.
#define KLFERR_GSPOSTPROC_NORUN
Program 'gs' cannot be executed to post-process EPS file (page size, outline fonts) ...
QByteArray svgdata
data for a SVG file, if ghostscript supports SVG
QString absolutePath() const
#define KLFERR_GSSVG_NORUN
Program 'gs' couldn't be executed to generate SVG.
#define KLFERR_GSBBOX_NONORMALEXIT
Program 'gs' crashed while calculating bbox (see also KLFERR_PROGERR_GSBBOX)
#define KLFERR_GSPNG_NONORMALEXIT
Program 'gs' didn't exit noramally (crashed) while generating PNG (see also KLFERR_PROGERR_GSPNG) ...
static bool saveOutputToFile(const klfOutput &output, const QString &fileName, const QString &format=QString(), QString *errorString=NULL)
Save the output to image file.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
KLF_EXPORT QStringList klfCurrentEnvironment()
#define KLFERR_DVIPS_OUTPUTREADFAIL
Error while opening .eps file for reading.
General settings for KLFBackend::getLatexFormula()
qint64 readLine(char *data, qint64 maxSize)
const T value(const Key &key, const T &defaultValue) const
int remove(const Key &key)
QByteArray toUtf8() const