NEW: added command line tool jkatmathtext_render that renders LaTeX into images, using it to generate the documentation images for JKQTMathText

This commit is contained in:
jkriege2 2022-08-07 18:00:05 +02:00
parent afa14cbbfb
commit bd1afe2a0a
18 changed files with 577 additions and 42 deletions

View File

@ -48,5 +48,11 @@ if(JKQtPlotter_BUILD_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()
if(JKQtPlotter_BUILD_TOOLS)
add_subdirectory(tools)
endif()
add_subdirectory(doc)

View File

@ -877,7 +877,8 @@ WARN_LOGFILE =
INPUT = . \ INPUT = . \
./doc/dox/ \ ./doc/dox/ \
./lib \ ./lib \
./examples ./examples \
./tools
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@ -906,9 +907,7 @@ INPUT_ENCODING = UTF-8
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, # comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
# *.vhdl, *.ucf, *.qsf and *.ice. # *.vhdl, *.ucf, *.qsf and *.ice.
FILE_PATTERNS = *.d \ FILE_PATTERNS = *.ii \
*.java \
*.ii \
*.ixx \ *.ixx \
*.ipp \ *.ipp \
*.i++ \ *.i++ \
@ -920,18 +919,8 @@ FILE_PATTERNS = *.d \
*.h++ \ *.h++ \
*.idl \ *.idl \
*.odl \ *.odl \
*.cs \
*.php \
*.php3 \
*.inc \ *.inc \
*.m \
*.mm \
*.dox \ *.dox \
*.py \
*.f90 \
*.f \
*.vhd \
*.vhdl \
*.md *.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should # The RECURSIVE tag can be used to specify whether or not subdirectories should
@ -993,7 +982,9 @@ EXCLUDE_PATTERNS = */build-* \
*/html/* \ */html/* \
*examples/*.cpp \ *examples/*.cpp \
*examples/*.h \ *examples/*.h \
*/doc/html/* */doc/html/* \
*tools/*.cpp \
*tools/*.h
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the # (namespaces, classes, functions, etc.) that should be excluded from the
@ -1010,7 +1001,8 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include # that contain example code fragments that are included (see the \include
# command). # command).
EXAMPLE_PATH = ./examples/ EXAMPLE_PATH = ./examples/ \
./tools/
# If the value of the EXAMPLE_PATH tag contains directories, you can use the # If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and

View File

@ -11,7 +11,10 @@ if(NOT DEFINED JKQtPlotter_BUILD_DECORATE_LIBNAMES_WITH_BUILDTYPE)
option(JKQtPlotter_BUILD_DECORATE_LIBNAMES_WITH_BUILDTYPE "If set, the build-type (debug/release/...) is appended to the library name" ON) option(JKQtPlotter_BUILD_DECORATE_LIBNAMES_WITH_BUILDTYPE "If set, the build-type (debug/release/...) is appended to the library name" ON)
endif() endif()
if(NOT DEFINED JKQtPlotter_BUILD_EXAMPLES) if(NOT DEFINED JKQtPlotter_BUILD_EXAMPLES)
option(JKQtPlotter_BUILD_EXAMPLES "Build the examples examples" ON) option(JKQtPlotter_BUILD_EXAMPLES "Build the examples" ON)
endif()
if(NOT DEFINED JKQtPlotter_BUILD_TOOLS)
option(JKQtPlotter_BUILD_TOOLS "Build the tools" ON)
endif() endif()
if(NOT DEFINED JKQtPlotter_BUILD_FORCE_NO_PRINTER_SUPPORT) if(NOT DEFINED JKQtPlotter_BUILD_FORCE_NO_PRINTER_SUPPORT)
option(JKQtPlotter_BUILD_FORCE_NO_PRINTER_SUPPORT "Build the library with printer support switched off, even if it is available" OFF) option(JKQtPlotter_BUILD_FORCE_NO_PRINTER_SUPPORT "Build the library with printer support switched off, even if it is available" OFF)

View File

@ -42,3 +42,5 @@ else()
set(JKQtPlotter_QT_CXX_STANDARD_REQUIRED TRUE) set(JKQtPlotter_QT_CXX_STANDARD_REQUIRED TRUE)
set(JKQtPlotter_QT_CXX_COMPILE_FEATURE cxx_std_17) set(JKQtPlotter_QT_CXX_COMPILE_FEATURE cxx_std_17)
endif() endif()
set(JKQtPlotter_QT_BINDIR $<TARGET_FILE_DIR:Qt${QT_VERSION_MAJOR}::qmake>) # ${QT_DIR}../../../../bin

View File

@ -5,7 +5,9 @@ This section assembles some simple examples of usage.
You can find more (complex) examples for the classes in this repository in the subfolder "test". You can find more (complex) examples for the classes in this repository in the subfolder "test".
All test-projects are Qt-projects that use qmake to build. You can load them into QtCreator easily. All test-projects are Qt-projects that use qmake to build. You can load them into QtCreator easily.
\section jkqtp_extut Overview of Examples&Tutorials \tableofcontents
\section jkqtp_extut_jkqtplotter Examples&Tutorials for JKQTPlotter
\subsection jkqtp_extut_plotstyles Different Plot Data Styles \subsection jkqtp_extut_plotstyles Different Plot Data Styles
@ -219,24 +221,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<td> \subpage JKQTPlotterMandelbrot <td> \subpage JKQTPlotterMandelbrot
<td> Allows to zoom into the Mandelbrot Set, using the different Zooming methods of JKQTPlotter <td> Allows to zoom into the Mandelbrot Set, using the different Zooming methods of JKQTPlotter
</table> </table>
\subsection jkqtp_extut_specialfeatures Tools and Special Features
<table>
<tr><th> Screenshot <th> Description <th> Notes
<tr><td> \image html jkqtmathtext_simpletest_small.png
<td> \subpage JKQTMathTextSimpleExample
<td> JKQTMathText<br>render LaTeX markup (Schrödinger's equation)
<tr><td> \image html jkqtmathtext_testapp_small.png
<td> \subpage JKQTMathTextTestApp
<td> JKQTMathText<br>render LaTeX markup
<tr><td> \image html jkqtfastplotter_test_small.png
<td> \subpage JKQTFastPlotterTest
<td> JKQTFastPlotter
</table>
\subsection jkqtp_extut_cmake_build CMake Build System \subsection jkqtp_extut_cmake_build CMake Build System
@ -245,6 +230,45 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html jkqtplotter_cmakelink_small.png <tr><td> \image html jkqtplotter_cmakelink_small.png
<td> \subpage JKQTCMakeLinkExample <td> \subpage JKQTCMakeLinkExample
<td> explains how to link against JKQTPlotter with CMake <td> explains how to link against JKQTPlotter with CMake
</table>
\section jkqtp_extut_jkqtmathtext Examples for JKQTMathText
<table>
<tr><th> Screenshot <th> Description <th> Notes
<tr><td> \image html jkqtmathtext_simpletest_small.png
<td> \subpage JKQTMathTextSimpleExample
<td> JKQTMathText<br>render LaTeX markup (Schrödinger's equation)
<tr><td> \image html jkqtmathtext_render_small.png
<td> \subpage JKQTMathTextRenderCmdLineTool
<td> JKQTMathText<br>command-line utility
<tr><td> \image html jkqtmathtext_testapp_small.png
<td> \subpage JKQTMathTextTestApp
<td> JKQTMathText<br>render LaTeX markup
</table>
\section jkqtp_extut_jkqtfastplotter Examples for JKQTFastPlotter
<table>
<tr><th> Screenshot <th> Description <th> Notes
<tr><td> \image html jkqtfastplotter_test_small.png
<td> \subpage JKQTFastPlotterTest
<td> JKQTFastPlotter
</table> </table>
\section jkqtp_extut_tools Tool Programs
<table>
<tr><th> Screenshot <th> Name <th> Notes/Description
<tr><td> \image html jkqtmathtext_render_small.png
<td> \subpage JKQTMathTextRenderCmdLineTool
<td> uses JKQTMathText to render LaTeX Markup into an image file
</table>
*/ */

View File

@ -10,6 +10,7 @@
Examples for the usage of this class can be found here: Examples for the usage of this class can be found here:
- \ref JKQTMathTextSimpleExample - \ref JKQTMathTextSimpleExample
- \ref JKQTMathTextRenderCmdLineTool
- \ref JKQTMathTextTestApp - \ref JKQTMathTextTestApp
. .

View File

@ -122,7 +122,7 @@
- \c \\left| \c \\right| : absolute value braces | |, \image html jkqtmathtext/jkqtmathtext_bracejkqtmathtext_brace_ucorner_oneline.png - \c \\left| \c \\right| : absolute value braces | |, \image html jkqtmathtext/jkqtmathtext_bracejkqtmathtext_brace_ucorner_oneline.png
- \c \\left\\| \c \\right\\| \endcode : norm braces || ||, \image html jkqtmathtext/jkqtmathtext_brace_dblline.png - \c \\left\\| \c \\right\\| \endcode : norm braces || ||, \image html jkqtmathtext/jkqtmathtext_brace_dblline.png
- \c \\left\\llcorner \c \\right\\lrcorner : lower corner braces , \image html jkqtmathtext/jkqtmathtext_brace_lcorner.png - \c \\left\\llcorner \c \\right\\lrcorner : lower corner braces , \image html jkqtmathtext/jkqtmathtext_brace_lcorner.png
- \c \\left\\ulcorner \c \\right\\urcorner : upper corner braces , \image html jkqtmathtext/.png - \c \\left\\ulcorner \c \\right\\urcorner : upper corner braces , \image html jkqtmathtext/jkqtmathtext_brace_ucorner.png
- You can use \c \\left. or \c \\right. to have only right or only left brace - You can use \c \\left. or \c \\right. to have only right or only left brace
. .
@ -143,12 +143,12 @@
\subsection JKQTMathTextSuppoertedLaTeXUnderOver Undersetting, Oversetting, Underbraces, Overbraces ... \subsection JKQTMathTextSuppoertedLaTeXUnderOver Undersetting, Oversetting, Underbraces, Overbraces ...
There are also instructions that allow to under/overset braces, arrows, ...: There are also instructions that allow to under/overset braces, arrows, ...:
- <code>$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underbrace.png - <code>$\\underbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMunderbrace.png
- <code>$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overbrace.png - <code>$\\overbrace{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMoverbrace.png
- <code>$\\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMunderbracket.png - <code>$\\underbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMunderbracket.png
- <code>$\\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMoverbracket.png - <code>$\\overbracket{x+x+...+x}{k\\ \\mathrm{times}}$</code> \image html jkqtmathtext/MTFMoverbracket.png
- <code>$\\overset{main}{over}$</code> \image html jkqtmathtext/jkqtmathtext_brace_overset.png - <code>$\\overset{main}{over}$</code> \image html jkqtmathtext/MTFMoverset.png
- <code>$\\underset{main}{under}$</code> \image html jkqtmathtext/jkqtmathtext_brace_underset.png - <code>$\\underset{main}{under}$</code> \image html jkqtmathtext/MTFMunderset.png
. .
\subsection JKQTMathTextSuppoertedLaTeXFrac Fraction Type Instructions \subsection JKQTMathTextSuppoertedLaTeXFrac Fraction Type Instructions

View File

@ -41,8 +41,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
<li>JKQTMathText:<ul> <li>JKQTMathText:<ul>
<li>check sub/superscript with italic text in math mode, possibly a correction is necessary</li> <li>check sub/superscript with italic text in math mode, possibly a correction is necessary</li>
<li>explore options to make font-environment-modifying commands avails, like "{blacktext\\color{red}redtext}", today only commands like "\\textcolor{red}{redtext}" work</li> <li>explore options to make font-environment-modifying commands avails, like "{blacktext\\color{red}redtext}", today only commands like "\\textcolor{red}{redtext}" work</li>
<li>maybe: add support for text with linebreaks by adding a JKQTMathTextVerticalListNode in addition to JKQTMathTextListNode</li>
<li>maybe: add tool programs to auto-generate some example images</li>
<li>improve support for array-environment with limited support for formatting string like l|r|c and maybe add support for \\hline command, possibly also \\cellcolor etz.</li> <li>improve support for array-environment with limited support for formatting string like l|r|c and maybe add support for \\hline command, possibly also \\cellcolor etz.</li>
<li></li> <li></li>
</ul></li> </ul></li>

View File

@ -82,6 +82,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: added support for \\begin{verbatim}...\\end{verbatim}, \\begin{verbatim*}...\\end{verbatim*}</li> <li>NEW: added support for \\begin{verbatim}...\\end{verbatim}, \\begin{verbatim*}...\\end{verbatim*}</li>
<li>NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize() </li> <li>NEW: additional method JKQTMathtext::getSizeDetail() that returns all size-properties as a convenient struct, also added matching varinat JKQTMathTextNode::getSize() </li>
<li>NEW: additional method JKQTMathtext::drawIntoPixmap(), JKQTMathtext::drawIntoPicture(), JKQTMathtext::drawIntoImage() which returns a QPixmap, QPicture and QImage respectively that contains the render result of the currently parsed markup</li> <li>NEW: additional method JKQTMathtext::drawIntoPixmap(), JKQTMathtext::drawIntoPicture(), JKQTMathtext::drawIntoImage() which returns a QPixmap, QPicture and QImage respectively that contains the render result of the currently parsed markup</li>
<li>NEW: added command line tool \ref JKQTMathTextRenderCmdLineTool that renders LaTeX into images, using it to generate the documentation images for JKQTMathText</li>
</ul></li> </ul></li>
</ul> </ul>

View File

@ -99,6 +99,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
| Screenshot | Description | Notes | | Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- | |:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_simpletest_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_simpletest) | [JKQTMathText: Simple Demonstration](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_simpletest) | | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_simpletest_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_simpletest) | [JKQTMathText: Simple Demonstration](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_simpletest) | |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_render_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/tools/jkqtmathtext_render) | [JKQTMathText: Command-Line Utility](https://github.com/jkriege2/JKQtPlotter/tree/master/tools/jkqtmathtext_render) | |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_testapp_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_test) | [JKQTMathText: Full Testing Application](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_test) | | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_testapp_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_test) | [JKQTMathText: Full Testing Application](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_test) | |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtfastplotter_test_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtfastplotter_test) | [JKQTFastPlotter: Example](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtfastplotter_test) | | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtfastplotter_test_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtfastplotter_test) | [JKQTFastPlotter: Example](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtfastplotter_test) | |

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

22
tools/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.16)
message( STATUS )
message( STATUS "............................................................................." )
message( STATUS ".. BUILDING TOOLS" )
message( STATUS "............................................................................." )
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
message( STATUS ".. - Precompiled Header: ON" )
else()
message( STATUS ".. - Precompiled Header: OFF")
endif()
message( STATUS "............................................................................." )
# examples specific to JKQtMathText
message( STATUS ".. BUILDING TOOLS FOR JKQTMATHTEXT:" )
add_subdirectory(jkqtmathtext_render)

