os/graphics/fbs/fontandbitmapserver/sfbs/fbsglyphdataiterator.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <e32def.h>
sl@0
    17
#include <gdi.h>
sl@0
    18
#include <graphics/gdi/gdistructs.h>
sl@0
    19
#include <graphics/gdi/gdiconsts.h>
sl@0
    20
#include <graphics/fbsglyphdataiterator.h>
sl@0
    21
#include "FbsMessage.h"
sl@0
    22
#include "UTILS.H"
sl@0
    23
sl@0
    24
const TInt KFbsGlyphDataIterCodeInvalid = -1;
sl@0
    25
sl@0
    26
extern void Panic(TFbsPanic aPanic);
sl@0
    27
sl@0
    28
/**
sl@0
    29
The default constructor sets the iterator to a closed and empty state. It 
sl@0
    30
is the only way of constructing an iterator as instances cannot be copied by 
sl@0
    31
assignment or passed by value.
sl@0
    32
 */
sl@0
    33
EXPORT_C RFbsGlyphDataIterator::RFbsGlyphDataIterator() :
sl@0
    34
    iImpl(NULL)
sl@0
    35
    {
sl@0
    36
    }
sl@0
    37
sl@0
    38
/**
sl@0
    39
For a given font (aFont), this method retrieves the glyph data for a list of 
sl@0
    40
glyph codes (aGlyphCodes), containing a number (aCount) of codes. On success, 
sl@0
    41
the iterator is initialised with the data for the first glyph in aGlyphCodes.
sl@0
    42
sl@0
    43
The memory allocated to aGlyphCodes must not be freed or altered while the 
sl@0
    44
iterator is in use (i.e. until the iterator has been closed). 
sl@0
    45
sl@0
    46
Open() may not be called on an already open iterator. In order to re-open an 
sl@0
    47
iterator, it must first be closed by a call tor Close().
sl@0
    48
sl@0
    49
If a glyph code is passed in that is not a recognised glyph code for the 
sl@0
    50
associated font, an empty-box glyph will be returned. This behaviour is 
sl@0
    51
consistent with CFbsFont::GetCharacterData().
sl@0
    52
sl@0
    53
@pre The iterator is not already open. 
sl@0
    54
sl@0
    55
@param aFont The font to provide the glyph code data for.
sl@0
    56
@param aGlyphCodes An array of glyph codes that the iterator will 
sl@0
    57
	provide data for. This memory allocated for this array must not be 
sl@0
    58
	freed before the iterator is closed.
sl@0
    59
@param aCount The number of glyph codes in aGlyphCodes.
sl@0
    60
sl@0
    61
@return 
sl@0
    62
	KErrNone, if the iterator is successfully initialised to retrieve 
sl@0
    63
		the glyph data;
sl@0
    64
	KErrInUse, if the iterator is already open, in which case the state of
sl@0
    65
        the iterator is left unchanged;
sl@0
    66
	KErrNoMemory, if the iterator cannot be opened due to insufficient 
sl@0
    67
		system memory;
sl@0
    68
	KErrNotSupported, if aFont refers to a bitmap font or an outline & shadow
sl@0
    69
        font, if the required version of the hardware driver is not available
sl@0
    70
        (EGL 1.3 or later is required), or if RSgImages are not supported by
sl@0
    71
        the system;
sl@0
    72
	KErrArgument, if aCount is negative or zero, or if aGlyphCodes is null.
sl@0
    73
 */
sl@0
    74
