lib

fontstyle.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
3 Copyright (C) 2006 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <tqpainter.h>
22#include <tqpen.h>
23#include <tqfontdatabase.h>
24#include <tqapplication.h>
25
26#include <kstaticdeleter.h>
27#include <tdelocale.h>
28#include <kstandarddirs.h>
29#include <tdeio/netaccess.h>
30#include <tdeio/job.h>
31#include <tdemessagebox.h>
32
33#include "fontstyle.h"
34
35
36KFORMULA_NAMESPACE_BEGIN
37
38#include "unicodetable.cpp"
39
40bool FontStyle::m_installed = false;
41
42bool FontStyle::init( ContextStyle* style, bool install )
43{
44 if (!m_installed && install)
45 installFonts();
46 m_symbolTable.init( style->getMathFont() );
47
48 return true;
49}
50
51// Cache the family list from TQFontDatabase after fixing it up (no foundry, lowercase)
52class FontList {
53public:
54 FontList() {
55 TQFontDatabase db;
56 const TQStringList lst = db.families();
57 for ( TQStringList::const_iterator it = lst.begin(), end = lst.end() ; it != end ; ++it ) {
58 const TQString name = *it;
59 int i = name.find('[');
60 TQString family = name;
61 // Remove foundry
62 if ( i > -1 ) {
63 const int li = name.findRev(']');
64 if (i < li) {
65 if (name[i - 1] == ' ')
66 i--;
67 family = name.left(i);
68 }
69 }
70 m_fontNames.append( family.lower() );
71 }
72 }
73 bool hasFont( const TQString& fontName ) const {
74 return m_fontNames.find( fontName ) != m_fontNames.end();
75 }
76 TQStringList m_fontNames;
77};
78static FontList* s_fontList = 0;
79static KStaticDeleter<FontList> s_fontList_sd;
80
81void FontStyle::testFont( TQStringList& missing, const TQString& fontName ) {
82 if ( !s_fontList )
83 s_fontList_sd.setObject( s_fontList, new FontList() );
84 if ( !s_fontList->hasFont( fontName ) ) {
85 kdWarning(39001) << "Font '" << fontName << "' not found" << endl;
86 missing.append( fontName );
87 }
88}
89
90
91TQStringList FontStyle::missingFonts( bool install )
92{
93 if (!m_installed && install)
94 installFonts();
95
96 TQStringList missing = missingFontsInternal();
97 return missing;
98}
99
100TQStringList FontStyle::missingFontsInternal()
101{
102 TQStringList missing;
103
104 testFont( missing, "cmex10" );
105 testFont( missing, "arev sans");
106
107 return missing;
108}
109
110void FontStyle::installFonts()
111{
112 if (m_installed)
113 return;
114 TQStringList missing = missingFontsInternal();
115 if (!missing.isEmpty())
116 {
117 TQStringList urlList;
118 for (TQStringList::iterator it = missing.begin(); it != missing.end(); ++it)
119 {
120 if ( *it == "arev sans" ) {
121 if (!TDEIO::NetAccess::exists("fonts:/Personal/Arev.ttf", true, NULL))
122 urlList.append(locate("data", "kformula/fonts/Arev.ttf"));
123 if (!TDEIO::NetAccess::exists("fonts:/Personal/ArevIt.ttf", true, NULL))
124 urlList.append(locate("data", "kformula/fonts/ArevIt.ttf"));
125 if (!TDEIO::NetAccess::exists("fonts:/Personal/ArevBd.ttf", true, NULL))
126 urlList.append(locate("data", "kformula/fonts/ArevBd.ttf"));
127 if (!TDEIO::NetAccess::exists("fonts:/Personal/ArevBI.ttf", true, NULL))
128 urlList.append(locate("data", "kformula/fonts/ArevBI.ttf"));
129 }
130 else {
131 if (!TDEIO::NetAccess::exists("fonts:/Personal/" + *it + ".ttf", true, NULL))
132 urlList.append(locate("data", "kformula/fonts/" + *it + ".ttf"));
133 }
134 }
135 TDEIO::copy(urlList, "fonts:/Personal/", false);
136 KMessageBox::information(tqApp->mainWidget(),
137 i18n("Some fonts have been installed to assure that symbols in formulas are properly visualized. You must restart the application in order so that changes take effect"));
138 }
139 m_installed = true;
140}
141
142Artwork* FontStyle::createArtwork( SymbolType type ) const
143{
144 return new Artwork( type );
145}
146
147// We claim that all chars come from the same font.
148// It's up to the font tables to ensure this.
149const TQChar leftRoundBracket[] = {
150 0x30, // uppercorner
151 0x40, // lowercorner
152 0x42 // line
153};
154const TQChar leftSquareBracket[] = {
155 0x32, // uppercorner
156 0x34, // lowercorner
157 0x36 // line
158};
159const TQChar leftCurlyBracket[] = {
160 0x38, // uppercorner
161 0x3A, // lowercorner
162 0x3E, // line
163 0x3C // middle
164};
165
166const TQChar leftLineBracket[] = {
167 0x36, // line
168 0x36, // line
169 0x36 // line
170};
171const TQChar rightLineBracket[] = {
172 0x37, // line
173 0x37, // line
174 0x37 // line
175};
176
177const TQChar rightRoundBracket[] = {
178 0x31, // uppercorner
179 0x41, // lowercorner
180 0x43 // line
181};
182const TQChar rightSquareBracket[] = {
183 0x33, // uppercorner
184 0x35, // lowercorner
185 0x37 // line
186};
187const TQChar rightCurlyBracket[] = {
188 0x39, // uppercorner
189 0x3B, // lowercorner
190 0x3E, // line
191 0x3D // middle
192};
193
194
195static const char cmex_LeftSquareBracket = 163;
196static const char cmex_RightSquareBracket = 164;
197static const char cmex_LeftCurlyBracket = 169;
198static const char cmex_RightCurlyBracket = 170;
199static const char cmex_LeftCornerBracket = 173;
200static const char cmex_RightCornerBracket = 174;
201static const char cmex_LeftRoundBracket = 161;
202static const char cmex_RightRoundBracket = 162;
203static const char cmex_SlashBracket = 177;
204static const char cmex_BackSlashBracket = 178;
205//static const char cmex_LeftLineBracket = 0x4b;
206//static const char cmex_RightLineBracket = 0x4b;
207
208// use the big symbols here
209static const char cmex_Int = 90;
210static const char cmex_Sum = 88;
211static const char cmex_Prod = 89;
212
213
214// cmex is a special font with symbols in four sizes.
215static short cmex_nextchar( short ch )
216{
217 switch ( ch ) {
218 case 161: return 179;
219 case 162: return 180;
220 case 163: return 104;
221 case 164: return 105;
222 case 169: return 110;
223 case 170: return 111;
224 case 165: return 106;
225 case 166: return 107;
226 case 167: return 108;
227 case 168: return 109;
228 case 173: return 68;
229 case 174: return 69;
230 case 177: return 46;
231 case 178: return 47;
232
233 case 179: return 181;
234 case 180: return 182;
235 case 104: return 183;
236 case 105: return 184;
237 case 110: return 189;
238 case 111: return 190;
239 case 106: return 185;
240 case 107: return 186;
241 case 108: return 187;
242 case 109: return 188;
243 case 68: return 191;
244 case 69: return 192;
245 case 46: return 193;
246 case 47: return 194;
247
248 case 181: return 195;
249 case 182: return 33;
250 case 183: return 34;
251 case 184: return 35;
252 case 189: return 40;
253 case 190: return 41;
254 case 185: return 36;
255 case 186: return 37;
256 case 187: return 38;
257 case 188: return 39;
258 case 191: return 42;
259 case 192: return 43;
260 case 193: return 44;
261 case 194: return 45;
262 }
263 return 0;
264}
265
266bool Artwork::calcCMDelimiterSize( const ContextStyle& context,
267 uchar c,
268 luPt fontSize,
269 luPt parentSize )
270{
271 TQFont f( "cmex10" );
272 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
273 TQFontMetrics fm( f );
274
275 for ( char i=1; c != 0; ++i ) {
276 LuPixelRect bound = fm.boundingRect( c );
277
278 luPt height = context.ptToLayoutUnitPt( bound.height() );
279 if ( height >= parentSize ) {
280 luPt width = context.ptToLayoutUnitPt( fm.width( c ) );
281 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
282
283 cmChar = c;
284
285 setHeight( height );
286 setWidth( width );
287 setBaseline( baseline );
288
289 return true;
290 }
291 c = cmex_nextchar( c );
292 }
293
294 // Build it up from pieces.
295 return false;
296}
297
298
299void Artwork::calcLargest( const ContextStyle& context,
300 uchar c, luPt fontSize )
301{
302 TQFont f( "cmex10" );
303 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
304 TQFontMetrics fm( f );
305
306 cmChar = c;
307 for ( ;; ) {
308 c = cmex_nextchar( c );
309 if ( c == 0 ) {
310 break;
311 }
312 cmChar = c;
313 }
314
315 LuPixelRect bound = fm.boundingRect( cmChar );
316
317 luPt height = context.ptToLayoutUnitPt( bound.height() );
318 luPt width = context.ptToLayoutUnitPt( fm.width( cmChar ) );
319 luPt baseline = context.ptToLayoutUnitPt( -bound.top() );
320
321 setHeight( height );
322 setWidth( width );
323 setBaseline( baseline );
324}
325
326
327void Artwork::drawCMDelimiter( TQPainter& painter, const ContextStyle& style,
328 luPixel x, luPixel y,
329 luPt height )
330{
331 TQFont f( "cmex10" );
332 f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
333
334 painter.setFont( f );
335 painter.drawText( style.layoutUnitToPixelX( x ),
336 style.layoutUnitToPixelY( y + getBaseline() ),
337 TQString( TQChar( cmChar ) ) );
338
339 // Debug
340#if 0
341 TQFontMetrics fm( f );
342 LuPixelRect bound = fm.boundingRect( cmChar );
343 painter.setBrush(TQt::NoBrush);
344 painter.setPen(TQt::green);
345 painter.drawRect( style.layoutUnitToPixelX( x ),
346 style.layoutUnitToPixelY( y ),
347 fm.width( cmChar ),
348 bound.height() );
349#endif
350}
351
352
353Artwork::Artwork(SymbolType t)
354 : baseline( -1 ), type(t)
355{
356}
357
358
359void Artwork::calcSizes( const ContextStyle& style,
361 double factor,
362 luPt parentSize )
363{
364 setBaseline( -1 );
365 cmChar = -1;
366 luPt mySize = style.getAdjustedSize( tstyle, factor );
367 switch (getType()) {
368 case LeftSquareBracket:
369 if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
370 mySize, parentSize ) ) {
371 return;
372 }
373 calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
374 break;
375 case RightSquareBracket:
376 if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
377 mySize, parentSize ) ) {
378 return;
379 }
380 calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
381 break;
382 case LeftLineBracket:
383 calcRoundBracket( style, leftLineBracket, parentSize, mySize );
384 setWidth( getWidth()/2 );
385 break;
386 case RightLineBracket:
387 calcRoundBracket( style, rightLineBracket, parentSize, mySize );
388 setWidth( getWidth()/2 );
389 break;
390 case SlashBracket:
391 if ( calcCMDelimiterSize( style, cmex_SlashBracket,
392 mySize, parentSize ) ) {
393 return;
394 }
395 calcLargest( style, cmex_SlashBracket, mySize );
396 break;
397 case BackSlashBracket:
398 if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
399 mySize, parentSize ) ) {
400 return;
401 }
402 calcLargest( style, cmex_BackSlashBracket, mySize );
403 break;
404 case LeftCornerBracket:
405 if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
406 mySize, parentSize ) ) {
407 return;
408 }
409 calcLargest( style, cmex_LeftCornerBracket, mySize );
410 break;
411 case RightCornerBracket:
412 if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
413 mySize, parentSize ) ) {
414 return;
415 }
416 calcLargest( style, cmex_RightCornerBracket, mySize );
417 break;
418 case LeftRoundBracket:
419 if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
420 mySize, parentSize ) ) {
421 return;
422 }
423 calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
424 break;
425 case RightRoundBracket:
426 if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
427 mySize, parentSize ) ) {
428 return;
429 }
430 calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
431 break;
432 case EmptyBracket:
433 setHeight(parentSize);
434 //setWidth(style.getEmptyRectWidth());
435 setWidth(0);
436 break;
437 case LeftCurlyBracket:
438 if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
439 mySize, parentSize ) ) {
440 return;
441 }
442 calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
443 break;
444 case RightCurlyBracket:
445 if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
446 mySize, parentSize ) ) {
447 return;
448 }
449 calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
450 break;
451 case Integral:
452 calcCharSize( style, style.getBracketFont(), mySize, cmex_Int );
453 break;
454 case Sum:
455 calcCharSize( style, style.getBracketFont(), mySize, cmex_Sum );
456 break;
457 case Product:
458 calcCharSize( style, style.getBracketFont(), mySize, cmex_Prod );
459 break;
460 }
461}
462
463void Artwork::calcSizes( const ContextStyle& style,
465 double factor )
466{
467 luPt mySize = style.getAdjustedSize( tstyle, factor );
468 switch (type) {
469 case LeftSquareBracket:
470 calcCharSize(style, mySize, leftSquareBracketChar);
471 break;
472 case RightSquareBracket:
473 calcCharSize(style, mySize, rightSquareBracketChar);
474 break;
475 case LeftLineBracket:
476 case RightLineBracket:
477 calcCharSize(style, mySize, verticalLineChar);
478 break;
479 case SlashBracket:
480 calcCharSize(style, mySize, slashChar);
481 break;
482 case BackSlashBracket:
483 calcCharSize(style, mySize, backSlashChar);
484 break;
485 case LeftCornerBracket:
486 calcCharSize(style, mySize, leftAngleBracketChar);
487 break;
488 case RightCornerBracket:
489 calcCharSize(style, mySize, rightAngleBracketChar);
490 break;
491 case LeftRoundBracket:
492 calcCharSize(style, mySize, leftParenthesisChar);
493 break;
494 case RightRoundBracket:
495 calcCharSize(style, mySize, rightParenthesisChar);
496 break;
497 case EmptyBracket:
498 //calcCharSize(style, mySize, spaceChar);
499 setHeight(0);
500 //setWidth(style.getEmptyRectWidth());
501 setWidth(0);
502 break;
503 case LeftCurlyBracket:
504 calcCharSize(style, mySize, leftCurlyBracketChar);
505 break;
506 case RightCurlyBracket:
507 calcCharSize(style, mySize, rightCurlyBracketChar);
508 break;
509 case Integral:
510 case Sum:
511 case Product:
512 break;
513 }
514}
515
516
517void Artwork::draw(TQPainter& painter, const LuPixelRect& /*r*/,
518 const ContextStyle& context, ContextStyle::TextStyle tstyle,
519 StyleAttributes& style, const LuPixelPoint& parentOrigin)
520{
521 luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() );
522 luPixel myX = parentOrigin.x() + getX();
523 luPixel myY = parentOrigin.y() + getY();
524 /*
525 if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
526 return;
527 */
528
529 painter.setPen(context.getDefaultColor());
530
531 switch (type) {
532 case LeftSquareBracket:
533 drawCharacter(painter, context, myX, myY, mySize, leftSquareBracketChar);
534 break;
535 case RightSquareBracket:
536 drawCharacter(painter, context, myX, myY, mySize, rightSquareBracketChar);
537 break;
538 case LeftCurlyBracket:
539 drawCharacter(painter, context, myX, myY, mySize, leftCurlyBracketChar);
540 break;
541 case RightCurlyBracket:
542 drawCharacter(painter, context, myX, myY, mySize, rightCurlyBracketChar);
543 break;
544 case LeftLineBracket:
545 case RightLineBracket:
546 drawCharacter(painter, context, myX, myY, mySize, verticalLineChar);
547 break;
548 case SlashBracket:
549 drawCharacter(painter, context, myX, myY, mySize, slashChar);
550 break;
551 case BackSlashBracket:
552 drawCharacter(painter, context, myX, myY, mySize, backSlashChar);
553 break;
554 case LeftCornerBracket:
555 drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
556 break;
557 case RightCornerBracket:
558 drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
559 break;
560 case LeftRoundBracket:
561 drawCharacter(painter, context, myX, myY, mySize, leftParenthesisChar);
562 break;
563 case RightRoundBracket:
564 drawCharacter(painter, context, myX, myY, mySize, rightParenthesisChar);
565 break;
566 case EmptyBracket:
567 break;
568 case Integral:
569 case Sum:
570 case Product:
571 break;
572 }
573}
574
575void Artwork::draw(TQPainter& painter, const LuPixelRect& ,
576 const ContextStyle& context, ContextStyle::TextStyle tstyle,
577 StyleAttributes& style, luPt , const LuPixelPoint& origin)
578{
579 luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() );
580 luPixel myX = origin.x() + getX();
581 luPixel myY = origin.y() + getY();
582 /*
583 if ( !LuPixelRect( myX, myY, getWidth(), getHeight() ).intersects( r ) )
584 return;
585 */
586
587 painter.setPen(context.getDefaultColor());
588
589 switch (getType()) {
590 case LeftSquareBracket:
591 if ( cmChar != -1 ) {
592 drawCMDelimiter( painter, context, myX, myY, mySize );
593 }
594 else {
595 drawBigRoundBracket( painter, context, leftSquareBracket, myX, myY, mySize );
596 }
597 break;
598 case RightSquareBracket:
599 if ( cmChar != -1 ) {
600 drawCMDelimiter( painter, context, myX, myY, mySize );
601 }
602 else {
603 drawBigRoundBracket( painter, context, rightSquareBracket, myX, myY, mySize );
604 }
605 break;
606 case LeftCurlyBracket:
607 if ( cmChar != -1 ) {
608 drawCMDelimiter( painter, context, myX, myY, mySize );
609 }
610 else {
611 drawBigCurlyBracket( painter, context, leftCurlyBracket, myX, myY, mySize );
612 }
613 break;
614 case RightCurlyBracket:
615 if ( cmChar != -1 ) {
616 drawCMDelimiter( painter, context, myX, myY, mySize );
617 }
618 else {
619 drawBigCurlyBracket( painter, context, rightCurlyBracket, myX, myY, mySize );
620 }
621 break;
622 case LeftLineBracket: {
623 luPixel halfWidth = getWidth()/2;
624 drawBigRoundBracket( painter, context, leftLineBracket,
625 myX-halfWidth, myY, mySize );
626 }
627 break;
628 case RightLineBracket: {
629 luPixel halfWidth = getWidth()/2;
630 drawBigRoundBracket( painter, context, rightLineBracket,
631 myX-halfWidth, myY, mySize );
632 }
633 break;
634 case SlashBracket:
635 if ( cmChar != -1 ) {
636 drawCMDelimiter( painter, context, myX, myY, mySize );
637 }
638 break;
639 case BackSlashBracket:
640 if ( cmChar != -1 ) {
641 drawCMDelimiter( painter, context, myX, myY, mySize );
642 }
643 break;
644 case LeftCornerBracket:
645 if ( cmChar != -1 ) {
646 drawCMDelimiter( painter, context, myX, myY, mySize );
647 }
648 else drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
649 break;
650 case RightCornerBracket:
651 if ( cmChar != -1 ) {
652 drawCMDelimiter( painter, context, myX, myY, mySize );
653 }
654 else drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
655 break;
656 case LeftRoundBracket:
657 if ( cmChar != -1 ) {
658 drawCMDelimiter( painter, context, myX, myY, mySize );
659 }
660 else {
661 drawBigRoundBracket( painter, context, leftRoundBracket, myX, myY, mySize );
662 }
663 break;
664 case RightRoundBracket:
665 if ( cmChar != -1 ) {
666 drawCMDelimiter( painter, context, myX, myY, mySize );
667 }
668 else {
669 drawBigRoundBracket( painter, context, rightRoundBracket, myX, myY, mySize );
670 }
671 break;
672 case EmptyBracket:
673 break;
674 case Integral:
675 drawCharacter(painter, context, TQFont( "cmex10" ), myX, myY, mySize, cmex_Int);
676 break;
677 case Sum:
678 drawCharacter(painter, context, TQFont( "cmex10" ), myX, myY, mySize, cmex_Sum);
679 break;
680 case Product:
681 drawCharacter(painter, context, TQFont( "cmex10" ), myX, myY, mySize, cmex_Prod);
682 break;
683 }
684
685 // debug
686// painter.setBrush(TQt::NoBrush);
687// painter.setPen(TQt::green);
688// painter.drawRect( context.layoutUnitToPixelX( myX ),
689// context.layoutUnitToPixelY( myY ),
690// context.layoutUnitToPixelX( getWidth() ),
691// context.layoutUnitToPixelY( getHeight() ) );
692}
693
694void Artwork::calcCharSize( const ContextStyle& style, luPt height, TQChar ch )
695{
696 calcCharSize( style, style.getMathFont(), height, ch );
697}
698
699
700void Artwork::drawCharacter( TQPainter& painter, const ContextStyle& style,
701 luPixel x, luPixel y,
702 luPt height, TQChar ch )
703{
704 drawCharacter( painter, style, style.getMathFont(), x, y, height, ch );
705}
706
707
708void Artwork::calcCharSize( const ContextStyle& style, TQFont f,
709 luPt height, TQChar c )
710{
711 f.setPointSizeFloat( style.layoutUnitPtToPt( height ) );
712 //f.setPointSize( height );
713 TQFontMetrics fm(f);
714 setWidth( style.ptToLayoutUnitPt( fm.width( c ) ) );
715 LuPixelRect bound = fm.boundingRect( c );
716 setHeight( style.ptToLayoutUnitPt( bound.height() ) );
717 setBaseline( style.ptToLayoutUnitPt( -bound.top() ) );
718}
719
720
721void Artwork::drawCharacter( TQPainter& painter, const ContextStyle& style,
722 TQFont f,
723 luPixel x, luPixel y, luPt height, uchar c )
724{
725 f.setPointSizeFloat( style.layoutUnitToFontSize( height, false ) );
726
727 painter.setFont( f );
728 painter.drawText( style.layoutUnitToPixelX( x ),
729 style.layoutUnitToPixelY( y+getBaseline() ),
730 TQString( TQChar( c ) ) );
731}
732
733
734void Artwork::calcRoundBracket( const ContextStyle& style, const TQChar chars[],
735 luPt height, luPt charHeight )
736{
737 uchar uppercorner = chars[0];
738 uchar lowercorner = chars[1];
739 //uchar line = style.symbolTable().character( chars[2] );
740
741 TQFont f = style.getBracketFont();
742 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
743 TQFontMetrics fm( f );
744 LuPtRect upperBound = fm.boundingRect( uppercorner );
745 LuPtRect lowerBound = fm.boundingRect( lowercorner );
746 //LuPtRect lineBound = fm.boundingRect( line );
747
748 setWidth( style.ptToLayoutUnitPt( fm.width( TQChar( uppercorner ) ) ) );
749 luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
750 //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
751
752 //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
753 setHeight( TQMAX( edgeHeight, height ) );
754}
755
756void Artwork::drawBigRoundBracket( TQPainter& p, const ContextStyle& style, const TQChar chars[],
757 luPixel x, luPixel y, luPt charHeight )
758{
759 uchar uppercorner = chars[0];
760 uchar lowercorner = chars[1];
761 uchar line = chars[2];
762
763 TQFont f = style.getBracketFont();
764 f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
765 p.setFont(f);
766
767 TQFontMetrics fm(f);
768 TQRect upperBound = fm.boundingRect(uppercorner);
769 TQRect lowerBound = fm.boundingRect(lowercorner);
770 TQRect lineBound = fm.boundingRect(line);
771
772 pixel ptX = style.layoutUnitToPixelX( x );
773 pixel ptY = style.layoutUnitToPixelY( y );
774 pixel height = style.layoutUnitToPixelY( getHeight() );
775
776// p.setPen( TQt::red );
777// //p.drawRect( ptX, ptY, upperBound.width(), upperBound.height() + lowerBound.height() );
778// p.drawRect( ptX, ptY, style.layoutUnitToPixelX( getWidth() ),
779// style.layoutUnitToPixelY( getHeight() ) );
780
781// p.setPen( TQt::black );
782 p.drawText( ptX, ptY-upperBound.top(), TQString( TQChar( uppercorner ) ) );
783 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
784 TQString( TQChar( lowercorner ) ) );
785
786 // for printing
787 //pt safety = lineBound.height() / 10.0;
788 pixel safety = 0;
789
790 pixel gap = height - upperBound.height() - lowerBound.height();
791 pixel lineHeight = lineBound.height() - safety;
792 int lineCount = tqRound( static_cast<double>( gap ) / lineHeight );
793 pixel start = upperBound.height()-lineBound.top() - safety;
794
795 for (int i = 0; i < lineCount; i++) {
796 p.drawText( ptX, ptY+start+i*lineHeight, TQString(TQChar(line)));
797 }
798 pixel remaining = gap - lineCount*lineHeight;
799 pixel dist = ( lineHeight - remaining ) / 2;
800 p.drawText( ptX, ptY+height-upperBound.height()+dist-lineBound.height()-lineBound.top(),
801 TQString( TQChar( line ) ) );
802}
803
804void Artwork::calcCurlyBracket( const ContextStyle& style, const TQChar chars[],
805 luPt height, luPt charHeight )
806{
807 uchar uppercorner = chars[0];
808 uchar lowercorner = chars[1];
809 //uchar line = style.symbolTable().character( chars[2] );
810 uchar middle = chars[3];
811
812 TQFont f = style.getBracketFont();
813 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
814 TQFontMetrics fm( f );
815 LuPtRect upperBound = fm.boundingRect( uppercorner );
816 LuPtRect lowerBound = fm.boundingRect( lowercorner );
817 //LuPtRect lineBound = fm.boundingRect( line );
818 LuPtRect middleBound = fm.boundingRect( middle );
819
820 setWidth( style.ptToLayoutUnitPt( fm.width( TQChar( uppercorner ) ) ) );
821 luPt edgeHeight = style.ptToLayoutUnitPt( upperBound.height()+
822 lowerBound.height()+
823 middleBound.height() );
824 //luPt lineHeight = style.ptToLayoutUnitPt( lineBound.height() );
825
826 //setHeight( edgeHeight + ( ( height-edgeHeight-1 ) / lineHeight + 1 ) * lineHeight );
827 setHeight( TQMAX( edgeHeight, height ) );
828}
829
830void Artwork::drawBigCurlyBracket( TQPainter& p, const ContextStyle& style, const TQChar chars[],
831 luPixel x, luPixel y, luPt charHeight )
832{
833 //TQFont f = style.getSymbolFont();
834 TQFont f = style.getBracketFont();
835 f.setPointSizeFloat( style.layoutUnitToFontSize( charHeight, false ) );
836 p.setFont(f);
837
838 uchar uppercorner = chars[0];
839 uchar lowercorner = chars[1];
840 uchar line = chars[2];
841 uchar middle = chars[3];
842
843 TQFontMetrics fm(p.fontMetrics());
844 TQRect upperBound = fm.boundingRect(uppercorner);
845 TQRect lowerBound = fm.boundingRect(lowercorner);
846 TQRect middleBound = fm.boundingRect(middle);
847 TQRect lineBound = fm.boundingRect(line);
848
849 pixel ptX = style.layoutUnitToPixelX( x );
850 pixel ptY = style.layoutUnitToPixelY( y );
851 pixel height = style.layoutUnitToPixelY( getHeight() );
852
853 //p.setPen(TQt::gray);
854 //p.drawRect(x, y, upperBound.width() + offset, height);
855
856 p.drawText( ptX, ptY-upperBound.top(), TQString( TQChar( uppercorner ) ) );
857 p.drawText( ptX, ptY+(height-middleBound.height())/2-middleBound.top(),
858 TQString( TQChar( middle ) ) );
859 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
860 TQString( TQChar( lowercorner ) ) );
861
862 // for printing
863 // If the world was perfect and the urw-symbol font correct
864 // this could be 0.
865 //lu safety = lineBound.height() / 10;
866 pixel safety = 0;
867
868 pixel lineHeight = lineBound.height() - safety;
869 pixel gap = height/2 - upperBound.height() - middleBound.height() / 2;
870
871 if (gap > 0) {
872 TQString ch = TQString(TQChar(line));
873 int lineCount = tqRound( gap / lineHeight ) + 1;
874
875 pixel start = (height - middleBound.height()) / 2 + safety;
876 for (int i = 0; i < lineCount; i++) {
877 p.drawText( ptX, ptY-lineBound.top()+TQMAX( start-(i+1)*lineHeight,
878 upperBound.width() ),
879 ch );
880 }
881
882 start = (height + middleBound.height()) / 2 - safety;
883 for (int i = 0; i < lineCount; i++) {
884 p.drawText( ptX, ptY-lineBound.top()+TQMIN( start+i*lineHeight,
885 height-upperBound.width()-lineBound.height() ),
886 ch );
887 }
888 }
889}
890
891KFORMULA_NAMESPACE_END
Contains all the style information for the formela.
luPt getAdjustedSize(TextStyle tstyle, double factor) const
Calculates the font size corresponding to the given TextStyle.
TextStyle
Textstyles like in TeX.
bool init(ContextStyle *context, bool install=true)
lazy init support.
Definition fontstyle.cpp:42
static void information(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const TQString &dontShowAgainName=TQString::null, int options=Notify)
double layoutUnitToFontSize(int luSize, bool) const
Given the font size for the font in layout units, in pt (use pointSize()) this returns the font size ...
static double ptToLayoutUnitPt(double pt)
Not zoom dependent.
int layoutUnitToPixelX(int lupix) const
The "layout unit pixel" -> "[zoomed] view pixel" conversions.