webengine/wmlengine/src/gdi/src/GDIDeviceContext.cpp
changeset 74 91031d3aab7d
parent 68 92a765b5b3e7
child 85 e358f2276d3f
equal deleted inserted replaced
68:92a765b5b3e7 74:91031d3aab7d
     1 /*
       
     2 * Copyright (c) 2002-2004 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 the License "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:  device context
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32def.h>  // First to avoid NULL redefine warning (no #ifndef NULL).
       
    21 #include "GDIDevicecontext.h"
       
    22 #include "nw_object_dynamici.h"
       
    23 #include "GDIFont.h"
       
    24 #include "nw_gdi_utils.h"
       
    25 #include "nw_text_ucs2.h"
       
    26 #include <nwx_string.h>
       
    27 #include <nwx_settings.h>
       
    28 #include "nwx_logger.h"
       
    29 #include "nwx_http_defs.h"
       
    30 #include "MVCView.h"
       
    31 #include <AknUtils.h>
       
    32 #include <gdi.h>
       
    33 #include <w32std.h>
       
    34 #include <eikenv.h>
       
    35 #include <barsread.h>
       
    36 #include <gulutil.h>
       
    37 #include <bautils.h>
       
    38 #include <webkit.rsg>
       
    39 #include <AknPictographInterface.h>
       
    40 #include <AknPictographDrawerInterface.h>
       
    41 #include <biditext.h>
       
    42 #include "BrsrStatusCodes.h"
       
    43 #include "featmgr.h"
       
    44 #include <AknFontAccess.h>
       
    45 
       
    46 #include <bldvariant.hrh>
       
    47 #include <data_caging_path_literals.hrh>
       
    48 #include "MemoryManager.h"
       
    49 
       
    50 // EXTERNAL DATA STRUCTURES
       
    51 
       
    52 // EXTERNAL FUNCTION PROTOTYPES
       
    53 
       
    54 // CONSTANTS
       
    55 
       
    56 /*
       
    57  The Thai language is unique in that it has certain characters that combine
       
    58  into a single entity that will be referred to as a Thai script "cell" or just
       
    59  "cell" for short.  Furthermore, the language uses white space very sparingly,
       
    60  frequently not having any space at all between individual words. These unique
       
    61  features create additional complexity when truncating or word-wrapping Thai
       
    62  text.
       
    63 
       
    64  Truncation should not occur in the middle of a "cell" if possible. The
       
    65  exception is if all that remains to be displayed is a single cell but
       
    66  there isn't space for the entire cell.
       
    67 
       
    68  As for word-wrapping, in optimal case, Thai text ought to be broken into lines
       
    69  at word boundaries. However, because white space is seldom used, word
       
    70  boundaries cannot be found unless a dictionary or a heavy statistical/
       
    71  morphological analysis is run on the text. Therefore, a less perfect approach
       
    72  is used.
       
    73 
       
    74  Line breaking is done according to Thai script "cells", which can be
       
    75  thought of as the smallest indivisible units of the script.
       
    76 
       
    77  The cells consist of combinations of characters from the following classes
       
    78  of characters, which are divided into two types -- spacing and combining:
       
    79    CONS  Consonant       (spacing)
       
    80    AD    Above Diacritic (combining)
       
    81    AV    Above Vowel     (combining)
       
    82    BD    Below Diacritic (combining)
       
    83    BV    Below Vowel     (combining)
       
    84    FV    Following Vowel (spacing)
       
    85    LV    Leading Vowel   (spacing)
       
    86    NON   Not a Thai letter, i.e. is a number, currency, etc (spacing)
       
    87    TONE  Tone mark       (combining)
       
    88 
       
    89  Graphically, the "cells" are built around a consonant, which functions as a
       
    90  base for a stack of combining elements, optionally preceded and/or followed
       
    91  by spacing vowels. The graph below illustrates how the bits and pieces of a
       
    92  cell are placed around the consonant:
       
    93 
       
    94              [TONE]
       
    95           [AV/AD/TONE]
       
    96 _______[LV]__[CONS]__[FV]________  (baseline)
       
    97             [BV/BD]
       
    98 
       
    99  In the encoded text, you can anticipate sequences like:
       
   100  ... [LV] [CONS] [AV/BV/AD/BD] [TONE] [FV] ...
       
   101 
       
   102  If such is a prototype of a Thai script "cell", lines can be split without
       
   103  interfering with the most crucial structures of the script
       
   104    * between subsequent [FV] and [LV]
       
   105    * between subsequent [CONS] and [LV]
       
   106    * between subsequent [AV/BV/AD/BD] and [LV]
       
   107    * between subsequent [TONE] and [LV]
       
   108    * between subsequent [CONS] and [CONS]
       
   109    * between subsequent [AV/BV/AD/BD] and [CONS]
       
   110    * between subsequent [TONE] and [CONS]
       
   111    * between subsequent [FV] and [CONS]
       
   112 
       
   113  This can be reduced to the following three rules:
       
   114    1. Splits can occur at whitespace.
       
   115    2. Splits can occur immediately preceding any LV.
       
   116    3. Splits can occur immediately preceding any CONS that is not
       
   117      immediately preceded by an LV.
       
   118 
       
   119  Unfortunately, this approach does not guarantee individual words, or even
       
   120  individual syllables, from being broken across lines. All that can be said is
       
   121  that the outer structure of the script is preserved - combining characters as
       
   122  well as the leading/following vowels stick with the base character.
       
   123 */
       
   124 
       
   125 // Thai unicode char range: 0x0E00 - 0x0E7F. Note, only the first 0x60
       
   126 // characters are used.
       
   127 #define THAI_CHAR_BASE 0x0E00
       
   128 // Charcter classes and types.
       
   129 #define THAI_CHAR_COMBINING_TYPE_FLAG 0x80
       
   130 #define THAI_CHAR_SPACING_TYPE_FLAG   0x40
       
   131 #define THAI_CHAR_CONS (1 | THAI_CHAR_SPACING_TYPE_FLAG)
       
   132 #define THAI_CHAR_AD   (2 | THAI_CHAR_COMBINING_TYPE_FLAG)
       
   133 #define THAI_CHAR_AV   (3 | THAI_CHAR_COMBINING_TYPE_FLAG)
       
   134 #define THAI_CHAR_BD   (4 | THAI_CHAR_COMBINING_TYPE_FLAG)
       
   135 #define THAI_CHAR_BV   (5 | THAI_CHAR_COMBINING_TYPE_FLAG)
       
   136 #define THAI_CHAR_FV   (6 | THAI_CHAR_SPACING_TYPE_FLAG)
       
   137 #define THAI_CHAR_LV   (7 | THAI_CHAR_SPACING_TYPE_FLAG)
       
   138 #define THAI_CHAR_NON  (8 | THAI_CHAR_SPACING_TYPE_FLAG)
       
   139 #define THAI_CHAR_TONE (9 | THAI_CHAR_COMBINING_TYPE_FLAG)
       
   140 
       
   141 // Map that defines the class and type for each Thai character.
       
   142 // Character range
       
   143 const TUint8 ThaiCharMap[0x60] =
       
   144     {
       
   145     // 0x0E00
       
   146     THAI_CHAR_NON,
       
   147     // 0x0E01 - 0x0E23
       
   148     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   149     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   150     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   151     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   152     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   153     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   154     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   155     // 0x0E24
       
   156     THAI_CHAR_FV,
       
   157     // 0x0E25
       
   158     THAI_CHAR_CONS,
       
   159     // 0x0E26
       
   160     THAI_CHAR_FV,
       
   161     // 0x0E27 - 0x0E2E
       
   162     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   163     THAI_CHAR_CONS, THAI_CHAR_CONS, THAI_CHAR_CONS,
       
   164     // 0x0E2F
       
   165     THAI_CHAR_NON,
       
   166     // 0x0E30
       
   167     THAI_CHAR_FV,
       
   168     // 0x0E31
       
   169     THAI_CHAR_AV,
       
   170     // 0x0E32 - 0x0E33
       
   171     THAI_CHAR_FV, THAI_CHAR_FV,
       
   172     // 0x0E34 - 0x0E37
       
   173     THAI_CHAR_AV, THAI_CHAR_AV, THAI_CHAR_AV, THAI_CHAR_AV,
       
   174     // 0x0E38 - 0x0E39
       
   175     THAI_CHAR_BV, THAI_CHAR_BV,
       
   176     // 0x0E3A
       
   177     THAI_CHAR_BD,
       
   178     // 0x0E3B - 0x0E3F
       
   179     THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON,
       
   180     // 0x0E40 - 0x0E44
       
   181     THAI_CHAR_LV, THAI_CHAR_LV, THAI_CHAR_LV, THAI_CHAR_LV, THAI_CHAR_LV,
       
   182     // 0x0E45
       
   183     THAI_CHAR_FV,
       
   184     // 0x0E46
       
   185     THAI_CHAR_NON,
       
   186     // 0x0E47
       
   187     THAI_CHAR_AD,
       
   188     // 0x0E48 - 0x0E4B
       
   189     THAI_CHAR_TONE, THAI_CHAR_TONE, THAI_CHAR_TONE, THAI_CHAR_TONE,
       
   190     // 0x0E4C - 0x0E4E
       
   191     THAI_CHAR_AD, THAI_CHAR_AD, THAI_CHAR_AD,
       
   192     // 0x0E4F - 0x0E5F
       
   193     THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON,
       
   194     THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON,
       
   195     THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON, THAI_CHAR_NON,
       
   196     THAI_CHAR_NON, THAI_CHAR_NON
       
   197     };
       
   198 
       
   199 // MACROS
       
   200 #define IS_THAI_CHAR(c) ((c >= 0x0E00) && (c <= 0x0E60))
       
   201 //#define IS_THAI_LEADING_VOWEL(c) ((c >= 0x0E40) && (c <= 0x0E44))
       
   202 #define IS_THAI_LEADING_VOWEL(c) (ThaiCharMap[c - THAI_CHAR_BASE] == THAI_CHAR_LV)
       
   203 //#define IS_THAI_CONSONANT(c) ((c >= 0x0E01) && (c <= 0x0E2E) && (c != 0x0E24) && (c != 0x0E26))
       
   204 #define IS_THAI_CONSONANT(c) (ThaiCharMap[c - THAI_CHAR_BASE] == THAI_CHAR_CONS)
       
   205 //#define IS_THAI_FOLLOWING_VOWEL(c) ((c == 0x0E24) || (c == 0x0E26) || (c == 0x0E30) || (c == 0x0E32) || (c == 0x0E33) || (c == 0x0E45))
       
   206 #define IS_THAI_FOLLOWING_VOWEL(c) (ThaiCharMap[c - THAI_CHAR_BASE] == THAI_CHAR_FV)
       
   207 #define IS_THAI_COMBINING(c) (ThaiCharMap[c - THAI_CHAR_BASE] & THAI_CHAR_COMBINING_TYPE_FLAG)
       
   208 
       
   209 
       
   210 // LOCAL CONSTANTS AND MACROS
       
   211 
       
   212 // MODULE DATA STRUCTURES
       
   213 
       
   214 // LOCAL FUNCTION PROTOTYPES
       
   215 
       
   216 // FORWARD DECLARATIONS
       
   217 
       
   218 // ============================= LOCAL FUNCTIONS ===============================
       
   219 
       
   220 
       
   221 // ============================ MEMBER FUNCTIONS ===============================
       
   222 // -----------------------------------------------------------------------------
       
   223 // CGDIDeviceContext::CGDIDeviceContext
       
   224 // C++ default constructor can NOT contain any code, that
       
   225 // might leave.
       
   226 // -----------------------------------------------------------------------------
       
   227 //
       
   228 CGDIDeviceContext::CGDIDeviceContext()
       
   229   {
       
   230   }
       
   231 
       
   232 // -----------------------------------------------------------------------------
       
   233 // CGDIDeviceContext::CGDIDeviceContext
       
   234 // Symbian 2nd phase constructor can leave.
       
   235 // -----------------------------------------------------------------------------
       
   236 //
       
   237 TBrowserStatusCode
       
   238 CGDIDeviceContext::ConstructL (void* aGraphicsContext,
       
   239                                CView* aOocEpoc32View)
       
   240   {
       
   241   // initialize the member variables
       
   242   iGraphicsContext = aGraphicsContext;
       
   243   if( !iGraphicsContext )
       
   244     {
       
   245     return KBrsrFailure;
       
   246     }
       
   247 
       
   248   iOocEpoc32View = aOocEpoc32View;
       
   249   if( !iOocEpoc32View )
       
   250     {
       
   251     return KBrsrFailure;
       
   252     }
       
   253 
       
   254   iVariantFlag = AknLayoutUtils::Variant();
       
   255 
       
   256   _LIT( KResourceFile, "\\resource\\Webkit.rsc");
       
   257   _LIT( KResourceFileZ, "Z:Webkit.rsc");  
       
   258   TFileName resourceFileName; 
       
   259   TParse parse;   
       
   260   Dll::FileName (resourceFileName);          
       
   261   parse.Set(KResourceFile, &resourceFileName, NULL);
       
   262   resourceFileName = parse.FullName();
       
   263     
       
   264   CCoeEnv* coeEnv=CCoeEnv::Static();
       
   265   BaflUtils::NearestLanguageFile(coeEnv->FsSession(), resourceFileName);
       
   266   if ( !BaflUtils::FileExists( coeEnv->FsSession(), resourceFileName ) )          
       
   267       {
       
   268       // Use resource file on the Z drive instead 
       
   269       parse.Set( KResourceFileZ, &KDC_RESOURCE_FILES_DIR, NULL );
       
   270       resourceFileName = parse.FullName(); 
       
   271       BaflUtils::NearestLanguageFile( coeEnv->FsSession(),resourceFileName );         	
       
   272       }
       
   273   iResourceFileOffset = coeEnv->AddResourceFileL(resourceFileName);
       
   274   
       
   275   // Get the array of available fonts on the phone
       
   276   CEikonEnv* eikEnv = CEikonEnv::Static();
       
   277   iWsScreenDev = eikEnv->ScreenDevice();
       
   278 
       
   279   // Create the font cache
       
   280   iFontCache = new (ELeave) CFontCache(30);  // 30 items in cache
       
   281 
       
   282   // Find out which language we support
       
   283   if ( FeatureManager::FeatureSupported(KFeatureIdAvkonELaf) )
       
   284       {
       
   285       iSupportedLanguage = EElafLanguage;
       
   286       }
       
   287   else if ( FeatureManager::FeatureSupported(KFeatureIdAvkonApac) )
       
   288     {
       
   289     if ( FeatureManager::FeatureSupported(KFeatureIdThai) )
       
   290         {
       
   291         iSupportedLanguage = EThaiLanguage;
       
   292         }
       
   293     else if ( FeatureManager::FeatureSupported(KFeatureIdJapanese) )
       
   294         {
       
   295         iSupportedLanguage = EJapaneseLanguage;
       
   296         }
       
   297     else if ( FeatureManager::FeatureSupported(KFeatureIdChineseTaiwanHkFonts) )
       
   298         {
       
   299         iSupportedLanguage = EChinaHKTWLanguage;
       
   300         }
       
   301     else  if ( FeatureManager::FeatureSupported(KFeatureIdChinesePrcFonts) )
       
   302         {
       
   303         iSupportedLanguage = EChinesePRCLanguage;
       
   304         }
       
   305     }
       
   306 
       
   307   iFillPattern=NW_GDI_Pattern_Solid;
       
   308   iLinePattern=NW_GDI_Pattern_Solid;
       
   309   iPaintMode=(NW_GDI_PaintMode_e)CGraphicsContext::EDrawModePEN;
       
   310   iLineWidth=1;
       
   311   iFontSizeLevel = EGDIDeviceContextFontSizeLevelNormal;
       
   312   // successful completion
       
   313   return KBrsrSuccess;
       
   314   }
       
   315 
       
   316 // -----------------------------------------------------------------------------
       
   317 // CGDIDeviceContext::NewL
       
   318 // Two-phased constructor.
       
   319 // -----------------------------------------------------------------------------
       
   320 //
       
   321 CGDIDeviceContext* CGDIDeviceContext::NewL (void* aGraphicsContext,
       
   322                                             CView* aOocEpoc32View)
       
   323   {
       
   324   CGDIDeviceContext* self = new( ELeave ) CGDIDeviceContext();
       
   325 
       
   326   CleanupStack::PushL( self );
       
   327   self->ConstructL(aGraphicsContext, aOocEpoc32View);
       
   328   CleanupStack::Pop();
       
   329 
       
   330   return self;
       
   331   }
       
   332 
       
   333 // -----------------------------------------------------------------------------
       
   334 // Destructor
       
   335 //
       
   336 // -----------------------------------------------------------------------------
       
   337 //
       
   338 CGDIDeviceContext::~CGDIDeviceContext()
       
   339     {
       
   340     CFont* font = NULL;
       
   341     CBitmapContext* gc = Epoc32GraphicsContext();
       
   342     while ((font = iFontCache->RemoveFirstEntry()) != NULL)
       
   343         {
       
   344         gc->DiscardFont();
       
   345         iWsScreenDev->ReleaseFont( font );
       
   346         }
       
   347 
       
   348     delete iFontCache;
       
   349 
       
   350     // screen device
       
   351     iWsScreenDev = NULL;
       
   352 
       
   353     // unload resource file
       
   354     CCoeEnv* coeEnv=CCoeEnv::Static();
       
   355     coeEnv->DeleteResourceFile(iResourceFileOffset);
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // CGDIDeviceContext::SwapColorBytes
       
   360 //
       
   361 // -----------------------------------------------------------------------------
       
   362 //
       
   363 NW_GDI_Color_t
       
   364 CGDIDeviceContext::SwapColorBytes(NW_GDI_Color_t aColor)
       
   365 {
       
   366   return NW_GDI_RGB(NW_GDI_GetBValue(aColor), NW_GDI_GetGValue(aColor), NW_GDI_GetRValue(aColor));
       
   367 }
       
   368 
       
   369 // -----------------------------------------------------------------------------
       
   370 // CGDIDeviceContext::Epoc32GraphicsContext
       
   371 //
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 CBitmapContext*
       
   375 CGDIDeviceContext::Epoc32GraphicsContext ()
       
   376 {
       
   377   return (CBitmapContext*)(iGraphicsContext);
       
   378 }
       
   379 
       
   380 // -----------------------------------------------------------------------------
       
   381 // CGDIDeviceContext::WordWrap
       
   382 // If a zero length string is passed in, KBrsrSuccess is returned and *length = 0
       
   383 // If constraint is -1 return the smallest string that can split and KBrsrSuccess
       
   384 //
       
   385 // -----------------------------------------------------------------------------
       
   386 //
       
   387 TBrowserStatusCode
       
   388 CGDIDeviceContext::WordWrap (NW_Text_t* aText,
       
   389                              CGDIFont* aGDIFont,
       
   390                              NW_GDI_Metric_t aConstraint,
       
   391                              NW_GDI_Metric_t aSpacing,
       
   392                              NW_GDI_FlowDirection_t aFlowDirection,
       
   393                              NW_Text_Length_t* aLength)
       
   394   {
       
   395   NW_REQUIRED_PARAM(aSpacing);
       
   396   NW_Text_Length_t strLen;
       
   397   NW_Text_Length_t i;
       
   398   TText16 ch1 = 0;
       
   399   TText16 ch2 = 0;
       
   400   TText16* string = NULL;
       
   401   TBool freeNeeded = NW_FALSE;
       
   402   TPtrC ptr;
       
   403   TBidiText *bidiText = NULL;
       
   404   CFont* epocFont = NULL;
       
   405 
       
   406   strLen = NW_Text_GetCharCount (aText);
       
   407   if (strLen == 0)
       
   408     {
       
   409     *aLength = 0;
       
   410     return KBrsrSuccess;
       
   411     }
       
   412 
       
   413   if (aConstraint == -1)
       
   414     {
       
   415     if (strLen > 1)
       
   416       {
       
   417       ch1 = (TText16)NW_Text_GetAt (aText, 0);
       
   418       for (i = 1; i < strLen; i++)
       
   419         {
       
   420         ch2 = (TText16)NW_Text_GetAt (aText, i);
       
   421         if (CanSplit(ch1, ch2))
       
   422           {
       
   423           *aLength = (NW_Text_Length_t)(i);
       
   424           return KBrsrSuccess;
       
   425           }
       
   426         ch1 = ch2;
       
   427         }
       
   428       }
       
   429     *aLength = strLen;
       
   430     return KBrsrSuccess;
       
   431     }
       
   432 
       
   433   if (aConstraint == 0)
       
   434     {
       
   435     *aLength = 0;
       
   436     return KBrsrLmgrNoSplit;
       
   437     }
       
   438 
       
   439   NW_TRY(status)
       
   440     {
       
   441     string = NW_Text_GetUCS2Buffer (aText,
       
   442         NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy,
       
   443         &strLen, (unsigned char*) &freeNeeded );
       
   444 
       
   445     for (i = 0; i < strLen; i++)
       
   446       {
       
   447       if (!NW_Str_Isspace((TText16)string[i]) && (string[i] != 0))
       
   448         {
       
   449         break;
       
   450         }
       
   451       }
       
   452 
       
   453     if (i == strLen)
       
   454       {
       
   455       *aLength = i;
       
   456       NW_THROW_SUCCESS(status);
       
   457       }
       
   458 
       
   459     ptr.Set(string, strLen);
       
   460     TRAPD(ret, bidiText = TBidiText::NewL(ptr, 1, (aFlowDirection == NW_GDI_FlowDirection_LeftRight) ?
       
   461         TBidiText::ELeftToRight : TBidiText::ERightToLeft));
       
   462     if (ret != KErrNone)
       
   463       {
       
   464       NW_THROW_STATUS (status, KBrsrOutOfMemory);
       
   465       }
       
   466 
       
   467     epocFont = (CFont*)aGDIFont->GetEpocNativeFont();
       
   468     bidiText->WrapText(aConstraint, *epocFont, 0);
       
   469 
       
   470     *aLength = bidiText->DisplayText().Length();
       
   471 
       
   472 	//Solution for bug in TBidiText::WrapText for long text
       
   473 	if(aFlowDirection == NW_GDI_FlowDirection_LeftRight)
       
   474 	{
       
   475 		NW_GDI_Dimension2D_t extent;
       
   476 		status = GetSubstringExtent (aText,
       
   477 									 aGDIFont,
       
   478 									 0,
       
   479 									 *aLength,
       
   480 									 aSpacing,
       
   481 									 aFlowDirection,
       
   482 									 &extent);
       
   483 		NW_THROW_ON_ERROR(status);
       
   484 		if(extent.width > aConstraint)
       
   485 		{
       
   486 			extent.width = 0;
       
   487 			NW_Text_Length_t len = 0;
       
   488 			while(extent.width < aConstraint)
       
   489 			{
       
   490 				len++;
       
   491 				status = GetSubstringExtent(aText, aGDIFont, 0, len, aSpacing, aFlowDirection, &extent);
       
   492 				NW_THROW_ON_ERROR(status);
       
   493 			}
       
   494 			*aLength = len -1;
       
   495 		}
       
   496 	}
       
   497 	//The above solution is to fix a Symbian bug in TBidiText::WrapText for long text
       
   498 
       
   499     delete bidiText;
       
   500     if (*aLength == 0)
       
   501       {
       
   502       NW_THROW_STATUS(status, KBrsrLmgrNoSplit);
       
   503       }
       
   504     if (*aLength < strLen)
       
   505       {
       
   506       // If the next character is a soft hyphen, add it to the aText
       
   507       if (string[*aLength] == NW_TEXT_UCS2_SOFT_HYPHEN)
       
   508         {
       
   509         (*aLength)++;
       
   510         NW_THROW_SUCCESS(status);
       
   511         }
       
   512 
       
   513       // TBidiText always omits the last space. see if we can add it back
       
   514       if ((*aLength) + 1 == strLen && NW_Str_Isspace(string[*aLength]))
       
   515         {
       
   516         NW_GDI_Dimension2D_t extent;
       
   517         status = GetSubstringExtent (aText,
       
   518                                      aGDIFont,
       
   519                                      0,
       
   520                                      *aLength,
       
   521                                      aSpacing,
       
   522                                      aFlowDirection,
       
   523                                      &extent);
       
   524         NW_THROW_ON_ERROR(status);
       
   525         if (extent.width <= aConstraint)
       
   526           {
       
   527           (*aLength)++;
       
   528           NW_THROW_SUCCESS(status);
       
   529           }
       
   530         }
       
   531 
       
   532       // Make sure we do the split at a valid position
       
   533       TInt len = *aLength;
       
   534       ch2 = (TText16)((len < (TInt)strLen) ? NW_Text_GetAt (aText, len) : 0);
       
   535       while (--len >= 0)
       
   536         {
       
   537         ch1 = (TText16)NW_Text_GetAt (aText, len);
       
   538         if (CanSplit(ch1, ch2))
       
   539           {
       
   540           break;
       
   541           }
       
   542         ch2 = ch1;
       
   543         }
       
   544 
       
   545 	  CGDIDeviceContext* self = const_cast<CGDIDeviceContext*> (this);
       
   546       if(NW_Str_Isspace(ch2)||
       
   547 		  len < 0	||
       
   548 		  ch1 == NW_TEXT_UCS2_SOFT_HYPHEN ||
       
   549 		  (self->VariantFlag() == EApacVariant && ch2 < 255 && ch1 > 255) //Doule bytes language word followed by a latin word
       
   550 		  )
       
   551 		{
       
   552 			*aLength = len + 1;
       
   553 		}
       
   554 	  else
       
   555 		{
       
   556 			*aLength = len;
       
   557 		}
       
   558       }
       
   559     if (*aLength == 0)
       
   560       {
       
   561       NW_THROW_STATUS(status, KBrsrLmgrNoSplit);
       
   562       }
       
   563     else
       
   564       {
       
   565       status =  KBrsrSuccess;
       
   566       }
       
   567     }
       
   568 
       
   569   NW_CATCH(status)
       
   570     {
       
   571     } // empty
       
   572   NW_FINALLY
       
   573     {
       
   574     if (freeNeeded)
       
   575       {
       
   576       NW_Mem_Free(string);
       
   577       }
       
   578     return status;
       
   579     }
       
   580   NW_END_TRY;
       
   581   }
       
   582 
       
   583 // -------------------------------------------------------------------------
       
   584 // CGDIDeviceContext::SplitAtNewline
       
   585 //
       
   586 // -----------------------------------------------------------------------------
       
   587 //
       
   588 TBrowserStatusCode
       
   589 CGDIDeviceContext::SplitAtNewline(NW_Text_t* aText,
       
   590                                   CGDIFont* aGDIFont,
       
   591                                   NW_GDI_Metric_t aConstraint,
       
   592                                   NW_GDI_Metric_t aSpacing,
       
   593                                   NW_GDI_FlowDirection_t aFlowDirection,
       
   594                                   NW_Text_Length_t* aLength)
       
   595   {
       
   596   NW_Text_Length_t strLen;
       
   597   NW_Text_Length_t i;
       
   598   TText16 ch = 0;
       
   599   NW_GDI_Dimension2D_t size;
       
   600 
       
   601   NW_TRY(status)
       
   602     {
       
   603     // Get the aText aLength
       
   604     strLen = NW_Text_GetCharCount (aText);
       
   605     if (strLen == 0)
       
   606       {
       
   607       *aLength = 0;
       
   608       NW_THROW_SUCCESS(status);
       
   609       }
       
   610 
       
   611     // Look for the first LF character
       
   612     for (i=0; i<strLen; i++)
       
   613       {
       
   614       ch = (TText16) NW_Text_GetAt (aText, i);
       
   615       if (ch == NW_TEXT_UCS2_LF)
       
   616         {
       
   617         break;
       
   618         }
       
   619       }
       
   620     if (aConstraint < 0)
       
   621       {
       
   622       if (ch == NW_TEXT_UCS2_LF)
       
   623         {
       
   624         *aLength = (NW_Text_Length_t)(i + 1);
       
   625         }
       
   626       else
       
   627         {
       
   628         *aLength = strLen;
       
   629         }
       
   630       }
       
   631     else
       
   632       {
       
   633       status = CGDIDeviceContext::GetSubstringExtent( aText,
       
   634                                                       aGDIFont,
       
   635                                                       0,
       
   636                                                       i,
       
   637                                                       aSpacing,
       
   638                                                       aFlowDirection, &size );
       
   639       NW_THROW_ON_ERROR(status);
       
   640 
       
   641       if (size.width <= aConstraint)
       
   642         {
       
   643         if (ch == NW_TEXT_UCS2_LF)
       
   644           {
       
   645           *aLength = (NW_Text_Length_t)(i + 1);
       
   646           NW_THROW_SUCCESS(status);
       
   647           }
       
   648         else
       
   649           {
       
   650           *aLength = strLen;
       
   651           NW_THROW_SUCCESS(status);
       
   652           }
       
   653         }
       
   654       else
       
   655         {
       
   656         *aLength = 0;
       
   657         NW_THROW_STATUS(status, KBrsrLmgrNoSplit);
       
   658         }
       
   659       }
       
   660     }
       
   661   NW_CATCH(status)
       
   662     {
       
   663     }
       
   664   NW_FINALLY
       
   665     {
       
   666     return status;
       
   667     }
       
   668   NW_END_TRY;
       
   669   }
       
   670 
       
   671 // -------------------------------------------------------------------------
       
   672 // CGDIDeviceContext::Truncate
       
   673 // NOTE:  This function never fails!  Even if a single character is too
       
   674 // big for the constraint, it will return length = 1, and STAT_SUCCESS
       
   675 //
       
   676 // -----------------------------------------------------------------------------
       
   677 //
       
   678 TBrowserStatusCode
       
   679 CGDIDeviceContext::Truncate (NW_Text_t* aText,
       
   680                              CGDIFont* aGDIFont,
       
   681                              NW_GDI_Metric_t aConstraint,
       
   682                              NW_GDI_Metric_t aSpacing,
       
   683                              NW_GDI_FlowDirection_t aFlowDirection,
       
   684                              NW_Text_Length_t* aLength)
       
   685 {
       
   686   NW_Text_Length_t strLen;
       
   687   TText16* string = NULL;
       
   688   TBool freeNeeded = NW_FALSE;
       
   689   TPtrC ptr;
       
   690   TBidiText *bidiText = NULL;
       
   691   CFont* epocFont = NULL;
       
   692 
       
   693   NW_REQUIRED_PARAM(aSpacing);
       
   694 
       
   695   if (NW_Text_GetCharCount(aText) == 0)
       
   696     {
       
   697     *aLength = 1; // Must return at least 1
       
   698     return KBrsrSuccess;
       
   699     }
       
   700 
       
   701   NW_TRY(status)
       
   702     {
       
   703     string =
       
   704       NW_Text_GetUCS2Buffer (aText,
       
   705                              NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy,
       
   706                              &strLen,
       
   707                              (unsigned char*) &freeNeeded);
       
   708 
       
   709     ptr.Set(string, strLen);
       
   710     TUint newLen = ptr.Locate('\n');
       
   711     if (newLen < strLen)
       
   712       {
       
   713       ptr.Set(ptr.Ptr(), newLen);
       
   714       }
       
   715 
       
   716     TRAPD(ret, bidiText = TBidiText::NewL(ptr, 1, (aFlowDirection == NW_GDI_FlowDirection_LeftRight) ?
       
   717         TBidiText::ELeftToRight : TBidiText::ERightToLeft));
       
   718     if (ret != KErrNone)
       
   719       {
       
   720       NW_THROW_STATUS (status, KBrsrOutOfMemory);
       
   721       }
       
   722 
       
   723     epocFont = (CFont*)aGDIFont->GetEpocNativeFont();
       
   724     bidiText->WrapText(aConstraint, *epocFont, 0);
       
   725 
       
   726     *aLength = bidiText->DisplayText().Length();
       
   727 
       
   728     //Solution for bug in TBidiText::WrapText for long text
       
   729 	  if(aFlowDirection == NW_GDI_FlowDirection_LeftRight)
       
   730 	    {
       
   731 		    NW_GDI_Dimension2D_t extent;
       
   732 		    status = GetSubstringExtent (aText,
       
   733 									     aGDIFont,
       
   734 									     0,
       
   735 									     *aLength,
       
   736 									     aSpacing,
       
   737 									     aFlowDirection,
       
   738 									     &extent);
       
   739 		    NW_THROW_ON_ERROR(status);
       
   740 		    if (extent.width > aConstraint)
       
   741 		      {
       
   742           NW_Text_Length_t len = *aLength;
       
   743           while(extent.width > aConstraint)
       
   744             {
       
   745             len--;
       
   746             status = GetSubstringExtent (aText,
       
   747 									     aGDIFont,
       
   748 									     0,
       
   749 									     len,
       
   750 									     aSpacing,
       
   751 									     aFlowDirection,
       
   752 									     &extent);
       
   753 		        NW_THROW_ON_ERROR(status);
       
   754             }
       
   755           *aLength = len;
       
   756 		      }
       
   757 	    }
       
   758 
       
   759     delete bidiText;
       
   760 
       
   761     // For the Thai language, truncation should not occur within the middle of
       
   762     // a "cell" unless all that is left is a single "cell". The text was
       
   763     // truncated above and now it will be walked in reverse, looking for a
       
   764     // spot that is not within a "cell", further reducing the returned length
       
   765     // if needed.
       
   766     TInt len = *aLength;
       
   767     if (len > 1)
       
   768       {
       
   769       TText16 ch1;
       
   770       TText16 ch2;
       
   771       ch2 = (TText16)((len < (TInt)strLen) ? NW_Text_GetAt (aText, len) : 0);
       
   772       while (--len >= 0)
       
   773         {
       
   774         ch1 = (TText16)NW_Text_GetAt (aText, len);
       
   775         if ( !IS_THAI_CHAR(ch1) || !IS_THAI_CHAR(ch2) )
       
   776           {
       
   777           break;
       
   778           }
       
   779         if (!IsThaiCell(ch1, ch2))
       
   780           {
       
   781           break;
       
   782           }
       
   783         ch2 = ch1;
       
   784         }
       
   785       len += 1;
       
   786       }
       
   787     if (len)
       
   788       {
       
   789       *aLength = len;
       
   790       }
       
   791     status = KBrsrSuccess;
       
   792     }
       
   793   NW_CATCH(status)
       
   794     {
       
   795     } // empty
       
   796   NW_FINALLY
       
   797     {
       
   798     if (freeNeeded)
       
   799       {
       
   800       NW_Mem_Free(string);
       
   801       }
       
   802     if (*aLength == 0)
       
   803       {
       
   804       // As described above, this function must not return aLength==0.
       
   805       // This happens when aConstraint is 0, as has occured in some tables, when
       
   806       // NW_LMgr_FormatContext->lineStart > NW_LMgr_FormatContext->lineEnd
       
   807 
       
   808       *aLength = 1;
       
   809       }
       
   810     return status;
       
   811     }
       
   812   NW_END_TRY;
       
   813   }
       
   814 
       
   815 // -------------------------------------------------------------------------
       
   816 // CGDIDeviceContext::ScaleBitmap
       
   817 //
       
   818 // -----------------------------------------------------------------------------
       
   819 //
       
   820 TBrowserStatusCode
       
   821 CGDIDeviceContext::ScaleBitmap (CFbsBitmap* aBitmap,
       
   822                                 CFbsBitmap** aScaledBitmap,
       
   823                                 TRect* aRect)
       
   824 {
       
   825   CBitmapContext* bitmapContext = NULL;
       
   826   CBitmapDevice* bitmapDevice = NULL;
       
   827 
       
   828   // parameter assertion block
       
   829   NW_ASSERT (aBitmap);
       
   830   NW_ASSERT (aScaledBitmap);
       
   831   NW_ASSERT (aRect);
       
   832 
       
   833   NW_TRY (status)
       
   834   {
       
   835     // create scaled aBitmap
       
   836     *aScaledBitmap = new CFbsBitmap();
       
   837     NW_THROW_OOM_ON_NULL( aScaledBitmap, status );
       
   838 
       
   839     TInt err = (*aScaledBitmap)->Create( aRect->Size(), aBitmap->DisplayMode() );
       
   840     if ( err != KErrNone )
       
   841     {
       
   842       NW_THROW_STATUS (status, KBrsrFailure);
       
   843     }
       
   844 
       
   845     // create aBitmap device and context
       
   846     TRAP( err, bitmapDevice = CFbsBitmapDevice::NewL( *aScaledBitmap ) );
       
   847     NW_THROW_OOM_ON_NULL( bitmapDevice, status );
       
   848     if ( err != KErrNone )
       
   849     {
       
   850       NW_THROW_STATUS (status, KBrsrFailure);
       
   851     }
       
   852 
       
   853     err = bitmapDevice->CreateBitmapContext( bitmapContext );
       
   854     if ( err != KErrNone )
       
   855     {
       
   856       NW_THROW_STATUS (status, KBrsrFailure);
       
   857     }
       
   858 
       
   859     // scale aBitmap
       
   860     bitmapContext->DrawBitmap( *aRect, aBitmap );
       
   861   }
       
   862   NW_CATCH (status)
       
   863   {
       
   864     delete *aScaledBitmap;
       
   865     *aScaledBitmap = NULL;
       
   866   }
       
   867   NW_FINALLY
       
   868   {
       
   869     delete bitmapContext;
       
   870     delete bitmapDevice;
       
   871 
       
   872     return status;
       
   873   }
       
   874   NW_END_TRY
       
   875 }
       
   876 
       
   877 // -------------------------------------------------------------------------
       
   878 // CGDIDeviceContext::InitializeGraphicsContext
       
   879 //
       
   880 // -----------------------------------------------------------------------------
       
   881 //
       
   882 void
       
   883 CGDIDeviceContext::InitializeGraphicsContext ()
       
   884 {
       
   885   CBitmapContext* gc = Epoc32GraphicsContext();
       
   886 
       
   887   if (iClipRect.dimension.width!=0 && iClipRect.dimension.height!=0)
       
   888   {
       
   889     gc->SetClippingRect( TRect(
       
   890         iClipRect.point.x,
       
   891         iClipRect.point.y,
       
   892         iClipRect.point.x+iClipRect.dimension.width,
       
   893         iClipRect.point.y+iClipRect.dimension.height ) );
       
   894   }
       
   895   else
       
   896   {
       
   897 	  gc->CancelClippingRect();
       
   898   }
       
   899 
       
   900   //gc->SetDrawMode((CGraphicsContext::TDrawMode)(iPaintMode));
       
   901   gc->SetPenSize(TSize(iLineWidth, iLineWidth));
       
   902   gc->SetPenStyle((CGraphicsContext::TPenStyle)(iLinePattern));
       
   903   gc->SetPenColor(iForegroundColor);
       
   904   gc->SetBrushStyle((CGraphicsContext::TBrushStyle)(iFillPattern));
       
   905   gc->SetBrushColor(iBackgroundColor);
       
   906 }
       
   907 
       
   908 // -------------------------------------------------------------------------
       
   909 // CGDIDeviceContext::DrawImage
       
   910 //
       
   911 // -----------------------------------------------------------------------------
       
   912 //
       
   913 void
       
   914 CGDIDeviceContext::DrawImage (const NW_GDI_Point2D_t* aLocation,
       
   915                              const NW_GDI_Rectangle_t* aRectangle,
       
   916                              NW_GDI_ImageBlock_t* aImageBlock)
       
   917 {
       
   918   NW_GDI_Rectangle_t imageRect;
       
   919   NW_GDI_Rectangle_t clipRect;
       
   920 
       
   921   // parameter assertion block
       
   922   NW_ASSERT (aLocation);
       
   923 
       
   924   NW_REQUIRED_PARAM(aRectangle);
       
   925 
       
   926   InitializeGraphicsContext();
       
   927 
       
   928   CBitmapContext* gc = Epoc32GraphicsContext() ;
       
   929   CFbsBitmap* bitmap = (CFbsBitmap*) aImageBlock->data;
       
   930 
       
   931   NW_ASSERT( bitmap );
       
   932 
       
   933   TPoint point( aLocation->x - iOrigin.x + iDisplayBounds.point.x,
       
   934                 aLocation->y - iOrigin.y + iDisplayBounds.point.y );
       
   935 
       
   936 
       
   937   TRect rect( aRectangle->point.x, aRectangle->point.y,
       
   938 				aRectangle->dimension.width + aRectangle->point.x,
       
   939 				aRectangle->dimension.height + aRectangle->point.y );
       
   940 
       
   941   imageRect.point.x = aLocation->x;
       
   942   imageRect.point.y = aLocation->y;
       
   943   imageRect.dimension.width = aRectangle->dimension.width;
       
   944   imageRect.dimension.height = aRectangle->dimension.height;
       
   945 
       
   946   clipRect = ClipRect();
       
   947   if ( NW_GDI_Rectangle_Cross( &imageRect, &clipRect, NULL ) == NW_TRUE )
       
   948   {
       
   949     // Set brush style to NULL to prevent filling of aRectangle
       
   950     gc->SetBrushStyle (CGraphicsContext::ENullBrush);
       
   951 
       
   952     if ( !aImageBlock->mask ){
       
   953       gc->BitBlt( point, bitmap, rect );
       
   954     }
       
   955     else {
       
   956       CFbsBitmap* mask = (CFbsBitmap*) aImageBlock->mask;
       
   957       gc->BitBltMasked( point, bitmap, rect, mask, ((aImageBlock->invertedMask == NW_TRUE) ? ETrue : EFalse) );
       
   958     }
       
   959   }
       
   960 }
       
   961 
       
   962 
       
   963 // -------------------------------------------------------------------------
       
   964 // CGDIDeviceContext::ScaleImage
       
   965 //
       
   966 // -----------------------------------------------------------------------------
       
   967 //
       
   968 TBrowserStatusCode
       
   969 CGDIDeviceContext::ScaleImage (const NW_GDI_Dimension3D_t* size,
       
   970                                const NW_GDI_ImageBlock_t* imageBlock,
       
   971                                NW_GDI_ImageBlock_t* scaledImageBlock)
       
   972 {
       
   973   CFbsBitmap* scaledBitmap = NULL;
       
   974   CFbsBitmap* scaledMask = NULL;
       
   975 
       
   976   // parameter assertion block
       
   977   NW_ASSERT (imageBlock);
       
   978   NW_ASSERT (size);
       
   979   NW_ASSERT (scaledImageBlock);
       
   980   NW_ASSERT (imageBlock->data);
       
   981 
       
   982   NW_TRY (status)
       
   983   {
       
   984     TRect rect (0, 0, size->width, size->height);
       
   985 
       
   986     // scale bitmap
       
   987     status = ScaleBitmap ((CFbsBitmap*)imageBlock->data, &scaledBitmap, &rect);
       
   988     _NW_THROW_ON_ERROR (status);
       
   989     scaledImageBlock->data = scaledBitmap;
       
   990 
       
   991     // scale mask, if any
       
   992     if ( imageBlock->mask )
       
   993     {
       
   994       status = ScaleBitmap((CFbsBitmap*)imageBlock->mask, &scaledMask, &rect);
       
   995       _NW_THROW_ON_ERROR (status);
       
   996       scaledImageBlock->mask = scaledMask;
       
   997     }
       
   998     else
       
   999     {
       
  1000       scaledImageBlock->mask = NULL;
       
  1001     }
       
  1002 
       
  1003     // set the rest of the scaled image parameters
       
  1004     scaledImageBlock->size = *size;
       
  1005     scaledImageBlock->conversionStatus = imageBlock->conversionStatus;
       
  1006     scaledImageBlock->transparencyIndex = imageBlock->transparencyIndex;
       
  1007     scaledImageBlock->isTransparent = imageBlock->isTransparent;
       
  1008     scaledImageBlock->colPalette = imageBlock->colPalette;
       
  1009   }
       
  1010   NW_CATCH (status)
       
  1011   {
       
  1012     delete scaledBitmap;
       
  1013     delete scaledMask;
       
  1014   }
       
  1015   NW_FINALLY
       
  1016   {
       
  1017     return status;
       
  1018   }
       
  1019   NW_END_TRY
       
  1020 }
       
  1021 
       
  1022 // -------------------------------------------------------------------------
       
  1023 // CGDIDeviceContext::DrawPixel
       
  1024 //
       
  1025 // -----------------------------------------------------------------------------
       
  1026 //
       
  1027 void
       
  1028 CGDIDeviceContext::DrawPixel (const NW_GDI_Point2D_t* aLocation)
       
  1029 {
       
  1030   // parameter assertion block
       
  1031   NW_ASSERT (aLocation);
       
  1032 
       
  1033   // for convenience
       
  1034   InitializeGraphicsContext();
       
  1035   Epoc32GraphicsContext()->Plot
       
  1036       ( TPoint( aLocation->x - iOrigin.x + iDisplayBounds.point.x,
       
  1037                 aLocation->y - iOrigin.y + iDisplayBounds.point.y ) );
       
  1038 }
       
  1039 
       
  1040 // -------------------------------------------------------------------------
       
  1041 // CGDIDeviceContext::DrawPolyline
       
  1042 //
       
  1043 // -----------------------------------------------------------------------------
       
  1044 //
       
  1045 TBrowserStatusCode
       
  1046 CGDIDeviceContext::DrawPolyline (NW_GDI_Metric_t aNumPoints,
       
  1047                                  const NW_GDI_Point2D_t* aPoints,
       
  1048                                  TBool aClosed)
       
  1049 {
       
  1050   NW_GDI_Color_t initialColor = 0;
       
  1051 
       
  1052   // parameter assertion block
       
  1053   NW_ASSERT (aPoints);
       
  1054 
       
  1055   // for convenience
       
  1056   if (iLineWidth == 0){
       
  1057     return KBrsrSuccess;
       
  1058   }
       
  1059 
       
  1060   initialColor = iForegroundColor;
       
  1061 
       
  1062   CBitmapContext* gc = Epoc32GraphicsContext();
       
  1063 
       
  1064   InitializeGraphicsContext();
       
  1065 
       
  1066   // convert NW_Point2D array into TPoint array
       
  1067   TPoint* epocPoints=new TPoint[aNumPoints];
       
  1068 
       
  1069   if (epocPoints)
       
  1070   {
       
  1071     for (TInt ii=0; ii<aNumPoints; ii++)
       
  1072     {
       
  1073       epocPoints[ii]=TPoint( aPoints[ii].x - iOrigin.x + iDisplayBounds.point.x,
       
  1074                              aPoints[ii].y - iOrigin.y + iDisplayBounds.point.y);
       
  1075     }
       
  1076     gc->DrawPolyLine(epocPoints, aNumPoints);
       
  1077     delete[] epocPoints;
       
  1078   }
       
  1079 
       
  1080   if (aClosed && aNumPoints>2)
       
  1081   {
       
  1082     DrawLine(aPoints[0], aPoints[aNumPoints-1]);
       
  1083   }
       
  1084   iForegroundColor = initialColor;
       
  1085   // successful completion
       
  1086   return KBrsrSuccess;
       
  1087 }
       
  1088 
       
  1089 // -------------------------------------------------------------------------
       
  1090 // CGDIDeviceContext::DrawaRectangle
       
  1091 //
       
  1092 // -----------------------------------------------------------------------------
       
  1093 //
       
  1094 void
       
  1095 CGDIDeviceContext::DrawRectangle (const NW_GDI_Rectangle_t* aRectangle)
       
  1096 {
       
  1097   NW_GDI_Rectangle_t clipRect;
       
  1098   NW_GDI_Color_t initialColor = 0;
       
  1099 
       
  1100   CBitmapContext* gc = Epoc32GraphicsContext();
       
  1101 
       
  1102   clipRect = ClipRect();
       
  1103 
       
  1104   initialColor = iForegroundColor;
       
  1105 
       
  1106   if ( NW_GDI_Rectangle_Cross( aRectangle, &clipRect, NULL ) == NW_TRUE )
       
  1107   {
       
  1108     InitializeGraphicsContext();
       
  1109 
       
  1110     // Style to null for NO-FILL in aRectangle
       
  1111     gc->SetBrushStyle (CGraphicsContext::ENullBrush);
       
  1112     gc->DrawRect( TRect( aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x,
       
  1113                   aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y,
       
  1114                   aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x + aRectangle->dimension.width,
       
  1115                   aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y + aRectangle->dimension.height));
       
  1116   }
       
  1117   iForegroundColor = initialColor;
       
  1118 }
       
  1119 
       
  1120 
       
  1121 // -------------------------------------------------------------------------
       
  1122 // CGDIDeviceContext::DrawText
       
  1123 //
       
  1124 // -----------------------------------------------------------------------------
       
  1125 //
       
  1126 TBrowserStatusCode
       
  1127 CGDIDeviceContext::DrawText (const NW_GDI_Point2D_t* aLocation,
       
  1128                              const NW_Text_t* aText,
       
  1129                              CGDIFont* aGDIFont,
       
  1130                              NW_GDI_Metric_t aSpacing,
       
  1131                              NW_GDI_TextDecoration_t aDecoration,
       
  1132                              NW_GDI_FlowDirection_t aGlobalDir,
       
  1133                              NW_GDI_Metric_t aWidth)
       
  1134   {
       
  1135   NW_Text_Length_t length;
       
  1136   NW_Text_Length_t trimmedLen;
       
  1137   NW_Text_Length_t i;
       
  1138   TText16* string = NULL;
       
  1139   TBool freeNeeded = NW_FALSE;
       
  1140   NW_GDI_Color_t initialColor = 0;
       
  1141 
       
  1142   // parameter assertion block
       
  1143   NW_ASSERT (aLocation);
       
  1144   NW_ASSERT (aText);
       
  1145 
       
  1146   NW_TRY (status)
       
  1147     {
       
  1148     // Get the aText as unicode
       
  1149     string =
       
  1150       NW_Text_GetUCS2Buffer (aText,
       
  1151                              NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy,
       
  1152                              &length,
       
  1153                              (unsigned char*) &freeNeeded);
       
  1154     if (length == 0)
       
  1155       {
       
  1156       NW_THROW_STATUS (status, KBrsrSuccess);
       
  1157       }
       
  1158 
       
  1159     if (!string)
       
  1160       {
       
  1161       NW_THROW_STATUS (status, KBrsrFailure);
       
  1162       }
       
  1163 
       
  1164     // Trim the string
       
  1165     trimmedLen = 0;
       
  1166     for (i = 0; i < length; i++)
       
  1167       {
       
  1168       if ((string[i] == NW_TEXT_UCS2_SOFT_HYPHEN) || (string[i] == NW_TEXT_UCS2_LF)
       
  1169           || (string[i] == NW_TEXT_UCS2_CR))
       
  1170         {
       
  1171           continue;
       
  1172         }
       
  1173       else if ((string[i] == NW_TEXT_UCS2_TAB) || (string[i] == NW_TEXT_UCS2_NBSP))
       
  1174         {
       
  1175         // In vertical-layout mode we want to ignore nbsp within a table cell
       
  1176         if (iRemoveNbsp)
       
  1177           {
       
  1178           continue;
       
  1179           }
       
  1180           string[trimmedLen++] = ' ';
       
  1181         }
       
  1182       else
       
  1183         {
       
  1184         string[trimmedLen++] = string[i];
       
  1185         }
       
  1186       }
       
  1187     string[trimmedLen] = 0;
       
  1188 
       
  1189     if (trimmedLen == 0)
       
  1190       {
       
  1191       NW_THROW_STATUS (status, KBrsrSuccess);
       
  1192       }
       
  1193 
       
  1194     initialColor = iForegroundColor;
       
  1195 
       
  1196     CBitmapContext* gc = Epoc32GraphicsContext();
       
  1197 
       
  1198     CFont* epocFont = NULL;
       
  1199     epocFont = (CFont*)aGDIFont->GetEpocNativeFont();
       
  1200 
       
  1201  	// Lowercase letters will be rendered as uppercase characters
       
  1202     // Font size remains intact (according to spec)
       
  1203 
       
  1204     if(aGDIFont->FontVariant() == EGDIFontVariantSmallCaps) {
       
  1205       if(!freeNeeded) {
       
  1206         string = NW_Text_GetUCS2Buffer(aText, NW_Text_Flags_Copy, NULL, NULL);
       
  1207        NW_THROW_OOM_ON_NULL (string, status);
       
  1208 
       
  1209        freeNeeded = NW_TRUE;
       
  1210       }
       
  1211       NW_Str_Strupr((TText16*)string);
       
  1212       }
       
  1213 
       
  1214     CGraphicsContext::TDrawTextParam params;
       
  1215     params.iCharJustExcess=aSpacing;
       
  1216     InitializeGraphicsContext();
       
  1217     gc->UseFont(epocFont);
       
  1218 
       
  1219     //Calculate Baseline offset
       
  1220     //Baseline is calculated as (Height + ascent in pixels - descent in pixels) /2
       
  1221     //iDisplayBounds and iOrigin are kept as it is to make sure drawing is respective to
       
  1222     //display bound
       
  1223     TInt heightInPixels = epocFont->HeightInPixels();
       
  1224     TInt descentInPixels = epocFont->DescentInPixels();
       
  1225     TInt acsentInPixels = epocFont->FontMaxAscent();
       
  1226     TInt baseLineOffset = (iDisplayBounds.point.y) + (heightInPixels + acsentInPixels - descentInPixels ) / (2) - iOrigin.y; 
       
  1227     
       
  1228     TPtrC ptrC(string);
       
  1229     TPoint point( aLocation->x - iOrigin.x + iDisplayBounds.point.x,
       
  1230                   aLocation->y + baseLineOffset);
       
  1231 
       
  1232     if (aDecoration & NW_GDI_TextDecoration_Underline) {
       
  1233       gc->SetUnderlineStyle(EUnderlineOn);
       
  1234     }
       
  1235 
       
  1236     if (aDecoration & NW_GDI_TextDecoration_Strikeout) {
       
  1237       gc->SetStrikethroughStyle(EStrikethroughOn);
       
  1238     }
       
  1239 
       
  1240     // Draw the aText either using the TBidiText sophicated method
       
  1241     // or the simple CGraphicsContext method if the orginal encoding is 8859-8
       
  1242     CGraphicsContext::TTextAlign alignment = CGraphicsContext::ELeft;
       
  1243     TInt ret = KErrNone;
       
  1244 
       
  1245     if (aGlobalDir == NW_GDI_FlowDirection_RightLeft) {
       
  1246       alignment = CGraphicsContext::ERight;
       
  1247     }
       
  1248 
       
  1249     // When aText is encoded with HTTP_iso_8859_8 CGraphicsContext::DrawText
       
  1250     // is used instead of TBidiText::DrawText.  This is done because this encoding
       
  1251     // implies that the buffer should be rendered as is if aGlobalDir is left to right
       
  1252     // or reversed and rendered if aGlobalDir is right to left (including latin chars).
       
  1253     if (NW_Settings_GetOriginalEncoding() == HTTP_iso_8859_8) {
       
  1254       if (aGlobalDir == NW_GDI_FlowDirection_RightLeft) {
       
  1255         NW_Text_Length_t len = NW_Str_Strlen(string);
       
  1256 
       
  1257         // Reverse the aText first then draw it
       
  1258         for (NW_Text_Length_t i = 0; i < (len / 2); i++) {
       
  1259           TText16 temp;
       
  1260 
       
  1261           temp = string[i];
       
  1262           string[i] = string[len - 1 - i];
       
  1263           string[len - 1 - i] = temp;
       
  1264         }
       
  1265       }
       
  1266 
       
  1267       gc->DrawText(ptrC, point);
       
  1268       iOocEpoc32View->DrawPictographsInText(*gc, *epocFont, ptrC, point);
       
  1269    }
       
  1270 
       
  1271     // Otherwise use TBidiText to render the aText which correctly renders
       
  1272     // hebrew chars right to left or left to right depending on aGlobalDir --
       
  1273     // embedded latin chars are always rendered left to right.
       
  1274     else {
       
  1275       TBidiText *bidiText = NULL;
       
  1276 
       
  1277       // Wrap the aText in a TBidiText to allow bi-directional flow.
       
  1278       TRAP(ret, bidiText = TBidiText::NewL(ptrC, 1,
       
  1279         (aGlobalDir == NW_GDI_FlowDirection_LeftRight) ?
       
  1280         TBidiText::ELeftToRight : TBidiText::ERightToLeft));
       
  1281 
       
  1282       if (ret != KErrNone) {
       
  1283         NW_THROW_STATUS (status, KBrsrFailure);
       
  1284       }
       
  1285 
       
  1286       bidiText->WrapText(aWidth, *epocFont, 0);
       
  1287       bidiText->DrawText(*gc, point, aSpacing, alignment);
       
  1288       iOocEpoc32View->DrawPictographsInText(*gc, *epocFont, ptrC, point);
       
  1289 
       
  1290       delete bidiText;
       
  1291     }
       
  1292 
       
  1293     if (aDecoration & NW_GDI_TextDecoration_Underline) {
       
  1294       gc->SetUnderlineStyle(EUnderlineOff);
       
  1295     }
       
  1296 
       
  1297     if (aDecoration & NW_GDI_TextDecoration_Strikeout) {
       
  1298       gc->SetStrikethroughStyle(EStrikethroughOff);
       
  1299     }
       
  1300 
       
  1301     gc->DiscardFont();
       
  1302 
       
  1303     iForegroundColor = initialColor;
       
  1304 
       
  1305   } NW_CATCH (status) {
       
  1306   } NW_FINALLY {
       
  1307 
       
  1308     if (freeNeeded){
       
  1309       NW_Mem_Free (string);
       
  1310     }
       
  1311 
       
  1312     return status;
       
  1313   } NW_END_TRY;
       
  1314 }
       
  1315 
       
  1316 // -------------------------------------------------------------------------
       
  1317 // CGDIDeviceContext::FillaRectangle
       
  1318 //
       
  1319 // -----------------------------------------------------------------------------
       
  1320 //
       
  1321 void
       
  1322 CGDIDeviceContext::FillRectangle (const NW_GDI_Rectangle_t* aRectangle)
       
  1323 {
       
  1324   NW_GDI_Rectangle_t clipRect;
       
  1325 
       
  1326   // parameter assertion block
       
  1327   NW_ASSERT (aRectangle);
       
  1328 
       
  1329   // for convenience
       
  1330   clipRect = ClipRect();
       
  1331   if ( NW_GDI_Rectangle_Cross( aRectangle, &clipRect, NULL ) == NW_TRUE )
       
  1332   {
       
  1333     CBitmapContext* gc = Epoc32GraphicsContext();
       
  1334 
       
  1335     InitializeGraphicsContext ();
       
  1336 
       
  1337     gc->SetPenColor(iBackgroundColor);
       
  1338     gc->DrawRect(TRect(aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x,
       
  1339              aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y,
       
  1340              aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x + aRectangle->dimension.width,
       
  1341              aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y + aRectangle->dimension.height));
       
  1342   }
       
  1343 }
       
  1344 
       
  1345 // -------------------------------------------------------------------------
       
  1346 // CGDIDeviceContext::GetColorPalette
       
  1347 //
       
  1348 // -----------------------------------------------------------------------------
       
  1349 //
       
  1350 TBrowserStatusCode
       
  1351 CGDIDeviceContext::GetColorPalette (NW_GDI_ColorPalette_t* aColPalette)
       
  1352 {
       
  1353   // parameter assertion block
       
  1354   NW_ASSERT (aColPalette);
       
  1355   NW_REQUIRED_PARAM (aColPalette);
       
  1356 
       
  1357 	// Get the system palette entries
       
  1358 
       
  1359   /***********************************************************
       
  1360    *  PORTING NOTE:
       
  1361    *
       
  1362    *  Write some statements similar to the next lines (NT
       
  1363    *  implementation reference) based on your platform properties:
       
  1364    *
       
  1365    *  GetSystemPaletteEntries(this->hdc,0,256,pe);
       
  1366    *
       
  1367    *  for(j = 0; j< 256; j++)
       
  1368    *  {
       
  1369    *	 aColPalette[j].Red   = pe[j].peRed;
       
  1370    *	 aColPalette[j].Green = pe[j].peGreen;
       
  1371    *	 aColPalette[j].Blue  = pe[j].peBlue;
       
  1372    *  }
       
  1373    ************************************************************/
       
  1374 
       
  1375   // successful completion
       
  1376   return KBrsrNotImplemented;
       
  1377 }
       
  1378 
       
  1379 // -------------------------------------------------------------------------
       
  1380 // CGDIDeviceContext::BackgroundColor
       
  1381 //
       
  1382 // -----------------------------------------------------------------------------
       
  1383 //
       
  1384 NW_GDI_Color_t
       
  1385 CGDIDeviceContext::BackgroundColor () const
       
  1386 {
       
  1387   CGDIDeviceContext* self = const_cast<CGDIDeviceContext*> (this);
       
  1388   return self->SwapColorBytes(iBackgroundColor);
       
  1389 }
       
  1390 
       
  1391 // -------------------------------------------------------------------------
       
  1392 // CGDIDeviceContext::ClipRect
       
  1393 //
       
  1394 // -----------------------------------------------------------------------------
       
  1395 //
       
  1396 NW_GDI_Rectangle_t
       
  1397 CGDIDeviceContext::ClipRect () const
       
  1398 {
       
  1399   NW_GDI_Rectangle_t clip;
       
  1400 
       
  1401   clip.point.x = (NW_GDI_Metric_t)
       
  1402                   (iClipRect.point.x + iOrigin.x - iDisplayBounds.point.x);
       
  1403 
       
  1404   clip.point.y = (NW_GDI_Metric_t)
       
  1405                   (iClipRect.point.y + iOrigin.y - iDisplayBounds.point.y);
       
  1406 
       
  1407   clip.dimension.width = (NW_GDI_Metric_t)(iClipRect.dimension.width);
       
  1408 
       
  1409   clip.dimension.height = (NW_GDI_Metric_t)(iClipRect.dimension.height);
       
  1410 
       
  1411   return clip;
       
  1412 }
       
  1413 
       
  1414 // -------------------------------------------------------------------------
       
  1415 // CGDIDeviceContext::DisplayBounds
       
  1416 //
       
  1417 // -----------------------------------------------------------------------------
       
  1418 //
       
  1419 const NW_GDI_Rectangle_t*
       
  1420 CGDIDeviceContext::DisplayBounds () const
       
  1421 {
       
  1422   // displayBounds
       
  1423   return &(iDisplayBounds);
       
  1424 }
       
  1425 
       
  1426 // -------------------------------------------------------------------------
       
  1427 // CGDIDeviceContext::DisplayDepth
       
  1428 //
       
  1429 // -----------------------------------------------------------------------------
       
  1430 //
       
  1431 TUint8
       
  1432 CGDIDeviceContext::DisplayDepth () const
       
  1433 {
       
  1434   // return the desired property
       
  1435 
       
  1436   // Gets 'bits per color' property of the display
       
  1437   CGDIDeviceContext* self = const_cast<CGDIDeviceContext*> (this);
       
  1438   switch(self->Epoc32GraphicsContext()->Device()->DisplayMode())
       
  1439   {
       
  1440     case EGray2:
       
  1441 	    return 1;
       
  1442     case EGray4:
       
  1443 	    return 2;
       
  1444     case EGray16:case EColor16:
       
  1445 	    return 4;
       
  1446     case EGray256:case EColor256:
       
  1447 	    return 8;
       
  1448     case EColor64K:
       
  1449 	    return 16;
       
  1450     case EColor16M:
       
  1451 	    return 24;
       
  1452     case EColor4K:
       
  1453 	    return 12;
       
  1454     default:
       
  1455 	    return 0;
       
  1456   }
       
  1457 }
       
  1458 
       
  1459 // -------------------------------------------------------------------------
       
  1460 // CGDIDeviceContext::FillPattern
       
  1461 //
       
  1462 // -----------------------------------------------------------------------------
       
  1463 //
       
  1464 NW_GDI_Pattern_t
       
  1465 CGDIDeviceContext::FillPattern () const
       
  1466 {
       
  1467   // return the desired property
       
  1468   return iFillPattern;
       
  1469 }
       
  1470 
       
  1471 // -------------------------------------------------------------------------
       
  1472 // CGDIDeviceContext::GetFlowDirection
       
  1473 //
       
  1474 // -----------------------------------------------------------------------------
       
  1475 //
       
  1476 TBrowserStatusCode
       
  1477 CGDIDeviceContext::GetFlowDirection (NW_Text_t* aText,
       
  1478                                      NW_GDI_FlowDirection_t* aFlowDirection) const
       
  1479 {
       
  1480   TText16* string;
       
  1481   NW_Text_Length_t strLen = 0;
       
  1482   TBool freeNeeded = NW_FALSE;
       
  1483   TPtrC textPtr;
       
  1484 
       
  1485   NW_ASSERT ( aFlowDirection );
       
  1486 
       
  1487   NW_TRY (status) {
       
  1488 
       
  1489     // Set the default response
       
  1490     *aFlowDirection = NW_GDI_FlowDirection_LeftRight;
       
  1491 
       
  1492     // Set the aText string*/
       
  1493     string =
       
  1494       NW_Text_GetUCS2Buffer (aText,
       
  1495                              NW_Text_Flags_Aligned | NW_Text_Flags_NullTerminated,
       
  1496                              &strLen,
       
  1497                              (unsigned char*) &freeNeeded);
       
  1498     NW_THROW_OOM_ON_NULL (string, status);
       
  1499 
       
  1500     // If no aText, we're done
       
  1501     if (strLen == 0) {
       
  1502       return KBrsrSuccess;
       
  1503     }
       
  1504     textPtr.Set(string, strLen);
       
  1505     TBool found;
       
  1506     TBidiText::TDirectionality bidiDir = TBidiText::TextDirectionality(textPtr, &found);
       
  1507     *aFlowDirection = (bidiDir == TBidiText::ELeftToRight) ? NW_GDI_FlowDirection_LeftRight : NW_GDI_FlowDirection_RightLeft;
       
  1508 
       
  1509   } NW_CATCH (status) {
       
  1510   } NW_FINALLY {
       
  1511     if (freeNeeded) NW_Mem_Free (string);
       
  1512     return status;
       
  1513   } NW_END_TRY
       
  1514 }
       
  1515 
       
  1516 // -------------------------------------------------------------------------
       
  1517 // CGDIDeviceContext::ForegroundColor
       
  1518 //
       
  1519 // -----------------------------------------------------------------------------
       
  1520 //
       
  1521 NW_GDI_Color_t
       
  1522 CGDIDeviceContext::ForegroundColor () const
       
  1523 {
       
  1524   CGDIDeviceContext* self = const_cast<CGDIDeviceContext*> (this);
       
  1525   return self->SwapColorBytes(iForegroundColor);
       
  1526 }
       
  1527 
       
  1528 // -------------------------------------------------------------------------
       
  1529 // CGDIDeviceContext::LinePattern
       
  1530 //
       
  1531 // -----------------------------------------------------------------------------
       
  1532 //
       
  1533 NW_GDI_Pattern_t
       
  1534 CGDIDeviceContext::LinePattern () const
       
  1535 {
       
  1536   return iLinePattern;
       
  1537 }
       
  1538 
       
  1539 // -------------------------------------------------------------------------
       
  1540 // CGDIDeviceContext::LineWidth
       
  1541 //
       
  1542 // -----------------------------------------------------------------------------
       
  1543 //
       
  1544 NW_GDI_Metric_t
       
  1545 CGDIDeviceContext::LineWidth () const
       
  1546 {
       
  1547   return iLineWidth;
       
  1548 }
       
  1549 
       
  1550 // -------------------------------------------------------------------------
       
  1551 // CGDIDeviceContext::Origin
       
  1552 //
       
  1553 // -----------------------------------------------------------------------------
       
  1554 //
       
  1555 const NW_GDI_Point2D_t*
       
  1556 CGDIDeviceContext::Origin () const
       
  1557 {
       
  1558   // return the desired property
       
  1559   return &iOrigin;
       
  1560 }
       
  1561 
       
  1562 // -------------------------------------------------------------------------
       
  1563 // CGDIDeviceContext::PaintMode
       
  1564 //
       
  1565 // -----------------------------------------------------------------------------
       
  1566 //
       
  1567 NW_GDI_PaintMode_t
       
  1568 CGDIDeviceContext::PaintMode () const
       
  1569 {
       
  1570   return iPaintMode;
       
  1571 }
       
  1572 
       
  1573 // -------------------------------------------------------------------------
       
  1574 // CGDIDeviceContext::GetScaledCFont
       
  1575 // This method takes GDI font as a parameter, updates its size according
       
  1576 // to font size level and returns corresponding CFont*
       
  1577 //
       
  1578 // -----------------------------------------------------------------------------
       
  1579 //
       
  1580 void*
       
  1581 CGDIDeviceContext::GetScaledCFont (CGDIFont* aFont) const
       
  1582     {
       
  1583     // parameter assertion block
       
  1584     NW_ASSERT (aFont);
       
  1585 
       
  1586   return (CFont*)aFont->GetEpocNativeFont();
       
  1587     }
       
  1588 
       
  1589 // -------------------------------------------------------------------------
       
  1590 // CGDIDeviceContext::TextDirection
       
  1591 //
       
  1592 // -----------------------------------------------------------------------------
       
  1593 //
       
  1594 NW_GDI_TextDirection_t
       
  1595 CGDIDeviceContext::TextDirection () const
       
  1596 {
       
  1597   // return the desired property
       
  1598   return iTextDirection;
       
  1599 }
       
  1600 
       
  1601 // -------------------------------------------------------------------------
       
  1602 // CGDIDeviceContext::GetTextExtent
       
  1603 // The purpose of this function is to calculate the length of a string (in
       
  1604 // pixels
       
  1605 //
       
  1606 // -----------------------------------------------------------------------------
       
  1607 //
       
  1608 TBrowserStatusCode
       
  1609 CGDIDeviceContext::GetTextExtent (const NW_Text_t* aText,
       
  1610                                   CGDIFont* aGDIFont,
       
  1611                                   NW_GDI_Metric_t aSpacing,
       
  1612                                   NW_GDI_FlowDirection_t aFlowDirection,
       
  1613                                   NW_GDI_Dimension2D_t* aExtent) const
       
  1614   {
       
  1615   TText16* string = NULL;
       
  1616   NW_Text_Length_t length;
       
  1617   NW_Text_Length_t trimmedLen;
       
  1618   NW_Text_Length_t i;
       
  1619   TBool freeNeeded = NW_FALSE;
       
  1620 
       
  1621   NW_REQUIRED_PARAM(aSpacing);
       
  1622 
       
  1623   // parameter assertion block
       
  1624   NW_ASSERT (aText);
       
  1625   NW_ASSERT (aExtent);
       
  1626 
       
  1627   NW_TRY (status)
       
  1628     {
       
  1629     (void) NW_Mem_memset (aExtent, 0, sizeof (*aExtent));
       
  1630 
       
  1631     // Get the aText as unicode
       
  1632     string =
       
  1633       NW_Text_GetUCS2Buffer (aText,
       
  1634                              NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy,
       
  1635                              &length,
       
  1636                              (unsigned char*) &freeNeeded);
       
  1637 
       
  1638     if (length == 0)
       
  1639       {
       
  1640       NW_THROW_STATUS (status, KBrsrSuccess);
       
  1641       }
       
  1642 
       
  1643     if (!string)
       
  1644       {
       
  1645       NW_THROW_STATUS (status, KBrsrOutOfMemory);
       
  1646       }
       
  1647 
       
  1648     // Trim the string
       
  1649     trimmedLen = 0;
       
  1650     for (i = 0; i < length; i++)
       
  1651       {
       
  1652       if ((string[i] == NW_TEXT_UCS2_SOFT_HYPHEN) || (string[i] == NW_TEXT_UCS2_CR))
       
  1653         {
       
  1654         continue;
       
  1655         }
       
  1656       else if ((string[i] == NW_TEXT_UCS2_TAB) || (string[i] == NW_TEXT_UCS2_NBSP))
       
  1657         {
       
  1658         // In vertical-layout mode we want to ignore nbsp within a table cell
       
  1659         if (iRemoveNbsp)
       
  1660           {
       
  1661           continue;
       
  1662           }
       
  1663         string[trimmedLen++] = ' ';
       
  1664         }
       
  1665       else
       
  1666         {
       
  1667         string[trimmedLen++] = string[i];
       
  1668    	    }
       
  1669       }
       
  1670     string[trimmedLen] = 0;
       
  1671 
       
  1672  	// Lowercase letters will be rendered as uppercase characters
       
  1673     // Font size remains intact (according to spec)
       
  1674 
       
  1675     if(aGDIFont->FontVariant() == EGDIFontVariantSmallCaps)
       
  1676       {
       
  1677       if(!freeNeeded)
       
  1678         {
       
  1679         string = NW_Text_GetUCS2Buffer(aText, NW_Text_Flags_Copy, NULL, NULL);
       
  1680         NW_THROW_OOM_ON_NULL (string, status);
       
  1681 
       
  1682         freeNeeded = NW_TRUE;
       
  1683         }
       
  1684         NW_Str_Strupr((TText16*)string);
       
  1685       }
       
  1686 
       
  1687     CFont* epocFont = (CFont*)aGDIFont->GetEpocNativeFont();
       
  1688 
       
  1689     TPtrC ptrC(string);
       
  1690 
       
  1691     TInt width = epocFont->TextWidthInPixels(ptrC);
       
  1692     width += (length-1)*aSpacing;
       
  1693 
       
  1694     TInt height = 0;
       
  1695     if (width)
       
  1696       {
       
  1697       height = epocFont->HeightInPixels();
       
  1698       }
       
  1699 
       
  1700     if (aFlowDirection == NW_GDI_FlowDirection_LeftRight ||
       
  1701         aFlowDirection == NW_GDI_FlowDirection_RightLeft)
       
  1702       {
       
  1703       aExtent->width=(NW_GDI_Metric_t)width;
       
  1704       aExtent->height=(NW_GDI_Metric_t)height;
       
  1705       }
       
  1706     else
       
  1707       {
       
  1708       aExtent->width=(NW_GDI_Metric_t)height;
       
  1709       aExtent->height=(NW_GDI_Metric_t)width;
       
  1710       }
       
  1711 
       
  1712     if (aExtent->width)
       
  1713       {
       
  1714       aExtent->width = (NW_GDI_Metric_t)(aExtent->width + 1);
       
  1715       }
       
  1716     if (aExtent->height)
       
  1717       {
       
  1718       if (iVariantFlag == EApacVariant)
       
  1719         {
       
  1720         aExtent->height = (NW_GDI_Metric_t)(aExtent->height + 3);
       
  1721         }
       
  1722       else
       
  1723         {
       
  1724 		aExtent->height = (NW_GDI_Metric_t)(aExtent->height + 1);
       
  1725 		}
       
  1726       }
       
  1727 
       
  1728     }
       
  1729   NW_CATCH (status)
       
  1730     {
       
  1731     }
       
  1732   NW_FINALLY
       
  1733     {
       
  1734     // cleanup!
       
  1735     if (freeNeeded)
       
  1736       {
       
  1737       NW_Mem_Free (string);
       
  1738       }
       
  1739     // successful completion
       
  1740     return status;
       
  1741     }
       
  1742   NW_END_TRY;
       
  1743   }
       
  1744 
       
  1745 // -------------------------------------------------------------------------
       
  1746 // CGDIDeviceContext::PreDraw
       
  1747 // The purpose of this function is to clean up the screen for next draw
       
  1748 //
       
  1749 // -----------------------------------------------------------------------------
       
  1750 //
       
  1751 void
       
  1752 CGDIDeviceContext::PreDraw ()
       
  1753 {
       
  1754   NW_GDI_Rectangle_t rect;
       
  1755 
       
  1756   rect.point.x = (NW_GDI_Metric_t)(iClipRect.point.x + iOrigin.x);
       
  1757   rect.point.y = (NW_GDI_Metric_t)(iClipRect.point.y + iOrigin.y);
       
  1758   rect.dimension.width = iClipRect.dimension.width;
       
  1759   rect.dimension.height = iClipRect.dimension.height;
       
  1760 
       
  1761   FillRectangle(&rect);
       
  1762 }
       
  1763 
       
  1764 // -------------------------------------------------------------------------
       
  1765 // CGDIDeviceContext::PostDraw
       
  1766 // The purpose of this function is to redraw the screen partially.  redraw
       
  1767 // area should be given
       
  1768 //
       
  1769 // -----------------------------------------------------------------------------
       
  1770 //
       
  1771 void
       
  1772 CGDIDeviceContext::PostDraw ( TBool aDrawNow)
       
  1773 {
       
  1774   iOocEpoc32View->EpocDrawNow ((unsigned char)aDrawNow);
       
  1775 }
       
  1776 
       
  1777 // -------------------------------------------------------------------------
       
  1778 // CGDIDeviceContext::SetBackgroundColor
       
  1779 //
       
  1780 // -----------------------------------------------------------------------------
       
  1781 //
       
  1782 void
       
  1783 CGDIDeviceContext::SetBackgroundColor (NW_GDI_Color_t aColor)
       
  1784 {
       
  1785   iBackgroundColor = SwapColorBytes(aColor);
       
  1786 }
       
  1787 
       
  1788 // -------------------------------------------------------------------------
       
  1789 // CGDIDeviceContext::SetClipRect
       
  1790 //
       
  1791 // -----------------------------------------------------------------------------
       
  1792 //
       
  1793 void
       
  1794 CGDIDeviceContext::SetClipRect (const NW_GDI_Rectangle_t* aRectangle)
       
  1795 {
       
  1796   if(aRectangle) {
       
  1797     iClipRect.point.x = (NW_GDI_Metric_t)
       
  1798                                 ((aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x) > 0 ?
       
  1799                                  (aRectangle->point.x - iOrigin.x + iDisplayBounds.point.x) : 0);
       
  1800 
       
  1801     iClipRect.point.y = (NW_GDI_Metric_t)
       
  1802                                 ((aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y) > 0 ?
       
  1803                                  (aRectangle->point.y - iOrigin.y + iDisplayBounds.point.y) : 0);
       
  1804     iClipRect.dimension.width = (NW_GDI_Metric_t)((aRectangle->dimension.width + 1) >
       
  1805                                         iDisplayBounds.dimension.width ?
       
  1806                                         iDisplayBounds.dimension.width :
       
  1807                                         aRectangle->dimension.width);
       
  1808     iClipRect.dimension.height = (NW_GDI_Metric_t)((aRectangle->dimension.height + 1) >
       
  1809                                          iDisplayBounds.dimension.height ?
       
  1810                                          iDisplayBounds.dimension.height :
       
  1811                                          aRectangle->dimension.height);
       
  1812   }
       
  1813   else {
       
  1814     iClipRect = iDisplayBounds;
       
  1815   }
       
  1816 }
       
  1817 
       
  1818 // -------------------------------------------------------------------------
       
  1819 // CGDIDeviceContext::SetFillPattern
       
  1820 //
       
  1821 // -----------------------------------------------------------------------------
       
  1822 //
       
  1823 void
       
  1824 CGDIDeviceContext::SetFillPattern (NW_GDI_Pattern_t aFillPattern)
       
  1825 {
       
  1826   iFillPattern = aFillPattern;
       
  1827 }
       
  1828 
       
  1829 // -------------------------------------------------------------------------
       
  1830 // CGDIDeviceContext::SetForegroundColor
       
  1831 //
       
  1832 // -----------------------------------------------------------------------------
       
  1833 //
       
  1834 void
       
  1835 CGDIDeviceContext::SetForegroundColor (NW_GDI_Color_t aColor)
       
  1836 {
       
  1837   iForegroundColor = SwapColorBytes(aColor);
       
  1838 }
       
  1839 
       
  1840 // -------------------------------------------------------------------------
       
  1841 // CGDIDeviceContext::SetLinePattern
       
  1842 //
       
  1843 // -----------------------------------------------------------------------------
       
  1844 //
       
  1845 void
       
  1846 CGDIDeviceContext::SetLinePattern (NW_GDI_Pattern_t aLinePattern)
       
  1847 {
       
  1848   iLinePattern = aLinePattern;
       
  1849 }
       
  1850 
       
  1851 // -------------------------------------------------------------------------
       
  1852 // CGDIDeviceContext::SetLineWidth
       
  1853 //
       
  1854 // -----------------------------------------------------------------------------
       
  1855 //
       
  1856 void
       
  1857 CGDIDeviceContext::SetLineWidth (NW_GDI_Metric_t aLineWidth)
       
  1858 {
       
  1859   // set the property
       
  1860   iLineWidth = aLineWidth;
       
  1861 }
       
  1862 
       
  1863 // -------------------------------------------------------------------------
       
  1864 // CGDIDeviceContext::SetOrigin
       
  1865 //
       
  1866 // -----------------------------------------------------------------------------
       
  1867 //
       
  1868 void
       
  1869 CGDIDeviceContext::SetOrigin (const NW_GDI_Point2D_t* aOrigin)
       
  1870 {
       
  1871   NW_ASSERT(aOrigin);
       
  1872 
       
  1873   // set the property
       
  1874   iOrigin=*aOrigin;
       
  1875 }
       
  1876 
       
  1877 // -------------------------------------------------------------------------
       
  1878 // CGDIDeviceContext::SetPaintMode
       
  1879 //
       
  1880 // -----------------------------------------------------------------------------
       
  1881 //
       
  1882 void
       
  1883 CGDIDeviceContext::SetPaintMode (NW_GDI_PaintMode_t aPaintMode)
       
  1884 {
       
  1885   // set the property
       
  1886   iPaintMode = aPaintMode;
       
  1887 }
       
  1888 
       
  1889 // -------------------------------------------------------------------------
       
  1890 // CGDIDeviceContext::SetTextDirection
       
  1891 //
       
  1892 // -----------------------------------------------------------------------------
       
  1893 //
       
  1894 void
       
  1895 CGDIDeviceContext::SetTextDirection (NW_GDI_TextDirection_t aTextDirection)
       
  1896 {
       
  1897   NW_REQUIRED_PARAM (aTextDirection);
       
  1898 
       
  1899   // set the property
       
  1900   iTextDirection = aTextDirection;
       
  1901 }
       
  1902 
       
  1903 // -------------------------------------------------------------------------
       
  1904 // CGDIDeviceContext::SetDisplayBounds
       
  1905 //
       
  1906 // -----------------------------------------------------------------------------
       
  1907 //
       
  1908 void
       
  1909 CGDIDeviceContext::SetDisplayBounds (const NW_GDI_Rectangle_t* aRectangle)
       
  1910 {
       
  1911   // set the desired property
       
  1912   iDisplayBounds = *aRectangle;
       
  1913   iClipRect = iDisplayBounds;
       
  1914 }
       
  1915 
       
  1916 // -------------------------------------------------------------------------
       
  1917 // CGDIDeviceContext::CreateFont
       
  1918 //
       
  1919 // -----------------------------------------------------------------------------
       
  1920 //
       
  1921 CGDIFont*
       
  1922 CGDIDeviceContext::CreateFont (const NW_Text_t* aFamily,
       
  1923                                TGDIFontStyle aStyle,
       
  1924                                TUint8 aSizeInPixels,
       
  1925                                TUint16 aWeight,
       
  1926                                TGDIFontVariant aVariant) const
       
  1927     {
       
  1928     // ignore err, because function is handling the error when font created is NULL
       
  1929     CGDIFont* font = NULL;
       
  1930 
       
  1931     // convert font size from pixels to twips
       
  1932     TUint16 sizeInTwips = (TUint16)iWsScreenDev->VerticalPixelsToTwips((TInt)aSizeInPixels);
       
  1933 
       
  1934 	TInt err;
       
  1935     TRAP( err, font = CGDIFont::NewL( this, aFamily, aStyle, sizeInTwips, aWeight, aVariant ) );
       
  1936     return font;
       
  1937     }
       
  1938 
       
  1939 // -------------------------------------------------------------------------
       
  1940 // CGDIDeviceContext::DrawLine
       
  1941 //
       
  1942 // -----------------------------------------------------------------------------
       
  1943 //
       
  1944 void
       
  1945 CGDIDeviceContext::DrawLine (NW_GDI_Point2D_t aStartPoint,
       
  1946                                       NW_GDI_Point2D_t aEndPoint)
       
  1947 {
       
  1948   CBitmapContext* gc = Epoc32GraphicsContext();
       
  1949 	if (iLinePattern != NW_GDI_Pattern_None)
       
  1950   {
       
  1951 		gc->SetPenStyle((CGraphicsContext::TPenStyle)(iLinePattern));
       
  1952   }
       
  1953 
       
  1954 	gc->DrawLine( TPoint( aStartPoint.x - iOrigin.x + iDisplayBounds.point.x,
       
  1955                           aStartPoint.y - iOrigin.y + iDisplayBounds.point.y),
       
  1956                   TPoint( aEndPoint.x - iOrigin.x + iDisplayBounds.point.x,
       
  1957                           aEndPoint.y - iOrigin.y + iDisplayBounds.point.y ) );
       
  1958 }
       
  1959 
       
  1960 // -------------------------------------------------------------------------
       
  1961 // CGDIDeviceContext::SetFontSizeLevel
       
  1962 //
       
  1963 // -----------------------------------------------------------------------------
       
  1964 //
       
  1965 TBool
       
  1966 CGDIDeviceContext::SetFontSizeLevel ()
       
  1967 {
       
  1968   TGDIDeviceContextFontSizeLevel fontSizeLevel;
       
  1969 
       
  1970   fontSizeLevel = (TGDIDeviceContextFontSizeLevel)NW_Settings_GetFontSizeLevel();
       
  1971   if (iFontSizeLevel == fontSizeLevel){
       
  1972     return NW_FALSE;
       
  1973   }
       
  1974 
       
  1975   switch(fontSizeLevel)
       
  1976   {
       
  1977     case EGDIDeviceContextFontSizeLevelAllSmall:
       
  1978     case EGDIDeviceContextFontSizeLevelSmaller:
       
  1979     case EGDIDeviceContextFontSizeLevelNormal:
       
  1980     case EGDIDeviceContextFontSizeLevelLarger:
       
  1981     case EGDIDeviceContextFontSizeLevelAllLarge:
       
  1982       iFontSizeLevel = fontSizeLevel;
       
  1983       return NW_TRUE;
       
  1984 
       
  1985     default:
       
  1986       return NW_FALSE;
       
  1987   }
       
  1988 
       
  1989 }
       
  1990 
       
  1991 // -----------------------------------------------------------------------------
       
  1992 // CGDIDeviceContext::ChangeFontSize
       
  1993 //
       
  1994 // -----------------------------------------------------------------------------
       
  1995 //
       
  1996 void
       
  1997 CGDIDeviceContext::ChangeFontSize (CGDIFont* aFont)
       
  1998 {
       
  1999   TInt16 fontSize;
       
  2000   TInt16 difference;
       
  2001   TInt16 newFontSize;
       
  2002 
       
  2003   switch(iFontSizeLevel)
       
  2004   {
       
  2005     case EGDIDeviceContextFontSizeLevelAllSmall:
       
  2006       // show text 40% smaller than the declared size
       
  2007       fontSize = aFont->DeclaredFontSize();
       
  2008       difference = (TInt16)((float)fontSize / 2.5);
       
  2009       newFontSize = (TInt16)(fontSize - difference);
       
  2010 
       
  2011       aFont->SetFontSize((TUint16)newFontSize);
       
  2012       return;
       
  2013     case EGDIDeviceContextFontSizeLevelSmaller:
       
  2014       // show text 20% smaller than the declared size
       
  2015       fontSize = aFont->DeclaredFontSize();
       
  2016       difference = (TInt16)((float)fontSize / 5);
       
  2017       newFontSize = (TInt16)(fontSize - difference);
       
  2018 
       
  2019       aFont->SetFontSize((TUint16)newFontSize);
       
  2020       return;
       
  2021     case EGDIDeviceContextFontSizeLevelNormal:
       
  2022       // show text to be the declared size
       
  2023       fontSize = aFont->DeclaredFontSize();
       
  2024 
       
  2025       aFont->SetFontSize((TUint16)fontSize);
       
  2026       return;
       
  2027     case EGDIDeviceContextFontSizeLevelLarger:
       
  2028       // show text 20% larger than the declared size
       
  2029       fontSize = aFont->DeclaredFontSize();
       
  2030       difference = (TInt16)((float)fontSize / 5);
       
  2031       newFontSize = (TInt16)(fontSize + difference);
       
  2032 
       
  2033       aFont->SetFontSize((TUint16)newFontSize);
       
  2034       return;
       
  2035     case EGDIDeviceContextFontSizeLevelAllLarge:
       
  2036       // show text 40% larger than the declared size
       
  2037       fontSize = aFont->DeclaredFontSize();
       
  2038       difference = (TInt16)((float)fontSize / 2.5);
       
  2039       newFontSize = (TInt16)(fontSize + difference);
       
  2040 
       
  2041       aFont->SetFontSize((TUint16)newFontSize);
       
  2042       return;
       
  2043     default:
       
  2044       return;
       
  2045   }
       
  2046 }
       
  2047 
       
  2048 // ----------------------------------------------------------------------------
       
  2049 // CGDIDeviceContext::GetHighlightColor
       
  2050 //
       
  2051 // -----------------------------------------------------------------------------
       
  2052 //
       
  2053 void
       
  2054 CGDIDeviceContext::GetHighlightColor (NW_GDI_Color_t* aColor)
       
  2055 {
       
  2056   NW_ASSERT (aColor);
       
  2057   TRgb col = CEikonEnv::Static()->Color(EColorControlHighlightBackground);
       
  2058 
       
  2059   *aColor = NW_GDI_RGB(col.Red(), col.Green(), col.Blue());
       
  2060 }
       
  2061 
       
  2062 // -----------------------------------------------------------------------------
       
  2063 // CGDIDeviceContext::SwitchAgainstBG
       
  2064 // switch the color to white if the background color is dark enough,
       
  2065 // i.e. darker than half of the white color indensity.
       
  2066 //
       
  2067 // -----------------------------------------------------------------------------
       
  2068 //
       
  2069 void
       
  2070 CGDIDeviceContext::SwitchAgainstBG( NW_GDI_Color_t* aColor)
       
  2071 {
       
  2072   NW_GDI_Color_t rValue = 0;
       
  2073   NW_GDI_Color_t gValue = 0;
       
  2074   NW_GDI_Color_t bValue = 0;
       
  2075   NW_GDI_Color_t bgColor = 0;
       
  2076 
       
  2077   bgColor = BackgroundColor();
       
  2078 
       
  2079   rValue = NW_GDI_GetRValue(bgColor);
       
  2080   gValue = NW_GDI_GetGValue(bgColor);
       
  2081   bValue = NW_GDI_GetBValue(bgColor);
       
  2082 
       
  2083   if ((rValue+gValue+bValue) < 384){
       
  2084     *aColor = SwapColorBytes(NW_GDI_Color_White);
       
  2085   }
       
  2086 }
       
  2087 
       
  2088 // -----------------------------------------------------------------------------
       
  2089 // CGDIDeviceContext::SplitText
       
  2090 //
       
  2091 // -----------------------------------------------------------------------------
       
  2092 //
       
  2093 TBrowserStatusCode
       
  2094 CGDIDeviceContext::SplitText (NW_Text_t* aText,
       
  2095                               CGDIFont* aGDIFont,
       
  2096                               NW_GDI_Metric_t aConstraint,
       
  2097                               NW_GDI_Metric_t aSpacing,
       
  2098                               NW_GDI_FlowDirection_t aFlowDirection,
       
  2099                               NW_Text_Length_t* aLength,
       
  2100                               TUint8 aMode)
       
  2101   {
       
  2102   if (aMode == NW_GDI_SplitMode_Newline)
       
  2103     {
       
  2104     return SplitAtNewline (aText, aGDIFont, aConstraint, aSpacing, aFlowDirection, aLength);
       
  2105     }
       
  2106   else if (aMode == NW_GDI_SplitMode_Clip)
       
  2107     {
       
  2108     return Truncate (aText, aGDIFont, aConstraint, aSpacing, aFlowDirection, aLength);
       
  2109     }
       
  2110   else
       
  2111     {
       
  2112     return WordWrap(aText, aGDIFont, aConstraint, aSpacing, aFlowDirection, aLength);
       
  2113     }
       
  2114   }
       
  2115 
       
  2116 // -----------------------------------------------------------------------------
       
  2117 // CGDIDeviceContext::GetSubstringExtent
       
  2118 //
       
  2119 // -----------------------------------------------------------------------------
       
  2120 //
       
  2121 TBrowserStatusCode
       
  2122 CGDIDeviceContext::GetSubstringExtent (const NW_Text_t* aText,
       
  2123                                        CGDIFont* aGDIFont,
       
  2124                                        NW_Text_Length_t aStart,
       
  2125                                        NW_Text_Length_t aLength,
       
  2126                                        NW_GDI_Metric_t aSpacing,
       
  2127                                        NW_GDI_FlowDirection_t aFlowDirection,
       
  2128                                        NW_GDI_Dimension2D_t* aExtent)
       
  2129 {
       
  2130   NW_Text_t* frag = NULL;
       
  2131   NW_Text_Length_t totalLength;
       
  2132   TText16* storage = NULL;
       
  2133   TBool freeNeeded = NW_FALSE;
       
  2134 
       
  2135   NW_Mem_memset(aExtent, 0, sizeof(NW_GDI_Dimension2D_t));
       
  2136 
       
  2137   NW_TRY(status) {
       
  2138 
       
  2139     storage = NW_Text_GetUCS2Buffer (aText, 0, &totalLength, (unsigned char*) &freeNeeded);
       
  2140     NW_THROW_OOM_ON_NULL(storage, status);
       
  2141 
       
  2142     if (totalLength < aStart + aLength) {
       
  2143       NW_THROW_STATUS(status, KBrsrFailure);
       
  2144     }
       
  2145 
       
  2146     if (aLength == 0) {
       
  2147       NW_THROW_SUCCESS(status);
       
  2148     }
       
  2149 
       
  2150     frag = (NW_Text_t*)NW_Text_UCS2_New(&storage[aStart], aLength, 0);
       
  2151     NW_THROW_OOM_ON_NULL(frag, status);
       
  2152 
       
  2153     status = GetTextExtent (frag, aGDIFont, aSpacing, aFlowDirection, aExtent);
       
  2154     NW_THROW_ON_ERROR(status);
       
  2155   }
       
  2156   NW_CATCH(status) {
       
  2157   }
       
  2158   NW_FINALLY {
       
  2159 
       
  2160     if (freeNeeded) {
       
  2161       NW_Str_Delete(storage);
       
  2162     }
       
  2163     NW_Object_Delete(frag);
       
  2164 
       
  2165     return status;
       
  2166   } NW_END_TRY;
       
  2167 }
       
  2168 
       
  2169 // -----------------------------------------------------------------------------
       
  2170 // CGDIDeviceContext::FindFont
       
  2171 //
       
  2172 // -----------------------------------------------------------------------------
       
  2173 //
       
  2174 CFont*
       
  2175 CGDIDeviceContext::FindFont (TFontSpec aFontSpec)
       
  2176     {
       
  2177 	CFont* font = (CFont*)iFontCache->Search(aFontSpec);
       
  2178 
       
  2179     if (!font) // not found in cache
       
  2180         {
       
  2181         // we should always get a font back from the Avkon
       
  2182         font = AknFontAccess::GetClosestFont( *iWsScreenDev,
       
  2183                                               aFontSpec.iFontStyle,
       
  2184                                               aFontSpec.iHeight,
       
  2185                                               aFontSpec.iTypeface.iName );
       
  2186 
       
  2187         CFont* discardFont = iFontCache->AddEntryL( (CFont*&)font, aFontSpec );
       
  2188         if (discardFont)
       
  2189             {
       
  2190             iWsScreenDev->ReleaseFont( discardFont );
       
  2191             }
       
  2192         }
       
  2193 
       
  2194     return font;
       
  2195     }
       
  2196 
       
  2197 // -----------------------------------------------------------------------------
       
  2198 // CGDIDeviceContext::SetRemoveNbsp
       
  2199 //
       
  2200 // -----------------------------------------------------------------------------
       
  2201 void
       
  2202 CGDIDeviceContext::SetRemoveNbsp( TBool aFlag )
       
  2203     {
       
  2204     iRemoveNbsp = aFlag;
       
  2205     }
       
  2206 
       
  2207 // -----------------------------------------------------------------------------
       
  2208 // CGDIDeviceContext::RemoveNbsp
       
  2209 //
       
  2210 // -----------------------------------------------------------------------------
       
  2211 //
       
  2212 TBool
       
  2213 CGDIDeviceContext::RemoveNbsp()
       
  2214 {
       
  2215   return iRemoveNbsp;
       
  2216 }
       
  2217 
       
  2218 // -----------------------------------------------------------------------------
       
  2219 // CGDIDeviceContext::SetGraphicsContext
       
  2220 //
       
  2221 // -----------------------------------------------------------------------------
       
  2222 //
       
  2223 void
       
  2224 CGDIDeviceContext::SetGraphicsContext( void* aGraphicsContext )
       
  2225 {
       
  2226   iGraphicsContext = aGraphicsContext;
       
  2227 }
       
  2228 
       
  2229 // -----------------------------------------------------------------------------
       
  2230 // CGDIDeviceContext::SetFontSizeLevel
       
  2231 //
       
  2232 // -----------------------------------------------------------------------------
       
  2233 //
       
  2234 void
       
  2235 CGDIDeviceContext::SetFontSizeLevel( TGDIDeviceContextFontSizeLevel aFontSizeLevel )
       
  2236 {
       
  2237   iFontSizeLevel = aFontSizeLevel;
       
  2238 }
       
  2239 
       
  2240 // -----------------------------------------------------------------------------
       
  2241 // CGDIDeviceContext::VariantFlag
       
  2242 //
       
  2243 // -----------------------------------------------------------------------------
       
  2244 //
       
  2245 EVariantFlag
       
  2246 CGDIDeviceContext::VariantFlag()
       
  2247 {
       
  2248   return iVariantFlag;
       
  2249 }
       
  2250 
       
  2251 TGDISupportedLanguage
       
  2252 CGDIDeviceContext::SupportedLanguage()
       
  2253     {
       
  2254     return iSupportedLanguage;
       
  2255     }
       
  2256 
       
  2257 // -----------------------------------------------------------------------------
       
  2258 // CGDIDeviceContext::CanSplit
       
  2259 //
       
  2260 // -----------------------------------------------------------------------------
       
  2261 //
       
  2262 TBool
       
  2263 CGDIDeviceContext::CanSplit( TText16 aChar1, TText16 aChar2 )
       
  2264     {
       
  2265     CGDIDeviceContext* self = const_cast<CGDIDeviceContext*> (this);
       
  2266     if ( (aChar1 == 0) || (aChar2 == 0) ||
       
  2267           NW_Str_Isspace( aChar1 ) || NW_Str_Isspace( aChar2 ) ||
       
  2268          (aChar1 == NW_TEXT_UCS2_HYPHEN) ||
       
  2269          (aChar1 == NW_TEXT_UCS2_SOFT_HYPHEN) )
       
  2270         {
       
  2271         return ETrue;
       
  2272         }
       
  2273 
       
  2274     // Special case the Thai language, unicode chars 0x0E00 - 0x0E7F. For more
       
  2275     // details, see description of Thai characters at the top of this file.
       
  2276     //
       
  2277     // The description at the top of this file defined 3 concise rules for
       
  2278     // splitting:
       
  2279     //   1. Splits can occur at whitespace.
       
  2280     //   2. Splits can occur immediately preceding any LV.
       
  2281     //   3. Splits can occur immediately preceding any CONS that is not
       
  2282     //     immediately preceded by an LV.
       
  2283     //
       
  2284     // Rule #1, dealing with whitespace, was handled above. Here, rules 2 and
       
  2285     // 3 are handled.
       
  2286     if ( IS_THAI_CHAR( aChar1) && IS_THAI_CHAR( aChar2 ) )
       
  2287         {
       
  2288         // Rule #2: Splits can occur immediately preceding any LV.
       
  2289         if ( IS_THAI_LEADING_VOWEL( aChar2 ) )
       
  2290             {
       
  2291             return ETrue;
       
  2292             }
       
  2293         // Rule #3: Splits can occur immediately preceding any CONS that is not
       
  2294         //     immediately preceded by an LV.
       
  2295         if ( !IS_THAI_LEADING_VOWEL( aChar1 ) && IS_THAI_CONSONANT( aChar2 ) )
       
  2296             {
       
  2297             return ETrue;
       
  2298             }
       
  2299         }
       
  2300 
       
  2301     //For Chinese string and other character-based language string can be broke between any two characters.
       
  2302     //Also we considered the case if some western words are embeded in a APAC string.
       
  2303         else if (self->VariantFlag() == EApacVariant && (aChar2 > 255 || aChar1 > 255) )
       
  2304 	{
       
  2305         return ETrue;
       
  2306       }
       
  2307 
       
  2308     return EFalse;
       
  2309     }
       
  2310 
       
  2311 // -----------------------------------------------------------------------------
       
  2312 // CGDIDeviceContext::IsThaiCell
       
  2313 //
       
  2314 // -----------------------------------------------------------------------------
       
  2315 //
       
  2316 TBool
       
  2317 CGDIDeviceContext::IsThaiCell( TText16 aChar1, TText16 aChar2 )
       
  2318     {
       
  2319     if ( IS_THAI_CHAR( aChar1 ) && IS_THAI_CHAR( aChar2) )
       
  2320         {
       
  2321         // The following "if" statements are not arranged how one would
       
  2322         // traverse a Thai script "cell" from left to right. Instead, they
       
  2323         // are arranged by which is most likely to occur; thereby maximizing
       
  2324         // performance, albeit only slightly.
       
  2325         if ( (IS_THAI_COMBINING( aChar1 ) || IS_THAI_CONSONANT( aChar1 ))
       
  2326             && (IS_THAI_COMBINING( aChar2 ) || IS_THAI_FOLLOWING_VOWEL( aChar2 )) )
       
  2327             {
       
  2328             return ETrue;
       
  2329             }
       
  2330         if ( IS_THAI_LEADING_VOWEL( aChar1 ) && IS_THAI_CONSONANT( aChar2 ) )
       
  2331             {
       
  2332             return ETrue;
       
  2333             }
       
  2334         }
       
  2335     return EFalse;
       
  2336     }