/* Copyright (c) 2008-2022 Jan W. Krieger () 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 . */ #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 #include #include #include #include #include #include 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); baselineHeight=0; overallHeight=0; strikeoutPos=fm.strikeOutPos(); } QHash JKQTMathTextWhitespaceNode::supportedInstructions; void JKQTMathTextWhitespaceNode::fillSupportedInstructions() { if (supportedInstructions.size()==0) { supportedInstructions[" "]=WhitespaceProps(WSTthicker, 1); supportedInstructions["nbsp"]=WhitespaceProps(WSTNonbreaking, 1); supportedInstructions["enspace"]=supportedInstructions["enskip"]=WhitespaceProps(WST1en, 1); 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 "???"; } double JKQTMathTextWhitespaceNode::Type2PixelWidth(Types type, JKQTMathTextEnvironment currentEv, QPaintDevice* pd) const { const QFontMetricsF fm(currentEv.getFont(parentMathText), pd); #if (QT_VERSION>=QT_VERSION_CHECK(5, 15, 0)) const double em=fm.horizontalAdvance(QChar(0x2003));//currentEv.fontSize; const double sp=fm.horizontalAdvance(' ');//currentEv.fontSize; #else const double em=fm.width(QChar(0x2003));//currentEv.fontSize; const double sp=fm.width(' ');//currentEv.fontSize; #endif const double en=em/2.0; switch (type) { case WSTNormal: return sp; case WSTNonbreaking: return sp; 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 " "; } 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(); }