:?: unicode font name


#1

the code fragment comes from juce demo:

// implements the SimpleListBoxModel method
    void paintListBoxItem (int rowNumber,
                           Graphics& g,
                           int width, int height,
                           bool rowIsSelected)
    {
        if (rowIsSelected)
            g.fillAll (Colours::lightblue);

        Font* f = fonts [rowNumber];

        if (f != 0)
        {
            f->setHeight (height * 0.7f);
            f->setBold (false);
            f->setItalic (false);

            g.setFont (*f);

            g.drawText (f->getTypefaceName(), 
                        4, 0, width - 4, height, 
                        Justification::centredLeft, true);
        }
    }

the Font::getTypefaceName()'s return is encoded native, in my windowsxp is gb2312.

i wonder how to convert it to unicode and us in drawText.

anybody knows it?
help


#2

ah - that’s probably because I haven’t done unicode versions of the font enumeration methods yet (you can see them in juce_win32_Fonts.cpp). It’s on the to-do-list!


#3

I have tried many many solutions, one of them is using libiconv(win32 version).
But when use the unicode version of font name in function Graphics::drawText() as first parameter, the result is wrong just the same.
Why??

In addtion:
when i use T("\u5e7c\u5706") as the first parameter, it’s done.
when i use uni_fontName(the unicode version font name), it’s wrong.

why?

code list:

class CodeConverter {
    private:
        iconv_t cd;
    public:
        CodeConverter(const char *from_charset,const char *to_charset) {
            cd = iconv_open(to_charset,from_charset);
        }
        
        ~CodeConverter() {
            iconv_close(cd);
        }
        
        int convert(const char *inbuf,int inlen,char *outbuf,int outlen) {
            memset(outbuf,0,outlen);
            return iconv(cd,&inbuf,(size_t *)&inlen,&outbuf,(size_t *)&outlen);
        }
};
    void paintListBoxItem (int rowNumber,
                           Graphics& g,
                           int width, int height,
                           bool rowIsSelected)
    {
        if (rowIsSelected)
            g.fillAll (Colours::lightblue);

        Font* f = fonts [rowNumber];

        char uni_out[OUTLEN];
        if (f != 0)
        {
            f->setHeight (height * 0.7f);
            f->setBold (false);
            f->setItalic (false);

            g.setFont (*f);

            const char* cp936_fontName = f->getTypefaceName();//
            
            CodeConverter cc2 = CodeConverter(("gb2312"),("utf-8"));
            cc2.convert(cp936_fontName,strlen(cp936_fontName),uni_fontName,OUTLEN);
            
            g.drawText (uni_fontName, 
                        4, 0, width - 4, height, 
                        Justification::centredLeft, true);
        }
    }

#4

Try replacing your juce_win32_Fonts.cpp file with this:

[code]/*

This file is part of the JUCE library - "Jules’ Utility Class Extensions"
Copyright 2004 by Julian Storer.


JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA


If you’d like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.

==============================================================================
*/

BEGIN_JUCE_NAMESPACE

//==============================================================================
UNICODE_FUNCTION (GetGlyphOutlineW, DWORD, (HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, CONST MAT2*))
UNICODE_FUNCTION (GetTextMetricsW, BOOL, (HDC, LPTEXTMETRICW))
UNICODE_FUNCTION (GetKerningPairsW, DWORD, (HDC, DWORD, LPKERNINGPAIR))
UNICODE_FUNCTION (EnumFontFamiliesExW, int, (HDC, LPLOGFONTW, FONTENUMPROCW, LPARAM, DWORD))
UNICODE_FUNCTION (CreateFontIndirectW, HFONT, (CONST LOGFONTW *));

static void juce_initialiseUnicodeFileFontFunctions()
{
static bool initialised = false;

if (! initialised)
{
    initialised = true;

    if (SystemStats::getOSType() != SystemStats::Win98
          && SystemStats::getOSType() != SystemStats::Win95)
    {
        HMODULE h = LoadLibraryA ("gdi32.dll");
        UNICODE_FUNCTION_LOAD (GetGlyphOutlineW)
        UNICODE_FUNCTION_LOAD (GetTextMetricsW)
        UNICODE_FUNCTION_LOAD (GetKerningPairsW)
        UNICODE_FUNCTION_LOAD (EnumFontFamiliesExW)
        UNICODE_FUNCTION_LOAD (CreateFontIndirectW)
    }
}

}

//==============================================================================
static int CALLBACK fontEnum2 (ENUMLOGFONTEX* lpelfe,
NEWTEXTMETRICEX*,
int type,
LPARAM lParam)
{
if (lpelfe != 0 && type == TRUETYPE_FONTTYPE)
{
const String fontName (lpelfe->elfLogFont.lfFaceName);

    ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@")));
}

return 1;

}

