Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
nsFontMetricsXft.cpp File Reference
#include "nsISupportsUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIPref.h"
#include "nsFontMetricsXft.h"
#include "prenv.h"
#include "prprf.h"
#include "prlink.h"
#include "nsQuickSort.h"
#include "nsFont.h"
#include "nsIDeviceContext.h"
#include "nsCairoRenderingContext.h"
#include "nsCairoDrawingSurface.h"
#include "nsReadableUtils.h"
#include "nsUnicharUtils.h"
#include "nsITimelineService.h"
#include "nsICharsetConverterManager.h"
#include "nsICharRepresentable.h"
#include "nsIPersistentProperties2.h"
#include "nsCompressedCharMap.h"
#include "nsNetUtil.h"
#include "nsClassHashtable.h"
#include "nsAutoBuffer.h"
#include "nsFontConfigUtils.h"
#include <gdk/gdkx.h>
#include <freetype/tttables.h>
#include <freetype/freetype.h>
#include "prlog.h"

Go to the source code of this file.

Classes

class  nsFontXft
class  nsFontXftUnicode
class  nsFontXftCustom
class  nsFontXftInfo
struct  DrawStringData
class  nsAutoDrawSpecBuffer

Defines

#define FORCE_PR_LOG
#define AUTO_BUFFER_SIZE   3000
#define FONT_MAX_FONT_SCALE   2
#define UCS2_REPLACEMENT   0xFFFD
#define IS_NON_BMP(c)   ((c) >> 16)
#define IS_NON_SURROGATE(c)   ((c < 0xd800 || c > 0xdfff))
#define INITIAL_FONT_MAP_SIZE   32
#define MOZ_FT_ROUND(x)   (((x) + 32) & ~63)
#define MOZ_FT_TRUNC(x)   ((x) >> 6)
#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s)   MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
#define NS_TO_GDK_RGB(ns)   ((ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff))
#define GDK_COLOR_TO_NS_RGB(c)   ((nscolor) NS_RGB(c.red, c.green, c.blue))

Typedefs

typedef nsAutoBuffer< FcChar32,
AUTO_BUFFER_SIZE
nsAutoFcChar32Buffer
typedef nsClassHashtable
< nsCharPtrHashKey,
nsFontXftInfo
nsFontXftInfoHash

Enumerations

enum  nsXftFontType {
  eFontTypeUnicode, eFontTypeCustom, eFontTypeCustomWide, eFontTypeUnicode,
  eFontTypeCustom, eFontTypeCustomWide
}

Functions

