xenocara/xserver/glamor/glamor_font.c

185 lines
6.2 KiB
C
Raw Normal View History

/*
* Copyright © 2014 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "glamor_priv.h"
#include "glamor_font.h"
#include <dixfontstr.h>
static int glamor_font_generation;
static int glamor_font_private_index;
static int glamor_font_screen_count;
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_MAX_LEVEL, 0);
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;
}
static Bool
glamor_realize_font(ScreenPtr screen, FontPtr font)
{
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
glamor_font_init(ScreenPtr screen)
{
if (glamor_font_generation != serverGeneration) {
glamor_font_private_index = AllocateFontPrivateIndex();
if (glamor_font_private_index == -1)
return FALSE;
glamor_font_screen_count = 0;
glamor_font_generation = serverGeneration;
}
if (screen->myNum >= glamor_font_screen_count)
glamor_font_screen_count = screen->myNum + 1;
screen->RealizeFont = glamor_realize_font;
screen->UnrealizeFont = glamor_unrealize_font;
return TRUE;
}