static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe,
NEWTEXTMETRICEXW*,
int type,
LPARAM lParam)
{
if (lpelfe != 0 && type == TRUETYPE_FONTTYPE)
{
const String fontName (lpelfe->elfLogFont.lfFaceName);

    ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@")));
}

return 1;

}

static int CALLBACK fontEnum1 (ENUMLOGFONTEX* lpelfe,
NEWTEXTMETRICEX*,
int type,
LPARAM lParam)
{
if (lpelfe != 0
&& ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0))
{
LOGFONT lf;
zeromem (&lf, sizeof (lf));

    lf.lfWeight = FW_DONTCARE;
    lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
    lf.lfQuality = DEFAULT_QUALITY;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfPitchAndFamily = FF_DONTCARE;

    const String fontName (lpelfe->elfLogFont.lfFaceName);
    fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);

    HDC dc = CreateCompatibleDC (0);
    EnumFontFamiliesEx (dc, &lf,
                        (FONTENUMPROC) &fontEnum2,
                        lParam, 0);
    DeleteDC (dc);
}

return 1;

}

static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe,
NEWTEXTMETRICEXW*,
int type,
LPARAM lParam)
{
if (lpelfe != 0
&& ((type & (DEVICE_FONTTYPE | RASTER_FONTTYPE)) == 0))
{
LOGFONTW lf;
zeromem (&lf, sizeof (lf));

    lf.lfWeight = FW_DONTCARE;
    lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
    lf.lfQuality = DEFAULT_QUALITY;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfPitchAndFamily = FF_DONTCARE;

    const String fontName (lpelfe->elfLogFont.lfFaceName);
    fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);

    HDC dc = CreateCompatibleDC (0);
    wEnumFontFamiliesExW (dc, &lf,
                          (FONTENUMPROCW) &wfontEnum2,
                          lParam, 0);
    DeleteDC (dc);
}

return 1;

}

const StringArray Font::getAllAvailableFontNames()
{
StringArray results;
HDC dc = CreateCompatibleDC (0);

if (wEnumFontFamiliesExW != 0)
{
    LOGFONTW lf;
    zeromem (&lf, sizeof (lf));

    lf.lfWeight = FW_DONTCARE;
    lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
    lf.lfQuality = DEFAULT_QUALITY;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfPitchAndFamily = FF_DONTCARE;
    lf.lfFaceName[0] = 0;

    wEnumFontFamiliesExW (dc, &lf,
                          (FONTENUMPROCW) &wfontEnum1,
                          (LPARAM) &results, 0);
}
else
{
    LOGFONT lf;
    zeromem (&lf, sizeof (lf));

    lf.lfWeight = FW_DONTCARE;
    lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
    lf.lfQuality = DEFAULT_QUALITY;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfPitchAndFamily = FF_DONTCARE;
    lf.lfFaceName[0] = 0;

    EnumFontFamiliesEx (dc, &lf,
                        (FONTENUMPROC) &fontEnum1,
                        (LPARAM) &results, 0);
}

DeleteDC (dc);
return results;

}

void Font::getDefaultFontNames (String& defaultSans,
String& defaultSerif,
String& defaultFixed)
{
defaultSans = T(“Verdana”);
defaultSerif = T(“Times”);
defaultFixed = T(“Lucida Console”);
}

//==============================================================================
class FontDCHolder : private DeletedAtShutdown
{
HDC dc;
HFONT fontH;
String fontName;
KERNINGPAIR* kps;
int numKPs;
bool bold, italic;

FontDCHolder (const FontDCHolder&);

public:
//==============================================================================
FontDCHolder() throw()
: dc (0),
kps (0),
numKPs (0),
bold (false),
italic (false)
{
juce_initialiseUnicodeFileFontFunctions();
}

~FontDCHolder() throw()
{
    if (dc != 0)
    {
        DeleteDC (dc);
        DeleteObject (fontH);

        if (kps)
            juce_free (kps);
    }
}

static FontDCHolder* getInstance() throw()
{
    static FontDCHolder* instance = 0;

    if (instance == 0)
        instance = new FontDCHolder();

    return instance;
}

//==============================================================================
HDC loadFont (const String& fontName_,
              const bool bold_,
              const bool italic_) throw()
{
    if (fontName != fontName_ || bold != bold_ || italic != italic_)
    {
        fontName = fontName_;
        bold = bold_;
        italic = italic_;

        if (dc != 0)
        {
            DeleteDC (dc);
            DeleteObject (fontH);

            if (kps != 0)
            {
                juce_free (kps);
                kps = 0;
            }
        }

        fontH = 0;

        dc = CreateCompatibleDC (0);
        SetMapperFlags (dc, 0);
        SetMapMode (dc, MM_TEXT);

        LOGFONT lf;
        LOGFONTW lfw;
        HFONT standardSizedFont = 0;

        if (wCreateFontIndirectW != 0)
        {
            zeromem (&lfw, sizeof (lfw));

            lfw.lfCharSet = DEFAULT_CHARSET;
            lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS;
            lfw.lfOutPrecision = OUT_OUTLINE_PRECIS;
            lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
            lfw.lfQuality = PROOF_QUALITY;
            lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE);
            lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL;
            fontName.copyToBuffer (lfw.lfFaceName, LF_FACESIZE - 1);

            lfw.lfHeight = -256;
            standardSizedFont = wCreateFontIndirectW (&lfw);
        }
        else
        {
            zeromem (&lf, sizeof (lf));

            lf.lfCharSet = DEFAULT_CHARSET;
            lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
            lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
            lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
            lf.lfQuality = PROOF_QUALITY;
            lf.lfItalic = (BYTE) (italic ? TRUE : FALSE);
            lf.lfWeight = bold ? FW_BOLD : FW_NORMAL;
            fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1);

            lf.lfHeight = -256;
            standardSizedFont = CreateFontIndirect (&lf);
        }

