os/graphics/fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,465 @@
     1.4 +// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <e32def.h>
    1.20 +#include <gdi.h>
    1.21 +#include <graphics/gdi/gdistructs.h>
    1.22 +#include <graphics/gdi/gdiconsts.h>
    1.23 +#include <graphics/fbsglyphdataiterator.h>
    1.24 +#include "FbsMessage.h"
    1.25 +#include "UTILS.H"
    1.26 +
    1.27 +const TInt KFbsGlyphDataIterCodeInvalid = -1;
    1.28 +
    1.29 +extern void Panic(TFbsPanic aPanic);
    1.30 +
    1.31 +/**
    1.32 +The default constructor sets the iterator to a closed and empty state. It 
    1.33 +is the only way of constructing an iterator as instances cannot be copied by 
    1.34 +assignment or passed by value.
    1.35 + */
    1.36 +EXPORT_C RFbsGlyphDataIterator::RFbsGlyphDataIterator() :
    1.37 +    iImpl(NULL)
    1.38 +    {
    1.39 +    }
    1.40 +
    1.41 +/**
    1.42 +For a given font (aFont), this method retrieves the glyph data for a list of 
    1.43 +glyph codes (aGlyphCodes), containing a number (aCount) of codes. On success, 
    1.44 +the iterator is initialised with the data for the first glyph in aGlyphCodes.
    1.45 +
    1.46 +The memory allocated to aGlyphCodes must not be freed or altered while the 
    1.47 +iterator is in use (i.e. until the iterator has been closed). 
    1.48 +
    1.49 +Open() may not be called on an already open iterator. In order to re-open an 
    1.50 +iterator, it must first be closed by a call tor Close().
    1.51 +
    1.52 +If a glyph code is passed in that is not a recognised glyph code for the 
    1.53 +associated font, an empty-box glyph will be returned. This behaviour is 
    1.54 +consistent with CFbsFont::GetCharacterData().
    1.55 +
    1.56 +@pre The iterator is not already open. 
    1.57 +
    1.58 +@param aFont The font to provide the glyph code data for.
    1.59 +@param aGlyphCodes An array of glyph codes that the iterator will 
    1.60 +	provide data for. This memory allocated for this array must not be 
    1.61 +	freed before the iterator is closed.
    1.62 +@param aCount The number of glyph codes in aGlyphCodes.
    1.63 +
    1.64 +@return 
    1.65 +	KErrNone, if the iterator is successfully initialised to retrieve 
    1.66 +		the glyph data;
    1.67 +	KErrInUse, if the iterator is already open, in which case the state of
    1.68 +        the iterator is left unchanged;
    1.69 +	KErrNoMemory, if the iterator cannot be opened due to insufficient 
    1.70 +		system memory;
    1.71 +	KErrNotSupported, if aFont refers to a bitmap font or an outline & shadow
    1.72 +        font, if the required version of the hardware driver is not available
    1.73 +        (EGL 1.3 or later is required), or if RSgImages are not supported by
    1.74 +        the system;
    1.75 +	KErrArgument, if aCount is negative or zero, or if aGlyphCodes is null.
    1.76 + */
    1.77 +EXPORT_C TInt RFbsGlyphDataIterator::Open(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount)
    1.78 +	{  
    1.79 +	if (iImpl)
    1.80 +		{
    1.81 +		return KErrInUse;
    1.82 +		}
    1.83 +	if ((aCount <= 0) || !aGlyphCodes)
    1.84 +		{
    1.85 +		return KErrArgument;
    1.86 +		}
    1.87 +	if (!aFont.Address()->IsOpenFont())
    1.88 +        {
    1.89 +        return KErrNotSupported;
    1.90 +        }
    1.91 +    TInt glyphBitmapType = aFont.Address()->GlyphBitmapType();
    1.92 +    if (!( (glyphBitmapType == EMonochromeGlyphBitmap) || (glyphBitmapType == EAntiAliasedGlyphBitmap) ))
    1.93 +        {
    1.94 +        //Only supported bitmap types can be used i.e. EMonochromeGlyphBitmap or EAntiAliasedGlyphBitmap
    1.95 +        return KErrNotSupported;
    1.96 +        }
    1.97 +    // Check that the max width and height of the font are both no more than 2048.
    1.98 +    // This is the smallest maximum size an RSgImage can be created with.
    1.99 +    // This limit is arbitrarily set as it should cover nearly all use cases.
   1.100 +    const TInt KMaxFontSizeInPixels = 2048;
   1.101 +    TInt maxHeight = aFont.FontMaxHeight();
   1.102 +    TInt maxWidth = aFont.MaxCharWidthInPixels();
   1.103 +    if ( (KMaxFontSizeInPixels < maxHeight) || (KMaxFontSizeInPixels < maxWidth) )
   1.104 +        {
   1.105 +        return KErrTooBig;
   1.106 +        }
   1.107 +    // Construct implementor object that holds the state for the iterator.
   1.108 +	iImpl = new CGlyphDataIteratorImpl(aFont.iHandle, aGlyphCodes, aCount);
   1.109 +	if (!iImpl)
   1.110 +	    {
   1.111 +	    return KErrNoMemory;
   1.112 +	    }
   1.113 +	TInt err = iImpl->Initialise();
   1.114 +	if (err != KErrNone)
   1.115 +	    {
   1.116 +        Close();
   1.117 +	    }
   1.118 +	return err;   
   1.119 +	}
   1.120 +
   1.121 +/**
   1.122 +Moves the iterator to the data for the next glyph code in the array passed 
   1.123 +into RFbsGlyphDataIterator::Open(). Data for the glyph can then be accessed 
   1.124 +using the Image(), Rect() and Metrics() methods.
   1.125 +
   1.126 +Once Next() has been called, the references returned by Image(), Rect() and 
   1.127 +Metrics() methods during the previous iteration should be considered invalid 
   1.128 +and must be discarded. 
   1.129 +
   1.130 +Calling Next() repeatedly will iterate through the glyph data for all the glyph
   1.131 +codes, until it has reached the last glyph code in the array (assuming no errors
   1.132 +are encountered), at which point KErrNotFound is returned, and the array of glyph
   1.133 +codes passed to RFbsGlyphDataIterator::Open() can safely be deleted.
   1.134 +
   1.135 +If the call was successful, KErrNone is returned. If an error is encountered an
   1.136 +error code will be returned and the state of the iterator is left unchanged.
   1.137 +
   1.138 +@pre The iterator has been opened by a successful call to Open().
   1.139 +@post The properties of the iterator are of the glyph corresponding
   1.140 +	to the next code passed in the array to Open().	However, if an error code 
   1.141 +	was returned, the state of the iterator	is unchanged.
   1.142 +	
   1.143 +@return 
   1.144 +	KErrNone, if the iterator was successfully advanced;
   1.145 +	KErrNotFound, if the iterator is already at the last element and cannot
   1.146 +		be advanced any further;
   1.147 +	KErrNoMemory, if there is insufficient system memory available;
   1.148 +	KErrNoGraphicsMemory, if there is insufficient graphics memory available.
   1.149 +	
   1.150 +@panic FBSCLI 31, if the iterator is not open.
   1.151 +@panic FBSERV -8, if as a result of this call, communication with the 
   1.152 +    server is invoked, and the associated CFbsFont has been destroyed.
   1.153 + */
   1.154 +EXPORT_C TInt RFbsGlyphDataIterator::Next()
   1.155 +    {
   1.156 +    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
   1.157 +    return iImpl->Next();
   1.158 +    }
   1.159 +
   1.160 +/**
   1.161 +Closes the iterator and releases its internal resources. After calling, all data 
   1.162 +retrieved by the iterator is no longer safe to use. Once closed, this iterator 
   1.163 +can be re-opened. Calling Close() on an already closed iterator has no effect.
   1.164 +
   1.165 +Once an iterator is closed, the array of glyphs (aGlyphCodes) passed to
   1.166 +RFbsGlyphDataIterator::Open() can safely be deleted.
   1.167 +
   1.168 +@post The iterator is closed.
   1.169 + */
   1.170 +EXPORT_C void RFbsGlyphDataIterator::Close()
   1.171 +    {
   1.172 +    delete iImpl;
   1.173 +    iImpl = NULL;
   1.174 +    }
   1.175 +
   1.176 +/**
   1.177 +Returns a reference to the RSgImage that contains the glyph for the current 
   1.178 +iteration. The image representation of the glyph is the same as the image 
   1.179 +returned by the existing CFbsFont::GetCharacterData() method (i.e. an alpha mask). 
   1.180 +
   1.181 +The RSgImage should only be considered a temporary handle for use in this 
   1.182 +iteration, and should not be used after a call to Next() or Close() has 
   1.183 +been made.
   1.184 +
   1.185 +Note: For glyphs such as space which have no visible representation, Image() 
   1.186 +will return a null image handle (i.e. RSgImage::IsNull() returns ETrue). This 
   1.187 +cannot be used for drawing. In this case Rect() will be empty however 
   1.188 +Metrics() will still be valid. 
   1.189 +
   1.190 +@pre The iterator has been initialised by successfully calling Open().
   1.191 +     
   1.192 +@return A handle to the image where the glyph for this iteration is stored.
   1.193 +     
   1.194 +@panic FBSCLI 31, if the iterator is not open.
   1.195 + */
   1.196 +EXPORT_C const RSgImage& RFbsGlyphDataIterator::Image() const
   1.197 +    {
   1.198 +    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
   1.199 +    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.200 +    return iImpl->iGlyphBatch.First()->iImage;
   1.201 +    }
   1.202 +
   1.203 +/**
   1.204 +Returns the area within the RSgImage where the glyph for the current
   1.205 +iteration is located. The reference returned by Rect() should be considered 
   1.206 +temporary for use within this iteration and should not be used after a call to 
   1.207 +Next() or Close() has been made.
   1.208 + 
   1.209 +@pre The iterator has been initialised by successfully calling Open().
   1.210 +     
   1.211 +@return A rectangle representing the position and size in pixels, 
   1.212 +	of the glyph for this iteration on the RSgImage provided by Image().
   1.213 +     
   1.214 +@panic FBSCLI 31, if the iterator is not open.
   1.215 + */
   1.216 +EXPORT_C const TRect& RFbsGlyphDataIterator::Rect() const
   1.217 +    {
   1.218 +    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
   1.219 +    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.220 +    return iImpl->iGlyphDataIterRect;
   1.221 +    }
   1.222 +
   1.223 +/**
   1.224 +Returns the glyph metrics for the current iteration. The reference returned by 
   1.225 +Metrics() should be considered temporary for use within this iteration and 
   1.226 +should not be used after a call to Next() or Close() has been made.
   1.227 +
   1.228 +@pre The iterator has been initialised by successfully calling Open().
   1.229 + 
   1.230 +@return The metrics for the glyph at the current iteration.
   1.231 +
   1.232 +@panic FBSCLI 31, if the iterator is not open.
   1.233 + */
   1.234 +EXPORT_C const TOpenFontCharMetrics& RFbsGlyphDataIterator::Metrics() const
   1.235 +    {
   1.236 +    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
   1.237 +    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.238 +    return iImpl->iGlyphBatch.First()->iInfo.iMetrics;
   1.239 +    }
   1.240 +
   1.241 +/**
   1.242 +Returns the glyph code associated with the data for the current iteration.
   1.243 +
   1.244 +@pre The iterator has been initialised by successfully calling Open().
   1.245 + 
   1.246 +@return The glyph code of the glyph at the current iteration.
   1.247 +
   1.248 +@panic FBSCLI 31, if the iterator is not open.
   1.249 + */
   1.250 +EXPORT_C TUint RFbsGlyphDataIterator::GlyphCode() const
   1.251 +    {
   1.252 +    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
   1.253 +    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.254 +    return iImpl->iGlyphDataIterCodes[iImpl->iGlyphDataIterCodeIndex];
   1.255 +    }
   1.256 +
   1.257 +
   1.258 +/**
   1.259 +Constructs a CGlyphDataIteratorImpl. 
   1.260 +@param aFbsFontHandle The handle of the FbsFont that the iterator is working with.
   1.261 +@param aGlyphCodes The array of glyph codes sent to RFbsGlyphDataIterator::Open()
   1.262 +@param aCount The number of glyph codes in aGlyphCodes.
   1.263 + */
   1.264 +CGlyphDataIteratorImpl::CGlyphDataIteratorImpl(TInt aFbsFontHandle, const TUint* aGlyphCodes, TInt aCount) :
   1.265 +    iGlyphBatch(_FOFF(TGlyphBatchItem, iLink)),
   1.266 +    iGlyphDataIterCodes(aGlyphCodes),
   1.267 +    iGlyphDataIterCodeCount(aCount),
   1.268 +    iGlyphDataIterCodeIndex(KFbsGlyphDataIterCodeInvalid),
   1.269 +    iFbsFontHandle(aFbsFontHandle)
   1.270 +    {
   1.271 +    }
   1.272 +
   1.273 +/** 
   1.274 +Destructor. Releases all resources, disconnects from server and frees any
   1.275 +items in the list of batched items.
   1.276 + */
   1.277 +CGlyphDataIteratorImpl::~CGlyphDataIteratorImpl()
   1.278 +    {
   1.279 +    if (iFbs)
   1.280 +        {
   1.281 +        if (iGlyphDataIterCodeIndex != KFbsGlyphDataIterCodeInvalid)
   1.282 +            {
   1.283 +            //Send the No-Op command to ensure that the "In Transit" RSgImage(s) are closed.
   1.284 +            iFbs->SendCommand(EFbsMessNoOp);
   1.285 +            }
   1.286 +        RFbsSession::Disconnect();
   1.287 +        iFbs = NULL;
   1.288 +        }
   1.289 +    while (!iGlyphBatch.IsEmpty())
   1.290 +        {
   1.291 +        TGlyphBatchItem* item = iGlyphBatch.First();
   1.292 +        item->iImage.Close();
   1.293 +        iGlyphBatch.Remove(*item);
   1.294 +        delete item;
   1.295 +        }
   1.296 +    iGlyphBatch.Reset();
   1.297 +    }
   1.298 +
   1.299 +/**
   1.300 +Sets up the CGlyphDataIteratorImpl, populating the first batch of glyphs.
   1.301 +Should only be called once, immediately after construction.
   1.302 + */
   1.303 +TInt CGlyphDataIteratorImpl::Initialise()
   1.304 +    {
   1.305 +    __ASSERT_DEBUG(iFbsFontHandle, Panic(EFbsPanicGlyphDataIteratorInvalidState));    
   1.306 +    __ASSERT_DEBUG(iGlyphDataIterCodes, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.307 +    __ASSERT_DEBUG(iGlyphDataIterCodeCount, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.308 +    __ASSERT_DEBUG(iGlyphDataIterCodeIndex == KFbsGlyphDataIterCodeInvalid, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.309 +    
   1.310 +    // If the client already has a session open, this is just a reference counting exercise and should incur no performance impact.
   1.311 +    TInt err = RFbsSession::Connect();
   1.312 +    if (err == KErrNone)
   1.313 +        {
   1.314 +        iFbs = RFbsSession::GetSession();
   1.315 +        err = UpdateGlyphBatch(0);
   1.316 +        }
   1.317 +    if (err == KErrNone)
   1.318 +        {
   1.319 +        iGlyphDataIterCodeIndex = 0;
   1.320 +        UpdateGlyphRect();
   1.321 +        }
   1.322 +    return err;
   1.323 +    }
   1.324 +
   1.325 +/**
   1.326 +Increments the current iteration if possible, re-sending the request
   1.327 +for more glyphs if the current batch of glyphs is down to the last
   1.328 +item.
   1.329 +@see RFbsGlyphDataIterator::Next()
   1.330 + */
   1.331 +TInt CGlyphDataIteratorImpl::Next()
   1.332 +    {
   1.333 +    __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.334 +    if ( (iGlyphDataIterCodeIndex + 1) >= iGlyphDataIterCodeCount) 
   1.335 +        {
   1.336 +        return KErrNotFound; 
   1.337 +        }
   1.338 +    TInt err = UpdateGlyphBatch(iGlyphDataIterCodeIndex + 1);
   1.339 +    if (err == KErrNone)
   1.340 +        {
   1.341 +        ++iGlyphDataIterCodeIndex;
   1.342 +        // Close the current image and pop the head of the batch.
   1.343 +        TGlyphBatchItem* item = iGlyphBatch.First();
   1.344 +        item->iImage.Close();
   1.345 +        iGlyphBatch.Remove(*item);
   1.346 +        delete item;
   1.347 +        __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.348 +        UpdateGlyphRect();
   1.349 +        }
   1.350 +    return err;
   1.351 +    }
   1.352 +
   1.353 +/**
   1.354 +Checks whether a call to the server is required to get a new batch of glyph 
   1.355 +info, and processes the response from the server as necessary.
   1.356 +
   1.357 +@param aIndex Specifies the index into the glyph array which needs to be in
   1.358 +the active glyph batch. If it is not there, a request is made to the server
   1.359 +to get it.
   1.360 +@return KErrNone if getting at least one glyph succeeded or a call to the
   1.361 +    server was not necessary, otherwise one of the system wide error codes.
   1.362 +@panic FBSCLI 31 (debug only), if the iterator is not open
   1.363 +@panic FBSCLI 33 (debug only), if an unexpected number of glyphs was received
   1.364 +    as a result of requesting glyphs from the server, or if the current batch
   1.365 +    of glyphs is empty when there should be at least one item.
   1.366 + */
   1.367 +TInt CGlyphDataIteratorImpl::UpdateGlyphBatch(TInt aIndex)
   1.368 +    {
   1.369 +    __ASSERT_DEBUG(Rng(0, aIndex, iGlyphDataIterCodeCount - 1), Panic(EFbsPanicGlyphDataIteratorIndexOutOfRange));
   1.370 +
   1.371 +    TInt err = KErrNone;
   1.372 +    
   1.373 +    TBool needMoreGlyphs = EFalse;
   1.374 +    if (iGlyphBatch.IsEmpty())
   1.375 +        {
   1.376 +        // Current batch is empty, must request more. Should only get here when the iterator 
   1.377 +        // is first opened, since one item should always be in the list from then on.
   1.378 +        __ASSERT_DEBUG(aIndex == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.379 +        needMoreGlyphs = ETrue;
   1.380 +        }
   1.381 +    else if (iGlyphBatch.IsLast(iGlyphBatch.First()))
   1.382 +        {
   1.383 +        // Only one item in the list. 
   1.384 +        needMoreGlyphs = ETrue;
   1.385 +        }
   1.386 +    
   1.387 +    if (needMoreGlyphs)
   1.388 +        {
   1.389 +        // If the array of batched images is empty OR only one left, means we need to request a new batch.
   1.390 +        // We make sure there is at least one glyph in the batch so the iterator is always usable even
   1.391 +        // when a failure to move to the next iteration occurs.
   1.392 +    
   1.393 +        TBool glyphAddedToBatch = EFalse;
   1.394 +        TUint glyphCodes[KMaxGlyphBatchSize];
   1.395 +        
   1.396 +        TInt numGlyphsToRequest = Min(iGlyphDataIterCodeCount - aIndex, KMaxGlyphBatchSize);        
   1.397 +        (void)Mem::Copy(glyphCodes, &(iGlyphDataIterCodes[aIndex]), sizeof(TUint) * numGlyphsToRequest);
   1.398 +        TPckg<TUint[KMaxGlyphBatchSize]> argGlyphCodes(glyphCodes);
   1.399 +        
   1.400 +        TGlyphImageInfo rcvdGlyphInfo[KMaxGlyphBatchSize];
   1.401 +        TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> argGlyphInfo(rcvdGlyphInfo);
   1.402 +        
   1.403 +        if (numGlyphsToRequest < KMaxGlyphBatchSize)
   1.404 +            {
   1.405 +            argGlyphCodes.SetLength(numGlyphsToRequest * sizeof(TUint));
   1.406 +            argGlyphInfo.SetLength(numGlyphsToRequest * sizeof(TGlyphImageInfo));
   1.407 +            }
   1.408 +        
   1.409 +        err = iFbs->SendCommand(EFbsMessGetGlyphs, TIpcArgs(iFbsFontHandle, &argGlyphCodes, &argGlyphInfo));
   1.410 +        if (err == KErrNone)
   1.411 +            {
   1.412 +            __ASSERT_DEBUG(argGlyphInfo.Length() % sizeof(TGlyphImageInfo) == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.413 +            TInt numRcvdGlyphs = argGlyphInfo.Length() / sizeof(TGlyphImageInfo);
   1.414 +            __ASSERT_DEBUG(numRcvdGlyphs > 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.415 +            __ASSERT_DEBUG(numRcvdGlyphs <= KMaxGlyphBatchSize, Panic(EFbsPanicGlyphDataIteratorInvalidState));
   1.416 +            
   1.417 +            // Store the received glyph data, and open the image handles so that the IDs
   1.418 +            // will not be released by FbServ between now and the client using them.
   1.419 +            // If a failure occurs while processing one of the recevied glyphs,
   1.420 +            // abort the rest but keep the ones that succeeded.
   1.421 +            for (TInt i = 0; (i < numRcvdGlyphs) && (err == KErrNone); ++i)
   1.422 +                {
   1.423 +                TGlyphBatchItem* glyphEntry = new TGlyphBatchItem;
   1.424 +                if (!glyphEntry)
   1.425 +                    {
   1.426 +                    err = KErrNoMemory;
   1.427 +                    }
   1.428 +                else
   1.429 +                    {
   1.430 +                    glyphEntry->iInfo = rcvdGlyphInfo[i];
   1.431 +                    
   1.432 +                    RSgImage glyphImage;
   1.433 +                    if (rcvdGlyphInfo[i].iImageId != KSgNullDrawableId)
   1.434 +                        {
   1.435 +                        err = glyphEntry->iImage.Open(rcvdGlyphInfo[i].iImageId);
   1.436 +                        }
   1.437 +                    if (err == KErrNone)
   1.438 +                        {
   1.439 +                        iGlyphBatch.AddLast(*glyphEntry);
   1.440 +                        glyphAddedToBatch = ETrue;
   1.441 +                        }
   1.442 +                    else
   1.443 +                        {
   1.444 +                        delete glyphEntry;
   1.445 +                        }
   1.446 +                    }
   1.447 +                }
   1.448 +            }
   1.449 +        if (err != KErrNone && glyphAddedToBatch)
   1.450 +            {
   1.451 +            // There was an error adding an item to the batch. Rather than return the
   1.452 +            // error to the client, ignore it and use what glyphs we successfully batched.
   1.453 +            err = KErrNone; 
   1.454 +            }
   1.455 +        }    
   1.456 +    return err;
   1.457 +    }
   1.458 +
   1.459 +/**
   1.460 +Updates the glyph rectangle member based on the current glyph metrics.
   1.461 +@post The iGlyphDataIterRect member is updated to reflect the position
   1.462 +    and size of the currently active glyph.
   1.463 + */
   1.464 +void CGlyphDataIteratorImpl::UpdateGlyphRect()
   1.465 +    {
   1.466 +    iGlyphDataIterRect.iTl = TPoint(iGlyphBatch.First()->iInfo.iPosX, iGlyphBatch.First()->iInfo.iPosY);
   1.467 +    iGlyphDataIterRect.SetSize(TSize(iGlyphBatch.First()->iInfo.iMetrics.Width(), iGlyphBatch.First()->iInfo.iMetrics.Height()));
   1.468 +    }