fbs/fontandbitmapserver/sfbs/fbsglyphmetricsarray.cpp
author hgs
Fri, 24 Sep 2010 16:14:28 +0300
changeset 187 9f66f99ee56f
permissions -rw-r--r--
201026
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
187
hgs
parents:
diff changeset
     1
// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     2
// All rights reserved.
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
hgs
parents:
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
hgs
parents:
diff changeset
     7
//
hgs
parents:
diff changeset
     8
// Initial Contributors:
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
hgs
parents:
diff changeset
    10
//
hgs
parents:
diff changeset
    11
// Contributors:
hgs
parents:
diff changeset
    12
//
hgs
parents:
diff changeset
    13
// Description:
hgs
parents:
diff changeset
    14
//
hgs
parents:
diff changeset
    15
hgs
parents:
diff changeset
    16
hgs
parents:
diff changeset
    17
#include <e32def.h>
hgs
parents:
diff changeset
    18
#include <gdi.h>
hgs
parents:
diff changeset
    19
#include <graphics/gdi/gdistructs.h>
hgs
parents:
diff changeset
    20
#include <graphics/gdi/gdiconsts.h>
hgs
parents:
diff changeset
    21
#include <graphics/fbsglyphmetricsarray.h>
hgs
parents:
diff changeset
    22
#include "UTILS.H"
hgs
parents:
diff changeset
    23
#include "FbsMessage.h"
hgs
parents:
diff changeset
    24
hgs
parents:
diff changeset
    25
// 'most significant bit' flag to ensure value is interpreted as a glyph code rather than an ascii code
hgs
parents:
diff changeset
    26
const TUint KGlyphCodeFlag = 0x80000000;      
hgs
parents:
diff changeset
    27
hgs
parents:
diff changeset
    28
extern void Panic(TFbsPanic aPanic);
hgs
parents:
diff changeset
    29
hgs
parents:
diff changeset
    30
/** Helper function for converting an offset (that was calculated using
hgs
parents:
diff changeset
    31
PointerToOffset()) back to a pointer relative to the passed heap base.
hgs
parents:
diff changeset
    32
@param aOffset The offset to be converted to a pointer.
hgs
parents:
diff changeset
    33
@param aHeapBase A pointer to the heap base of the current process.
hgs
parents:
diff changeset
    34
@return A pointer relative to the passed heap base.
hgs
parents:
diff changeset
    35
*/
hgs
parents:
diff changeset
    36
static TAny* OffsetToPointer(const TInt aOffset, TUint8* aHeapBase)
hgs
parents:
diff changeset
    37
    {
hgs
parents:
diff changeset
    38
    if ( (aOffset != 0) && (aHeapBase != NULL) )
hgs
parents:
diff changeset
    39
        {
hgs
parents:
diff changeset
    40
        return (TAny*)(aOffset + aHeapBase);
hgs
parents:
diff changeset
    41
        }
hgs
parents:
diff changeset
    42
    return NULL;
hgs
parents:
diff changeset
    43
    }
hgs
parents:
diff changeset
    44
hgs
parents:
diff changeset
    45
/**
hgs
parents:
diff changeset
    46
Constructs an empty RFbsGlyphMetricsArray instance. This will not allocate any memory.
hgs
parents:
diff changeset
    47
 */
hgs
parents:
diff changeset
    48
EXPORT_C RFbsGlyphMetricsArray::RFbsGlyphMetricsArray() :
hgs
parents:
diff changeset
    49
    iGlyphCodes(NULL)
hgs
parents:
diff changeset
    50
    {
hgs
parents:
diff changeset
    51
    }
hgs
parents:
diff changeset
    52
hgs
parents:
diff changeset
    53