        if (standardSizedFont != 0)
        {
            if (SelectObject (dc, standardSizedFont) != 0)
            {
                OUTLINETEXTMETRIC otm;
                if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0)
                {
                    if (wCreateFontIndirectW != 0)
                    {
                        lfw.lfHeight = -(int) otm.otmEMSquare;
                        fontH = wCreateFontIndirectW (&lfw);
                    }
                    else
                    {
                        lf.lfHeight = -(int) otm.otmEMSquare;
                        fontH = CreateFontIndirect (&lf);
                    }

                    SelectObject (dc, fontH);
                    DeleteObject (standardSizedFont);
                }
                else
                {
                    jassertfalse
                }
            }
            else
            {
                jassertfalse
            }
        }
        else
        {
            jassertfalse
        }
    }

    return dc;
}

//==============================================================================
KERNINGPAIR* getKerningPairs (int& numKPs_) throw()
{
    if (kps == 0)
    {
        if (wGetKerningPairsW != 0)
        {
            numKPs = wGetKerningPairsW (dc, 0, 0);
            kps = (KERNINGPAIR*) juce_calloc (sizeof (KERNINGPAIR) * numKPs);
            wGetKerningPairsW (dc, numKPs, kps);
        }
        else
        {
            numKPs = GetKerningPairs (dc, 0, 0);
            kps = (KERNINGPAIR*) juce_calloc (sizeof (KERNINGPAIR) * numKPs);
            GetKerningPairs (dc, numKPs, kps);
        }
    }

    numKPs_ = numKPs;
    return kps;
}

};

//==============================================================================
static MAT2 identityMatrix;

static void addGlyphToTypeface (HDC dc,
juce_wchar character,
Typeface& dest,
bool addKerning)
{
Path destShape;
GLYPHMETRICS gm;

float height;

if (wGetTextMetricsW != 0)
{
    TEXTMETRICW tm;
    wGetTextMetricsW (dc, &tm);

    height = (float) tm.tmHeight;
}
else
{
    TEXTMETRIC tm;
    GetTextMetrics (dc, &tm);

    height = (float) tm.tmHeight;
}

const float scaleX = 1.0f / height;
const float scaleY = -1.0f / height;

int bufSize;

if (wGetGlyphOutlineW != 0)
    bufSize = wGetGlyphOutlineW (dc, character, GGO_NATIVE,
                                 &gm, 0, 0, &identityMatrix);
else
    bufSize = GetGlyphOutline (dc, character, GGO_NATIVE,
                               &gm, 0, 0, &identityMatrix);

if (bufSize > 0)
{
    char* const data = (char*) juce_malloc (bufSize);

    if (wGetGlyphOutlineW != 0)
        wGetGlyphOutlineW (dc, character, GGO_NATIVE, &gm,
                           bufSize, data, &identityMatrix);
    else
        GetGlyphOutline (dc, character, GGO_NATIVE, &gm,
                         bufSize, data, &identityMatrix);

    const TTPOLYGONHEADER* pheader = (TTPOLYGONHEADER*) data;

    while ((char*) pheader < data + bufSize)
    {



        float x = remapX (pheader->pfxStart);
        float y = remapY (pheader->pfxStart);

        destShape.startNewSubPath (x, y);

        const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER));
        const char* const curveEnd = ((const char*) pheader) + pheader->cb;

        while ((const char*) curve < curveEnd)
        {
            if (curve->wType == TT_PRIM_LINE)
            {
                for (int i = 0; i < curve->cpfx; ++i)
                {
                    x = remapX (curve->apfx [i]);
                    y = remapY (curve->apfx [i]);

                    destShape.lineTo (x, y);
                }
            }
            else if (curve->wType == TT_PRIM_QSPLINE)
            {
                for (int i = 0; i < curve->cpfx - 1; ++i)
                {
                    const float x2 = remapX (curve->apfx [i]);
                    const float y2 = remapY (curve->apfx [i]);
                    float x3, y3;

                    if (i < curve->cpfx - 2)
                    {
                        x3 = 0.5f * (x2 + remapX (curve->apfx [i + 1]));
                        y3 = 0.5f * (y2 + remapY (curve->apfx [i + 1]));
                    }
                    else
                    {
                        x3 = remapX (curve->apfx [i + 1]);
                        y3 = remapY (curve->apfx [i + 1]);
                    }

                    destShape.quadraticTo (x2, y2, x3, y3);

                    x = x3;
                    y = y3;
                }
            }

            curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]);
        }

        pheader = (const TTPOLYGONHEADER*) curve;

        destShape.closeSubPath();
    }

    juce_free (data);
}

