JKQtPlotter/lib/jkqtmathtext/jkqtmathtexttools.h

450 lines
19 KiB
C
Raw Normal View History

/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
with contributions from: Razi Alavizadeh
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Name: jkqtmathtext.h
Copyright: (c) 2010-2019
Author: Jan krieger <jan@jkrieger.de>, http://www.jkrieger.de/
*/
#ifndef JKQTMATHTEXTTOOLS_H
#define JKQTMATHTEXTTOOLS_H
#include <QObject>
#include <QSettings>
#include <QPainter>
#include <QString>
#include <QSet>
#include <QFile>
#include "jkqtmathtext/jkqtmathtext_imexport.h"
#include <QWidget>
#include <QLabel>
#include <QHash>
#include <QPainterPath>
class JKQTMathText; // forward
/** \brief initialized Qt-ressources necessary for JKQTMathText
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT void initJKQTMathTextResources();
/*! \brief represents a font specifier for JKQTMathText. The font consists of two parts: the actual font and the font used for math output (which may be empty)
\ingroup jkqtmathtext_tools
\section JKQTMathTextFontSpecifier_specialNames Special FOnt Names
This object also implements replacing special font names with actual fonts. Supported special font names are:
- \c default / \c app / \c application - the applications default font
- \c times / \c serif - a general serif font
- \c sans-serif - a general sans-serif font
- \c typewriter - a general typewrter/monospaced font
- \c cursive
- \c decorative
- \c fantasy
- \c monospace
- \c system
.
If copiled with Qt>5.3 you can also use these:
- \c fixed
- \c smallest_readable
- \c title
- \c general
.
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontSpecifier {
JKQTMathTextFontSpecifier();
JKQTMathTextFontSpecifier(const QString& fontName, const QString& mathFontName);
/** \brief construct a JKQTMathTextFontSpecifier, by parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
static JKQTMathTextFontSpecifier fromFontSpec(const QString& fontSpec);
/** \brief initialises the object with values from parsing a \a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
void setFontSpec(const QString& fontSpec);
/** \brief returns the object's constents as a fontSpec string with the form \c "FONT_NAME[+MATH_FONT_NAME]". */
QString getFontSpec() const;
/** \copydoc m_fontName */
QString fontName() const;
/** \copydoc m_mathFontName */
QString mathFontName() const;
/** \copydoc m_fontName */
void setFontName(const QString& name);
/** \copydoc m_mathFontName */
void setmathFontName(const QString& name);
/** \brief finds actual fonts for some predefined special font names, as listed in \ref JKQTMathTextFontSpecifier_specialNames */
static QString transformFontName(const QString& fontName);
/** \brief same as transformFontName(), but also finds the actual name for XITS, STIX, ASANA,... */
static QString transformFontNameAndDecodeSpecialFonts(const QString& fontName);
/** \brief leiefert \c true, wenn ein fontName() verfügbar ist */
bool hasFontName() const;
/** \brief leiefert \c true, wenn ein mathFontName() verfügbar ist */
bool hasMathFontName() const;
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getXITSFamilies();
/** \brief initialize with the font-families from the XITS package for text and math */
static JKQTMathTextFontSpecifier getASANAFamilies();
/** \brief initialize with the font-families from the STIX package for text and math */
static JKQTMathTextFontSpecifier getSTIXFamilies();
private:
/** \brief specifies the main font name */
QString m_fontName;
/** \brief specifies the math font to use in addition to fontName */
QString m_mathFontName;
};
/** \brief used to specify the font encoding used for drawing
* \ingroup jkqtmathtext_tools
*/
enum JKQTMathTextFontEncoding {
MTFEWinSymbol=0, /*!< \brief This assumes that symbols shall be taken from a MS Windows style Symbol font */
MTFEUnicode=1, /*!< \brief This assumes that symbols shall be taken from a Unicode font, which ideally offers full symbol support (e.g. the XITS fonts, STIX fonts from <a href="http://www.stixfonts.org/">http://www.stixfonts.org/</a>)*/
MTFELatin1=2, /*!< \brief the encoding of a standard Latin1 TTF font (i.e. we can only expect letters,number and not many special characters) */
MTFEStandard=MTFELatin1
};
/** \brief this function tries to determine the JKQTMathTextFontEncoding of a given font (HEURISTICS!!!)
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontEncoding estimateJKQTMathTextFontEncoding(QFont font);
/** \brief convert MTfontEncoding to a string
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextFontEncoding2String(JKQTMathTextFontEncoding e);
/** \brief types of available braces
* \ingroup jkqtmathtext_tools
*/
enum JKQTMathTextBraceType {
MTBTParenthesis=0, /*!< \brief parantheses () \image html jkqtmathtext/jkqtmathtext_brace_round.png */
MTBTSquareBracket, /*!< \brief brackets [] \image html jkqtmathtext/jkqtmathtext_brace_rect.png */
MTBTCurlyBracket, /*!< \brief curly braces {} \image html jkqtmathtext/jkqtmathtext_brace_curly.png */
MTBTAngleBracket, /*!< \brief angle backets <> \image html jkqtmathtext/jkqtmathtext_brace_tri.png */
MTBTCeilBracket, /*!< \brief ceil brackets \image html jkqtmathtext/jkqtmathtext_brace_ceil.png */
MTBTFloorBracket, /*!< \brief floor brackets \image html jkqtmathtext/jkqtmathtext_brace_floor.png */
MTBTDoubleLine, /*!< \brief double-line brackets (norm ||...||) \image html jkqtmathtext/jkqtmathtext_brace_dblline.png */
MTBTSingleLine, /*!< \brief single-line brackets (abs |...|) \image html jkqtmathtext/jkqtmathtext_brace_oneline.png */
MTBTTopCorner, /*!< \brief top-corner brackets \image html jkqtmathtext/jkqtmathtext_brace_topcorner.png */
MTBTBottomCorner, /*!< \brief bottom-corner brackets \image html jkqtmathtext/jkqtmathtext_brace_bottomcorner.png */
MTBTNone, /*!< \brief no bracket */
MTBTAny, /*!< \brief any bracket, used by JKQTMathText::parseLatexString() */
MTBTUnknown /*!< \brief an unknown tokenName presented to TokenName2JKQTMathTextBraceType() */
};
/** \brief convert a JKQTMathTextBraceType into a string
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextBraceType2String(JKQTMathTextBraceType type);
/** \brief convert a string \a tokenName describing a LaTeX Token or Instruction into an opening or closing JKQTMathTextBraceType
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType TokenName2JKQTMathTextBraceType(const QString& tokenName);
/** \brief convert a string \a tokenName describing a LaTeX Instruction into an opening JKQTMathTextBraceType
* \ingroup jkqtmathtext_tools
*
* This returns a JKQTMathTextBraceType for which isPrintableJKQTMathTextBraceType() is \c true, or MTBTUnknown,
* never MTBTNone or MTBTAny.
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType InstructionName2OpeningJKQTMathTextBraceType(const QString& tokenName);
/** \brief convert a string \a tokenName describing a LaTeX Instruction into an opening or closing JKQTMathTextBraceType
* \ingroup jkqtmathtext_tools
*
* This returns a JKQTMathTextBraceType for which isPrintableJKQTMathTextBraceType() is \c true, or MTBTUnknown,
* never MTBTNone or MTBTAny.
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextBraceType InstructionName2JKQTMathTextBraceType(const QString& tokenName);
/** \brief return \c true if \a type represents a printable type of brace (including MTBTNone), basically \c true
* for any JKQTMathTextBraceType that can be used as parameter to JKQTMathTextBraceNode
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT bool isPrintableJKQTMathTextBraceType(JKQTMathTextBraceType type);
/** \brief returns true, if the given token/instruction-Name \a token ("{", "(", ..., "lceil", ".", ...) matches the given \a type (returns true, when \a type == MTBTAny )
* \ingroup jkqtmathtext_tools
*
* This accepts TokenName2JKQTMathTextBraceType(toke)==MTBTNone for any \a type, iff \a acceptMTBTNone \a ==true.
*
* Optionally returns in \a tokenEqualsNone whether \a token was encoding for MTBTNone .
*/
JKQTMATHTEXT_LIB_EXPORT bool TokenNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool *tokenEqualsNone=nullptr);
/** \brief returns true, if the given instruction-Name \a token ("|", "{", ..., "lceil", ".", ...) matches the given \a type (returns true, when \a type == MTBTAny )
* \ingroup jkqtmathtext_tools
*
* This accepts TokenName2JKQTMathTextBraceType(toke)==MTBTNone for any \a type, iff \a acceptMTBTNone \a ==true.
*
* Optionally returns in \a tokenEqualsNone whether \a token was encoding for MTBTNone .
*/
JKQTMATHTEXT_LIB_EXPORT bool InstructionNameMatchesJKQTMathTextBraceType(const QString &token, JKQTMathTextBraceType type, bool acceptMTBTNone, bool *tokenEqualsNone=nullptr);
/** \brief the available logical fonts (default is MTEroman)
* \ingroup jkqtmathtext_tools
*/
enum JKQTMathTextEnvironmentFont {
MTEroman, /*!< \brief roman font, e.g. <code>\\rm{}</code> */
MTEsans, /*!< \brief sans-serif font, e.g. <code>\\sf{}</code> */
MTEmathRoman, /*!< \brief math-mode roman font, e.g. <code>\\mathrm{}</code> */
MTEmathSans, /*!< \brief math-mode sans-serif font, e.g. <code>\\mathsf{}</code> */
MTEtypewriter, /*!< \brief typewriter font, e.g. <code>\\tt{},\\mathtt{}</code> */
MTEscript, /*!< \brief script font, e.g. <code>\\script{},\\mathscript{}</code> */
MTEblackboard, /*!< \brief blackboard font, e.g. <code>\\mathbb{}</code> */
MTEcaligraphic, /*!< \brief caligraphic font, e.g. <code>\\mathcal{}</code> */
MTEfraktur, /*!< \brief fraktur font, e.g. <code>\\mathfrak{}</code> */
MTEFallbackSymbols, /*!< \brief symbol font */
MTECurrentFont, /*!< \brief internal enum value that specifies that the currently set font shall be used \internal */
MTECustomFont, /*!< \brief internal enum value that specifies that a custom font specified elsewhere shall be used \internal */
};
/** \brief describes the current drawing environment (base fontname ...)
* \ingroup jkqtmathtext_tools
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextEnvironment {
/** \brief units for the property JKQTMathTextEnvironment::fontSize (Points/PT or Pixels) */
enum FontSizeUnit {
POINTS,
PIXELS
};
/** \brief convert a FontSizeUnit to a string \see FontSizeUnit,String2FontSizeUnit() */
static QString FontSizeUnit2String(FontSizeUnit unit);
/** \brief convert a string into a FontSizeUnit \see FontSizeUnit,FontSizeUnit2String() */
static FontSizeUnit String2FontSizeUnit(QString unit);
JKQTMathTextEnvironment();
/** \brief current font color */
QColor color;
/** \brief current font */
JKQTMathTextEnvironmentFont font;
/** \brief custom font, when font==MTECustomFont */
QString customFontName;
/** \brief current font size the unit is determined by fontSizeUnit */
double fontSize;
/** \brief the unit of the font size fontSize */
FontSizeUnit fontSizeUnit;
/** \brief is the text currently bold? */
bool bold;
/** \brief is the text currently italic? */
bool italic;
/** \brief is the text currently in small caps? */
bool smallCaps;
/** \brief is the text currently underlined? */
bool underlined;
/** \brief is the text currently overlined? */
bool overline;
/** \brief is the text currently stroke through? */
bool strike;
/** \brief is the text currently are we inside a math environment? */
bool insideMath;
/** \brief if \a insideMath \c ==true and this is \c true (the default), then digits are forced to be typeset in upright, otherwise they are typeset as defined by the other properties */
bool insideMathForceDigitsUpright;
/** \brief sets insideMath \c =true and insideMathForceDigitsUpright \c =true */
void beginMathMode();
/** \brief sets insideMath \c =false and insideMathForceDigitsUpright \c =true */
void endMathMode();
/** \brief build a QFont object from the settings in this object */
QFont getFont(JKQTMathText* parent) const;
/** \brief return the encoding of the given Font */
JKQTMathTextFontEncoding getFontEncoding(JKQTMathText *parent) const;
/** \brief generate a HTML prefix that formats the text after it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlStart(JKQTMathTextEnvironment defaultEv, JKQTMathText *parentMathText) const;
/** \brief generate a HTML postfix that formats the text in front of it according to the settings in this object
*
* \param defaultEv environment before applying the current object (to detect changes)
* \see toHtmlAfter()
*/
QString toHtmlAfter(JKQTMathTextEnvironment defaultEv, JKQTMathText *parentMathText) const;
};
/** \brief beschreibt die Größe eines Knotens
* \ingroup jkqtmathtext_tools
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextNodeSize {
JKQTMathTextNodeSize();
double width;
double baselineHeight;
double overallHeight;
double strikeoutPos;
};
/** \brief summarizes all information available on a font for a specific MTenvironmentFont
* \ingroup jkqtmathtext_tools
* \see fontDefinitions
*/
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextFontDefinition {
JKQTMathTextFontDefinition();
/** \brief name of the font */
QString fontName;
/** \brief specifies the encoding of the font (default is \c MTFEwinSymbol ) */
JKQTMathTextFontEncoding fontEncoding;
};
/** \brief create a QPainterPath for drawing horizontal braces, use QPainter::fillPath() with a vanishing line-width to draw this
* \ingroup jkqtmathtext_tools
*
* \image html jkqtmathtext/JKQTMathTextMakeHBracePath.png
*
* \param x x-center-position of the brace
* \param ybrace y-center-position of the brace
* \param width with of the overall brace
2022-07-24 20:50:28 +08:00
* \param bw height of the brace
* \param lineWidth linewidth when drawing, used for correcting so the brace exactly fills the rectangle and not overshoots it
* \param cubicshrink
* \param cubiccontrolfac
* \param lineWidthShrinkFactor the width of the tips is lineWidth reduced by this factor
* \param lineWidthGrowFactor the width of the horizontal bars is increased by this factor from lineWidth
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeHBracePath(double x, double ybrace, double width, double bw, double lineWidth, double cubicshrink=0.5, double cubiccontrolfac=0.3, double lineWidthShrinkFactor=0.3, double lineWidthGrowFactor=0.9);
/** \brief create a QPainterPath for drawing horizontal arrows
* \ingroup jkqtmathtext_tools
*
* \image html jkqtmathtext/JKQTMathTextMakeArrow.png
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
/** \brief create a QPainterPath for drawing horizontal double arrows
* \ingroup jkqtmathtext_tools
*
* \image html jkqtmathtext/JKQTMathTextMakeDArrow.png
*/
JKQTMATHTEXT_LIB_EXPORT QPainterPath JKQTMathTextMakeDArrow(double x, double y, double width, double arrowW, bool left=false, bool right=true);
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRData {
explicit JKQTMathTextTBRData(const QFont& f, const QString& text, QPaintDevice *pd);
QFontMetricsF fm;
QString text;
QRectF tbr;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
//QPaintDevice *pd;
bool operator==(const JKQTMathTextTBRData& other) const;
};
struct JKQTMATHTEXT_LIB_EXPORT JKQTMathTextTBRDataH {
explicit JKQTMathTextTBRDataH(const QFont& f, const QString& text, QPaintDevice *pd);
QString text;
QFont f;
int ldpiX, ldpiY, pdpiX, pdpiY;
bool operator==(const JKQTMathTextTBRDataH& other) const;
};
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
inline size_t qHash(const JKQTMathTextTBRDataH& data, size_t /*seed=0*/) {
#else
inline uint qHash(const JKQTMathTextTBRDataH& data) {
#endif
return qHash(data.f.family())+qHash(data.text);
}
/** \brief calculates the tight bounding rectangle around \a text, uses internal hashing to not redo a calculation that has already been performed
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QRectF JKQTMathTextGetTightBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
/** \brief returns a copy of \a f, but with the italic-property set to \c false
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QFont JKQTMathTextGetNonItalic(const QFont& f);
/** \brief types of horizontal alignment
* \ingroup jkqtmathtext_tools
*
* \image html jkqtmathtext_horizontalalignment.png
*
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode
*/
enum JKQTMathTextHorizontalAlignment {
MTHALeft, /*!< \brief align left */
MTHACentered, /*!< \brief align centered */
MTHARight, /*!< \brief align right */
};
/** \brief convert a JKQTMathTextHorizontalAlignment into a string
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextHorizontalAlignment2String(JKQTMathTextHorizontalAlignment type);
/** \brief convert a string \a tokenName into a JKQTMathTextHorizontalAlignment
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextHorizontalAlignment String2JKQTMathTextHorizontalAlignment(QString tokenName);
/** \brief type of ffractions represented by JKQTMathTextFracNode
* \ingroup jkqtmathtext_tools
*
* \image html jkqtmathtext_verticalorientation.png
*
* \see JKQTMathTextVerticalOrientation2String(), String2JKQTMathTextVerticalOrientation(), JKQTMathTextVerticalListNode
*/
enum JKQTMathTextVerticalOrientation {
MTVOTop, /*!< \brief baseline of the whole block is at the top of the first */
MTVOFirstLine, /*!< \brief baseline of the whole block is at the baseline of the first line */
MTVOCentered, /*!< \brief baseline of the whole block is at the center of all lines */
MTVOLastLine, /*!< \brief baseline of the whole block is at the baseline of the last line */
MTVOBottom, /*!< \brief baseline of the whole block is at the bottom of the last line */
};
/** \brief convert a JKQTMathTextVerticalOrientation into a QString
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT QString JKQTMathTextVerticalOrientation2String(JKQTMathTextVerticalOrientation mode);
/** \brief returns the JKQTMathTextVerticalOrientation corresponding to \a instructionName
* \ingroup jkqtmathtext_tools
*/
JKQTMATHTEXT_LIB_EXPORT JKQTMathTextVerticalOrientation String2JKQTMathTextVerticalOrientation(QString mode);
#endif // JKQTMATHTEXTTOOLS_H