/** Realize the font, \a pFont, on the back-end server associated with * \a pScreen. */ Bool dmxRealizeFont(ScreenPtr pScreen, FontPtr pFont) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; dmxFontPrivPtr pFontPriv; if (!(pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); pFontPriv = malloc(sizeof(dmxFontPrivRec)); if (!pFontPriv) return FALSE; pFontPriv->font = NULL; MAXSCREENSALLOC(pFontPriv->font); if (!pFontPriv->font) { free(pFontPriv); return FALSE; } pFontPriv->refcnt = 0; } FontSetPrivate(pFont, dmxFontPrivateIndex, (void *) pFontPriv); if (dmxScreen->beDisplay) { if (!dmxBELoadFont(pScreen, pFont)) return FALSE; pFontPriv->refcnt++; } else { pFontPriv->font[pScreen->myNum] = NULL; } return TRUE; }
static Bool glamor_unrealize_font(ScreenPtr screen, FontPtr font) { glamor_screen_private *glamor_priv; glamor_font_t *privates = FontGetPrivate(font, glamor_font_private_index); glamor_font_t *glamor_font; int s; if (!privates) return TRUE; glamor_font = &privates[screen->myNum]; if (!glamor_font->realized) return TRUE; /* Unrealize the font, freeing the allocated texture */ glamor_font->realized = FALSE; glamor_priv = glamor_get_screen_private(screen); glamor_make_current(glamor_priv); glDeleteTextures(1, &glamor_font->texture_id); /* Check to see if all of the screens are done with this font * and free the private when that happens */ for (s = 0; s < glamor_font_screen_count; s++) if (privates[s].realized) return TRUE; free(privates); FontSetPrivate(font, glamor_font_private_index, NULL); return TRUE; }
Bool xnestRealizeFont(ScreenPtr pScreen, FontPtr pFont) { pointer priv; Atom name_atom, value_atom; int nprops; FontPropPtr props; int i; char *name; FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); if (requestingClient && XpClientIsPrintClient(requestingClient, NULL)) return True; name_atom = MakeAtom("FONT", 4, True); value_atom = 0L; nprops = pFont->info.nprops; props = pFont->info.props; for (i = 0; i < nprops; i++) if (props[i].name == name_atom) { value_atom = props[i].value; break; } if (!value_atom) return False; name = (char *)NameForAtom(value_atom); if (!name) return False; priv = (pointer)xalloc(sizeof(xnestPrivFont)); FontSetPrivate(pFont, xnestFontPrivateIndex, priv); xnestFontPriv(pFont)->font_struct = XLoadQueryFont(xnestDisplay, name); if (!xnestFontStruct(pFont)) return False; return True; }
Bool xnestUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) { if (xnestFontPriv(pFont)) { if (xnestFontStruct(pFont)) XFreeFont(xnestDisplay, xnestFontStruct(pFont)); xfree(xnestFontPriv(pFont)); FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); } return True; }
/** Unrealize the font, \a pFont, on the back-end server associated with * \a pScreen. */ Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; dmxFontPrivPtr pFontPriv; if ((pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { /* In case the font failed to load properly */ if (!pFontPriv->refcnt) { MAXSCREENSFREE(pFontPriv->font); free(pFontPriv); FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); } else if (pFontPriv->font[pScreen->myNum]) { if (dmxScreen->beDisplay) dmxBEFreeFont(pScreen, pFont); /* The code below is non-obvious, so here's an explanation... * * When creating the default GC, the server opens up the * default font once for each screen, which in turn calls * the RealizeFont function pointer once for each screen. * During this process both dix's font refcnt and DMX's font * refcnt are incremented once for each screen. * * Later, when shutting down the X server, dix shuts down * each screen in reverse order. During this shutdown * procedure, each screen's default GC is freed and then * that screen is closed by calling the CloseScreen function * pointer. screenInfo.numScreens is then decremented after * closing each screen. This procedure means that the dix's * font refcnt for the font used by the default GC's is * decremented once for each screen # greater than 0. * However, since dix's refcnt for the default font is not * yet 0 for each screen greater than 0, no call to the * UnrealizeFont function pointer is made for those screens. * Then, when screen 0 is being closed, dix's font refcnt * for the default GC's font is finally 0 and the font is * unrealized. However, since screenInfo.numScreens has * been decremented already down to 1, only one call to * UnrealizeFont is made (for screen 0). Thus, even though * RealizeFont was called once for each screen, * UnrealizeFont is only called for screen 0. * * This is a bug in dix. * * To avoid the memory leak of pFontPriv for each server * generation, we can also free pFontPriv if the refcnt is * not yet 0 but the # of screens is 1 -- i.e., the case * described in the dix bug above. This is only a temporary * workaround until the bug in dix is solved. * * The other problem is that the font structure allocated by * XLoadQueryFont() above is not freed for screens > 0. * This problem cannot be worked around here since the back- * end displays for screens > 0 have already been closed by * the time this code is called from dix. * * When the bug in dix described above is fixed, then we can * remove the "|| screenInfo.numScreens == 1" code below and * the memory leaks will be eliminated. */ if (--pFontPriv->refcnt == 0 #if 1 /* Remove this code when the dix bug is fixed */ || screenInfo.numScreens == 1 #endif ) { MAXSCREENSFREE(pFontPriv->font); free(pFontPriv); FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); } } } return TRUE; }
static int ProcXF86BigfontQueryFont( ClientPtr client) { FontPtr pFont; REQUEST(xXF86BigfontQueryFontReq); CARD32 stuff_flags; xCharInfo* pmax; xCharInfo* pmin; int nCharInfos; int shmid; #ifdef HAS_SHM ShmDescPtr pDesc; #else #define pDesc 0 #endif xCharInfo* pCI; CARD16* pIndex2UniqIndex; CARD16* pUniqIndex2Index; CARD32 nUniqCharInfos; #if 0 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); #else switch (client->req_len) { case 2: /* client with version 1.0 libX11 */ stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); break; case 3: /* client with version 1.1 libX11 */ stuff_flags = stuff->flags; break; default: return BadLength; } #endif client->errorValue = stuff->id; /* EITHER font or gc */ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, SecurityReadAccess); if (!pFont) { /* can't use VERIFY_GC because it might return BadGC */ GC *pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, SecurityReadAccess); if (!pGC) { client->errorValue = stuff->id; return BadFont; /* procotol spec says only error is BadFont */ } pFont = pGC->font; } pmax = FONTINKMAX(pFont); pmin = FONTINKMIN(pFont); nCharInfos = (pmax->rightSideBearing == pmin->rightSideBearing && pmax->leftSideBearing == pmin->leftSideBearing && pmax->descent == pmin->descent && pmax->ascent == pmin->ascent && pmax->characterWidth == pmin->characterWidth) ? 0 : N2dChars(pFont); shmid = -1; pCI = NULL; pIndex2UniqIndex = NULL; pUniqIndex2Index = NULL; nUniqCharInfos = 0; if (nCharInfos > 0) { #ifdef HAS_SHM pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); if (pDesc) { pCI = (xCharInfo *) pDesc->attach_addr; if (stuff_flags & XF86Bigfont_FLAGS_Shm) shmid = pDesc->shmid; } else { if (stuff_flags & XF86Bigfont_FLAGS_Shm) pDesc = shmalloc(nCharInfos * sizeof(xCharInfo) + sizeof(CARD32)); if (pDesc) { pCI = (xCharInfo *) pDesc->attach_addr; shmid = pDesc->shmid; } else { #endif pCI = (xCharInfo *) ALLOCATE_LOCAL(nCharInfos * sizeof(xCharInfo)); if (!pCI) return BadAlloc; #ifdef HAS_SHM } #endif /* Fill nCharInfos starting at pCI. */ { xCharInfo* prCI = pCI; int ninfos = 0; int ncols = pFont->info.lastCol - pFont->info.firstCol + 1; int row; for (row = pFont->info.firstRow; row <= pFont->info.lastRow && ninfos < nCharInfos; row++) { unsigned char chars[512]; xCharInfo* tmpCharInfos[256]; unsigned long count; int col; unsigned long i; i = 0; for (col = pFont->info.firstCol; col <= pFont->info.lastCol; col++) { chars[i++] = row; chars[i++] = col; } (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, &count, tmpCharInfos); for (i = 0; i < count && ninfos < nCharInfos; i++) { *prCI++ = *tmpCharInfos[i]; ninfos++; } } } #ifdef HAS_SHM if (pDesc) { *(CARD32 *)(pCI + nCharInfos) = signature; if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) { shmdealloc(pDesc); return BadAlloc; } } } #endif if (shmid == -1) { /* Cannot use shared memory, so remove-duplicates the xCharInfos using a temporary hash table. */ /* Note that CARD16 is suitable as index type, because nCharInfos <= 0x10000. */ CARD32 hashModulus; CARD16* pHash2UniqIndex; CARD16* pUniqIndex2NextUniqIndex; CARD32 NextIndex; CARD32 NextUniqIndex; CARD16* tmp; CARD32 i, j; hashModulus = 67; if (hashModulus > nCharInfos+1) hashModulus = nCharInfos+1; tmp = (CARD16*) ALLOCATE_LOCAL((4*nCharInfos+1) * sizeof(CARD16)); if (!tmp) { if (!pDesc) DEALLOCATE_LOCAL(pCI); return BadAlloc; } pIndex2UniqIndex = tmp; /* nCharInfos elements */ pUniqIndex2Index = tmp + nCharInfos; /* max. nCharInfos elements */ pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos; /* max. nCharInfos elements */ pHash2UniqIndex = tmp + 3*nCharInfos; /* hashModulus (<= nCharInfos+1) elements */ /* Note that we can use 0xffff as end-of-list indicator, because even if nCharInfos = 0x10000, 0xffff can not occur as valid entry before the last element has been inserted. And once the last element has been inserted, we don't need the hash table any more. */ for (j = 0; j < hashModulus; j++) pHash2UniqIndex[j] = (CARD16)(-1); NextUniqIndex = 0; for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) { xCharInfo* p = &pCI[NextIndex]; CARD32 hashCode = hashCI(p) % hashModulus; for (i = pHash2UniqIndex[hashCode]; i != (CARD16)(-1); i = pUniqIndex2NextUniqIndex[i]) { j = pUniqIndex2Index[i]; if (pCI[j].leftSideBearing == p->leftSideBearing && pCI[j].rightSideBearing == p->rightSideBearing && pCI[j].characterWidth == p->characterWidth && pCI[j].ascent == p->ascent && pCI[j].descent == p->descent && pCI[j].attributes == p->attributes) break; } if (i != (CARD16)(-1)) { /* Found *p at Index j, UniqIndex i */ pIndex2UniqIndex[NextIndex] = i; } else { /* Allocate a new entry in the Uniq table */ if (hashModulus <= 2*NextUniqIndex && hashModulus < nCharInfos+1) { /* Time to increate hash table size */ hashModulus = 2*hashModulus+1; if (hashModulus > nCharInfos+1) hashModulus = nCharInfos+1; for (j = 0; j < hashModulus; j++) pHash2UniqIndex[j] = (CARD16)(-1); for (i = 0; i < NextUniqIndex; i++) pUniqIndex2NextUniqIndex[i] = (CARD16)(-1); for (i = 0; i < NextUniqIndex; i++) { j = pUniqIndex2Index[i]; p = &pCI[j]; hashCode = hashCI(p) % hashModulus; pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; pHash2UniqIndex[hashCode] = i; } p = &pCI[NextIndex]; hashCode = hashCI(p) % hashModulus; } i = NextUniqIndex++; pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; pHash2UniqIndex[hashCode] = i; pUniqIndex2Index[i] = NextIndex; pIndex2UniqIndex[NextIndex] = i; } } nUniqCharInfos = NextUniqIndex; /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */ } } { int nfontprops = pFont->info.nprops; int rlength = sizeof(xXF86BigfontQueryFontReply) + nfontprops * sizeof(xFontProp) + (nCharInfos > 0 && shmid == -1 ? nUniqCharInfos * sizeof(xCharInfo) + (nCharInfos+1)/2 * 2 * sizeof(CARD16) : 0); xXF86BigfontQueryFontReply* reply = (xXF86BigfontQueryFontReply *) ALLOCATE_LOCAL(rlength); char* p; if (!reply) { if (nCharInfos > 0) { if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex); if (!pDesc) DEALLOCATE_LOCAL(pCI); } return BadAlloc; } reply->type = X_Reply; reply->length = (rlength - sizeof(xGenericReply)) >> 2; reply->sequenceNumber = client->sequence; reply->minBounds = pFont->info.ink_minbounds; reply->maxBounds = pFont->info.ink_maxbounds; reply->minCharOrByte2 = pFont->info.firstCol; reply->maxCharOrByte2 = pFont->info.lastCol; reply->defaultChar = pFont->info.defaultCh; reply->nFontProps = pFont->info.nprops; reply->drawDirection = pFont->info.drawDirection; reply->minByte1 = pFont->info.firstRow; reply->maxByte1 = pFont->info.lastRow; reply->allCharsExist = pFont->info.allExist; reply->fontAscent = pFont->info.fontAscent; reply->fontDescent = pFont->info.fontDescent; reply->nCharInfos = nCharInfos; reply->nUniqCharInfos = nUniqCharInfos; reply->shmid = shmid; reply->shmsegoffset = 0; if (client->swapped) { char tmp; swaps(&reply->sequenceNumber, tmp); swapl(&reply->length, tmp); swapCharInfo(&reply->minBounds); swapCharInfo(&reply->maxBounds); swaps(&reply->minCharOrByte2, tmp); swaps(&reply->maxCharOrByte2, tmp); swaps(&reply->defaultChar, tmp); swaps(&reply->nFontProps, tmp); swaps(&reply->fontAscent, tmp); swaps(&reply->fontDescent, tmp); swapl(&reply->nCharInfos, tmp); swapl(&reply->nUniqCharInfos, tmp); swapl(&reply->shmid, tmp); swapl(&reply->shmsegoffset, tmp); } p = (char*) &reply[1]; { FontPropPtr pFP; xFontProp* prFP; int i; for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p; i < nfontprops; i++, pFP++, prFP++) { prFP->name = pFP->name; prFP->value = pFP->value; if (client->swapped) { char tmp; swapl(&prFP->name, tmp); swapl(&prFP->value, tmp); } } p = (char*) prFP; } if (nCharInfos > 0 && shmid == -1) { xCharInfo* pci; CARD16* ps; int i, j; pci = (xCharInfo*) p; for (i = 0; i < nUniqCharInfos; i++, pci++) { *pci = pCI[pUniqIndex2Index[i]]; if (client->swapped) swapCharInfo(pci); } ps = (CARD16*) pci; for (j = 0; j < nCharInfos; j++, ps++) { *ps = pIndex2UniqIndex[j]; if (client->swapped) { char tmp; swaps(ps, tmp); } } } WriteToClient(client, rlength, (char *)reply); DEALLOCATE_LOCAL(reply); if (nCharInfos > 0) { if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex); if (!pDesc) DEALLOCATE_LOCAL(pCI); } return (client->noClientException); } }
glamor_font_t * glamor_font_get(ScreenPtr screen, FontPtr font) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_font_t *privates; glamor_font_t *glamor_font; int overall_width, overall_height; int num_rows; int num_cols; int glyph_width_pixels; int glyph_width_bytes; int glyph_height; int row, col; unsigned char c[2]; CharInfoPtr glyph; unsigned long count; privates = FontGetPrivate(font, glamor_font_private_index); if (!privates) { privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t)); if (!privates) return NULL; FontSetPrivate(font, glamor_font_private_index, privates); } glamor_font = &privates[screen->myNum]; if (glamor_font->realized) return glamor_font; glamor_font->realized = TRUE; /* Figure out how many glyphs are in the font */ num_cols = font->info.lastCol - font->info.firstCol + 1; num_rows = font->info.lastRow - font->info.firstRow + 1; /* Figure out the size of each glyph */ glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing; glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent; glyph_width_bytes = (glyph_width_pixels + 7) >> 3; glamor_font->glyph_width_pixels = glyph_width_pixels; glamor_font->glyph_width_bytes = glyph_width_bytes; glamor_font->glyph_height = glyph_height; overall_width = glyph_width_bytes * num_cols; overall_height = glyph_height * num_rows; /* Check whether the font has a default character */ c[0] = font->info.lastRow + 1; c[1] = font->info.lastCol + 1; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); glamor_font->default_char = count ? glyph : NULL; glamor_font->default_row = font->info.defaultCh >> 8; glamor_font->default_col = font->info.defaultCh; glamor_priv = glamor_get_screen_private(screen); glamor_make_current(glamor_priv); glGenTextures(1, &glamor_font->texture_id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Allocate storage */ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* Paint all of the glyphs */ for (row = 0; row < num_rows; row++) { for (col = 0; col < num_cols; col++) { c[0] = row + font->info.firstRow; c[1] = col + font->info.firstCol; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); if (count) glTexSubImage2D(GL_TEXTURE_2D, 0, col * glyph_width_bytes, row * glyph_height, GLYPHWIDTHBYTES(glyph), GLYPHHEIGHTPIXELS(glyph), GL_RED_INTEGER, GL_UNSIGNED_BYTE, glyph->bits); } } return glamor_font; }
glamor_font_t * glamor_font_get(ScreenPtr screen, FontPtr font) { glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_font_t *privates; glamor_font_t *glamor_font; int overall_width, overall_height; int num_rows; int num_cols; int glyph_width_pixels; int glyph_width_bytes; int glyph_height; int row, col; unsigned char c[2]; CharInfoPtr glyph; unsigned long count; char *bits; if (glamor_priv->glsl_version < 130) return NULL; privates = FontGetPrivate(font, glamor_font_private_index); if (!privates) { privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t)); if (!privates) return NULL; FontSetPrivate(font, glamor_font_private_index, privates); } glamor_font = &privates[screen->myNum]; if (glamor_font->realized) return glamor_font; /* Figure out how many glyphs are in the font */ num_cols = font->info.lastCol - font->info.firstCol + 1; num_rows = font->info.lastRow - font->info.firstRow + 1; /* Figure out the size of each glyph */ glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing; glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent; glyph_width_bytes = (glyph_width_pixels + 7) >> 3; glamor_font->glyph_width_pixels = glyph_width_pixels; glamor_font->glyph_width_bytes = glyph_width_bytes; glamor_font->glyph_height = glyph_height; /* * Layout the font two blocks of columns wide. * This avoids a problem with some fonts that are too high to fit. */ glamor_font->row_width = glyph_width_bytes * num_cols; if (num_rows > 1) { overall_width = glamor_font->row_width * 2; overall_height = glyph_height * ((num_rows + 1) / 2); } else { overall_width = glamor_font->row_width; overall_height = glyph_height; } if (overall_width > glamor_priv->max_fbo_size || overall_height > glamor_priv->max_fbo_size) { /* fallback if we don't fit inside a texture */ return NULL; } bits = malloc(overall_width * overall_height); if (!bits) return NULL; /* Check whether the font has a default character */ c[0] = font->info.lastRow + 1; c[1] = font->info.lastCol + 1; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); glamor_font->default_char = count ? glyph : NULL; glamor_font->default_row = font->info.defaultCh >> 8; glamor_font->default_col = font->info.defaultCh; glamor_priv = glamor_get_screen_private(screen); glamor_make_current(glamor_priv); glGenTextures(1, &glamor_font->texture_id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Paint all of the glyphs */ for (row = 0; row < num_rows; row++) { for (col = 0; col < num_cols; col++) { c[0] = row + font->info.firstRow; c[1] = col + font->info.firstCol; (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph); if (count) { char *dst; char *src = glyph->bits; unsigned y; dst = bits; /* get offset of start of first row */ dst += (row / 2) * glyph_height * overall_width; /* add offset into second row */ dst += (row & 1) ? glamor_font->row_width : 0; dst += col * glyph_width_bytes; for (y = 0; y < GLYPHHEIGHTPIXELS(glyph); y++) { memcpy(dst, src, GLYPHWIDTHBYTES(glyph)); dst += overall_width; src += GLYPHWIDTHBYTESPADDED(glyph); } } } } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glamor_priv->suppress_gl_out_of_memory_logging = true; glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits); glamor_priv->suppress_gl_out_of_memory_logging = false; if (glGetError() == GL_OUT_OF_MEMORY) return NULL; free(bits); glamor_font->realized = TRUE; return glamor_font; }