1ae7e3b26SLisandro Dalcin 2ae7e3b26SLisandro Dalcin /* 3ae7e3b26SLisandro Dalcin This file contains simple code to manage access to fonts, insuring that 4ae7e3b26SLisandro Dalcin library routines access/load fonts only once 5ae7e3b26SLisandro Dalcin */ 6ae7e3b26SLisandro Dalcin 7ae7e3b26SLisandro Dalcin #include <../src/sys/classes/draw/impls/x/ximpl.h> 8ae7e3b26SLisandro Dalcin 909440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *); 1009440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *, PetscDrawXiFont *); 1109440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *, int, int); 1209440f25SLisandro Dalcin 13ae7e3b26SLisandro Dalcin /* 14ae7e3b26SLisandro Dalcin PetscDrawXiFontFixed - Return a pointer to the selected font. 15ae7e3b26SLisandro Dalcin 16ae7e3b26SLisandro Dalcin Warning: Loads a new font for each window. This should be 17ae7e3b26SLisandro Dalcin ok because there will never be many windows and the graphics 18ae7e3b26SLisandro Dalcin are not intended to be high performance. 19ae7e3b26SLisandro Dalcin */ 20d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X *XBWin, int w, int h, PetscDrawXiFont **outfont) 21d71ae5a4SJacob Faibussowitsch { 2202c9f0b5SLisandro Dalcin static PetscDrawXiFont *curfont = NULL, *font; 23ae7e3b26SLisandro Dalcin 24ae7e3b26SLisandro Dalcin PetscFunctionBegin; 259566063dSJacob Faibussowitsch if (!curfont) PetscCall(PetscDrawXiInitFonts(XBWin)); 269566063dSJacob Faibussowitsch PetscCall(PetscNew(&font)); 279566063dSJacob Faibussowitsch PetscCall(PetscDrawXiMatchFontSize(font, w, h)); 289566063dSJacob Faibussowitsch PetscCall(PetscDrawXiLoadFont(XBWin, font)); 29ae7e3b26SLisandro Dalcin 30ae7e3b26SLisandro Dalcin curfont = font; 31ae7e3b26SLisandro Dalcin *outfont = curfont; 32*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33ae7e3b26SLisandro Dalcin } 34ae7e3b26SLisandro Dalcin 35ae7e3b26SLisandro Dalcin /* this is set by XListFonts at startup */ 36ae7e3b26SLisandro Dalcin #define NFONTS 20 37d71ae5a4SJacob Faibussowitsch static struct { 38d71ae5a4SJacob Faibussowitsch int w, h, descent; 39d71ae5a4SJacob Faibussowitsch } nfonts[NFONTS]; 40ae7e3b26SLisandro Dalcin static int act_nfonts = 0; 41ae7e3b26SLisandro Dalcin 42ae7e3b26SLisandro Dalcin /* 43ae7e3b26SLisandro Dalcin These routines determine the font to be used based on the requested size, 44ae7e3b26SLisandro Dalcin and load it if necessary 45ae7e3b26SLisandro Dalcin */ 46ae7e3b26SLisandro Dalcin 47d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiLoadFont(PetscDraw_X *XBWin, PetscDrawXiFont *font) 48d71ae5a4SJacob Faibussowitsch { 49ae7e3b26SLisandro Dalcin char font_name[100]; 50ae7e3b26SLisandro Dalcin XFontStruct *FontInfo; 51ae7e3b26SLisandro Dalcin XGCValues values; 52ae7e3b26SLisandro Dalcin 53ae7e3b26SLisandro Dalcin PetscFunctionBegin; 54a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(font_name, PETSC_STATIC_ARRAY_LENGTH(font_name), "%dx%d", font->font_w, font->font_h)); 55ae7e3b26SLisandro Dalcin font->fnt = XLoadFont(XBWin->disp, font_name); 56ae7e3b26SLisandro Dalcin 57ae7e3b26SLisandro Dalcin /* The font->descent may not have been set correctly; get it now that 58ae7e3b26SLisandro Dalcin the font has been loaded */ 59ae7e3b26SLisandro Dalcin FontInfo = XQueryFont(XBWin->disp, font->fnt); 60ae7e3b26SLisandro Dalcin font->font_descent = FontInfo->descent; 61ae7e3b26SLisandro Dalcin font->font_w = FontInfo->max_bounds.rbearing - FontInfo->min_bounds.lbearing; 62ae7e3b26SLisandro Dalcin font->font_h = FontInfo->max_bounds.ascent + FontInfo->max_bounds.descent; 63ae7e3b26SLisandro Dalcin 6402c9f0b5SLisandro Dalcin XFreeFontInfo(NULL, FontInfo, 1); 65ae7e3b26SLisandro Dalcin 66ae7e3b26SLisandro Dalcin /* Set the current font in the CG */ 67ae7e3b26SLisandro Dalcin values.font = font->fnt; 68ae7e3b26SLisandro Dalcin XChangeGC(XBWin->disp, XBWin->gc.set, GCFont, &values); 69*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70ae7e3b26SLisandro Dalcin } 71ae7e3b26SLisandro Dalcin 72ae7e3b26SLisandro Dalcin /* Code to find fonts and their characteristics */ 73d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiInitFonts(PetscDraw_X *XBWin) 74d71ae5a4SJacob Faibussowitsch { 75ae7e3b26SLisandro Dalcin char **names; 76ae7e3b26SLisandro Dalcin int cnt, i, j; 77ae7e3b26SLisandro Dalcin XFontStruct *info; 78ae7e3b26SLisandro Dalcin 79ae7e3b26SLisandro Dalcin PetscFunctionBegin; 80ae7e3b26SLisandro Dalcin /* This just gets the most basic fixed-width fonts */ 81ae7e3b26SLisandro Dalcin names = XListFontsWithInfo(XBWin->disp, "?x??", NFONTS, &cnt, &info); 82ae7e3b26SLisandro Dalcin j = 0; 83ae7e3b26SLisandro Dalcin for (i = 0; i < cnt; i++) { 84ae7e3b26SLisandro Dalcin names[i][1] = '\0'; 85ae7e3b26SLisandro Dalcin nfonts[j].w = info[i].max_bounds.width; 86ae7e3b26SLisandro Dalcin nfonts[j].h = info[i].ascent + info[i].descent; 87ae7e3b26SLisandro Dalcin nfonts[j].descent = info[i].descent; 88ae7e3b26SLisandro Dalcin if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue; 89ae7e3b26SLisandro Dalcin j++; 90ae7e3b26SLisandro Dalcin if (j >= NFONTS) break; 91ae7e3b26SLisandro Dalcin } 92ae7e3b26SLisandro Dalcin act_nfonts = j; 93ae7e3b26SLisandro Dalcin if (cnt > 0) XFreeFontInfo(names, info, cnt); 94ae7e3b26SLisandro Dalcin 95ae7e3b26SLisandro Dalcin /* If the above fails,try this: */ 96ae7e3b26SLisandro Dalcin if (!act_nfonts) { 97ae7e3b26SLisandro Dalcin /* This just gets the most basic fixed-width fonts */ 98ae7e3b26SLisandro Dalcin names = XListFontsWithInfo(XBWin->disp, "?x", NFONTS, &cnt, &info); 99ae7e3b26SLisandro Dalcin j = 0; 100ae7e3b26SLisandro Dalcin for (i = 0; i < cnt; i++) { 101ae7e3b26SLisandro Dalcin size_t len; 102ae7e3b26SLisandro Dalcin 1039566063dSJacob Faibussowitsch PetscCall(PetscStrlen(names[i], &len)); 104ae7e3b26SLisandro Dalcin if (len != 2) continue; 105ae7e3b26SLisandro Dalcin names[i][1] = '\0'; 106ae7e3b26SLisandro Dalcin nfonts[j].w = info[i].max_bounds.width; 107ae7e3b26SLisandro Dalcin /* nfonts[j].w = info[i].max_bounds.lbearing + info[i].max_bounds.rbearing; */ 108ae7e3b26SLisandro Dalcin nfonts[j].h = info[i].ascent + info[i].descent; 109ae7e3b26SLisandro Dalcin nfonts[j].descent = info[i].descent; 110ae7e3b26SLisandro Dalcin if (nfonts[j].w <= 0 || nfonts[j].h <= 0) continue; 111ae7e3b26SLisandro Dalcin j++; 112ae7e3b26SLisandro Dalcin if (j >= NFONTS) break; 113ae7e3b26SLisandro Dalcin } 114ae7e3b26SLisandro Dalcin act_nfonts = j; 115ae7e3b26SLisandro Dalcin XFreeFontInfo(names, info, cnt); 116ae7e3b26SLisandro Dalcin } 117*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 118ae7e3b26SLisandro Dalcin } 119ae7e3b26SLisandro Dalcin 120d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiMatchFontSize(PetscDrawXiFont *font, int w, int h) 121d71ae5a4SJacob Faibussowitsch { 122ae7e3b26SLisandro Dalcin int i, max, imax, tmp; 123ae7e3b26SLisandro Dalcin 124ae7e3b26SLisandro Dalcin PetscFunctionBegin; 125ae7e3b26SLisandro Dalcin for (i = 0; i < act_nfonts; i++) { 126ae7e3b26SLisandro Dalcin if (nfonts[i].w == w && nfonts[i].h == h) { 127ae7e3b26SLisandro Dalcin font->font_w = w; 128ae7e3b26SLisandro Dalcin font->font_h = h; 129ae7e3b26SLisandro Dalcin font->font_descent = nfonts[i].descent; 130*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131ae7e3b26SLisandro Dalcin } 132ae7e3b26SLisandro Dalcin } 133ae7e3b26SLisandro Dalcin 134ae7e3b26SLisandro Dalcin /* determine closest fit,per max. norm */ 135ae7e3b26SLisandro Dalcin imax = 0; 136ae7e3b26SLisandro Dalcin max = PetscMax(PetscAbsInt(nfonts[0].w - w), PetscAbsInt(nfonts[0].h - h)); 137ae7e3b26SLisandro Dalcin for (i = 1; i < act_nfonts; i++) { 138ae7e3b26SLisandro Dalcin tmp = PetscMax(PetscAbsInt(nfonts[i].w - w), PetscAbsInt(nfonts[i].h - h)); 1399371c9d4SSatish Balay if (tmp < max) { 1409371c9d4SSatish Balay max = tmp; 1419371c9d4SSatish Balay imax = i; 1429371c9d4SSatish Balay } 143ae7e3b26SLisandro Dalcin } 144ae7e3b26SLisandro Dalcin 145ae7e3b26SLisandro Dalcin /* should use font with closest match */ 146ae7e3b26SLisandro Dalcin font->font_w = nfonts[imax].w; 147ae7e3b26SLisandro Dalcin font->font_h = nfonts[imax].h; 148ae7e3b26SLisandro Dalcin font->font_descent = nfonts[imax].descent; 149*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 150ae7e3b26SLisandro Dalcin } 151