/**
hgs
parents:
diff changeset
    54
Allocates the memory for the array if it has not already been allocated, and 
hgs
parents:
diff changeset
    55
populates the RFbsGlyphMetricsArray with the metrics information for aCount glyph 
hgs
parents:
diff changeset
    56
codes passed in as the array aGlyphCodes, for the font aFont. If the operation 
hgs
parents:
diff changeset
    57
is successful, KErrNone is returned and the array is populated with glyph 
hgs
parents:
diff changeset
    58
metrics data. Each entry in the array will be in the same order as the 
hgs
parents:
diff changeset
    59
corresponding codes in aGlyphCodes.
hgs
parents:
diff changeset
    60
hgs
parents:
diff changeset
    61
The memory allocated to aGlyphCodes can be freed after the call to Get().
hgs
parents:
diff changeset
    62
hgs
parents:
diff changeset
    63
Get() can be called on an RFbsGlyphMetricsArray multiple times without calling 
hgs
parents:
diff changeset
    64
Close(), since the memory for the array is not de-allocated until a call to 
hgs
parents:
diff changeset
    65
Close(). Calls to Get() will cause the previous content of the array to be 
hgs
parents:
diff changeset
    66
overwritten.
hgs
parents:
diff changeset
    67
hgs
parents:
diff changeset
    68
In the event of an error code other than KErrNone, the state of the array
hgs
parents:
diff changeset
    69
will remain unchanged.
hgs
parents:
diff changeset
    70
 
hgs
parents:
diff changeset
    71
@param aFont A font which to retrieve the glyph metrics for.
hgs
parents:
diff changeset
    72
@param aGlyphCodes An array of glyph codes to retrieve the metrics for.
hgs
parents:
diff changeset
    73
@param aCount The number of glyph codes in aGlyphCodes.
hgs
parents:
diff changeset
    74
hgs
parents:
diff changeset
    75
@return
hgs
parents:
diff changeset
    76
	KErrNone, if the array is successfully populated with glyph metrics;
hgs
parents:
diff changeset
    77
	KErrNoMemory, if insufficient system memory is available;
hgs
parents:
diff changeset
    78
	KErrArgument, if aCount is negative or zero, or if aGlyphCodes is null;
hgs
parents:
diff changeset
    79
	KErrNotSupported, if aFont is a bitmap font.
hgs
parents:
diff changeset
    80
*/
hgs
parents:
diff changeset
    81