View File

@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME jkqtmathtext_render)
set(EXENAME ${EXAMPLE_NAME})
message( STATUS ".. Building Tool ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES
${EXAMPLE_NAME}.cpp
)
set(HEADERS )
set(RESOURCES )
set(UIS )
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
target_include_directories(${EXENAME} PRIVATE ../../lib)
if(JKQtPlotter_BUILD_STATIC_LIBS)
target_link_libraries(${EXENAME} JKQTMathTextLib)
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
target_link_libraries(${EXENAME} JKQTMathTextSharedLib)
endif()
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,80 @@
# Example (JKQTMathText): Command-Line Utility jkqtmathtext_render {#JKQTMathTextRenderCmdLineTool}
JKQTMathText is a hand-written LaTeX-renderer for Qt (implemented in native C++, using Qt). It supports a large set of standard LaTeX markup and can render it to a QPainter.
This project (see `./examples/jkqtmathtext_render/`) is a command-line utility that accepts a LaTeX markup string and a filename for the generated image.
It then renders the string into the image.
The source code of the main application can be found in [`jkqtmathtext_render.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/jkqtmathtext_render/jkqtmathtext_render.cpp).
The major rendering portion look like this:
First we generate dummy QPixmap that is needed to use the QPainter, that is required for determining the size of the rendering.
```.cpp
QPixmap pix(10,10);
```
Now we create a JKQTMathText object and configure it
```.cpp
QPainter painter;
JKQTMathText mathText;
if (useXITS) mathText.useXITS();
mathText.setFontSize(fontsize);
```
Now we parse some LaTeX code and thus generate its memory representation.
```.cpp
mathText.parse(latex);
```
Finally we can generate a QImage with the output of the rendering algorithm and save it as a file.
```.cpp
const QImage pix=mathText.drawIntoImage(drawBoxes, backgroundColor, sizeincrease);
pix.save(outputFilename);
```
calling this utility with the LaTeX code:
```.sh
> jkqtmathtext_render "$x_{1/2}=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$" jkqtmathtext_render_output.png
```
results in this output:
![jkqtmathtext_render_output](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtmathtext_render_output.png)
The tool supports these command-line options:
- *command-line mode*: call `jkqtmathtext_render LATEX OUTPUTFILE`
- The extension of the `OUTPUTFILE` determines the file type. The tool supports `.png`, `.bmp`, `.jpg`, `.ppm`, `.xbm` and `.xpm`
- *file-mode*: call `jkqtmathtext_render --inputfile=INPUTFILE.jkmt --outputdir=OUTPUTDIR`
- The file `INPUTFILE.jkmt` is a text file with several "render jobs", deparated by `---` lines.
- The first line in each job defines the output filename (relative to `OUTPUTDIR`)
- The second line is optional and contains a list of altered command-line options, e.g. `--fontsize=24 --fontmathroman=XITS`, Note however that only options concerning formatting are allowed, `--verbose` or the file/directory-options will not be processed!
- The third and further lines is concatenated to form the LaTeX markup to be rendered.
- All modes support these command-line options:
- `--verbose`: verbose output of the tool
- `--sizeincrease=SIZE_PIXELS`: set the width of the additional margin around the rendering result
- `--drawboxes`: flag that enables drawing of rectangles around each box
- `--font=FONT_SERIF`: sets text- and math-mode serif font to `FONT_SERIF`
- `--font=FONT_SERIF,FONT_SANS`: sets text- and math-mode serif font to `FONT_SERIF` and sans font to `FONT_SANS`
- `--font=FONT_TEXT_SERIF,FONT_TEXT_SANS,FONT_MATH_SERIF,FONT_MATH_SANS`: sets text- and math-mode serif font to `FONT_TEXT_SERIF` and `FONT_MATH_SERIF` and sans fonts to `FONT_TEXT_SANS` and `FONT_MATH_SANS`
- `--font=...+XITS|STIX|ASANA`: set fonts as given above and then use XITS-/STIX- or ASANA-fonts for math-roman
- `--fontsize=SIZE_PT`: set the font-size in pt
- `--fontroman=FONT`: set the text-mode roman font
- `--fontsans=FONT`: set the text-mode sans font
- `--fontmathroman=FONT`: set the math-mode roman font
- `--fontmathsans=FONT`: set the math-mode sans font
- `--fontblackboard=FONT`: use the given font as blackboard-font and de-activate the simulate-feature
- `--fontblackboardsimulated=FONT`: use the given font as blackboard-font and activate the simulate-feature
- `--fonttypewriter=FONT`: set the typewriter font
- `--fontscript=FONT`: set the script font
- `--fontcaligraphic=FONT`: set the caligraphic font
- `--fontfraktur=FONT`: set the fraktur font
- `--fontfallbacksymbol=FONT`: set the fallback symbol font, using unicode encoding
- `--fontfallbacksymbol_symbolencoding=FONT`: set the fallback symbol font, using WinSymbol encoding
- `--background=COLOR`: set the background color of the output image
- `--textcolor=COLOR`: set the text color of the output image

View File

@ -0,0 +1,341 @@
/** \example jkqtmathtext_render.cpp
* A very basic example for the usage of JKQTMathText
*
* \ref JKQTMathTextRenderCmdLineTool
*/
#include <QApplication>
#include <QPixmap>
#include <QPainter>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QElapsedTimer>
#include <QFile>
#include <QDir>
#if (QT_VERSION>=QT_VERSION_CHECK(6, 0, 0))
#include<QRegularExpression>
#include<QRegularExpressionMatch>
#else
#include<QRegExp>
#endif
#include "jkqtmathtext/jkqtmathtextlabel.h"
#include "jkqtcommon/jkqtpstringtools.h"
#include <iostream>
void processFont(const QString font, QStringList& fonts, QString& mathFont)
{
fonts.clear();
mathFont="";
QString current="";
bool isExtra=false;
for (int i=0; i<font.size(); i++) {
if (font[i]==',') {
fonts.push_back(current);
current="";
} else if (font[i]=='+') {
fonts.push_back(current);
isExtra=true;
current="";
} else {
if (isExtra) {
mathFont+=font[i];
} else {
current+=font[i];
}
}
}
if (current.size()>0) {
fonts.append(current);
}
}
int main(int argc, char* argv[])
{
// 1. create Qt Appcilation object and a QCommandLineParser to go with it
QApplication app(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription("JKQTMathText command line tool that renders LaTeX markup into an image");
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("latex", "LaTeX markup to be rendered");
parser.addPositionalArgument("output", "output image file (extensions determines file type)");
QCommandLineOption inputfileOption("inputfile", "read from a file instead of from command line.", "inputfile", "");
parser.addOption(inputfileOption);
QCommandLineOption outputDirectoryOption("outputdir", "write results into this directory.", "outputdir", app.applicationDirPath());
parser.addOption(outputDirectoryOption);
QCommandLineOption drawBoxesOption("drawboxes", "draw boxes.");
parser.addOption(drawBoxesOption);
QCommandLineOption verboseOption("verbose", "verbose output.");
parser.addOption(verboseOption);
QCommandLineOption fontOption("font", "font( size)s) to use.", "font", "XITS");
parser.addOption(fontOption);
QCommandLineOption fontsizeOption("fontsize", "font size.", "fontsize", "12");
parser.addOption(fontsizeOption);
QCommandLineOption fontBlackboardSimOption("fontblackboardsimulated", "set the blackboard font and activate simulated-mode.", "fontblackboardsimulated", "");
parser.addOption(fontBlackboardSimOption);
QCommandLineOption fontRomanOption("fontroman", "set the text-mode roman font to use.", "fontroman", "");
parser.addOption(fontRomanOption);
QCommandLineOption fontSansOption("fontsans", "set the text-mode sans font to use.", "fontsans", "");
parser.addOption(fontSansOption);
QCommandLineOption fontMathRomanOption("fontmathroman", "set the math-mode roman font to use.", "fontmathroman", "");
parser.addOption(fontMathRomanOption);
QCommandLineOption fontMathSansOption("fontmathsans", "set the math-mode sans font to use.", "fontmathsans", "");
parser.addOption(fontMathSansOption);
QCommandLineOption fontFallbackSymbolOption("fontfallbacksymbol", "set the fallback symbol font to use.", "fontfallbacksymbol", "");
parser.addOption(fontFallbackSymbolOption);
QCommandLineOption fontFallbackSymbol_symbolencodingOption("fontfallbacksymbol_symbolencoding", "set the fallback symbol font to use and use the encoding of the MS Symbol font for it.", "fontfallbacksymbol_symbolencoding", "");
parser.addOption(fontFallbackSymbol_symbolencodingOption);
QCommandLineOption fontTypewriterOption("fonttypewriter", "set the typewriter font to use.", "fonttypewriter", "");
parser.addOption(fontTypewriterOption);
QCommandLineOption fontScriptOption("fontscript", "set the Script font to use.", "fontscript", "");
parser.addOption(fontScriptOption);
QCommandLineOption fontFrakturOption("fontfraktur", "set the Fraktur font to use.", "fontfraktur", "");
parser.addOption(fontFrakturOption);
QCommandLineOption fontcaligraphicOption("fontcaligraphic", "set the caligraphic font to use.", "fontcaligraphic", "");
parser.addOption(fontcaligraphicOption);
QCommandLineOption fontblackboardOption("fontblackboard", "set the blackboard font to use.", "fontblackboard", "");
parser.addOption(fontblackboardOption);
QCommandLineOption textcolorOption("textcolor", "set the color of the text.", "textcolor", "black");
parser.addOption(textcolorOption);
QCommandLineOption sizeincreaseOption("sizeincrease", "additional pixels around output.", "sizeincrease", "2");
parser.addOption(sizeincreaseOption);
QCommandLineOption resolutionOption("resolution", "set output image resolution in DPI.", "resolution", "96");
parser.addOption(resolutionOption);
QCommandLineOption backgroundOption("background", "background color.", "background", "white");
parser.addOption(backgroundOption);
parser.process(app);
const QStringList args = parser.positionalArguments();
const QString latex_cmdline=args.value(0, "$x_{1/2}=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}$");
const QDir outputDir(parser.value(outputDirectoryOption));
const QString outputFilename_cmdline=outputDir.absoluteFilePath(args.value(1, "output.png"));
const QString inputfile=parser.value(inputfileOption);
const bool verbose = parser.isSet(verboseOption);
QStringList latex, outputFilename;
QList<QMap<QString,QString>> cmdoptions;
if (inputfile.size()<=0) {
latex.append(latex_cmdline);
outputFilename.append(outputFilename_cmdline);
cmdoptions.append(QMap<QString,QString>());
} else {
QFile f(inputfile);
if (f.open(QFile::ReadOnly|QFile::Text)) {
QString currentOutFile="";
QString currentLatex="";
QMap<QString,QString> currentOptions;
bool isFile=true;
bool beforeLatex=true;
while (!f.atEnd()) {
const QString line=f.readLine().trimmed();
const QString line_simple=line.simplified();
if (line_simple=="---" || line_simple=="###") {
if (currentOutFile.size()>0) {
outputFilename.append(currentOutFile);
latex.append(currentLatex);
cmdoptions.append(currentOptions);
isFile=true;
beforeLatex=true;
currentLatex="";
currentOutFile="";
currentOptions.clear();
}
} else if (isFile) {
currentOutFile=line;
isFile=false;
} else if (beforeLatex) {
if (line.startsWith("--")) {
QStringList commands=line.right(line.size()-2).split("--");
for (QString cmd: commands) {
cmd=cmd.trimmed();
QString cmdn="", param="";
bool iscmd=true;
for (const QChar& ch: cmd) {
if (iscmd) {
if (ch=='=') {
iscmd=false;
} else {
cmdn+=ch;
}
} else {
param+=ch;
}
}
currentOptions[cmdn.trimmed()]=param.trimmed();
}
} else {
if (currentLatex.size()>0) currentLatex+="\n";
currentLatex+=line;
}
beforeLatex=false;
} else {
if (currentLatex.size()>0) currentLatex+="\n";
currentLatex+=line;
}
}
f.close();
if (currentOutFile.size()>0) {
outputFilename.append(currentOutFile);
latex.append(currentLatex);
cmdoptions.append(currentOptions);
}
}
}
if (verbose) {
std::cout
<<"===========================================================\n"
<<"= jkqtmathtext_render: ";
if (inputfile.size()>0) std::cout<<"FILE-MODE ("<<inputfile.toStdString()<<")\n";
else std::cout<<"COMMAND-LINE-MODE\n";
std::cout<<"\n"
<<"===========================================================\n";
}
for (int i=0; i<latex.size(); i++) {
if (inputfile.size()>0 && verbose) {
std::cout<<"\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
<<"+ processing entry "<<(i+1)<<"/"<<latex.size()<<"\n";
if (cmdoptions[i].size()>0) {
std::cout<<"+ additional command-line options: ";
for (const QString& key: cmdoptions[i].keys()) {
std::cout<<" --"<<key.toStdString()<<"="<<cmdoptions[i].value(key).toStdString();
}
std::cout<<"\n";
}
}
QStringList fonts;
QString mathFont="";
processFont(parser.value(fontOption), fonts, mathFont);
bool drawBoxes = parser.isSet(drawBoxesOption);
double fontsize = parser.value(fontsizeOption).toDouble();
int sizeincrease = parser.value(sizeincreaseOption).toInt();
int resolution_dpi = parser.value(resolutionOption).toInt();
QColor backgroundColor = jkqtp_String2QColor(parser.value(backgroundOption));
QColor textColor = jkqtp_String2QColor(parser.value(textcolorOption));
QString fontBlackboardSim = parser.value(fontBlackboardSimOption);
QString fontBlackboard=parser.value(fontblackboardOption);
QString fontRoman=parser.value(fontRomanOption);
QString fontSans=parser.value(fontSansOption);
QString fontMathRoman=parser.value(fontMathRomanOption);
QString fontMathSans=parser.value(fontMathSansOption);
QString fontFallbackSymbol=parser.value(fontFallbackSymbolOption);
QString fontFallbackSymbol_symbolencoding=parser.value(fontFallbackSymbol_symbolencodingOption);
QString fontTypewriter=parser.value(fontTypewriterOption);
QString fontScript=parser.value(fontScriptOption);
QString fontFraktur=parser.value(fontFrakturOption);
QString fontCaligraphic=parser.value(fontcaligraphicOption);
if (cmdoptions[i].size()>0) {
for (const QString& key: cmdoptions[i].keys()) {
if (key=="drawboxes") drawBoxes=true;
else if (key=="fontsize") fontsize=cmdoptions[i].value(key).toDouble();
else if (key=="sizeincrease") sizeincrease=cmdoptions[i].value(key).toInt();
else if (key=="background") backgroundColor=jkqtp_String2QColor(cmdoptions[i].value(key));
else if (key=="textcolor") textColor=jkqtp_String2QColor(cmdoptions[i].value(key));
else if (key=="fontblackboardsimulated") fontBlackboardSim=cmdoptions[i].value(key);
else if (key=="fontblackboard") fontBlackboard=cmdoptions[i].value(key);
else if (key=="font") processFont(cmdoptions[i].value(key), fonts, mathFont);
else if (key=="fontroman") fontRoman=cmdoptions[i].value(key);
else if (key=="fontsans") fontSans=cmdoptions[i].value(key);
else if (key=="fontmathroman") fontMathRoman=cmdoptions[i].value(key);
else if (key=="fontmathsans") fontMathSans=cmdoptions[i].value(key);
else if (key=="fonttypewriter") fontTypewriter=cmdoptions[i].value(key);
else if (key=="fontfallbacksymbol") fontFallbackSymbol=cmdoptions[i].value(key);
else if (key=="fontfallbacksymbol_symbolencoding") fontFallbackSymbol_symbolencoding=cmdoptions[i].value(key);
else if (key=="fontscript") fontScript=cmdoptions[i].value(key);
else if (key=="fontcaligraphic") fontCaligraphic=cmdoptions[i].value(key);
else if (key=="fontfraktur") fontFraktur=cmdoptions[i].value(key);
}
}
// 2. now we create a JKQTMathText object and configure it
JKQTMathText mathText;
if (fonts.size()==1) {
mathText.useAnyUnicode(fonts[0], mathText.getFontSans());
} else if (fonts.size()==2) {
mathText.useAnyUnicode(fonts[0], fonts[1]);
} else if (fonts.size()==4) {
mathText.useAnyUnicodeForTextOnly(fonts[0], fonts[1]);
mathText.useAnyUnicodeForMathOnly(fonts[2], fonts[3]);
}
if (mathFont.toUpper() == "XITS") mathText.useXITS(true);
else if (mathFont.toUpper() == "XITS_MATHANDTEXT") mathText.useXITS(false);
if (mathFont.toUpper() == "STIX") mathText.useSTIX(true);
else if (mathFont.toUpper() == "STIX_MATHANDTEXT") mathText.useSTIX(false);
if (mathFont.toUpper() == "ASANA") mathText.useASANA(true);
else if (mathFont.toUpper() == "ASANA_MATHANDTEXT") mathText.useASANA(false);
if (fontRoman.size()>0) mathText.setFontRoman(fontRoman, MTFEUnicode);
if (fontSans.size()>0) mathText.setFontSans(fontSans, MTFEUnicode);
if (fontMathRoman.size()>0) {
if (fontMathRoman.toUpper()=="XITS") mathText.useXITS(true);
else if (fontMathRoman.toUpper()=="STIX") mathText.useSTIX(true);
else if (fontMathRoman.toUpper()=="ASANA") mathText.useASANA(true);
else mathText.setFontMathRoman(fontMathRoman, MTFEUnicode);
}
if (fontMathSans.size()>0) mathText.setFontMathSans(fontMathSans, MTFEUnicode);
if (fontTypewriter.size()>0) mathText.setFontTypewriter(fontTypewriter, MTFEUnicode);
if (fontScript.size()>0) mathText.setFontScript(fontScript, MTFEUnicode);
if (fontCaligraphic.size()>0) mathText.setFontCaligraphic(fontCaligraphic, MTFEUnicode);
if (fontFraktur.size()>0) mathText.setFontFraktur(fontFraktur, MTFEUnicode);
if (fontFallbackSymbol.size()>0) mathText.setFallbackFontSymbols(fontFallbackSymbol, MTFEUnicode);
if (fontFallbackSymbol_symbolencoding.size()>0) mathText.setFallbackFontSymbols(fontFallbackSymbol_symbolencoding, MTFEWinSymbol);
if (fontBlackboardSim.size()>0) {
mathText.setFontBlackboard(fontBlackboardSim, MTFEUnicode);
mathText.setFontBlackboardSimulated(true);
}
if (fontBlackboard.size()>0) {
mathText.setFontBlackboard(fontBlackboard, MTFEUnicode);
mathText.setFontBlackboardSimulated(false);
}
mathText.setFontSize(fontsize);
mathText.setFontColor(textColor);
// 3. now we parse some LaTeX code
QElapsedTimer timer;
timer.start();
mathText.parse(latex[i]);
const double durParseMS=static_cast<double>(timer.nsecsElapsed())/1.0e6;
if (mathText.hadErrors()) {
std::cerr<<"ERRORS while parsing LaTeX:\n"
<<"-----------------------------------------------------------\n"
<<latex[i].toStdString()<<"\n"
<<"-----------------------------------------------------------\n"
<<mathText.getErrorList().join("\n").toStdString()<<"\n"
<<"-----------------------------------------------------------\n"
;
} else if (verbose) {
std::cout<<"parsing LaTeX: OK\n"
<<"parsing duration: "<<durParseMS<<"ms\n"
<<"-----------------------------------------------------------\n"
<<latex[i].toStdString()<<"\n"
<<"-----------------------------------------------------------\n";
}
// 4. now we draw the result into a QPixmap
timer.start();
const QImage pix=mathText.drawIntoImage(drawBoxes, backgroundColor, sizeincrease, 1.0, resolution_dpi);
const double durRenderMS=static_cast<double>(timer.nsecsElapsed())/1.0e6;
if (verbose) std::cout<<"rendering into QImage "<<pix.width()<<"x"<<pix.height()<<"pixels\n"
<<"rendering duration: "<<durRenderMS<<"ms\n"
<<"rendering resolution: "<<pix.dotsPerMeterX()/(1000.0/25.4)<<"x"<<pix.dotsPerMeterY()/(1000.0/25.4)<<"dpi\n"
<<"devicepixelratio: "<<pix.devicePixelRatioF()<<"\n"
;
// 5. before ending the application, we store the result into a file
const QString outname=outputDir.absoluteFilePath(outputFilename[i]);
if (QFileInfo::exists(outname)) QFile::remove(outname);
if (!pix.save(outname)) {
std::cerr<<"ERROR storing to "<<outname.toStdString()<<"\n";
} else {
if (verbose) std::cout<<"stored to "<<outname.toStdString()<<"\n"
<<" size "<<static_cast<double>(QFileInfo(outname).size())/1024.0<<"kBytes\n";
}
}
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,23 @@
TARGET = jkqtmathtext_render
TEMPLATE = app
SOURCES += jkqtmathtext_render.cpp
CONFIG += link_prl qt
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
DEPENDPATH += ../../lib ../../qmake/staticlib/jkqtmathtextlib
INCLUDEPATH += ../../lib
CONFIG (debug, debug|release) {
DEPENDPATH += ../../qmake/staticlib/jkqtmathtextlib/debug
LIBS += -L../../qmake/staticlib/jkqtmathtextlib/debug -L../../../qmake/staticlib/jkqtmathtextlib/debug -ljkqtmathtextlib_debug
} else {
DEPENDPATH += ../../qmake/staticlib/jkqtmathtextlib/release
LIBS += -L../../qmake/staticlib/jkqtmathtextlib/release -L../../../qmake/staticlib/jkqtmathtextlib/release -ljkqtmathtextlib
}
message("LIBS = $$LIBS")
win32-msvc*: DEFINES += _USE_MATH_DEFINES
win32-msvc*: DEFINES += NOMINMAX

View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += jkqtmathtextlib jkqtmathtext_render
jkqtmathtextlib.file = ../../qmake/staticlib/jkqtmathtextlib/jkqtmathtextlib.pro
jkqtmathtext_render.file=$$PWD/jkqtmathtext_render.pro
jkqtmathtext_render.depends = jkqtmathtextlib