uifw/EikStd/coctlsrc/EIKLABEL.CPP
changeset 0 2f259fa3e83a
child 29 a8834a2e9a96
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <eiklabel.h>
       
    20 #include <coeutils.h>
       
    21 #include <eikenv.h>
       
    22 #include <eikpanic.h>
       
    23 #include <barsread.h>
       
    24 #include <uikon.hrh>
       
    25 #include "laflabel.h"
       
    26 
       
    27 #include <gulcolor.h>
       
    28 #include <AknUtils.h>
       
    29 
       
    30 #include <bidivisual.h> 
       
    31 #include <biditext.h>
       
    32 #include <AknBidiTextUtils.h>
       
    33 
       
    34 #include <AknPictographInterface.h>
       
    35 #include <AknPictographDrawerInterface.h>
       
    36 #include <AknLayoutFont.h>
       
    37 
       
    38 const TInt KTextEmphasisMask		= 0x30;
       
    39 const TInt KTextBufferReserveLength = 0x40;
       
    40 
       
    41 
       
    42 /* This class needs to be in .cpp file so that we
       
    43    do not accidentally make it derivable; that would
       
    44    destroy all the binary compability advantages this
       
    45    class has..
       
    46    */
       
    47 NONSHARABLE_CLASS(CEikLabelExtension) : public CBase
       
    48 	{
       
    49 public: // enums
       
    50     enum {
       
    51         ECropText,
       
    52         EUseDynamicBidiTextAlignment,
       
    53         EUseBrushStyle
       
    54         };
       
    55 public:
       
    56 	static CEikLabelExtension* NewL();
       
    57 	~CEikLabelExtension();
       
    58 	void SetTextLengthL(TInt aLength);
       
    59 
       
    60 private:
       
    61 	CEikLabelExtension();
       
    62 	void ConstructL();
       
    63 public: //data
       
    64 	HBufC* iLabelLine;
       
    65     TBitFlags iFlags;
       
    66     CWindowGc::TBrushStyle iBrushStyle;
       
    67     CAknPictographInterface* iPictographInterface; // not owned
       
    68 	};
       
    69 
       
    70 CEikLabelExtension* CEikLabelExtension::NewL()
       
    71 	{
       
    72 	CEikLabelExtension* self = new(ELeave) CEikLabelExtension;
       
    73 	CleanupStack::PushL(self);
       
    74 	self->ConstructL();
       
    75 	CleanupStack::Pop(self);
       
    76 	return self;
       
    77 	}
       
    78 
       
    79 CEikLabelExtension::CEikLabelExtension()
       
    80 	{
       
    81     iFlags.ClearAll();
       
    82 	}
       
    83 
       
    84 CEikLabelExtension::~CEikLabelExtension()
       
    85 	{
       
    86 	delete iLabelLine;
       
    87 	}
       
    88 
       
    89 void CEikLabelExtension::ConstructL()
       
    90 	{
       
    91 	iLabelLine = HBufC::NewL(0);
       
    92 	}
       
    93 
       
    94 void CEikLabelExtension::SetTextLengthL(TInt aLength)
       
    95 	{
       
    96     aLength += TBidiLogicalToVisual::KMinCharAvailable;
       
    97 	if (aLength <= iLabelLine->Des().MaxLength())
       
    98 		return;
       
    99 
       
   100 	HBufC* tempBuf = HBufC::NewL(aLength);
       
   101 	delete iLabelLine;
       
   102 	iLabelLine = tempBuf;
       
   103 	}
       
   104 
       
   105 /**
       
   106  * Gets the list of logical colors employed in the drawing of the control,
       
   107  * paired with an explanation of how they are used. Appends the list to aColorUseList.
       
   108  *
       
   109  * @since ER5U 
       
   110  */
       
   111 EXPORT_C void CEikLabel::GetColorUseListL(CArrayFix<TCoeColorUse>& aColorUseList) const
       
   112 	{
       
   113 	CCoeControl::GetColorUseListL(aColorUseList);
       
   114 
       
   115 	TInt commonAttributes = TCoeColorUse::ESurrounds|TCoeColorUse::ENormal|TCoeColorUse::ENeutral;
       
   116 	TCoeColorUse colorUse;
       
   117 
       
   118 	colorUse.SetLogicalColor(EColorLabelText);
       
   119 	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EActive|commonAttributes);
       
   120 	aColorUseList.AppendL(colorUse);
       
   121 
       
   122 	colorUse.SetLogicalColor(EColorControlBackground);
       
   123 	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EActive|commonAttributes);
       
   124 	aColorUseList.AppendL(colorUse);
       
   125 
       
   126 	colorUse.SetLogicalColor(EColorLabelDimmedText);
       
   127 	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EDimmed|commonAttributes);
       
   128 	aColorUseList.AppendL(colorUse);
       
   129 
       
   130 	TInt highlightAttributes = TCoeColorUse::EHighlights|TCoeColorUse::ENormal|TCoeColorUse::ENeutral;
       
   131 
       
   132 	colorUse.SetLogicalColor(EColorLabelTextEmphasis);
       
   133 	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EActive|highlightAttributes);
       
   134 	aColorUseList.AppendL(colorUse);
       
   135 
       
   136 	colorUse.SetLogicalColor(EColorLabelHighlightFullEmphasis);
       
   137 	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EActive|highlightAttributes);
       
   138 	aColorUseList.AppendL(colorUse);
       
   139 
       
   140 	colorUse.SetLogicalColor(EColorLabelHighlightPartialEmphasis);
       
   141 	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EDimmed|highlightAttributes);
       
   142 	aColorUseList.AppendL(colorUse);
       
   143 	}
       
   144 
       
   145 /**
       
   146  * Handles a change to the control's resources of type aType
       
   147  * which are shared across the environment, e.g. colors or fonts.
       
   148  *
       
   149  * @since ER5U 
       
   150  */
       
   151 EXPORT_C void CEikLabel::HandleResourceChange(TInt aType)
       
   152 	{
       
   153 	CCoeControl::HandleResourceChange(aType);
       
   154 	}
       
   155 
       
   156 EXPORT_C CEikLabel::~CEikLabel()
       
   157 	{
       
   158 	delete iText;
       
   159 	delete iExtension;
       
   160  	}
       
   161 
       
   162 EXPORT_C CEikLabel::CEikLabel()	: 
       
   163     iLabFlags( EUseLogicalToVisualConversion ),
       
   164     iGapBetweenLines( LafLabel::DefaultGapBetweenLines() )
       
   165 	{
       
   166 	__DECLARE_NAME(_S("CEikLabel"));
       
   167 	iFont=iCoeEnv->NormalFont();
       
   168 	}
       
   169 
       
   170 EXPORT_C void CEikLabel::SetLabelAlignment(TInt aAlignment)
       
   171 	{
       
   172     if (CheckAndCreateExtension())
       
   173         iExtension->iFlags.Assign(CEikLabelExtension::EUseDynamicBidiTextAlignment, (aAlignment == ELayoutAlignBidi));
       
   174 
       
   175     switch(aAlignment)
       
   176         {
       
   177         case ELayoutAlignBidi: // alignment handled above in extension above
       
   178             break;
       
   179         default:
       
   180             SetAlignment(AknLayoutUtils::GulAlignFromId(aAlignment));
       
   181             break;
       
   182         }
       
   183 	}
       
   184 
       
   185 EXPORT_C void CEikLabel::SetBrushStyle(CWindowGc::TBrushStyle aBrushStyle)
       
   186     {
       
   187     if (CheckAndCreateExtension())
       
   188         {
       
   189         iExtension->iBrushStyle = aBrushStyle;
       
   190         iExtension->iFlags.Set(CEikLabelExtension::EUseBrushStyle);
       
   191         }
       
   192     }
       
   193 
       
   194 EXPORT_C void CEikLabel::SetBrushStyleFromContext()
       
   195     {
       
   196     if (CheckAndCreateExtension()) // can't be sure creation above passed
       
   197         {
       
   198         iExtension->iFlags.Clear(CEikLabelExtension::EUseBrushStyle);
       
   199         }
       
   200     }
       
   201 
       
   202 EXPORT_C void CEikLabel::ConstructFromResourceL(TResourceReader& aReader)
       
   203 	{
       
   204 	TInt flags=aReader.ReadInt16();
       
   205 	SetUnderlining(flags&EikLabelUnderline);
       
   206 	SetStrikethrough(flags&EikLabelStrikeThrough);
       
   207 	iAlignment.SetHAlignment((TGulHAlignment)aReader.ReadInt16());
       
   208 	iAlignment.SetVAlignment((TGulVAlignment)aReader.ReadInt16());
       
   209 	TInt standardFont=aReader.ReadInt16();
       
   210 	switch (standardFont)
       
   211 		{
       
   212 	case EEikLabelFontLegend:
       
   213 		iFont=iEikonEnv->LegendFont();
       
   214 		break;
       
   215 	case EEikLabelFontAnnotation:
       
   216 		iFont=iEikonEnv->AnnotationFont();
       
   217 		break;
       
   218 	default:
       
   219 		break;
       
   220 		}
       
   221 	TInt length=aReader.ReadInt16();
       
   222 	if (length)
       
   223 		SetBufferReserveLengthL(length);
       
   224 	SetTextL(aReader.ReadTPtrC());
       
   225 	}
       
   226        
       
   227 EXPORT_C void CEikLabel::SetTextL(const TDesC& aText)
       
   228 	{
       
   229 	__ASSERT_DEBUG(&aText,Panic(EEikPanicLabelNullText));
       
   230 	
       
   231 	if (iLabFlags&KTextBufferReserveLength || 
       
   232 		(iText && iText->Des().MaxLength() >= aText.Length()))
       
   233 		{
       
   234         *iText=aText; // will panic if not long enough
       
   235 		}
       
   236     else
       
   237         {
       
   238         User::LeaveIfError( AknBidiTextUtils::PrepareRunInfoArray( aText ) );
       
   239 
       
   240         HBufC* newText=aText.AllocL();
       
   241 	    delete(iText); // after the AllocL succeeds
       
   242 	    iText=newText;
       
   243 
       
   244 		if ( !iExtension )
       
   245 			{
       
   246 			iExtension = CEikLabelExtension::NewL();
       
   247 			}
       
   248 		iExtension->SetTextLengthL(iText->Length());
       
   249         }
       
   250     if (iExtension)
       
   251         iExtension->iFlags.Clear(CEikLabelExtension::ECropText); // reset ECropText
       
   252     iNumberOfLines=1;
       
   253     TPtrC ptr=(*iText);
       
   254     FOREVER
       
   255         {
       
   256         const TInt offset=ptr.Locate('\n');
       
   257         if (offset<0 || offset==ptr.Length()-1)
       
   258             break;
       
   259         iNumberOfLines++;
       
   260         ptr.Set(ptr.Mid(offset+1));
       
   261         }
       
   262 	return ;
       
   263  	}
       
   264 
       
   265 EXPORT_C void CEikLabel::CropText()
       
   266 	{
       
   267 	if ( iExtension ) // if no extension do nothing as SetTextL has not yet been called
       
   268 		iExtension->iFlags.Set(CEikLabelExtension::ECropText);
       
   269 	}
       
   270 	
       
   271 TInt CEikLabel::HeightInPixels() const
       
   272     {
       
   273     return(iMargin.iTop+iMargin.iBottom + iGapBetweenLines*(iNumberOfLines-1) + iNumberOfLines*iFont->HeightInPixels());
       
   274     }
       
   275 
       
   276 TInt CEikLabel::WidthInPixels(TPtrC& aText) const
       
   277     {
       
   278     TInt maxLineWidth=0;
       
   279 
       
   280     FOREVER
       
   281         {
       
   282         const TInt offset=aText.Locate('\n');
       
   283         TPtrC left=aText;
       
   284         if (offset>=0)
       
   285             left.Set(aText.Left(offset));
       
   286 
       
   287         CFont::TMeasureTextInput input;
       
   288         if ( !(iLabFlags & EUseLogicalToVisualConversion) )
       
   289             {
       
   290             input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
       
   291             }
       
   292         TInt thisWidth = iFont->MeasureText( left, &input );
       
   293 
       
   294         if (thisWidth>maxLineWidth)
       
   295             maxLineWidth=thisWidth;
       
   296         if (offset<0 || offset==aText.Length()-1)
       
   297             break;
       
   298         aText.Set(aText.Mid(offset+1));
       
   299         }
       
   300     return(iMargin.iLeft + iMargin.iRight + maxLineWidth);
       
   301     }
       
   302 
       
   303 TInt CEikLabel::HeightInPixels(const TDesC& aText) const
       
   304     {
       
   305     // Calculate amount of lines in aText
       
   306     TInt numberOfLines = 1;
       
   307     TPtrC ptr=aText;
       
   308     FOREVER
       
   309         {
       
   310         const TInt offset=ptr.Locate('\n');
       
   311         if (offset<0 || offset==ptr.Length()-1)
       
   312             break;
       
   313         numberOfLines++;
       
   314         ptr.Set(ptr.Mid(offset+1));
       
   315         }
       
   316 
       
   317     // Calculate height.
       
   318     return(iMargin.iTop+iMargin.iBottom + iGapBetweenLines*(numberOfLines-1) + numberOfLines*iFont->HeightInPixels());
       
   319     }
       
   320 
       
   321 EXPORT_C void CEikLabel::Draw( const TRect& /*aRect*/ ) const
       
   322     {
       
   323     CWindowGc& gc = SystemGc();
       
   324     DrawToContext( gc, NULL );
       
   325     gc.SetOpaque( EFalse ); // transparency back on
       
   326     }
       
   327 
       
   328 
       
   329 void CEikLabel::DrawToContext( CBitmapContext& aContext, 
       
   330         const TRgb* aOverrideColor ) const
       
   331     {
       
   332     __ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
       
   333     TInt textTooLong = KErrNone;
       
   334     if (iExtension->iLabelLine->Des().MaxLength() < iText->Length() + TBidiLogicalToVisual::KMinCharAvailable)
       
   335         {
       
   336         TRAP(textTooLong, iExtension->SetTextLengthL(iText->Length()));
       
   337         } // textTooLong condition is handled later in this function, tries to recover as much as possible
       
   338 
       
   339     TBool outlineEffectOn = EFalse;
       
   340     const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( iFont ); 
       
   341     if (layoutFont) 
       
   342         {
       
   343         outlineEffectOn = layoutFont->FontSpecification().IsOutlineEffectOn(); 
       
   344         }
       
   345 
       
   346     CBitmapContext& gc = aContext;
       
   347     if (IsStrikethrough())
       
   348         {
       
   349         gc.SetStrikethroughStyle(EStrikethroughOn);
       
   350         }
       
   351     else
       
   352         {
       
   353         gc.SetStrikethroughStyle(EStrikethroughOff);
       
   354         }
       
   355 
       
   356     if (IsUnderlined())
       
   357         {
       
   358         gc.SetUnderlineStyle(EUnderlineOn);
       
   359         }
       
   360     else
       
   361         {
       
   362         gc.SetUnderlineStyle(EUnderlineOff);
       
   363         }
       
   364     
       
   365     if ( aOverrideColor )
       
   366         {
       
   367         gc.SetPenColor(*aOverrideColor);
       
   368         gc.SetBrushColor(*aOverrideColor);
       
   369         }
       
   370     else if ((iLabFlags&KTextEmphasisMask) != ENoEmphasis)
       
   371         {
       
   372         SetupGcForEmphasis(gc);
       
   373         }
       
   374     else
       
   375         {
       
   376         TRgb penColor;
       
   377         TRgb brushColor;
       
   378         if (IsDimmed()) 
       
   379             {
       
   380             penColor = iEikonEnv->ControlColor(EColorLabelDimmedText,*this); 
       
   381             brushColor = iEikonEnv->ControlColor(EColorControlDimmedBackground,*this); 
       
   382             }
       
   383         else
       
   384             {
       
   385             penColor = iEikonEnv->ControlColor(EColorLabelText,*this); 
       
   386             brushColor = iEikonEnv->ControlColor(EColorControlBackground,*this); 
       
   387             }
       
   388         if(outlineEffectOn)
       
   389             {
       
   390             ConvertColorsForOutlineEffect(penColor, brushColor); 
       
   391             }
       
   392         gc.SetPenColor(penColor); 
       
   393         gc.SetBrushColor(brushColor); 
       
   394         }
       
   395 
       
   396     
       
   397     gc.UseFont(iFont);
       
   398 
       
   399     if (iExtension->iFlags.IsSet(CEikLabelExtension::EUseBrushStyle))
       
   400         {
       
   401         gc.SetBrushStyle(iExtension->iBrushStyle);
       
   402         }
       
   403     
       
   404     const TRect rect = Rect();
       
   405 
       
   406     const TInt deltaHeight=rect.Height()-HeightInPixels();
       
   407     TInt preHeight=iMargin.iTop; // used on first line
       
   408     TInt postHeight=iMargin.iBottom; // used on last line
       
   409     if (deltaHeight>0)
       
   410         {
       
   411         switch(iAlignment.VAlignment())
       
   412             {
       
   413             case EVTop:
       
   414                 postHeight+=deltaHeight;
       
   415                 break;
       
   416             case EVBottom:
       
   417                 preHeight+=deltaHeight;
       
   418                 break;
       
   419             case EVCenter:
       
   420                 TInt postInc=deltaHeight/2; // give odd pixel to pre-Height
       
   421                 preHeight+=deltaHeight-postInc;
       
   422                 postHeight+=postInc;
       
   423             }
       
   424         }
       
   425     TInt lineNo=0;
       
   426     
       
   427     TPtrC ptr=(*iText);
       
   428     TRect box=rect;
       
   429     TBool clippedAtBottom=EFalse;
       
   430     TInt textPaneTopToBaseline(0);
       
   431     TInt textPaneHeight(0);
       
   432     
       
   433     if ( layoutFont )
       
   434         {
       
   435         textPaneTopToBaseline = layoutFont->TextPaneTopToBaseline();
       
   436         textPaneHeight = layoutFont->TextPaneHeight();
       
   437         }
       
   438     else
       
   439         {
       
   440         textPaneTopToBaseline = iFont->AscentInPixels();
       
   441         textPaneHeight = iFont->HeightInPixels();
       
   442         }
       
   443     
       
   444     // iGapBetweenLines is defined as baseline separation - CFont::HeightInPixels
       
   445     // Since we are using the better metrics above, we have to actually use something which is 
       
   446     // derived from iGapBetweenLines, but is e.g. reduced if textpaneheight > heightInPixels
       
   447     TInt gapBetweenTextPanes( iGapBetweenLines - (textPaneHeight - iFont->HeightInPixels()) );
       
   448 
       
   449     FOREVER
       
   450         {
       
   451         TInt ascent=textPaneTopToBaseline+preHeight;
       
   452         TInt lineHeight=textPaneHeight+preHeight;
       
   453         if (++lineNo==iNumberOfLines)
       
   454             {
       
   455             lineHeight+=postHeight;
       
   456             }
       
   457         
       
   458         TInt off=ptr.Locate('\n');
       
   459         TPtrC left=ptr;
       
   460         if (off>=0)
       
   461             {
       
   462             left.Set(ptr.Left(off));
       
   463             }
       
   464         
       
   465         box.iBr.iY=box.iTl.iY+lineHeight;
       
   466         if (box.iBr.iY>rect.iBr.iY)
       
   467             {
       
   468             box.iBr.iY=rect.iBr.iY;
       
   469             clippedAtBottom=ETrue;
       
   470             }
       
   471         
       
   472         CGraphicsContext::TTextAlign align=iAlignment.TextAlign();
       
   473         TInt margin = iMargin.iLeft;
       
   474         
       
   475         TBidiText::TDirectionality labelDirectionality = TBidiText::TextDirectionality(*iText);
       
   476         if (iExtension->iFlags.IsSet(CEikLabelExtension::EUseDynamicBidiTextAlignment))
       
   477             {
       
   478             switch(labelDirectionality)
       
   479                 {
       
   480                 case TBidiText::ELeftToRight:
       
   481                     align = CGraphicsContext::ELeft;
       
   482                     break;
       
   483                 case TBidiText::ERightToLeft:
       
   484                     align = CGraphicsContext::ERight;
       
   485                     break;
       
   486                 default:
       
   487                     break; // do nothing
       
   488                 }
       
   489             }
       
   490         
       
   491         if (align==CGraphicsContext::ERight)
       
   492             {
       
   493             margin = iMargin.iRight;
       
   494             }
       
   495         else if (align==CGraphicsContext::ECenter)
       
   496             {
       
   497             margin -= iMargin.iRight;
       
   498             }
       
   499         
       
   500         TRect adjustedBox( box ) ;  // create a new box to accommodate underline if present (without affecting layout)
       
   501         if ( IsUnderlined() )
       
   502             {
       
   503             TAknTextDecorationMetrics decoration(iFont);
       
   504             TInt underlineWidth = decoration.UnderlineHeight();
       
   505             TInt underlineSpace = decoration.BaselineToUnderlineOffset();
       
   506             
       
   507             if (  ( textPaneTopToBaseline + underlineSpace ) > textPaneHeight )
       
   508                 {
       
   509                 adjustedBox.iBr.iY += (  textPaneTopToBaseline + underlineSpace - textPaneHeight ) ;
       
   510                 }
       
   511             }
       
   512         
       
   513         TPtr text = iExtension->iLabelLine->Des();
       
   514         TInt textMaxLength = text.MaxLength();
       
   515         TBool dontDoComplicatedDraw = EFalse;
       
   516         
       
   517         TInt usableLength = 0;
       
   518         if (textTooLong == KErrNone || textMaxLength >= left.Length() + TBidiLogicalToVisual::KMinCharAvailable)
       
   519             {
       
   520             usableLength = left.Length(); // no problem with memory
       
   521             }
       
   522         else
       
   523             { // problem with lack of memory so find a usable length.
       
   524             if (labelDirectionality == TBidiText::ELeftToRight || !(iLabFlags & EUseLogicalToVisualConversion))
       
   525                 { // most likely western text so just display logically (no truncation)
       
   526                 dontDoComplicatedDraw = ETrue;
       
   527                 }
       
   528             else
       
   529                 { // most likely NOT western text so display as much visually as possible
       
   530                 if (textMaxLength > TBidiLogicalToVisual::KMinCharAvailable)
       
   531                     {
       
   532                     usableLength = textMaxLength - TBidiLogicalToVisual::KMinCharAvailable;
       
   533                     }
       
   534                 else // there is no buffer so give up and draw logically
       
   535                     {
       
   536                     dontDoComplicatedDraw = ETrue;
       
   537                     }
       
   538                 }
       
   539             }
       
   540         
       
   541         if (dontDoComplicatedDraw)
       
   542             {
       
   543             gc.DrawText( left, adjustedBox, ascent, align, margin );
       
   544             if ( iExtension->iPictographInterface )
       
   545                 {
       
   546                 iExtension->iPictographInterface->Interface()->DrawPictographsInText(
       
   547                     gc, *iFont, left, adjustedBox, ascent, align, margin );
       
   548                 }
       
   549             }
       
   550         else
       
   551             { // we have some buffer space to try and draw text correctly
       
   552             TPtrC usableText=left.Left(usableLength);
       
   553             TInt adjustedBoxWidth = adjustedBox.Size().iWidth;
       
   554             
       
   555             if (iLabFlags & EUseLogicalToVisualConversion)
       
   556                 {
       
   557                 if (iExtension->iFlags.IsSet(CEikLabelExtension::ECropText))
       
   558                     {
       
   559                     AknBidiTextUtils::ConvertToVisualAndClip(usableText, text, *iFont, adjustedBoxWidth, adjustedBoxWidth);
       
   560                     }
       
   561                 else
       
   562                     {
       
   563                     const TUint KEmptyChar = TUint(0xFFFF);
       
   564                     AknBidiTextUtils::ConvertToVisualAndClip(usableText, text, *iFont, adjustedBoxWidth, adjustedBoxWidth, AknBidiTextUtils::EImplicit, KEmptyChar );
       
   565                     }
       
   566                 }
       
   567             else
       
   568                 {
       
   569                 text = usableText; // copy
       
   570                 }
       
   571             gc.DrawText( text, adjustedBox, ascent, align, margin );
       
   572             if ( iExtension->iPictographInterface )
       
   573                 {
       
   574                 iExtension->iPictographInterface->Interface()->DrawPictographsInText(
       
   575                     gc, *iFont, text, adjustedBox, ascent, align, margin );
       
   576                 }
       
   577             }
       
   578         
       
   579         
       
   580         if (off<0 || off==ptr.Length()-1 || clippedAtBottom)
       
   581             break;
       
   582         
       
   583         ptr.Set(ptr.Mid(off+1));
       
   584         box.iTl.iY=box.iBr.iY;
       
   585         
       
   586         preHeight=gapBetweenTextPanes;
       
   587         }
       
   588     
       
   589     gc.DiscardFont();
       
   590     }
       
   591 
       
   592 EXPORT_C void CEikLabel::SetBufferReserveLengthL(TInt aLength)
       
   593 	{
       
   594 	if (iText)
       
   595 		iText=iText->ReAllocL(aLength);
       
   596 	else
       
   597 		iText=HBufC::NewL(aLength);
       
   598 	iLabFlags|=KTextBufferReserveLength;
       
   599 	iReserveLength=aLength;
       
   600 	if ( !iExtension )
       
   601 		{
       
   602 		iExtension = CEikLabelExtension::NewL();
       
   603 		}
       
   604 	iExtension->SetTextLengthL(iText->Length());
       
   605 	}
       
   606 
       
   607 EXPORT_C void CEikLabel::SetFont(const CFont* aFont) 
       
   608 	{
       
   609 	iFont=aFont;
       
   610 	}
       
   611 
       
   612 EXPORT_C TSize CEikLabel::CalcMinimumSize(TPtrC& aText) const
       
   613     {
       
   614     // HeightInPixels does not modify aText.
       
   615     const TInt height = HeightInPixels(aText);
       
   616 
       
   617     // Note that WidthInPixels modifies aText and so
       
   618     // it must be called after HeightInPixels.
       
   619     const TInt width = WidthInPixels(aText);
       
   620     return TSize( width, height );
       
   621     }
       
   622 
       
   623 EXPORT_C void CEikLabel::SetEmphasis(TTextEmphasis aEmphasis)
       
   624 	{
       
   625     iLabFlags&=(~KTextEmphasisMask);
       
   626     iLabFlags|=aEmphasis;
       
   627 	}
       
   628 
       
   629 EXPORT_C TSize CEikLabel::MinimumSize()
       
   630 	{
       
   631 	__ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
       
   632 	TPtrC ptr=(*iText);
       
   633 	iSize=TSize(WidthInPixels(ptr),HeightInPixels());
       
   634 	return(iSize);
       
   635 	}
       
   636 
       
   637 EXPORT_C void CEikLabel::SetPixelGapBetweenLines(TInt aGap)
       
   638 	{
       
   639 	iGapBetweenLines=aGap;
       
   640 	}
       
   641 
       
   642 EXPORT_C TInt CEikLabel::PixelGapBetweenLines() const
       
   643 	{
       
   644 	return iGapBetweenLines;
       
   645 	}
       
   646 
       
   647 EXPORT_C void CEikLabel::SetUnderlining(TBool aUnderLining)
       
   648 	{
       
   649 	if (aUnderLining) {iLabFlags|=EUnderlining;}
       
   650         else iLabFlags&=(~EUnderlining);
       
   651 	}
       
   652 
       
   653 EXPORT_C void CEikLabel::SetStrikethrough(TBool aStrikethrough)
       
   654 	{
       
   655 	if (aStrikethrough) {iLabFlags|=EStrikethrough;}
       
   656         else iLabFlags&=(~EStrikethrough);
       
   657 	}
       
   658 
       
   659 EXPORT_C TInt CEikLabel::BufferReserveLength() const
       
   660 	{
       
   661 	return (iLabFlags&KTextBufferReserveLength? iReserveLength : 0);
       
   662 	}
       
   663 
       
   664 EXPORT_C void CEikLabel::UseLogicalToVisualConversion( TBool aUseConversion )
       
   665     {
       
   666     if ( aUseConversion )
       
   667         {
       
   668         iLabFlags |= EUseLogicalToVisualConversion;
       
   669         }
       
   670     else
       
   671         {
       
   672         iLabFlags &= (~EUseLogicalToVisualConversion);
       
   673         }
       
   674     }
       
   675 
       
   676 EXPORT_C TBool CEikLabel::LogicalToVisualConversionUsed() const
       
   677     {
       
   678     return iLabFlags & EUseLogicalToVisualConversion;
       
   679     }
       
   680 
       
   681 EXPORT_C void CEikLabel::EnablePictographsL( CAknPictographInterface& aInterface )
       
   682     {
       
   683     if ( !iExtension )
       
   684         {
       
   685         iExtension = CEikLabelExtension::NewL();
       
   686         }
       
   687 
       
   688     iExtension->iPictographInterface = &aInterface;
       
   689     }
       
   690 
       
   691 EXPORT_C void CEikLabel::DisablePictographs()
       
   692     {
       
   693     if ( iExtension )
       
   694         {
       
   695         iExtension->iPictographInterface = NULL;
       
   696         }
       
   697     }
       
   698 
       
   699 void CEikLabel::SetupGcForEmphasis(CGraphicsContext& aGc) const
       
   700 	{
       
   701     TRgb penColor;
       
   702     TRgb brushColor; 
       
   703 
       
   704     penColor = (iEikonEnv->ControlColor(EColorLabelTextEmphasis,*this)); 
       
   705     if ((iLabFlags&KTextEmphasisMask) == EFullEmphasis) 
       
   706         {
       
   707         brushColor = (iEikonEnv->ControlColor(EColorLabelHighlightFullEmphasis,*this)); 
       
   708         }
       
   709     else
       
   710         {
       
   711         brushColor = (iEikonEnv->ControlColor(EColorLabelHighlightPartialEmphasis,*this)); 
       
   712         }
       
   713     
       
   714     aGc.SetPenColor(penColor); 
       
   715     aGc.SetBrushColor(brushColor);
       
   716     aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); 
       
   717     }
       
   718 
       
   719 TBool CEikLabel::CheckAndCreateExtension()
       
   720     {
       
   721 	if (!iExtension)
       
   722 		{
       
   723 		TRAP_IGNORE(iExtension = CEikLabelExtension::NewL());
       
   724 		}
       
   725     return (iExtension != NULL);
       
   726     }
       
   727 
       
   728 /**
       
   729  * Writes the internal state of the control and its components to aStream.
       
   730  * Does nothing in release mode.
       
   731  * Designed to be overidden and base called by subclasses.
       
   732  *
       
   733  * @internal
       
   734  * @since App-Framework_6.1
       
   735  */
       
   736 #ifndef _DEBUG
       
   737 EXPORT_C void CEikLabel::WriteInternalStateL(RWriteStream&) const
       
   738 	{}
       
   739 #else
       
   740 EXPORT_C void CEikLabel::WriteInternalStateL(RWriteStream& aWriteStream) const
       
   741 	{
       
   742 	_LIT(KLitEikLblCtlStart, "<CEiklabel>");
       
   743 	_LIT(KLitEikLblCtlEnd, "<\\CEikLabel>");
       
   744 
       
   745 	_LIT(KLitEikLblTxt,"<iText>");
       
   746 	_LIT(KLitEikLblTxtEnd,"<\\iText>");
       
   747 	_LIT(KLitEikLblFnt,"<iFont>");
       
   748 	_LIT(KLitEikLblFntEnd,"<\\iFont>");
       
   749 	_LIT(KLitEikLblNoLns,"<iNumberOfLines>");
       
   750 	_LIT(KLitEikLblNoLnsEnd,"<\\iNumberOfLines>");
       
   751 	_LIT(KLitEikLblFlgs,"<iLabFlags>");
       
   752 	_LIT(KLitEikLblFlgsEnd,"<\\iLabFlags>");
       
   753 	_LIT(KLitEikLblGpBtwnLns,"<iGapBetweenLines>");
       
   754 	_LIT(KLitEikLblGpBtwnLnsEnd,"<\\iGapBetweenLines>");
       
   755 	_LIT(KLitEikLblResLen,"<iReserveLength>");
       
   756 	_LIT(KLitEikLblResLenEnd,"<\\iReserveLength>");
       
   757 
       
   758 	aWriteStream << KLitEikLblCtlStart;
       
   759 	aWriteStream << KLitEikLblTxt;
       
   760 	if(iText)
       
   761 		aWriteStream.WriteL(*iText);
       
   762 	aWriteStream << KLitEikLblTxtEnd;
       
   763 	aWriteStream << KLitEikLblFnt;
       
   764 	const TFontSpec& spec=iFont->FontSpecInTwips();
       
   765 	aWriteStream << spec;
       
   766 	aWriteStream << KLitEikLblFntEnd;
       
   767 	aWriteStream << KLitEikLblNoLns;
       
   768 	aWriteStream.WriteInt32L(iNumberOfLines);
       
   769 	aWriteStream << KLitEikLblNoLnsEnd;
       
   770 	aWriteStream << KLitEikLblFlgs;
       
   771 	aWriteStream.WriteInt32L(iLabFlags);
       
   772 	aWriteStream << KLitEikLblFlgsEnd;
       
   773 	aWriteStream << KLitEikLblGpBtwnLns;
       
   774 	aWriteStream.WriteInt32L(iGapBetweenLines);
       
   775 	aWriteStream << KLitEikLblGpBtwnLnsEnd;
       
   776 	aWriteStream << KLitEikLblResLen;
       
   777 	aWriteStream.WriteInt32L(iReserveLength);
       
   778 	aWriteStream << KLitEikLblResLenEnd;
       
   779 	CEikAlignedControl::WriteInternalStateL(aWriteStream);
       
   780 	aWriteStream << KLitEikLblCtlEnd;
       
   781 	}
       
   782 #endif
       
   783 
       
   784 EXPORT_C void CEikLabel::HandlePointerEventL(const TPointerEvent& aPointerEvent) 
       
   785     { 
       
   786     CEikAlignedControl::HandlePointerEventL(aPointerEvent); 
       
   787     }
       
   788 
       
   789 EXPORT_C void* CEikLabel::ExtensionInterface( TUid /*aInterface*/ )
       
   790     {
       
   791     return NULL;
       
   792     }
       
   793 
       
   794 EXPORT_C void CEikLabel::Reserved_2()
       
   795 	{}
       
   796 
       
   797 // @todo use some utility 
       
   798 #define max(a, b) a > b ? a : b; 
       
   799 #define min(a, b) a < b ? a : b; 
       
   800 #define abs(a) a < 0 ? -a : a; 
       
   801 
       
   802 TInt CalculateLuminance(const TRgb& aColor) 
       
   803     { 
       
   804     TInt R = aColor.Red(); 
       
   805     TInt G = aColor.Green(); 
       
   806     TInt B = aColor.Blue(); 
       
   807     // Should be scaled to 0-255? 
       
   808     TInt Y = (((66 * R) + (129 * G) + (25 * B) + 128) >> 8) + 16; 
       
   809     return Y; 
       
   810     } 
       
   811     
       
   812 void CEikLabel::ConvertColorsForOutlineEffect(TRgb& aPenColor, TRgb& aBrushColor) const 
       
   813     { 
       
   814     // the caller intends the brush color to be the background or outline, 
       
   815     // and the pen color to be the foreground color 
       
   816     TRgb innerColor = aPenColor; 
       
   817     TRgb outerColor = aBrushColor; 
       
   818 
       
   819     // @todo maybe there is already some conversion utility in multimedia image library? 
       
   820     TInt innerLum = CalculateLuminance(innerColor); 
       
   821     TInt outerLum = CalculateLuminance(outerColor); 
       
   822     
       
   823     // if the defined colours are the same, then change the outline color so that 
       
   824     // it's either black or white, contrasting according to the font label text color's brightness 
       
   825     TInt difference = outerLum - innerLum; 
       
   826     difference = abs(difference); 
       
   827     TInt half = (0xff / 2); // @todo figure out hlsMax somehow 
       
   828     TInt threshold = (0xff / 3); // @todo figure out hlsMax somehow, and decide on the threshold! 
       
   829     if(difference < threshold) 
       
   830         { 
       
   831         // if inner luminance is low, the outer luminance should be high, i.e. white 
       
   832         outerColor = (innerLum < half) ? KRgbWhite : KRgbBlack; 
       
   833         } 
       
   834     
       
   835     // for outline effect, we must set the color we want as the outline to the pen color, and 
       
   836     // the color we want as the fill to the brush color, so swap them round 
       
   837     aPenColor = outerColor; 
       
   838     aBrushColor = innerColor; 
       
   839     } 
       
   840 
       
   841