uifw/EikStd/coctlsrc/EIKLABEL.CPP
changeset 0 2f259fa3e83a
child 13 a8834a2e9a96
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/coctlsrc/EIKLABEL.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,841 @@
+/*
+* Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <eiklabel.h>
+#include <coeutils.h>
+#include <eikenv.h>
+#include <eikpanic.h>
+#include <barsread.h>
+#include <uikon.hrh>
+#include "laflabel.h"
+
+#include <gulcolor.h>
+#include <AknUtils.h>
+
+#include <bidivisual.h> 
+#include <biditext.h>
+#include <AknBidiTextUtils.h>
+
+#include <AknPictographInterface.h>
+#include <AknPictographDrawerInterface.h>
+#include <AknLayoutFont.h>
+
+const TInt KTextEmphasisMask		= 0x30;
+const TInt KTextBufferReserveLength = 0x40;
+
+
+/* This class needs to be in .cpp file so that we
+   do not accidentally make it derivable; that would
+   destroy all the binary compability advantages this
+   class has..
+   */
+NONSHARABLE_CLASS(CEikLabelExtension) : public CBase
+	{
+public: // enums
+    enum {
+        ECropText,
+        EUseDynamicBidiTextAlignment,
+        EUseBrushStyle
+        };
+public:
+	static CEikLabelExtension* NewL();
+	~CEikLabelExtension();
+	void SetTextLengthL(TInt aLength);
+
+private:
+	CEikLabelExtension();
+	void ConstructL();
+public: //data
+	HBufC* iLabelLine;
+    TBitFlags iFlags;
+    CWindowGc::TBrushStyle iBrushStyle;
+    CAknPictographInterface* iPictographInterface; // not owned
+	};
+
+CEikLabelExtension* CEikLabelExtension::NewL()
+	{
+	CEikLabelExtension* self = new(ELeave) CEikLabelExtension;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CEikLabelExtension::CEikLabelExtension()
+	{
+    iFlags.ClearAll();
+	}
+
+CEikLabelExtension::~CEikLabelExtension()
+	{
+	delete iLabelLine;
+	}
+
+void CEikLabelExtension::ConstructL()
+	{
+	iLabelLine = HBufC::NewL(0);
+	}
+
+void CEikLabelExtension::SetTextLengthL(TInt aLength)
+	{
+    aLength += TBidiLogicalToVisual::KMinCharAvailable;
+	if (aLength <= iLabelLine->Des().MaxLength())
+		return;
+
+	HBufC* tempBuf = HBufC::NewL(aLength);
+	delete iLabelLine;
+	iLabelLine = tempBuf;
+	}
+
+/**
+ * Gets the list of logical colors employed in the drawing of the control,
+ * paired with an explanation of how they are used. Appends the list to aColorUseList.
+ *
+ * @since ER5U 
+ */
+EXPORT_C void CEikLabel::GetColorUseListL(CArrayFix<TCoeColorUse>& aColorUseList) const
+	{
+	CCoeControl::GetColorUseListL(aColorUseList);
+
+	TInt commonAttributes = TCoeColorUse::ESurrounds|TCoeColorUse::ENormal|TCoeColorUse::ENeutral;
+	TCoeColorUse colorUse;
+
+	colorUse.SetLogicalColor(EColorLabelText);
+	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EActive|commonAttributes);
+	aColorUseList.AppendL(colorUse);
+
+	colorUse.SetLogicalColor(EColorControlBackground);
+	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EActive|commonAttributes);
+	aColorUseList.AppendL(colorUse);
+
+	colorUse.SetLogicalColor(EColorLabelDimmedText);
+	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EDimmed|commonAttributes);
+	aColorUseList.AppendL(colorUse);
+
+	TInt highlightAttributes = TCoeColorUse::EHighlights|TCoeColorUse::ENormal|TCoeColorUse::ENeutral;
+
+	colorUse.SetLogicalColor(EColorLabelTextEmphasis);
+	colorUse.SetUse(TCoeColorUse::EFore|TCoeColorUse::EActive|highlightAttributes);
+	aColorUseList.AppendL(colorUse);
+
+	colorUse.SetLogicalColor(EColorLabelHighlightFullEmphasis);
+	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EActive|highlightAttributes);
+	aColorUseList.AppendL(colorUse);
+
+	colorUse.SetLogicalColor(EColorLabelHighlightPartialEmphasis);
+	colorUse.SetUse(TCoeColorUse::EBack|TCoeColorUse::EDimmed|highlightAttributes);
+	aColorUseList.AppendL(colorUse);
+	}
+
+/**
+ * Handles a change to the control's resources of type aType
+ * which are shared across the environment, e.g. colors or fonts.
+ *
+ * @since ER5U 
+ */
+EXPORT_C void CEikLabel::HandleResourceChange(TInt aType)
+	{
+	CCoeControl::HandleResourceChange(aType);
+	}
+
+EXPORT_C CEikLabel::~CEikLabel()
+	{
+	delete iText;
+	delete iExtension;
+ 	}
+
+EXPORT_C CEikLabel::CEikLabel()	: 
+    iLabFlags( EUseLogicalToVisualConversion ),
+    iGapBetweenLines( LafLabel::DefaultGapBetweenLines() )
+	{
+	__DECLARE_NAME(_S("CEikLabel"));
+	iFont=iCoeEnv->NormalFont();
+	}
+
+EXPORT_C void CEikLabel::SetLabelAlignment(TInt aAlignment)
+	{
+    if (CheckAndCreateExtension())
+        iExtension->iFlags.Assign(CEikLabelExtension::EUseDynamicBidiTextAlignment, (aAlignment == ELayoutAlignBidi));
+
+    switch(aAlignment)
+        {
+        case ELayoutAlignBidi: // alignment handled above in extension above
+            break;
+        default:
+            SetAlignment(AknLayoutUtils::GulAlignFromId(aAlignment));
+            break;
+        }
+	}
+
+EXPORT_C void CEikLabel::SetBrushStyle(CWindowGc::TBrushStyle aBrushStyle)
+    {
+    if (CheckAndCreateExtension())
+        {
+        iExtension->iBrushStyle = aBrushStyle;
+        iExtension->iFlags.Set(CEikLabelExtension::EUseBrushStyle);
+        }
+    }
+
+EXPORT_C void CEikLabel::SetBrushStyleFromContext()
+    {
+    if (CheckAndCreateExtension()) // can't be sure creation above passed
+        {
+        iExtension->iFlags.Clear(CEikLabelExtension::EUseBrushStyle);
+        }
+    }
+
+EXPORT_C void CEikLabel::ConstructFromResourceL(TResourceReader& aReader)
+	{
+	TInt flags=aReader.ReadInt16();
+	SetUnderlining(flags&EikLabelUnderline);
+	SetStrikethrough(flags&EikLabelStrikeThrough);
+	iAlignment.SetHAlignment((TGulHAlignment)aReader.ReadInt16());
+	iAlignment.SetVAlignment((TGulVAlignment)aReader.ReadInt16());
+	TInt standardFont=aReader.ReadInt16();
+	switch (standardFont)
+		{
+	case EEikLabelFontLegend:
+		iFont=iEikonEnv->LegendFont();
+		break;
+	case EEikLabelFontAnnotation:
+		iFont=iEikonEnv->AnnotationFont();
+		break;
+	default:
+		break;
+		}
+	TInt length=aReader.ReadInt16();
+	if (length)
+		SetBufferReserveLengthL(length);
+	SetTextL(aReader.ReadTPtrC());
+	}
+       
+EXPORT_C void CEikLabel::SetTextL(const TDesC& aText)
+	{
+	__ASSERT_DEBUG(&aText,Panic(EEikPanicLabelNullText));
+	
+	if (iLabFlags&KTextBufferReserveLength || 
+		(iText && iText->Des().MaxLength() >= aText.Length()))
+		{
+        *iText=aText; // will panic if not long enough
+		}
+    else
+        {
+        User::LeaveIfError( AknBidiTextUtils::PrepareRunInfoArray( aText ) );
+
+        HBufC* newText=aText.AllocL();
+	    delete(iText); // after the AllocL succeeds
+	    iText=newText;
+
+		if ( !iExtension )
+			{
+			iExtension = CEikLabelExtension::NewL();
+			}
+		iExtension->SetTextLengthL(iText->Length());
+        }
+    if (iExtension)
+        iExtension->iFlags.Clear(CEikLabelExtension::ECropText); // reset ECropText
+    iNumberOfLines=1;
+    TPtrC ptr=(*iText);
+    FOREVER
+        {
+        const TInt offset=ptr.Locate('\n');
+        if (offset<0 || offset==ptr.Length()-1)
+            break;
+        iNumberOfLines++;
+        ptr.Set(ptr.Mid(offset+1));
+        }
+	return ;
+ 	}
+
+EXPORT_C void CEikLabel::CropText()
+	{
+	if ( iExtension ) // if no extension do nothing as SetTextL has not yet been called
+		iExtension->iFlags.Set(CEikLabelExtension::ECropText);
+	}
+	
+TInt CEikLabel::HeightInPixels() const
+    {
+    return(iMargin.iTop+iMargin.iBottom + iGapBetweenLines*(iNumberOfLines-1) + iNumberOfLines*iFont->HeightInPixels());
+    }
+
+TInt CEikLabel::WidthInPixels(TPtrC& aText) const
+    {
+    TInt maxLineWidth=0;
+
+    FOREVER
+        {
+        const TInt offset=aText.Locate('\n');
+        TPtrC left=aText;
+        if (offset>=0)
+            left.Set(aText.Left(offset));
+
+        CFont::TMeasureTextInput input;
+        if ( !(iLabFlags & EUseLogicalToVisualConversion) )
+            {
+            input.iFlags = CFont::TMeasureTextInput::EFVisualOrder;
+            }
+        TInt thisWidth = iFont->MeasureText( left, &input );
+
+        if (thisWidth>maxLineWidth)
+            maxLineWidth=thisWidth;
+        if (offset<0 || offset==aText.Length()-1)
+            break;
+        aText.Set(aText.Mid(offset+1));
+        }
+    return(iMargin.iLeft + iMargin.iRight + maxLineWidth);
+    }
+
+TInt CEikLabel::HeightInPixels(const TDesC& aText) const
+    {
+    // Calculate amount of lines in aText
+    TInt numberOfLines = 1;
+    TPtrC ptr=aText;
+    FOREVER
+        {
+        const TInt offset=ptr.Locate('\n');
+        if (offset<0 || offset==ptr.Length()-1)
+            break;
+        numberOfLines++;
+        ptr.Set(ptr.Mid(offset+1));
+        }
+
+    // Calculate height.
+    return(iMargin.iTop+iMargin.iBottom + iGapBetweenLines*(numberOfLines-1) + numberOfLines*iFont->HeightInPixels());
+    }
+
+EXPORT_C void CEikLabel::Draw( const TRect& /*aRect*/ ) const
+    {
+    CWindowGc& gc = SystemGc();
+    DrawToContext( gc, NULL );
+    gc.SetOpaque( EFalse ); // transparency back on
+    }
+
+
+void CEikLabel::DrawToContext( CBitmapContext& aContext, 
+        const TRgb* aOverrideColor ) const
+    {
+    __ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
+    TInt textTooLong = KErrNone;
+    if (iExtension->iLabelLine->Des().MaxLength() < iText->Length() + TBidiLogicalToVisual::KMinCharAvailable)
+        {
+        TRAP(textTooLong, iExtension->SetTextLengthL(iText->Length()));
+        } // textTooLong condition is handled later in this function, tries to recover as much as possible
+
+    TBool outlineEffectOn = EFalse;
+    const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( iFont ); 
+    if (layoutFont) 
+        {
+        outlineEffectOn = layoutFont->FontSpecification().IsOutlineEffectOn(); 
+        }
+
+    CBitmapContext& gc = aContext;
+    if (IsStrikethrough())
+        {
+        gc.SetStrikethroughStyle(EStrikethroughOn);
+        }
+    else
+        {
+        gc.SetStrikethroughStyle(EStrikethroughOff);
+        }
+
+    if (IsUnderlined())
+        {
+        gc.SetUnderlineStyle(EUnderlineOn);
+        }
+    else
+        {
+        gc.SetUnderlineStyle(EUnderlineOff);
+        }
+    
+    if ( aOverrideColor )
+        {
+        gc.SetPenColor(*aOverrideColor);
+        gc.SetBrushColor(*aOverrideColor);
+        }
+    else if ((iLabFlags&KTextEmphasisMask) != ENoEmphasis)
+        {
+        SetupGcForEmphasis(gc);
+        }
+    else
+        {
+        TRgb penColor;
+        TRgb brushColor;
+        if (IsDimmed()) 
+            {
+            penColor = iEikonEnv->ControlColor(EColorLabelDimmedText,*this); 
+            brushColor = iEikonEnv->ControlColor(EColorControlDimmedBackground,*this); 
+            }
+        else
+            {
+            penColor = iEikonEnv->ControlColor(EColorLabelText,*this); 
+            brushColor = iEikonEnv->ControlColor(EColorControlBackground,*this); 
+            }
+        if(outlineEffectOn)
+            {
+            ConvertColorsForOutlineEffect(penColor, brushColor); 
+            }
+        gc.SetPenColor(penColor); 
+        gc.SetBrushColor(brushColor); 
+        }
+
+    
+    gc.UseFont(iFont);
+
+    if (iExtension->iFlags.IsSet(CEikLabelExtension::EUseBrushStyle))
+        {
+        gc.SetBrushStyle(iExtension->iBrushStyle);
+        }
+    
+    const TRect rect = Rect();
+
+    const TInt deltaHeight=rect.Height()-HeightInPixels();
+    TInt preHeight=iMargin.iTop; // used on first line
+    TInt postHeight=iMargin.iBottom; // used on last line
+    if (deltaHeight>0)
+        {
+        switch(iAlignment.VAlignment())
+            {
+            case EVTop:
+                postHeight+=deltaHeight;
+                break;
+            case EVBottom:
+                preHeight+=deltaHeight;
+                break;
+            case EVCenter:
+                TInt postInc=deltaHeight/2; // give odd pixel to pre-Height
+                preHeight+=deltaHeight-postInc;
+                postHeight+=postInc;
+            }
+        }
+    TInt lineNo=0;
+    
+    TPtrC ptr=(*iText);
+    TRect box=rect;
+    TBool clippedAtBottom=EFalse;
+    TInt textPaneTopToBaseline(0);
+    TInt textPaneHeight(0);
+    
+    if ( layoutFont )
+        {
+        textPaneTopToBaseline = layoutFont->TextPaneTopToBaseline();
+        textPaneHeight = layoutFont->TextPaneHeight();
+        }
+    else
+        {
+        textPaneTopToBaseline = iFont->AscentInPixels();
+        textPaneHeight = iFont->HeightInPixels();
+        }
+    
+    // iGapBetweenLines is defined as baseline separation - CFont::HeightInPixels
+    // Since we are using the better metrics above, we have to actually use something which is 
+    // derived from iGapBetweenLines, but is e.g. reduced if textpaneheight > heightInPixels
+    TInt gapBetweenTextPanes( iGapBetweenLines - (textPaneHeight - iFont->HeightInPixels()) );
+
+    FOREVER
+        {
+        TInt ascent=textPaneTopToBaseline+preHeight;
+        TInt lineHeight=textPaneHeight+preHeight;
+        if (++lineNo==iNumberOfLines)
+            {
+            lineHeight+=postHeight;
+            }
+        
+        TInt off=ptr.Locate('\n');
+        TPtrC left=ptr;
+        if (off>=0)
+            {
+            left.Set(ptr.Left(off));
+            }
+        
+        box.iBr.iY=box.iTl.iY+lineHeight;
+        if (box.iBr.iY>rect.iBr.iY)
+            {
+            box.iBr.iY=rect.iBr.iY;
+            clippedAtBottom=ETrue;
+            }
+        
+        CGraphicsContext::TTextAlign align=iAlignment.TextAlign();
+        TInt margin = iMargin.iLeft;
+        
+        TBidiText::TDirectionality labelDirectionality = TBidiText::TextDirectionality(*iText);
+        if (iExtension->iFlags.IsSet(CEikLabelExtension::EUseDynamicBidiTextAlignment))
+            {
+            switch(labelDirectionality)
+                {
+                case TBidiText::ELeftToRight:
+                    align = CGraphicsContext::ELeft;
+                    break;
+                case TBidiText::ERightToLeft:
+                    align = CGraphicsContext::ERight;
+                    break;
+                default:
+                    break; // do nothing
+                }
+            }
+        
+        if (align==CGraphicsContext::ERight)
+            {
+            margin = iMargin.iRight;
+            }
+        else if (align==CGraphicsContext::ECenter)
+            {
+            margin -= iMargin.iRight;
+            }
+        
+        TRect adjustedBox( box ) ;  // create a new box to accommodate underline if present (without affecting layout)
+        if ( IsUnderlined() )
+            {
+            TAknTextDecorationMetrics decoration(iFont);
+            TInt underlineWidth = decoration.UnderlineHeight();
+            TInt underlineSpace = decoration.BaselineToUnderlineOffset();
+            
+            if (  ( textPaneTopToBaseline + underlineSpace ) > textPaneHeight )
+                {
+                adjustedBox.iBr.iY += (  textPaneTopToBaseline + underlineSpace - textPaneHeight ) ;
+                }
+            }
+        
+        TPtr text = iExtension->iLabelLine->Des();
+        TInt textMaxLength = text.MaxLength();
+        TBool dontDoComplicatedDraw = EFalse;
+        
+        TInt usableLength = 0;
+        if (textTooLong == KErrNone || textMaxLength >= left.Length() + TBidiLogicalToVisual::KMinCharAvailable)
+            {
+            usableLength = left.Length(); // no problem with memory
+            }
+        else
+            { // problem with lack of memory so find a usable length.
+            if (labelDirectionality == TBidiText::ELeftToRight || !(iLabFlags & EUseLogicalToVisualConversion))
+                { // most likely western text so just display logically (no truncation)
+                dontDoComplicatedDraw = ETrue;
+                }
+            else
+                { // most likely NOT western text so display as much visually as possible
+                if (textMaxLength > TBidiLogicalToVisual::KMinCharAvailable)
+                    {
+                    usableLength = textMaxLength - TBidiLogicalToVisual::KMinCharAvailable;
+                    }
+                else // there is no buffer so give up and draw logically
+                    {
+                    dontDoComplicatedDraw = ETrue;
+                    }
+                }
+            }
+        
+        if (dontDoComplicatedDraw)
+            {
+            gc.DrawText( left, adjustedBox, ascent, align, margin );
+            if ( iExtension->iPictographInterface )
+                {
+                iExtension->iPictographInterface->Interface()->DrawPictographsInText(
+                    gc, *iFont, left, adjustedBox, ascent, align, margin );
+                }
+            }
+        else
+            { // we have some buffer space to try and draw text correctly
+            TPtrC usableText=left.Left(usableLength);
+            TInt adjustedBoxWidth = adjustedBox.Size().iWidth;
+            
+            if (iLabFlags & EUseLogicalToVisualConversion)
+                {
+                if (iExtension->iFlags.IsSet(CEikLabelExtension::ECropText))
+                    {
+                    AknBidiTextUtils::ConvertToVisualAndClip(usableText, text, *iFont, adjustedBoxWidth, adjustedBoxWidth);
+                    }
+                else
+                    {
+                    const TUint KEmptyChar = TUint(0xFFFF);
+                    AknBidiTextUtils::ConvertToVisualAndClip(usableText, text, *iFont, adjustedBoxWidth, adjustedBoxWidth, AknBidiTextUtils::EImplicit, KEmptyChar );
+                    }
+                }
+            else
+                {
+                text = usableText; // copy
+                }
+            gc.DrawText( text, adjustedBox, ascent, align, margin );
+            if ( iExtension->iPictographInterface )
+                {
+                iExtension->iPictographInterface->Interface()->DrawPictographsInText(
+                    gc, *iFont, text, adjustedBox, ascent, align, margin );
+                }
+            }
+        
+        
+        if (off<0 || off==ptr.Length()-1 || clippedAtBottom)
+            break;
+        
+        ptr.Set(ptr.Mid(off+1));
+        box.iTl.iY=box.iBr.iY;
+        
+        preHeight=gapBetweenTextPanes;
+        }
+    
+    gc.DiscardFont();
+    }
+
+EXPORT_C void CEikLabel::SetBufferReserveLengthL(TInt aLength)
+	{
+	if (iText)
+		iText=iText->ReAllocL(aLength);
+	else
+		iText=HBufC::NewL(aLength);
+	iLabFlags|=KTextBufferReserveLength;
+	iReserveLength=aLength;
+	if ( !iExtension )
+		{
+		iExtension = CEikLabelExtension::NewL();
+		}
+	iExtension->SetTextLengthL(iText->Length());
+	}
+
+EXPORT_C void CEikLabel::SetFont(const CFont* aFont) 
+	{
+	iFont=aFont;
+	}
+
+EXPORT_C TSize CEikLabel::CalcMinimumSize(TPtrC& aText) const
+    {
+    // HeightInPixels does not modify aText.
+    const TInt height = HeightInPixels(aText);
+
+    // Note that WidthInPixels modifies aText and so
+    // it must be called after HeightInPixels.
+    const TInt width = WidthInPixels(aText);
+    return TSize( width, height );
+    }
+
+EXPORT_C void CEikLabel::SetEmphasis(TTextEmphasis aEmphasis)
+	{
+    iLabFlags&=(~KTextEmphasisMask);
+    iLabFlags|=aEmphasis;
+	}
+
+EXPORT_C TSize CEikLabel::MinimumSize()
+	{
+	__ASSERT_ALWAYS(iText,Panic(EEikPanicLabelNullText));
+	TPtrC ptr=(*iText);
+	iSize=TSize(WidthInPixels(ptr),HeightInPixels());
+	return(iSize);
+	}
+
+EXPORT_C void CEikLabel::SetPixelGapBetweenLines(TInt aGap)
+	{
+	iGapBetweenLines=aGap;
+	}
+
+EXPORT_C TInt CEikLabel::PixelGapBetweenLines() const
+	{
+	return iGapBetweenLines;
+	}
+
+EXPORT_C void CEikLabel::SetUnderlining(TBool aUnderLining)
+	{
+	if (aUnderLining) {iLabFlags|=EUnderlining;}
+        else iLabFlags&=(~EUnderlining);
+	}
+
+EXPORT_C void CEikLabel::SetStrikethrough(TBool aStrikethrough)
+	{
+	if (aStrikethrough) {iLabFlags|=EStrikethrough;}
+        else iLabFlags&=(~EStrikethrough);
+	}
+
+EXPORT_C TInt CEikLabel::BufferReserveLength() const
+	{
+	return (iLabFlags&KTextBufferReserveLength? iReserveLength : 0);
+	}
+
+EXPORT_C void CEikLabel::UseLogicalToVisualConversion( TBool aUseConversion )
+    {
+    if ( aUseConversion )
+        {
+        iLabFlags |= EUseLogicalToVisualConversion;
+        }
+    else
+        {
+        iLabFlags &= (~EUseLogicalToVisualConversion);
+        }
+    }
+
+EXPORT_C TBool CEikLabel::LogicalToVisualConversionUsed() const
+    {
+    return iLabFlags & EUseLogicalToVisualConversion;
+    }
+
+EXPORT_C void CEikLabel::EnablePictographsL( CAknPictographInterface& aInterface )
+    {
+    if ( !iExtension )
+        {
+        iExtension = CEikLabelExtension::NewL();
+        }
+
+    iExtension->iPictographInterface = &aInterface;
+    }
+
+EXPORT_C void CEikLabel::DisablePictographs()
+    {
+    if ( iExtension )
+        {
+        iExtension->iPictographInterface = NULL;
+        }
+    }
+
+void CEikLabel::SetupGcForEmphasis(CGraphicsContext& aGc) const
+	{
+    TRgb penColor;
+    TRgb brushColor; 
+
+    penColor = (iEikonEnv->ControlColor(EColorLabelTextEmphasis,*this)); 
+    if ((iLabFlags&KTextEmphasisMask) == EFullEmphasis) 
+        {
+        brushColor = (iEikonEnv->ControlColor(EColorLabelHighlightFullEmphasis,*this)); 
+        }
+    else
+        {
+        brushColor = (iEikonEnv->ControlColor(EColorLabelHighlightPartialEmphasis,*this)); 
+        }
+    
+    aGc.SetPenColor(penColor); 
+    aGc.SetBrushColor(brushColor);
+    aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); 
+    }
+
+TBool CEikLabel::CheckAndCreateExtension()
+    {
+	if (!iExtension)
+		{
+		TRAP_IGNORE(iExtension = CEikLabelExtension::NewL());
+		}
+    return (iExtension != NULL);
+    }
+
+/**
+ * Writes the internal state of the control and its components to aStream.
+ * Does nothing in release mode.
+ * Designed to be overidden and base called by subclasses.
+ *
+ * @internal
+ * @since App-Framework_6.1
+ */
+#ifndef _DEBUG
+EXPORT_C void CEikLabel::WriteInternalStateL(RWriteStream&) const
+	{}
+#else
+EXPORT_C void CEikLabel::WriteInternalStateL(RWriteStream& aWriteStream) const
+	{
+	_LIT(KLitEikLblCtlStart, "<CEiklabel>");
+	_LIT(KLitEikLblCtlEnd, "<\\CEikLabel>");
+
+	_LIT(KLitEikLblTxt,"<iText>");
+	_LIT(KLitEikLblTxtEnd,"<\\iText>");
+	_LIT(KLitEikLblFnt,"<iFont>");
+	_LIT(KLitEikLblFntEnd,"<\\iFont>");
+	_LIT(KLitEikLblNoLns,"<iNumberOfLines>");
+	_LIT(KLitEikLblNoLnsEnd,"<\\iNumberOfLines>");
+	_LIT(KLitEikLblFlgs,"<iLabFlags>");
+	_LIT(KLitEikLblFlgsEnd,"<\\iLabFlags>");
+	_LIT(KLitEikLblGpBtwnLns,"<iGapBetweenLines>");
+	_LIT(KLitEikLblGpBtwnLnsEnd,"<\\iGapBetweenLines>");
+	_LIT(KLitEikLblResLen,"<iReserveLength>");
+	_LIT(KLitEikLblResLenEnd,"<\\iReserveLength>");
+
+	aWriteStream << KLitEikLblCtlStart;
+	aWriteStream << KLitEikLblTxt;
+	if(iText)
+		aWriteStream.WriteL(*iText);
+	aWriteStream << KLitEikLblTxtEnd;
+	aWriteStream << KLitEikLblFnt;
+	const TFontSpec& spec=iFont->FontSpecInTwips();
+	aWriteStream << spec;
+	aWriteStream << KLitEikLblFntEnd;
+	aWriteStream << KLitEikLblNoLns;
+	aWriteStream.WriteInt32L(iNumberOfLines);
+	aWriteStream << KLitEikLblNoLnsEnd;
+	aWriteStream << KLitEikLblFlgs;
+	aWriteStream.WriteInt32L(iLabFlags);
+	aWriteStream << KLitEikLblFlgsEnd;
+	aWriteStream << KLitEikLblGpBtwnLns;
+	aWriteStream.WriteInt32L(iGapBetweenLines);
+	aWriteStream << KLitEikLblGpBtwnLnsEnd;
+	aWriteStream << KLitEikLblResLen;
+	aWriteStream.WriteInt32L(iReserveLength);
+	aWriteStream << KLitEikLblResLenEnd;
+	CEikAlignedControl::WriteInternalStateL(aWriteStream);
+	aWriteStream << KLitEikLblCtlEnd;
+	}
+#endif
+
+EXPORT_C void CEikLabel::HandlePointerEventL(const TPointerEvent& aPointerEvent) 
+    { 
+    CEikAlignedControl::HandlePointerEventL(aPointerEvent); 
+    }
+
+EXPORT_C void* CEikLabel::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+EXPORT_C void CEikLabel::Reserved_2()
+	{}
+
+// @todo use some utility 
+#define max(a, b) a > b ? a : b; 
+#define min(a, b) a < b ? a : b; 
+#define abs(a) a < 0 ? -a : a; 
+
+TInt CalculateLuminance(const TRgb& aColor) 
+    { 
+    TInt R = aColor.Red(); 
+    TInt G = aColor.Green(); 
+    TInt B = aColor.Blue(); 
+    // Should be scaled to 0-255? 
+    TInt Y = (((66 * R) + (129 * G) + (25 * B) + 128) >> 8) + 16; 
+    return Y; 
+    } 
+    
+void CEikLabel::ConvertColorsForOutlineEffect(TRgb& aPenColor, TRgb& aBrushColor) const 
+    { 
+    // the caller intends the brush color to be the background or outline, 
+    // and the pen color to be the foreground color 
+    TRgb innerColor = aPenColor; 
+    TRgb outerColor = aBrushColor; 
+
+    // @todo maybe there is already some conversion utility in multimedia image library? 
+    TInt innerLum = CalculateLuminance(innerColor); 
+    TInt outerLum = CalculateLuminance(outerColor); 
+    
+    // if the defined colours are the same, then change the outline color so that 
+    // it's either black or white, contrasting according to the font label text color's brightness 
+    TInt difference = outerLum - innerLum; 
+    difference = abs(difference); 
+    TInt half = (0xff / 2); // @todo figure out hlsMax somehow 
+    TInt threshold = (0xff / 3); // @todo figure out hlsMax somehow, and decide on the threshold! 
+    if(difference < threshold) 
+        { 
+        // if inner luminance is low, the outer luminance should be high, i.e. white 
+        outerColor = (innerLum < half) ? KRgbWhite : KRgbBlack; 
+        } 
+    
+    // for outline effect, we must set the color we want as the outline to the pen color, and 
+    // the color we want as the fill to the brush color, so swap them round 
+    aPenColor = outerColor; 
+    aBrushColor = innerColor; 
+    } 
+
+