00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <sys/time.h>
00027
00028 #include <qapplication.h>
00029 #include <qregexp.h>
00030 #include <qfile.h>
00031 #include <qdatetime.h>
00032 #include <qtextstream.h>
00033 #include <qbuffer.h>
00034 #include <qdir.h>
00035
00036
00037 #include "klfblockprocess.h"
00038 #include "klfbackend.h"
00039
00040
00041 #include "klfqt34common.h"
00042
00043
00074
00075
00076 #ifdef KLF_EXTRA_SEARCH_PATHS
00077 # define EXTRA_PATHS_PRE KLF_EXTRA_SEARCH_PATHS ,
00078 # define EXTRA_PATHS KLF_EXTRA_SEARCH_PATHS
00079 #else
00080 # define EXTRA_PATHS_PRE
00081 # define EXTRA_PATHS
00082 #endif
00083
00084
00085 #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
00086 QStringList progLATEX = QStringList() << "latex.exe";
00087 QStringList progDVIPS = QStringList() << "dvips.exe";
00088 QStringList progGS = QStringList() << "gswin32c.exe" << "mgs.exe";
00089 QStringList progEPSTOPDF = QStringList() << "epstopdf.exe";
00090 static const char * standard_extra_paths[] = {
00091 EXTRA_PATHS_PRE
00092 "C:\\Program Files\\MiKTeX*\\miktex\\bin",
00093 "C:\\Program Files\\gs\\gs*\\bin",
00094 NULL
00095 };
00096 #elif defined(Q_WS_MAC)
00097 QStringList progLATEX = QStringList() << "latex";
00098 QStringList progDVIPS = QStringList() << "dvips";
00099 QStringList progGS = QStringList() << "gs";
00100 QStringList progEPSTOPDF = QStringList() << "epstopdf";
00101 static const char * standard_extra_paths[] = {
00102 EXTRA_PATHS_PRE
00103 "/usr/texbin:/usr/local/bin:/sw/bin:/sw/usr/bin",
00104 NULL
00105 };
00106 #else
00107 QStringList progLATEX = QStringList() << "latex";
00108 QStringList progDVIPS = QStringList() << "dvips";
00109 QStringList progGS = QStringList() << "gs";
00110 QStringList progEPSTOPDF = QStringList() << "epstopdf";
00111 static const char * standard_extra_paths[] = {
00112 EXTRA_PATHS_PRE
00113 NULL
00114 };
00115 #endif
00116
00117
00118
00119
00120
00121 KLFBackend::KLFBackend()
00122 {
00123 }
00124
00125
00126
00127 QString progErrorMsg(QString progname, int exitstatus, QString stderrstr, QString stdoutstr)
00128 {
00129 QString stdouthtml = stdoutstr;
00130 QString stderrhtml = stderrstr;
00131 stdouthtml.replace("&", "&");
00132 stdouthtml.replace("<", "<");
00133 stdouthtml.replace(">", ">");
00134 stderrhtml.replace("&", "&");
00135 stderrhtml.replace("<", "<");
00136 stderrhtml.replace(">", ">");
00137
00138 if (stderrstr.isEmpty() && stdoutstr.isEmpty())
00139 return QObject::tr("<p><b>%1</b> reported an error (exit status %2). No Output was generated.</p>",
00140 "KLFBackend")
00141 .arg(progname).arg(exitstatus);
00142 if (stderrstr.isEmpty())
00143 return
00144 QObject::tr("<p><b>%1</b> reported an error (exit status %2). Here is full stdout output:</p>\n"
00145 "<pre>\n%3</pre>", "KLFBackend")
00146 .arg(progname).arg(exitstatus).arg(stdouthtml);
00147 if (stdoutstr.isEmpty())
00148 return
00149 QObject::tr("<p><b>%1</b> reported an error (exit status %2). Here is full stderr output:</p>\n"
00150 "<pre>\n%3</pre>", "KLFBackend")
00151 .arg(progname).arg(exitstatus).arg(stderrhtml);
00152
00153 return QObject::tr("<p><b>%1</b> reported an error (exit status %2). Here is full stderr output:</p>\n"
00154 "<pre>\n%3</pre><p>And here is full stdout output:</p><pre>\n%4</pre>", "KLFBackend")
00155 .arg(progname).arg(exitstatus).arg(stderrhtml).arg(stdouthtml);
00156 }
00157
00158
00159
00160
00161 struct cleanup_caller {
00162 QString tempfname;
00163 cleanup_caller(QString fn) : tempfname(fn) { }
00164 ~cleanup_caller() {
00165 KLFBackend::cleanup(tempfname);
00166 }
00167 };
00168
00169 QString __klf_expand_env_vars(const QString& envexpr)
00170 {
00171 QString s = envexpr;
00172 QRegExp rx("\\$(?:(\\$|(?:[A-Za-z0-9_]+))|\\{([A-Za-z0-9_]+)\\})");
00173 int i = 0;
00174 while ( (i = rx.rx_indexin_i(s, i)) != -1 ) {
00175
00176 QString envvarname = rx.cap(1);
00177 if (envvarname.isEmpty() || envvarname == QLatin1String("$")) {
00178
00179 s.replace(i, rx.matchedLength(), QLatin1String("$"));
00180 i += 1;
00181 continue;
00182 }
00183 const char *svalue = getenv(qPrintable(envvarname));
00184 QString qsvalue = (svalue != NULL) ? QString::fromLocal8Bit(svalue) : QString();
00185 s.replace(i, rx.matchedLength(), qsvalue);
00186 i += qsvalue.length();
00187 }
00188
00189 return s;
00190 }
00191
00192 void __klf_append_replace_env_var(QStringList *list, const QString& var, const QString& line)
00193 {
00194
00195 int k;
00196 for (k = 0; k < (int)list->size(); ++k) {
00197 if (list->operator[](k).startsWith(var+QString("="))) {
00198 list->operator[](k) = line;
00199 return;
00200 }
00201 }
00202
00203 list->append(line);
00204 }
00205
00206
00207
00208 KLFBackend::klfOutput KLFBackend::getLatexFormula(const klfInput& in, const klfSettings& settings)
00209 {
00210
00211 QMutexLocker mutexlocker(&__mutex);
00212
00213 int k;
00214
00215 qDebug("%s: %s: KLFBackend::getLatexFormula() called. latex=%s", KLF_FUNC_NAME, KLF_SHORT_TIME,
00216 qPrintable(in.latex));
00217
00218
00219 QStringList execenv = klf_cur_environ();
00220 for (k = 0; k < (int)settings.execenv.size(); ++k) {
00221 int eqpos = settings.execenv[k].s_indexOf(QChar('='));
00222 if (eqpos == -1) {
00223 qWarning("%s: badly formed environment definition in `environ': %s", KLF_FUNC_NAME,
00224 qPrintable(settings.execenv[k]));
00225 continue;
00226 }
00227 QString varname = settings.execenv[k].mid(0, eqpos);
00228 QString newenvdef = __klf_expand_env_vars(settings.execenv[k]);
00229 __klf_append_replace_env_var(&execenv, varname, newenvdef);
00230 }
00231
00232 klfDbg("execution environment for sub-processes:\n"+execenv.join("\n")) ;
00233
00234 klfOutput res;
00235 res.status = KLFERR_NOERROR;
00236 res.errorstr = QString();
00237 res.result = QImage();
00238 res.pngdata_raw = QByteArray();
00239 res.pngdata = QByteArray();
00240 res.epsdata = QByteArray();
00241 res.pdfdata = QByteArray();
00242 res.input = in;
00243 res.settings = settings;
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 QString tempfname = settings.tempdir + "/klatexformulatmp" KLF_VERSION_STRING "-"
00257 + QDateTime::currentDateTime().toString("hh-mm-ss");
00258
00259 QString fnTex = tempfname + ".tex";
00260 QString fnDvi = tempfname + ".dvi";
00261 QString fnRawEps = tempfname + "-raw.eps";
00262 QString fnBBCorrEps = tempfname + "-bbcorr.eps";
00263 QString fnOutlFontsEps = tempfname + "-outlfonts.eps";
00264 QString fnFinalEps = settings.outlineFonts ? fnOutlFontsEps : fnBBCorrEps;
00265 QString fnPng = tempfname + ".png";
00266 QString fnPdf = tempfname + ".pdf";
00267
00268
00269
00270 cleanup_caller cleanupcallerinstance(tempfname);
00271
00272 #ifdef KLFBACKEND_QT4
00273 QString latexsimplified = in.latex.s_trimmed();
00274 #else
00275 QString latexsimplified = in.latex.stripWhiteSpace();
00276 #endif
00277 if (latexsimplified.isEmpty()) {
00278 res.errorstr = QObject::tr("You must specify a LaTeX formula!", "KLFBackend");
00279 res.status = KLFERR_MISSINGLATEXFORMULA;
00280 return res;
00281 }
00282
00283 QString latexin;
00284 if (!in.bypassTemplate) {
00285 if (in.mathmode.contains("...") == 0) {
00286 res.status = KLFERR_MISSINGMATHMODETHREEDOTS;
00287 res.errorstr = QObject::tr("The math mode string doesn't contain '...'!", "KLFBackend");
00288 return res;
00289 }
00290 latexin = in.mathmode;
00291 latexin.replace("...", in.latex);
00292 }
00293
00294 {
00295 QFile file(fnTex);
00296 bool r = file.open(dev_WRITEONLY);
00297 if ( ! r ) {
00298 res.status = KLFERR_TEXWRITEFAIL;
00299 res.errorstr = QObject::tr("Can't open file for writing: '%1'!", "KLFBackend")
00300 .arg(fnTex);
00301 return res;
00302 }
00303 QTextStream stream(&file);
00304 if (!in.bypassTemplate) {
00305 stream << "\\documentclass{article}\n"
00306 << "\\usepackage[dvips]{color}\n"
00307 << in.preamble << "\n"
00308 << "\\begin{document}\n"
00309 << "\\thispagestyle{empty}\n"
00310 << QString("\\definecolor{klffgcolor}{rgb}{%1,%2,%3}\n").arg(qRed(in.fg_color)/255.0)
00311 .arg(qGreen(in.fg_color)/255.0).arg(qBlue(in.fg_color)/255.0)
00312 << QString("\\definecolor{klfbgcolor}{rgb}{%1,%2,%3}\n").arg(qRed(in.bg_color)/255.0)
00313 .arg(qGreen(in.bg_color)/255.0).arg(qBlue(in.bg_color)/255.0)
00314 << ( (qAlpha(in.bg_color)>0) ? "\\pagecolor{klfbgcolor}\n" : "" )
00315 << "{\\color{klffgcolor} " << latexin << " }\n"
00316 << "\\end{document}\n";
00317 } else {
00318 stream << in.latex;
00319 }
00320 }
00321
00322 {
00323
00324 KLFBlockProcess proc;
00325 QStringList args;
00326
00327 proc.setWorkingDirectory(settings.tempdir);
00328
00329 args << settings.latexexec << dir_native_separators(fnTex);
00330
00331 qDebug("%s: %s: about to exec latex...", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00332 bool r = proc.startProcess(args, execenv);
00333 qDebug("%s: %s: latex returned.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00334
00335 if (!r) {
00336 res.status = KLFERR_NOLATEXPROG;
00337 res.errorstr = QObject::tr("Unable to start Latex program %1!", "KLFBackend")
00338 .arg(settings.latexexec);
00339 return res;
00340 }
00341 if (!proc.processNormalExit()) {
00342 res.status = KLFERR_LATEXNONORMALEXIT;
00343 res.errorstr = QObject::tr("Latex was killed!", "KLFBackend");
00344 return res;
00345 }
00346 if (proc.processExitStatus() != 0) {
00347 res.status = KLFERR_PROGERR_LATEX;
00348 res.errorstr = progErrorMsg("LaTeX", proc.processExitStatus(), proc.readStderrString(),
00349 proc.readStdoutString());
00350 return res;
00351 }
00352
00353 if (!QFile::exists(fnDvi)) {
00354 res.status = KLFERR_NODVIFILE;
00355 res.errorstr = QObject::tr("DVI file didn't appear after having called Latex!", "KLFBackend");
00356 return res;
00357 }
00358
00359 }
00360
00361 {
00362
00363 KLFBlockProcess proc;
00364 QStringList args;
00365 args << settings.dvipsexec << "-E" << dir_native_separators(fnDvi)
00366 << "-o" << dir_native_separators(fnRawEps);
00367
00368 qDebug("%s: %s: about to dvips... %s", KLF_FUNC_NAME, KLF_SHORT_TIME, qPrintable(args.join(" "))) ;
00369 bool r = proc.startProcess(args, execenv);
00370 qDebug("%s: %s: dvips returned.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00371
00372 if ( ! r ) {
00373 res.status = KLFERR_NODVIPSPROG;
00374 res.errorstr = QObject::tr("Unable to start dvips!\n", "KLFBackend");
00375 return res;
00376 }
00377 if ( !proc.processNormalExit() ) {
00378 res.status = KLFERR_DVIPSNONORMALEXIT;
00379 res.errorstr = QObject::tr("Dvips was mercilessly killed!\n", "KLFBackend");
00380 return res;
00381 }
00382 if ( proc.processExitStatus() != 0) {
00383 res.status = KLFERR_PROGERR_DVIPS;
00384 res.errorstr = progErrorMsg("dvips", proc.processExitStatus(), proc.readStderrString(),
00385 proc.readStdoutString());
00386 return res;
00387 }
00388 if (!QFile::exists(fnRawEps)) {
00389 res.status = KLFERR_NOEPSFILE;
00390 res.errorstr = QObject::tr("EPS file didn't appear after dvips call!\n", "KLFBackend");
00391 return res;
00392 }
00393
00394
00395
00396 QFile epsfile(fnRawEps);
00397 r = epsfile.open(dev_READONLY);
00398 if ( ! r ) {
00399 res.status = KLFERR_EPSREADFAIL;
00400 res.errorstr = QObject::tr("Can't read file '%1'!\n", "KLFBackend").arg(fnRawEps);
00401 return res;
00402 }
00405 QByteArray epscontent = epsfile.readAll();
00406 #ifdef KLFBACKEND_QT4
00407 QByteArray epscontent_s = epscontent;
00408 int i = epscontent_s.indexOf("%%BoundingBox: ");
00409 #else
00410 QCString epscontent_s(epscontent.data(), epscontent.size());
00411 int i = epscontent_s.find("%%BoundingBox: ");
00412 #endif
00413
00414 if ( i == -1 ) {
00415 res.status = KLFERR_NOEPSBBOX;
00416 res.errorstr = QObject::tr("File '%1' does not contain line \"%%BoundingBox: ... \" !",
00417 "KLFBackend").arg(fnRawEps);
00418 return res;
00419 }
00420 int ax, ay, bx, by;
00421 char temp[250];
00422 const int k = i;
00423 i += strlen("%%BoundingBox:");
00424 int n = sscanf(epscontent_s.data()+i, "%d %d %d %d", &ax, &ay, &bx, &by);
00425 if ( n != 4 ) {
00426 res.status = KLFERR_BADEPSBBOX;
00427 res.errorstr = QObject::tr("file %1: Line %%BoundingBox: can't read values!\n", "KLFBackend")
00428 .arg(fnRawEps);
00429 return res;
00430 }
00431
00432
00433 sprintf(temp, "%%%%BoundingBox: %d %d %d %d",
00434 (int)(ax-settings.lborderoffset+0.5),
00435 (int)(ay-settings.bborderoffset+0.5),
00436 (int)(bx+settings.rborderoffset+0.5),
00437 (int)(by+settings.tborderoffset+0.5));
00438 QString chunk = QString::fromLocal8Bit(epscontent_s.data()+k);
00439 QRegExp rx("^%%BoundingBox: [0-9]+ [0-9]+ [0-9]+ [0-9]+");
00440 rx.rx_indexin(chunk);
00441 int l = rx.matchedLength();
00442 epscontent_s.replace(k, l, temp);
00443
00444
00445 QFile epsgoodfile(fnBBCorrEps);
00446 r = epsgoodfile.open(dev_WRITEONLY);
00447 if ( ! r ) {
00448 res.status = KLFERR_EPSWRITEFAIL;
00449 res.errorstr = QObject::tr("Can't write to file '%1'!\n", "KLFBackend")
00450 .arg(fnBBCorrEps);
00451 return res;
00452 }
00453 epsgoodfile.dev_write(epscontent_s);
00454
00455 if ( ! settings.outlineFonts ) {
00456 res.epsdata.ba_assign(epscontent_s);
00457 }
00458
00459
00460 qDebug("%s: %s: eps bbox set.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00461
00462 }
00463
00464 if (settings.outlineFonts) {
00465
00466 KLFBlockProcess proc;
00467 QStringList args;
00468 args << settings.gsexec << "-dNOCACHE" << "-dNOPAUSE" << "-dSAFER" << "-dEPSCrop"
00469 << "-sDEVICE=pswrite" << "-sOutputFile="+dir_native_separators(fnOutlFontsEps)
00470 << "-q" << "-dBATCH" << dir_native_separators(fnBBCorrEps);
00471
00472 qDebug("%s: %s: about to gs (for outline fonts)...\n%s", KLF_FUNC_NAME, KLF_SHORT_TIME,
00473 qPrintable(args.join(" ")));
00474 bool r = proc.startProcess(args, execenv);
00475 qDebug("%s: %s: gs returned (for outline fonts).", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00476
00477 if ( ! r ) {
00478 res.status = KLFERR_NOGSPROG;
00479 res.errorstr = QObject::tr("Unable to start gs!\n", "KLFBackend");
00480 return res;
00481 }
00482 if ( !proc.processNormalExit() ) {
00483 res.status = KLFERR_GSNONORMALEXIT;
00484 res.errorstr = QObject::tr("gs died abnormally!\n", "KLFBackend");
00485 return res;
00486 }
00487 if ( proc.processExitStatus() != 0) {
00488 res.status = KLFERR_PROGERR_GS_OF;
00489 res.errorstr = progErrorMsg("gs", proc.processExitStatus(), proc.readStderrString(),
00490 proc.readStdoutString());
00491 return res;
00492 }
00493 if (!QFile::exists(fnOutlFontsEps)) {
00494 res.status = KLFERR_NOEPSFILE_OF;
00495 res.errorstr = QObject::tr("EPS file (with outlined fonts) didn't appear after call to gs!\n",
00496 "KLFBackend");
00497 return res;
00498 }
00499
00500
00501 QFile ofepsfile(fnOutlFontsEps);
00502 r = ofepsfile.open(dev_READONLY);
00503 if ( ! r ) {
00504 res.status = KLFERR_EPSREADFAIL_OF;
00505 res.errorstr = QObject::tr("Unable to read file %1!\n", "KLFBackend")
00506 .arg(fnOutlFontsEps);
00507 return res;
00508 }
00509 res.epsdata = ofepsfile.readAll();
00510 ofepsfile.close();
00511
00512 }
00513
00514 {
00515 KLFBlockProcess proc;
00516 QStringList args;
00517 args << settings.gsexec << "-dNOPAUSE" << "-dSAFER" << "-dEPSCrop"
00518 << "-r"+QString::number(in.dpi) << "-dTextAlphaBits=4"
00519 << "-dGraphicsAlphaBits=4";
00520 if (qAlpha(in.bg_color) > 0) {
00521 args << "-sDEVICE=png16m";
00522 } else {
00523 args << "-sDEVICE=pngalpha";
00524 }
00525 args << "-sOutputFile="+dir_native_separators(fnPng) << "-q" << "-dBATCH"
00526 << dir_native_separators(fnFinalEps);
00527
00528 qDebug("%s: %s: about to gs... %s", KLF_FUNC_NAME, KLF_SHORT_TIME, qPrintable(args.join(" "))) ;
00529 bool r = proc.startProcess(args, execenv);
00530 qDebug("%s: %s: gs returned.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00531
00532 if ( ! r ) {
00533 res.status = KLFERR_NOGSPROG;
00534 res.errorstr = QObject::tr("Unable to start gs!\n", "KLFBackend");
00535 return res;
00536 }
00537 if ( !proc.processNormalExit() ) {
00538 res.status = KLFERR_GSNONORMALEXIT;
00539 res.errorstr = QObject::tr("gs died abnormally!\n", "KLFBackend");
00540 return res;
00541 }
00542 if ( proc.processExitStatus() != 0) {
00543 res.status = KLFERR_PROGERR_GS;
00544 res.errorstr = progErrorMsg("gs", proc.processExitStatus(), proc.readStderrString(),
00545 proc.readStdoutString());
00546 return res;
00547 }
00548 if (!QFile::exists(fnPng)) {
00549 res.status = KLFERR_NOPNGFILE;
00550 res.errorstr = QObject::tr("PNG file didn't appear after call to gs!\n", "KLFBackend");
00551 return res;
00552 }
00553
00554
00555 QFile pngfile(fnPng);
00556 r = pngfile.open(dev_READONLY);
00557 if ( ! r ) {
00558 res.status = KLFERR_PNGREADFAIL;
00559 res.errorstr = QObject::tr("Unable to read file %1!\n", "KLFBackend")
00560 .arg(fnPng);
00561 return res;
00562 }
00563 res.pngdata_raw = pngfile.readAll();
00564 pngfile.close();
00565
00566 res.result.loadFromData(res.pngdata_raw, "PNG");
00567
00568
00569 res.result.img_settext("AppVersion", QString::fromLatin1("KLatexFormula " KLF_VERSION_STRING));
00570 res.result.img_settext("Application",
00571 QObject::tr("Created with KLatexFormula version %1", "KLFBackend::saveOutputToFile"));
00572 res.result.img_settext("Software", QString::fromLatin1("KLatexFormula " KLF_VERSION_STRING));
00573 res.result.img_settext("InputLatex", in.latex);
00574 res.result.img_settext("InputMathMode", in.mathmode);
00575 res.result.img_settext("InputPreamble", in.preamble);
00576 res.result.img_settext("InputFgColor", QString("rgb(%1, %2, %3)").arg(qRed(in.fg_color))
00577 .arg(qGreen(in.fg_color)).arg(qBlue(in.fg_color)));
00578 res.result.img_settext("InputBgColor", QString("rgba(%1, %2, %3, %4)").arg(qRed(in.bg_color))
00579 .arg(qGreen(in.bg_color)).arg(qBlue(in.bg_color))
00580 .arg(qAlpha(in.bg_color)));
00581 res.result.img_settext("InputDPI", QString::number(in.dpi));
00582 res.result.img_settext("SettingsTBorderOffset", QString::number(settings.tborderoffset));
00583 res.result.img_settext("SettingsRBorderOffset", QString::number(settings.rborderoffset));
00584 res.result.img_settext("SettingsBBorderOffset", QString::number(settings.bborderoffset));
00585 res.result.img_settext("SettingsLBorderOffset", QString::number(settings.lborderoffset));
00586 res.result.img_settext("SettingsOutlineFonts", settings.outlineFonts?QString("true"):QString("false"));
00587 }
00588
00589 {
00590 #ifdef KLFBACKEND_QT4
00591 QBuffer buf(&res.pngdata);
00592 #else
00593 QBuffer buf(res.pngdata);
00594 #endif
00595 buf.open(dev_WRITEONLY);
00596 bool r = res.result.save(&buf, "PNG");
00597 if (!r) {
00598 qWarning("%s: Error: Can't save \"final\" PNG data.", KLF_FUNC_NAME);
00599 res.pngdata.ba_assign(res.pngdata_raw);
00600 }
00601 }
00602
00603 if (!settings.epstopdfexec.isEmpty()) {
00604
00605 KLFBlockProcess proc;
00606 QStringList args;
00607 args << settings.epstopdfexec << dir_native_separators(fnFinalEps)
00608 << ("--outfile="+dir_native_separators(fnPdf));
00609
00610 qDebug("%s: %s: about to epstopdf... %s", KLF_FUNC_NAME, KLF_SHORT_TIME, qPrintable(args.join(" "))) ;
00611 bool r = proc.startProcess(args, execenv);
00612 qDebug("%s: %s: epstopdf returned.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00613
00614 if ( ! r ) {
00615 res.status = KLFERR_NOEPSTOPDFPROG;
00616 res.errorstr = QObject::tr("Unable to start epstopdf!\n", "KLFBackend");
00617 return res;
00618 }
00619 if ( !proc.processNormalExit() ) {
00620 res.status = KLFERR_EPSTOPDFNONORMALEXIT;
00621 res.errorstr = QObject::tr("epstopdf died nastily!\n", "KLFBackend");
00622 return res;
00623 }
00624 if ( proc.processExitStatus() != 0) {
00625 res.status = KLFERR_PROGERR_EPSTOPDF;
00626 res.errorstr = progErrorMsg("epstopdf", proc.processExitStatus(), proc.readStderrString(),
00627 proc.readStdoutString());
00628 return res;
00629 }
00630 if (!QFile::exists(fnPdf)) {
00631 qDebug("%s: %s: pdf file '%s' didn't appear after epstopdf!", KLF_FUNC_NAME, KLF_SHORT_TIME,
00632 qPrintable(fnPdf));
00633 res.status = KLFERR_NOPDFFILE;
00634 res.errorstr = QObject::tr("PDF file didn't appear after call to epstopdf!\n", "KLFBackend");
00635 return res;
00636 }
00637
00638
00639 QFile pdffile(fnPdf);
00640 r = pdffile.open(dev_READONLY);
00641 if ( ! r ) {
00642 res.status = KLFERR_PDFREADFAIL;
00643 res.errorstr = QObject::tr("Unable to read file %1!\n", "KLFBackend").arg(fnPdf);
00644 return res;
00645 }
00646 res.pdfdata = pdffile.readAll();
00647
00648 }
00649
00650 qDebug("%s: %s: end of function.", KLF_FUNC_NAME, KLF_SHORT_TIME) ;
00651
00652 return res;
00653 }
00654
00655
00656 void KLFBackend::cleanup(QString tempfname)
00657 {
00658 if (QFile::exists(tempfname+".tex")) QFile::remove(tempfname+".tex");
00659 if (QFile::exists(tempfname+".dvi")) QFile::remove(tempfname+".dvi");
00660 if (QFile::exists(tempfname+".aux")) QFile::remove(tempfname+".aux");
00661 if (QFile::exists(tempfname+".log")) QFile::remove(tempfname+".log");
00662 if (QFile::exists(tempfname+".toc")) QFile::remove(tempfname+".toc");
00663 if (QFile::exists(tempfname+".eps")) QFile::remove(tempfname+".eps");
00664 if (QFile::exists(tempfname+"-good.eps")) QFile::remove(tempfname+"-good.eps");
00665 if (QFile::exists(tempfname+"-raw.eps")) QFile::remove(tempfname+"-raw.eps");
00666 if (QFile::exists(tempfname+"-bbcorr.eps")) QFile::remove(tempfname+"-bbcorr.eps");
00667 if (QFile::exists(tempfname+"-outlfonts.eps")) QFile::remove(tempfname+"-outlfonts.eps");
00668 if (QFile::exists(tempfname+".png")) QFile::remove(tempfname+".png");
00669 if (QFile::exists(tempfname+".pdf")) QFile::remove(tempfname+".pdf");
00670 }
00671
00672
00673 QMutex KLFBackend::__mutex;
00674
00675 KLF_EXPORT bool operator==(const KLFBackend::klfInput& a, const KLFBackend::klfInput& b)
00676 {
00677 return a.latex == b.latex &&
00678 a.mathmode == b.mathmode &&
00679 a.preamble == b.preamble &&
00680 a.fg_color == b.fg_color &&
00681 a.bg_color == b.bg_color &&
00682 a.dpi == b.dpi;
00683 }
00684
00685
00686 bool KLFBackend::saveOutputToDevice(const klfOutput& klfoutput, QIODevice *device,
00687 const QString& fmt, QString *errorStringPtr)
00688 {
00689 QString format = fmt.s_trimmed().s_toUpper();
00690
00691
00692 if (format == "EPS" || format == "PS") {
00693 device->dev_write(klfoutput.epsdata);
00694 } else if (format == "PNG") {
00695 device->dev_write(klfoutput.pngdata);
00696 } else if (format == "PDF") {
00697 if (klfoutput.pdfdata.isEmpty()) {
00698 QString error = QObject::tr("PDF format is not available!\n",
00699 "KLFBackend::saveOutputToFile");
00700 qWarning("%s", qPrintable(error));
00701 if (errorStringPtr != NULL)
00702 errorStringPtr->operator=(error);
00703 return false;
00704 }
00705 device->dev_write(klfoutput.pdfdata);
00706 } else {
00707 bool res = klfoutput.result.save(device, format.s_toLatin1());
00708 if ( ! res ) {
00709 QString errstr = QObject::tr("Unable to save image in format `%1'!",
00710 "KLFBackend::saveOutputToDevice").arg(format);
00711 qWarning("%s", qPrintable(errstr));
00712 if (errorStringPtr != NULL)
00713 *errorStringPtr = errstr;
00714 return false;
00715 }
00716 }
00717
00718 return true;
00719 }
00720
00721 bool KLFBackend::saveOutputToFile(const klfOutput& klfoutput, const QString& fileName,
00722 const QString& fmt, QString *errorStringPtr)
00723 {
00724 QString format = fmt;
00725
00726 if (format.isEmpty() && !fileName.isEmpty()) {
00727 QFileInfo fi(fileName);
00728 if ( ! fi.fi_suffix().isEmpty() )
00729 format = fi.fi_suffix();
00730 }
00731 if (format.isEmpty())
00732 format = QLatin1String("PNG");
00733 format = format.s_trimmed().s_toUpper();
00734
00735 QFile fout;
00736 if (fileName.isEmpty() || fileName == "-") {
00737 if ( ! fout.f_open_fp(stdout) ) {
00738 QString error = QObject::tr("Unable to open stderr for write! Error: %1\n",
00739 "KLFBackend::saveOutputToFile").arg(fout.f_error());
00740 qWarning("%s", qPrintable(error));
00741 if (errorStringPtr != NULL)
00742 *errorStringPtr = error;
00743 return false;
00744 }
00745 } else {
00746 fout.f_setFileName(fileName);
00747 if ( ! fout.open(dev_WRITEONLY) ) {
00748 QString error = QObject::tr("Unable to write to file `%1'! Error: %2\n",
00749 "KLFBackend::saveOutputToFile")
00750 .arg(fileName).arg(fout.f_error());
00751 qWarning("%s", qPrintable(error));
00752 if (errorStringPtr != NULL)
00753 *errorStringPtr = error;
00754 return false;
00755 }
00756 }
00757
00758 return saveOutputToDevice(klfoutput, &fout, format, errorStringPtr);
00759 }
00760
00761
00762 bool KLFBackend::detectSettings(klfSettings *settings, const QString& extraPath)
00763 {
00764 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00765
00766 QStringList stdextrapaths;
00767 int k, j;
00768 for (k = 0; standard_extra_paths[k] != NULL; ++k) {
00769 stdextrapaths.append(standard_extra_paths[k]);
00770 }
00771 QString extra_paths = stdextrapaths.join(QString("")+KLF_PATH_SEP);
00772 if (!extraPath.isEmpty())
00773 extra_paths += KLF_PATH_SEP + extraPath;
00774
00775
00776 #ifdef KLFBACKEND_QT4
00777 settings->tempdir = QDir::fromNativeSeparators(QDir::tempPath());
00778 #else
00779 # if defined(Q_OS_UNIX) || defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_MACX)
00780 settings->tempdir = "/tmp";
00781 # elif defined(Q_OS_WIN32)
00782 settings->tempdir = getenv("TEMP");
00783 # else
00784 settings->tempdir = QString();
00785 # endif
00786 #endif
00787
00788
00789 settings->lborderoffset = 1;
00790 settings->tborderoffset = 1;
00791 settings->rborderoffset = 1;
00792 settings->bborderoffset = 1;
00793
00794
00795 struct { QString * target_setting; QStringList prog_names; } progs_to_find[] = {
00796 { & settings->latexexec, progLATEX },
00797 { & settings->dvipsexec, progDVIPS },
00798 { & settings->gsexec, progGS },
00799 { & settings->epstopdfexec, progEPSTOPDF },
00800 { NULL, QStringList() }
00801 };
00802
00803 klfDbg(klfFmtCC("Our base extra paths are: %s", qPrintable(extra_paths))) ;
00804 QString ourextrapaths = extra_paths;
00805 ourextrapaths.replace("@executable_path", qApp->applicationDirPath());
00806 klfDbg(klfFmtCC("Our extra paths are: %s", qPrintable(ourextrapaths))) ;
00807
00808 for (k = 0; progs_to_find[k].target_setting != NULL; ++k) {
00809 klfDbg("Looking for "+progs_to_find[k].prog_names.join(" or ")) ;
00810 for (j = 0; j < (int)progs_to_find[k].prog_names.size(); ++j) {
00811 klfDbg("Testing `"+progs_to_find[k].prog_names[j]+"'") ;
00812 *progs_to_find[k].target_setting
00813 = klfSearchPath(progs_to_find[k].prog_names[j], ourextrapaths);
00814 if (!progs_to_find[k].target_setting->isEmpty()) {
00815 klfDbg("Found! at `"+ *progs_to_find[k].target_setting+"'") ;
00816 break;
00817 }
00818 }
00819 }
00820
00821 klf_detect_execenv(settings);
00822
00823 bool result_failure =
00824 settings->tempdir.isEmpty() || settings->latexexec.isEmpty() || settings->dvipsexec.isEmpty() ||
00825 settings->gsexec.isEmpty();
00826
00827 return !result_failure;
00828 }
00829
00830
00847 KLF_EXPORT bool klf_detect_execenv(KLFBackend::klfSettings *settings)
00848 {
00849
00850 QFileInfo gsfi(settings->gsexec);
00851 if (gsfi.fileName() == "mgs.exe") {
00852 QString mgsenv = QString("MIKTEX_GS_LIB=")
00853 + dir_native_separators(gsfi.fi_absolutePath()+"/../../ghostscript/base")
00854 + ";"
00855 + dir_native_separators(gsfi.fi_absolutePath()+"/../../fonts");
00856 __klf_append_replace_env_var(& settings->execenv, "MIKTEX_GS_LIB", mgsenv);
00857 klfDbg("Adjusting environment for mgs.exe: `"+mgsenv+"'") ;
00858 }
00859
00860 #ifdef Q_WS_MAC
00861
00862
00863 if (!settings->epstopdfexec.isEmpty()) {
00864 QFileInfo epstopdf_fi(settings->epstopdfexec);
00865 QString execenvpath = QString("PATH=%1:$PATH").arg(epstopdf_fi.fi_absolutePath());
00866 __klf_append_replace_env_var(& settings->execenv, "PATH", execenvpath);
00867 }
00868 #endif
00869
00870 return true;
00871 }