416 Q_UNUSED(lineBegin) |
418 Q_UNUSED(lineBegin) |
417 #endif // HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
419 #endif // HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
418 } |
420 } |
419 |
421 |
420 /* |
422 /* |
421 This method paint each line in tree pieces. |
423 This method paints single piece of text layout. |
422 In each piece uses different pen. |
424 If line contains criticalX value then fadePen is used for painting in other |
423 When fade effect is not needed on some end centerPen is used. |
425 case normalPen is used. |
424 */ |
426 */ |
425 int HbTextItemPrivate::paintFaded(QPainter *painter, |
427 void HbTextItemPrivate::paintArea(QPainter *painter, |
426 int firstItemToPaint, |
428 int firstItemToPaint, |
427 const QPen& leftPen, |
429 int lastItemToPaint, |
428 const QPen& centerPen, |
430 const QPen& normalPen, |
429 const QPen& rightPen, |
431 const QPen& fadePen, |
430 const QRectF& area ) const |
432 qreal criticalX) const |
431 { |
433 { |
432 Q_Q(const HbTextItem); |
434 for(int i=firstItemToPaint; i<=lastItemToPaint; ++i) { |
433 |
|
434 const int n = mTextLayout.lineCount(); |
|
435 const qreal leftBorder = q->contentsRect().left()-KFadeTolerance; |
|
436 const qreal rightBorder = q->contentsRect().right()+KFadeTolerance; |
|
437 |
|
438 QRectF leftRect(area); |
|
439 leftRect.setRight(mFadeFromRect.left()); |
|
440 QRectF centerRect(area); |
|
441 centerRect.moveLeft(leftRect.right()); |
|
442 centerRect.setRight(mFadeFromRect.right()); |
|
443 QRectF rightRect(area); |
|
444 rightRect.setLeft(centerRect.right()); |
|
445 |
|
446 qreal maxY = area.bottom(); |
|
447 |
|
448 for(int i=firstItemToPaint; i<n; ++i) { |
|
449 QTextLine line = mTextLayout.lineAt(i); |
435 QTextLine line = mTextLayout.lineAt(i); |
450 QRectF lineRect = line.naturalTextRect(); |
436 QRectF lineRect = line.naturalTextRect(); |
451 lineRect.translate(mOffsetPos); |
437 lineRect.translate(mOffsetPos); |
452 |
438 |
453 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
439 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
454 const QPointF gradientOffset( |
440 const QPointF gradientOffset(lineRect.left(), |
455 QPointF(lineRect.left(), |
441 lineRect.top()+line.ascent()); |
456 lineRect.top()+line.ascent()) |
442 |
457 ); |
443 if (lineRect.left()<criticalX && lineRect.right()>criticalX) { |
|
444 setPainterPen(painter, fadePen, gradientOffset); |
|
445 } else { |
|
446 setPainterPen(painter, normalPen, gradientOffset); |
|
447 } |
|
448 #else |
|
449 if (lineRect.left()<criticalX && lineRect.right()>criticalX) { |
|
450 painter->setPen(fadePen); |
|
451 } else { |
|
452 painter->setPen(normalPen); |
|
453 } |
458 #endif // HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
454 #endif // HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
459 |
455 |
460 QRectF currentCenter(centerRect); |
456 line.draw(painter, mOffsetPos); |
461 |
457 } // for i |
462 if(lineRect.top()>maxY) { |
458 } |
463 // stop painting line by line |
459 |
464 return i; // current line won't be painted at all |
460 /* |
465 } |
461 This method is used to draw center part of lines. |
466 |
462 It is also used to calculate range of lines needed for painting in this range. |
467 if(lineRect.left()<leftBorder) { |
463 */ |
|
464 int HbTextItemPrivate::paintArea(QPainter *painter, |
|
465 int firstItemToPaint, |
|
466 const QPen& normalPen, |
|
467 qreal lastValidY) const |
|
468 { |
|
469 int i; |
|
470 const int n = mTextLayout.lineCount(); |
|
471 |
|
472 #ifndef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
|
473 painter->setPen(normalPen); |
|
474 #endif |
|
475 |
|
476 for(i=firstItemToPaint; i<n; ++i) { |
|
477 QTextLine line = mTextLayout.lineAt(i); |
|
478 QRectF lineRect = line.naturalTextRect(); |
|
479 lineRect.translate(mOffsetPos); |
|
480 |
|
481 if (lineRect.top()>lastValidY) { |
|
482 return i; |
|
483 } |
468 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
484 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
469 setPainterPen(painter, leftPen, gradientOffset); |
485 const QPointF gradientOffset(lineRect.left(), |
470 #else |
486 lineRect.top()+line.ascent()); |
471 painter->setPen(leftPen); |
487 |
472 #endif |
488 setPainterPen(painter, normalPen, gradientOffset); |
473 painter->setClipRect(leftRect); |
489 #endif // HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
474 line.draw(painter, mOffsetPos); |
490 |
475 } else { |
491 line.draw(painter, mOffsetPos); |
476 // no fade on this end so extend currentCenter |
492 |
477 currentCenter.setLeft(leftRect.left()); |
493 if (lineRect.bottom()>lastValidY) { |
478 } |
494 return i; |
479 |
495 } |
480 if(lineRect.right()>rightBorder) { |
496 } // for i |
481 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
497 return n-1; |
482 setPainterPen(painter, rightPen, gradientOffset); |
498 } |
483 #else |
499 |
484 painter->setPen(rightPen); |
500 bool HbTextItemPrivate::setClipPath(QPainter *painter, |
485 #endif |
501 const QRectF& rect, |
486 painter->setClipRect(rightRect); |
502 const QPainterPath& initialCliping) const |
487 line.draw(painter, mOffsetPos); |
503 { |
488 } else { |
504 if (initialCliping.isEmpty()) { |
489 // no fade on this end so extend currentCenter |
505 painter->setClipRect(rect); |
490 currentCenter.setRight(rightRect.right()); |
506 } else { |
491 } |
507 QPainterPath newPath(rect.topLeft()); |
492 |
508 newPath.addRect(rect); |
493 if(currentCenter.width()>0) { |
509 |
494 #ifdef HB_FADE_EFFECT_WORKAROUND_ON_PHONE |
510 if (!initialCliping.intersects(newPath)) { |
495 setPainterPen(painter, centerPen, gradientOffset); |
511 return false; // dont paint |
496 #else |
512 } |
497 painter->setPen(centerPen); |
513 newPath = initialCliping.intersected(newPath); |
498 #endif |
514 |
499 painter->setClipRect(currentCenter); |
515 painter->setClipPath(newPath); |
500 line.draw(painter, mOffsetPos); |
516 } |
501 } |
517 return true; |
502 |
518 } |
503 if(lineRect.bottom()>maxY) { |
|
504 // stop painting line by line |
|
505 return i; // current line has been painted partially |
|
506 } |
|
507 } // for loop |
|
508 |
|
509 return n; |
|
510 } // paintFaded() |
|
511 |
519 |
512 void HbTextItemPrivate::paintWithFadeEffect(QPainter *painter) const |
520 void HbTextItemPrivate::paintWithFadeEffect(QPainter *painter) const |
513 { |
521 { |
514 Q_Q(const HbTextItem); |
522 Q_Q(const HbTextItem); |
515 |
523 |
516 QLinearGradient gradient; |
524 QLinearGradient gradient; |
517 setupGradient(&gradient, q->textColor()); |
525 setupGradient(&gradient, q->textColor()); |
|
526 const QPainterPath initialClipPath = painter->clipPath(); |
518 |
527 |
519 const QRectF contentRect = q->contentsRect(); |
528 const QRectF contentRect = q->contentsRect(); |
520 int i=0; |
529 int i=0; |
521 |
530 |
522 const int n = mTextLayout.lineCount(); |
531 const int n = mTextLayout.lineCount(); |
532 |
541 |
533 QRectF centerRect(mFadeToRect); |
542 QRectF centerRect(mFadeToRect); |
534 if(mTextLayout.lineAt(0).y()+mOffsetPos.y()<contentRect.top()) { |
543 if(mTextLayout.lineAt(0).y()+mOffsetPos.y()<contentRect.top()) { |
535 centerRect.setTop(mFadeFromRect.top()); |
544 centerRect.setTop(mFadeFromRect.top()); |
536 |
545 |
|
546 // top center gradient (==): |
|
547 QPointF from(mFadeFromRect.topLeft()); |
|
548 gradient.setStart(mFadeFromRect.left(),mFadeToRect.top()); |
|
549 gradient.setFinalStop(from); |
|
550 QBrush centerBrush(gradient); |
|
551 QPen centerPen; |
|
552 centerPen.setBrush(centerBrush); |
|
553 |
|
554 if (setClipPath(painter, |
|
555 QRectF(gradient.start(), mFadeFromRect.topRight()), |
|
556 initialClipPath)) { |
|
557 i = paintArea(painter, 0, centerPen, from.y()); |
|
558 } else { |
|
559 i = 0; |
|
560 } |
|
561 |
537 // top left gradient (//): |
562 // top left gradient (//): |
538 QPointF from(mFadeFromRect.topLeft()); |
|
539 gradient.setStart(from.x()-mCornerFadeX, from.y()-mCornerFadeY); |
563 gradient.setStart(from.x()-mCornerFadeX, from.y()-mCornerFadeY); |
540 gradient.setFinalStop(from); |
|
541 QBrush leftBrush(gradient); |
564 QBrush leftBrush(gradient); |
542 QPen leftPen; |
565 QPen leftPen; |
543 leftPen.setBrush(leftBrush); |
566 leftPen.setBrush(leftBrush); |
544 |
567 if (setClipPath(painter, |
545 // top center gradient (==): |
568 QRectF(mFadeToRect.topLeft(), mFadeFromRect.topLeft()), |
546 gradient.setStart(mFadeFromRect.left(),mFadeToRect.top()); |
569 initialClipPath)) { |
547 QBrush centerBrush(gradient); |
570 paintArea(painter, 0, i, centerPen, leftPen, contentRect.left()-KFadeTolerance); |
548 QPen centerPen; |
571 } |
549 centerPen.setBrush(centerBrush); |
|
550 |
572 |
551 // top right gradient (\\): |
573 // top right gradient (\\): |
552 from = mFadeFromRect.topRight(); |
574 from = mFadeFromRect.topRight(); |
553 gradient.setStart(from.x()+mCornerFadeX, from.y()-mCornerFadeY); |
575 gradient.setStart(from.x()+mCornerFadeX, from.y()-mCornerFadeY); |
554 gradient.setFinalStop(from); |
576 gradient.setFinalStop(from); |
555 QBrush rightBrush(gradient); |
577 QBrush rightBrush(gradient); |
556 QPen rightPen; |
578 QPen rightPen; |
557 rightPen.setBrush(rightBrush); |
579 rightPen.setBrush(rightBrush); |
558 |
580 |
559 QRectF clipTo(mFadeToRect); |
581 if (setClipPath(painter, |
560 clipTo.setBottom(mFadeFromRect.top()); |
582 QRectF(mFadeToRect.topRight(), mFadeFromRect.topRight()), |
561 i = paintFaded(painter, 0, leftPen, centerPen, rightPen, clipTo); |
583 initialClipPath)) { |
562 } |
584 paintArea(painter, 0, i, centerPen, rightPen, contentRect.right()+KFadeTolerance); |
563 |
585 } |
|
586 } |
|
587 |
|
588 bool paintBottom = false; |
564 if(mTextLayout.lineAt(n-1).naturalTextRect().bottom()+mOffsetPos.y()>contentRect.bottom()) { |
589 if(mTextLayout.lineAt(n-1).naturalTextRect().bottom()+mOffsetPos.y()>contentRect.bottom()) { |
565 // bottom fade is needed here |
590 // bottom fade is needed here |
566 centerRect.setBottom(mFadeFromRect.bottom()); |
591 centerRect.setBottom(mFadeFromRect.bottom()); |
|
592 paintBottom = true; |
567 } |
593 } |
568 |
594 |
569 // paint center part |
595 // paint center part |
570 { |
596 { |
|
597 int startFrom = i; |
|
598 QPen centerPen(q->textColor()); |
|
599 if (setClipPath(painter, |
|
600 QRectF(QPointF(mFadeFromRect.left(), centerRect.top()), |
|
601 QPointF(mFadeFromRect.right(), centerRect.bottom())), |
|
602 initialClipPath)) { |
|
603 // center with no gradient: |
|
604 i = paintArea(painter, i, centerPen, centerRect.bottom()); |
|
605 } |
|
606 |
571 // left gradient | || |
607 // left gradient | || |
572 gradient.setStart(mFadeToRect.left(), mFadeFromRect.top()); |
608 gradient.setStart(mFadeToRect.left(), mFadeFromRect.top()); |
573 gradient.setFinalStop(mFadeFromRect.topLeft()); |
609 gradient.setFinalStop(mFadeFromRect.topLeft()); |
574 QBrush leftBrush(gradient); |
610 QBrush leftBrush(gradient); |
575 QPen leftPen; |
611 QPen leftPen; |
576 leftPen.setBrush(leftBrush); |
612 leftPen.setBrush(leftBrush); |
577 |
613 if (setClipPath(painter, |
578 // center with no gradient: |
614 QRectF(centerRect.topLeft(), |
579 QPen centerPen(q->textColor()); |
615 QPointF(mFadeFromRect.left(), |
580 |
616 centerRect.bottom())), |
581 // top right gradient || | |
617 initialClipPath)) { |
|
618 paintArea(painter, startFrom, i, centerPen, leftPen, contentRect.left()-KFadeTolerance); |
|
619 } |
|
620 |
|
621 // right gradient || | |
582 gradient.setStart(mFadeToRect.right(), mFadeFromRect.top()); |
622 gradient.setStart(mFadeToRect.right(), mFadeFromRect.top()); |
583 gradient.setFinalStop(mFadeFromRect.topRight()); |
623 gradient.setFinalStop(mFadeFromRect.topRight()); |
584 QBrush rightBrush(gradient); |
624 QBrush rightBrush(gradient); |
585 QPen rightPen; |
625 QPen rightPen; |
586 rightPen.setBrush(rightBrush); |
626 rightPen.setBrush(rightBrush); |
587 i = paintFaded(painter, i, leftPen, centerPen, rightPen, centerRect); |
627 |
|
628 if (setClipPath(painter, |
|
629 QRectF(QPointF(mFadeFromRect.right(), centerRect.top()), |
|
630 centerRect.bottomRight()), |
|
631 initialClipPath)) { |
|
632 paintArea(painter, startFrom, i, centerPen, rightPen, contentRect.right()+KFadeTolerance); |
|
633 } |
588 } |
634 } |
589 |
635 |
590 // need to draw bottom as faded? is some lines remained? |
636 // need to draw bottom as faded? is some lines remained? |
591 if(i<n) { |
637 if (paintBottom) { |
592 // bottom left gradient (\\): |
638 int startFrom = i; |
|
639 |
|
640 // bottom center gradient (==): |
593 QPointF from(mFadeFromRect.bottomLeft()); |
641 QPointF from(mFadeFromRect.bottomLeft()); |
594 gradient.setStart(from.x()-mCornerFadeX, from.y()+mCornerFadeY); |
|
595 gradient.setFinalStop(from); |
642 gradient.setFinalStop(from); |
596 QBrush leftBrush(gradient); |
|
597 QPen leftPen; |
|
598 leftPen.setBrush(leftBrush); |
|
599 |
|
600 // bottom center gradient (==): |
|
601 gradient.setStart(mFadeFromRect.left(),mFadeToRect.bottom()); |
643 gradient.setStart(mFadeFromRect.left(),mFadeToRect.bottom()); |
602 QBrush centerBrush(gradient); |
644 QBrush centerBrush(gradient); |
603 QPen centerPen; |
645 QPen centerPen; |
604 centerPen.setBrush(centerBrush); |
646 centerPen.setBrush(centerBrush); |
|
647 |
|
648 if (setClipPath(painter, |
|
649 QRectF(mFadeFromRect.bottomLeft(), |
|
650 QPointF(mFadeFromRect.right(), mFadeToRect.bottom())), |
|
651 initialClipPath)) { |
|
652 // center with no gradient: |
|
653 i = paintArea(painter, i, centerPen, mFadeToRect.bottom()); |
|
654 } |
|
655 |
|
656 // bottom left gradient (\\): |
|
657 gradient.setStart(from.x()-mCornerFadeX, from.y()+mCornerFadeY); |
|
658 QBrush leftBrush(gradient); |
|
659 QPen leftPen; |
|
660 leftPen.setBrush(leftBrush); |
|
661 |
|
662 if (setClipPath(painter, |
|
663 QRectF(mFadeFromRect.bottomLeft(), |
|
664 mFadeToRect.bottomLeft()), |
|
665 initialClipPath)) { |
|
666 // center with no gradient: |
|
667 paintArea(painter, startFrom, i, centerPen, leftPen, contentRect.left()-KFadeTolerance); |
|
668 } |
605 |
669 |
606 // bottom right gradient (//): |
670 // bottom right gradient (//): |
607 from = mFadeFromRect.bottomRight(); |
671 from = mFadeFromRect.bottomRight(); |
608 gradient.setStart(from.x()+mCornerFadeX, from.y()+mCornerFadeY); |
672 gradient.setStart(from.x()+mCornerFadeX, from.y()+mCornerFadeY); |
609 gradient.setFinalStop(from); |
673 gradient.setFinalStop(from); |
610 QBrush rightBrush(gradient); |
674 QBrush rightBrush(gradient); |
611 QPen rightPen; |
675 QPen rightPen; |
612 rightPen.setBrush(rightBrush); |
676 rightPen.setBrush(rightBrush); |
613 |
677 |
614 QRectF clipTo(mFadeToRect); |
678 if (setClipPath(painter, |
615 clipTo.setTop(mFadeFromRect.bottom()); |
679 QRectF(mFadeFromRect.bottomRight(), |
616 i = paintFaded(painter, 0, leftPen, centerPen, rightPen, clipTo); |
680 mFadeToRect.bottomRight()), |
617 } |
681 initialClipPath)) { |
|
682 // center with no gradient: |
|
683 paintArea(painter, startFrom, i, centerPen, rightPen, contentRect.right()+KFadeTolerance); |
|
684 } |
|
685 } |
|
686 |
|
687 // restoring initial clipping region |
|
688 painter->setClipPath(initialClipPath); |
618 } |
689 } |
619 |
690 |
620 void HbTextItemPrivate::setFadeLengths(qreal xLength, qreal yLength) |
691 void HbTextItemPrivate::setFadeLengths(qreal xLength, qreal yLength) |
621 { |
692 { |
622 static const qreal KMinDiff = 0.5; |
693 static const qreal KMinDiff = 0.5; |
1151 |
1227 |
1152 /*! |
1228 /*! |
1153 Shows (default) or hides text. |
1229 Shows (default) or hides text. |
1154 Size hint remains unchanged (same as when text is visible). |
1230 Size hint remains unchanged (same as when text is visible). |
1155 |
1231 |
1156 \sa HbTextItem::isVisible() |
1232 Equvalent of QGraphicsItem::setVisible(bool) |
1157 */ |
1233 */ |
1158 void HbTextItem::setTextVisible(bool isVisible) |
1234 void HbTextItem::setTextVisible(bool isVisible) |
1159 { |
1235 { |
1160 Q_D(HbTextItem); |
1236 setVisible(isVisible); |
1161 if( d->mDontPrint == isVisible ) { |
|
1162 d->mDontPrint = !isVisible; |
|
1163 update(); |
|
1164 } |
|
1165 } |
1237 } |
1166 |
1238 |
1167 /*! |
1239 /*! |
1168 Returns if text is visible. |
1240 Returns if text is visible. |
1169 |
1241 |
1170 \sa HbTextItem::setTextVisible(bool) |
1242 \sa HbTextItem::setTextVisible(bool) |
|
1243 |
|
1244 Equvalent of QGraphicsItem::isVisible() |
1171 */ |
1245 */ |
1172 bool HbTextItem::isTextVisible() const |
1246 bool HbTextItem::isTextVisible() const |
1173 { |
1247 { |
1174 Q_D(const HbTextItem); |
1248 return isVisible(); |
1175 return !d->mDontPrint; |
1249 } |
1176 } |
1250 |
1177 |
1251 /*! |
1178 /*! |
1252 enables (default) od disables text cliping when item geometry is to small. |
1179 enables (default) or disables text clipping when item geometry is too small. |
|
1180 |
1253 |
1181 \sa HbTextItem::isTextClip() |
1254 \sa HbTextItem::isTextClip() |
|
1255 |
|
1256 Equvalent of QGraphicsItem::setFlag(QGraphicsItem::ItemClipsToShape, clipping) |
1182 */ |
1257 */ |
1183 void HbTextItem::setTextClip(bool clipping) |
1258 void HbTextItem::setTextClip(bool clipping) |
1184 { |
1259 { |
1185 Q_D(HbTextItem); |
1260 setFlag(QGraphicsItem::ItemClipsToShape, clipping); |
1186 if( d->mDontClip == clipping ) { |
1261 } |
1187 prepareGeometryChange(); |
1262 |
1188 d->mDontClip = !clipping; |
1263 /*! |
1189 setFlag(QGraphicsItem::ItemClipsToShape, clipping); |
1264 Returns true if text is cliped when item geometry is to small. |
1190 update(); |
|
1191 } |
|
1192 } |
|
1193 |
|
1194 /*! |
|
1195 Returns true if text is clipped when item geometry is too small. |
|
1196 |
|
1197 \sa HbTextItem::setTextClip(bool) |
1265 \sa HbTextItem::setTextClip(bool) |
|
1266 |
|
1267 Equvalent of QGraphicsItem::flags().testFlag(QGraphicsItem::ItemClipsToShape) |
1198 */ |
1268 */ |
1199 bool HbTextItem::isTextClip() const |
1269 bool HbTextItem::isTextClip() const |
1200 { |
1270 { |
1201 Q_D(const HbTextItem); |
1271 return flags().testFlag(ItemClipsToShape); |
1202 return !d->mDontClip; |
|
1203 } |
1272 } |
1204 |
1273 |
1205 /*! |
1274 /*! |
1206 Sets minimum number of lines for text item. If minimum number of lines is set, |
1275 Sets minimum number of lines for text item. If minimum number of lines is set, |
1207 then text item will always draw at least this number of lines. |
1276 then text item will always draw at least this number of lines. |