From 2af3c28de8021cdd799a5aa2ff7e65aa8e2a488d Mon Sep 17 00:00:00 2001 From: Laurent Carlier Date: Sun, 12 Sep 2010 18:36:22 +0000 Subject: [PATCH] [GB.SDL] * NEW: System fonts are now displayed with SDL_ttf library. git-svn-id: svn://localhost/gambas/trunk@3208 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- gb.sdl/src/Cdraw.cpp | 11 ++ gb.sdl/src/SDLapp.cpp | 2 +- gb.sdl/src/SDLfont.cpp | 262 +++++++++++++++----------------------- gb.sdl/src/SDLfont.h | 3 +- gb.sdl/src/SDLsurface.cpp | 2 + 5 files changed, 119 insertions(+), 161 deletions(-) diff --git a/gb.sdl/src/Cdraw.cpp b/gb.sdl/src/Cdraw.cpp index 2bb4c4c77..1dea5f453 100644 --- a/gb.sdl/src/Cdraw.cpp +++ b/gb.sdl/src/Cdraw.cpp @@ -56,6 +56,8 @@ static bool check_graphic(void) void DRAW_begin(void *device) { + static GB_CLASS font_id = NULL; + if (THIS >= &draw_stack[DRAW_STACK_MAX - 1]) { GB.Error("Too many nested drawings"); @@ -73,6 +75,15 @@ void DRAW_begin(void *device) THIS->backcolor = 0x00000000; THIS->forecolor = 0x00FFFFFF; + if (!font_id) + font_id = GB.FindClass("Font"); + + if (FONT) + GB.Unref(POINTER(&FONT)); + + GB.New(POINTER(&FONT), font_id, NULL, NULL); + GB.Ref(FONT); + if (GB.Is(device, CLASS_Window)) { THIS->device = device; diff --git a/gb.sdl/src/SDLapp.cpp b/gb.sdl/src/SDLapp.cpp index bd2f031ac..bab4e8426 100644 --- a/gb.sdl/src/SDLapp.cpp +++ b/gb.sdl/src/SDLapp.cpp @@ -58,7 +58,7 @@ SDLapplication::SDLapplication(int &argc, char **argv) } else { - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE /* | SDL_INIT_EVENTTHREAD*/)<0) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE /* | SDL_INIT_EVENTTHREAD */)<0) { sMsg =+ SDL_GetError(); goto _error; diff --git a/gb.sdl/src/SDLfont.cpp b/gb.sdl/src/SDLfont.cpp index 9d6d835da..4c0a59cab 100644 --- a/gb.sdl/src/SDLfont.cpp +++ b/gb.sdl/src/SDLfont.cpp @@ -30,17 +30,24 @@ #include #include +typedef struct { + std::string name; + std::string realname; + std::string foundry; + } fontdesc; + +static std::vector fontDB; + static StringList _FontList; Display *SDLfont::display = 0; int SDLfont::screen = 0; -XftColor SDLfont::background, SDLfont::foreground; #define DEFAULT_FONT_SIZE 20 #define DEFAULT_DPI 72 /* Default DPI size in SDL_TTF */ -inline bool cmp_nocase(const std::string x, const std::string y) +inline bool cmp_db_nocase(const fontdesc x, const fontdesc y) { - std::string a = x, b = y; + std::string a = x.name, b = y.name; transform(a.begin(), a.end(), a.begin(), tolower); transform(b.begin(), b.end(), b.begin(), tolower); return (b>a) ? 1 : 0; @@ -52,94 +59,118 @@ StringList SDLfont::GetFontList(void ) return _FontList; Display *disp = SDLapp->X11appDisplay(); - XftFontSet *hSet = XftListFonts(disp, DefaultScreen(disp), NULL, XFT_FAMILY, NULL); - + XftFontSet *FntnameSet = XftListFonts(disp, DefaultScreen(disp), NULL, + XFT_FAMILY, /*XFT_FILE, XFT_FOUNDRY,*/ NULL); + int i; + // Get the fonts name - for (int i=0; infont; i++) - { + for (i = 0; i < FntnameSet->nfont; i++) { char *name[255]; - XftResult res = XftPatternGetString(hSet->fonts[i], XFT_FAMILY, 0, name); + char *foundry[255]; + fontdesc font; + unsigned int j; + + XftResult res = XftPatternGetString(FntnameSet->fonts[i], XFT_FAMILY, 0, name); - if (res!=XftResultMatch) - { - XFree(hSet); - SDLerror::RaiseError("Failed to list system fonts !"); - return _FontList; - } + if (res!=XftResultMatch) + continue; - _FontList.push_back(name[0]); + XftFontSet *Fntdetail = XftListFonts(disp, DefaultScreen(disp), + XFT_FAMILY, XftTypeString, name[0], 0, + XFT_FOUNDRY, NULL); + j = Fntdetail->nfont; + + if (j>1) { + while (j) { + XftPatternGetString(Fntdetail->fonts[j-1], XFT_FOUNDRY, 0, foundry); + font.name = font.realname = name[0]; + font.foundry = foundry[0]; + font.name = font.name + " [" +font.foundry+ "]"; + fontDB.push_back(font); + j--; + } + } + else { + font.name = font.realname = name[0]; + XftPatternGetString(Fntdetail->fonts[0], XFT_FOUNDRY, 0, foundry); + font.foundry = foundry[0]; + fontDB.push_back(font); + } +// XftPatternGetString(hSet->fonts[i], XFT_FILE, 0, name); + XFree(Fntdetail); } - std::sort(_FontList.begin(), _FontList.end(), cmp_nocase); + std::sort(fontDB.begin(), fontDB.end(), cmp_db_nocase); + XFree(FntnameSet); - XFree(hSet); + std::string font = ""; + i = 0; + while (iX11appDisplay(); screen = DefaultScreen(display); - - // full white - foreg.red = foreg.green = foreg.blue = backg.alpha = 0xFFFF; - //transparent black - backg.red = backg.green = backg.blue = foreg.alpha = 0x0000; - - if (!XftColorAllocValue(display , DefaultVisual(display, screen), - DefaultColormap(display, screen), &foreg, &foreground)) - std::cerr << "error XftColorAllocValue() foreground" << std::endl; - - if (!XftColorAllocValue(display , DefaultVisual(display, screen), - DefaultColormap(display, screen), &backg, &background)) - std::cerr << "error XftColorAllocValue() background" << std::endl; - } void SDLfont::Exit() { - XftColorFree(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &foreground); - XftColorFree(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &background); } SDLfont::SDLfont() { hfonttype = X_font; - char fnt[512]; - - snprintf(fnt, 512, "Arial,helvetica-%d:medium:slant=roman:dpi=%d", - DEFAULT_FONT_SIZE, DEFAULT_DPI); - - hXfont = XftFontOpenName(display, screen, fnt); -// XftNameUnparse(hXfont->pattern, fnt, 512); -// std::cout << fnt << std::endl; - - if (UNLIKELY(hXfont == NULL)) - SDLerror::RaiseError("Failed to open default font!"); -} - -SDLfont::SDLfont(char *fontfile) -{ - hfonttype = SDLTTF_font; - hfontname = fontfile; hfontsize = DEFAULT_FONT_SIZE; + char *res[255]; + + SDLfont::GetFontList(); + XftFontSet *Fntdetail = XftListFonts(SDLapp->X11appDisplay(), DefaultScreen(SDLapp->X11appDisplay()), + XFT_FAMILY, XftTypeString, fontDB[0].name.c_str(), + XFT_FOUNDRY, XftTypeString, fontDB[0].foundry.c_str(), 0, + XFT_FILE, NULL); + XftPatternGetString(Fntdetail->fonts[0], XFT_FILE, 0, res); + hfontname = res[0]; + hfontindex = 0; + XFree(Fntdetail); - hSDLfont = TTF_OpenFont(fontfile, hfontsize); + hSDLfont = TTF_OpenFont(hfontname.c_str(), hfontsize); if (UNLIKELY(hSDLfont == NULL)) SDLerror::RaiseError(TTF_GetError()); } +SDLfont::SDLfont(char *fontfile) +{ + hfonttype = SDLTTF_font; + hfontsize = DEFAULT_FONT_SIZE; + hfontname = fontfile; + + hSDLfont = TTF_OpenFont(fontfile, hfontsize); + + if (UNLIKELY(hSDLfont == NULL)) + SDLerror::RaiseError(TTF_GetError()); +} + SDLfont::~SDLfont() { - if ((hfonttype == SDLTTF_font) && hSDLfont) + if (hSDLfont) TTF_CloseFont(hSDLfont); - - if ((hfonttype == X_font) && hXfont) - XftFontClose(display, hXfont); } void SDLfont::SetFontName(char* name) @@ -148,152 +179,67 @@ void SDLfont::SetFontName(char* name) const char* SDLfont::GetFontName(void ) { - if (hfonttype == SDLTTF_font) - { + if (hfonttype == SDLTTF_font) { std::string name; name = hfontname.substr((hfontname.find_last_of("/"))+1); return name.c_str(); } - else - return hfontname.c_str(); + else + return fontDB[hfontindex].name.c_str(); } void SDLfont::SetFontSize(int size) { hfontsize = size; - if (hfonttype == SDLTTF_font) - { - if (hSDLfont) - TTF_CloseFont(hSDLfont); + if (hSDLfont) + TTF_CloseFont(hSDLfont); - hSDLfont = TTF_OpenFont(hfontname.c_str(), hfontsize); + hSDLfont = TTF_OpenFont(hfontname.c_str(), hfontsize); - if (UNLIKELY(hSDLfont == NULL)) - SDLerror::RaiseError(TTF_GetError()); - } + if (UNLIKELY(hSDLfont == NULL)) + SDLerror::RaiseError(TTF_GetError()); } void SDLfont::SetFontUnderline(bool state) { - if (hfonttype == SDLTTF_font) - { - } } bool SDLfont::IsFontUnderlined(void ) { - if (hfonttype == SDLTTF_font) - { - } - return false; } bool SDLfont::IsFontScalable(void ) { - if (hfonttype == SDLTTF_font) - return true; - else - { - Bool scalable; - - XftPatternGetBool(hXfont->pattern, - XFT_SCALABLE, 0, &scalable); - return (scalable); - } + return true; } int SDLfont::GetFontAscent(void ) { - if (hfonttype == SDLTTF_font) - return TTF_FontAscent(hSDLfont); - else - return (hXfont->ascent); + return TTF_FontAscent(hSDLfont); } int SDLfont::GetFontDescent(void ) { - if (hfonttype == SDLTTF_font) - return TTF_FontDescent(hSDLfont); - else - return (hXfont->descent); + return TTF_FontDescent(hSDLfont); } bool SDLfont::IsFontFixed(void ) { - if (hfonttype == SDLTTF_font) - return (TTF_FontFaceIsFixedWidth(hSDLfont)); - else - { - int spacing; - - XftPatternGetInteger(hXfont->pattern, - XFT_SPACING, 0, &spacing); - return (spacing >= XFT_MONO); - } + return (TTF_FontFaceIsFixedWidth(hSDLfont)); } void SDLfont::SizeText(const char *text, int *width, int *height) { - if (hfonttype == SDLTTF_font) - TTF_SizeText(hSDLfont, text, width, height); - else - { - XGlyphInfo glyphinfo; - - XftTextExtentsUtf8(display , hXfont, (XftChar8* )text, strlen(text), &glyphinfo); - *width = int(glyphinfo.width); - *height = int(glyphinfo.height); - } + TTF_SizeText(hSDLfont, text, width, height); } SDLsurface* SDLfont::RenderText(const char* text) { - if (hfonttype == SDLTTF_font) - { - SDL_Color fg = {0xFF, 0xFF, 0xFF}; + SDL_Color fg = {0xFF, 0xFF, 0xFF}; - SDL_Surface *result = TTF_RenderUTF8_Blended(hSDLfont, text, fg); - SDLsurface *surf = new SDLsurface(result); - return (surf); - } - else - { - XGlyphInfo glyphinfo; - - SDLapp->LockX11(); - XftTextExtentsUtf8(display , hXfont, (XftChar8* )text, strlen(text), &glyphinfo); - // Create the pixmap to draw on. - Pixmap pixmap = XCreatePixmap(display, DefaultRootWindow(display), glyphinfo.width, - glyphinfo.height, DefaultDepth(display, screen)); - - // And the Xft wrapper around it. - XftDraw *draw = XftDrawCreate(display, pixmap, DefaultVisual(display, screen), - DefaultColormap(display, screen)); - XftDrawRect(draw, &background, 0, 0, glyphinfo.width, glyphinfo.height); - XftDrawString8(draw, &foreground, hXfont, 0, glyphinfo.height-1 , (XftChar8 *)text, strlen(text)); - XImage *img = XGetImage(display, pixmap, 0, 0, glyphinfo.width, glyphinfo.height, AllPlanes, ZPixmap); - SDLsurface *surf = new SDLsurface(glyphinfo.width, glyphinfo.height); - Uint8 *data = (Uint8 *) surf->GetData(); - - for (int y = 0; y < glyphinfo.height; y++) - { - for (int x = 0; x < glyphinfo.width; x++) - { - Uint32 pixel = (Uint32 )XGetPixel(img, x, y); - ((Uint32* )surf->GetData())[x + (y * glyphinfo.width)] = XGetPixel(img, x, y); - /* Create alpha value depending of pixel value (lowest R,G,B value)*/ - data[3] = (pixel & 0xFF) & ((pixel >> 8) & 0xFF) & - ((pixel >> 16) & 0xFF); - data += 4; - } - } - // clean up - XDestroyImage(img); - XftDrawDestroy(draw); - XFreePixmap(display, pixmap); - SDLapp->UnlockX11(); - return (surf); - } + SDL_Surface *result = TTF_RenderUTF8_Blended(hSDLfont, text, fg); + SDLsurface *surf = new SDLsurface(result); + return (surf); } \ No newline at end of file diff --git a/gb.sdl/src/SDLfont.h b/gb.sdl/src/SDLfont.h index 68a850263..30ec8db1e 100644 --- a/gb.sdl/src/SDLfont.h +++ b/gb.sdl/src/SDLfont.h @@ -76,10 +76,9 @@ private: int hSDLfontstyle; /* System font */ - XftFont *hXfont; - static XftColor background, foreground; static Display *display; static int screen; + int hfontindex; }; #endif /* _SDLFONT_H */ diff --git a/gb.sdl/src/SDLsurface.cpp b/gb.sdl/src/SDLsurface.cpp index e420711ce..c5e02993f 100644 --- a/gb.sdl/src/SDLsurface.cpp +++ b/gb.sdl/src/SDLsurface.cpp @@ -123,6 +123,8 @@ SDLsurface::SDLsurface(int Width, int Height) if (!hSurface) SDLcore::RaiseError(SDL_GetError()); + + hTexture->ToLoad(); } SDLsurface::~SDLsurface()