- NEW: JKQTMathText supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
- NEW: JKQTMathText: reworked drawing of decorations: improved appearance and positioning!
@ -26,7 +26,8 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<li>NEW: new "seaborn" style for plots</li>
|
||||
<li>NEW/BREAKING CHANGE: changed JKQTPColorDerivationMode into a struct, which extends its capabilities above the previously available few enum-items</li>
|
||||
<li>NEW: added debug-feature to show boxes around text in the plot</li>
|
||||
<li>NEW: JKQTMathText supports new instructions: \cancel, \xcancel, \bcancel, \sout</li>
|
||||
<li>NEW: JKQTMathText supports new decoration instructions: \cancel, \xcancel, \bcancel, \sout, \ocirc, \widetilde, \widehat, \breve</li>
|
||||
<li>NEW: JKQTMathText: reworked drawing of decorations: improved appearance and positioning!</li>
|
||||
</ul>
|
||||
|
||||
\subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
doc/images/mathparser/MTDbreve.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
doc/images/mathparser/MTDcheck.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
doc/images/mathparser/MTDocirc.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
doc/images/mathparser/MTDwidecheck.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
doc/images/mathparser/MTDwidehat.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
doc/images/mathparser/MTDwidetilde.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
doc/images/mathparser/decoration_sizing.png
Normal file
After Width: | Height: | Size: 26 KiB |
352
doc/images/mathparser/decoration_sizing.svg
Normal file
@ -0,0 +1,352 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="116.54318mm"
|
||||
height="40.395004mm"
|
||||
viewBox="0 0 116.54318 40.395004"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
|
||||
sodipodi:docname="decoration_sizing.svg"
|
||||
inkscape:export-filename="C:\Jan\Programmieren\JKQtPlotter\doc\images\mathparser\decoration_sizing.png"
|
||||
inkscape:export-xdpi="132.17781"
|
||||
inkscape:export-ydpi="132.17781"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="7.2466938"
|
||||
inkscape:cx="281.57668"
|
||||
inkscape:cy="91.352004"
|
||||
inkscape:window-width="2240"
|
||||
inkscape:window-height="1294"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2Sstart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Sstart"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="matrix(0.3,0,0,0.3,-0.69,0)"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
|
||||
id="path41032" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2Send"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Send"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="matrix(-0.3,0,0,-0.3,0.69,0)"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
|
||||
id="path41035" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2Mend"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
transform="scale(-0.6)"
|
||||
d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.625;stroke-linejoin:round"
|
||||
id="path41029" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0.37879707,-54.001381)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="58.922813"
|
||||
y="87.494171"
|
||||
id="text2036"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2034"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:serif;fill:#808080;stroke-width:0.738106"
|
||||
x="58.922813"
|
||||
y="87.494171">X</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="154.56786"
|
||||
y="264.95605"
|
||||
id="text2436"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2434"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:serif;stroke-width:0.738106"
|
||||
x="154.56786"
|
||||
y="264.95605" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="30.565086"
|
||||
y="149.89005"
|
||||
id="text2436-4"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2434-5"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:serif;fill:#000000;stroke-width:0.738106"
|
||||
x="30.565086"
|
||||
y="149.89005" /></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 62.808775,94.396386 V 62.305722"
|
||||
id="path30140" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 78.174032,88.591152 V 56.500488"
|
||||
id="path40820" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="60.612206"
|
||||
y="87.475121"
|
||||
id="text2036-2"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2034-1"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:'serif Italic';fill:#000000;stroke-width:0.738106"
|
||||
x="60.612206"
|
||||
y="87.475121">X</tspan></text>
|
||||
<path
|
||||
style="fill:#ff0000;stroke:#ff0000;stroke-width:0.174917;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 81.865878,93.921744 V 56.500488"
|
||||
id="path40929" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.259281px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 59.522835,56.500487 H 77.819642"
|
||||
id="path41000" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="61.677063"
|
||||
y="55.61005"
|
||||
id="text42860"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan42858"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#ffaaaa;stroke-width:0.264583"
|
||||
x="61.677063"
|
||||
y="55.61005">width_nonitalic</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.283136px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 59.594994,61.56064 H 81.413512"
|
||||
id="path47490" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="59.585876"
|
||||
y="60.670204"
|
||||
id="text47494"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan47492"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#ff0000;stroke-width:0.264583"
|
||||
x="59.585876"
|
||||
y="60.670204">width_possiblyitalic</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:0.268864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 81.482279,58.126965 H 78.628775"
|
||||
id="path52452" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="82.640556"
|
||||
y="58.604836"
|
||||
id="text52474"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan52472"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#0000ff;stroke-width:0.264583"
|
||||
x="82.640556"
|
||||
y="58.604836">italic_xcorrectoin</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#008000;stroke-width:1.14943;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 64.911552,64.753716 h 14.099882 l -3.49997,-1.738871"
|
||||
id="path59089" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#008000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="46.29007"
|
||||
y="65.62709"
|
||||
id="text62089"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan62087"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#008000;stroke-width:0.264583"
|
||||
x="46.29007"
|
||||
y="65.62709">decoration</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#008000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="46.29007"
|
||||
y="76.41864"
|
||||
id="text66311"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan66309"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;stroke-width:0.264583"
|
||||
x="46.29007"
|
||||
y="76.41864">decorated</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;stroke-width:0.264583"
|
||||
x="46.29007"
|
||||
y="79.064476"
|
||||
id="tspan66335">text block</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#0000ff;stroke-width:0.268864;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 62.429254,64.68451 H 59.57575"
|
||||
id="path68697" />
|
||||
<path
|
||||
style="fill:none;stroke:#00ff00;stroke-width:0.204488;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="m 63.042888,64.68451 h 1.650626"
|
||||
id="path68699" />
|
||||
<path
|
||||
style="fill:none;stroke:#00ff00;stroke-width:0.204488;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="m 79.824008,64.68451 h 1.650626"
|
||||
id="path68719" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="82.640556"
|
||||
y="65.265648"
|
||||
id="text68723"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan68721"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#00ff00;stroke-width:0.264583"
|
||||
x="82.640556"
|
||||
y="65.265648">decoration_width_reduction_Xfactor</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#00ff00;stroke-width:0.264583"
|
||||
x="82.640556"
|
||||
y="67.911484"
|
||||
id="tspan79301"> / 2 * width("X")</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="19.614639"
|
||||
y="87.475121"
|
||||
id="text70976"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan70974"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:'serif Italic';fill:#000000;stroke-width:0.738106"
|
||||
x="19.614639"
|
||||
y="87.475121">X</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#008000;stroke-width:1.14943;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 23.913986,64.753716 h 14.099882 l -3.49997,-1.738871"
|
||||
id="path70978" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 83.066541,87.468108 H 16.432587"
|
||||
id="path71150"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 83.066541,66.29808 H 16.432587"
|
||||
id="path71289"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 43.308196,64.697419 H 16.432587"
|
||||
id="path71291"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#00ff00;stroke-width:0.204488;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 18.017019,66.004509 V 64.943516"
|
||||
id="path71457"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff0000;stroke-width:0.283136px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 17.204484,86.922066 17.240995,66.78305"
|
||||
id="path71672"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="-84.37542"
|
||||
y="16.314053"
|
||||
id="text71676"
|
||||
transform="rotate(-90)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan71674"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#ff0000;stroke-width:0.264583"
|
||||
x="-84.37542"
|
||||
y="16.314053">baseline_height</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#008000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="-0.48039722"
|
||||
y="63.43644"
|
||||
id="text73109"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan73107"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#00ff00;stroke-width:0.264583"
|
||||
x="-0.48039722"
|
||||
y="63.43644">decoration_height_factor </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#00ff00;stroke-width:0.264583"
|
||||
x="-0.48039722"
|
||||
y="66.082275"
|
||||
id="tspan78903">* baseline_height</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.5242px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.738106"
|
||||
x="60.612206"
|
||||
y="87.475121"
|
||||
id="text80682"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan80680"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:serif;-inkscape-font-specification:'serif Italic';fill:#000000;stroke-width:0.738106"
|
||||
x="60.612206"
|
||||
y="87.475121">X</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ffaaaa;stroke-width:0.15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 59.230707,88.591152 V 56.500488"
|
||||
id="path80684" />
|
||||
<path
|
||||
style="fill:#808000;stroke:#808000;stroke-width:0.259281px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"
|
||||
d="M 63.210436,89.031701 H 81.507243"
|
||||
id="path80686" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:2.11667px;line-height:1.25;font-family:sans-serif;fill:#808000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="63.685162"
|
||||
y="91.062141"
|
||||
id="text80690"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan80688"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#808000;stroke-width:0.264583"
|
||||
x="63.685162"
|
||||
y="91.062141">width </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11667px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';fill:#808000;stroke-width:0.264583"
|
||||
x="63.685162"
|
||||
y="93.707977"
|
||||
id="tspan82712">- italic_xcorrection</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 19 KiB |
@ -29,7 +29,8 @@ TestForm::TestForm(QWidget *parent) :
|
||||
ui->cmbTestset->addItem("text 0", "text");
|
||||
ui->cmbTestset->addItem("text 1", "text \\mathbf{bold}");
|
||||
ui->cmbTestset->addItem("text 2", "text \\mathbf{bold}\\textcolor{red}{RED}");
|
||||
ui->cmbTestset->addItem("decoration: math", "$\\vec{x}\\vec{X}\\vec{\\psi} -- \\dot{x}\\dot{X}\\dot{\\psi} -- \\ddot{x}\\ddot{X}\\ddot{\\psi} -- \\overline{x}\\overline{X}\\overline{\\psi} -- \\underline{x}\\underline{X}\\underline{\\psi} -- \\hat{x}\\hat{X}\\hat{\\psi} -- \\tilde{x}\\tilde{X}\\tilde{\\psi} -- \\uul{x}\\uul{X}\\uul{\\psi} -- \\ool{x}\\ool{X}\\ool{\\psi} -- \\bar{x}\\bar{X}\\bar{\\psi} -- \\arrow{x}\\arrow{X}\\arrow{\\psi} -- \\cancel{x}\\cancel{X}\\cancel{\\psi} -- \\bcancel{x}\\bcancel{X}\\bcancel{\\psi} -- \\xcancel{x}\\xcancel{X}\\xcancel{\\psi} -- \\sout{x}\\sout{X}\\sout{\\psi}$");
|
||||
const auto mathDecoExample=[](const QString& deco)->QString { return "\\"+deco+"{x}\\"+deco+"{i}\\"+deco+"{X}\\"+deco+"{\\psi}\\"+deco+"{abc}"; };
|
||||
ui->cmbTestset->addItem("decoration: math", "$"+mathDecoExample("vec")+" -- "+mathDecoExample("dot")+" -- "+mathDecoExample("ddot")+" -- "+mathDecoExample("ocirc")+" -- "+mathDecoExample("overline")+" -- "+mathDecoExample("underline")+" -- "+mathDecoExample("hat")+" -- "+mathDecoExample("widehat")+" -- "+mathDecoExample("check")+" -- "+mathDecoExample("widecheck")+" -- "+mathDecoExample("breve")+" -- "+mathDecoExample("tilde")+" -- "+mathDecoExample("widetilde")+" -- "+mathDecoExample("uul")+" -- "+mathDecoExample("ool")+" -- "+mathDecoExample("bar")+" -- "+mathDecoExample("arrow")+" -- "+mathDecoExample("cancel")+" -- "+mathDecoExample("bcancel")+" -- "+mathDecoExample("xcancel")+" -- "+mathDecoExample("sout")+"$");
|
||||
ui->cmbTestset->addItem("decoration: text", "Text \\ul{underlined Text Equator} -- \\ol{overlined Text Equator} -- \\sout{striked out Text Equator} -- \\cancel{canceled out Text Equator} -- \\bcancel{b-canceled out Text Equator} -- \\xcancel{x-canceled out Text Equator}");
|
||||
ui->cmbTestset->addItem("mathtest", "This is normal text: $this is math:\\langle r^2(\\tau)\\rangle=\\left\\langle (\\vec{r}(t)-\\vec{r}(t+\\tau) )^2\\right\\rangle\\ \\ \\ g(\\tau)=\\frac{1}{N}\\cdot\\left(1+\\frac{2}{3}\\frac{\\langle r^2(\\tau)\\rangle}{w_{xy}^2}\\right)^{-1} \\lfloor\\rfloor\\lceil\\rceil\\langle\\rangle\\left\\{\\va\\left|\\|\\va\\|_2\\geq2\\right.\\right\\} \\vr\\vR\\frac{\\sqrt{\\sqrt{\\sqrt{\\sum_{i=0}^\\infty \\hat{i}^2}+y^\\alpha}+1}}{\\dot{v}\\equiv\\ddot{r}}\\argmin_{\\vec{k}}\\sum_{\\sqrt{i}=0}^{N}\\int_{x_0}^{x_1}\\left(\\left(\\left(x\\right)\\right)\\right)\\underbrace{\\left[\\left\\{\\frac{\\partial f}{\\partial x}\\right\\}\\cdot\\frac{1}{2}\\right]}{\\text{underbraced text \\hbar}}\\cdots\\frac{\\sqrt{\\sum_{i=0}^2 \\hat{i}^2}+y^\\alpha}{\\dot{v}\\equiv\\ddot{r}}, \\hat{t}\\hat{T} \\overbrace{\\left|\\sqrt{x\\cdot Y}\\right|}{\\propto\\bbN\\circ\\bbZ} \\left<\\arrow{x(\\tau)}\\cdot\\vec{R}(t+\\bar{\\tau})\\right> \\alpha\\beta\\gamma\\delta\\epsilon\\Gamma\\Delta\\Theta\\Omega \\left\\_\\left~\\cbrt{\\hbar\\omega}\\right~\\right\\_$");
|
||||
ui->cmbTestset->addItem("upper/lower parantheses test:", "$\\text{bblabla} \\frac{1}{2}\\cdot\\left(\\frac{1}{\\mathrm{e}^x+\\mathrm{e}^{-x}}\\right)\\cdot\\left(\\frac{1}{\\frac{1+2}{5+x}}\\right)\\cdot\\left(\\frac{1}{\\exp\\left[-\\frac{y^2}{\\sqrt{x}}\\right]\\cdot\\exp\\left[-\\frac{1}{\\frac{1}{2}}\\right]}\\right) $");
|
||||
|
@ -206,6 +206,21 @@ void JKQTMathText::MTnode::getSize(QPainter &painter, JKQTMathText::MTenvironmen
|
||||
if (s<1e5) strikeoutPos=s;
|
||||
}
|
||||
|
||||
|
||||
double JKQTMathText::MTnode::getNonItalicXCorretion(QPainter &painter, double width_potentiallyitalic, const MTenvironment &ev_potentiallyitalic, JKQTMathText::MTnode* child) const
|
||||
{
|
||||
double italic_xcorrection=0.0;
|
||||
if (ev_potentiallyitalic.italic) {
|
||||
MTenvironment ev_nonitalic=ev_potentiallyitalic;
|
||||
ev_nonitalic.italic=false;
|
||||
double width_nonitalic=0, baselineHeight_nonitalic=0, overallHeight_nonitalic=0, strikeoutPos_nonitalic=0;
|
||||
child->getSize(painter, ev_nonitalic, width_nonitalic, baselineHeight_nonitalic, overallHeight_nonitalic, strikeoutPos_nonitalic);
|
||||
italic_xcorrection=width_potentiallyitalic-width_nonitalic;
|
||||
}
|
||||
return italic_xcorrection;
|
||||
}
|
||||
|
||||
|
||||
bool JKQTMathText::MTnode::toHtml(QString &/*html*/, JKQTMathText::MTenvironment /*currentEv*/, JKQTMathText::MTenvironment /*defaultEv*/) {
|
||||
return false;
|
||||
}
|
||||
@ -1147,15 +1162,25 @@ JKQTMathText::MTdecoratedNode::~MTdecoratedNode() {
|
||||
}
|
||||
|
||||
void JKQTMathText::MTdecoratedNode::getSizeInternal(QPainter& painter, JKQTMathText::MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* /*prevNodeSize*/) {
|
||||
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
|
||||
double wc=fm.boundingRect("A").width();
|
||||
double dheightfactor=1.0+parent->getDecorationHeightFactor()*2.0;
|
||||
const QFontMetricsF fm(currentEv.getFont(parent), painter.device());
|
||||
|
||||
child->getSize(painter, currentEv, width, baselineHeight, overallHeight, strikeoutPos);
|
||||
|
||||
overallHeight=overallHeight*dheightfactor;
|
||||
baselineHeight=baselineHeight*dheightfactor;
|
||||
width=width+0.3*wc;
|
||||
const double italic_xcorrection=getNonItalicXCorretion(painter, width, currentEv, child);
|
||||
const double decoheightfactor=parent->getDecorationHeightFactor();
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("~").width():fm.boundingRect("^").width())-italic_xcorrection;
|
||||
|
||||
const double decoAboveAscent_yposdelta=fm.ascent()*(1.0+2.0*decoheightfactor);
|
||||
const double decoAboveBaselineheight_yposdelta=baselineHeight*(1.0+decoheightfactor);
|
||||
|
||||
|
||||
const double descent=overallHeight-baselineHeight;
|
||||
baselineHeight=decoAboveBaselineheight_yposdelta;
|
||||
if (decoration==MTDbar) {
|
||||
baselineHeight=std::max<double>(baselineHeight, decoAboveAscent_yposdelta);
|
||||
}
|
||||
overallHeight=baselineHeight+descent;
|
||||
width=std::max<double>(deco_miniwidth,width);
|
||||
}
|
||||
|
||||
double JKQTMathText::MTdecoratedNode::draw(QPainter& painter, double x, double y, JKQTMathText::MTenvironment currentEv, const MTnodeSize* /*prevNodeSize*/) {
|
||||
@ -1163,135 +1188,198 @@ double JKQTMathText::MTdecoratedNode::draw(QPainter& painter, double x, double y
|
||||
MTenvironment ev=currentEv;
|
||||
double width=0, baselineHeight=0, overallHeight=0, strikeoutPos=0;
|
||||
child->getSize(painter, ev, width, baselineHeight, overallHeight, strikeoutPos);
|
||||
QFontMetricsF fm(ev.getFont(parent), painter.device());
|
||||
double w=width;
|
||||
double wc=fm.boundingRect("A").width();
|
||||
//double ll=wc*0.8;
|
||||
double a=baselineHeight;
|
||||
//double d=overallHeight-baselineHeight;
|
||||
double dheightfactor=parent->getDecorationHeightFactor();
|
||||
double dpos=y-a*(1.0+dheightfactor);
|
||||
double spos=y-a/2.0;
|
||||
double dposb=y+qMax((overallHeight-baselineHeight)*(1.0+dheightfactor), fm.xHeight()*dheightfactor);
|
||||
double deltax=0;//(wc-ll)/2.0;
|
||||
double dheight=dheightfactor*a;
|
||||
const QFont font=ev.getFont(parent);
|
||||
const QFontMetricsF fm(font, painter.device());
|
||||
const double width_X=fm.boundingRect("X").width();
|
||||
const double width_x=fm.boundingRect("x").width();
|
||||
const double width_dot=fm.boundingRect(".").width()/2.0;
|
||||
const double decoheightfactor=parent->getDecorationHeightFactor();
|
||||
const double deco_ypos=y-baselineHeight*(1.0+decoheightfactor);
|
||||
const double decoAboveAscent_ypos=y-fm.ascent()*(1.0+decoheightfactor);
|
||||
const double strike_ypos=y-baselineHeight/2.0;
|
||||
const double decobelow_ypos=y+qMax((overallHeight-baselineHeight)*(1.0+decoheightfactor), fm.xHeight()*decoheightfactor);
|
||||
const double deco_height=decoheightfactor*baselineHeight;
|
||||
const double italic_xcorrection=getNonItalicXCorretion(painter, width, ev, child);
|
||||
const double deco_xoffset=parent->getDecorationWidthReductionXFactor()*width_X/2.0;
|
||||
const double deco_width=std::max<double>(width_x*0.5,width-2.0*deco_xoffset-italic_xcorrection);
|
||||
const double deco_vecwidth=width_x*0.33;
|
||||
const double deco_miniwidth=((decoration==MTDtilde||decoration==MTDbreve)?fm.boundingRect("~").width():fm.boundingRect("^").width())-italic_xcorrection;
|
||||
const double decotop_xcenter=x+italic_xcorrection+(width-italic_xcorrection)/2.0;
|
||||
const double decotop_xstart=decotop_xcenter-deco_width/2.0;
|
||||
const double decotop_xend=decotop_xcenter+deco_width/2.0;
|
||||
const double decobot_xstart=x;
|
||||
const double decobot_xend=x+width-italic_xcorrection;
|
||||
const double decobot_xcenter=(decobot_xstart+decobot_xend)/2.0;
|
||||
|
||||
|
||||
|
||||
if (ev.italic) deltax+=0.1*fm.boundingRect("A").width();
|
||||
QPen pold=painter.pen();
|
||||
QPen p=pold;
|
||||
p.setColor(ev.color);
|
||||
p.setWidthF(qMax(JKQTMathText::ABS_MIN_LINEWIDTH, fm.lineWidth()));//ceil(currentEv.fontSize/16.0));
|
||||
if (decoration==MTDbar) ev.overline=true;
|
||||
|
||||
double xnew=child->draw(painter, x, y, ev);
|
||||
|
||||
if (decoration==MTDvec) {
|
||||
painter.setPen(p);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(x+deltax, dpos)<<QPointF(xnew+deltax-0.2*wc, dpos)<<QPointF(xnew-0.4*wc+deltax, dpos-dheight*2.0/3.0);
|
||||
poly<<QPointF(decotop_xstart, deco_ypos)<<QPointF(decotop_xend, deco_ypos)<<QPointF(decotop_xend-deco_vecwidth, deco_ypos-deco_height*2.0/3.0);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDoverline) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dpos, xnew+deltax-0.2*wc, dpos);
|
||||
const QLineF l(decotop_xstart, deco_ypos, decotop_xend, deco_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDbar) {
|
||||
painter.setPen(p);
|
||||
const QLineF l(decotop_xstart, decoAboveAscent_ypos, decotop_xend, decoAboveAscent_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDdoubleoverline) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dpos, xnew+deltax-0.2*wc, dpos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
l=QLineF(x+deltax, dpos-2.0*p.widthF(), xnew+deltax-0.2*wc, dpos-2.0*p.widthF());
|
||||
const QLineF l(decotop_xstart, deco_ypos, decotop_xend, deco_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
const QLineF l2(decotop_xstart, deco_ypos-2.0*p.widthF(), decotop_xend, deco_ypos-2.0*p.widthF());
|
||||
if (l2.length()>0) painter.drawLine(l2);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDunderline) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dposb, xnew+deltax-0.2*wc, dposb);
|
||||
const QLineF l(decobot_xstart, decobelow_ypos, decobot_xend, decobelow_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDdoubleunderline) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dposb, xnew+deltax-0.2*wc, dposb);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
l=QLineF(x+deltax, dposb+2.0*p.widthF(), xnew+deltax-0.2*wc, dposb+2.0*p.widthF());
|
||||
const QLineF l(decobot_xstart, decobelow_ypos, decobot_xend, decobelow_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
QLineF l2(decobot_xstart, decobelow_ypos+2.0*p.widthF(), decobot_xend, decobelow_ypos+2.0*p.widthF());
|
||||
if (l2.length()>0) painter.drawLine(l2);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDarrow) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dpos+dheight/2.0, xnew+deltax-0.2*wc, dpos+dheight/2.0);
|
||||
const QLineF l(decotop_xstart, deco_ypos+deco_height/2.0, decotop_xend, deco_ypos+deco_height/2.0);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(xnew+deltax-0.4*wc, dpos)<<QPointF(xnew+deltax-0.2*wc, dpos+dheight/2.0)<<QPointF(xnew+deltax-0.4*wc, dpos+dheight);
|
||||
poly<<QPointF(decotop_xend-deco_vecwidth, deco_ypos)<<QPointF(decotop_xend, deco_ypos+deco_height/2.0)<<QPointF(decotop_xend-deco_vecwidth, deco_ypos+deco_height);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
/*} else if (decoration==MTDbar) {
|
||||
painter.setPen(p);
|
||||
painter.drawLine(QLineF(x+0.2*wc+deltax, dpos, xnew+0.2*wc+deltax, dpos);
|
||||
painter.setPen(pold);*/
|
||||
} else if (decoration==MTDhat) {
|
||||
painter.setPen(p);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(x+w/2.0-0.25*wc+deltax, dpos+dheight/2.0)<<QPointF(x+w/2.0+deltax, dpos)<<QPointF(x+w/2.0+0.25*wc+deltax, dpos+dheight/2.0);
|
||||
poly<<QPointF(decotop_xcenter-0.5*deco_miniwidth, deco_ypos+deco_height/3.0)<<QPointF(decotop_xcenter, deco_ypos)<<QPointF(decotop_xcenter+0.5*deco_miniwidth, deco_ypos+deco_height/3.0);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDwidehat) {
|
||||
painter.setPen(p);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(decotop_xstart, deco_ypos+deco_height/2.0)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xend, deco_ypos+deco_height/2.0);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
|
||||
} else if (decoration==MTDcheck) {
|
||||
painter.setPen(p);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(decotop_xcenter-0.5*deco_miniwidth, deco_ypos)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xcenter+0.5*deco_miniwidth, deco_ypos);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDwidecheck) {
|
||||
painter.setPen(p);
|
||||
QPolygonF poly;
|
||||
poly<<QPointF(decotop_xstart, deco_ypos-deco_height/2.0)<<QPointF(decotop_xcenter, deco_ypos+deco_height/3.0)<<QPointF(decotop_xend, deco_ypos-deco_height/2.0);
|
||||
painter.drawPolyline(poly);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDbreve) {
|
||||
painter.setPen(p);
|
||||
QPainterPath path;
|
||||
const double x0=decotop_xcenter-deco_miniwidth/2.0;
|
||||
const double x1=decotop_xcenter+deco_miniwidth/2.0;
|
||||
path.moveTo(x0, deco_ypos);
|
||||
path.cubicTo(x0, deco_ypos+deco_height, x1, deco_ypos+deco_height , x1, deco_ypos);
|
||||
painter.drawPath(path);
|
||||
painter.setPen(pold);
|
||||
|
||||
} else if (decoration==MTDtilde) {
|
||||
painter.setPen(p);
|
||||
QPainterPath path;
|
||||
double x0=x+deltax;
|
||||
double x1=xnew+deltax-0.2*wc;
|
||||
path.moveTo(x0, dpos);
|
||||
path.cubicTo((x0+x1)/2.0, dpos+dheight, (x0+x1)/2.0, dpos-dheight , x1, dpos);
|
||||
const double x0=decotop_xcenter-deco_miniwidth/2.0;
|
||||
const double x1=decotop_xcenter+deco_miniwidth/2.0;
|
||||
path.moveTo(x0, deco_ypos);
|
||||
path.cubicTo((x0+x1)/2.0, deco_ypos+deco_height, (x0+x1)/2.0, deco_ypos-deco_height , x1, deco_ypos);
|
||||
painter.drawPath(path);
|
||||
painter.setPen(pold);
|
||||
|
||||
} else if (decoration==MTDwidetilde) {
|
||||
painter.setPen(p);
|
||||
QPainterPath path;
|
||||
const double x0=decotop_xstart;
|
||||
const double x1=decotop_xend;
|
||||
path.moveTo(x0, deco_ypos);
|
||||
path.cubicTo((x0+x1)/2.0, deco_ypos+deco_height, (x0+x1)/2.0, deco_ypos-deco_height , x1, deco_ypos);
|
||||
painter.drawPath(path);
|
||||
painter.setPen(pold);
|
||||
|
||||
} else if (decoration==MTDocirc) {
|
||||
painter.setPen(p);
|
||||
const QBrush bold=painter.brush();
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawEllipse(QPointF(decotop_xcenter, deco_ypos), width_dot/1.5, width_dot/1.5);
|
||||
painter.setBrush(bold);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDdot) {
|
||||
p.setWidthF(0.01);
|
||||
painter.setPen(p);
|
||||
QBrush b=painter.brush();
|
||||
QBrush bold=b;
|
||||
const QBrush bold=b;
|
||||
b.setColor(ev.color);
|
||||
b.setStyle(Qt::SolidPattern);
|
||||
painter.setBrush(b);
|
||||
painter.drawEllipse(QPointF(x+w/2.0+deltax, dpos), wc/10.0, wc/10.0);
|
||||
painter.drawEllipse(QPointF(decotop_xcenter, deco_ypos), width_dot/2.0, width_dot/2.0);
|
||||
painter.setBrush(bold);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDddot) {
|
||||
p.setWidthF(0.01);
|
||||
painter.setPen(p);
|
||||
QBrush b=painter.brush();
|
||||
QBrush bold=b;
|
||||
const QBrush bold=b;
|
||||
b.setColor(ev.color);
|
||||
b.setStyle(Qt::SolidPattern);
|
||||
painter.setBrush(b);
|
||||
painter.drawEllipse(QPointF(x+w/2.0-0.2*wc+deltax, dpos), wc/10.0, wc/10.0);
|
||||
painter.drawEllipse(QPointF(x+w/2.0+0.2*wc+deltax, dpos), wc/10.0, wc/10.0);
|
||||
painter.drawEllipse(QPointF(decotop_xcenter-width_dot, deco_ypos), width_dot/2.0, width_dot/2.0);
|
||||
painter.drawEllipse(QPointF(decotop_xcenter+width_dot, deco_ypos), width_dot/2.0, width_dot/2.0);
|
||||
painter.setBrush(bold);
|
||||
painter.setPen(pold);
|
||||
painter.setBrush(bold);
|
||||
} else if (decoration==MTDstrike) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, spos, xnew+deltax-0.2*wc, spos);
|
||||
const QLineF l((decotop_xstart+decobot_xstart)/2.0, strike_ypos, (decotop_xend+decobot_xend)/2.0, strike_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDcancel) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dposb, xnew+deltax-0.2*wc, dpos);
|
||||
const QLineF l(decobot_xstart, decobelow_ypos, decotop_xend, deco_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDbcancel) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dpos, xnew+deltax-0.2*wc, dposb);
|
||||
const QLineF l(decobot_xstart, deco_ypos, decotop_xend, decobelow_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
painter.setPen(pold);
|
||||
} else if (decoration==MTDxcancel) {
|
||||
painter.setPen(p);
|
||||
QLineF l(x+deltax, dpos, xnew+deltax-0.2*wc, dposb);
|
||||
const QLineF l(decobot_xstart, deco_ypos, decotop_xend, decobelow_ypos);
|
||||
if (l.length()>0) painter.drawLine(l);
|
||||
QLineF l1(x+deltax, dposb, xnew+deltax-0.2*wc, dpos);
|
||||
const QLineF l1(decobot_xstart, decobelow_ypos, decotop_xend, deco_ypos);
|
||||
if (l1.length()>0) painter.drawLine(l1);
|
||||
painter.setPen(pold);
|
||||
}
|
||||
//
|
||||
return xnew+0.3*wc;
|
||||
|
||||
/*painter.setPen(QPen(Qt::red, 1.5));
|
||||
painter.drawLine(QLineF(x, deco_ypos, xnew, deco_ypos));
|
||||
painter.setPen(QPen(Qt::green, 1.5));
|
||||
painter.drawLine(QLineF(deco_xstart, deco_ypos+2, deco_xend, deco_ypos+2));
|
||||
painter.drawEllipse(QPointF(deco_xpos_center, deco_ypos+2), 5, 5);
|
||||
painter.setPen(pold);*/
|
||||
return xnew;
|
||||
}
|
||||
|
||||
bool JKQTMathText::MTdecoratedNode::toHtml(QString &/*html*/, JKQTMathText::MTenvironment /*currentEv*/, JKQTMathText::MTenvironment /*defaultEv*/) {
|
||||
@ -3348,6 +3436,7 @@ JKQTMathText::JKQTMathText(QObject* parent):
|
||||
underbrace_factor=0.75;
|
||||
undersetFactor=0.7;
|
||||
decoration_height_factor=0.2;
|
||||
decoration_width_reduction_Xfactor=0.2;
|
||||
brace_y_shift_factor=0.7;//-1;
|
||||
operatorsubsuper_size_factor=0.65;
|
||||
mathoperator_width_factor=1.5;
|
||||
@ -3483,6 +3572,7 @@ void JKQTMathText::loadSettings(const QSettings& settings, const QString& group)
|
||||
undersetFactor=settings.value(group+"undersetFactor", undersetFactor).toDouble();
|
||||
brace_y_shift_factor=settings.value(group+"brace_y_shift_factor", brace_y_shift_factor).toDouble();
|
||||
decoration_height_factor=settings.value(group+"decoration_height_factor", decoration_height_factor).toDouble();
|
||||
decoration_width_reduction_Xfactor=settings.value(group+"decoration_width_reduction_xfactor", decoration_width_reduction_Xfactor).toDouble();
|
||||
operatorsubsuper_size_factor=settings.value(group+"operatorsubsuper_size_factor", operatorsubsuper_size_factor).toDouble();
|
||||
mathoperator_width_factor=settings.value(group+"mathoperator_width_factor", mathoperator_width_factor).toDouble();
|
||||
|
||||
@ -3510,6 +3600,7 @@ void JKQTMathText::saveSettings(QSettings& settings, const QString& group) const
|
||||
settings.setValue(group+ "mathoperator_width_factor", mathoperator_width_factor);
|
||||
settings.setValue(group+ "brace_y_shift_factor", brace_y_shift_factor);
|
||||
settings.setValue(group+ "decoration_height_factor", decoration_height_factor);
|
||||
settings.setValue(group+ "decoration_width_reduction_xfactor", decoration_width_reduction_Xfactor);
|
||||
}
|
||||
|
||||
bool JKQTMathText::useSTIX(bool mathModeOnly) {
|
||||
@ -4046,6 +4137,16 @@ double JKQTMathText::getDecorationHeightFactor() const
|
||||
return this->decoration_height_factor;
|
||||
}
|
||||
|
||||
void JKQTMathText::setDecorationWidthReductionXFactor(double __value)
|
||||
{
|
||||
decoration_width_reduction_Xfactor=__value;
|
||||
}
|
||||
|
||||
double JKQTMathText::getDecorationWidthReductionXFactor() const
|
||||
{
|
||||
return decoration_width_reduction_Xfactor;
|
||||
}
|
||||
|
||||
void JKQTMathText::setExpensiveRendering(bool __value)
|
||||
{
|
||||
this->expensiveRendering = __value;
|
||||
@ -4357,14 +4458,26 @@ JKQTMathText::MTnode* JKQTMathText::parseLatexString(bool get, const QString& qu
|
||||
nl->addNode(new MTdecoratedNode(this, MTDdoubleoverline, parseLatexString(true)));
|
||||
} else if (name=="arrow"||name=="overrightarrow"||name=="overarrow") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDarrow, parseLatexString(true)));
|
||||
} else if (name=="hat") {
|
||||
} else if (name=="hat" || name=="^") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDhat, parseLatexString(true)));
|
||||
} else if (name=="widehat") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDwidehat, parseLatexString(true)));
|
||||
} else if (name=="check" || name=="v") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDcheck, parseLatexString(true)));
|
||||
} else if (name=="widecheck") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDwidecheck, parseLatexString(true)));
|
||||
} else if (name=="bar") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDbar, parseLatexString(true)));
|
||||
} else if (name=="dot") {
|
||||
} else if (name=="dot" || name==".") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDdot, parseLatexString(true)));
|
||||
} else if (name=="tilde") {
|
||||
} else if (name=="ocirc") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDocirc, parseLatexString(true)));
|
||||
} else if (name=="tilde" || name=="~") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDtilde, parseLatexString(true)));
|
||||
} else if (name=="breve" || name=="u") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDbreve, parseLatexString(true)));
|
||||
} else if (name=="widetilde") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDwidetilde, parseLatexString(true)));
|
||||
} else if (name=="ddot") {
|
||||
nl->addNode(new MTdecoratedNode(this, MTDddot, parseLatexString(true)));
|
||||
} else if (name=="cancel") {
|
||||
@ -4635,6 +4748,13 @@ QRectF JKQTMathText::getTightBoundingRect(const QFont &fm, const QString &text,
|
||||
return d.tbr;
|
||||
}
|
||||
|
||||
QFont JKQTMathText::getNonItalic(const QFont &font)
|
||||
{
|
||||
QFont f=font;
|
||||
f.setItalic(false);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -4817,8 +4937,20 @@ QString JKQTMathText::decorationToString(JKQTMathText::MTdecoration mode)
|
||||
return "vec";
|
||||
case MTDtilde:
|
||||
return "tilde";
|
||||
case MTDbreve:
|
||||
return "breve";
|
||||
case MTDwidetilde:
|
||||
return "widetilde";
|
||||
case MTDhat:
|
||||
return "hat";
|
||||
case MTDwidehat:
|
||||
return "widehat";
|
||||
case MTDcheck:
|
||||
return "check";
|
||||
case MTDwidecheck:
|
||||
return "widecheck";
|
||||
case MTDocirc:
|
||||
return "ocirc";
|
||||
case MTDdot:
|
||||
return "dot";
|
||||
case MTDddot:
|
||||
|
@ -584,10 +584,15 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
void setBraceYShiftFactor(double __value);
|
||||
/** \copydoc brace_y_shift_factor */
|
||||
double getBraceYShiftFactor() const;
|
||||
|
||||
/** \copydoc decoration_height_factor */
|
||||
void setDecorationHeightFactor(double __value);
|
||||
/** \copydoc decoration_height_factor */
|
||||
double getDecorationHeightFactor() const;
|
||||
/** \copydoc decoration_width_reduction_Xfactor */
|
||||
void setDecorationWidthReductionXFactor(double __value);
|
||||
/** \copydoc decoration_width_reduction_Xfactor */
|
||||
double getDecorationWidthReductionXFactor() const;
|
||||
/** \copydoc expensiveRendering */
|
||||
void setExpensiveRendering(bool __value);
|
||||
/** \copydoc expensiveRendering */
|
||||
@ -676,6 +681,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
*
|
||||
*/
|
||||
void getSize(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr);
|
||||
/** \brief calculates the x-size-difference between the given (probably) italic (width externally calculated: \A width_potentiallyitalic, \a ev_potentiallyitalic) and the non-italic version of \a child */
|
||||
double getNonItalicXCorretion(QPainter &painter, double width_potentiallyitalic, const MTenvironment &ev_potentiallyitalic, JKQTMathText::MTnode* child) const;
|
||||
/** \brief draw the contents at the designated position
|
||||
*
|
||||
* \param painter QPainter to use
|
||||
@ -741,10 +748,12 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
/** \copydoc text */
|
||||
QString getText() const;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override ;
|
||||
protected:
|
||||
/** \copydoc MTnode::getSizeInternal() */
|
||||
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
|
||||
/** \brief text-contents of the node */
|
||||
QString text;
|
||||
/** \brief transforms the text before sizing/drawing (may e.g. exchange special letters for other unicode symbols etc.) */
|
||||
virtual QString textTransform(const QString& text, JKQTMathText::MTenvironment currentEv, bool forSize=false);
|
||||
@ -771,7 +780,6 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual ~MTwhitespaceNode() override;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override;
|
||||
/** \brief convert node to HTML and returns \c true on success */
|
||||
/** \copydoc MTnode::toHtml() */
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
};
|
||||
@ -791,7 +799,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
/** \copydoc symbolName */
|
||||
QString getSymbolName() const;
|
||||
/** \brief get font name of the symbol */
|
||||
QString getSymbolfontName() const;
|
||||
/** \copydoc addWhitespace */
|
||||
bool getAddWhitespace() const;
|
||||
protected:
|
||||
/** \copydoc MTnode::getSizeInternal() */
|
||||
@ -847,6 +857,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual QString getTypeName() const override;
|
||||
/** \copydoc MTnode::draw() */
|
||||
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
|
||||
/** \brief add a child node */
|
||||
void addNode(MTnode* n) { nodes.append(n); }
|
||||
/** \copydoc MTnode::toHtml() */
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
@ -908,6 +919,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override; /** \brief returns the child node */
|
||||
/** \brief returns the child node */
|
||||
MTnode *getChild() const;
|
||||
/** \copydoc MTnode::toHtml() */
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
@ -1002,6 +1014,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
/** \copydoc MTnode::setDrawBoxes() */
|
||||
virtual void setDrawBoxes(bool draw) override;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override ;
|
||||
/** \brief returns the child node */
|
||||
MTnode *getChild() const;
|
||||
@ -1036,6 +1049,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
public:
|
||||
MTfracNode(JKQTMathText* parent, MTnode* child_top, MTnode* child_bottom, MTfracMode mode);
|
||||
virtual ~MTfracNode() override;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override;
|
||||
/** \copydoc MTnode::draw() */
|
||||
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv, const MTnodeSize* prevNodeSize=nullptr) override;
|
||||
@ -1084,10 +1098,15 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
int lines;
|
||||
};
|
||||
|
||||
|
||||
/** \brief types of decoration available in a MTdecoratedNode */
|
||||
enum MTdecoration {
|
||||
MTDvec, /*!< \brief vector arrow over block \image html mathparser/MTDvec.png */
|
||||
MTDhat, /*!< \brief hat over block \image html mathparser/MTDhat.png */
|
||||
MTDhat, /*!< \brief small hat over block \image html mathparser/MTDhat.png */
|
||||
MTDwidehat, /*!< \brief full-width hat over block \image html mathparser/MTDwidehat.png */
|
||||
MTDcheck, /*!< \brief small v over block \image html mathparser/MTDcheck.png */
|
||||
MTDwidecheck, /*!< \brief full-width v over block \image html mathparser/MTDwidecheck.png */
|
||||
MTDbreve, /*!< \brief small tilde over block \image html mathparser/MTDbreve.png */
|
||||
MTDocirc, /*!< \brief single circle over block \image html mathparser/MTDocirc.png */
|
||||
MTDdot, /*!< \brief single dot over block \image html mathparser/MTDvec.png */
|
||||
MTDddot, /*!< \brief double dot over block \image html mathparser/MTDddot.png */
|
||||
MTDbar, /*!< \brief bar over block \image html mathparser/MTDbar.png */
|
||||
@ -1096,7 +1115,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
MTDdoubleoverline, /*!< \brief double overline over block \image html mathparser/MTDdoubleoverline.png */
|
||||
MTDunderline, /*!< \brief underline under block \image html mathparser/MTDunderline.png */
|
||||
MTDdoubleunderline, /*!< \brief double underline under block \image html mathparser/MTDdoubleunderline.png */
|
||||
MTDtilde, /*!< \brief tilde over block \image html mathparser/MTDtilde.png */
|
||||
MTDtilde, /*!< \brief small tilde over block \image html mathparser/MTDtilde.png */
|
||||
MTDwidetilde, /*!< \brief full width tilde over block \image html mathparser/MTDwidetilde.png */
|
||||
MTDcancel, /*!< \brief cancel text with sloped line \image html mathparser/MTDcancel.png */
|
||||
MTDbcancel, /*!< \brief cancel text with backward sloped line \image html mathparser/MTDbcancel.png */
|
||||
MTDxcancel, /*!< \brief cancel text with X \image html mathparser/MTDxcancel.png */
|
||||
@ -1107,6 +1127,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
|
||||
/** \brief subclass representing a decorated text m (e.g. \c \\vec \c \\hat ...) node
|
||||
* \ingroup jkqtmathtext_items
|
||||
*
|
||||
* \image html mathparser/decoration_sizing.png
|
||||
*
|
||||
*/
|
||||
class JKQTMATHTEXT_LIB_EXPORT MTdecoratedNode: public MTnode {
|
||||
public:
|
||||
@ -1118,6 +1141,7 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
virtual bool toHtml(QString& html, JKQTMathText::MTenvironment currentEv, JKQTMathText::MTenvironment defaultEv) override;
|
||||
/** \copydoc MTnode::setDrawBoxes() */
|
||||
virtual void setDrawBoxes(bool draw) override;
|
||||
/** \copydoc MTnode::getTypeName() */
|
||||
virtual QString getTypeName() const override ;
|
||||
/** \brief returns the child node */
|
||||
MTnode* getChild() const;
|
||||
@ -1126,7 +1150,9 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
protected:
|
||||
/** \copydoc MTnode::getSizeInternal() */
|
||||
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos, const MTnodeSize* prevNodeSize=nullptr) override;
|
||||
/** \brief child node that is decorated by this node */
|
||||
MTnode* child;
|
||||
/** \brief type of decoration that is added to the child node */
|
||||
MTdecoration decoration;
|
||||
};
|
||||
|
||||
@ -1198,8 +1224,16 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
double undersetFactor;
|
||||
/** \brief fraction of the brace ascent that the brace is shifted downwards, when scaled */
|
||||
double brace_y_shift_factor;
|
||||
/** \brief size of the decorations (dot, tilde, ...), as fractio of the baselineheight */
|
||||
/** \brief size of the decorations (dot, tilde, ...), as fraction of the baselineheight
|
||||
*
|
||||
* \image html mathparser/decoration_sizing.png
|
||||
*/
|
||||
double decoration_height_factor;
|
||||
/** \brief a decoration has a size, which is slightly smaller than the text- width. the width is reduced by \c decoration_width_reduction_Xfactor*width("X") and the position is centered around the child-box. Also an italic correction is applied:
|
||||
*
|
||||
* \image html mathparser/decoration_sizing.png
|
||||
*/
|
||||
double decoration_width_reduction_Xfactor;
|
||||
/** \brief switches on some options that will grant better rendering at the expense of higher time consumption */
|
||||
bool expensiveRendering;
|
||||
/** \brief a list that will be filled with error messages while parsing, if any error occur */
|
||||
@ -1275,7 +1309,8 @@ class JKQTMATHTEXT_LIB_EXPORT JKQTMathText : public QObject {
|
||||
static QList<JKQTMathText::tbrData> tbrs;
|
||||
static QHash<JKQTMathText::tbrDataH, QRectF> tbrh;
|
||||
static QRectF getTightBoundingRect(const QFont &fm, const QString& text, QPaintDevice *pd);
|
||||
|
||||
/** \brief returns a copy of \a f, but with the italic-property set to \c false */
|
||||
static QFont getNonItalic(const QFont& f);
|
||||
};
|
||||
|
||||
|
||||
|