EXPORT_C TInt RFbsGlyphMetricsArray::Get(CFbsFont& aFont, const TUint* aGlyphCodes, TInt aCount)
hgs
parents:
diff changeset
    82
	{
hgs
parents:
diff changeset
    83
    if ((aCount <= 0) || !aGlyphCodes)
hgs
parents:
diff changeset
    84
        {
hgs
parents:
diff changeset
    85
        return KErrArgument;
hgs
parents:
diff changeset
    86
        }
hgs
parents:
diff changeset
    87
    if (iMetrics.Reserve(aCount) != KErrNone)
hgs
parents:
diff changeset
    88
        {
hgs
parents:
diff changeset
    89
        return KErrNoMemory;
hgs
parents:
diff changeset
    90
        }
hgs
parents:
diff changeset
    91
    if (!aFont.Address()->IsOpenFont())
hgs
parents:
diff changeset
    92
        {
hgs
parents:
diff changeset
    93
        return KErrNotSupported;
hgs
parents:
diff changeset
    94
        }
hgs
parents:
diff changeset
    95
    
hgs
parents:
diff changeset
    96
    iGlyphCodes = aGlyphCodes;
hgs
parents:
diff changeset
    97
    iCount = aCount;
hgs
parents:
diff changeset
    98
    TInt err = KErrNone;
hgs
parents:
diff changeset
    99
    
hgs
parents:
diff changeset
   100
    
hgs
parents:
diff changeset
   101
    // If iMetrics array already has a count greater than aCount, remove entries
hgs
parents:
diff changeset
   102
    // until count is same as aCount so that we can reuse the existing entries.
hgs
parents:
diff changeset
   103
    TInt numEntriesToRemove = iMetrics.Count() - aCount;
hgs
parents:
diff changeset
   104
    while (0 < numEntriesToRemove)
hgs
parents:
diff changeset
   105
        {
hgs
parents:
diff changeset
   106
        --numEntriesToRemove;
hgs
parents:
diff changeset
   107
        iMetrics.Remove(aCount + numEntriesToRemove);
hgs
parents:
diff changeset
   108
        }
hgs
parents:
diff changeset
   109
    const TInt indexToGrowArrayAt = iMetrics.Count();
hgs
parents:
diff changeset
   110
    
hgs
parents:
diff changeset
   111
    CBitmapFont* font = aFont.Address();
hgs
parents:
diff changeset
   112
    TUint ipcGlyphArrayIndex[KMaxMetricsBatchSize];
hgs
parents:
diff changeset
   113
    TInt ipcGlyphArrayIndexCount = 0;   
hgs
parents:
diff changeset
   114
    const TUint8* dummyBitmap;
hgs
parents:
diff changeset
   115
    TOpenFontCharMetrics charDataMetrics;
hgs
parents:
diff changeset
   116
            
hgs
parents:
diff changeset
   117
    for (TInt i = 0; i < aCount && (err == KErrNone); ++i)
hgs
parents:
diff changeset
   118
        {
hgs
parents:
diff changeset
   119
        // First check the cache in shared memory - if present it will avoid using IPC.
hgs
parents:
diff changeset
   120
        if (font->GetCharacterData(aFont.iFbs->ServerSessionHandle(), aGlyphCodes[i] | KGlyphCodeFlag, charDataMetrics, dummyBitmap))
hgs
parents:
diff changeset
   121
            {
hgs
parents:
diff changeset
   122
            if (i < indexToGrowArrayAt)
hgs
parents:
diff changeset
   123
                {
hgs
parents:
diff changeset
   124
                iMetrics[i] = charDataMetrics;
hgs
parents:
diff changeset
   125
                }
hgs
parents:
diff changeset
   126
            else
hgs
parents:
diff changeset
   127
                {
hgs
parents:
diff changeset
   128
                // Extending the size of the array, but memory is already reserved.
hgs
parents:
diff changeset
   129
                (void) iMetrics.Append(charDataMetrics);    
hgs
parents:
diff changeset
   130
                }
hgs
parents:
diff changeset
   131
            }            
hgs
parents:
diff changeset
   132
        else
hgs
parents:
diff changeset
   133
            {
hgs
parents:
diff changeset
   134
            // Not found in shared memory - instead add the index to index array, which will
hgs
parents:
diff changeset
   135
            // be processed when the array is full or at the end of the loop.
hgs
parents:
diff changeset
   136
            ipcGlyphArrayIndex[ipcGlyphArrayIndexCount++] = i;
hgs
parents:
diff changeset
   137
            if (ipcGlyphArrayIndexCount == KMaxMetricsBatchSize)
hgs
parents:
diff changeset
   138
                {
hgs
parents:
diff changeset
   139
                err = SendRecvGlyphMetrics(aFont, ipcGlyphArrayIndex, ipcGlyphArrayIndexCount, &iMetrics);
hgs
parents:
diff changeset
   140
                ipcGlyphArrayIndexCount = 0;
hgs
parents:
diff changeset
   141
                }
hgs
parents:
diff changeset
   142
            else if (i >= indexToGrowArrayAt)
hgs
parents:
diff changeset
   143
                {
hgs
parents:
diff changeset
   144
                // Add a metrics placeholder to keep the size of the array and the currently
hgs
parents:
diff changeset
   145
                // processed glyph in sync. It will later get overwritten when it is received
hgs
parents:
diff changeset
   146
                // from the server.
hgs
parents:
diff changeset
   147
                (void) iMetrics.Append(charDataMetrics);
hgs
parents:
diff changeset
   148
                }
hgs
parents:
diff changeset
   149
            }
hgs
parents:
diff changeset
   150
        }
hgs
parents:
diff changeset
   151
    if ((err == KErrNone) && (ipcGlyphArrayIndexCount != 0))
hgs
parents:
diff changeset
   152
        {
hgs
parents:
diff changeset
   153
        err = SendRecvGlyphMetrics(aFont, ipcGlyphArrayIndex, ipcGlyphArrayIndexCount, &iMetrics);
hgs
parents:
diff changeset
   154
        }
hgs
parents:
diff changeset
   155
    
hgs
parents:
diff changeset
   156
    __ASSERT_DEBUG((err != KErrNone) || (aCount == iMetrics.Count()), Panic(EFbsPanicGlyphMetricsArrayInvalidState));  
hgs
parents:
diff changeset
   157
    
hgs
parents:
diff changeset
   158
    return err;    
hgs
parents:
diff changeset
   159
	}
hgs
parents:
diff changeset
   160
/**
hgs
parents:
diff changeset
   161
Helper function for Get(). 
hgs
parents:
diff changeset
   162
Given a list of indices into a glyph code array, the corresponding glyph
hgs
parents:
diff changeset
   163
codes are made into a single list sent to the server, and the received glyph
hgs
parents:
diff changeset
   164
metrics are set in the array of metrics at the corresponding indices.
hgs
parents:
diff changeset
   165
hgs
parents:
diff changeset
   166
@param aFont The font to receive the glyph metrics of.
hgs
parents:
diff changeset
   167
@param aArrayIndices An array of indices into the glyphcode array which
hgs
parents:
diff changeset
   168
    will be sent for requesting of metrics to the server.
hgs
parents:
diff changeset
   169
@param aArrayIndicesCount The number of glyphs in aGlyphArrayIndices.
hgs
parents:
diff changeset
   170
@param aMetrics The array which will store the resulting metrics objects upon
hgs
parents:
diff changeset
   171
    completion.
hgs
parents:
diff changeset
   172
@return KErrNone if successful, otherwise one of the system-wide error codes. 
hgs
parents:
diff changeset
   173
hgs
parents:
diff changeset
   174
@panic FBSCLI 39 in debug builds only, if the parameters to this method are
hgs
parents:
diff changeset
   175
    invalid, or if the output array is of the wrong size when appending to it.
hgs
parents:
diff changeset
   176
 */
