|
1 /* |
|
2 * Copyright (c) 2006-2007 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: Implementation of CHuiTextVisual. CHuiTextVisual is a visual |
|
15 * that draws text. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include <AknsConstants.h> |
|
22 #include <AknsUtils.h> |
|
23 #include <AknPictographInterface.h> |
|
24 #include <AknPictographDrawerInterface.h> |
|
25 #include <AknUtils.h> |
|
26 #include "uiacceltk/HuiTextVisual.h" // Class definition |
|
27 #include "HuiRenderPlugin.h" |
|
28 #include "uiacceltk/HuiControl.h" |
|
29 #include "uiacceltk/HuiDrawing.h" |
|
30 #include "uiacceltk/HuiTextMesh.h" |
|
31 #include "uiacceltk/HuiUtil.h" |
|
32 #include "uiacceltk/huitextstyle.h" |
|
33 #include "uiacceltk/huitextstylemanager.h" |
|
34 #include "uiacceltk/huidropshadow.h" |
|
35 |
|
36 #include "HuiRosterImpl.h" |
|
37 |
|
38 // Internal class to handle Japanese pictograph animations. |
|
39 NONSHARABLE_CLASS(CHuiPictographAnimator) : public CBase, public MAknPictographAnimatorCallBack |
|
40 { |
|
41 public: |
|
42 CHuiPictographAnimator(CHuiTextVisual* aVisual, CHuiTextMesh* aTextMesh); |
|
43 ~CHuiPictographAnimator(); |
|
44 TBool IsAnimating() const; |
|
45 void SetAnimating(TBool aAnimating); |
|
46 // From MAknPictographAnimatorCallBack |
|
47 void DrawPictographArea(); |
|
48 private: |
|
49 CHuiTextVisual* iVisual; |
|
50 CHuiTextMesh* iTextMesh; |
|
51 TBool iAnimating; |
|
52 }; |
|
53 |
|
54 CHuiPictographAnimator::CHuiPictographAnimator(CHuiTextVisual* aVisual, CHuiTextMesh* aTextMesh) |
|
55 { |
|
56 iVisual = aVisual; |
|
57 iTextMesh = aTextMesh; |
|
58 } |
|
59 |
|
60 CHuiPictographAnimator::~CHuiPictographAnimator() |
|
61 { |
|
62 iVisual = NULL; |
|
63 iTextMesh = NULL; |
|
64 } |
|
65 |
|
66 TBool CHuiPictographAnimator::IsAnimating() const |
|
67 { |
|
68 return iAnimating; |
|
69 } |
|
70 |
|
71 void CHuiPictographAnimator::SetAnimating(TBool aAnimating) |
|
72 { |
|
73 iAnimating = aAnimating; |
|
74 } |
|
75 |
|
76 void CHuiPictographAnimator::DrawPictographArea() |
|
77 { |
|
78 // This condition might need some further consideration. |
|
79 if (iVisual->EffectiveOpacity() > 0.0 && |
|
80 CHuiStatic::Env().RefreshMode() != EHuiRefreshModeManual) |
|
81 { |
|
82 SetAnimating(ETrue); |
|
83 // This BuildPictographsL()-call also keeps the animation ticker |
|
84 // behind CAknPictographInterface alive. |
|
85 TRAP_IGNORE(iTextMesh->BuildPictographsL()) |
|
86 iVisual->SetChanged(); |
|
87 } |
|
88 else |
|
89 { |
|
90 // No call made to CAknPictographInterface -> animation timer gets automatically freezed. |
|
91 SetAnimating(EFalse); |
|
92 } |
|
93 } |
|
94 |
|
95 |
|
96 EXPORT_C CHuiTextVisual* CHuiTextVisual::AddNewL(CHuiControl& aOwnerControl, |
|
97 CHuiLayout* aParentLayout) |
|
98 { |
|
99 CHuiTextVisual* text = STATIC_CAST(CHuiTextVisual*, |
|
100 aOwnerControl.AppendVisualL(EHuiVisualTypeText, aParentLayout)); |
|
101 return text; |
|
102 } |
|
103 |
|
104 |
|
105 CHuiTextVisual::CHuiTextVisual(MHuiVisualOwner& aOwner) |
|
106 : CHuiVisual(aOwner), |
|
107 iLineWrapping(ELineWrapManual), |
|
108 iAlignHorizontal(EHuiAlignHCenter), |
|
109 iAlignVertical(EHuiAlignVCenter), |
|
110 iStyle(EHuiTextStyleNormal), |
|
111 iFontColor(KRgbWhite), |
|
112 iFontColorId(KAknsIIDNone) |
|
113 { |
|
114 } |
|
115 |
|
116 |
|
117 void CHuiTextVisual::ConstructL() |
|
118 { |
|
119 CHuiVisual::ConstructL(); |
|
120 |
|
121 iTextMesh = CHuiStatic::Renderer().CreateTextMeshL(); |
|
122 iTextMesh->SetRelatedVisual( this ); |
|
123 |
|
124 iMeshUpdated = EFalse; |
|
125 iExtentsUpdated = EFalse; |
|
126 iPictographAnimator = new (ELeave) CHuiPictographAnimator(this, iTextMesh); |
|
127 // Ugly missing CCoeControl workaround, but CAknPictographInterface does not seem to use CCoeControl. |
|
128 CCoeControl* dummy = NULL; |
|
129 iPictographInterface = CAknPictographInterface::NewL( *dummy, *iPictographAnimator ); // Returns NULL if not supported. |
|
130 if (iPictographInterface) |
|
131 { |
|
132 iTextMesh->InitPictographsL(iPictographInterface); |
|
133 } |
|
134 } |
|
135 |
|
136 |
|
137 CHuiTextVisual::~CHuiTextVisual() |
|
138 { |
|
139 delete iText; |
|
140 delete iTextMesh; |
|
141 delete iPictographAnimator; |
|
142 delete iPictographInterface; |
|
143 } |
|
144 |
|
145 |
|
146 EXPORT_C void CHuiTextVisual::SetStyle(THuiPreconfiguredTextStyle aStyle, THuiBackgroundType aBackgroundType) |
|
147 { |
|
148 SetTextStyle(aStyle); |
|
149 iStyle = aStyle; |
|
150 THuiTextStyle* textStyle = Env().TextStyleManager().TextStyle(aStyle); |
|
151 |
|
152 if( aBackgroundType == EHuiBackgroundTypeLight) |
|
153 { |
|
154 textStyle->SetTextColor(KRgbBlack); |
|
155 } |
|
156 else |
|
157 { |
|
158 textStyle->SetTextColor(KRgbWhite); |
|
159 } |
|
160 iBackgroundType = aBackgroundType; |
|
161 } |
|
162 |
|
163 |
|
164 EXPORT_C THuiPreconfiguredTextStyle CHuiTextVisual::Style() const |
|
165 { |
|
166 return iStyle; |
|
167 } |
|
168 |
|
169 |
|
170 EXPORT_C void CHuiTextVisual::SetMaxLineCount(TInt aMaxLineCount) |
|
171 { |
|
172 if(iTextMesh->SetMaxLineCount(aMaxLineCount)) |
|
173 { |
|
174 iMeshUpdated = EFalse; |
|
175 iExtentsUpdated = EFalse; |
|
176 SetChanged(); |
|
177 } |
|
178 } |
|
179 |
|
180 |
|
181 EXPORT_C TInt CHuiTextVisual::MaxLineCount() const |
|
182 { |
|
183 return iTextMesh->MaxLineCount(); |
|
184 } |
|
185 |
|
186 |
|
187 EXPORT_C CHuiTextVisual::TLineWrap CHuiTextVisual::Wrapping() const |
|
188 { |
|
189 return iLineWrapping; |
|
190 } |
|
191 |
|
192 |
|
193 EXPORT_C void CHuiTextVisual::SetWrapping(TLineWrap aWrap) |
|
194 { |
|
195 iLineWrapping = aWrap; |
|
196 switch(iLineWrapping) |
|
197 { |
|
198 case ELineWrapManual: |
|
199 case ELineWrapTruncate: |
|
200 iTextMesh->SetLineMode(CHuiTextMesh::ELineModeTruncate); |
|
201 break; |
|
202 |
|
203 case ELineWrapBreak: |
|
204 iTextMesh->SetLineMode(CHuiTextMesh::ELineModeWrap); |
|
205 break; |
|
206 } |
|
207 SetChanged(); |
|
208 } |
|
209 |
|
210 |
|
211 EXPORT_C THuiBackgroundType CHuiTextVisual::BackgroundType() const |
|
212 { |
|
213 return iBackgroundType; |
|
214 } |
|
215 |
|
216 |
|
217 EXPORT_C void CHuiTextVisual::SetTextL(const TDesC& aText) |
|
218 { |
|
219 delete iText; iText = 0; |
|
220 iText = aText.AllocL(); |
|
221 |
|
222 iMeshUpdated = EFalse; |
|
223 iExtentsUpdated = EFalse; |
|
224 SetChanged(); |
|
225 } |
|
226 |
|
227 |
|
228 EXPORT_C const TDesC& CHuiTextVisual::Text() const |
|
229 { |
|
230 if(iText) |
|
231 { |
|
232 return *iText; |
|
233 } |
|
234 _LIT(KNoText, ""); |
|
235 return KNoText; |
|
236 } |
|
237 |
|
238 |
|
239 EXPORT_C void CHuiTextVisual::SetAlign(THuiAlignHorizontal aAlignHorizontal, |
|
240 THuiAlignVertical aAlignVertical) |
|
241 { |
|
242 iAlignHorizontal = aAlignHorizontal; |
|
243 iAlignVertical = aAlignVertical; |
|
244 |
|
245 SetChanged(); |
|
246 } |
|
247 |
|
248 |
|
249 EXPORT_C void CHuiTextVisual::SetLineSpacing(TInt aLineSpacing, TLineSpacingUnits aUnits) |
|
250 { |
|
251 TInt lineSpacingInPixels = 0; |
|
252 |
|
253 if(aUnits == ETwips) |
|
254 { |
|
255 CWsScreenDevice* screenDev = CHuiStatic::ScreenDevice(); |
|
256 lineSpacingInPixels = screenDev->VerticalTwipsToPixels(aLineSpacing); |
|
257 } |
|
258 else |
|
259 { |
|
260 lineSpacingInPixels = aLineSpacing; |
|
261 } |
|
262 |
|
263 iTextMesh->SetLineSpacing(lineSpacingInPixels); |
|
264 } |
|
265 |
|
266 |
|
267 EXPORT_C TSize CHuiTextVisual::TextExtents() const |
|
268 { |
|
269 if(!iText) |
|
270 { |
|
271 return TSize(0, 0); |
|
272 } |
|
273 |
|
274 if (!iExtentsUpdated) |
|
275 { |
|
276 TRAPD(err, iTextMesh->SetTextL(*iText, EFalse)); |
|
277 if (err != KErrNone) |
|
278 { |
|
279 HUI_DEBUG1(_L("CHuiTextVisual::TextExtents() - ERROR! Failed to update mesh with leave errorcode %i. Text extents are not currently available. "), err); |
|
280 iExtentsUpdated = EFalse; // we have to retry soon.. |
|
281 return TSize(0, 0); |
|
282 } |
|
283 |
|
284 iExtentsUpdated = ETrue; |
|
285 } |
|
286 |
|
287 return iTextMesh->Extents(); |
|
288 } |
|
289 |
|
290 EXPORT_C TRect CHuiTextVisual::SubstringExtents(TUint aStart, TUint aEnd) const |
|
291 { |
|
292 if(!iText) |
|
293 { |
|
294 return TRect(0, 0, 0, 0); |
|
295 } |
|
296 |
|
297 // Retrieve the text style used when rasterizing this text. |
|
298 THuiTextStyle* textStyle = CHuiStatic::Env().TextStyleManager().TextStyle(iTextMesh->TextStyle()); |
|
299 |
|
300 TSize begin(0,0); |
|
301 TSize end(0,0); |
|
302 TRAP_IGNORE( |
|
303 { |
|
304 begin = textStyle->LineExtentsL(iText->Mid(0, aStart)); |
|
305 end = textStyle->LineExtentsL(iText->Mid(0, aEnd)); |
|
306 }) |
|
307 |
|
308 return TRect(begin.iWidth, 0, end.iWidth, end.iHeight); |
|
309 } |
|
310 |
|
311 const TUint8 color_s_to_lin[256] = { |
|
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, |
|
313 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
|
314 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, |
|
315 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, |
|
316 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, |
|
317 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, |
|
318 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, |
|
319 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0d, |
|
320 0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10, |
|
321 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x14, |
|
322 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, |
|
323 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, |
|
324 0x1e, 0x1f, 0x1f, 0x20, 0x21, 0x21, 0x22, 0x23, |
|
325 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, |
|
326 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, 0x2e, 0x2f, |
|
327 0x30, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35, 0x36, |
|
328 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, |
|
329 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, |
|
330 0x47, 0x48, 0x49, 0x4a, 0x4c, 0x4d, 0x4e, 0x4f, |
|
331 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, |
|
332 0x5a, 0x5b, 0x5c, 0x5d, 0x5f, 0x60, 0x61, 0x63, |
|
333 0x64, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6c, 0x6d, |
|
334 0x6f, 0x70, 0x72, 0x73, 0x74, 0x76, 0x77, 0x79, |
|
335 0x7a, 0x7c, 0x7d, 0x7f, 0x80, 0x82, 0x83, 0x85, |
|
336 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x92, |
|
337 0x93, 0x95, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9f, |
|
338 0xa1, 0xa3, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xad, |
|
339 0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, 0xbc, |
|
340 0xbe, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, |
|
341 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, |
|
342 0xde, 0xe0, 0xe2, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, |
|
343 0xef, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfd, 0xff }; |
|
344 |
|
345 inline TRgb ConvertToLinear(TRgb aColor) |
|
346 { |
|
347 // perform sRGB->linear color conversion if the renderer is |
|
348 // openvg |
|
349 // NOTE: For emulator depending on the OpenVG SW version mapping may |
|
350 // be needed or not. Use/unuse ifdefs below if text colors are too dark/light. |
|
351 //#ifndef __WINSCW__ |
|
352 // if (CHuiStatic::Env().Renderer() == EHuiRendererVg10) |
|
353 { |
|
354 TUint32 color = aColor.Internal(); |
|
355 return |
|
356 ((TUint32)color_s_to_lin[(color >> 0) & 0xff] << 16) | |
|
357 ((TUint32)color_s_to_lin[(color >> 8) & 0xff] << 8) | |
|
358 ((TUint32)color_s_to_lin[(color >> 16) & 0xff] << 0) | |
|
359 (color & 0xff000000); |
|
360 } |
|
361 //#endif |
|
362 return aColor; |
|
363 } |
|
364 |
|
365 |
|
366 EXPORT_C void CHuiTextVisual::SetColor(const TRgb& aColor) |
|
367 { |
|
368 iFontColor = ConvertToLinear(aColor); |
|
369 iFontColorId = KAknsIIDNone; |
|
370 iFontColorIndex = -1; |
|
371 iFontColorValid = ETrue; |
|
372 SetChanged(); |
|
373 } |
|
374 |
|
375 |
|
376 EXPORT_C void CHuiTextVisual::SetColor(const TAknsItemID& aID,const TInt aIndex) |
|
377 { |
|
378 iFontColorId = aID; |
|
379 iFontColorIndex = aIndex; |
|
380 iFontColorValid = EFalse; |
|
381 SetChanged(); |
|
382 } |
|
383 |
|
384 |
|
385 EXPORT_C void CHuiTextVisual::EnableShadow(TBool aDoEnable) |
|
386 { |
|
387 TRAP_IGNORE( EnableDropShadowL(aDoEnable) ); |
|
388 } |
|
389 |
|
390 |
|
391 TBool CHuiTextVisual::PrepareDrawL() |
|
392 { |
|
393 if (Flags() & EHuiVisualFlagDrawOnlyAsExternalContent) |
|
394 { |
|
395 // This is used only as external content visual. Return now if we are not currently drawing |
|
396 // external content. |
|
397 if (!Display() || !Display()->RosterImpl().IsDrawingExternalContent()) |
|
398 { |
|
399 return ETrue; |
|
400 } |
|
401 } |
|
402 |
|
403 if(!iText) |
|
404 { |
|
405 return ETrue; |
|
406 } |
|
407 |
|
408 TReal32 effectiveOpacity = EffectiveOpacity(); |
|
409 if(effectiveOpacity <= 0) |
|
410 { |
|
411 return ETrue; |
|
412 } |
|
413 |
|
414 if ( DropShadowHandler() ) |
|
415 { |
|
416 if ( DropShadowHandler()->iRadius.Changed() ) |
|
417 { |
|
418 iMeshUpdated = EFalse; |
|
419 } |
|
420 } |
|
421 |
|
422 iTextMesh->EnableRasterizedShadow(TBool(DropShadowHandler())); |
|
423 |
|
424 // use directly target rect and thus rasterize the text only once |
|
425 // and not for each frame when the visual's size is changing |
|
426 THuiRealRect content = DisplayRectTarget(); |
|
427 content.Shrink(PaddingInPixels()); |
|
428 |
|
429 // In wrapping mode, let the mesh know how much space there is |
|
430 // for drawing into. |
|
431 TInt maxWidth = KMaxTInt; |
|
432 if(iLineWrapping != ELineWrapManual) |
|
433 { |
|
434 maxWidth = TInt(content.Width()+0.5f); |
|
435 } |
|
436 |
|
437 // Update the text mesh, if needed. Set max line width first to avoid |
|
438 // rendering with wrong max line width. |
|
439 if(iTextMesh->SetMaxLineWidth(maxWidth) || !iMeshUpdated) |
|
440 { |
|
441 UpdateMeshL(); |
|
442 } |
|
443 |
|
444 if (effectiveOpacity > 0 && |
|
445 iPictographInterface && |
|
446 iPictographAnimator && |
|
447 !iPictographAnimator->IsAnimating()) |
|
448 { |
|
449 iPictographAnimator->DrawPictographArea(); // restarts animation timer if needed |
|
450 } |
|
451 |
|
452 return ETrue; |
|
453 } |
|
454 |
|
455 |
|
456 void CHuiTextVisual::DrawSelf(CHuiGc& aGc, const TRect& aDisplayRect) const |
|
457 { |
|
458 if(!iText) |
|
459 { |
|
460 return; |
|
461 } |
|
462 |
|
463 TReal32 effectiveOpacity = EffectiveOpacity(); |
|
464 if(effectiveOpacity <= 0) |
|
465 { |
|
466 return; |
|
467 } |
|
468 aGc.Enable(CHuiGc::EFeatureBlending); |
|
469 aGc.SetAlign(iAlignHorizontal, iAlignVertical); |
|
470 aGc.SetPenAlpha(TInt(effectiveOpacity * 255)); |
|
471 |
|
472 // Set up the text color. Priority order is: explicit color set, then by skin ID, then by Hui Style |
|
473 TBool setDefaultColor = ETrue; |
|
474 if ( iFontColorValid ) |
|
475 { |
|
476 setDefaultColor = EFalse; |
|
477 aGc.SetPenColor(iFontColor); |
|
478 } |
|
479 else if (iFontColorId != KAknsIIDNone) |
|
480 { |
|
481 TRgb color = KRgbGreen; |
|
482 setDefaultColor = ( CHuiStatic::GetCachedColor( |
|
483 color, iFontColorId, iFontColorIndex ) |
|
484 != KErrNone ); |
|
485 if ( !setDefaultColor ) |
|
486 { |
|
487 aGc.SetPenColor(color); |
|
488 } |
|
489 } |
|
490 else |
|
491 { |
|
492 // setDefaultColor equals to ETrue and so it's ok. |
|
493 } |
|
494 |
|
495 if ( setDefaultColor ) |
|
496 { |
|
497 // Default is to use the color indicated by style |
|
498 aGc.SetPenColor(Skin().StyleTextColor(iStyle, iBackgroundType)); |
|
499 } |
|
500 |
|
501 HUI_DEBUGF3(_L("CHuiTextVisual::DrawSelf() -- iStyle=%i, iBackgroundType=%i, lightness=%f"), |
|
502 iStyle, iBackgroundType, HuiUtil::ColorLightness(aGc.PenColor())); |
|
503 |
|
504 THuiRealRect content = aDisplayRect; |
|
505 content.Shrink(PaddingInPixels()); |
|
506 content.iTl += LocalPointInPixels(iOffset.Now()); |
|
507 |
|
508 if ( DropShadowHandler() ) |
|
509 { |
|
510 aGc.DrawText(*iTextMesh, content, DropShadowHandler()->iOpacity.Now()); |
|
511 } |
|
512 else |
|
513 { |
|
514 aGc.DrawText(*iTextMesh, content, 0.f); |
|
515 } |
|
516 |
|
517 |
|
518 if(iHighlightEnd - iHighlightStart) |
|
519 { |
|
520 TPoint textPos(content.iTl.iX, content.iTl.iY); |
|
521 |
|
522 TSize textBounds = TextExtents(); |
|
523 |
|
524 switch(iAlignHorizontal) |
|
525 { |
|
526 case EHuiAlignHRight: |
|
527 textPos.iX = content.iBr.iX - textBounds.iWidth; |
|
528 break; |
|
529 |
|
530 case EHuiAlignHCenter: |
|
531 textPos.iX = content.Center().iX - textBounds.iWidth / 2; // or 2.f? |
|
532 break; |
|
533 |
|
534 default: |
|
535 break; |
|
536 } |
|
537 |
|
538 switch(iAlignVertical) |
|
539 { |
|
540 case EHuiAlignVBottom: |
|
541 textPos.iY = content.iBr.iY - textBounds.iHeight; |
|
542 break; |
|
543 |
|
544 case EHuiAlignVCenter: |
|
545 textPos.iY = content.Center().iY - textBounds.iHeight / 2; // or 2.f? |
|
546 break; |
|
547 |
|
548 default: |
|
549 break; |
|
550 } |
|
551 |
|
552 THuiRealRect textRect(textPos, textBounds); |
|
553 |
|
554 // hackish, for now |
|
555 TBool conversionRequired = ETrue; |
|
556 if (iHighlightStart > iText->Length() || iHighlightEnd > iText->Length() ) |
|
557 { |
|
558 conversionRequired = ETrue; |
|
559 } |
|
560 |
|
561 const TBidiText::TDirectionality bidiDirection = TBidiText::TextDirectionality( *iText); |
|
562 if ( bidiDirection == TBidiText::ERightToLeft ) |
|
563 { |
|
564 textRect.iBr.iX -= conversionRequired?SubstringExtents(0, iHighlightStart).Width():iHighlightStart; |
|
565 textRect.iTl.iX = textRect.iBr.iX - conversionRequired?SubstringExtents(iHighlightStart,iHighlightEnd).Width():iHighlightEnd; |
|
566 } |
|
567 else |
|
568 { |
|
569 textRect.iTl.iX += conversionRequired?SubstringExtents(0, iHighlightStart).Width():iHighlightStart; |
|
570 textRect.iBr.iX = textRect.iTl.iX + conversionRequired?SubstringExtents(iHighlightStart,iHighlightEnd).Width():iHighlightEnd; |
|
571 } |
|
572 |
|
573 aGc.SetPenColor(iHighlightColor); |
|
574 aGc.DrawRect(textRect); |
|
575 aGc.SetPenColor(iHighlightTextColor); |
|
576 |
|
577 THuiTextStyle* textStyle = CHuiStatic::Env().TextStyleManager().TextStyle(iTextMesh->TextStyle()); |
|
578 |
|
579 textRect.Move(- textPos.iX, - textPos.iY); |
|
580 |
|
581 textStyle->EnableClipping(textRect); |
|
582 |
|
583 TRAPD(error,UpdateMeshL()); |
|
584 |
|
585 if ( DropShadowHandler() ) |
|
586 { |
|
587 aGc.DrawText(*iTextMesh, content, DropShadowHandler()->iOpacity.Now()); |
|
588 } |
|
589 else |
|
590 { |
|
591 aGc.DrawText(*iTextMesh, content, 0.f); |
|
592 } |
|
593 |
|
594 textStyle->DisableClipping(); |
|
595 |
|
596 TRAP(error,UpdateMeshL()); |
|
597 |
|
598 } |
|
599 |
|
600 } |
|
601 |
|
602 |
|
603 TBool CHuiTextVisual::Changed() const |
|
604 { |
|
605 if(CHuiVisual::Changed()) |
|
606 { |
|
607 return ETrue; |
|
608 } |
|
609 return (iOffset.Changed() ); |
|
610 } |
|
611 |
|
612 |
|
613 void CHuiTextVisual::ClearChanged() |
|
614 { |
|
615 CHuiVisual::ClearChanged(); |
|
616 iOffset.ClearChanged(); |
|
617 } |
|
618 |
|
619 |
|
620 void CHuiTextVisual::UpdateMeshL() const |
|
621 { |
|
622 iTextMesh->Reset(); |
|
623 iTextMesh->SetTextL(*iText, ETrue); |
|
624 iMeshUpdated = ETrue; |
|
625 iExtentsUpdated = ETrue; |
|
626 } |
|
627 |
|
628 |
|
629 void CHuiTextVisual::NotifySkinChangedL() |
|
630 { |
|
631 iMeshUpdated = EFalse; |
|
632 iExtentsUpdated = EFalse; |
|
633 SetChanged(); |
|
634 } |
|
635 |
|
636 |
|
637 void CHuiTextVisual::ExpandRectWithContent(TRect& aRect) const |
|
638 { |
|
639 if(!Clipping() && iText && iText->Length() ) |
|
640 { |
|
641 TSize extents = TextExtents(); |
|
642 TPoint tl = aRect.Center(); |
|
643 |
|
644 // check top left X |
|
645 THuiAlignHorizontal usedHorizontalAlign = iAlignHorizontal; |
|
646 switch(iAlignHorizontal) |
|
647 { |
|
648 case EHuiAlignHLocale: |
|
649 if(CHuiStatic::LayoutMirrored()) |
|
650 { |
|
651 usedHorizontalAlign = EHuiAlignHRight; |
|
652 } |
|
653 else |
|
654 { |
|
655 usedHorizontalAlign = EHuiAlignHLeft; |
|
656 } |
|
657 break; |
|
658 |
|
659 case EHuiAlignHLocaleMirrored: |
|
660 if(CHuiStatic::LayoutMirrored()) |
|
661 { |
|
662 usedHorizontalAlign = EHuiAlignHLeft; |
|
663 } |
|
664 else |
|
665 { |
|
666 usedHorizontalAlign = EHuiAlignHRight; |
|
667 } |
|
668 break; |
|
669 case EHuiAlignHBidirectionalText: |
|
670 { |
|
671 TBool bidiInformationFound = EFalse; |
|
672 const TBidiText::TDirectionality bidiDirection = TBidiText::TextDirectionality( *iText, &bidiInformationFound ); |
|
673 if ( bidiInformationFound ) |
|
674 { |
|
675 if ( bidiDirection == TBidiText::ELeftToRight ) |
|
676 { |
|
677 usedHorizontalAlign = EHuiAlignHLeft; |
|
678 } |
|
679 else // ERightToLeft |
|
680 { |
|
681 usedHorizontalAlign = EHuiAlignHRight; |
|
682 } |
|
683 } |
|
684 else // fall back... use locale |
|
685 { |
|
686 if(CHuiStatic::LayoutMirrored()) |
|
687 { |
|
688 usedHorizontalAlign = EHuiAlignHRight; |
|
689 } |
|
690 else |
|
691 { |
|
692 usedHorizontalAlign = EHuiAlignHLeft; |
|
693 } |
|
694 } |
|
695 } |
|
696 break; |
|
697 case EHuiAlignHBidirectionalTextMirrored: |
|
698 { |
|
699 TBool bidiInformationFound = EFalse; |
|
700 const TBidiText::TDirectionality bidiDirection = TBidiText::TextDirectionality( *iText, &bidiInformationFound ); |
|
701 if ( bidiInformationFound ) |
|
702 { |
|
703 if ( bidiDirection == TBidiText::ELeftToRight ) |
|
704 { |
|
705 usedHorizontalAlign = EHuiAlignHRight; |
|
706 } |
|
707 else // ERightToLeft |
|
708 { |
|
709 usedHorizontalAlign = EHuiAlignHLeft; |
|
710 } |
|
711 } |
|
712 else // fall back... use locale mirrored |
|
713 { |
|
714 if(CHuiStatic::LayoutMirrored()) |
|
715 { |
|
716 usedHorizontalAlign = EHuiAlignHLeft; |
|
717 } |
|
718 else |
|
719 { |
|
720 usedHorizontalAlign = EHuiAlignHRight; |
|
721 } |
|
722 } |
|
723 } |
|
724 break; |
|
725 default: |
|
726 break; |
|
727 } |
|
728 |
|
729 switch( usedHorizontalAlign ) |
|
730 { |
|
731 case EHuiAlignHLeft: |
|
732 tl.iX = aRect.iTl.iX; |
|
733 break; |
|
734 case EHuiAlignHCenter: |
|
735 tl.iX -= extents.iWidth/2; |
|
736 break; |
|
737 case EHuiAlignHRight: |
|
738 tl.iX = aRect.iBr.iX - extents.iWidth; |
|
739 break; |
|
740 default: |
|
741 break; |
|
742 } |
|
743 |
|
744 // check top left Y |
|
745 switch( iAlignVertical ) |
|
746 { |
|
747 case EHuiAlignVTop: |
|
748 tl.iY = aRect.iTl.iY; |
|
749 break; |
|
750 case EHuiAlignVCenter: |
|
751 tl.iY -= extents.iHeight/2; |
|
752 break; |
|
753 case EHuiAlignVBottom: |
|
754 tl.iY = aRect.iBr.iY - extents.iHeight; |
|
755 break; |
|
756 default: |
|
757 break; |
|
758 } |
|
759 |
|
760 TRect textExtendsRect(tl, extents); |
|
761 textExtendsRect.Grow(1,1); // fix rounding errors from Center() and /2 functions. |
|
762 |
|
763 textExtendsRect.Move(TPoint(LocalPointInPixels(iOffset.Now()))); |
|
764 |
|
765 aRect.BoundingRect(textExtendsRect); |
|
766 |
|
767 |
|
768 // add shadow |
|
769 CHuiDropShadow* shadowHandler = DropShadowHandler(); |
|
770 if ( shadowHandler && |
|
771 !HuiUtil::RealCompare( shadowHandler->iScale.Now(), 0.f ) && |
|
772 !HuiUtil::RealCompare( shadowHandler->iOpacity.Now(), 0.f ) ) |
|
773 { |
|
774 iTextMesh->ExpandRectWithShadow( aRect ); |
|
775 } |
|
776 } |
|
777 |
|
778 CHuiVisual::ExpandRectWithContent(aRect); |
|
779 } |
|
780 |
|
781 |
|
782 EXPORT_C void CHuiTextVisual::SetTextStyle(TInt aTextStyleId) |
|
783 { |
|
784 iTextMesh->SetTextStyle(aTextStyleId); |
|
785 |
|
786 iMeshUpdated = EFalse; |
|
787 iExtentsUpdated = EFalse; |
|
788 iStyle = STATIC_CAST(THuiPreconfiguredTextStyle, aTextStyleId); |
|
789 SetChanged(); |
|
790 } |
|
791 |
|
792 EXPORT_C TInt CHuiTextVisual::TextStyle() const |
|
793 { |
|
794 return iStyle; |
|
795 } |
|
796 |
|
797 |
|
798 EXPORT_C void CHuiTextVisual::SetHighlightRange(TInt aStart, TInt aEnd, TRgb& aHighlightColor, TRgb& aHighlightTextColor) |
|
799 { |
|
800 /* |
|
801 if((aStart < 0) || (aStart > iText->Length()) || (aEnd < 0)) |
|
802 return; |
|
803 |
|
804 if(aStart >= aEnd) |
|
805 return; |
|
806 |
|
807 if(aEnd > iText->Length()) |
|
808 aEnd = iText->Length(); |
|
809 */ |
|
810 iHighlightStart = aStart; |
|
811 iHighlightEnd = aEnd; |
|
812 |
|
813 iHighlightColor = aHighlightColor; |
|
814 iHighlightTextColor = aHighlightTextColor; |
|
815 |
|
816 SetChanged(); |
|
817 } |
|
818 |
|
819 EXPORT_C void CHuiTextVisual::UpdateMeshL(const TDesC8& aBuffer) |
|
820 { |
|
821 iTextMesh->UpdateMeshL(aBuffer); |
|
822 if (!iText) |
|
823 { |
|
824 SetTextL(KNullDesC); |
|
825 } |
|
826 |
|
827 SetChanged(); |
|
828 } |