+ if(Cmd_Argc() < 3)
+ filelist = "gfx/conchars";
+ else
+ filelist = Cmd_Argv(2);
+
+ memset(f->fallbacks, 0, sizeof(f->fallbacks));
+ memset(f->fallback_faces, 0, sizeof(f->fallback_faces));
+
+ // first font is handled "normally"
+ c = strchr(filelist, ':');
+ cm = strchr(filelist, ',');
+ if(c && (!cm || c < cm))
+ f->req_face = atoi(c+1);
+ else
+ {
+ f->req_face = 0;
+ c = cm;
+ }
+
+ if(!c || (c - filelist) > MAX_QPATH)
+ strlcpy(mainfont, filelist, sizeof(mainfont));
+ else
+ {
+ memcpy(mainfont, filelist, c - filelist);
+ mainfont[c - filelist] = 0;
+ }
+
+ for(i = 0; i < MAX_FONT_FALLBACKS; ++i)
+ {
+ c = strchr(filelist, ',');
+ if(!c)
+ break;
+ filelist = c + 1;
+ if(!*filelist)
+ break;
+ c = strchr(filelist, ':');
+ cm = strchr(filelist, ',');
+ if(c && (!cm || c < cm))
+ f->fallback_faces[i] = atoi(c+1);
+ else
+ {
+ f->fallback_faces[i] = 0; // f->req_face; could make it stick to the default-font's face index
+ c = cm;
+ }
+ if(!c || (c-filelist) > MAX_QPATH)
+ {
+ strlcpy(f->fallbacks[i], filelist, sizeof(mainfont));
+ }
+ else
+ {
+ memcpy(f->fallbacks[i], filelist, c - filelist);
+ f->fallbacks[i][c - filelist] = 0;
+ }
+ }
+
+ // for now: by default load only one size: the default size
+ f->req_sizes[0] = 0;
+ for(i = 1; i < MAX_FONT_SIZES; ++i)
+ f->req_sizes[i] = -1;
+
+ scale = 1;
+ voffset = 0;
+ if(Cmd_Argc() >= 4)
+ {
+ for(sizes = 0, i = 3; i < Cmd_Argc(); ++i)
+ {
+ // special switches
+ if (!strcmp(Cmd_Argv(i), "scale"))
+ {
+ i++;
+ if (i < Cmd_Argc())
+ scale = atof(Cmd_Argv(i));
+ continue;
+ }
+ if (!strcmp(Cmd_Argv(i), "voffset"))
+ {
+ i++;
+ if (i < Cmd_Argc())
+ voffset = atof(Cmd_Argv(i));
+ continue;
+ }
+
+ if (sizes == -1)
+ continue; // no slot for other sizes
+
+ // parse one of sizes
+ sz = atof(Cmd_Argv(i));
+ if (sz > 0.001f && sz < 1000.0f) // do not use crap sizes
+ {
+ // search for duplicated sizes
+ int j;
+ for (j=0; j<sizes; j++)
+ if (f->req_sizes[j] == sz)
+ break;
+ if (j != sizes)
+ continue; // sz already in req_sizes, don't add it again
+
+ if (sizes == MAX_FONT_SIZES)
+ {
+ Con_Printf("Warning: specified more than %i different font sizes, exceding ones are ignored\n", MAX_FONT_SIZES);
+ sizes = -1;
+ continue;
+ }
+ f->req_sizes[sizes] = sz;
+ sizes++;
+ }
+ }
+ }
+
+ LoadFont(true, mainfont, f, scale, voffset);
+}
+
+/*
+===============
+Draw_Init
+===============
+*/
+static void gl_draw_start(void)
+{
+ int i;
+ char vabuf[1024];
+ drawtexturepool = R_AllocTexturePool();
+
+ numcachepics = 0;
+ memset(cachepichash, 0, sizeof(cachepichash));
+
+ font_start();
+
+ // load default font textures
+ for(i = 0; i < dp_fonts.maxsize; ++i)
+ if (dp_fonts.f[i].title[0])
+ LoadFont(false, va(vabuf, sizeof(vabuf), "gfx/font_%s", dp_fonts.f[i].title), &dp_fonts.f[i], 1, 0);
+
+ // draw the loading screen so people have something to see in the newly opened window
+ SCR_UpdateLoadingScreen(true, true);
+}
+
+static void gl_draw_shutdown(void)
+{
+ font_shutdown();
+
+ R_FreeTexturePool(&drawtexturepool);
+
+ numcachepics = 0;
+ memset(cachepichash, 0, sizeof(cachepichash));
+}
+
+static void gl_draw_newmap(void)
+{
+ font_newmap();
+}
+
+void GL_Draw_Init (void)
+{
+ int i, j;
+
+ Cvar_RegisterVariable(&r_font_postprocess_blur);
+ Cvar_RegisterVariable(&r_font_postprocess_outline);
+ Cvar_RegisterVariable(&r_font_postprocess_shadow_x);
+ Cvar_RegisterVariable(&r_font_postprocess_shadow_y);
+ Cvar_RegisterVariable(&r_font_postprocess_shadow_z);
+ Cvar_RegisterVariable(&r_font_hinting);
+ Cvar_RegisterVariable(&r_font_antialias);
+ Cvar_RegisterVariable(&r_textshadow);
+ Cvar_RegisterVariable(&r_textbrightness);
+ Cvar_RegisterVariable(&r_textcontrast);
+ Cvar_RegisterVariable(&r_nearest_2d);
+ Cvar_RegisterVariable(&r_nearest_conchars);
+
+ // allocate fonts storage
+ fonts_mempool = Mem_AllocPool("FONTS", 0, NULL);
+ dp_fonts.maxsize = MAX_FONTS;
+ dp_fonts.f = (dp_font_t *)Mem_Alloc(fonts_mempool, sizeof(dp_font_t) * dp_fonts.maxsize);
+ memset(dp_fonts.f, 0, sizeof(dp_font_t) * dp_fonts.maxsize);
+
+ // assign starting font names
+ strlcpy(FONT_DEFAULT->title, "default", sizeof(FONT_DEFAULT->title));
+ strlcpy(FONT_DEFAULT->texpath, "gfx/conchars", sizeof(FONT_DEFAULT->texpath));
+ strlcpy(FONT_CONSOLE->title, "console", sizeof(FONT_CONSOLE->title));
+ strlcpy(FONT_SBAR->title, "sbar", sizeof(FONT_SBAR->title));
+ strlcpy(FONT_NOTIFY->title, "notify", sizeof(FONT_NOTIFY->title));
+ strlcpy(FONT_CHAT->title, "chat", sizeof(FONT_CHAT->title));
+ strlcpy(FONT_CENTERPRINT->title, "centerprint", sizeof(FONT_CENTERPRINT->title));
+ strlcpy(FONT_INFOBAR->title, "infobar", sizeof(FONT_INFOBAR->title));
+ strlcpy(FONT_MENU->title, "menu", sizeof(FONT_MENU->title));
+ for(i = 0, j = 0; i < MAX_USERFONTS; ++i)
+ if(!FONT_USER(i)->title[0])
+ dpsnprintf(FONT_USER(i)->title, sizeof(FONT_USER(i)->title), "user%d", j++);
+
+ Cmd_AddCommand ("loadfont",LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions");
+ R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL);
+}
+
+static void _DrawQ_Setup(void) // see R_ResetViewRendering2D
+{
+ if (r_refdef.draw2dstage == 1)
+ return;
+ r_refdef.draw2dstage = 1;
+
+ R_ResetViewRendering2D_Common(0, NULL, NULL, vid_conwidth.integer, vid_conheight.integer);
+}
+
+qboolean r_draw2d_force = false;
+static void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha)
+{
+ _DrawQ_Setup();
+ if(!r_draw2d.integer && !r_draw2d_force)
+ return;
+ DrawQ_ProcessDrawFlag(flags, (alpha < 1) || (pic && pic->hasalpha));
+}
+void DrawQ_ProcessDrawFlag(int flags, qboolean alpha)
+{
+ if(flags == DRAWFLAG_ADDITIVE)
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(alpha ? GL_SRC_ALPHA : GL_ONE, GL_ONE);
+ }
+ else if(flags == DRAWFLAG_MODULATE)
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+ }
+ else if(flags == DRAWFLAG_2XMODULATE)
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ }
+ else if(flags == DRAWFLAG_SCREEN)
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE);
+ }
+ else if(alpha)
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else
+ {
+ GL_DepthMask(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ }
+}
+
+void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
+{
+ float floats[36];
+
+ _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha);
+ if(!r_draw2d.integer && !r_draw2d_force)
+ return;
+
+// R_Mesh_ResetTextureState();
+ floats[12] = 0.0f;floats[13] = 0.0f;
+ floats[14] = 1.0f;floats[15] = 0.0f;
+ floats[16] = 1.0f;floats[17] = 1.0f;
+ floats[18] = 0.0f;floats[19] = 1.0f;
+ floats[20] = floats[24] = floats[28] = floats[32] = red;
+ floats[21] = floats[25] = floats[29] = floats[33] = green;
+ floats[22] = floats[26] = floats[30] = floats[34] = blue;
+ floats[23] = floats[27] = floats[31] = floats[35] = alpha;
+ if (pic)
+ {
+ if (width == 0)
+ width = pic->width;
+ if (height == 0)
+ height = pic->height;
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
+
+#if 0
+ // AK07: lets be texel correct on the corners
+ {
+ float horz_offset = 0.5f / pic->width;
+ float vert_offset = 0.5f / pic->height;
+
+ floats[12] = 0.0f + horz_offset;floats[13] = 0.0f + vert_offset;
+ floats[14] = 1.0f - horz_offset;floats[15] = 0.0f + vert_offset;
+ floats[16] = 1.0f - horz_offset;floats[17] = 1.0f - vert_offset;
+ floats[18] = 0.0f + horz_offset;floats[19] = 1.0f - vert_offset;
+ }
+#endif
+ }
+ else
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
+
+ floats[2] = floats[5] = floats[8] = floats[11] = 0;
+ floats[0] = floats[9] = x;
+ floats[1] = floats[4] = y;
+ floats[3] = floats[6] = x + width;
+ floats[7] = floats[10] = y + height;
+
+ R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+}
+
+void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, float org_x, float org_y, float angle, float red, float green, float blue, float alpha, int flags)
+{
+ float floats[36];
+ float af = DEG2RAD(-angle); // forward
+ float ar = DEG2RAD(-angle + 90); // right
+ float sinaf = sin(af);
+ float cosaf = cos(af);
+ float sinar = sin(ar);
+ float cosar = cos(ar);
+
+ _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha);
+ if(!r_draw2d.integer && !r_draw2d_force)
+ return;
+
+// R_Mesh_ResetTextureState();
+ if (pic)
+ {
+ if (width == 0)
+ width = pic->width;
+ if (height == 0)
+ height = pic->height;
+ R_SetupShader_Generic(Draw_GetPicTexture(pic), NULL, GL_MODULATE, 1, (flags & DRAWFLAGS_BLEND) ? false : true, true, false);
+ }
+ else
+ R_SetupShader_Generic_NoTexture((flags & DRAWFLAGS_BLEND) ? false : true, true);
+
+ floats[2] = floats[5] = floats[8] = floats[11] = 0;
+
+// top left
+ floats[0] = x - cosaf*org_x - cosar*org_y;
+ floats[1] = y - sinaf*org_x - sinar*org_y;
+
+// top right
+ floats[3] = x + cosaf*(width-org_x) - cosar*org_y;
+ floats[4] = y + sinaf*(width-org_x) - sinar*org_y;
+
+// bottom right
+ floats[6] = x + cosaf*(width-org_x) + cosar*(height-org_y);
+ floats[7] = y + sinaf*(width-org_x) + sinar*(height-org_y);
+
+// bottom left
+ floats[9] = x - cosaf*org_x + cosar*(height-org_y);
+ floats[10] = y - sinaf*org_x + sinar*(height-org_y);
+
+ floats[12] = 0.0f;floats[13] = 0.0f;
+ floats[14] = 1.0f;floats[15] = 0.0f;
+ floats[16] = 1.0f;floats[17] = 1.0f;
+ floats[18] = 0.0f;floats[19] = 1.0f;
+ floats[20] = floats[24] = floats[28] = floats[32] = red;
+ floats[21] = floats[25] = floats[29] = floats[33] = green;
+ floats[22] = floats[26] = floats[30] = floats[34] = blue;
+ floats[23] = floats[27] = floats[31] = floats[35] = alpha;
+
+ R_Mesh_PrepareVertices_Generic_Arrays(4, floats, floats + 20, floats + 12);
+ R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
+}
+
+void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)