|
1 /* |
|
2 * Copyright (c) 2003 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: SVG Implementation source file |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #if !defined(__E32BASE_H__) |
|
20 #include <e32base.h> |
|
21 #endif |
|
22 |
|
23 #include <AknBidiTextUtils.h> |
|
24 |
|
25 #include "SVGTextAreaElementImpl.h" |
|
26 #include "SVGRectElementImpl.h" |
|
27 #include "SVGTextElementImpl.h" |
|
28 #include "SVGElementImpl.h" |
|
29 #include "SVGDocumentImpl.h" |
|
30 #include "SVGSchemaData.h" |
|
31 #include "SVGEngineImpl.h" |
|
32 #include "GfxAffineTransform.h" |
|
33 |
|
34 // --------------------------------------------------------------------------- |
|
35 // |
|
36 // --------------------------------------------------------------------------- |
|
37 CSvgTextAreaElementImpl* CSvgTextAreaElementImpl::NewL( const TUint8 aElemID, |
|
38 CSvgDocumentImpl* aDoc ) |
|
39 { |
|
40 CSvgTextAreaElementImpl*self = new ( ELeave ) CSvgTextAreaElementImpl( aDoc ); |
|
41 CleanupStack::PushL( self ); |
|
42 self->ConstructL( aElemID); |
|
43 CleanupStack::Pop(); |
|
44 |
|
45 return self; |
|
46 } |
|
47 |
|
48 // --------------------------------------------------------------------------- |
|
49 // |
|
50 // --------------------------------------------------------------------------- |
|
51 CSvgTextAreaElementImpl* CSvgTextAreaElementImpl::NewLC( const TUint8 aElemID, |
|
52 CSvgDocumentImpl* aDoc ) |
|
53 { |
|
54 CSvgTextAreaElementImpl*self = new ( ELeave ) CSvgTextAreaElementImpl( aDoc ); |
|
55 CleanupStack::PushL( self ); |
|
56 self->ConstructL( aElemID ); |
|
57 |
|
58 return self; |
|
59 } |
|
60 |
|
61 // --------------------------------------------------------------------------- |
|
62 // |
|
63 // --------------------------------------------------------------------------- |
|
64 CSvgTextAreaElementImpl::~CSvgTextAreaElementImpl() |
|
65 { |
|
66 if ( iSvgStyleProperties ) |
|
67 { |
|
68 iSvgStyleProperties->Close(); |
|
69 delete iSvgStyleProperties; |
|
70 iSvgStyleProperties = NULL; |
|
71 } |
|
72 |
|
73 if ( iInnerRectangle ) |
|
74 { |
|
75 this->RemoveChild(iInnerRectangle); |
|
76 delete iInnerRectangle; |
|
77 iInnerRectangle = NULL; |
|
78 } |
|
79 |
|
80 if ( iBorderRectangle ) |
|
81 { |
|
82 this->RemoveChild(iBorderRectangle); |
|
83 delete iBorderRectangle; |
|
84 iBorderRectangle = NULL; |
|
85 } |
|
86 |
|
87 if (iTextElementsArray) |
|
88 { |
|
89 iTextElementsArray->Reset(); |
|
90 iTextElementsArray->Close(); |
|
91 delete iTextElementsArray; |
|
92 iTextElementsArray = NULL; |
|
93 } |
|
94 if (iAllText) |
|
95 { |
|
96 delete iAllText; |
|
97 iAllText = NULL; |
|
98 } |
|
99 |
|
100 ((CSvgDocumentImpl*)OwnerDocument())->RemoveInternalMouseListener( this ); |
|
101 |
|
102 } |
|
103 |
|
104 // ******************************************************* |
|
105 // From SVG DOM |
|
106 // --------------------------------------------------------------------------- |
|
107 // |
|
108 // --------------------------------------------------------------------------- |
|
109 TFloatFixPt CSvgTextAreaElementImpl::X() |
|
110 { |
|
111 if (!iInitialized) |
|
112 { |
|
113 return 0; |
|
114 } |
|
115 |
|
116 return iBorderRectangle->X(); |
|
117 } |
|
118 |
|
119 // --------------------------------------------------------------------------- |
|
120 // |
|
121 // --------------------------------------------------------------------------- |
|
122 TFloatFixPt CSvgTextAreaElementImpl::Y() |
|
123 { |
|
124 if (!iInitialized) |
|
125 { |
|
126 return 0; |
|
127 } |
|
128 |
|
129 return iBorderRectangle->Y(); |
|
130 } |
|
131 |
|
132 // --------------------------------------------------------------------------- |
|
133 // |
|
134 // --------------------------------------------------------------------------- |
|
135 TFloatFixPt CSvgTextAreaElementImpl::Width() |
|
136 { |
|
137 if (!iInitialized) |
|
138 { |
|
139 return 0; |
|
140 } |
|
141 |
|
142 return iBorderRectangle->Width(); |
|
143 } |
|
144 |
|
145 // --------------------------------------------------------------------------- |
|
146 // |
|
147 // --------------------------------------------------------------------------- |
|
148 TFloatFixPt CSvgTextAreaElementImpl::Height() |
|
149 { |
|
150 if (!iInitialized) |
|
151 { |
|
152 return 0; |
|
153 } |
|
154 |
|
155 return iBorderRectangle->Height(); |
|
156 } |
|
157 |
|
158 // --------------------------------------------------------------------------- |
|
159 // |
|
160 // --------------------------------------------------------------------------- |
|
161 TFloatFixPt CSvgTextAreaElementImpl::Rx() |
|
162 { |
|
163 if (!iInitialized) |
|
164 { |
|
165 return 0; |
|
166 } |
|
167 |
|
168 return iBorderRectangle->Rx(); |
|
169 } |
|
170 |
|
171 // --------------------------------------------------------------------------- |
|
172 // |
|
173 // --------------------------------------------------------------------------- |
|
174 TFloatFixPt CSvgTextAreaElementImpl::Ry() |
|
175 { |
|
176 if (!iInitialized) |
|
177 { |
|
178 return 0; |
|
179 } |
|
180 |
|
181 return iBorderRectangle->Ry(); |
|
182 } |
|
183 |
|
184 // --------------------------------------------------------------------------- |
|
185 // |
|
186 // --------------------------------------------------------------------------- |
|
187 TBool CSvgTextAreaElementImpl::IsEditable() |
|
188 { |
|
189 return iEditable; |
|
190 } |
|
191 |
|
192 |
|
193 // --------------------------------------------------------------------------- |
|
194 // For JSR support |
|
195 // --------------------------------------------------------------------------- |
|
196 void CSvgTextAreaElementImpl::SetTextAreaDimensions(TFloatFixPt aX, TFloatFixPt aY, TFloatFixPt aWidth, TFloatFixPt aHeight) |
|
197 { |
|
198 if (!iInitialized) |
|
199 { |
|
200 TRAPD(err, InitializeL()); |
|
201 if (err) |
|
202 { |
|
203 #ifdef _DEBUG |
|
204 _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in InitializeL()" ); |
|
205 RDebug::Print(KErrMsg); |
|
206 #endif //_DEBUG |
|
207 } |
|
208 } |
|
209 |
|
210 TRAPD(err, iBorderRectangle->SetAttributeFloatL(KAtrX, aX)); |
|
211 if (err) |
|
212 { |
|
213 #ifdef _DEBUG |
|
214 _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" ); |
|
215 RDebug::Print(KErrMsg); |
|
216 #endif //_DEBUG |
|
217 } |
|
218 |
|
219 TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrY, aY)); |
|
220 if (err) |
|
221 { |
|
222 #ifdef _DEBUG |
|
223 _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" ); |
|
224 RDebug::Print(KErrMsg); |
|
225 #endif //_DEBUG |
|
226 } |
|
227 |
|
228 TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrWidth, aWidth)); |
|
229 if (err) |
|
230 { |
|
231 #ifdef _DEBUG |
|
232 _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" ); |
|
233 RDebug::Print(KErrMsg); |
|
234 #endif //_DEBUG |
|
235 } |
|
236 |
|
237 TRAP(err, iBorderRectangle->SetAttributeFloatL(KAtrHeight, aHeight)); |
|
238 if (err) |
|
239 { |
|
240 #ifdef _DEBUG |
|
241 _LIT( KErrMsg, "CSvgTextAreaElementImpl::SetTextAreaDimensions Error in SetAttributeFloatL" ); |
|
242 RDebug::Print(KErrMsg); |
|
243 #endif //_DEBUG |
|
244 } |
|
245 } |
|
246 |
|
247 // From MXmlElementOpt |
|
248 // --------------------------------------------------------------------------- |
|
249 // |
|
250 // --------------------------------------------------------------------------- |
|
251 TInt CSvgTextAreaElementImpl::GetAttributeFloat( const TInt aNameId, |
|
252 TFloatFixPt& aValue ) |
|
253 { |
|
254 if (!iInitialized) |
|
255 { |
|
256 TRAPD(err, InitializeL()); |
|
257 if (err) |
|
258 { |
|
259 #ifdef _DEBUG |
|
260 _LIT( KErrMsg, "CSvgTextAreaElementImpl::GetAttributeFloat Error in InitializeL()" ); |
|
261 RDebug::Print(KErrMsg); |
|
262 #endif //_DEBUG |
|
263 } |
|
264 } |
|
265 |
|
266 switch ( aNameId ) |
|
267 { |
|
268 case KAtrX: |
|
269 case KAtrRefX: |
|
270 aValue = X(); |
|
271 break; |
|
272 case KAtrY: |
|
273 case KAtrRefY: |
|
274 aValue = Y(); |
|
275 break; |
|
276 case KAtrWidth: |
|
277 aValue = Width(); |
|
278 break; |
|
279 case KAtrHeight: |
|
280 aValue = Height(); |
|
281 break; |
|
282 // added as a part of get and Set api updation |
|
283 case KAtrRx: |
|
284 aValue = Rx(); |
|
285 break; |
|
286 case KAtrRy: |
|
287 aValue = Ry(); |
|
288 break; |
|
289 default: |
|
290 return CSvgElementImpl::GetAttributeFloat( aNameId, aValue ); |
|
291 } |
|
292 return KErrNone; |
|
293 } |
|
294 |
|
295 // --------------------------------------------------------------------------- |
|
296 // |
|
297 // --------------------------------------------------------------------------- |
|
298 TInt CSvgTextAreaElementImpl::SetAttributeFloatL( const TInt aNameId, |
|
299 const TFloatFixPt aValue ) |
|
300 { |
|
301 if (!iInitialized) |
|
302 { |
|
303 InitializeL(); |
|
304 } |
|
305 |
|
306 switch ( aNameId ) |
|
307 { |
|
308 case KAtrX: |
|
309 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
310 iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2)); |
|
311 break; |
|
312 case KAtrY: |
|
313 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
314 iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2)); |
|
315 break; |
|
316 case KAtrRx: |
|
317 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
318 //iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2)); |
|
319 break; |
|
320 case KAtrRy: |
|
321 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
322 //iInnerRectangle->SetAttributeFloatL(aNameId, aValue+TFloatFixPt(2)); |
|
323 break; |
|
324 case KAtrWidth: |
|
325 if(iReqAttrFlag == KAtrSVGRec) |
|
326 { |
|
327 iReqAttrFlag = KAtrHeight; |
|
328 } |
|
329 else |
|
330 { |
|
331 iReqAttrFlag = 0; |
|
332 } |
|
333 |
|
334 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
335 iInnerRectangle->SetAttributeFloatL(aNameId, aValue-TFloatFixPt(4)); |
|
336 break; |
|
337 |
|
338 case KAtrHeight: |
|
339 if(iReqAttrFlag == KAtrSVGRec) |
|
340 { |
|
341 iReqAttrFlag = KAtrWidth; |
|
342 } |
|
343 else |
|
344 { |
|
345 iReqAttrFlag = 0; |
|
346 } |
|
347 iBorderRectangle->SetAttributeFloatL(aNameId, aValue); |
|
348 iInnerRectangle->SetAttributeFloatL(aNameId, aValue-TFloatFixPt(4)); |
|
349 break; |
|
350 default: |
|
351 return CSvgElementImpl::SetAttributeFloatL( aNameId, aValue ); |
|
352 } |
|
353 return KErrNone; |
|
354 } |
|
355 |
|
356 |
|
357 // ******************************************************* |
|
358 // From MXmlElement |
|
359 // --------------------------------------------------------------------------- |
|
360 // |
|
361 // --------------------------------------------------------------------------- |
|
362 TInt CSvgTextAreaElementImpl::SetAttributeL( const TDesC& aName, |
|
363 const TDesC& aValue ) |
|
364 { |
|
365 if (!iInitialized) |
|
366 { |
|
367 InitializeL(); |
|
368 } |
|
369 |
|
370 CSvgElementImpl::SetAttributeL(aName,aValue); |
|
371 return KErrNone; |
|
372 } |
|
373 |
|
374 // --------------------------------------------------------------------------- |
|
375 // |
|
376 // --------------------------------------------------------------------------- |
|
377 TInt CSvgTextAreaElementImpl::GetAttributeDes( const TInt aNameId, TPtrC16& aValue ) |
|
378 { |
|
379 if (!iInitialized) |
|
380 { |
|
381 return KErrNone; |
|
382 } |
|
383 |
|
384 switch ( aNameId ) |
|
385 { |
|
386 case KAtrCdata: |
|
387 aValue.Set(*iAllText); |
|
388 break; |
|
389 default: |
|
390 return CSvgElementImpl::GetAttributeDes( aNameId, aValue ); |
|
391 } |
|
392 return KErrNone; |
|
393 } |
|
394 // --------------------------------------------------------------------------- |
|
395 // |
|
396 // --------------------------------------------------------------------------- |
|
397 TInt CSvgTextAreaElementImpl::SetAttributeDesL( const TInt aNameId, |
|
398 const TDesC& aValue ) |
|
399 { |
|
400 switch ( aNameId ) |
|
401 { |
|
402 case KAtrCdata: |
|
403 SetTextL( aValue ); |
|
404 break; |
|
405 |
|
406 default: |
|
407 return CSvgElementImpl::SetAttributeDesL( aNameId, aValue ); |
|
408 } |
|
409 return KErrNone; |
|
410 } |
|
411 |
|
412 |
|
413 // --------------------------------------------------------------------------- |
|
414 // |
|
415 // --------------------------------------------------------------------------- |
|
416 void CSvgTextAreaElementImpl::SetEditable( const TDesC& aValue ) |
|
417 { |
|
418 if (aValue.FindF(_L("simple")) == KErrNotFound && aValue.FindF(_L("true")) == KErrNotFound) |
|
419 { |
|
420 iEditable = EFalse; |
|
421 } |
|
422 else |
|
423 { |
|
424 iEditable = ETrue; |
|
425 } |
|
426 } |
|
427 |
|
428 // --------------------------------------------------------------------------- |
|
429 // |
|
430 // --------------------------------------------------------------------------- |
|
431 void CSvgTextAreaElementImpl::LocalizedArrangeTextL( CGfx2dGc* /* aGc */ ) |
|
432 { |
|
433 if (!iInitialized) |
|
434 { |
|
435 return; |
|
436 } |
|
437 |
|
438 //every time we call arrange text we will clear the previous text elements |
|
439 //very expensive but easiest way to do this |
|
440 if (iTextElementsArray) |
|
441 { |
|
442 TInt textEleArrayCnt = iTextElementsArray->Count(); |
|
443 for (TInt i=0; i < textEleArrayCnt; i++) |
|
444 { |
|
445 this->RemoveChild( iTextElementsArray->operator[](i) ); |
|
446 delete iTextElementsArray->operator[](i); |
|
447 } |
|
448 |
|
449 iTextElementsArray->Reset(); |
|
450 } |
|
451 // If there is some text in the text area, we need to do the following operations |
|
452 // a. calculate number of lines that can fit in the inner rectangle of textArea |
|
453 // i. For this we need to get the dimension of Inner Rectangle |
|
454 // ii. Then get the font corresponding to the current scale. This is obtained |
|
455 // by creating a dummy text element and updating its CTM. |
|
456 // |
|
457 if (iAllText && iAllText->Length() > 0) |
|
458 { |
|
459 TFloatFixPt lInnerRectWidthF, lInnerRectHeightF; |
|
460 iInnerRectangle->GetAttributeFloat( KAtrWidth, lInnerRectWidthF ); |
|
461 iInnerRectangle->GetAttributeFloat( KAtrHeight, lInnerRectHeightF ); |
|
462 |
|
463 // Create a dummy text element to obtain the font |
|
464 CSvgTextElementImpl* lTextElement = |
|
465 (CSvgTextElementImpl*)iOwnerDocument->CreateElementL(KSvgTextElement); |
|
466 CleanupStack::PushL(lTextElement); |
|
467 lTextElement->SetAttributeDesL(KAtrCdata,iAllText->Des()); |
|
468 |
|
469 this->AppendChildL(lTextElement); |
|
470 CleanupStack::Pop(lTextElement); |
|
471 lTextElement->UpdateCTM(); |
|
472 // Update the text element's font corresponding to the CTM. |
|
473 lTextElement->UpdateCurrentScaledFont(); |
|
474 |
|
475 TFloatFixPt lScale = GetCurrentScale(); |
|
476 |
|
477 //Taken the widest charactor to check against the dimensions of the text area. |
|
478 //There is no point in going futher, If the area of text area elelment |
|
479 //is not big enough to fit the single char, |
|
480 TChar ch('W'); |
|
481 if ( lScale == TFloatFixPt( 0 ) || |
|
482 ((TReal32)( lInnerRectWidthF * lScale)) < lTextElement->Font()->CharWidthInPixels( ch ) || |
|
483 ((TReal32)( lInnerRectHeightF * lScale)) < lTextElement->Font()->FontMaxHeight()) |
|
484 { |
|
485 // Scale = 0 , means no drawing will take place. |
|
486 // Cleanup the text element |
|
487 this->RemoveChild(lTextElement); |
|
488 delete lTextElement; |
|
489 lTextElement = NULL; |
|
490 return; |
|
491 } |
|
492 |
|
493 // Store the current font's ascent and descent |
|
494 TInt lTextAscent = lTextElement->Font()->FontMaxAscent(); |
|
495 TInt lTextDescent = lTextElement->Font()->FontMaxDescent(); |
|
496 |
|
497 TReal32 lTextHeight = lTextAscent + lTextDescent; |
|
498 |
|
499 if (lTextHeight == 0) |
|
500 { |
|
501 //no text height so we need to not draw the text |
|
502 this->RemoveChild(lTextElement); |
|
503 delete lTextElement; |
|
504 lTextElement = NULL; |
|
505 return; |
|
506 } |
|
507 |
|
508 // Calculate gap between two consecutive lines of text |
|
509 // CFont provides FontLineGap() which is Font Height + Line Gap |
|
510 |
|
511 TInt lLineGap = lTextElement->Font()->FontLineGap(); |
|
512 // Number of lines of text |
|
513 TInt lNumOflines = (TReal32)( lInnerRectHeightF * lScale)/( lLineGap ) ; |
|
514 |
|
515 if( lNumOflines < 1) |
|
516 { |
|
517 //text is taller than the rectangle |
|
518 this->RemoveChild(lTextElement); |
|
519 delete lTextElement; |
|
520 lTextElement = NULL; |
|
521 return; |
|
522 } |
|
523 // Create a list of line widths and line texts to use with ConvertToVisualAndWrapToArrayL |
|
524 CArrayFixFlat<TInt>* lLineWidthArray = new ( ELeave ) CArrayFixFlat<TInt>( lNumOflines ); |
|
525 CleanupStack::PushL(lLineWidthArray); |
|
526 |
|
527 //one px offset is taken on Left & right ends w.r. to inner rect width. |
|
528 lLineWidthArray->AppendL((TInt)( lInnerRectWidthF * lScale ) - 2,lNumOflines); |
|
529 |
|
530 CArrayFixFlat< TPtrC >* lWrappedArray = new ( ELeave ) CArrayFixFlat<TPtrC>( lLineWidthArray->Count() ); |
|
531 |
|
532 CleanupStack::PushL(lWrappedArray); |
|
533 |
|
534 //ConvertToVisualAndWrapToArrayL requires KAknBidiExtraSpacePerLine. |
|
535 //Refer the help of AknBidiTextUtils::ConvertToVisualAndWrapToArrayL |
|
536 HBufC *lBuf = HBufC::NewLC(iAllText->Length() + (lNumOflines) * KAknBidiExtraSpacePerLine); |
|
537 |
|
538 TPtr buf = lBuf->Des(); |
|
539 buf.Copy(iAllText->Des()); |
|
540 // Below API fills the lWrappedArray with the lines of text. If no space |
|
541 // is available in textArea, then trailing ellipsis(...) will be displayed. |
|
542 AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(buf, *lLineWidthArray, |
|
543 *lTextElement->iBitmapFont, *lWrappedArray, ETrue); |
|
544 |
|
545 // Dummy text element is no longer required. |
|
546 this->RemoveChild(lTextElement); |
|
547 delete lTextElement; |
|
548 lTextElement = NULL; |
|
549 |
|
550 // Calculating the y offset for first line of text. |
|
551 // Text is positioned wrt font baseline, hence the position = |
|
552 // Inner Rectangle 's Y Coordinate + Unscaled Font Ascent |
|
553 // The scaling will be taken care of by UpdateCTM on the text elements. |
|
554 TInt lTextCurrentY = TReal32(iInnerRectangle->Y()) + (lTextAscent / (TReal32)lScale ); |
|
555 TInt lWrappedArrayCnt = lWrappedArray->Count(); |
|
556 |
|
557 // lWrappedArrayCnt is guaranteed to be less than lNumOfLines. |
|
558 // This loop creates Text elements as many as elements in lWrapppedArray. |
|
559 // These elements are appended as child to the text area. |
|
560 for( TInt i=0; i < lWrappedArrayCnt ; i++) |
|
561 { |
|
562 lTextElement = (CSvgTextElementImpl*)iOwnerDocument->CreateElementL(KSvgTextElement); |
|
563 CleanupStack::PushL( lTextElement ); |
|
564 iTextElementsArray->Append(lTextElement); |
|
565 |
|
566 TPtrC lineText = lWrappedArray->At(i); |
|
567 lTextElement->SetAttributeDesL(KAtrCdata,lineText); |
|
568 |
|
569 //Text positioned from the inner rectangle's X- coordinate + 1 pixel gap |
|
570 lTextElement->SetAttributeFloatL(KAtrX, TFloatFixPt(iInnerRectangle->X() + TFloatFixPt(1))); |
|
571 |
|
572 //need to set the next text element up to go down the height here too... |
|
573 lTextElement->SetAttributeFloatL(KAtrY, TFloatFixPt(lTextCurrentY)); |
|
574 |
|
575 lTextElement->SetAttributeFloatL(KAtrWidth, TFloatFixPt(iInnerRectangle->Width() - TFloatFixPt(2))); |
|
576 lTextElement->SetAttributeFloatL(KAtrHeight, lTextHeight); |
|
577 |
|
578 this->AppendChildL(lTextElement); |
|
579 |
|
580 lTextElement->UpdateCTM(); |
|
581 lTextElement->UpdateCurrentScaledFont(); |
|
582 |
|
583 //The subsequent position calculated as lTextHeight( Ascent + descent ) / unscaled line gap |
|
584 lTextCurrentY += (TInt)(( lLineGap )/(TReal32)lScale); |
|
585 |
|
586 CleanupStack::Pop( lTextElement ); |
|
587 } |
|
588 |
|
589 //delete lBuf; |
|
590 CleanupStack::PopAndDestroy(lBuf); |
|
591 CleanupStack::Pop(lWrappedArray); |
|
592 delete lWrappedArray; |
|
593 CleanupStack::Pop(lLineWidthArray); |
|
594 delete lLineWidthArray; |
|
595 |
|
596 } |
|
597 } |
|
598 // --------------------------------------------------------------------------- |
|
599 // |
|
600 // --------------------------------------------------------------------------- |
|
601 TInt CSvgTextAreaElementImpl::GetLength() |
|
602 { |
|
603 return iAllText->Length(); |
|
604 } |
|
605 |
|
606 // --------------------------------------------------------------------------- |
|
607 // |
|
608 // --------------------------------------------------------------------------- |
|
609 void CSvgTextAreaElementImpl::GetText( TDes& allText ) |
|
610 { |
|
611 if ( iAllText ) |
|
612 { |
|
613 if ( allText.MaxLength() < iAllText->Length() ) |
|
614 { |
|
615 allText = iAllText->Left( allText.MaxLength() ); |
|
616 } |
|
617 else |
|
618 { |
|
619 allText = *iAllText; |
|
620 } |
|
621 } |
|
622 } |
|
623 |
|
624 // --------------------------------------------------------------------------- |
|
625 // |
|
626 // --------------------------------------------------------------------------- |
|
627 void CSvgTextAreaElementImpl::SetTextL( const TDesC& aText ) |
|
628 { |
|
629 |
|
630 _LIT( KPreserve, "preserve" ); |
|
631 _LIT( KDefault, "default"); |
|
632 if ( iAllText ) |
|
633 { |
|
634 delete iAllText; |
|
635 iAllText = NULL; |
|
636 } |
|
637 |
|
638 iAllText = aText.AllocL(); |
|
639 TPtr textDes = iAllText->Des(); |
|
640 TBool def = ETrue; |
|
641 |
|
642 // Get the xml:space value. |
|
643 TBuf<20> lXmlspace; |
|
644 |
|
645 if(XMLSpace() == KPreserve) |
|
646 { |
|
647 lXmlspace=KPreserve; |
|
648 def=EFalse; |
|
649 } |
|
650 else if(XMLSpace() == KDefault) |
|
651 { |
|
652 lXmlspace=KDefault; |
|
653 } |
|
654 // xml:space is inherited if not specified |
|
655 if ( lXmlspace!= KPreserve && lXmlspace != KDefault) |
|
656 { |
|
657 // Traverse to the nearest parent element which has the xml:space |
|
658 // If no xml:space then render using xml:space="default" |
|
659 CSvgElementImpl *lRoot=(CSvgElementImpl *)this->ParentNode(); |
|
660 while(lRoot) |
|
661 { |
|
662 if ((lRoot->XMLSpace() == KPreserve)) |
|
663 { |
|
664 def = EFalse; |
|
665 break; |
|
666 } |
|
667 else if(lRoot->XMLSpace()==KDefault) |
|
668 { |
|
669 break; |
|
670 } |
|
671 lRoot=(CSvgElementImpl *)lRoot->ParentNode(); |
|
672 } |
|
673 } |
|
674 |
|
675 _LIT(KSpace, " "); |
|
676 // default |
|
677 if ( def && lXmlspace != KPreserve ) |
|
678 { |
|
679 |
|
680 // Remove leading, trailing and contiguous spaces |
|
681 textDes.TrimAll(); |
|
682 |
|
683 for (TInt i = textDes.Length() - 1; i >= 0; i--) |
|
684 { |
|
685 |
|
686 // Remove new line character |
|
687 if (textDes[i] == '\n') |
|
688 { |
|
689 textDes.Delete(i,1); |
|
690 } |
|
691 |
|
692 // Tab to be replaced with space. |
|
693 if(textDes[i] == '\t') |
|
694 { |
|
695 textDes.Replace(i,1,KSpace); |
|
696 } |
|
697 } |
|
698 } |
|
699 // preserve |
|
700 else |
|
701 { |
|
702 |
|
703 for ( TInt i = 0; i < textDes.Length(); i++ ) |
|
704 { |
|
705 // ms-dos carriage return contains two characters: 13, 10 |
|
706 const TInt KCarriageReturn1 = 13; |
|
707 const TInt KCarriageReturn2 = 10; |
|
708 |
|
709 if ( i + 1 < textDes.Length() && |
|
710 (TInt)textDes[i] == KCarriageReturn1 && |
|
711 (TInt)textDes[i+1] == KCarriageReturn2 ) |
|
712 { |
|
713 textDes[i] = ' '; |
|
714 textDes.Delete( i+1, 1 ); |
|
715 } |
|
716 |
|
717 // New line and tab should be replaced by space character. |
|
718 if (textDes[i] == '\n' ||textDes[i] == '\t') |
|
719 { |
|
720 textDes.Replace(i,1, KSpace); |
|
721 } |
|
722 } |
|
723 } |
|
724 |
|
725 iNeedTextRearrange = ETrue; |
|
726 |
|
727 } |
|
728 |
|
729 // --------------------------------------------------------------------------- |
|
730 // |
|
731 // --------------------------------------------------------------------------- |
|
732 void CSvgTextAreaElementImpl::InitializeL() |
|
733 { |
|
734 if (!iBorderRectangle && !iInnerRectangle) |
|
735 { |
|
736 iBorderRectangle = CSvgRectElementImpl::NewL(KSvgRectElement, (CSvgDocumentImpl*)iOwnerDocument); |
|
737 this->AppendChildL(iBorderRectangle); |
|
738 iInnerRectangle = CSvgRectElementImpl::NewL(KSvgRectElement, (CSvgDocumentImpl*)iOwnerDocument); |
|
739 this->AppendChildL(iInnerRectangle); |
|
740 |
|
741 iInnerRectangle->SetAttributeFloatL(KAtrRx, 2); |
|
742 iInnerRectangle->SetAttributeFloatL(KAtrRy, 2); |
|
743 iInnerRectangle->SetPropertyL(KCSS_ATTR_FILL, _L("none")); |
|
744 iInnerRectangle->SetPropertyL(KCSS_ATTR_STROKEWIDTH, _L(".02")); |
|
745 iInnerRectangle->SetPropertyL(KCSS_ATTR_STROKE, _L("black")); |
|
746 |
|
747 iBorderRectangle->SetAttributeFloatL(KAtrRx, 2); |
|
748 iBorderRectangle->SetAttributeFloatL(KAtrRy, 2); |
|
749 iBorderRectangle->SetPropertyL(KCSS_ATTR_FILL, _L("none")); |
|
750 iBorderRectangle->SetPropertyL(KCSS_ATTR_STROKEWIDTH, _L(".1")); |
|
751 iBorderRectangle->SetPropertyL(KCSS_ATTR_STROKE, _L("black")); |
|
752 |
|
753 iInitialized = ETrue; |
|
754 } |
|
755 } |
|
756 |
|
757 // --------------------------------------------------------------------------- |
|
758 // |
|
759 // --------------------------------------------------------------------------- |
|
760 TBool CSvgTextAreaElementImpl::DrawL( CGfx2dGc* aGc, CSvgElementImpl* aElement ) |
|
761 { |
|
762 if (iBorderRectangle->Width() <= TFloatFixPt(0) || iBorderRectangle->Height() <= TFloatFixPt(0)) |
|
763 { |
|
764 return ETrue; |
|
765 } |
|
766 |
|
767 TFloatFixPt scale = GetCurrentScale(); |
|
768 TFloatFixPt width = iInnerRectangle->Width() * scale; |
|
769 TFloatFixPt height = iInnerRectangle->Height() * scale; |
|
770 |
|
771 if ( width != iLastBBox.iWidth || height != iLastBBox.iHeight ) |
|
772 { |
|
773 iNeedTextRearrange = ETrue; |
|
774 iLastBBox.iWidth = width; |
|
775 iLastBBox.iHeight = height; |
|
776 } |
|
777 |
|
778 DrawTextElements( aGc, aElement ); |
|
779 |
|
780 return ETrue; |
|
781 } |
|
782 |
|
783 // --------------------------------------------------------------------------- |
|
784 // |
|
785 // --------------------------------------------------------------------------- |
|
786 TBool CSvgTextAreaElementImpl::DrawTextElements( CGfx2dGc* aGc, CSvgElementImpl* /*aElement*/ ) |
|
787 { |
|
788 //draw text elements...readjust their positions according the width and height of the inner rectangle... |
|
789 if (iNeedTextRearrange) |
|
790 { |
|
791 //TRAPD(err, ArrangeTextL(aGc)); |
|
792 TRAPD(err, LocalizedArrangeTextL(aGc)); |
|
793 if (err) |
|
794 { |
|
795 #ifdef _DEBUG |
|
796 _LIT( KErrMsg, "CSvgTextAreaElementImpl::DrawTextElements Error in ArrangeTextL()" ); |
|
797 RDebug::Print(KErrMsg); |
|
798 #endif //_DEBUG |
|
799 } |
|
800 |
|
801 iNeedTextRearrange = EFalse; |
|
802 } |
|
803 |
|
804 //draw text until it reaches the inner border then start a new text element on the next line down |
|
805 /*if (iTextElementsArray) |
|
806 { |
|
807 for (int i=0; i < iTextElementsArray->Count(); i++) |
|
808 { |
|
809 //draw text elements here... |
|
810 TRAPD(err, iTextElementsArray->operator[](i)->DrawL(aGc, aElement)); |
|
811 if (err) |
|
812 { |
|
813 #ifdef _DEBUG |
|
814 _LIT( KErrMsg, "CSvgTextAreaElementImpl::DrawTextElements Error in DrawL()" ); |
|
815 RDebug::Print(KErrMsg); |
|
816 #endif //_DEBUG |
|
817 } |
|
818 |
|
819 } |
|
820 }*/ |
|
821 |
|
822 return ETrue; |
|
823 } |
|
824 // --------------------------------------------------------------------------- |
|
825 // |
|
826 // --------------------------------------------------------------------------- |
|
827 void CSvgTextAreaElementImpl::ConstructL( const TUint8 aElemID ) |
|
828 { |
|
829 CSvgElementImpl::InitializeL( aElemID ); |
|
830 |
|
831 iSvgStyleProperties = new(ELeave) RPointerArray<CCssValue>(KCSS_MAX_ATTR ); |
|
832 |
|
833 User::LeaveIfError( iSvgStyleProperties->Append( NULL ) ); |
|
834 iSvgStyleProperties->Remove( 0 ); |
|
835 |
|
836 iTextElementsArray = new (ELeave)RPointerArray<CSvgTextElementImpl> (1); |
|
837 iTextElementsArray->Reset(); |
|
838 |
|
839 iSvgTransformable = CSvgTransformableImpl::NewL(); |
|
840 |
|
841 iReqAttrFlag=KSVG_RECT_ELEMFLAG; |
|
842 |
|
843 iBorderRectangle = NULL; |
|
844 iInnerRectangle = NULL; |
|
845 |
|
846 iNeedTextRearrange = ETrue; |
|
847 iInitialized = EFalse; |
|
848 |
|
849 iAllText = HBufC::NewL( 2 ); |
|
850 |
|
851 iEditable = EFalse; |
|
852 |
|
853 // Add this as internal event receiver |
|
854 //((CSvgDocumentImpl*)iOwnerDocument)->AddToEventReceiverListL( this, KSvgEventMaskExternalUI); |
|
855 |
|
856 ((CSvgDocumentImpl*)OwnerDocument())->AddInternalMouseListener( this ); |
|
857 |
|
858 } |
|
859 |
|
860 // --------------------------------------------------------------------------- |
|
861 // |
|
862 // --------------------------------------------------------------------------- |
|
863 |
|
864 CSvgTextAreaElementImpl::CSvgTextAreaElementImpl( CSvgDocumentImpl* aDoc ) |
|
865 { |
|
866 SetOwnerDocument(aDoc); |
|
867 } |
|
868 |
|
869 // --------------------------------------------------------------------------- |
|
870 // |
|
871 // --------------------------------------------------------------------------- |
|
872 void CSvgTextAreaElementImpl::GetBBox( TGfxRectangle2D& aBbox ) |
|
873 { |
|
874 if (!iInitialized) |
|
875 { |
|
876 TGfxRectangle2D myRect(0,0,0,0); |
|
877 aBbox = myRect; |
|
878 return; |
|
879 } |
|
880 |
|
881 iBorderRectangle->GetBBox( aBbox ); |
|
882 } |
|
883 |
|
884 // --------------------------------------------------------------------------- |
|
885 // |
|
886 // --------------------------------------------------------------------------- |
|
887 void CSvgTextAreaElementImpl::GetUnscaledBBox( TGfxRectangle2D& aBbox ) |
|
888 { |
|
889 if (!iInitialized) |
|
890 { |
|
891 TGfxRectangle2D myRect(0,0,0,0); |
|
892 aBbox = myRect; |
|
893 return; |
|
894 } |
|
895 |
|
896 iBorderRectangle->GetUnscaledBBox(aBbox); |
|
897 } |
|
898 |
|
899 // --------------------------------------------------------------------------- |
|
900 // perform a deep clone of this object |
|
901 // --------------------------------------------------------------------------- |
|
902 MXmlElement* CSvgTextAreaElementImpl::CloneL(MXmlElement* aParentElement) |
|
903 { |
|
904 // create new text area |
|
905 CSvgTextAreaElementImpl* newElement = CSvgTextAreaElementImpl::NewL( this->ElemID(), ((CSvgDocumentImpl*)iOwnerDocument) ); |
|
906 |
|
907 newElement->iParentNode = aParentElement; |
|
908 // copy everything over |
|
909 this->CopyL(newElement); |
|
910 |
|
911 return newElement; |
|
912 } |
|
913 |
|
914 // --------------------------------------------------------------------------- |
|
915 // perform a deep copy of this object |
|
916 // --------------------------------------------------------------------------- |
|
917 void CSvgTextAreaElementImpl::CopyL( CSvgTextAreaElementImpl* aDestElement ) |
|
918 { |
|
919 // copy stuff from superclass |
|
920 this->CSvgElementImpl::CopyL(aDestElement); |
|
921 |
|
922 // copy iRectangle items special to circle |
|
923 aDestElement->iBorderRectangle = (CSvgRectElementImpl*)iBorderRectangle->CloneL((MXmlElement*)iBorderRectangle); |
|
924 aDestElement->iInnerRectangle = (CSvgRectElementImpl*)iInnerRectangle->CloneL((MXmlElement*)iInnerRectangle); |
|
925 |
|
926 if (iTextElementsArray) |
|
927 { |
|
928 TInt textEleArrayCnt = iTextElementsArray->Count(); |
|
929 for (int i=0; i < textEleArrayCnt; i++) |
|
930 { |
|
931 aDestElement->iTextElementsArray->Append((CSvgTextElementImpl*)iTextElementsArray->operator[](i)->CloneL((MXmlElement*)iTextElementsArray->operator[](i))); |
|
932 } |
|
933 } |
|
934 |
|
935 // copy the reference to idoc (CSvgDocumentImpl) |
|
936 aDestElement->iOwnerDocument = this->iOwnerDocument; |
|
937 } |
|
938 |
|
939 /*** FROM MSvgMouseListener ***/ |
|
940 // --------------------------------------------------------------------------- |
|
941 // mouse entered |
|
942 // --------------------------------------------------------------------------- |
|
943 TBool CSvgTextAreaElementImpl::MouseEntered( RPointerArray<CSvgElementImpl>& aElements, |
|
944 TInt /*aX*/, TInt /*aY*/ ) |
|
945 { |
|
946 CSvgEngineImpl* engine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); |
|
947 |
|
948 TInt eleCnt = aElements.Count(); |
|
949 for (TInt i = 0; i < eleCnt; i++ ) |
|
950 { |
|
951 if ( aElements[i] == this ) |
|
952 { |
|
953 engine->NotifyTextAreaEntered(this); |
|
954 return ETrue; |
|
955 } |
|
956 } |
|
957 |
|
958 return EFalse; |
|
959 } |
|
960 |
|
961 // --------------------------------------------------------------------------- |
|
962 // Notified when the mouse pointer exits a visible svg element. |
|
963 // --------------------------------------------------------------------------- |
|
964 TBool CSvgTextAreaElementImpl::MouseExited( RPointerArray<CSvgElementImpl>& aElements, |
|
965 TInt /*aX*/, TInt /*aY*/ ) |
|
966 { |
|
967 CSvgEngineImpl* lEngine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); |
|
968 |
|
969 TInt eleCnt = aElements.Count(); |
|
970 for (TInt i = 0; i < eleCnt; i++ ) |
|
971 { |
|
972 if ( aElements[i] == this ) |
|
973 { |
|
974 lEngine->NotifyTextAreaExited(this); |
|
975 return ETrue; |
|
976 } |
|
977 } |
|
978 |
|
979 return EFalse; |
|
980 } |
|
981 |
|
982 // --------------------------------------------------------------------------- |
|
983 // Notified when the mouse pointer is pressed down on visible svg element. |
|
984 // --------------------------------------------------------------------------- |
|
985 TBool CSvgTextAreaElementImpl::MouseMoved( RPointerArray<CSvgElementImpl>& /*aElements*/, |
|
986 TInt /*aX*/, TInt /*aY*/ ) |
|
987 { |
|
988 return EFalse; |
|
989 } |
|
990 // --------------------------------------------------------------------------- |
|
991 // Notified when the mouse pointer is pressed down on visible svg element. |
|
992 // --------------------------------------------------------------------------- |
|
993 TBool CSvgTextAreaElementImpl::MousePressed( RPointerArray<CSvgElementImpl>& /*aElements*/, |
|
994 TInt /*aX*/, TInt /*aY*/ ) |
|
995 { |
|
996 return EFalse; |
|
997 } |
|
998 |
|
999 // --------------------------------------------------------------------------- |
|
1000 // Notified when the mouse pointer is released on on visible svg element. |
|
1001 // --------------------------------------------------------------------------- |
|
1002 TBool CSvgTextAreaElementImpl::MouseReleased( RPointerArray<CSvgElementImpl>& aElements, |
|
1003 TInt /*aX*/, TInt /*aY*/ ) |
|
1004 { |
|
1005 CSvgEngineImpl* lEngine = ( ( CSvgDocumentImpl* ) OwnerDocument() )->Engine(); |
|
1006 |
|
1007 TInt eleCnt = aElements.Count(); |
|
1008 for (TInt i = 0; i < eleCnt; i++ ) |
|
1009 { |
|
1010 if ( aElements[i] == this ) |
|
1011 { |
|
1012 lEngine->NotifyTextAreaActivated(this); |
|
1013 return ETrue; |
|
1014 } |
|
1015 } |
|
1016 |
|
1017 return EFalse; |
|
1018 } |
|
1019 |
|
1020 // --------------------------------------------------------------------------- |
|
1021 // void CSvgTextAreaElementImpl::Print() |
|
1022 // --------------------------------------------------------------------------- |
|
1023 void CSvgTextAreaElementImpl::Print( TBool aIsEncodeOn ) |
|
1024 { |
|
1025 if (!aIsEncodeOn) |
|
1026 { |
|
1027 #ifdef _DEBUG |
|
1028 RDebug::Printf("<textarea x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" editable=\"%d\" >hmm</textarea>", (int)X(), (int)Y(), (int)Width(), (int)Height(), (int)iEditable/*, iAllText*/); |
|
1029 #endif |
|
1030 } |
|
1031 } |