static int CompareFontNames (const void *aArg1, const void *aArg2, void *aClosure)
static nsresult EnumFontsXft (nsIAtom *aLangGroup, const char *aGeneric, PRUint32 *aCount, PRUnichar ***aResult)
static void ConvertCharToUCS4 (const char *aString, PRUint32 aLength, nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
static void ConvertUnicharToUCS4 (const PRUnichar *aString, PRUint32 aLength, nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
static nsresult ConvertUCS4ToCustom (FcChar32 *aSrc, PRUint32 aSrcLen, PRUint32 &aDestLen, nsIUnicodeEncoder *aConverter, PRBool aIsWide, nsAutoFcChar32Buffer &Result)
static NS_DEFINE_CID (kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID)
static nsresult GetEncoding (const char *aFontName, char **aEncoding, nsXftFontType &aType, FT_Encoding &aFTEncoding)
static nsresult GetConverter (const char *aEncoding, nsIUnicodeEncoder **aConverter)
static nsresult FreeGlobals (void)
static nsFontXftInfoGetFontXftInfo (FcPattern *aPattern)

Variables

PRLogModuleInfogXftFontLoad = nsnull
static int gNumInstances = 0
static PRBool gInitialized = PR_FALSE
static nsIPersistentPropertiesgFontEncodingProperties = nsnull
static nsICharsetConverterManagergCharsetManager = nsnull
static nsFontXftInfoHash gFontXftMaps

Class Documentation

struct DrawStringData

Definition at line 201 of file nsFontMetricsXft.cpp.

Collaboration diagram for DrawStringData:
Class Members
XftColor color
nsRenderingContextGTK * context
nsCairoRenderingContext * context
XftDraw * draw
nsAutoDrawSpecBuffer * drawBuffer
HDC mDC
nsFontOS2 * mFont
HFONT mFont
nscoord mLength
nscoord mMaxLength
HPS mPS
const nscoord * mSpacing
nsDrawingSurfaceOS2 * mSurface
nsTransform2D * mTranMatrix
nscoord mX
nscoord mY
float p2t
const nscoord * spacing
nscoord x
nscoord xOffset
nscoord y

Define Documentation

Definition at line 220 of file nsFontMetricsXft.cpp.

Definition at line 750 of file nsFontMetricsXft.cpp.

Definition at line 250 of file nsFontMetricsXft.cpp.

Definition at line 73 of file nsFontMetricsXft.cpp.

#define GDK_COLOR_TO_NS_RGB (   c)    ((nscolor) NS_RGB(c.red, c.green, c.blue))

Definition at line 304 of file nsFontMetricsXft.cpp.

#define IS_NON_BMP (   c)    ((c) >> 16)

Definition at line 254 of file nsFontMetricsXft.cpp.

#define IS_NON_SURROGATE (   c)    ((c < 0xd800 || c > 0xdfff))

Definition at line 255 of file nsFontMetricsXft.cpp.

#define MOZ_FT_ROUND (   x)    (((x) + 32) & ~63)

Definition at line 748 of file nsFontMetricsXft.cpp.

#define MOZ_FT_TRUNC (   x)    ((x) >> 6)

Definition at line 749 of file nsFontMetricsXft.cpp.

#define NS_TO_GDK_RGB (   ns)    ((ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff))
#define UCS2_REPLACEMENT   0xFFFD

Definition at line 252 of file nsFontMetricsXft.cpp.


Typedef Documentation

Definition at line 221 of file nsFontMetricsXft.cpp.

Definition at line 302 of file nsFontMetricsXft.cpp.


Enumeration Type Documentation

Enumerator:
eFontTypeUnicode 
eFontTypeCustom 
eFontTypeCustomWide 
eFontTypeUnicode 
eFontTypeCustom 
eFontTypeCustomWide 

Definition at line 171 of file nsFontMetricsXft.cpp.


Function Documentation

int CompareFontNames ( const void aArg1,
const void aArg2,
void aClosure 
) [static]

Definition at line 2177 of file nsFontMetricsXft.cpp.

{
    const PRUnichar* str1 = *((const PRUnichar**) aArg1);
    const PRUnichar* str2 = *((const PRUnichar**) aArg2);

    return nsCRT::strcmp(str1, str2);
}

Here is the caller graph for this function:

void ConvertCharToUCS4 ( const char *  aString,
PRUint32  aLength,
nsAutoFcChar32Buffer aOutBuffer,
PRUint32 aOutLen 
) [static]

Definition at line 2314 of file nsFontMetricsXft.cpp.

{
    *aOutLen = 0;
    FcChar32 *outBuffer;

    if (!aOutBuffer.EnsureElemCapacity(aLength))
        return;
    outBuffer  = aOutBuffer.get();
    
    for (PRUint32 i = 0; i < aLength; ++i) {
        outBuffer[i] = PRUint8(aString[i]); // to convert char >= 0x80 correctly
    }

    *aOutLen = aLength;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult ConvertUCS4ToCustom ( FcChar32 *  aSrc,
PRUint32  aSrcLen,
PRUint32 aDestLen,
nsIUnicodeEncoder aConverter,
PRBool  aIsWide,
nsAutoFcChar32Buffer Result 
) [static]

Definition at line 2605 of file nsFontMetricsXft.cpp.

{
    nsresult rv = NS_OK;

    nsCOMPtr<nsIUnicodeEncoder> converter = aConverter;
    if (!converter )
        return NS_ERROR_UNEXPECTED;

    // Convert to UTF-16 because UnicodeEncoder expects input to be in
    // UTF-16.  We can get away with in-place replacement because
    // UTF-16 is at most as long as UCS-4 so that UCS-4(source) buffer
    // pointer is always ahead of UTF-16(target) buffer pointer and we
    // won't revisit the buffer we already processed.
    
    PRUnichar *utf16Src  = NS_REINTERPRET_CAST(PRUnichar *, aSrc);
    PRUnichar *utf16Ptr = utf16Src;
    for (PRUint32 i = 0; i < aSrcLen; ++i, ++utf16Ptr) {
        if (!IS_NON_BMP(aSrc[i])) {
            *utf16Ptr = PRUnichar(aSrc[i]);
        }
        else {
            *utf16Ptr = H_SURROGATE(aSrc[i]);
            *++utf16Ptr = L_SURROGATE(aSrc[i]);
        }
    }

    PRInt32 utf16SrcLen = utf16Ptr - utf16Src;
    PRInt32 medLen = utf16SrcLen;
    // Length can increase for 'Wide' custom fonts.
    if (aIsWide &&
        NS_FAILED(aConverter->GetMaxLength(utf16Src, utf16SrcLen, &medLen))) {
        return NS_ERROR_UNEXPECTED;
    }

    nsAutoBuffer<char, AUTO_BUFFER_SIZE> medBuffer;
    if (!medBuffer.EnsureElemCapacity(medLen))
        return NS_ERROR_OUT_OF_MEMORY;
    char *med  = medBuffer.get();

    // Convert utf16Src  to font-specific encoding with mConverter.
    rv = converter->Convert(utf16Src, &utf16SrcLen, med, &medLen);
    NS_ENSURE_SUCCESS(rv, rv);

    // Put pseudo-unicode str. into font specific pseudo-UCS-4 str.
    if (aIsWide) {
#ifdef IS_LITTLE_ENDIAN
        // Convert BE UTF-16 to LE UTF-16 for 'wide' custom fonts
        char* pstr = med;
        while (pstr < med + medLen) {
            PRUint8 tmp = pstr[0];
            pstr[0] = pstr[1];
            pstr[1] = tmp;
            pstr += 2; // swap every two bytes
        }
#endif
        // Convert 16bit  custom font codes to UCS4
        ConvertUnicharToUCS4(NS_REINTERPRET_CAST(PRUnichar *, med),
                             medLen >> 1, aResult, &aDestLen);
        rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
    }
    else {
        // Convert 8bit custom font codes to UCS4
        ConvertCharToUCS4(med, medLen, aResult, &aDestLen);
        rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
    }

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ConvertUnicharToUCS4 ( const PRUnichar aString,
PRUint32  aLength,
nsAutoFcChar32Buffer aOutBuffer,
PRUint32 aOutLen 
) [static]

Definition at line 2335 of file nsFontMetricsXft.cpp.

{
    *aOutLen = 0;
    FcChar32 *outBuffer;

    if (!aOutBuffer.EnsureElemCapacity(aLength))
        return;
    outBuffer  = aOutBuffer.get();

    PRUint32 outLen = 0;

    // Walk the passed in string looking for surrogates to convert to
    // their full ucs4 representation.
    for (PRUint32 i = 0; i < aLength; ++i) {
        PRUnichar c = aString[i];

        // Optimized for the non-surrogate case
        if (IS_NON_SURROGATE(c)) {
            outBuffer[outLen] = c;
        }
        else if (IS_HIGH_SURROGATE(aString[i])) {
            if (i + 1 < aLength && IS_LOW_SURROGATE(aString[i+1])) {
                outBuffer[outLen] = SURROGATE_TO_UCS4(c, aString[i + 1]);
                ++i;
            }
            else { // Unpaired high surrogate
                outBuffer[outLen] = UCS2_REPLACEMENT;
            }
        }
        else if (IS_LOW_SURROGATE(aString[i])) { // Unpaired low surrogate?
            outBuffer[outLen] = UCS2_REPLACEMENT;
        }

        outLen++;
    }

    *aOutLen = outLen;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult EnumFontsXft ( nsIAtom aLangGroup,
const char *  aGeneric,
PRUint32 aCount,
PRUnichar ***  aResult 
) [static]

Definition at line 2187 of file nsFontMetricsXft.cpp.

{
    FcPattern   *pat = NULL;
    FcObjectSet *os  = NULL;
    FcFontSet   *fs  = NULL;
    nsresult     rv  = NS_ERROR_FAILURE;

    PRUnichar **array = NULL;
    PRUint32    narray = 0;
    PRInt32     serif = 0, sansSerif = 0, monospace = 0, nGenerics;

    *aCount = 0;
    *aResult = nsnull;

    pat = FcPatternCreate();
    if (!pat)
        goto end;

    os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, 0);
    if (!os)
        goto end;

    // take the pattern and add the lang group to it
    if (aLangGroup)
        NS_AddLangGroup(pat, aLangGroup);

    // get the font list
    fs = FcFontList(0, pat, os);

    if (!fs)
        goto end;

    if (!fs->nfont) {
        rv = NS_OK;
        goto end;
    }

    // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
    // "monospace", slightly different from CSS's 5.
    if (!aGeneric)
        serif = sansSerif = monospace = 1;
    else if (!strcmp(aGeneric, "serif"))
        serif = 1;
    else if (!strcmp(aGeneric, "sans-serif"))
        sansSerif = 1;
    else if (!strcmp(aGeneric, "monospace"))
        monospace = 1;
    else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
        serif = sansSerif =  1;
    else
        NS_NOTREACHED("unexpected generic family");
    nGenerics = serif + sansSerif + monospace;

    array = NS_STATIC_CAST(PRUnichar **,
               nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
    if (!array)
        goto end;

    if (serif) {
        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
        if (!name)
            goto end;
        array[narray++] = name;
    }

    if (sansSerif) {
        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
        if (!name)
            goto end;
        array[narray++] = name;
    }

    if (monospace) {
        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
        if (!name)
            goto end;
        array[narray++] = name;
    }

    for (int i=0; i < fs->nfont; ++i) {
        char *family;

        // if there's no family, just move to the next iteration
        if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
                                (FcChar8 **) &family) != FcResultMatch) {
            continue;
        }

        // fontconfig always returns family names in UTF-8
        PRUnichar* name =  UTF8ToNewUnicode(nsDependentCString(family));

        if (!name)
            goto end;

        array[narray++] = name;
    }

    NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
                 CompareFontNames, nsnull);

    *aCount = narray;
    if (narray)
        *aResult = array;
    else
        nsMemory::Free(array);

    rv = NS_OK;

 end:
    if (NS_FAILED(rv) && array) {
        while (narray)
            nsMemory::Free (array[--narray]);
        nsMemory::Free (array);
    }
    if (pat)
        FcPatternDestroy(pat);
    if (os)
        FcObjectSetDestroy(os);
    if (fs)
        FcFontSetDestroy(fs);

    return rv;
}

Here is the call graph for this function:

nsresult FreeGlobals ( void  ) [static]

Definition at line 2522 of file nsFontMetricsXft.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

static nsresult GetConverter ( const char *  aEncoding,
nsIUnicodeEncoder **  aConverter 
) [static]

Definition at line 2494 of file nsFontMetricsXft.cpp.

{
    nsresult rv;

    if (!gCharsetManager) {
        CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
        if (!gCharsetManager) {
            FreeGlobals();
            return NS_ERROR_FAILURE;
        }
    }

    // encoding name obtained from fontEncoding.properties is
    // canonical so that we don't need the alias resolution. use 'Raw'
    // version.
    rv = gCharsetManager->GetUnicodeEncoderRaw(aEncoding, aConverter);
    NS_ENSURE_SUCCESS(rv, rv);
    if (PR_LOG_TEST(gXftFontLoad, PR_LOG_DEBUG)) {
        printf("\t\tc> got the converter for %s \n", aEncoding);
    }

    return (*aConverter)->SetOutputErrorBehavior(
            (*aConverter)->kOnError_Replace, nsnull, '?');
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult GetEncoding ( const char *  aFontName,
char **  aEncoding,
nsXftFontType aType,
FT_Encoding &  aFTEncoding 
) [static]

Definition at line 2405 of file nsFontMetricsXft.cpp.

{
  // below is a list of common used name for startup
    if ((!strcmp(aFontName, "Helvetica" )) ||
         (!strcmp(aFontName, "Times" )) ||
         (!strcmp(aFontName, "Times New Roman" )) ||
         (!strcmp(aFontName, "Courier New" )) ||
         (!strcmp(aFontName, "Courier" )) ||
         (!strcmp(aFontName, "Arial" )) ||
         (!strcmp(aFontName, "MS P Gothic" )) ||
        (!strcmp(aFontName, "Verdana" ))) {
        // error mean do not get a special encoding
        return NS_ERROR_NOT_AVAILABLE; 
    }

    nsCAutoString name;
    name.Assign(NS_LITERAL_CSTRING("encoding.") + 
                nsDependentCString(aFontName) + NS_LITERAL_CSTRING(".ttf"));

    name.StripWhitespace();
    ToLowerCase(name);

    // if we have not init the property yet, init it right now.
    if (!gFontEncodingProperties)
        NS_LoadPersistentPropertiesFromURISpec(&gFontEncodingProperties,
            NS_LITERAL_CSTRING("resource://gre/res/fonts/fontEncoding.properties"));

    nsAutoString encoding;
    *aEncoding = nsnull;
    if (gFontEncodingProperties) {
        nsresult rv = gFontEncodingProperties->GetStringProperty(name,
                                                                 encoding);
        if (NS_FAILED(rv)) 
            return NS_ERROR_NOT_AVAILABLE;  // Unicode font

        // '.wide' at the end indicates 'wide' font.
        if (encoding.Length() > 5 && 
            StringEndsWith(encoding, NS_LITERAL_STRING(".wide"))) {
            aType = eFontTypeCustomWide;
            encoding.Truncate(encoding.Length() - 5);
        }
        else  {
            aType = eFontTypeCustom;

            // Mathematica and TeX CM truetype fonts have both Apple Roman
            // (PID=1, EID=0) and Unicode (PID=3, EID=1) cmaps. In the
            // former, Unicode cmap uses codepoints in PUA beginning
            // at U+F000 not representable in a single byte encoding
            // like MathML encodings. ( On the other hand, TeX CM fonts
            // have 'pseudo-Unicode' cmap with codepoints below U+0100.)
            // Unicode to font encoding converters for MathML map input 
            // Unicode codepoints to 'pseudo-glyph indices' in Apple Roman 
            // for  Mathematica, Symbol and MTExtra fonts while it maps
            // input Unicode codepoints  to 'pseudo-glyph indices' in 
            // 'Unicode cmap' for TeX CM fonts. Therefore we have to select
            // different FT_Encoding for two groups to guarantee that
            // glyph index look-up with FT_Get_Char_Index succeeds for
            // all MathML fonts. Instead of hard-coding this relation,
            // it's put in fontEncoding.properties file and is parsed here.
          
            nsAutoString ftCharMap; 
            nsresult rv = gFontEncodingProperties->GetStringProperty(
                          Substring(name, 0, name.Length() - 4) + 
                          NS_LITERAL_CSTRING(".ftcmap"), ftCharMap);
          
            if (NS_FAILED(rv)) 
                aFTEncoding = ft_encoding_none;
            else if (ftCharMap.LowerCaseEqualsLiteral("mac_roman"))
                aFTEncoding = ft_encoding_apple_roman;
            else if (ftCharMap.LowerCaseEqualsLiteral("unicode"))
                aFTEncoding = ft_encoding_unicode;
        }

        // encoding name is always in US-ASCII so that there's no loss here.
        *aEncoding = ToNewCString(encoding);
        if (PR_LOG_TEST(gXftFontLoad, PR_LOG_DEBUG)) {
          printf("\t\tc> it's %s and encoding is %s\n",
                  aType==eFontTypeCustom ? "narrow" : "wide", *aEncoding);
        }

        return NS_OK;
    }

    return NS_ERROR_NOT_AVAILABLE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsFontXftInfo * GetFontXftInfo ( FcPattern *  aPattern) [static]

Definition at line 2535 of file nsFontMetricsXft.cpp.

{
    const char* family;

    // If there's no family, just treat it as if it's a normal Unicode font
    if (FcPatternGetString(aPattern, FC_FAMILY, 0, (FcChar8 **) &family) 
         != FcResultMatch) {
        return nsnull;
    }

    NS_ASSERTION(gFontXftMaps.IsInitialized(), "gFontXMaps should be init'd by now.");

    nsFontXftInfo* info;

    // cached entry found. 
    if (gFontXftMaps.Get(family, &info))
        return info;

    nsCOMPtr<nsIUnicodeEncoder> converter;
    nsXftFontType fontType =  eFontTypeUnicode; 
    nsXPIDLCString encoding;
    FT_Encoding ftEncoding = ft_encoding_unicode;
    PRUint16* ccmap = nsnull;

    // See if a font has a custom/private encoding by matching
    // its family name against the list in fontEncoding.properties 
    // with GetEncoding(). It also sets fonttype (wide or narrow). 
    // Then get the converter and see if has a valid coverage map. 
    
    // XXX these two if-statements used to be logically AND'ed, but
    // string changes (bug 231995) made it impossible to use getter_Copies(encoding)
    // and encoding.get() in a single statement. Until Darin comes up with 
    // a solution, we need to split it into two if-statements. (bug 234908)
    if (NS_SUCCEEDED(GetEncoding(family, getter_Copies(encoding), 
                     fontType, ftEncoding))) {
        if (NS_SUCCEEDED(GetConverter(encoding.get(), 
                         getter_AddRefs(converter)))) {
            nsCOMPtr<nsICharRepresentable> mapper(do_QueryInterface(converter));
            if (PR_LOG_TEST(gXftFontLoad, PR_LOG_DEBUG)) {
               printf("\t\tc> got the converter and CMap :%s !!\n",
                      encoding.get());
            }

            if (mapper) {
                ccmap = MapperToCCMap(mapper);
            }
        }
    }

    // XXX Need to check if an identical map has already been added - Bug 75260
    // For Xft, this doesn't look as critical as in GFX Win.

    info = new nsFontXftInfo; 
    if (!info) 
        return nsnull; 

    info->mCCMap =  ccmap;  
    info->mConverter = converter;
    info->mFontType = fontType;
    info->mFT_Encoding = ftEncoding;

    gFontXftMaps.Put(family, info); 

    return info;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static NS_DEFINE_CID ( kCharsetConverterManagerCID  ,
NS_ICHARSETCONVERTERMANAGER_CID   
) [static]

Variable Documentation

Definition at line 300 of file nsFontMetricsXft.cpp.

Definition at line 299 of file nsFontMetricsXft.cpp.

Definition at line 303 of file nsFontMetricsXft.cpp.

Definition at line 298 of file nsFontMetricsXft.cpp.

int gNumInstances = 0 [static]

Definition at line 280 of file nsFontMetricsXft.cpp.

Definition at line 279 of file nsFontMetricsXft.cpp.