hgs
parents:
diff changeset
   177
TInt RFbsGlyphMetricsArray::SendRecvGlyphMetrics(CFbsFont& aFont, TUint* aArrayIndices, TInt aArrayIndicesCount, RArray<TOpenFontCharMetrics>* aMetrics) const
hgs
parents:
diff changeset
   178
    {
hgs
parents:
diff changeset
   179
    __ASSERT_DEBUG(aArrayIndicesCount > 0, Panic(EFbsPanicGlyphDataIteratorInvalidState)); 
hgs
parents:
diff changeset
   180
    __ASSERT_DEBUG(aArrayIndicesCount <= KMaxMetricsBatchSize, Panic(EFbsPanicGlyphDataIteratorInvalidState)); 
hgs
parents:
diff changeset
   181
    __ASSERT_DEBUG(aArrayIndices, Panic(EFbsPanicGlyphDataIteratorInvalidState));
hgs
parents:
diff changeset
   182
    TInt err = KErrNone;
hgs
parents:
diff changeset
   183
    
hgs
parents:
diff changeset
   184
    TUint glyphCodes[KMaxMetricsBatchSize];
hgs
parents:
diff changeset
   185
    for (TInt i = 0; i < aArrayIndicesCount; ++i)
hgs
parents:
diff changeset
   186
        {
hgs
parents:
diff changeset
   187
        glyphCodes[i] = iGlyphCodes[aArrayIndices[i]];
hgs
parents:
diff changeset
   188
        }
hgs
parents:
diff changeset
   189
    
hgs
parents:
diff changeset
   190
    TInt rcvdGlyphMetricsOffsets[KMaxMetricsBatchSize];
hgs
parents:
diff changeset
   191
    TPckg<TUint[KMaxMetricsBatchSize]> argGlyphCodes(glyphCodes);
hgs
parents:
diff changeset
   192
    TPckg<TInt[KMaxMetricsBatchSize]> argGlyphMetricsOffsets(rcvdGlyphMetricsOffsets);
hgs
parents:
diff changeset
   193
    if (aArrayIndicesCount < KMaxMetricsBatchSize)
hgs
parents:
diff changeset
   194
        {
hgs
parents:
diff changeset
   195
        argGlyphCodes.SetLength(aArrayIndicesCount * sizeof(TUint));
hgs
parents:
diff changeset
   196
        argGlyphMetricsOffsets.SetLength(aArrayIndicesCount * sizeof(TInt));
hgs
parents:
diff changeset
   197
        }   
hgs
parents:
diff changeset
   198
    err = aFont.iFbs->SendCommand(EFbsMessGetGlyphMetrics, TIpcArgs(aFont.iHandle, &argGlyphCodes, &argGlyphMetricsOffsets));
hgs
parents:
diff changeset
   199
    
hgs
parents:
diff changeset
   200
    if (err == KErrNone)
hgs
parents:
diff changeset
   201
        {
hgs
parents:
diff changeset
   202
        TInt numRcvdMetrics = argGlyphMetricsOffsets.Length() / sizeof(TInt);
hgs
parents:
diff changeset
   203
        __ASSERT_DEBUG(argGlyphMetricsOffsets.Length() % sizeof(TInt) == 0, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
hgs
parents:
diff changeset
   204
        __ASSERT_DEBUG(numRcvdMetrics == aArrayIndicesCount, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
hgs
parents:
diff changeset
   205
        
hgs
parents:
diff changeset
   206
        if (numRcvdMetrics == aArrayIndicesCount)
hgs
parents:
diff changeset
   207
            {
hgs
parents:
diff changeset
   208
            TInt arrayCount = aMetrics->Count();
hgs
parents:
diff changeset
   209
            TUint8* heapBase = aFont.iFbs->HeapBase();
hgs
parents:
diff changeset
   210
            for (TInt rcvdMetricsItem = 0; rcvdMetricsItem < numRcvdMetrics; ++rcvdMetricsItem)
hgs
parents:
diff changeset
   211
                {
hgs
parents:
diff changeset
   212
                TInt arrayIndex = aArrayIndices[rcvdMetricsItem];
hgs
parents:
diff changeset
   213
                // The array should never need to grow more than one item. If the difference is larger, 
hgs
parents:
diff changeset
   214
                // it means the glyph and the metrics are not in sync.
hgs
parents:
diff changeset
   215
                __ASSERT_DEBUG(arrayIndex <= arrayCount, Panic(EFbsPanicGlyphMetricsArrayInvalidState));
hgs
parents:
diff changeset
   216
                
hgs
parents:
diff changeset
   217
                TInt metricsOffset = rcvdGlyphMetricsOffsets[rcvdMetricsItem];              
hgs
parents:
diff changeset
   218
                const TOpenFontCharMetrics* metrics = (const TOpenFontCharMetrics*)(OffsetToPointer(metricsOffset, heapBase));
hgs
parents:
diff changeset
   219
                
hgs
parents:
diff changeset
   220
                if (arrayIndex < arrayCount)
hgs
parents:
diff changeset
   221
                    {
hgs
parents:
diff changeset
   222
                    // Copy metrics into existing element
hgs
parents:
diff changeset
   223
                    (*aMetrics)[arrayIndex] = *metrics;
hgs
parents:
diff changeset
   224
                    }
hgs
parents:
diff changeset
   225
                else if (arrayIndex == arrayCount)
hgs
parents:
diff changeset
   226
                    {
hgs
parents:
diff changeset
   227
                    // Memory should already be reserved by GetGlyphMetricsArray()
hgs
parents:
diff changeset
   228
                    (void) aMetrics->Append(*metrics);    
hgs
parents:
diff changeset
   229
                    ++arrayCount;
hgs
parents:
diff changeset
   230
                    }
hgs
parents:
diff changeset
   231
                }
hgs
parents:
diff changeset
   232
            }
hgs
parents:
diff changeset
   233
        else
hgs
parents:
diff changeset
   234
            {
hgs
parents:
diff changeset
   235
            // did not receive the same number of glyphs as was asked.
hgs
parents:
diff changeset
   236
            err = KErrGeneral;
hgs
parents:
diff changeset
   237
            }
hgs
parents:
diff changeset
   238
        }
hgs
parents:
diff changeset
   239
    return err;
hgs
parents:
diff changeset
   240
    }
hgs
parents:
diff changeset
   241
hgs
parents:
diff changeset
   242
/**
hgs
parents:
diff changeset
   243
Closes the array, and releases the memory for the array. Calling Close() on an 
hgs
parents:
diff changeset
   244
already closed RFbsGlyphMetricsArray has no effect. 
hgs
parents:
diff changeset
   245
hgs
parents:
diff changeset
   246
In the typical case where the array is a member of a class, Close() should only 
hgs
parents:
diff changeset
   247
be called in the destructor of that class.
hgs
parents:
diff changeset
   248
 */
hgs
parents:
diff changeset
   249
EXPORT_C void RFbsGlyphMetricsArray::Close()
hgs
parents:
diff changeset
   250
	{
hgs
parents:
diff changeset
   251
	iMetrics.Close();
hgs
parents:
diff changeset
   252
	}
hgs
parents:
diff changeset
   253
hgs
parents:
diff changeset
   254
/**
hgs
parents:
diff changeset
   255
Retrieves the glyph metrics for the glyph which was at position aIndex in the 
hgs
parents:
diff changeset
   256
array passed to Get().
hgs
parents:
diff changeset
   257
hgs
parents:
diff changeset
   258
@param aIndex The index of the entry in the array to access.
hgs
parents:
diff changeset
   259
@return The metrics for the glyph at the requested index.
hgs
parents:
diff changeset
   260
@panic FBSCLI 32, if aIndex is out of bounds.
hgs
parents:
diff changeset
   261
 */
hgs
parents:
diff changeset
   262
EXPORT_C const TOpenFontCharMetrics& RFbsGlyphMetricsArray::operator[](TInt aIndex) const
hgs
parents:
diff changeset
   263
	{
hgs
parents:
diff changeset
   264
	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < iMetrics.Count(), Panic(EFbsPanicGlyphMetricsArrayOutOfBounds));
hgs
parents:
diff changeset
   265
	return (iMetrics)[aIndex];
hgs
parents:
diff changeset
   266
	}
hgs
parents:
diff changeset
   267
hgs
parents:
diff changeset
   268
/**
hgs
parents:
diff changeset
   269
@return The number of glyph metrics held in the array.
hgs
parents:
diff changeset
   270
 */
hgs
parents:
diff changeset
   271
EXPORT_C TInt RFbsGlyphMetricsArray::Count() const
hgs
parents:
diff changeset
   272
	{
hgs
parents:
diff changeset
   273
	return iMetrics.Count();
hgs
parents:
diff changeset
   274
	}