EXPORT_C TInt RFbsGlyphDataIterator::Open(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount)
sl@0
    75
	{  
sl@0
    76
	if (iImpl)
sl@0
    77
		{
sl@0
    78
		return KErrInUse;
sl@0
    79
		}
sl@0
    80
	if ((aCount <= 0) || !aGlyphCodes)
sl@0
    81
		{
sl@0
    82
		return KErrArgument;
sl@0
    83
		}
sl@0
    84
	if (!aFont.Address()->IsOpenFont())
sl@0
    85
        {
sl@0
    86
        return KErrNotSupported;
sl@0
    87
        }
sl@0
    88
    TInt glyphBitmapType = aFont.Address()->GlyphBitmapType();
sl@0
    89
    if (!( (glyphBitmapType == EMonochromeGlyphBitmap) || (glyphBitmapType == EAntiAliasedGlyphBitmap) ))
sl@0
    90
        {
sl@0
    91
        //Only supported bitmap types can be used i.e. EMonochromeGlyphBitmap or EAntiAliasedGlyphBitmap
sl@0
    92
        return KErrNotSupported;
sl@0
    93
        }
sl@0
    94
    // Check that the max width and height of the font are both no more than 2048.
sl@0
    95
    // This is the smallest maximum size an RSgImage can be created with.
sl@0
    96
    // This limit is arbitrarily set as it should cover nearly all use cases.
sl@0
    97
    const TInt KMaxFontSizeInPixels = 2048;
sl@0
    98
    TInt maxHeight = aFont.FontMaxHeight();
sl@0
    99
    TInt maxWidth = aFont.MaxCharWidthInPixels();
sl@0
   100
    if ( (KMaxFontSizeInPixels < maxHeight) || (KMaxFontSizeInPixels < maxWidth) )
sl@0
   101
        {
sl@0
   102
        return KErrTooBig;
sl@0
   103
        }
sl@0
   104
    // Construct implementor object that holds the state for the iterator.
sl@0
   105
	iImpl = new CGlyphDataIteratorImpl(aFont.iHandle, aGlyphCodes, aCount);
sl@0
   106
	if (!iImpl)
sl@0
   107
	    {
sl@0
   108
	    return KErrNoMemory;
sl@0
   109
	    }
sl@0
   110
	TInt err = iImpl->Initialise();
sl@0
   111
	if (err != KErrNone)
sl@0
   112
	    {
sl@0
   113
        Close();
sl@0
   114
	    }
sl@0
   115
	return err;   
sl@0
   116
	}
sl@0
   117
sl@0
   118
/**
sl@0
   119
Moves the iterator to the data for the next glyph code in the array passed 
sl@0
   120
into RFbsGlyphDataIterator::Open(). Data for the glyph can then be accessed 
sl@0
   121
using the Image(), Rect() and Metrics() methods.
sl@0
   122
sl@0
   123
Once Next() has been called, the references returned by Image(), Rect() and 
sl@0
   124
Metrics() methods during the previous iteration should be considered invalid 
sl@0
   125
and must be discarded. 
sl@0
   126
sl@0
   127
Calling Next() repeatedly will iterate through the glyph data for all the glyph
sl@0
   128
codes, until it has reached the last glyph code in the array (assuming no errors
sl@0
   129
are encountered), at which point KErrNotFound is returned, and the array of glyph
sl@0
   130
codes passed to RFbsGlyphDataIterator::Open() can safely be deleted.
sl@0
   131
sl@0
   132
If the call was successful, KErrNone is returned. If an error is encountered an
sl@0
   133
error code will be returned and the state of the iterator is left unchanged.
sl@0
   134
sl@0
   135
@pre The iterator has been opened by a successful call to Open().
sl@0
   136
@post The properties of the iterator are of the glyph corresponding
sl@0
   137
	to the next code passed in the array to Open().	However, if an error code 
sl@0
   138
	was returned, the state of the iterator	is unchanged.
sl@0
   139
	
sl@0
   140
@return 
sl@0
   141
	KErrNone, if the iterator was successfully advanced;
sl@0
   142
	KErrNotFound, if the iterator is already at the last element and cannot
sl@0
   143
		be advanced any further;
sl@0
   144
	KErrNoMemory, if there is insufficient system memory available;
sl@0
   145
	KErrNoGraphicsMemory, if there is insufficient graphics memory available.
sl@0
   146
	
sl@0
   147
@panic FBSCLI 31, if the iterator is not open.
sl@0
   148
@panic FBSERV -8, if as a result of this call, communication with the 
sl@0
   149
    server is invoked, and the associated CFbsFont has been destroyed.
sl@0
   150
 */
sl@0
   151
EXPORT_C TInt RFbsGlyphDataIterator::Next()
sl@0
   152
    {
sl@0
   153
    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
sl@0
   154
    return iImpl->Next();
sl@0
   155
    }
sl@0
   156
sl@0
   157
/**
sl@0
   158
Closes the iterator and releases its internal resources. After calling, all data 
sl@0
   159
retrieved by the iterator is no longer safe to use. Once closed, this iterator 
sl@0
   160
can be re-opened. Calling Close() on an already closed iterator has no effect.
sl@0
   161
sl@0
   162
Once an iterator is closed, the array of glyphs (aGlyphCodes) passed to
sl@0
   163
RFbsGlyphDataIterator::Open() can safely be deleted.
sl@0
   164
sl@0
   165
@post The iterator is closed.
sl@0
   166
 */