dest.addGlyph (character, destShape, gm.gmCellIncX / height);

if (addKerning)
{
    int numKPs;
    const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs);

    for (int i = 0; i < numKPs; ++i)
    {
        if (kps[i].wFirst == character)
        {
            dest.addKerningPair (kps[i].wFirst,
                                 kps[i].wSecond,
                                 kps[i].iKernAmount / height);
        }
    }
}

}

//==============================================================================
void Typeface::findAndAddSystemGlyph (juce_wchar character)
{
HDC dc = FontDCHolder::getInstance()->loadFont (getName(), isBold(), isItalic());
addGlyphToTypeface (dc, character, *this, true);
}

//==============================================================================
void Typeface::initialiseTypefaceCharacteristics (const String& fontName,
bool bold,
bool italic,
bool addAllGlyphsToFont)
{
zeromem (&identityMatrix, sizeof (identityMatrix));
identityMatrix.eM11.value = 1;
identityMatrix.eM22.value = 1;

clear();

HDC dc = FontDCHolder::getInstance()->loadFont (fontName, bold, italic);

float height;
int firstChar, lastChar;

if (wGetTextMetricsW != 0)
{
    TEXTMETRICW tm;
    wGetTextMetricsW (dc, &tm);

    height = (float) tm.tmHeight;
    firstChar = tm.tmFirstChar;
    lastChar = tm.tmLastChar;

    setAscent (tm.tmAscent / height);
    setDefaultCharacter (tm.tmDefaultChar);
}
else
{
    TEXTMETRIC tm;
    GetTextMetrics (dc, &tm);

    height = (float) tm.tmHeight;
    firstChar = tm.tmFirstChar;
    lastChar = tm.tmLastChar;

    setAscent (tm.tmAscent / height);
    setDefaultCharacter (tm.tmDefaultChar);
}

setName (fontName);
setBold (bold);
setItalic (italic);

if (addAllGlyphsToFont)
{
    for (int character = firstChar; character <= lastChar; ++character)
        addGlyphToTypeface (dc, (juce_wchar) character, *this, false);

    int numKPs;
    const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs);

    for (int i = 0; i < numKPs; ++i)
    {
        addKerningPair (kps[i].wFirst,
                        kps[i].wSecond,
                        kps[i].iKernAmount / height);
    }
}

}

END_JUCE_NAMESPACE
[/code]


#5

clobber is clobber again.

More terribly many chinese fonts have the same character set.
my god!


#6

[quote=“ehu4ever”]clobber is clobber again.

More terribly many chinese fonts have the same character set.
my god![/quote]

…right… so do you mean that it worked!??


#7

you solution is not worked.

furthermore,
the new bug is different chinese fonts have same characters.

i’m sorry for my wrong expression.


#8

Not sure I understand… could you explain again, or maybe post a screenshot?


#9

detail:
when select different chinese font in the left listbox, the text in the right textbox has the same result.

http://wiki.woodpecker.org.cn/moin/ehu4ever/2005-09-18?action=AttachFile&do=get&target=Snap1.png
http://wiki.woodpecker.org.cn/moin/ehu4ever/2005-09-18?action=AttachFile&do=get&target=Snap2.png
http://wiki.woodpecker.org.cn/moin/ehu4ever/2005-09-18?action=AttachFile&do=get&target=Snap3.png


#10

oh - that’s not right, is it! I suppose it must be failing to open the font at juce_win32_Fonts.cpp, line 311.

Maybe you could have a look and see what it’s doing in there - it might be something obvious. Or could you maybe send me one of the chinese fonts so I can try it myself?


#11

[quote=“jules”]oh - that’s not right, is it! I suppose it must be failing to open the font at juce_win32_Fonts.cpp, line 311.

Maybe you could have a look and see what it’s doing in there - it might be something obvious. Or could you maybe send me one of the chinese fonts so I can try it myself?[/quote]

I have emailed some chinese fonts to you.


#12