2022-07-04 02:30:12 +08:00
/*
Copyright ( c ) 2008 - 2022 Jan W . Krieger ( < jan @ jkrieger . de > )
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/>.
*/
# include "jkqtmathtext/nodes/jkqtmathtextwhitespacenode.h"
# include "jkqtmathtext/jkqtmathtexttools.h"
# include "jkqtmathtext/nodes/jkqtmathtextnode.h"
# include "jkqtmathtext/jkqtmathtext.h"
# include "jkqtcommon/jkqtpcodestructuring.h"
# include "jkqtcommon/jkqtpstringtools.h"
# include <cmath>
# include <QFontMetricsF>
# include <QDebug>
# include <QFontDatabase>
# include <QFontInfo>
# include <QApplication>
# include <QFont>
JKQTMathTextWhitespaceNode : : JKQTMathTextWhitespaceNode ( Types type , JKQTMathText * _parent ) :
JKQTMathTextWhitespaceNode ( type , 1 , _parent )
{
}
JKQTMathTextWhitespaceNode : : JKQTMathTextWhitespaceNode ( JKQTMathText * _parent ) :
JKQTMathTextWhitespaceNode ( WSTNormal , 1 , _parent )
{
}
JKQTMathTextWhitespaceNode : : JKQTMathTextWhitespaceNode ( const QString & _type , JKQTMathText * parent ) :
JKQTMathTextWhitespaceNode ( parent )
{
fillSupportedInstructions ( ) ;
whitespace = supportedInstructions [ _type ] ;
}
JKQTMathTextWhitespaceNode : : JKQTMathTextWhitespaceNode ( const QString & _type , size_t count , JKQTMathText * parent ) :
JKQTMathTextWhitespaceNode ( parent )
{
fillSupportedInstructions ( ) ;
whitespace = supportedInstructions [ _type ] ;
whitespace . count = whitespace . count * count ;
}
JKQTMathTextWhitespaceNode : : JKQTMathTextWhitespaceNode ( Types type , size_t count , JKQTMathText * parent ) :
JKQTMathTextNode ( parent ) ,
whitespace ( type , count )
{
fillSupportedInstructions ( ) ;
}
JKQTMathTextWhitespaceNode : : ~ JKQTMathTextWhitespaceNode ( ) {
}
QString JKQTMathTextWhitespaceNode : : getTypeName ( ) const
{
return QLatin1String ( " JKQTMathTextWhitespaceNode( " ) + Type2String ( whitespace . type ) + " , count= " + QString : : number ( whitespace . count ) + " ) " ;
}
bool JKQTMathTextWhitespaceNode : : toHtml ( QString & html , JKQTMathTextEnvironment /*currentEv*/ , JKQTMathTextEnvironment /*defaultEv*/ ) {
for ( size_t i = 0 ; i < whitespace . count ; i + + ) {
html = html + Type2HTML ( whitespace . type ) ;
}
return true ;
}
JKQTMathTextWhitespaceNode : : WhitespaceProps : : WhitespaceProps ( JKQTMathTextWhitespaceNode : : Types _type , size_t _count ) :
type ( _type ) , count ( _count )
{
}
JKQTMathTextWhitespaceNode : : Types JKQTMathTextWhitespaceNode : : getWhitespaceType ( ) const
{
return whitespace . type ;
}
size_t JKQTMathTextWhitespaceNode : : getWhitespaceCount ( ) const
{
return whitespace . count ;
}
2022-08-03 15:55:45 +08:00
double JKQTMathTextWhitespaceNode : : draw ( QPainter & painter , double x , double y , JKQTMathTextEnvironment currentEv , const JKQTMathTextNodeSize * prevNodeSize )
2022-07-04 02:30:12 +08:00
{
2022-08-03 15:55:45 +08:00
doDrawBoxes ( painter , x , y , currentEv ) ;
2022-07-04 02:30:12 +08:00
double width = 0 , bh = 0 , oh = 0 , sp = 0 ;
getSize ( painter , currentEv , width , bh , oh , sp , prevNodeSize ) ;
return x + width ;
}
2022-07-22 04:17:37 +08:00
void JKQTMathTextWhitespaceNode : : getSizeInternal ( QPainter & painter , JKQTMathTextEnvironment currentEv , double & width , double & baselineHeight , double & overallHeight , double & strikeoutPos , const JKQTMathTextNodeSize */ * prevNodeSize */ )
2022-07-04 02:30:12 +08:00
{
2022-07-05 03:02:43 +08:00
const double singelWidthPIX = Type2PixelWidth ( whitespace . type , currentEv , painter . device ( ) ) ;
2022-07-04 02:30:12 +08:00
const QFontMetricsF fm ( currentEv . getFont ( parentMathText ) ) ;
width = singelWidthPIX * static_cast < double > ( whitespace . count ) ;
baselineHeight = 0 ;
overallHeight = 0 ;
strikeoutPos = fm . strikeOutPos ( ) ;
}
QHash < QString , JKQTMathTextWhitespaceNode : : WhitespaceProps > JKQTMathTextWhitespaceNode : : supportedInstructions ;
void JKQTMathTextWhitespaceNode : : fillSupportedInstructions ( )
{
if ( supportedInstructions . size ( ) = = 0 ) {
supportedInstructions [ " " ] = WhitespaceProps ( WSTthicker , 1 ) ;
supportedInstructions [ " nbsp " ] = WhitespaceProps ( WSTNonbreaking , 1 ) ;
2022-07-05 03:02:43 +08:00
supportedInstructions [ " enspace " ] = supportedInstructions [ " enskip " ] = WhitespaceProps ( WST1en , 1 ) ;
2022-07-04 02:30:12 +08:00
supportedInstructions [ " quad " ] = supportedInstructions [ " emspace " ] = WhitespaceProps ( WSTQuad , 1 ) ;
supportedInstructions [ " qquad " ] = WhitespaceProps ( WSTQuad , 2 ) ;
supportedInstructions [ " , " ] = supportedInstructions [ " thinspace " ] = WhitespaceProps ( WSTthin , 1 ) ;
supportedInstructions [ " : " ] = supportedInstructions [ " medspace " ] = WhitespaceProps ( WSTmedium , 1 ) ;
supportedInstructions [ " ; " ] = supportedInstructions [ " thickspace " ] = WhitespaceProps ( WSTthick , 1 ) ;
supportedInstructions [ " ! " ] = supportedInstructions [ " negthinspace " ] = WhitespaceProps ( WSTnegthin , 1 ) ;
supportedInstructions [ " negmedspace " ] = WhitespaceProps ( WSTnegmedium , 1 ) ;
supportedInstructions [ " negthickspace " ] = WhitespaceProps ( WSTnegthick , 1 ) ;
}
}
QString JKQTMathTextWhitespaceNode : : Type2String ( Types type )
{
switch ( type ) {
case WSTNormal : return " WSTNormal " ;
case WSTNonbreaking : return " WSTNonbreaking " ;
case WST1en : return " WST1en " ;
case WST1em : return " WST1em " ;
case WSThair : return " WSThair " ;
case WSTthin : return " WSTthin " ;
case WSTnegthin : return " WSTnegthin " ;
case WSTmedium : return " WSTmedium " ;
case WSTnegmedium : return " WSTnegmedium " ;
case WSTthick : return " WSTthick " ;
case WSTnegthick : return " WSTnegthick " ;
case WSTthicker : return " WSTthicker " ;
}
return " ??? " ;
}
2022-07-05 03:02:43 +08:00
double JKQTMathTextWhitespaceNode : : Type2PixelWidth ( Types type , JKQTMathTextEnvironment currentEv , QPaintDevice * pd ) const
2022-07-04 02:30:12 +08:00
{
2022-07-05 03:02:43 +08:00
const QFontMetricsF fm ( currentEv . getFont ( parentMathText ) , pd ) ;
2022-07-06 02:14:51 +08:00
# if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
2022-07-05 03:02:43 +08:00
const double em = fm . horizontalAdvance ( QChar ( 0x2003 ) ) ; //currentEv.fontSize;
2022-07-06 02:14:51 +08:00
const double sp = fm . horizontalAdvance ( ' ' ) ; //currentEv.fontSize;
2022-07-05 03:02:43 +08:00
# else
const double em = fm . width ( QChar ( 0x2003 ) ) ; //currentEv.fontSize;
2022-07-06 02:14:51 +08:00
const double sp = fm . width ( ' ' ) ; //currentEv.fontSize;
2022-07-05 03:02:43 +08:00
# endif
2022-07-04 02:30:12 +08:00
const double en = em / 2.0 ;
switch ( type ) {
2022-07-06 02:14:51 +08:00
case WSTNormal : return sp ;
case WSTNonbreaking : return sp ;
2022-07-04 02:30:12 +08:00
case WST1en : return en ;
case WST1em : return em ;
case WSThair : return em / 12.0 ;
case WSTthin : return em / 6.0 ;
case WSTnegthin : return - em / 6.0 ;
case WSTmedium : return em * 2.0 / 9.0 ;
case WSTnegmedium : return - em * 2.0 / 9.0 ;
case WSTthick : return em * 5.0 / 18.0 ;
case WSTnegthick : return - em * 5.0 / 18.0 ;
case WSTthicker : return em / 3.0 ;
}
return 0.0 ;
}
bool JKQTMathTextWhitespaceNode : : supportsInstructionName ( const QString & instruction )
{
fillSupportedInstructions ( ) ;
return supportedInstructions . contains ( instruction ) ;
}
QString JKQTMathTextWhitespaceNode : : Type2HTML ( Types type )
{
switch ( type ) {
case WSTNonbreaking : return " " ;
case WST1en : return "   " ;
case WST1em : return "   " ;
case WSThair : return " &hairsp " ;
case WSTthin : return "   " ;
case WSTnegthin : return " " ;
case WSTmedium : return "   " ;
case WSTnegmedium : return " " ;
case WSTthick : return "   " ;
case WSTnegthick : return " " ;
case WSTthicker : return "    " ;
case WSTNormal :
default :
return " " ;
}
return " " ;
}
2022-08-03 15:55:45 +08:00
QString JKQTMathTextEmptyBoxNode : : Units2String ( Units type )
{
switch ( type ) {
case EBUem : return " em " ;
case EBUex : return " ex " ;
}
return " ? " ;
}
JKQTMathTextEmptyBoxNode : : Units JKQTMathTextEmptyBoxNode : : String2Units ( QString type )
{
type = type . toLower ( ) . trimmed ( ) ;
if ( type = = " ex " ) return EBUex ;
if ( type = = " em " ) return EBUem ;
return EBUem ;
}
double JKQTMathTextEmptyBoxNode : : Units2PixelWidth ( double value , Units unit , JKQTMathTextEnvironment currentEv , QPaintDevice * pd ) const
{
const QFontMetricsF fm ( currentEv . getFont ( parentMathText ) , pd ) ;
if ( unit = = EBUem ) {
# if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0))
const double em = fm . horizontalAdvance ( QChar ( 0x2003 ) ) ; //currentEv.fontSize;
# else
const double em = fm . width ( QChar ( 0x2003 ) ) ; //currentEv.fontSize;
# endif
return value * em ;
} else if ( unit = = EBUex ) {
const double ex = fm . xHeight ( ) ;
return value * ex ;
}
return 0 ;
}
JKQTMathTextEmptyBoxNode : : JKQTMathTextEmptyBoxNode ( JKQTMathText * parent , double width_ , Units widthUnit_ , double height_ , Units heightUnit_ ) :
JKQTMathTextNode ( parent ) ,
width ( width_ ) , widthUnit ( widthUnit_ ) ,
height ( height_ ) , heightUnit ( heightUnit_ )
{
}
JKQTMathTextEmptyBoxNode : : ~ JKQTMathTextEmptyBoxNode ( )
{
}
QString JKQTMathTextEmptyBoxNode : : getTypeName ( ) const
{
return QString ( " JKQTMathTextEmptyBoxNode(%1%2 x %3%4) " ).arg(getWidth()).arg(JKQTMathTextEmptyBoxNode::Units2String(getWidthUnit())).arg(getHeight()).arg(JKQTMathTextEmptyBoxNode::Units2String(getHeightUnit())) ;
}
bool JKQTMathTextEmptyBoxNode : : toHtml ( QString & html , JKQTMathTextEnvironment currentEv , JKQTMathTextEnvironment defaultEv )
{
return true ;
}
JKQTMathTextEmptyBoxNode : : Units JKQTMathTextEmptyBoxNode : : getWidthUnit ( ) const
{
return widthUnit ;
}
double JKQTMathTextEmptyBoxNode : : getWidth ( ) const
{
return width ;
}
JKQTMathTextEmptyBoxNode : : Units JKQTMathTextEmptyBoxNode : : getHeightUnit ( ) const
{
return heightUnit ;
}
double JKQTMathTextEmptyBoxNode : : getHeight ( ) const
{
return height ;
}
double JKQTMathTextEmptyBoxNode : : draw ( QPainter & painter , double x , double y , JKQTMathTextEnvironment currentEv , const JKQTMathTextNodeSize * prevNodeSize )
{
doDrawBoxes ( painter , x , y , currentEv ) ;
double width = 0 , bh = 0 , oh = 0 , sp = 0 ;
getSize ( painter , currentEv , width , bh , oh , sp , prevNodeSize ) ;
return x + width ;
}
void JKQTMathTextEmptyBoxNode : : getSizeInternal ( QPainter & painter , JKQTMathTextEnvironment currentEv , double & width , double & baselineHeight , double & overallHeight , double & strikeoutPos , const JKQTMathTextNodeSize */ * prevNodeSize */ )
{
const QFontMetricsF fm ( currentEv . getFont ( parentMathText ) , painter . device ( ) ) ;
width = Units2PixelWidth ( width , widthUnit , currentEv , painter . device ( ) ) ;
overallHeight = Units2PixelWidth ( height , heightUnit , currentEv , painter . device ( ) ) ;
if ( height > 0 ) {
baselineHeight = overallHeight ;
} else {
baselineHeight = 0 ;
}
strikeoutPos = fm . strikeOutPos ( ) ;
}