sl@0
   167
EXPORT_C void RFbsGlyphDataIterator::Close()
sl@0
   168
    {
sl@0
   169
    delete iImpl;
sl@0
   170
    iImpl = NULL;
sl@0
   171
    }
sl@0
   172
sl@0
   173
/**
sl@0
   174
Returns a reference to the RSgImage that contains the glyph for the current 
sl@0
   175
iteration. The image representation of the glyph is the same as the image 
sl@0
   176
returned by the existing CFbsFont::GetCharacterData() method (i.e. an alpha mask). 
sl@0
   177
sl@0
   178
The RSgImage should only be considered a temporary handle for use in this 
sl@0
   179
iteration, and should not be used after a call to Next() or Close() has 
sl@0
   180
been made.
sl@0
   181
sl@0
   182
Note: For glyphs such as space which have no visible representation, Image() 
sl@0
   183
will return a null image handle (i.e. RSgImage::IsNull() returns ETrue). This 
sl@0
   184
cannot be used for drawing. In this case Rect() will be empty however 
sl@0
   185
Metrics() will still be valid. 
sl@0
   186
sl@0
   187
@pre The iterator has been initialised by successfully calling Open().
sl@0
   188
     
sl@0
   189
@return A handle to the image where the glyph for this iteration is stored.
sl@0
   190
     
sl@0
   191
@panic FBSCLI 31, if the iterator is not open.
sl@0
   192
 */
sl@0
   193
EXPORT_C const RSgImage& RFbsGlyphDataIterator::Image() const
sl@0
   194
    {
sl@0
   195
    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
sl@0
   196
    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   197
    return iImpl->iGlyphBatch.First()->iImage;
sl@0
   198
    }
sl@0
   199
sl@0
   200
/**
sl@0
   201
Returns the area within the RSgImage where the glyph for the current
sl@0
   202
iteration is located. The reference returned by Rect() should be considered 
sl@0
   203
temporary for use within this iteration and should not be used after a call to 
sl@0
   204
Next() or Close() has been made.
sl@0
   205
 
sl@0
   206
@pre The iterator has been initialised by successfully calling Open().
sl@0
   207
     
sl@0
   208
@return A rectangle representing the position and size in pixels, 
sl@0
   209
	of the glyph for this iteration on the RSgImage provided by Image().
sl@0
   210
     
sl@0
   211
@panic FBSCLI 31, if the iterator is not open.
sl@0
   212
 */
sl@0
   213
EXPORT_C const TRect& RFbsGlyphDataIterator::Rect() const
sl@0
   214
    {
sl@0
   215
    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
sl@0
   216
    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   217
    return iImpl->iGlyphDataIterRect;
sl@0
   218
    }
sl@0
   219
sl@0
   220
/**
sl@0
   221
Returns the glyph metrics for the current iteration. The reference returned by 
sl@0
   222
Metrics() should be considered temporary for use within this iteration and 
sl@0
   223
should not be used after a call to Next() or Close() has been made.
sl@0
   224
sl@0
   225
@pre The iterator has been initialised by successfully calling Open().
sl@0
   226
 
sl@0
   227
@return The metrics for the glyph at the current iteration.
sl@0
   228
sl@0
   229
@panic FBSCLI 31, if the iterator is not open.
sl@0
   230
 */
sl@0
   231
EXPORT_C const TOpenFontCharMetrics& RFbsGlyphDataIterator::Metrics() const
sl@0
   232
    {
sl@0
   233
    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
sl@0
   234
    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   235
    return iImpl->iGlyphBatch.First()->iInfo.iMetrics;
sl@0
   236
    }
sl@0
   237
sl@0
   238
/**
sl@0
   239
Returns the glyph code associated with the data for the current iteration.
sl@0
   240
sl@0
   241
@pre The iterator has been initialised by successfully calling Open().
sl@0
   242
 
sl@0
   243
@return The glyph code of the glyph at the current iteration.
sl@0
   244
sl@0
   245
@panic FBSCLI 31, if the iterator is not open.
sl@0
   246
 */
sl@0
   247
