--- a/uifw/AvKon/src/AknSmileyModel.cpp Fri Feb 19 23:04:46 2010 +0200
+++ b/uifw/AvKon/src/AknSmileyModel.cpp Fri Mar 12 15:43:43 2010 +0200
@@ -15,7 +15,6 @@
*
*/
-
#include <barsread.h>
#include <AknUtils.h>
#include <aknlayoutscalable_avkon.cdl.h>
@@ -23,6 +22,9 @@
#include <centralrepository.h>
#include <AvkonInternalCRKeys.h>
+#include <AknBidiTextUtils.h>
+#include <AknPanic.h>
+
#include <smiley.rsg>
#include <smiley.mbg>
@@ -40,21 +42,17 @@
}
TSmileyIconInfo::TSmileyIconInfo(const TSmileyIconInfo& aInfo) :
-iName(aInfo.iName),
-iId(aInfo.iId),
iSkinItemID(aInfo.iSkinItemID),
-iDefaultThumbnailID(aInfo.iDefaultThumbnailID),
-iDefaultAnimationID(aInfo.iDefaultAnimationID)
+iDefaultStillImageID(aInfo.iDefaultStillImageID),
+iDefaultAnimationImageID(aInfo.iDefaultAnimationImageID)
{
}
void TSmileyIconInfo::Reset()
{
- iName.Zero();
- iId = 0;
iSkinItemID.Set(0, 0);
- iDefaultThumbnailID = 0;
- iDefaultAnimationID = 0;
+ iDefaultStillImageID = 0;
+ iDefaultAnimationImageID = 0;
}
@@ -63,76 +61,83 @@
// CSmileyIcon
///////////////////////////////////////////////////////////////////////////////////////////////
-CSmileyIcon* CSmileyIcon::NewL(const TSmileyIconInfo& aInfo, MSmileyIconObserver* aObserver)
+CSmileyIcon* CSmileyIcon::NewL(const TSmileyIconInfo& aInfo, MAknSmileyObserver* aObserver)
{
- CSmileyIcon* self = new (ELeave) CSmileyIcon(aInfo, aObserver);
+ CSmileyIcon* self = new (ELeave) CSmileyIcon(aObserver);
CleanupStack::PushL(self);
- self->ConstructL();
+ self->ConstructL(aInfo);
CleanupStack::Pop(); // self;
return self;
}
-void CSmileyIcon::ConstructL()
+void CSmileyIcon::ConstructL(const TSmileyIconInfo& aInfo)
{
- iThumbnailImage = CSmileyImage::NewL(iInfo.iSkinItemID, iInfo.iDefaultThumbnailID, FALSE, this);
+ iIndex = aInfo.iIndex;
+
+ iStillImage = CSmileyImage::NewL(aInfo.iSkinItemID, aInfo.iDefaultStillImageID, EFalse, this);
- if(iInfo.iSkinItemID.iMinor==0 && iInfo.iDefaultAnimationID>0)
+ if(aInfo.iSkinItemID.iMinor==0 && aInfo.iDefaultAnimationImageID>0)
{
- iAnimationImage = CSmileyImage::NewL(iInfo.iSkinItemID, iInfo.iDefaultAnimationID, TRUE, this);
+ TAknsItemID nullID;
+ nullID.Set(0, 0);
+ iAnimationImage = CSmileyImage::NewL(nullID, aInfo.iDefaultAnimationImageID, ETrue, this);
}
}
-CSmileyIcon::CSmileyIcon(const TSmileyIconInfo& aInfo, MSmileyIconObserver* aObserver) :
-iInfo(aInfo), iSmileyIconObserver(aObserver)
+CSmileyIcon::CSmileyIcon(MAknSmileyObserver* aObserver) : iSmileyIconObserver(aObserver)
{
}
CSmileyIcon::~CSmileyIcon()
{
- delete iThumbnailImage;
+ delete iStillImage;
delete iAnimationImage;
- }
-
-TBool CSmileyIcon::ReadyToDraw() const
- {
- TBool thumbnailCanDraw = iThumbnailImage->ReadyToDraw();
- TBool animationCanDraw = iAnimationImage ? iAnimationImage->ReadyToDraw() : FALSE;
- return (thumbnailCanDraw || animationCanDraw);
+ iTextArray.Close();
}
const CFbsBitmap* CSmileyIcon::Image() const
{
- if(ShouldShowAnimation())
+ if(AnimationImageIsReadyToDraw())
{
return iAnimationImage->Image();
}
else
{
- return iThumbnailImage->Image();
+ return iStillImage->Image();
}
}
const CFbsBitmap* CSmileyIcon::Mask() const
{
- if(ShouldShowAnimation())
+ if(AnimationImageIsReadyToDraw())
{
return iAnimationImage->Mask();
}
else
{
- return iThumbnailImage->Mask();
+ return iStillImage->Mask();
}
}
-void CSmileyIcon::LoadThumbnailL()
+TBool CSmileyIcon::ReadyToDraw() const
{
- iThumbnailImage->LoadL();
+ return StillImageIsReadyToDraw() || AnimationImageIsReadyToDraw();
}
-TBool CSmileyIcon::ThumbnailReady() const
+void CSmileyIcon::SetSize(const TSize& aSize)
{
- return iThumbnailImage->ReadyToDraw();
+ iStillImage->SetSize(aSize);
+
+ if(iAnimationImage)
+ {
+ iAnimationImage->SetSize(aSize);
+ }
+ }
+
+const TSize& CSmileyIcon::Size() const
+ {
+ return iStillImage->Size();
}
void CSmileyIcon::PlayAnimationL(TInt aRepeat, TInt aDelay)
@@ -151,36 +156,72 @@
}
}
-void CSmileyIcon::SetSize(const TSize& aSize)
+void CSmileyIcon::BitmapChanged(CSmileyImage* aSmileyImage, CFbsBitmap* /*aBitmap*/)
{
- iThumbnailImage->SetSize(aSize);
-
- if(iAnimationImage)
+ if(aSmileyImage == iStillImage)
{
- iAnimationImage->SetSize(aSize);
+ if(iSmileyIconObserver) iSmileyIconObserver->SmileyStillImageLoaded(this);
+ }
+ else
+ {
+ if(iSmileyIconObserver) iSmileyIconObserver->SmileyAnimationChanged(this);
}
}
-const TSize& CSmileyIcon::Size() const
+TInt CSmileyIcon::Index() const
+ {
+ return iIndex;
+ }
+
+void CSmileyIcon::LoadStillImageL(TInt aDelay)
{
- return iThumbnailImage->Size();
+ iStillImage->LoadL(0, aDelay);
+ }
+
+TBool CSmileyIcon::StillImageIsReadyToDraw() const
+ {
+ return iStillImage->ReadyToDraw();
+ }
+
+TBool CSmileyIcon::AnimationImageIsReadyToDraw() const
+ {
+ return (iAnimationImage && iAnimationImage->ReadyToDraw());
}
-void CSmileyIcon::BitmapChanged(CSmileyImage* aSmileyImage, CFbsBitmap* /*aBitmap*/)
+void CSmileyIcon::AddText(const TDesC& aText) // for spliting strings = ":P :p :-P :-p";
{
- if(aSmileyImage == iThumbnailImage)
+ TPtrC ptr(aText);
+
+ while(ptr.Length())
{
- if(iSmileyIconObserver) iSmileyIconObserver->ThumbnailLoaded(this);
+ TInt left = ptr.Find(_L(" "));
+ TInt right = ptr.Length() - left - 1;
+ if(left == KErrNotFound)
+ {
+ left = ptr.Length();
+ right = 0;
+ }
+
+ iTextArray.Append(ptr.Left(left));
+ ptr.Set(ptr.Right(right));
+ }
+ }
+
+const TDesC& CSmileyIcon::Text(TInt aVariate) const
+ {
+ if(aVariate>=0 && aVariate<TextVariate())
+ {
+ return iTextArray[aVariate];
}
else
{
- if(iSmileyIconObserver) iSmileyIconObserver->AnimationChanged(this);
+ return KNullDesC;
}
}
-TBool CSmileyIcon::ShouldShowAnimation() const
+TInt CSmileyIcon::TextVariate() const
{
- return (iAnimationImage && iAnimationImage->ReadyToDraw());
+ return iTextArray.Count();
}
@@ -196,15 +237,16 @@
CSmileyTnumbnailAsynLoader::~CSmileyTnumbnailAsynLoader()
{
- iTaskArray.Close();
+ iLoadingTaskArray.Close();
}
void CSmileyTnumbnailAsynLoader::AddTaskL(CSmileyIcon* aSmileyIcon)
{
if(aSmileyIcon)
{
- iTaskArray.Append(aSmileyIcon);
- if(!iIsLoading)
+ TBool isIdel = (TaskCount() == 0);
+ iLoadingTaskArray.Append(aSmileyIcon);
+ if(isIdel)
{
DoNextTaskL();
}
@@ -213,45 +255,203 @@
void CSmileyTnumbnailAsynLoader::DiscardAll()
{
- iTaskArray.Reset();
+ iLoadingTaskArray.Reset();
}
TInt CSmileyTnumbnailAsynLoader::TaskCount() const
{
- return iTaskArray.Count();
+ return iLoadingTaskArray.Count();
}
void CSmileyTnumbnailAsynLoader::DoNextTaskL()
{
- TInt count = TaskCount();
- if(count > 0)
+ if(TaskCount() > 0)
{
- CSmileyIcon* icon = iTaskArray[0];
- iTaskArray.Remove(0);
+ CSmileyIcon* icon = iLoadingTaskArray[0];
+ iLoadingTaskArray.Remove(0);
- if(icon->ThumbnailReady())
+ if(icon->StillImageIsReadyToDraw())
{
DoNextTaskL();
}
else
{
- icon->LoadThumbnailL();
- iIsLoading = TRUE;
+ icon->LoadStillImageL(1); // 1 is for asynchronous
}
}
+ }
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// CSmileyTextTreeNode
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+NONSHARABLE_CLASS(CSmileyTextTreeNode) : public CBase
+ {
+public:
+ CSmileyTextTreeNode(TChar aChar);
+ ~CSmileyTextTreeNode();
+
+ TChar Char() const;
+ TChar LastChildChar() const;
+ TChar FirstChildChar() const;
+
+ CSmileyTextTreeNode* AddTreeL(const TDesC& aText, TChar aCode);
+ TInt ChildCount() const;
+ CSmileyTextTreeNode* Child(TInt aIndex) const;
+ CSmileyTextTreeNode* Child(TChar aChar) const;
+
+private:
+ CSmileyTextTreeNode* AddChildL(TChar aChar);
+
+private:
+ TChar iChar;
+
+ typedef CArrayPtrFlat<CSmileyTextTreeNode> CSmileyTextTreeNodeArrayPtrFlat;
+ CSmileyTextTreeNodeArrayPtrFlat* iChildArray;
+
+ };
+
+
+CSmileyTextTreeNode::CSmileyTextTreeNode(TChar aChar) : iChar(aChar)
+ {
+ }
+
+CSmileyTextTreeNode::~CSmileyTextTreeNode()
+ {
+ if(iChildArray)
+ {
+ iChildArray->ResetAndDestroy();
+ delete iChildArray;
+ }
+ }
+
+TChar CSmileyTextTreeNode::Char() const
+ {
+ return iChar;
+ }
+
+TChar CSmileyTextTreeNode::LastChildChar() const
+ {
+ if(iChildArray)
+ {
+ TInt index = iChildArray->Count() - 1;
+ return iChildArray->At(index)->Char();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+TChar CSmileyTextTreeNode::FirstChildChar() const
+ {
+ if(iChildArray)
+ {
+ return iChildArray->At(0)->Char();
+ }
else
{
- iIsLoading = FALSE;
+ return 0;
+ }
+ }
+
+CSmileyTextTreeNode* CSmileyTextTreeNode::AddTreeL(const TDesC& aText, TChar aCode)
+ {
+ TInt length = aText.Length();
+ if(length > 0)
+ {
+ CSmileyTextTreeNode* node = AddChildL(aText[0]);
+ return node->AddTreeL(aText.Right(length-1), aCode);
+ }
+ else
+ {
+ return AddChildL(aCode);
+ }
+ }
+
+TInt CSmileyTextTreeNode::ChildCount() const
+ {
+ if(iChildArray)
+ {
+ return iChildArray->Count();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+CSmileyTextTreeNode* CSmileyTextTreeNode::Child(TInt aIndex) const
+ {
+ if(aIndex>=0 && aIndex<ChildCount())
+ {
+ return iChildArray->At(aIndex);
+ }
+ else
+ {
+ return NULL;
}
}
+CSmileyTextTreeNode* CSmileyTextTreeNode::Child(TChar aChar) const
+ {
+ if(iChildArray)
+ {
+ for(TInt i=iChildArray->Count()-1; i>=0; i--)
+ {
+ CSmileyTextTreeNode* node = iChildArray->At(i);
+ if(node->Char() == aChar)
+ {
+ return node;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+CSmileyTextTreeNode* CSmileyTextTreeNode::AddChildL(TChar aChar)
+ {
+ // new
+ if(!iChildArray)
+ {
+ iChildArray = new (ELeave) CSmileyTextTreeNodeArrayPtrFlat(1);
+ }
+
+ // sequential search
+ TInt pos = 0;
+ for(; pos<iChildArray->Count(); pos++)
+ {
+ CSmileyTextTreeNode* node = iChildArray->At(pos);
+ TChar character = node->Char();
+ if(aChar == character)
+ {
+ return node;
+ }
+ else if(aChar < character)
+ {
+ break;
+ }
+ }
+
+ CSmileyTextTreeNode* node = new (ELeave) CSmileyTextTreeNode(aChar);
+ iChildArray->InsertL(pos, node);
+ return node;
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// CSmileyModel
///////////////////////////////////////////////////////////////////////////////////////////////
-CSmileyModel::CSmileyModel(MSmileyIconObserver* aObserver) : iSmileyIconObserver(aObserver)
+const TUint16 KBaseCodeOn = 0xf880;
+const TUint16 KBaseCodeOff = 0x7FFF;
+_LIT(KPlaceHolder, "\xf880i");
+
+CSmileyModel::CSmileyModel(MAknSmileyObserver* aObserver) : iSmileyIconObserver(aObserver)
{
}
@@ -265,18 +465,6 @@
void CSmileyModel::LoadResourceL()
{
if(Count() > 0) return;
-
- // append sct & smiley switch icon
- {
- TSmileyIconInfo info;
- info.iSkinItemID = KAknsIIDQgnIndiSwitchSmiley2;
- info.iDefaultThumbnailID = EMbmSmileyQgn_indi_switch_smiley2;
- iSmileyIconArray.Append(CSmileyIcon::NewL(info, this));
-
- info.iSkinItemID = KAknsIIDQgnIndiSwitchSct2;
- info.iDefaultThumbnailID = EMbmSmileyQgn_indi_switch_sct2;
- iSmileyIconArray.Append(CSmileyIcon::NewL(info, this));
- }
// append image resourece
TResourceReader reader;
@@ -285,48 +473,74 @@
TInt offset = CCoeEnv::Static()->AddResourceFileL(smileyRscName);
CCoeEnv::Static()->CreateResourceReaderLC(reader, R_SMILEY_ICONS_INFO);
+ iBaseCode = KBaseCodeOn;
+ TInt index = 0;
+
+ iTextSearchTree = new (ELeave) CSmileyTextTreeNode(0);
+
TInt count(reader.ReadInt16());
- for(TInt id(1); id<=count; id++)
+ for(TInt i(0); i<count; i++)
{
TSmileyIconInfo info;
-
- info.iId = id; // id
-
+
TBool isAnimation = (reader.ReadInt16() == 1);
- TInt16 code = reader.ReadInt16();
+ TInt code = reader.ReadInt16();
TInt bmpId1 = reader.ReadInt32();
TInt maskId1 = reader.ReadInt32();
TInt bmpId2 = reader.ReadInt32();
TInt maskId2 = reader.ReadInt32();
+ if(iBaseCode > code) iBaseCode = code;
+
+ info.iIndex = index++;
+
if(bmpId2 > 0)
{
- info.iDefaultThumbnailID = bmpId2;
- info.iDefaultAnimationID = bmpId1;
+ info.iDefaultStillImageID = bmpId2;
+ info.iDefaultAnimationImageID = bmpId1;
}
else
{
- info.iDefaultThumbnailID = bmpId1;
- info.iDefaultAnimationID = 0;
+ info.iDefaultStillImageID = bmpId1;
+ info.iDefaultAnimationImageID = 0;
}
TBuf<64> smileyName = reader.ReadTPtrC(); // strings
- TInt pos = smileyName.Find(_L(" "));
- if(pos > 0) smileyName.SetLength(pos);
- info.iName = smileyName;
-
- iSmileyIconArray.Append(CSmileyIcon::NewL(info, this));
+
+ CSmileyIcon* icon = CSmileyIcon::NewL(info, this);
+ icon->AddText(smileyName);
+ iSmileyIconArray.Append(icon);
+
+ // build text search tree
+ for(TInt j=0; j<icon->TextVariate(); j++)
+ {
+ iTextSearchTree->AddTreeL(icon->Text(j), SmileyCode(i,j));
+ }
}
CCoeEnv::Static()->DeleteResourceFile(offset);
CleanupStack::PopAndDestroy(); // reader
+
+ // sct & smiley switch icon
+ TSmileyIconInfo info;
+ info.iIndex = index++;
+ info.iSkinItemID = KAknsIIDQgnIndiSwitchSmiley2;
+ info.iDefaultStillImageID = EMbmSmileyQgn_indi_switch_smiley2;
+ iSmileyIconArray.Append(CSmileyIcon::NewL(info,this));
+
+ info.iIndex = index++;
+ info.iSkinItemID = KAknsIIDQgnIndiSwitchSct2;
+ info.iDefaultStillImageID = EMbmSmileyQgn_indi_switch_sct2;
+ iSmileyIconArray.Append(CSmileyIcon::NewL(info,this));
}
void CSmileyModel::ReleaseResource()
{
+ if(Count() == 0) return;
+
// reset array
- for(TInt i(0); i<Count(); i++)
+ for(TInt i(0); i<ArrayCount(); i++)
{
delete iSmileyIconArray[i];
iSmileyIconArray[i] = NULL;
@@ -334,25 +548,410 @@
iSmileyIconArray.Reset();
// reset task loader
- iSmileyThumbnailLoader.DiscardAll();
+ iSmileyLoader.DiscardAll();
+
+ delete iTextSearchTree;
+ iTextSearchTree = NULL;
+
+ iBaseCode = 0x7FFF; // max value
+ }
+
+TInt CSmileyModel::ConvertCodesToTextL(TDes& aText)
+ {
+ TInt converted = 0;
+ iConvertBuffer.Zero();
+
+ // deal all
+ TInt pos = 0;
+ while(pos < aText.Length())
+ {
+ TChar character = aText[pos++];
+ if(IsSmiley(character))
+ {
+ converted++;
+ pos++; // jump the 'i'
+ iConvertBuffer.Append(Text(character));
+ }
+ else
+ {
+ iConvertBuffer.Append(character);
+ }
+ }
+
+ // replace
+ if(converted)
+ {
+ aText.Copy(iConvertBuffer);
+ }
+
+ return converted;
}
-void CSmileyModel::LoadThumbnailAsyn(TInt aIndex)
+TInt CSmileyModel::ConvertTextToCodesL(TDes& aText)
{
- TRAP_IGNORE(iSmileyThumbnailLoader.AddTaskL((*this)[aIndex]));
+ TInt converted = 0;
+ iConvertBuffer.Zero();
+
+ CSmileyTextTreeNode* node = iTextSearchTree;
+ TChar lastChar = node->LastChildChar();
+ TChar firstChar = node->FirstChildChar();
+ TInt matchedLength = 0;
+
+ // deal all
+ TInt pos = 0;
+ while(pos < aText.Length())
+ {
+ TChar character = aText[pos++];
+ iConvertBuffer.Append(character);
+
+ if(!(character<firstChar || character>lastChar)) // is possible
+ {
+ CSmileyTextTreeNode* find = node->Child(character);
+ if(find)
+ {
+ matchedLength++; // character is mathed
+
+ CSmileyTextTreeNode* child = find->Child(0);
+ if(child && child->ChildCount()==0) // whole combination is matched
+ {
+ converted++;
+
+ TChar code = child->Char();
+
+ // replace with code
+ iConvertBuffer.SetLength(iConvertBuffer.Length() - matchedLength);
+ iConvertBuffer.Append(code);
+ iConvertBuffer.Append('i');
+
+ // load thumnail
+ LoadStillImageL(code);
+
+ // restart
+ matchedLength = 0;
+ node = iTextSearchTree;
+ }
+ else
+ {
+ node = find;
+ }
+
+ lastChar = node->LastChildChar();
+ firstChar = node->FirstChildChar();
+ continue;
+ }
+ }
+
+ // character is not matched
+ if(matchedLength)
+ {
+ matchedLength = 0;
+ node = iTextSearchTree;
+ lastChar = node->LastChildChar();
+ firstChar = node->FirstChildChar();
+ }
+ }
+
+ // replace
+ if(converted)
+ {
+ aText.Copy(iConvertBuffer);
+ }
+
+ return converted;
+ }
+
+TBool CSmileyModel::IsSmiley(TChar aCode) const
+ {
+ return (aCode >= iBaseCode);
+ }
+
+const TDesC& CSmileyModel::Text(TChar aCode) const
+ {
+ TInt index, variate;
+ if(DecodeSmileyCode(aCode, index, variate))
+ {
+ return Text(index, variate);
+ }
+ else
+ {
+ return KNullDesC;
+ }
}
void CSmileyModel::SetSize(const TSize& aSize)
{
- for(TInt i(0); i<Count(); i++)
+ if(ArrayCount() && iSmileyIconArray[0]->Size()!=aSize)
+ {
+ for(TInt i(0); i<ArrayCount(); i++)
+ {
+ iSmileyIconArray[i]->SetSize(aSize);
+ }
+ }
+ }
+
+void CSmileyModel::SetSizeByFont(const CFont* aFont)
+ {
+ TSize size(aFont->TextWidthInPixels(KPlaceHolder),aFont->HeightInPixels());
+ SetSize(size);
+ }
+
+void CSmileyModel::DrawText(CWindowGc& aGc, const TDesC& aText, const CFont* aFont, const TPoint& aPosition) const
+ {
+ TPtrC ptr = aText;
+ TPoint pos = aPosition;
+
+ aGc.UseFont(aFont);
+
+ TBool metSmileyNotReady = EFalse;
+
+ while(ptr.Length())
{
- iSmileyIconArray[i]->SetSize(aSize);
+ TInt i = 0;
+ for(; i<aText.Length(); i++) // find next smiley code
+ {
+ if(IsSmiley(ptr[i]))
+ {
+ break;
+ }
+ }
+
+ if(i > 0) // have text
+ {
+ TPtrC txt = ptr.Left(i);
+ aGc.DrawText(txt, pos);
+ pos += TPoint(aFont->TextWidthInPixels(txt),0);
+
+ ptr.Set(ptr.Right(ptr.Length()-i));
+ i = 0;
+ }
+
+ if(ptr.Length()) // breaked by smiley code
+ {
+ CAknSmileyIcon* icon = Smiley(ptr[i]);
+ if(icon)
+ {
+ TSize size = icon->Size();
+ TPoint tl = pos;
+ tl.iY = tl.iY - (size.iHeight + aFont->HeightInPixels()) / 2;
+ if(!metSmileyNotReady && icon->ReadyToDraw())
+ {
+ aGc.BitBltMasked(tl, icon->Image(), TRect(size), icon->Mask(), EFalse);
+ }
+ else
+ {
+ metSmileyNotReady = ETrue;
+ }
+ pos += TPoint(aFont->TextWidthInPixels(ptr.Left(2)),0);
+ }
+
+ ptr.Set(ptr.Right(ptr.Length()-2));
+ }
}
}
-CSmileyIcon* CSmileyModel::operator[](TInt aIndex) const
+void CSmileyModel::DrawText(CWindowGc& aGc, const TDesC& aText, const TAknLayoutText& aLayout, TBool aUseLogicalToVisualConversion) const
+ {
+ // adapter variables
+ const CFont* font = aLayout.Font();
+ TRect textRect = aLayout.TextRect();
+ TInt offset = aLayout.BaselineOffset();
+ CGraphicsContext::TTextAlign align = aLayout.Align();
+
+ // belows are all from
+ // void TAknLayoutText::DrawText(CGraphicsContext& aGc,const TDesC& aText,TBool aUseLogicalToVisualConversion, const TRgb &aColor) const
+
+ __ASSERT_DEBUG(font, Panic(EAknPanicLayoutTextNotCalled));
+
+ //aGc.UseFont( font );
+ //aGc.SetPenColor( aColor );
+ if ( aText.Length() )
+ {
+ HBufC* visualBuf = NULL;
+ TPtrC text( aText );
+
+ if ( aUseLogicalToVisualConversion )
+ {
+ visualBuf = HBufC::New( aText.Length() + KAknBidiExtraSpacePerLine );
+
+ // In OOM, logical to visual conversion is not performed...
+
+ if ( visualBuf )
+ {
+ *visualBuf = aText; // copy
+ TPtr ptr = visualBuf->Des();
+
+ TInt maxWidth = textRect.Size().iWidth;
+
+ // Logical to visual conversion.
+ AknBidiTextUtils::ConvertToVisualAndClip(
+ aText,
+ ptr,
+ *font,
+ maxWidth,
+ maxWidth );
+
+ // for smiley begin
+ const TInt length = ptr.Length();
+ if(length>1 && IsSmiley(ptr[length-2]))
+ {
+ if(ptr[length-1] != 'i')
+ {
+ // smiley is clipped for visual, del this smiley
+ ptr.Delete(length-2, 1);
+ }
+ }
+ // for smiley end
+
+ text.Set( ptr );
+ }
+ }
+
+ // Calculate x-offset based on the used alignment
+ TInt margin = 0;
+ if ( align != CGraphicsContext::ELeft )
+ {
+ // Measure the full width of the text (ie. what DrawText needs)
+ TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth( *font, text,CFont::TMeasureTextInput::EFVisualOrder );
+
+ const TInt extraWidth = textRect.Width() - textWidth;
+ if ( align == CGraphicsContext::ECenter )
+ {
+ margin = extraWidth / 2;
+ }
+ else // right aligned
+ {
+ margin = extraWidth;
+ }
+ }
+
+ // Need to make the drawing rectangle bigger to account for underlines
+ TRect drawRect(textRect);
+ TInt height = drawRect.Height();
+ // The underline position is not available from the GC. The following code imitates what Symbian CFbsBitGC implements.
+ // (height-offset) is the part below the baseline. Check if it sufficient
+ TInt extraHeightForUnderlining = 1 + Max(1, height/10)-(height-offset);
+ if ( extraHeightForUnderlining > 0 )
+ drawRect.iBr.iY += extraHeightForUnderlining;
+
+ // for smiley
+ //aGc.DrawText( text, drawRect, offset, CGraphicsContext::ELeft, margin );
+ DrawText(aGc, text, font, drawRect, offset, CGraphicsContext::ELeft, margin);
+
+ delete visualBuf;
+ }
+
+ //aGc.DiscardFont(); // Release the font cache
+ }
+
+void CSmileyModel::DrawText(CWindowGc& aGc, const TDesC& aText, const CFont* aFont, const TRect& aBox, TInt aBaselineOffset,
+ CGraphicsContext::TTextAlign aAlignment, TInt aLeftMargin) const
{
- if(aIndex>=0 && aIndex<Count())
+ TInt boxWidth = aBox.Width();
+ TInt textWidth = aFont->TextWidthInPixels(aText);
+
+ TPoint offset;
+ offset.iY = aBaselineOffset;
+
+ switch(aAlignment)
+ {
+ case CGraphicsContext::ELeft:
+ offset.iX = aLeftMargin;
+ break;
+
+ case CGraphicsContext::ERight:
+ offset.iX = boxWidth - textWidth - aLeftMargin;
+ break;
+
+ case CGraphicsContext::ECenter:
+ offset.iX = (boxWidth - textWidth) / 2;
+ break;
+
+ default:
+ break;
+ }
+
+ DrawText(aGc, aText, aFont, aBox, offset);
+ }
+
+void CSmileyModel::DrawText(CWindowGc& aGc, const TDesC& aText, const CFont* aFont, const TRect& aBox, const TPoint& aOffset) const
+ {
+ TPtrC ptr = aText;
+ TPoint offset = aOffset;
+
+ aGc.UseFont(aFont);
+
+ TInt fontH = aFont->HeightInPixels();
+
+ TBool metSmileyNotReady = EFalse;
+
+ while(ptr.Length())
+ {
+ TInt i = 0;
+ for(; i<ptr.Length(); i++) // find next smiley code
+ {
+ if(IsSmiley(ptr[i]))
+ {
+ break;
+ }
+ }
+
+ if(i > 0) // have text
+ {
+ TPtrC txt = ptr.Left(i);
+ aGc.DrawText(txt, aBox, offset.iY, CGraphicsContext::ELeft, offset.iX);
+ offset.iX += aFont->TextWidthInPixels(txt);
+
+ ptr.Set(ptr.Right(ptr.Length()-i));
+ i = 0;
+ }
+
+ if(ptr.Length()) // breaked by smiley code
+ {
+ CAknSmileyIcon* icon = Smiley(ptr[i]);
+ if(icon)
+ {
+ TSize size = icon->Size();
+ TPoint tl = aBox.iTl + offset;
+ tl.iY = tl.iY - (size.iHeight + fontH) / 2;
+ TRect imgWindow(tl, size);
+ imgWindow.Intersection(aBox);
+ if(!imgWindow.IsEmpty())
+ {
+ TRect innerRect = TRect(imgWindow.iTl-tl,imgWindow.Size());
+ if(!metSmileyNotReady && icon->ReadyToDraw())
+ {
+ aGc.BitBltMasked(imgWindow.iTl, icon->Image(), innerRect, icon->Mask(), EFalse);
+ }
+ else
+ {
+ metSmileyNotReady = ETrue;
+ }
+ }
+
+ offset += TPoint(aFont->TextWidthInPixels(ptr.Left(2)),0);
+ }
+
+ ptr.Set(ptr.Right(ptr.Length()-2));
+ }
+ }
+ }
+
+CAknSmileyIcon* CSmileyModel::Smiley(TChar aCode) const
+ {
+ TInt index, variate;
+ if(DecodeSmileyCode(aCode, index, variate))
+ {
+ return (*this)[index];
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+CAknSmileyIcon* CSmileyModel::operator[](TInt aIndex) const
+ {
+ if(aIndex>=0 && aIndex<ArrayCount())
{
return iSmileyIconArray[aIndex];
}
@@ -364,19 +963,117 @@
TInt CSmileyModel::Count() const
{
+ return iSmileyIconArray.Count() - 2;
+ }
+
+CAknSmileyIcon* CSmileyModel::SwitchToSmileyIcon() const
+ {
+ return (*this)[Count()];
+ }
+
+CAknSmileyIcon* CSmileyModel::SwitchToSctIcon() const
+ {
+ return (*this)[Count()+1];
+ }
+
+TChar CSmileyModel::SwitchToSmileyCode() const
+ {
+ return SmileyCode(Count());
+ }
+
+TChar CSmileyModel::SwitchToSctCode() const
+ {
+ return SmileyCode(Count()+1);
+ }
+
+TChar CSmileyModel::SmileyCode(TInt aIndex, TInt aVariate) const
+ {
+ return EncodeSmileyCode(aIndex, aVariate);
+ }
+
+TChar CSmileyModel::SmileyCode(CAknSmileyIcon* aSmileyIcon) const
+ {
+ if(aSmileyIcon)
+ {
+ CSmileyIcon* icon = static_cast<CSmileyIcon*>(aSmileyIcon);
+ return EncodeSmileyCode(icon->Index(), 0);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+void CSmileyModel::LoadStillImagesL(const TDesC& aText)
+ {
+ for(TInt i(0); i<aText.Length(); i++)
+ {
+ LoadStillImageL(aText[i]);
+ }
+ }
+
+void CSmileyModel::LoadStillImageL(TChar aChar)
+ {
+ CSmileyIcon* icon = static_cast<CSmileyIcon*>(Smiley(aChar));
+ iSmileyLoader.AddTaskL(icon);
+ }
+
+const TDesC& CSmileyModel::Text(TInt aIndex, TInt aVariate) const
+ {
+ CSmileyIcon* icon = static_cast<CSmileyIcon*>((*this)[aIndex]);
+ if(icon)
+ {
+ return icon->Text(aVariate);
+ }
+ else
+ {
+ return KNullDesC;
+ }
+ }
+
+TInt CSmileyModel::ArrayCount() const
+ {
return iSmileyIconArray.Count();
}
-void CSmileyModel::ThumbnailLoaded(CSmileyIcon* aSmileyIcon)
+TChar CSmileyModel::EncodeSmileyCode(TInt aIndex, TInt aVariate) const
{
- TRAP_IGNORE(iSmileyThumbnailLoader.DoNextTaskL());
-
- if(iSmileyIconObserver) iSmileyIconObserver->ThumbnailLoaded(aSmileyIcon);
+ if(aVariate)
+ {
+ return (iBaseCode + aIndex + (aVariate<<8));
+ }
+ else
+ {
+ return (iBaseCode + aIndex);
+ }
}
-void CSmileyModel::AnimationChanged(CSmileyIcon* aSmileyIcon)
+#define KMaskL 0x00FF
+
+TBool CSmileyModel::DecodeSmileyCode(TChar aCode, TInt& aIndex, TInt& aVariate) const
{
- if(iSmileyIconObserver) iSmileyIconObserver->AnimationChanged(aSmileyIcon);
+ if(aCode >= iBaseCode)
+ {
+ aIndex = (aCode&KMaskL) - (iBaseCode&KMaskL);
+ aVariate = (aCode>>8) - (iBaseCode>>8);
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+void CSmileyModel::SmileyStillImageLoaded(CAknSmileyIcon* aSmileyIcon)
+ {
+ TRAP_IGNORE(iSmileyLoader.DoNextTaskL());
+
+ if(iSmileyIconObserver) iSmileyIconObserver->SmileyStillImageLoaded(aSmileyIcon);
+ }
+
+void CSmileyModel::SmileyAnimationChanged(CAknSmileyIcon* aSmileyIcon)
+ {
+ if(iSmileyIconObserver) iSmileyIconObserver->SmileyAnimationChanged(aSmileyIcon);
}