lib

tokenstyleelement.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <tqpainter.h>
21
22#include "basicelement.h"
23#include "tokenstyleelement.h"
24
25KFORMULA_NAMESPACE_BEGIN
26
27TokenStyleElement::TokenStyleElement( BasicElement* parent ) : SequenceElement( parent ),
28 m_mathSizeType ( NoSize ),
29 m_charStyle( anyChar ),
30 m_charFamily( anyFamily ),
31 m_mathColor( "#000000" ),
32 m_mathBackground( "#FFFFFF" ),
33 m_fontSizeType( NoSize ),
34 m_customMathVariant( false ),
35 m_customMathColor( false ),
36 m_customMathBackground( false ),
37 m_customFontWeight( false ),
38 m_customFontStyle( false ),
39 m_customFontFamily( false ),
40 m_customColor( false )
41{
42}
43
46 ContextStyle::IndexStyle istyle,
47 StyleAttributes& style )
48{
49 setStyleSize( context, style );
50 setStyleVariant( style );
51 setStyleColor( style );
52 setStyleBackground( style );
53 inherited::calcSizes( context, tstyle, istyle, style );
54 resetStyle( style );
55}
56
57void TokenStyleElement::draw( TQPainter& painter, const LuPixelRect& r,
58 const ContextStyle& context,
60 ContextStyle::IndexStyle istyle,
61 StyleAttributes& style,
62 const LuPixelPoint& parentOrigin )
63{
64 setStyleSize( context, style );
65 setStyleVariant( style );
66 setStyleColor( style );
67 setStyleBackground( style );
68 if ( style.background() != TQt::color0 ) {
69 painter.fillRect( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
70 context.layoutUnitToPixelY( parentOrigin.y() + getY() ),
71 context.layoutUnitToPixelX( getWidth() ),
72 context.layoutUnitToPixelY( getHeight() ),
73 style.background() );
74 }
75 inherited::draw( painter, r, context, tstyle, istyle, style, parentOrigin );
76 resetStyle( style );
77}
78
79bool TokenStyleElement::readAttributesFromMathMLDom( const TQDomElement& element )
80{
82 return false;
83 }
84
85 // MathML Section 3.2.2
86 TQString variantStr = element.attribute( "mathvariant" );
87 if ( !variantStr.isNull() ) {
88 if ( variantStr == "normal" ) {
89 setCharStyle( normalChar );
90 setCharFamily( normalFamily );
91 }
92 else if ( variantStr == "bold" ) {
93 setCharStyle( boldChar );
94 setCharFamily( normalFamily );
95 }
96 else if ( variantStr == "italic" ) {
97 setCharStyle( italicChar );
98 setCharFamily( normalFamily );
99 }
100 else if ( variantStr == "bold-italic" ) {
101 setCharStyle( boldItalicChar );
102 setCharFamily( normalFamily );
103 }
104 else if ( variantStr == "double-struck" ) {
105 setCharStyle( normalChar );
106 setCharFamily( doubleStruckFamily );
107 }
108 else if ( variantStr == "bold-fraktur" ) {
109 setCharStyle( boldChar );
110 setCharFamily( frakturFamily );
111 }
112 else if ( variantStr == "script" ) {
113 setCharStyle( normalChar );
114 setCharFamily( scriptFamily );
115 }
116 else if ( variantStr == "bold-script" ) {
117 setCharStyle( boldChar );
118 setCharFamily( scriptFamily );
119 }
120 else if ( variantStr == "fraktur" ) {
121 setCharStyle( boldChar );
122 setCharFamily( frakturFamily );
123 }
124 else if ( variantStr == "sans-serif" ) {
125 setCharStyle( normalChar );
126 setCharFamily( sansSerifFamily );
127 }
128 else if ( variantStr == "bold-sans-serif" ) {
129 setCharStyle( boldChar );
130 setCharFamily( sansSerifFamily );
131 }
132 else if ( variantStr == "sans-serif-italic" ) {
133 setCharStyle( italicChar );
134 setCharFamily( sansSerifFamily );
135 }
136 else if ( variantStr == "sans-serif-bold-italic" ) {
137 setCharStyle( boldItalicChar );
138 setCharFamily( sansSerifFamily );
139 }
140 else if ( variantStr == "monospace" ) {
141 setCharStyle( normalChar );
142 setCharFamily( monospaceFamily );
143 }
144 }
145
146 TQString sizeStr = element.attribute( "mathsize" );
147 if ( !sizeStr.isNull() ) {
148 if ( sizeStr == "small" ) {
149 setRelativeSize( 0.8 ); // ### Arbitrary size
150 }
151 else if ( sizeStr == "normal" ) {
152 setRelativeSize( 1.0 );
153 }
154 else if ( sizeStr == "big" ) {
155 setRelativeSize( 1.2 ); // ### Arbitrary size
156 }
157 else {
158 double s = getSize( sizeStr, &m_mathSizeType );
159 switch ( m_mathSizeType ) {
160 case AbsoluteSize:
161 setAbsoluteSize( s );
162 break;
163 case RelativeSize:
164 setRelativeSize( s );
165 break;
166 case PixelSize:
167 setPixelSize( s );
168 break;
169 default:
170 break;
171 }
172 }
173 }
174
175 TQString colorStr = element.attribute( "mathcolor" );
176 if ( !colorStr.isNull() ) {
177 if ( colorStr[0] != '#' ) {
178 setMathColor( TQColor( getHtmlColor( colorStr ) ) );
179 }
180 else {
181 setMathColor( TQColor( colorStr ) );
182 }
183 }
184 TQString backgroundStr = element.attribute( "mathbackground" );
185 if ( !backgroundStr.isNull() ) {
186 if ( backgroundStr[0] != '#' ) {
187 setMathBackground( TQColor( getHtmlColor( backgroundStr ) ) );
188 }
189 else {
190 setMathBackground( TQColor( backgroundStr ) );
191 }
192 }
193
194 // Deprecated attributes. See Section 3.2.2.1
195
196 sizeStr = element.attribute( "fontsize" );
197 if ( ! sizeStr.isNull() ) {
198 if ( sizeStr == "small" ) {
199 setRelativeSize( 0.8, true ); // ### Arbitrary size
200 }
201 else if ( sizeStr == "normal" ) {
202 setRelativeSize( 1.0, true );
203 }
204 else if ( sizeStr == "big" ) {
205 setRelativeSize( 1.2, true ); // ### Arbitrary size
206 }
207 else {
208 double s = getSize( sizeStr, &m_fontSizeType );
209 switch ( m_fontSizeType ) {
210 case AbsoluteSize:
211 setAbsoluteSize( s, true );
212 break;
213 case RelativeSize:
214 setRelativeSize( s, true );
215 break;
216 case PixelSize:
217 setPixelSize( s, true );
218 break;
219 default:
220 break;
221 }
222 }
223 }
224
225 TQString styleStr = element.attribute( "fontstyle" );
226 if ( ! styleStr.isNull() ) {
227 if ( styleStr.lower() == "italic" ) {
228 setFontStyle( true );
229 }
230 else {
231 setFontStyle( false );
232 }
233 }
234
235 TQString weightStr = element.attribute( "fontweight" );
236 if ( ! weightStr.isNull() ) {
237 if ( weightStr.lower() == "bold" ) {
238 setFontWeight( true );
239 }
240 else {
241 setFontWeight( false );
242 }
243 }
244
245 TQString familyStr = element.attribute( "fontfamily" );
246 if ( ! familyStr.isNull() ) {
247 setFontFamily( familyStr );
248 }
249
250 colorStr = element.attribute( "color" );
251 if ( ! colorStr.isNull() ) {
252 if ( colorStr[0] != '#' ) {
253 setColor( TQColor( getHtmlColor( colorStr ) ) );
254 }
255 else {
256 setColor( TQColor( colorStr ) );
257 }
258 }
259
260 return true;
261}
262
263void TokenStyleElement::writeMathMLAttributes( TQDomElement& element ) const
264{
265 // mathvariant attribute
266 if ( customMathVariant() ) {
267 if ( charFamily() == normalFamily ) {
268 if ( charStyle() == normalChar ) {
269 element.setAttribute( "mathvariant", "normal" );
270 }
271 else if ( charStyle() == boldChar ) {
272 element.setAttribute( "mathvariant", "bold" );
273 }
274 else if ( charStyle() == italicChar ) {
275 element.setAttribute( "mathvariant", "italic" );
276 }
277 else if ( charStyle() == boldItalicChar ) {
278 element.setAttribute( "mathvariant", "bold-italic" );
279 }
280 else { // anyChar or unknown, it's always an error
281 kdWarning( DEBUGID ) << "Mathvariant: unknown style for normal family\n";
282 }
283 }
284 else if ( charFamily() == doubleStruckFamily ) {
285 if ( charStyle() == normalChar ) {
286 element.setAttribute( "mathvariant", "double-struck" );
287 }
288 else { // Shouldn't happen, it's a bug
289 kdWarning( DEBUGID ) << "Mathvariant: unknown style for double-struck family\n";
290 }
291 }
292 else if ( charFamily() == frakturFamily ) {
293 if ( charStyle() == normalChar ) {
294 element.setAttribute( "mathvariant", "fraktur" );
295 }
296 else if ( charStyle() == boldChar ) {
297 element.setAttribute( "mathvariant", "bold-fraktur" );
298 }
299 else {
300 kdWarning( DEBUGID ) << "Mathvariant: unknown style for fraktur family\n";
301 }
302 }
303 else if ( charFamily() == scriptFamily ) {
304 if ( charStyle() == normalChar ) {
305 element.setAttribute( "mathvariant", "script" );
306 }
307 else if ( charStyle() == boldChar ) {
308 element.setAttribute( "mathvariant", "bold-script" );
309 }
310 else { // Shouldn't happen, it's a bug
311 kdWarning( DEBUGID ) << "Mathvariant: unknown style for script family\n";
312 }
313 }
314 else if ( charFamily() == sansSerifFamily ) {
315 if ( charStyle() == normalChar ) {
316 element.setAttribute( "mathvariant", "sans-serif" );
317 }
318 else if ( charStyle() == boldChar ) {
319 element.setAttribute( "mathvariant", "bold-sans-serif" );
320 }
321 else if ( charStyle() == italicChar ) {
322 element.setAttribute( "mathvariant", "sans-serif-italic" );
323 }
324 else if ( charStyle() == boldItalicChar ) {
325 element.setAttribute( "mathvariant", "sans-serif-bold-italic" );
326 }
327 else {
328 kdWarning( DEBUGID ) << "Mathvariant: unknown style for sans serif family\n";
329 }
330 }
331 else if ( charFamily() == monospaceFamily ) {
332 if ( charStyle() == normalChar ) {
333 element.setAttribute( "mathvariant", "monospace" );
334 }
335 else {
336 kdWarning( DEBUGID ) << "Mathvariant: unknown style for monospace family\n";
337 }
338 }
339 else {
340 kdWarning( DEBUGID ) << "Mathvariant: unknown family\n";
341 }
342 }
343
344 // mathsize attribute
345 switch ( m_mathSizeType ) {
346 case AbsoluteSize:
347 element.setAttribute( "mathsize", TQString( "%1pt" ).arg( m_mathSize ) );
348 break;
349 case RelativeSize:
350 element.setAttribute( "mathsize", TQString( "%1%" ).arg( m_mathSize * 100.0 ) );
351 break;
352 case PixelSize:
353 element.setAttribute( "mathsize", TQString( "%1px" ).arg( m_mathSize ) );
354 break;
355 default:
356 break;
357 }
358
359 // mathcolor attribute
360 if ( customMathColor() ) {
361 element.setAttribute( "mathcolor", mathColor().name() );
362 }
363
364 // mathbackground attribute
365 if ( customMathBackground() ) {
366 element.setAttribute( "mathbackground", mathBackground().name() );
367 }
368
369 // Deprecated MathML 1.01 Attributes
370 // fontsize attribute
371 switch ( m_fontSizeType ) {
372 case AbsoluteSize:
373 element.setAttribute( "fontsize", TQString( "%1pt" ).arg( m_fontSize ) );
374 break;
375 case RelativeSize:
376 element.setAttribute( "fontsize", TQString( "%1%" ).arg( m_fontSize * 100.0 ) );
377 break;
378 case PixelSize:
379 element.setAttribute( "fontsize", TQString( "%3px" ).arg( m_fontSize ) );
380 break;
381 default:
382 break;
383 }
384
385 // fontweight attribute
386 if ( customFontWeight() ) {
387 element.setAttribute( "fontweight", fontWeight() ? "bold" : "normal" );
388 }
389
390 // fontstyle attribute
391 if ( customFontStyle() ) {
392 element.setAttribute( "fontstyle", fontStyle() ? "italic" : "normal" );
393 }
394
395 // fontfamily attribute
396 if ( customFontFamily() ) {
397 element.setAttribute( "fontfamily", fontFamily() );
398 }
399
400 // color attribute
401 if ( customColor() ) {
402 element.setAttribute( "color", color().name() );
403 }
404}
405
406void TokenStyleElement::setAbsoluteSize( double s, bool fontsize )
407{
408 kdDebug( DEBUGID) << "Setting absolute size: " << s << endl;
409 if ( fontsize ) {
410 m_fontSizeType = AbsoluteSize;
411 m_fontSize = s;
412 }
413 else {
414 m_mathSizeType = AbsoluteSize;
415 m_mathSize = s;
416 }
417}
418
419void TokenStyleElement::setRelativeSize( double f, bool fontsize )
420{
421 kdDebug( DEBUGID) << "Setting relative size: " << f << endl;
422 if ( fontsize ) {
423 m_fontSizeType = RelativeSize;
424 m_fontSize = f;
425 }
426 else {
427 m_mathSizeType = RelativeSize;
428 m_mathSize = f;
429 }
430}
431
432void TokenStyleElement::setPixelSize( double px, bool fontsize )
433{
434 kdDebug( DEBUGID) << "Setting pixel size: " << px << endl;
435 if ( fontsize ) {
436 m_fontSizeType = PixelSize;
437 m_fontSize = px;
438 }
439 else {
440 m_mathSizeType = PixelSize;
441 m_mathSize = px;
442 }
443}
444
445void TokenStyleElement::setStyleSize( const ContextStyle& context, StyleAttributes& style )
446{
447 style.setSizeFactor( sizeFactor( context, style.sizeFactor() ) );
448}
449
450void TokenStyleElement::setStyleVariant( StyleAttributes& style )
451{
452 if ( customMathVariant() || style.customMathVariant() ) {
453 style.setCustomMathVariant ( true );
454 style.setCustomFontWeight( false );
455 style.setCustomFontStyle( false );
456 style.setCustomFont( false );
457 if ( customMathVariant() ) {
458 style.setCharFamily ( charFamily() );
459 style.setCharStyle( charStyle() );
460 }
461 else {
462 style.setCharFamily( style.charFamily() );
463 style.setCharStyle( style.charStyle() );
464 }
465 }
466 else {
467 style.setCustomMathVariant( false );
468 if ( customFontFamily() ) {
469 style.setCustomFont( true );
470 style.setFont( TQFont(fontFamily()) );
471 }
472
473 bool fontweight = false;
474 if ( customFontWeight() || style.customFontWeight() ) {
475 style.setCustomFontWeight( true );
476 if ( customFontWeight() ) {
477 fontweight = fontWeight();
478 }
479 else {
480 fontweight = style.fontWeight();
481 }
482 style.setFontWeight( fontweight );
483 }
484 else {
485 style.setCustomFontWeight( false );
486 }
487
488 bool fontstyle = false;
489 if ( style.customFontStyle() ) {
490 style.setCustomFontStyle( true );
491 fontstyle = style.fontStyle();
492 style.setFontStyle( fontstyle );
493 }
494 else {
495 style.setCustomFontStyle( false );
496 }
497 if ( customFontStyle() ) {
498 fontstyle = fontStyle();
499 }
500
501 if ( fontweight && fontstyle ) {
502 style.setCharStyle( boldItalicChar );
503 }
504 else if ( fontweight && ! fontstyle ) {
505 style.setCharStyle( boldChar );
506 }
507 else if ( ! fontweight && fontstyle ) {
508 style.setCharStyle( italicChar );
509 }
510 else {
511 style.setCharStyle( normalChar );
512 }
513 }
514}
515
516void TokenStyleElement::setStyleColor( StyleAttributes& style )
517{
518 if ( customMathColor() ) {
519 style.setColor( mathColor() );
520 }
521 else if ( customColor() ) {
522 style.setColor( color() );
523 }
524 else {
525 style.setColor( style.color() );
526 }
527}
528
529void TokenStyleElement::setStyleBackground( StyleAttributes& style )
530{
531 if ( customMathBackground() ) {
532 style.setBackground( mathBackground() );
533 }
534 else {
535 style.setBackground( style.background() );
536 }
537}
538
539void TokenStyleElement::resetStyle( StyleAttributes& style )
540{
541 style.resetSize();
542 style.resetCharStyle();
543 style.resetCharFamily();
544 style.resetColor();
545 style.resetBackground();
546 style.resetFontFamily();
547 style.resetFontWeight();
548 style.resetFontStyle();
549}
550
551double TokenStyleElement::sizeFactor( const ContextStyle& context, double factor )
552{
553 double basesize = context.layoutUnitPtToPt( context.getBaseSize() );
554 switch ( m_mathSizeType ) {
555 case AbsoluteSize:
556 return m_mathSize / basesize;
557 case RelativeSize:
558 return m_mathSize;
559 case PixelSize:
560 // 3.2.2 says v-unit instead of h-unit, that's why we use Y and not X
561 return context.pixelYToPt( m_mathSize ) / basesize;
562 case NoSize:
563 switch ( m_fontSizeType ) {
564 case AbsoluteSize:
565 return m_fontSize / basesize;
566 case RelativeSize:
567 return m_fontSize;
568 case PixelSize:
569 return context.pixelYToPt( m_fontSize ) / basesize;
570 default:
571 return factor;
572 }
573 default:
574 break;
575 }
576 kdWarning( DEBUGID ) << k_funcinfo << " Unknown SizeType\n";
577 return factor;
578}
579
583TQString TokenStyleElement::getHtmlColor( const TQString& colorStr ){
584
585 TQString colorname = colorStr.lower();
586
587 if ( colorname == "black" )
588 return "#000000";
589 if ( colorname == "silver" )
590 return "#C0C0C0";
591 if ( colorname == "gray" )
592 return "#808080";
593 if ( colorname == "white" )
594 return "#FFFFFF";
595 if ( colorname == "maroon" )
596 return "#800000";
597 if ( colorname == "red" )
598 return "#FF0000";
599 if ( colorname == "purple" )
600 return "#800080";
601 if ( colorname == "fuchsia" )
602 return "#FF00FF";
603 if ( colorname == "green" )
604 return "#008000";
605 if ( colorname == "lime" )
606 return "#00FF00";
607 if ( colorname == "olive" )
608 return "#808000";
609 if ( colorname == "yellow" )
610 return "#FFFF00";
611 if ( colorname == "navy" )
612 return "#000080";
613 if ( colorname == "blue")
614 return "#0000FF";
615 if ( colorname == "teal" )
616 return "#008080";
617 if ( colorname == "aqua" )
618 return "#00FFFF";
619 kdWarning( DEBUGID ) << "Invalid HTML color: " << colorname << endl;
620 return "#FFFFFF"; // ### Arbitrary selection of default color
621}
622
623
624KFORMULA_NAMESPACE_END
Basis of every formula element.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
double getSize(const TQString &str, SizeType *st)
Utility function that sets the size type and returns the size value from a MathML attribute string wi...
Contains all the style information for the formela.
TextStyle
Textstyles like in TeX.
The element that contains a number of children.
virtual void calcSizes(const ContextStyle &cstyle, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
TQString getHtmlColor(const TQString &colorStr)
Return RGB string from HTML Colors.
virtual void calcSizes(const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
virtual void setStyleVariant(StyleAttributes &style)
Set the mathvariant related info in style stacks, including info for deprecated attributes.
const char * name(StdAction id)