EXPORT_C TUint RFbsGlyphDataIterator::GlyphCode() const
sl@0
   248
    {
sl@0
   249
    __ASSERT_ALWAYS(iImpl, Panic(EFbsPanicGlyphDataIteratorClosed));
sl@0
   250
    __ASSERT_DEBUG(!iImpl->iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   251
    return iImpl->iGlyphDataIterCodes[iImpl->iGlyphDataIterCodeIndex];
sl@0
   252
    }
sl@0
   253
sl@0
   254
sl@0
   255
/**
sl@0
   256
Constructs a CGlyphDataIteratorImpl. 
sl@0
   257
@param aFbsFontHandle The handle of the FbsFont that the iterator is working with.
sl@0
   258
@param aGlyphCodes The array of glyph codes sent to RFbsGlyphDataIterator::Open()
sl@0
   259
@param aCount The number of glyph codes in aGlyphCodes.
sl@0
   260
 */
sl@0
   261
CGlyphDataIteratorImpl::CGlyphDataIteratorImpl(TInt aFbsFontHandle, const TUint* aGlyphCodes, TInt aCount) :
sl@0
   262
    iGlyphBatch(_FOFF(TGlyphBatchItem, iLink)),
sl@0
   263
    iGlyphDataIterCodes(aGlyphCodes),
sl@0
   264
    iGlyphDataIterCodeCount(aCount),
sl@0
   265
    iGlyphDataIterCodeIndex(KFbsGlyphDataIterCodeInvalid),
sl@0
   266
    iFbsFontHandle(aFbsFontHandle)
sl@0
   267
    {
sl@0
   268
    }
sl@0
   269
sl@0
   270
/** 
sl@0
   271
Destructor. Releases all resources, disconnects from server and frees any
sl@0
   272
items in the list of batched items.
sl@0
   273
 */
sl@0
   274
CGlyphDataIteratorImpl::~CGlyphDataIteratorImpl()
sl@0
   275
    {
sl@0
   276
    if (iFbs)
sl@0
   277
        {
sl@0
   278
        if (iGlyphDataIterCodeIndex != KFbsGlyphDataIterCodeInvalid)
sl@0
   279
            {
sl@0
   280
            //Send the No-Op command to ensure that the "In Transit" RSgImage(s) are closed.
sl@0
   281
            iFbs->SendCommand(EFbsMessNoOp);
sl@0
   282
            }
sl@0
   283
        RFbsSession::Disconnect();
sl@0
   284
        iFbs = NULL;
sl@0
   285
        }
sl@0
   286
    while (!iGlyphBatch.IsEmpty())
sl@0
   287
        {
sl@0
   288
        TGlyphBatchItem* item = iGlyphBatch.First();
sl@0
   289
        item->iImage.Close();
sl@0
   290
        iGlyphBatch.Remove(*item);
sl@0
   291
        delete item;
sl@0
   292
        }
sl@0
   293
    iGlyphBatch.Reset();
sl@0
   294
    }
sl@0
   295
sl@0
   296
/**
sl@0
   297
Sets up the CGlyphDataIteratorImpl, populating the first batch of glyphs.
sl@0
   298
Should only be called once, immediately after construction.
sl@0
   299
 */
sl@0
   300
TInt CGlyphDataIteratorImpl::Initialise()
sl@0
   301
    {
sl@0
   302
    __ASSERT_DEBUG(iFbsFontHandle, Panic(EFbsPanicGlyphDataIteratorInvalidState));    
sl@0
   303
    __ASSERT_DEBUG(iGlyphDataIterCodes, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   304
    __ASSERT_DEBUG(iGlyphDataIterCodeCount, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   305
    __ASSERT_DEBUG(iGlyphDataIterCodeIndex == KFbsGlyphDataIterCodeInvalid, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   306
    
sl@0
   307
    // If the client already has a session open, this is just a reference counting exercise and should incur no performance impact.
sl@0
   308
    TInt err = RFbsSession::Connect();
sl@0
   309
    if (err == KErrNone)
sl@0
   310
        {
sl@0
   311
        iFbs = RFbsSession::GetSession();
sl@0
   312
        err = UpdateGlyphBatch(0);
sl@0
   313
        }
sl@0
   314
    if (err == KErrNone)
sl@0
   315
        {
sl@0
   316
        iGlyphDataIterCodeIndex = 0;
sl@0
   317
        UpdateGlyphRect();
sl@0
   318
        }
sl@0
   319
    return err;
sl@0
   320
    }
sl@0
   321
sl@0
   322
/**
sl@0
   323
Increments the current iteration if possible, re-sending the request
sl@0
   324
for more glyphs if the current batch of glyphs is down to the last
sl@0
   325
item.
sl@0
   326
@see RFbsGlyphDataIterator::Next()
sl@0
   327
 */
sl@0
   328
TInt CGlyphDataIteratorImpl::Next()
sl@0
   329
    {
sl@0
   330
    __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   331
    if ( (iGlyphDataIterCodeIndex + 1) >= iGlyphDataIterCodeCount) 
sl@0
   332
        {
sl@0
   333
        return KErrNotFound; 
sl@0
   334
        }
sl@0
   335
    TInt err = UpdateGlyphBatch(iGlyphDataIterCodeIndex + 1);
sl@0
   336
    if (err == KErrNone)
sl@0
   337
        {
sl@0
   338
        ++iGlyphDataIterCodeIndex;
sl@0
   339
        // Close the current image and pop the head of the batch.
sl@0
   340
        TGlyphBatchItem* item = iGlyphBatch.First();
sl@0
   341
        item->iImage.Close();
sl@0
   342
        iGlyphBatch.Remove(*item);
sl@0
   343
        delete item;
sl@0
   344
        __ASSERT_DEBUG(!iGlyphBatch.IsEmpty(), Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   345
        UpdateGlyphRect();
sl@0
   346
        }
sl@0
   347
    return err;
sl@0
   348
    }
sl@0
   349
sl@0
   350
/**
sl@0
   351
Checks whether a call to the server is required to get a new batch of glyph 
sl@0
   352
info, and processes the response from the server as necessary.
sl@0
   353
sl@0
   354
@param aIndex Specifies the index into the glyph array which needs to be in
sl@0
   355
the active glyph batch. If it is not there, a request is made to the server
sl@0
   356
to get it.
sl@0
   357
@return KErrNone if getting at least one glyph succeeded or a call to the
sl@0
   358
    server was not necessary, otherwise one of the system wide error codes.
sl@0
   359
@panic FBSCLI 31 (debug only), if the iterator is not open
sl@0
   360
@panic FBSCLI 33 (debug only), if an unexpected number of glyphs was received
sl@0
   361
    as a result of requesting glyphs from the server, or if the current batch
sl@0
   362
    of glyphs is empty when there should be at least one item.
sl@0
   363
 */
sl@0
   364
TInt CGlyphDataIteratorImpl::UpdateGlyphBatch(TInt aIndex)
sl@0
   365
    {
sl@0
   366
    __ASSERT_DEBUG(Rng(0, aIndex, iGlyphDataIterCodeCount - 1), Panic(EFbsPanicGlyphDataIteratorIndexOutOfRange));
sl@0
   367
sl@0
   368
    TInt err = KErrNone;
sl@0
   369
    
sl@0
   370
    TBool needMoreGlyphs = EFalse;
sl@0
   371
    if (iGlyphBatch.IsEmpty())
sl@0
   372
        {
sl@0
   373
        // Current batch is empty, must request more. Should only get here when the iterator 
sl@0
   374
        // is first opened, since one item should always be in the list from then on.
sl@0
   375
        __ASSERT_DEBUG(aIndex == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   376
        needMoreGlyphs = ETrue;
sl@0
   377
        }
sl@0
   378
    else if (iGlyphBatch.IsLast(iGlyphBatch.First()))
sl@0
   379
        {
sl@0
   380
        // Only one item in the list. 
sl@0
   381
        needMoreGlyphs = ETrue;
sl@0
   382
        }
sl@0
   383
    
sl@0
   384
    if (needMoreGlyphs)
sl@0
   385
        {
sl@0
   386
        // If the array of batched images is empty OR only one left, means we need to request a new batch.
sl@0
   387
        // We make sure there is at least one glyph in the batch so the iterator is always usable even
sl@0
   388
        // when a failure to move to the next iteration occurs.
sl@0
   389
    
sl@0
   390
        TBool glyphAddedToBatch = EFalse;
sl@0
   391
        TUint glyphCodes[KMaxGlyphBatchSize];
sl@0
   392
        
sl@0
   393
        TInt numGlyphsToRequest = Min(iGlyphDataIterCodeCount - aIndex, KMaxGlyphBatchSize);        
sl@0
   394
        (void)Mem::Copy(glyphCodes, &(iGlyphDataIterCodes[aIndex]), sizeof(TUint) * numGlyphsToRequest);
sl@0
   395
        TPckg<TUint[KMaxGlyphBatchSize]> argGlyphCodes(glyphCodes);
sl@0
   396
        
sl@0
   397
        TGlyphImageInfo rcvdGlyphInfo[KMaxGlyphBatchSize];
sl@0
   398
        TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> argGlyphInfo(rcvdGlyphInfo);
sl@0
   399
        
sl@0
   400
        if (numGlyphsToRequest < KMaxGlyphBatchSize)
sl@0
   401
            {
sl@0
   402
            argGlyphCodes.SetLength(numGlyphsToRequest * sizeof(TUint));
sl@0
   403
            argGlyphInfo.SetLength(numGlyphsToRequest * sizeof(TGlyphImageInfo));
sl@0
   404
            }
sl@0
   405
        
sl@0
   406
        err = iFbs->SendCommand(EFbsMessGetGlyphs, TIpcArgs(iFbsFontHandle, &argGlyphCodes, &argGlyphInfo));
sl@0
   407
        if (err == KErrNone)
sl@0
   408
            {
sl@0
   409
            __ASSERT_DEBUG(argGlyphInfo.Length() % sizeof(TGlyphImageInfo) == 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   410
            TInt numRcvdGlyphs = argGlyphInfo.Length() / sizeof(TGlyphImageInfo);
sl@0
   411
            __ASSERT_DEBUG(numRcvdGlyphs > 0, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   412
            __ASSERT_DEBUG(numRcvdGlyphs <= KMaxGlyphBatchSize, Panic(EFbsPanicGlyphDataIteratorInvalidState));
sl@0
   413
            
sl@0
   414
            // Store the received glyph data, and open the image handles so that the IDs
sl@0
   415
            // will not be released by FbServ between now and the client using them.
sl@0
   416
            // If a failure occurs while processing one of the recevied glyphs,
sl@0
   417
            // abort the rest but keep the ones that succeeded.
sl@0
   418
            for (TInt i = 0; (i < numRcvdGlyphs) && (err == KErrNone); ++i)
sl@0
   419
                {
sl@0
   420
                TGlyphBatchItem* glyphEntry = new TGlyphBatchItem;
sl@0
   421
                if (!glyphEntry)
sl@0
   422
                    {
sl@0
   423
                    err = KErrNoMemory;
sl@0
   424
                    }
sl@0
   425
                else
sl@0
   426
                    {
sl@0
   427
                    glyphEntry->iInfo = rcvdGlyphInfo[i];
sl@0
   428
                    
sl@0
   429
                    RSgImage glyphImage;
sl@0
   430
                    if (rcvdGlyphInfo[i].iImageId != KSgNullDrawableId)
sl@0
   431
                        {
sl@0
   432
                        err = glyphEntry->iImage.Open(rcvdGlyphInfo[i].iImageId);
sl@0
   433
                        }
sl@0
   434
                    if (err == KErrNone)
sl@0
   435
                        {
sl@0
   436
                        iGlyphBatch.AddLast(*glyphEntry);
sl@0
   437
                        glyphAddedToBatch = ETrue;
sl@0
   438
                        }
sl@0
   439
                    else
sl@0
   440
                        {
sl@0
   441
                        delete glyphEntry;
sl@0
   442
                        }
sl@0
   443
                    }
sl@0
   444
                }
sl@0
   445
            }
sl@0
   446
        if (err != KErrNone && glyphAddedToBatch)
sl@0
   447
            {
sl@0
   448
            // There was an error adding an item to the batch. Rather than return the
sl@0
   449
            // error to the client, ignore it and use what glyphs we successfully batched.
sl@0
   450
            err = KErrNone; 
sl@0
   451
            }
sl@0
   452
        }    
sl@0
   453
    return err;
sl@0
   454
    }
sl@0
   455
sl@0
   456
/**
sl@0
   457
Updates the glyph rectangle member based on the current glyph metrics.
sl@0
   458
@post The iGlyphDataIterRect member is updated to reflect the position
sl@0
   459
    and size of the currently active glyph.
sl@0
   460
 */
sl@0
   461
void CGlyphDataIteratorImpl::UpdateGlyphRect()
sl@0
   462
    {
sl@0
   463
    iGlyphDataIterRect.iTl = TPoint(iGlyphBatch.First()->iInfo.iPosX, iGlyphBatch.First()->iInfo.iPosY);
sl@0
   464
    iGlyphDataIterRect.SetSize(TSize(iGlyphBatch.First()->iInfo.iMetrics.Width(), iGlyphBatch.First()->iInfo.iMetrics.Height()));
sl@0
   465
    }