--- /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;
+ }
+
+