unsigned char *lmpdata;
char lmpname[MAX_QPATH];
int texflags;
+ int j;
texflags = TEXF_ALPHA;
if (!(cachepicflags & CACHEPICFLAG_NOCLAMP))
hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
for (pic = cachepichash[hashkey];pic;pic = pic->chain)
if (!strcmp (path, pic->name))
- if(pic->texflags == texflags)
+ if(!((pic->texflags ^ texflags) & ~(TEXF_COMPRESS))) // ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag
+ {
+ if(!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
+ {
+ if(pic->tex)
+ pic->autoload = false; // persist it
+ else
+ goto reload; // load it below, and then persist
+ }
return pic;
+ }
if (numcachepics == MAX_CACHED_PICS)
{
pic->chain = cachepichash[hashkey];
cachepichash[hashkey] = pic;
+reload:
// check whether it is an dynamic texture (if so, we can directly use its texture handler)
pic->tex = CL_GetDynTexture( path );
// if so, set the width/height, too
return pic;
}
+ pic->hasalpha = true; // assume alpha unless we know it has none
pic->texflags = texflags;
pic->autoload = (cachepicflags & CACHEPICFLAG_NOTPERSISTENT);
pixels = loadimagepixelsbgra(path+4, false, true, r_texture_convertsRGB_2d.integer, NULL);
if (pixels)
{
+ pic->hasalpha = false;
+ if (pic->texflags & TEXF_ALPHA)
+ {
+ for (j = 3;j < image_width * image_height * 4;j += 4)
+ {
+ if (pixels[j] < 255)
+ {
+ pic->hasalpha = true;
+ break;
+ }
+ }
+ }
+
pic->width = image_width;
pic->height = image_height;
if (!pic->autoload)
- pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, TEXTYPE_BGRA, pic->texflags, -1, NULL);
+ pic->tex = R_LoadTexture2D(drawtexturepool, path, image_width, image_height, pixels, TEXTYPE_BGRA, pic->texflags & (pic->hasalpha ? ~0 : ~TEXF_ALPHA), -1, NULL);
}
else
{
cachepic_t *Draw_CachePic (const char *path)
{
- return Draw_CachePic_Flags (path, 0);
+ return Draw_CachePic_Flags (path, 0); // default to persistent!
}
int draw_frame = 1;
pic->height = height;
if (pic->tex)
R_FreeTexture(pic->tex);
- pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0) | TEXF_ALLOWUPDATES, -1, NULL);
+ pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels_bgra, TEXTYPE_BGRA, (alpha ? TEXF_ALPHA : 0), -1, NULL);
return pic;
}
extern int con_linewidth; // to force rewrapping
void LoadFont(qboolean override, const char *name, dp_font_t *fnt, float scale, float voffset)
{
- int i;
+ int i, ch;
float maxwidth;
char widthfile[MAX_QPATH];
char *widthbuf;
dpsnprintf(widthfile, sizeof(widthfile), "%s.width", fnt->texpath);
// unspecified width == 1 (base width)
- for(i = 1; i < 256; ++i)
- fnt->width_of[i] = 1;
+ for(ch = 0; ch < 256; ++ch)
+ fnt->width_of[ch] = 1;
// FIXME load "name.width", if it fails, fill all with 1
if((widthbuf = (char *) FS_LoadFile(widthfile, tempmempool, true, &widthbufsize)))
{
float extraspacing = 0;
const char *p = widthbuf;
- int ch = 0;
+ ch = 0;
while(ch < 256)
{
if(!COM_ParseToken_Simple(&p, false, false))
case '-':
case '.':
fnt->width_of[ch] = atof(com_token) + extraspacing;
- if (fnt->ft2)
- {
- for (i = 0; i < MAX_FONT_SIZES; ++i)
- {
- //Font_MapForIndex(fnt->ft2, i)->width_of[ch] = snap_to_pixel_x(fnt->width_of[ch] * fnt->req_sizes[i], 0.4);
- ft2_font_map_t *map = Font_MapForIndex(fnt->ft2, i);
- if (!map)
- break;
- map->width_of[ch] = Font_SnapTo(fnt->width_of[ch], 1/map->size);
- }
- }
ch++;
break;
default:
Mem_Free(widthbuf);
}
- maxwidth = fnt->width_of[1];
- for(i = 2; i < 256; ++i)
+ if(fnt->ft2)
+ {
+ for (i = 0; i < MAX_FONT_SIZES; ++i)
+ {
+ ft2_font_map_t *map = Font_MapForIndex(fnt->ft2, i);
+ if (!map)
+ break;
+ for(ch = 0; ch < 256; ++ch)
+ map->width_of[ch] = Font_SnapTo(fnt->width_of[ch], 1/map->size);
+ }
+ }
+
+ maxwidth = fnt->width_of[0];
+ for(i = 1; i < 256; ++i)
maxwidth = max(maxwidth, fnt->width_of[i]);
fnt->maxwidth = maxwidth;
extern cvar_t developer_font;
dp_font_t *FindFont(const char *title, qboolean allocate_new)
{
- int i;
+ int i, oldsize;
// find font
for(i = 0; i < dp_fonts.maxsize; ++i)
}
}
// if no any 'free' fonts - expand buffer
- i = dp_fonts.maxsize;
+ oldsize = dp_fonts.maxsize;
dp_fonts.maxsize = dp_fonts.maxsize + FONTS_EXPAND;
if (developer_font.integer)
- Con_Printf("FindFont: enlarging fonts buffer (%i -> %i)\n", i, dp_fonts.maxsize);
- dp_fonts.f = Mem_Realloc(fonts_mempool, dp_fonts.f, sizeof(dp_font_t) * dp_fonts.maxsize);
+ Con_Printf("FindFont: enlarging fonts buffer (%i -> %i)\n", oldsize, dp_fonts.maxsize);
+ dp_fonts.f = (dp_font_t *)Mem_Realloc(fonts_mempool, dp_fonts.f, sizeof(dp_font_t) * dp_fonts.maxsize);
+ // relink ft2 structures
+ for(i = 0; i < oldsize; ++i)
+ if (dp_fonts.f[i].ft2)
+ dp_fonts.f[i].ft2->settings = &dp_fonts.f[i].settings;
// register a font in first expanded slot
- strlcpy(dp_fonts.f[i].title, title, sizeof(dp_fonts.f[i].title));
- return &dp_fonts.f[i];
+ strlcpy(dp_fonts.f[oldsize].title, title, sizeof(dp_fonts.f[oldsize].title));
+ return &dp_fonts.f[oldsize];
}
return NULL;
}
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++;
}
R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL);
}
-void _DrawQ_Setup(void)
+static void _DrawQ_Setup(void)
{
r_viewport_t viewport;
- if (r_refdef.draw2dstage)
+ if (r_refdef.draw2dstage == 1)
return;
- r_refdef.draw2dstage = true;
+ r_refdef.draw2dstage = 1;
CHECKGLERROR
R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height, 0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100, NULL);
R_SetViewport(&viewport);
GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
R_EntityMatrix(&identitymatrix);
- GL_DepthMask(true);
GL_DepthRange(0, 1);
GL_PolygonOffset(0, 0);
GL_DepthTest(false);
GL_Color(1,1,1,1);
GL_AlphaTest(false);
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
qboolean r_draw2d_force = false;
-static void _DrawQ_ProcessDrawFlag(int flags)
+void _DrawQ_SetupAndProcessDrawFlag(int flags, cachepic_t *pic, float alpha)
{
_DrawQ_Setup();
CHECKGLERROR
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_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ {
+ 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_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
+ {
+ GL_DepthMask(false);
+ GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ }
else if(flags == DRAWFLAG_SCREEN)
- GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
- else
+ {
+ 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[20];
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha);
if(!r_draw2d.integer && !r_draw2d_force)
return;
-
GL_Color(red, green, blue, alpha);
R_Mesh_VertexPointer(floats, 0, 0);
float sinar = sin(ar);
float cosar = cos(ar);
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, pic, alpha);
if(!r_draw2d.integer && !r_draw2d_force)
return;
-
GL_Color(red, green, blue, alpha);
R_Mesh_VertexPointer(floats, 0, 0);
{
float floats[12];
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha);
if(!r_draw2d.integer && !r_draw2d_force)
return;
-
GL_Color(red, green, blue, alpha);
R_Mesh_VertexPointer(floats, 0, 0);
if (maxlen < 1)
maxlen = 1<<30;
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 0);
if(!r_draw2d.integer && !r_draw2d_force)
return startx + DrawQ_TextWidth_UntilWidth_TrackColors_Scale(text, &maxlen, w, h, sw, sh, NULL, ignorecolorcodes, fnt, 1000000000);
}
if (!fontmap || (ch <= 0xFF && fontmap->glyphs[ch].image) || (ch >= 0xE000 && ch <= 0xE0FF))
{
- if (ch > 0xE000)
+ if (ch >= 0xE000)
ch -= 0xE000;
if (ch > 0xFF)
- continue;
+ goto out;
if (fontmap)
{
if (map != ft2_oldstyle_map)
//prevmap = map;
prevch = ch;
}
+out:
if (shadow)
{
x -= 1.0/pix_x * r_textshadow.value;
{
float floats[36];
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, pic, a1*a2*a3*a4);
if(!r_draw2d.integer && !r_draw2d_force)
return;
R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
}
-void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
+void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags, qboolean hasalpha)
{
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_Setup();
+ CHECKGLERROR
if(!r_draw2d.integer && !r_draw2d_force)
return;
+ DrawQ_ProcessDrawFlag(flags, hasalpha);
R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
{
int num;
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, NULL, 1);
if(!r_draw2d.integer && !r_draw2d_force)
return;
//[515]: this is old, delete
void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
{
- _DrawQ_ProcessDrawFlag(flags);
+ _DrawQ_SetupAndProcessDrawFlag(flags, NULL, alpha);
if(!r_draw2d.integer && !r_draw2d_force)
return;
// OGL uses top to bottom
ix = (int)(0.5 + x * ((float)vid.width / vid_conwidth.integer));
iy = (int)(0.5 + y * ((float) vid.height / vid_conheight.integer));
- iw = (int)(width * ((float)vid.width / vid_conwidth.integer));
- ih = (int)(height * ((float)vid.height / vid_conheight.integer));
+ iw = (int)(0.5 + (x+width) * ((float)vid.width / vid_conwidth.integer)) - ix;
+ ih = (int)(0.5 + (y+height) * ((float) vid.height / vid_conheight.integer)) - iy;
GL_Scissor(ix, vid.height - iy - ih, iw, ih);
GL_ScissorTest(true);
void DrawQ_Finish(void)
{
- r_refdef.draw2dstage = false;
+ r_refdef.draw2dstage = 0;
+}
+
+void DrawQ_RecalcView(void)
+{
+ if(r_refdef.draw2dstage)
+ r_refdef.draw2dstage = -1; // next draw call will set viewport etc. again
}
static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};