Path: blob/21.2-virgl/src/gallium/frontends/glx/xlib/glx_usefont.c
4561 views
/*1* Mesa 3-D graphics library2*3* Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de4* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.5* Copyright (C) 2009 VMware, Inc. All Rights Reserved.6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice shall be included15* in all copies or substantial portions of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL20* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR21* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,22* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR23* OTHER DEALINGS IN THE SOFTWARE.24*/252627/**28* Fake implementation of glXUseXFont().29*/3031#include <stdlib.h>32#include <string.h>33#include <stdio.h>34#include <GL/glx.h>35#include "main/errors.h"363738/* Some debugging info. */3940#ifdef DEBUG41#include <ctype.h>4243int debug_xfonts = 0;4445static void46dump_char_struct(XCharStruct * ch, char *prefix)47{48printf("%slbearing = %d, rbearing = %d, width = %d\n",49prefix, ch->lbearing, ch->rbearing, ch->width);50printf("%sascent = %d, descent = %d, attributes = %u\n",51prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);52}5354static void55dump_font_struct(XFontStruct * font)56{57printf("ascent = %d, descent = %d\n", font->ascent, font->descent);58printf("char_or_byte2 = (%u,%u)\n",59font->min_char_or_byte2, font->max_char_or_byte2);60printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);61printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");62printf("default_char = %c (\\%03o)\n",63(char) (isprint(font->default_char) ? font->default_char : ' '),64font->default_char);65dump_char_struct(&font->min_bounds, "min> ");66dump_char_struct(&font->max_bounds, "max> ");67#if 068for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {69char prefix[8];70sprintf(prefix, "%d> ", c);71dump_char_struct(&font->per_char[c], prefix);72}73#endif74}7576static void77dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)78{79unsigned int x, y;8081printf(" ");82for (x = 0; x < 8 * width; x++)83printf("%o", 7 - (x % 8));84putchar('\n');85for (y = 0; y < height; y++) {86printf("%3o:", y);87for (x = 0; x < 8 * width; x++)88putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %898))))90? '*' : '.');91printf(" ");92for (x = 0; x < width; x++)93printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);94putchar('\n');95}96}97#endif /* DEBUG */9899100/* Implementation. */101102/* Fill a BITMAP with a character C from thew current font103in the graphics context GC. WIDTH is the width in bytes104and HEIGHT is the height in bits.105106Note that the generated bitmaps must be used with107108glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);109glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);110glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);111glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);112glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);113glPixelStorei (GL_UNPACK_ALIGNMENT, 1);114115Possible optimizations:116117* use only one reusable pixmap with the maximum dimensions.118* draw the entire font into a single pixmap (careful with119proportional fonts!).120*/121122123/*124* Generate OpenGL-compatible bitmap.125*/126static void127fill_bitmap(Display * dpy, Window win, GC gc,128unsigned int width, unsigned int height,129int x0, int y0, unsigned int c, GLubyte * bitmap)130{131XImage *image;132unsigned int x, y;133Pixmap pixmap;134XChar2b char2b;135136pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);137XSetForeground(dpy, gc, 0);138XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);139XSetForeground(dpy, gc, 1);140141char2b.byte1 = (c >> 8) & 0xff;142char2b.byte2 = (c & 0xff);143144XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);145146image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);147if (image) {148/* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */149for (y = 0; y < height; y++)150for (x = 0; x < 8 * width; x++)151if (XGetPixel(image, x, y))152bitmap[width * (height - y - 1) + x / 8] |=153(1 << (7 - (x % 8)));154XDestroyImage(image);155}156157XFreePixmap(dpy, pixmap);158}159160/*161* determine if a given glyph is valid and return the162* corresponding XCharStruct.163*/164static XCharStruct *165isvalid(XFontStruct * fs, unsigned int which)166{167unsigned int rows, pages;168unsigned int byte1 = 0, byte2 = 0;169int i, valid = 1;170171rows = fs->max_byte1 - fs->min_byte1 + 1;172pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;173174if (rows == 1) {175/* "linear" fonts */176if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))177valid = 0;178}179else {180/* "matrix" fonts */181byte2 = which & 0xff;182byte1 = which >> 8;183if ((fs->min_char_or_byte2 > byte2) ||184(fs->max_char_or_byte2 < byte2) ||185(fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))186valid = 0;187}188189if (valid) {190if (fs->per_char) {191if (rows == 1) {192/* "linear" fonts */193return (fs->per_char + (which - fs->min_char_or_byte2));194}195else {196/* "matrix" fonts */197i = ((byte1 - fs->min_byte1) * pages) +198(byte2 - fs->min_char_or_byte2);199return (fs->per_char + i);200}201}202else {203return (&fs->min_bounds);204}205}206return (NULL);207}208209210PUBLIC void211glXUseXFont(Font font, int first, int count, int listbase)212{213Display *dpy;214Window win;215Pixmap pixmap;216GC gc;217XGCValues values;218unsigned long valuemask;219XFontStruct *fs;220GLint swapbytes, lsbfirst, rowlength;221GLint skiprows, skippixels, alignment;222unsigned int max_width, max_height, max_bm_width, max_bm_height;223GLubyte *bm;224int i;225226dpy = glXGetCurrentDisplay();227if (!dpy)228return; /* I guess glXMakeCurrent wasn't called */229i = DefaultScreen(dpy);230win = RootWindow(dpy, i);231232fs = XQueryFont(dpy, font);233if (!fs) {234_mesa_error(NULL, GL_INVALID_VALUE,235"Couldn't get font structure information");236return;237}238239/* Allocate a bitmap that can fit all characters. */240max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;241max_height = fs->max_bounds.ascent + fs->max_bounds.descent;242max_bm_width = (max_width + 7) / 8;243max_bm_height = max_height;244245bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte));246if (!bm) {247XFreeFontInfo(NULL, fs, 1);248_mesa_error(NULL, GL_OUT_OF_MEMORY,249"Couldn't allocate bitmap in glXUseXFont()");250return;251}252253#if 0254/* get the page info */255pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;256firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;257lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;258rows = fs->max_byte1 - fs->min_byte1 + 1;259unsigned int first_char, last_char, pages, rows;260#endif261262/* Save the current packing mode for bitmaps. */263glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);264glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);265glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);266glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);267glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);268glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);269270/* Enforce a standard packing mode which is compatible with271fill_bitmap() from above. This is actually the default mode,272except for the (non)alignment. */273glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);274glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);275glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);276glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);277glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);278glPixelStorei(GL_UNPACK_ALIGNMENT, 1);279280pixmap = XCreatePixmap(dpy, win, 10, 10, 1);281values.foreground = BlackPixel(dpy, DefaultScreen(dpy));282values.background = WhitePixel(dpy, DefaultScreen(dpy));283values.font = fs->fid;284valuemask = GCForeground | GCBackground | GCFont;285gc = XCreateGC(dpy, pixmap, valuemask, &values);286XFreePixmap(dpy, pixmap);287288#ifdef DEBUG289if (debug_xfonts)290dump_font_struct(fs);291#endif292293for (i = 0; i < count; i++) {294unsigned int width, height, bm_width, bm_height;295GLfloat x0, y0, dx, dy;296XCharStruct *ch;297int x, y;298unsigned int c = first + i;299int list = listbase + i;300int valid;301302/* check on index validity and get the bounds */303ch = isvalid(fs, c);304if (!ch) {305ch = &fs->max_bounds;306valid = 0;307}308else {309valid = 1;310}311312#ifdef DEBUG313if (debug_xfonts) {314char s[7];315sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);316dump_char_struct(ch, s);317}318#endif319320/* glBitmap()' parameters:321straight from the glXUseXFont(3) manpage. */322width = ch->rbearing - ch->lbearing;323height = ch->ascent + ch->descent;324x0 = -ch->lbearing;325y0 = ch->descent - 0; /* XXX used to subtract 1 here */326/* but that caused a conformace failure */327dx = ch->width;328dy = 0;329330/* X11's starting point. */331x = -ch->lbearing;332y = ch->ascent;333334/* Round the width to a multiple of eight. We will use this also335for the pixmap for capturing the X11 font. This is slightly336inefficient, but it makes the OpenGL part real easy. */337bm_width = (width + 7) / 8;338bm_height = height;339340glNewList(list, GL_COMPILE);341if (valid && (bm_width > 0) && (bm_height > 0)) {342343memset(bm, '\0', bm_width * bm_height);344fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);345346glBitmap(width, height, x0, y0, dx, dy, bm);347#ifdef DEBUG348if (debug_xfonts) {349printf("width/height = %u/%u\n", width, height);350printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);351dump_bitmap(bm_width, bm_height, bm);352}353#endif354}355else {356glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);357}358glEndList();359}360361free(bm);362XFreeFontInfo(NULL, fs, 1);363XFreeGC(dpy, gc);364365/* Restore saved packing modes. */366glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);367glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);368glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);369glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);370glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);371glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);372}373374375