stb_rect_pack: fix LARGE_RECT bug
stb_truetype: oversampling, including oversampling demo app
This commit is contained in:
parent
b6f8358f47
commit
f03e352093
@ -495,6 +495,12 @@ static int rect_original_order(const void *a, const void *b)
|
|||||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
#define STBRP__MAXVAL 0xffffffff
|
||||||
|
#else
|
||||||
|
#define STBRP__MAXVAL 0xffff
|
||||||
|
#endif
|
||||||
|
|
||||||
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -516,7 +522,7 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
|
|||||||
rects[i].x = (stbrp_coord) fr.x;
|
rects[i].x = (stbrp_coord) fr.x;
|
||||||
rects[i].y = (stbrp_coord) fr.y;
|
rects[i].y = (stbrp_coord) fr.y;
|
||||||
} else {
|
} else {
|
||||||
rects[i].x = rects[i].y = 0xffff;
|
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +531,6 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
|
|||||||
|
|
||||||
// set was_packed flags
|
// set was_packed flags
|
||||||
for (i=0; i < num_rects; ++i)
|
for (i=0; i < num_rects; ++i)
|
||||||
rects[i].was_packed = !(rects[i].x == 0xffff && rects[i].y == 0xffff);
|
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
343
stb_truetype.h
343
stb_truetype.h
@ -35,6 +35,9 @@
|
|||||||
// Hou Qiming
|
// Hou Qiming
|
||||||
// Fabian "ryg" Giesen
|
// Fabian "ryg" Giesen
|
||||||
//
|
//
|
||||||
|
// Misc other:
|
||||||
|
// Ryan Gordon
|
||||||
|
//
|
||||||
// VERSION HISTORY
|
// VERSION HISTORY
|
||||||
//
|
//
|
||||||
// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
|
// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
|
||||||
@ -428,7 +431,7 @@ extern "C" {
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
|
unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
|
||||||
float xoff,yoff,xadvance;
|
float xoff,yoff,xadvance;
|
||||||
} stbtt_bakedchar;
|
} stbtt_bakedchar;
|
||||||
|
|
||||||
extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
|
extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
|
||||||
@ -471,24 +474,38 @@ extern void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // sa
|
|||||||
// This provides options for packing multiple fonts into one atlas, not
|
// This provides options for packing multiple fonts into one atlas, not
|
||||||
// perfectly but better than nothing.
|
// perfectly but better than nothing.
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
|
||||||
|
float xoff,yoff,xadvance;
|
||||||
|
float xoff2,yoff2;
|
||||||
|
} stbtt_packedchar;
|
||||||
|
|
||||||
typedef struct stbtt_pack_context stbtt_pack_context;
|
typedef struct stbtt_pack_context stbtt_pack_context;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
float font_size; // if positive, pixel height; if negative, points
|
float font_size; // if positive, pixel height; if negative, points
|
||||||
int first_unicode_char_in_range;
|
int first_unicode_char_in_range;
|
||||||
int num_chars_in_range;
|
int num_chars_in_range;
|
||||||
stbtt_bakedchar *chardata_for_range; // output
|
stbtt_packedchar *chardata_for_range; // output
|
||||||
} stbtt_pack_range;
|
} stbtt_pack_range;
|
||||||
|
|
||||||
extern int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, void *alloc_context);
|
extern int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context);
|
||||||
// returns 0 if the allocations fail
|
// returns 0 if the allocations fail
|
||||||
|
|
||||||
|
extern void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
|
||||||
extern void stbtt_PackEnd (stbtt_pack_context *spc);
|
extern void stbtt_PackEnd (stbtt_pack_context *spc);
|
||||||
extern int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
extern int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
||||||
int first_unicode_char_in_range, int num_chars_in_range, stbtt_bakedchar *chardata_for_range);
|
int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
|
||||||
extern int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
|
extern int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
|
||||||
|
|
||||||
|
|
||||||
|
extern void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
||||||
|
int char_index, // character to display
|
||||||
|
float *xpos, float *ypos, // pointers to current position in screen pixel space
|
||||||
|
stbtt_aligned_quad *q, // output: quad to draw
|
||||||
|
int align_to_integer);
|
||||||
|
|
||||||
// this is an opaque structure that you shouldn't mess with which holds
|
// this is an opaque structure that you shouldn't mess with which holds
|
||||||
// all the context needed from PackBegin to PackEnd.
|
// all the context needed from PackBegin to PackEnd.
|
||||||
struct stbtt_pack_context {
|
struct stbtt_pack_context {
|
||||||
@ -497,6 +514,8 @@ struct stbtt_pack_context {
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int stride_in_bytes;
|
int stride_in_bytes;
|
||||||
|
int padding;
|
||||||
|
unsigned int h_oversample, v_oversample;
|
||||||
unsigned char *pixels;
|
unsigned char *pixels;
|
||||||
void *nodes;
|
void *nodes;
|
||||||
};
|
};
|
||||||
@ -808,6 +827,12 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC
|
|||||||
|
|
||||||
#ifdef STB_TRUETYPE_IMPLEMENTATION
|
#ifdef STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
|
||||||
|
#ifndef STBTT_MAX_OVERSAMPLE
|
||||||
|
#define STBTT_MAX_OVERSAMPLE 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// accessors to parse data from file
|
// accessors to parse data from file
|
||||||
@ -1947,9 +1972,9 @@ extern int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font
|
|||||||
chardata[i].xadvance = scale * advance;
|
chardata[i].xadvance = scale * advance;
|
||||||
chardata[i].xoff = (float) x0;
|
chardata[i].xoff = (float) x0;
|
||||||
chardata[i].yoff = (float) y0;
|
chardata[i].yoff = (float) y0;
|
||||||
x = x + gw + 2;
|
x = x + gw + 1;
|
||||||
if (y+gh+2 > bottom_y)
|
if (y+gh+1 > bottom_y)
|
||||||
bottom_y = y+gh+2;
|
bottom_y = y+gh+1;
|
||||||
}
|
}
|
||||||
return bottom_y;
|
return bottom_y;
|
||||||
}
|
}
|
||||||
@ -1975,6 +2000,78 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
|
|||||||
*xpos += b->xadvance;
|
*xpos += b->xadvance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// rectangle packing replacement routines if you don't have stb_rect_pack.h
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_RECT_PACK_VERSION
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define STBTT__NOTUSED(v) (void)(v)
|
||||||
|
#else
|
||||||
|
#define STBTT__NOTUSED(v) (void)sizeof(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// COMPILER WARNING ?!?!? //
|
||||||
|
// //
|
||||||
|
// //
|
||||||
|
// if you get a compile warning due to these symbols being defined more than //
|
||||||
|
// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
|
||||||
|
// //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int width,height;
|
||||||
|
int x,y,bottom_y;
|
||||||
|
} stbrp_context;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char x;
|
||||||
|
} stbrp_node;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int id,w,h,x,y,was_packed;
|
||||||
|
} stbrp_rect;
|
||||||
|
|
||||||
|
static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
|
||||||
|
{
|
||||||
|
con->width = pw;
|
||||||
|
con->height = ph;
|
||||||
|
con->x = 0;
|
||||||
|
con->y = 0;
|
||||||
|
con->bottom_y = 0;
|
||||||
|
STBTT__NOTUSED(nodes);
|
||||||
|
STBTT__NOTUSED(num_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
if (con->x + rects[i].w > con->width) {
|
||||||
|
con->x = 0;
|
||||||
|
con->y = con->bottom_y;
|
||||||
|
}
|
||||||
|
if (con->y + rects[i].h > con->height)
|
||||||
|
break;
|
||||||
|
rects[i].x = con->x;
|
||||||
|
rects[i].y = con->y;
|
||||||
|
rects[i].was_packed = 1;
|
||||||
|
con->x += rects[i].w;
|
||||||
|
if (con->y + rects[i].h > con->bottom_y)
|
||||||
|
con->bottom_y = con->y + rects[i].h;
|
||||||
|
}
|
||||||
|
for ( ; i < num_rects; ++i)
|
||||||
|
rects[i].was_packed = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// bitmap baking
|
// bitmap baking
|
||||||
@ -1982,26 +2079,10 @@ void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_inde
|
|||||||
// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
|
// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
|
||||||
// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
|
// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
|
||||||
|
|
||||||
#ifndef STB_RECT_PACK_VERSION
|
int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
|
||||||
// @TODO: simulate STB_RECT_PACK API with trivial logic from BakeFontBitmap,
|
|
||||||
// try to share code?!?
|
|
||||||
#error "no stb_rect_pack"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct stbtt_pack_context {
|
|
||||||
void *user_allocator_context;
|
|
||||||
void *pack_info;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
unsigned char *pixels;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, void *alloc_context)
|
|
||||||
{
|
{
|
||||||
stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
|
stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
|
||||||
int num_nodes = pw-1;
|
int num_nodes = pw - padding;
|
||||||
stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
|
stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
|
||||||
|
|
||||||
if (context == NULL || nodes == NULL) {
|
if (context == NULL || nodes == NULL) {
|
||||||
@ -2016,9 +2097,12 @@ int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int
|
|||||||
spc->pixels = pixels;
|
spc->pixels = pixels;
|
||||||
spc->pack_info = context;
|
spc->pack_info = context;
|
||||||
spc->nodes = nodes;
|
spc->nodes = nodes;
|
||||||
|
spc->padding = padding;
|
||||||
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
|
||||||
|
spc->h_oversample = 1;
|
||||||
|
spc->v_oversample = 1;
|
||||||
|
|
||||||
stbrp_init_target(context, pw-1, ph-1, nodes, num_nodes);
|
stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
|
||||||
|
|
||||||
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
|
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
|
||||||
|
|
||||||
@ -2031,9 +2115,135 @@ void stbtt_PackEnd (stbtt_pack_context *spc)
|
|||||||
STBTT_free(spc->pack_info, spc->user_allocator_context);
|
STBTT_free(spc->pack_info, spc->user_allocator_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
|
||||||
|
{
|
||||||
|
assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
|
||||||
|
assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
|
||||||
|
if (h_oversample <= STBTT_MAX_OVERSAMPLE)
|
||||||
|
spc->h_oversample = h_oversample;
|
||||||
|
if (v_oversample <= STBTT_MAX_OVERSAMPLE)
|
||||||
|
spc->v_oversample = v_oversample;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
|
||||||
|
|
||||||
|
static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
|
||||||
|
{
|
||||||
|
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
||||||
|
int safe_w = w - kernel_width;
|
||||||
|
int j;
|
||||||
|
for (j=0; j < h; ++j) {
|
||||||
|
int i;
|
||||||
|
unsigned int total;
|
||||||
|
unsigned char *pixels_ahead = pixels + (kernel_width);
|
||||||
|
memset(buffer, 0, kernel_width);
|
||||||
|
|
||||||
|
total = 0;
|
||||||
|
|
||||||
|
// make kernel_width a constant in common cases so compiler can optimize out the divide
|
||||||
|
switch (kernel_width) {
|
||||||
|
case 2:
|
||||||
|
for (i=0; i <= safe_w; ++i) {
|
||||||
|
total += pixels[i] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
|
||||||
|
pixels[i] = total / 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
for (i=0; i <= safe_w; ++i) {
|
||||||
|
total += pixels[i] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
|
||||||
|
pixels[i] = total / 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
for (i=0; i <= safe_w; ++i) {
|
||||||
|
total += pixels[i] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
|
||||||
|
pixels[i] = total / 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
for (i=0; i <= safe_w; ++i) {
|
||||||
|
total += pixels[i] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
|
||||||
|
pixels[i] = total / kernel_width;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < w; ++i) {
|
||||||
|
assert(pixels[i] == 0);
|
||||||
|
total -= buffer[i & STBTT__OVER_MASK];
|
||||||
|
pixels[i] = total / kernel_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels += stride_in_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
|
||||||
|
{
|
||||||
|
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
|
||||||
|
int safe_h = h - kernel_width;
|
||||||
|
int j;
|
||||||
|
for (j=0; j < w; ++j) {
|
||||||
|
int i;
|
||||||
|
unsigned int total;
|
||||||
|
unsigned char *pixels_ahead = pixels + (kernel_width)*stride_in_bytes;
|
||||||
|
memset(buffer, 0, kernel_width);
|
||||||
|
|
||||||
|
total = 0;
|
||||||
|
|
||||||
|
// make kernel_width a constant in common cases so compiler can optimize out the divide
|
||||||
|
switch (kernel_width) {
|
||||||
|
case 2:
|
||||||
|
for (i=0; i <= safe_h; ++i) {
|
||||||
|
total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
|
||||||
|
pixels[i*stride_in_bytes] = total / 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
for (i=0; i <= safe_h; ++i) {
|
||||||
|
total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
|
||||||
|
pixels[i*stride_in_bytes] = total / 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
for (i=0; i <= safe_h; ++i) {
|
||||||
|
total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
|
||||||
|
pixels[i*stride_in_bytes] = total / 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
for (i=0; i <= safe_h; ++i) {
|
||||||
|
total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
|
||||||
|
buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
|
||||||
|
pixels[i*stride_in_bytes] = total / kernel_width;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < h; ++i) {
|
||||||
|
assert(pixels[i*stride_in_bytes] == 0);
|
||||||
|
total -= buffer[i & STBTT__OVER_MASK];
|
||||||
|
pixels[i*stride_in_bytes] = total / kernel_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||||
{
|
{
|
||||||
stbtt_fontinfo info;
|
stbtt_fontinfo info;
|
||||||
|
float recip_h = 1.0f / spc->h_oversample;
|
||||||
|
float recip_v = 1.0f / spc->v_oversample;
|
||||||
|
float sub_x = spc->h_oversample ? recip_h : 0;
|
||||||
|
float sub_y = spc->v_oversample ? recip_v : 0;
|
||||||
int i,j,k,n, return_value = 1;
|
int i,j,k,n, return_value = 1;
|
||||||
stbrp_context *context = (stbrp_context *) spc->pack_info;
|
stbrp_context *context = (stbrp_context *) spc->pack_info;
|
||||||
stbrp_rect *rects;
|
stbrp_rect *rects;
|
||||||
@ -2062,9 +2272,13 @@ int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int f
|
|||||||
float scale = stbtt_ScaleForPixelHeight(&info, fh);
|
float scale = stbtt_ScaleForPixelHeight(&info, fh);
|
||||||
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
||||||
int x0,y0,x1,y1;
|
int x0,y0,x1,y1;
|
||||||
stbtt_GetCodepointBitmapBox(&info, ranges[i].first_unicode_char_in_range + j, scale,scale, &x0,&y0,&x1,&y1);
|
stbtt_GetCodepointBitmapBoxSubpixel(&info, ranges[i].first_unicode_char_in_range + j,
|
||||||
rects[k].w = x1-x0+1;
|
scale * spc->h_oversample,
|
||||||
rects[k].h = y1-y0+1;
|
scale * spc->v_oversample,
|
||||||
|
0,0,
|
||||||
|
&x0,&y0,&x1,&y1);
|
||||||
|
rects[k].w = x1-x0 + spc->padding + spc->h_oversample-1;
|
||||||
|
rects[k].h = y1-y0 + spc->padding + spc->v_oversample-1;
|
||||||
++k;
|
++k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2079,26 +2293,49 @@ int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int f
|
|||||||
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
for (j=0; j < ranges[i].num_chars_in_range; ++j) {
|
||||||
stbrp_rect *r = &rects[k];
|
stbrp_rect *r = &rects[k];
|
||||||
if (r->was_packed) {
|
if (r->was_packed) {
|
||||||
stbtt_bakedchar *bc = &ranges[i].chardata_for_range[j];
|
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
|
||||||
int advance, lsb, x0,y0,x1,y1;
|
int advance, lsb, x0,y0,x1,y1;
|
||||||
int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
|
int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j);
|
||||||
|
|
||||||
|
// pad on left and top
|
||||||
|
r->x += spc->padding;
|
||||||
|
r->y += spc->padding;
|
||||||
|
r->w -= spc->padding;
|
||||||
|
r->h -= spc->padding;
|
||||||
stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
|
stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb);
|
||||||
stbtt_GetGlyphBitmapBox(&info, glyph, scale,scale, &x0,&y0,&x1,&y1);
|
stbtt_GetGlyphBitmapBox(&info, glyph,
|
||||||
|
scale * spc->h_oversample,
|
||||||
|
scale * spc->v_oversample,
|
||||||
|
&x0,&y0,&x1,&y1);
|
||||||
stbtt_MakeGlyphBitmapSubpixel(&info,
|
stbtt_MakeGlyphBitmapSubpixel(&info,
|
||||||
spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
||||||
r->w-1, r->h-1,
|
r->w - spc->h_oversample+1,
|
||||||
|
r->h - spc->v_oversample+1,
|
||||||
spc->stride_in_bytes,
|
spc->stride_in_bytes,
|
||||||
scale,scale,
|
scale * spc->h_oversample,
|
||||||
0.0f, 0.0f,
|
scale * spc->v_oversample,
|
||||||
|
0,0,
|
||||||
glyph);
|
glyph);
|
||||||
|
|
||||||
|
if (spc->h_oversample > 1)
|
||||||
|
stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
||||||
|
r->w, r->h, spc->stride_in_bytes,
|
||||||
|
spc->h_oversample);
|
||||||
|
|
||||||
|
if (spc->v_oversample > 1)
|
||||||
|
stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
|
||||||
|
r->w, r->h, spc->stride_in_bytes,
|
||||||
|
spc->v_oversample);
|
||||||
|
|
||||||
bc->x0 = (stbtt_int16) r->x;
|
bc->x0 = (stbtt_int16) r->x;
|
||||||
bc->y0 = (stbtt_int16) r->y;
|
bc->y0 = (stbtt_int16) r->y;
|
||||||
bc->x1 = (stbtt_int16) (r->x + r->w-1);
|
bc->x1 = (stbtt_int16) (r->x + r->w);
|
||||||
bc->y1 = (stbtt_int16) (r->y + r->h-1);
|
bc->y1 = (stbtt_int16) (r->y + r->h);
|
||||||
bc->xadvance = scale * advance;
|
bc->xadvance = scale * advance;
|
||||||
bc->xoff = (float) x0;
|
bc->xoff = (float) x0 * recip_h + sub_x;
|
||||||
bc->yoff = (float) y0;
|
bc->yoff = (float) y0 * recip_v + sub_y;
|
||||||
|
bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
|
||||||
|
bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
|
||||||
} else {
|
} else {
|
||||||
return_value = 0; // if any fail, report failure
|
return_value = 0; // if any fail, report failure
|
||||||
}
|
}
|
||||||
@ -2111,7 +2348,7 @@ int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int f
|
|||||||
}
|
}
|
||||||
|
|
||||||
int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size,
|
||||||
int first_unicode_char_in_range, int num_chars_in_range, stbtt_bakedchar *chardata_for_range)
|
int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
|
||||||
{
|
{
|
||||||
stbtt_pack_range range;
|
stbtt_pack_range range;
|
||||||
range.first_unicode_char_in_range = first_unicode_char_in_range;
|
range.first_unicode_char_in_range = first_unicode_char_in_range;
|
||||||
@ -2121,6 +2358,34 @@ int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int fo
|
|||||||
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
|
return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
|
||||||
|
{
|
||||||
|
float ipw = 1.0f / pw, iph = 1.0f / ph;
|
||||||
|
stbtt_packedchar *b = chardata + char_index;
|
||||||
|
|
||||||
|
if (align_to_integer) {
|
||||||
|
float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5);
|
||||||
|
float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5);
|
||||||
|
q->x0 = x;
|
||||||
|
q->y0 = y;
|
||||||
|
q->x1 = x + b->xoff2 - b->xoff;
|
||||||
|
q->y1 = y + b->yoff2 - b->yoff;
|
||||||
|
} else {
|
||||||
|
q->x0 = *xpos + b->xoff;
|
||||||
|
q->y0 = *ypos + b->yoff;
|
||||||
|
q->x1 = *xpos + b->xoff2;
|
||||||
|
q->y1 = *ypos + b->yoff2;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->s0 = b->x0 * ipw;
|
||||||
|
q->t0 = b->y0 * iph;
|
||||||
|
q->s1 = b->x1 * ipw;
|
||||||
|
q->t1 = b->y1 * iph;
|
||||||
|
|
||||||
|
*xpos += b->xadvance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// font name matching -- recommended not to use this
|
// font name matching -- recommended not to use this
|
||||||
|
@ -41,7 +41,7 @@ RSC=rc.exe
|
|||||||
# PROP Intermediate_Dir "Release"
|
# PROP Intermediate_Dir "Release"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
272
tests/oversample/main.c
Normal file
272
tests/oversample/main.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
#pragma warning(disable:4244; disable:4305; disable:4018)
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#define STB_DEFINE
|
||||||
|
#define STB_WINMAIN
|
||||||
|
#define STB_NO_REGISTRY
|
||||||
|
#include "stb_wingraph.h"
|
||||||
|
#include "stb.h"
|
||||||
|
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
#include "stb_rect_pack.h"
|
||||||
|
#include "stb_truetype.h"
|
||||||
|
|
||||||
|
#ifndef WINGDIAPI
|
||||||
|
#define CALLBACK __stdcall
|
||||||
|
#define WINGDIAPI __declspec(dllimport)
|
||||||
|
#define APIENTRY __stdcall
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gl/gl.h>
|
||||||
|
#include <gl/glu.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define SIZE_X 1024
|
||||||
|
#define SIZE_Y 768
|
||||||
|
|
||||||
|
stbtt_packedchar chardata[3][128];
|
||||||
|
|
||||||
|
int sx=SIZE_X, sy=SIZE_Y;
|
||||||
|
|
||||||
|
#define BITMAP_W 512
|
||||||
|
#define BITMAP_H 512
|
||||||
|
unsigned char temp_bitmap[BITMAP_W][BITMAP_H];
|
||||||
|
unsigned char ttf_buffer[1 << 25];
|
||||||
|
GLuint font_tex;
|
||||||
|
|
||||||
|
void load_fonts(void)
|
||||||
|
{
|
||||||
|
stbtt_pack_context pc;
|
||||||
|
FILE *f = fopen("c:/windows/fonts/times.ttf", "rb");
|
||||||
|
if (!f) exit(0);
|
||||||
|
fread(ttf_buffer, 1, 1<<25, f);
|
||||||
|
|
||||||
|
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
|
||||||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[0]+32);
|
||||||
|
stbtt_PackSetOversampling(&pc, 2, 2);
|
||||||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[1]+32);
|
||||||
|
stbtt_PackSetOversampling(&pc, 3, 1);
|
||||||
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 24.0, 32, 95, chardata[2]+32);
|
||||||
|
stbtt_PackEnd(&pc);
|
||||||
|
|
||||||
|
glGenTextures(1, &font_tex);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_init(void)
|
||||||
|
{
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glViewport(0,0,sx,sy);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluOrtho2D(0,sx,sy,0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawBoxTC(float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1)
|
||||||
|
{
|
||||||
|
glTexCoord2f(s0,t0); glVertex2f(x0,y0);
|
||||||
|
glTexCoord2f(s1,t0); glVertex2f(x1,y0);
|
||||||
|
glTexCoord2f(s1,t1); glVertex2f(x1,y1);
|
||||||
|
glTexCoord2f(s0,t1); glVertex2f(x0,y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int integer_align;
|
||||||
|
|
||||||
|
void print(float x, float y, int font, char *text)
|
||||||
|
{
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, font_tex);
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
while (*text) {
|
||||||
|
stbtt_aligned_quad q;
|
||||||
|
stbtt_GetPackedQuad(chardata[font], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, font ? 0 : integer_align);
|
||||||
|
drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
int font=0;
|
||||||
|
int translating;
|
||||||
|
int rotating=0;
|
||||||
|
float rotate_t, translate_t;
|
||||||
|
int show_tex;
|
||||||
|
|
||||||
|
void draw_world(void)
|
||||||
|
{
|
||||||
|
float x = 20;
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glColor3f(1,1,1);
|
||||||
|
|
||||||
|
if (font==1)
|
||||||
|
print(100, 50, font, "2x2 oversampled text at 1:1");
|
||||||
|
else if (font == 2)
|
||||||
|
print(100, 50, font, "3x1 oversampled text at 1:1");
|
||||||
|
else if (integer_align)
|
||||||
|
print(100, 50, font, "1:1 text, one texel = one pixel, snapped to integer coordinates");
|
||||||
|
else
|
||||||
|
print(100, 50, font, "1:1 text, one texel = one pixel");
|
||||||
|
|
||||||
|
print(100, 80, font, "O: toggle oversampling");
|
||||||
|
print(100,105, font, "T: toggle translation");
|
||||||
|
print(100,130, font, "R: toggle rotation");
|
||||||
|
print(100,155, font, "P: toggle pixel-snap (only non-oversampled)");
|
||||||
|
print(100,180, font, "V: view font texture");
|
||||||
|
|
||||||
|
if (show_tex) {
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
drawBoxTC(200,200, 200+BITMAP_W,200+BITMAP_H, 0,0,1,1);
|
||||||
|
glEnd();
|
||||||
|
} else {
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glTranslatef(200,250,0);
|
||||||
|
|
||||||
|
if (translating)
|
||||||
|
x += fmod(translate_t*8,30);
|
||||||
|
|
||||||
|
if (rotating) {
|
||||||
|
glTranslatef(100,150,0);
|
||||||
|
glRotatef(rotate_t*2,0,0,1);
|
||||||
|
glTranslatef(-100,-150,0);
|
||||||
|
}
|
||||||
|
print(x,100, font, "This is a test");
|
||||||
|
print(x,130, font, "Now is the time for all good men to come to the aid of their country.");
|
||||||
|
print(x,160, font, "The quick brown fox jumps over the lazy dog.");
|
||||||
|
print(x,190, font, "0123456789");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(void)
|
||||||
|
{
|
||||||
|
draw_init();
|
||||||
|
draw_world();
|
||||||
|
stbwingraph_SwapBuffers(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int initialized=0;
|
||||||
|
static float last_dt;
|
||||||
|
|
||||||
|
int move[4];
|
||||||
|
int raw_mouse_x, raw_mouse_y;
|
||||||
|
|
||||||
|
int loopmode(float dt, int real, int in_client)
|
||||||
|
{
|
||||||
|
float actual_dt = dt;
|
||||||
|
|
||||||
|
if (!initialized) return 0;
|
||||||
|
|
||||||
|
rotate_t += dt;
|
||||||
|
translate_t += dt;
|
||||||
|
|
||||||
|
// music_sim();
|
||||||
|
if (!real)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (dt > 0.25) dt = 0.25;
|
||||||
|
if (dt < 0.01) dt = 0.01;
|
||||||
|
|
||||||
|
draw();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int winproc(void *data, stbwingraph_event *e)
|
||||||
|
{
|
||||||
|
switch (e->type) {
|
||||||
|
case STBWGE_create:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STBWGE_char:
|
||||||
|
switch(e->key) {
|
||||||
|
case 27:
|
||||||
|
stbwingraph_ShowCursor(NULL,1);
|
||||||
|
return STBWINGRAPH_winproc_exit;
|
||||||
|
break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
font = (font+1) % 3;
|
||||||
|
break;
|
||||||
|
case 't': case 'T':
|
||||||
|
translating = !translating;
|
||||||
|
translate_t = 0;
|
||||||
|
break;
|
||||||
|
case 'r': case 'R':
|
||||||
|
rotating = !rotating;
|
||||||
|
rotate_t = 0;
|
||||||
|
break;
|
||||||
|
case 'p': case 'P':
|
||||||
|
integer_align = !integer_align;
|
||||||
|
break;
|
||||||
|
case 'v': case 'V':
|
||||||
|
show_tex = !show_tex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STBWGE_mousemove:
|
||||||
|
raw_mouse_x = e->mx;
|
||||||
|
raw_mouse_y = e->my;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case STBWGE_mousewheel: do_mouse(e,0,0); break;
|
||||||
|
case STBWGE_leftdown: do_mouse(e, 1,0); break;
|
||||||
|
case STBWGE_leftup: do_mouse(e,-1,0); break;
|
||||||
|
case STBWGE_rightdown: do_mouse(e,0, 1); break;
|
||||||
|
case STBWGE_rightup: do_mouse(e,0,-1); break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case STBWGE_keydown:
|
||||||
|
if (e->key == VK_RIGHT) move[0] = 1;
|
||||||
|
if (e->key == VK_LEFT) move[1] = 1;
|
||||||
|
if (e->key == VK_UP) move[2] = 1;
|
||||||
|
if (e->key == VK_DOWN) move[3] = 1;
|
||||||
|
break;
|
||||||
|
case STBWGE_keyup:
|
||||||
|
if (e->key == VK_RIGHT) move[0] = 0;
|
||||||
|
if (e->key == VK_LEFT) move[1] = 0;
|
||||||
|
if (e->key == VK_UP) move[2] = 0;
|
||||||
|
if (e->key == VK_DOWN) move[3] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STBWGE_size:
|
||||||
|
sx = e->width;
|
||||||
|
sy = e->height;
|
||||||
|
loopmode(0,1,0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STBWGE_draw:
|
||||||
|
if (initialized)
|
||||||
|
loopmode(0,1,0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return STBWINGRAPH_unprocessed;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_main(void)
|
||||||
|
{
|
||||||
|
stbwingraph_Priority(2);
|
||||||
|
stbwingraph_CreateWindow(1, winproc, NULL, "tt", SIZE_X,SIZE_Y, 0, 1, 0, 0);
|
||||||
|
stbwingraph_ShowCursor(NULL, 0);
|
||||||
|
load_fonts();
|
||||||
|
initialized = 1;
|
||||||
|
stbwingraph_MainLoop(loopmode, 0.016f); // 30 fps = 0.33
|
||||||
|
}
|
||||||
|
|
97
tests/oversample/oversample.dsp
Normal file
97
tests/oversample/oversample.dsp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="oversample" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=oversample - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "oversample.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "oversample.mak" CFG="oversample - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "oversample - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "oversample - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "oversample - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /WX /GX /O2 /I "c:\sean\prj\stb" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
|
||||||
|
# SUBTRACT CPP /YX
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# SUBTRACT LINK32 /map /debug
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "oversample - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /WX /Gm /GX /Zi /Od /I "c:\sean\prj\stb" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib winspool.lib comdlg32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "oversample - Win32 Release"
|
||||||
|
# Name "oversample - Win32 Debug"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\main.c
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
29
tests/oversample/oversample.dsw
Normal file
29
tests/oversample/oversample.dsw
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "oversample"=.\oversample.dsp - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
824
tests/oversample/stb_wingraph.h
Normal file
824
tests/oversample/stb_wingraph.h
Normal file
@ -0,0 +1,824 @@
|
|||||||
|
// stb_wingraph.h v0.01 - public domain windows graphics programming
|
||||||
|
// wraps WinMain, ChoosePixelFormat, ChangeDisplayResolution, etc. for
|
||||||
|
// doing OpenGL graphics
|
||||||
|
//
|
||||||
|
// in ONE source file, put '#define STB_DEFINE' before including this
|
||||||
|
// OR put '#define STB_WINMAIN' to define a WinMain that calls stbwingraph_main(void)
|
||||||
|
//
|
||||||
|
// @TODO:
|
||||||
|
// 2d rendering interface (that can be done easily in software)
|
||||||
|
// STB_WINGRAPH_SOFTWARE -- 2d software rendering only
|
||||||
|
// STB_WINGRAPH_OPENGL -- OpenGL only
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef INCLUDE_STB_WINGRAPH_H
|
||||||
|
#define INCLUDE_STB_WINGRAPH_H
|
||||||
|
|
||||||
|
#ifdef STB_WINMAIN
|
||||||
|
#ifndef STB_DEFINE
|
||||||
|
#define STB_DEFINE
|
||||||
|
#define STB_WINGRAPH_DISABLE_DEFINE_AT_END
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STB_DEFINE
|
||||||
|
#pragma comment(lib, "opengl32.lib")
|
||||||
|
#pragma comment(lib, "glu32.lib")
|
||||||
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define STB_EXTERN extern "C"
|
||||||
|
#else
|
||||||
|
#define STB_EXTERN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STB_DEFINE
|
||||||
|
#ifndef _WINDOWS_
|
||||||
|
#ifdef APIENTRY
|
||||||
|
#undef APIENTRY
|
||||||
|
#endif
|
||||||
|
#ifdef WINGDIAPI
|
||||||
|
#undef WINGDIAPI
|
||||||
|
#endif
|
||||||
|
#define _WIN32_WINNT 0x0400 // WM_MOUSEWHEEL
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void * stbwingraph_hwnd;
|
||||||
|
typedef void * stbwingraph_hinstance;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBWINGRAPH_unprocessed = -(1 << 24),
|
||||||
|
STBWINGRAPH_do_not_show,
|
||||||
|
STBWINGRAPH_winproc_exit,
|
||||||
|
STBWINGRAPH_winproc_update,
|
||||||
|
STBWINGRAPH_update_exit,
|
||||||
|
STBWINGRAPH_update_pause,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STBWGE__none=0,
|
||||||
|
|
||||||
|
STBWGE_create,
|
||||||
|
STBWGE_create_postshow,
|
||||||
|
STBWGE_draw,
|
||||||
|
STBWGE_destroy,
|
||||||
|
STBWGE_char,
|
||||||
|
STBWGE_keydown,
|
||||||
|
STBWGE_syskeydown,
|
||||||
|
STBWGE_keyup,
|
||||||
|
STBWGE_syskeyup,
|
||||||
|
STBWGE_deactivate,
|
||||||
|
STBWGE_activate,
|
||||||
|
STBWGE_size,
|
||||||
|
|
||||||
|
STBWGE_mousemove ,
|
||||||
|
STBWGE_leftdown , STBWGE_leftup ,
|
||||||
|
STBWGE_middledown, STBWGE_middleup,
|
||||||
|
STBWGE_rightdown , STBWGE_rightup ,
|
||||||
|
STBWGE_mousewheel,
|
||||||
|
} stbwingraph_event_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
stbwingraph_event_type type;
|
||||||
|
|
||||||
|
// for input events (mouse, keyboard)
|
||||||
|
int mx,my; // mouse x & y
|
||||||
|
int dx,dy;
|
||||||
|
int shift, ctrl, alt;
|
||||||
|
|
||||||
|
// for keyboard events
|
||||||
|
int key;
|
||||||
|
|
||||||
|
// for STBWGE_size:
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
// for STBWGE_crate
|
||||||
|
int did_share_lists; // if true, wglShareLists succeeded
|
||||||
|
|
||||||
|
void *handle;
|
||||||
|
|
||||||
|
} stbwingraph_event;
|
||||||
|
|
||||||
|
typedef int (*stbwingraph_window_proc)(void *data, stbwingraph_event *event);
|
||||||
|
|
||||||
|
extern stbwingraph_hinstance stbwingraph_app;
|
||||||
|
extern stbwingraph_hwnd stbwingraph_primary_window;
|
||||||
|
extern int stbwingraph_request_fullscreen;
|
||||||
|
extern int stbwingraph_request_windowed;
|
||||||
|
|
||||||
|
STB_EXTERN void stbwingraph_ods(char *str, ...);
|
||||||
|
STB_EXTERN int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type,
|
||||||
|
char *caption, char *text, ...);
|
||||||
|
STB_EXTERN int stbwingraph_ChangeResolution(unsigned int w, unsigned int h,
|
||||||
|
unsigned int bits, int use_message_box);
|
||||||
|
STB_EXTERN int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits,
|
||||||
|
int alpha_bits, int depth_bits, int stencil_bits, int accum_bits);
|
||||||
|
STB_EXTERN int stbwingraph_DefineClass(void *hinstance, char *iconname);
|
||||||
|
STB_EXTERN void stbwingraph_SwapBuffers(void *win);
|
||||||
|
STB_EXTERN void stbwingraph_Priority(int n);
|
||||||
|
|
||||||
|
STB_EXTERN void stbwingraph_MakeFonts(void *window, int font_base);
|
||||||
|
STB_EXTERN void stbwingraph_ShowWindow(void *window);
|
||||||
|
STB_EXTERN void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil);
|
||||||
|
STB_EXTERN void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height);
|
||||||
|
STB_EXTERN void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh);
|
||||||
|
STB_EXTERN void stbwingraph_DestroyWindow(void *window);
|
||||||
|
STB_EXTERN void stbwingraph_ShowCursor(void *window, int visible);
|
||||||
|
STB_EXTERN float stbwingraph_GetTimestep(float minimum_time);
|
||||||
|
STB_EXTERN void stbwingraph_SetGLWindow(void *win);
|
||||||
|
typedef int (*stbwingraph_update)(float timestep, int real, int in_client);
|
||||||
|
STB_EXTERN int stbwingraph_MainLoop(stbwingraph_update func, float mintime);
|
||||||
|
|
||||||
|
#ifdef STB_DEFINE
|
||||||
|
stbwingraph_hinstance stbwingraph_app;
|
||||||
|
stbwingraph_hwnd stbwingraph_primary_window;
|
||||||
|
int stbwingraph_request_fullscreen;
|
||||||
|
int stbwingraph_request_windowed;
|
||||||
|
|
||||||
|
void stbwingraph_ods(char *str, ...)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
va_list v;
|
||||||
|
va_start(v,str);
|
||||||
|
vsprintf(buffer, str, v);
|
||||||
|
va_end(v);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...)
|
||||||
|
{
|
||||||
|
va_list v;
|
||||||
|
char buffer[1024];
|
||||||
|
va_start(v, text);
|
||||||
|
vsprintf(buffer, text, v);
|
||||||
|
va_end(v);
|
||||||
|
return MessageBox(win, buffer, caption, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_Priority(int n)
|
||||||
|
{
|
||||||
|
int p;
|
||||||
|
switch (n) {
|
||||||
|
case -1: p = THREAD_PRIORITY_BELOW_NORMAL; break;
|
||||||
|
case 0: p = THREAD_PRIORITY_NORMAL; break;
|
||||||
|
case 1: p = THREAD_PRIORITY_ABOVE_NORMAL; break;
|
||||||
|
default:
|
||||||
|
if (n < 0) p = THREAD_PRIORITY_LOWEST;
|
||||||
|
else p = THREAD_PRIORITY_HIGHEST;
|
||||||
|
}
|
||||||
|
SetThreadPriority(GetCurrentThread(), p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbwingraph_ResetResolution(void)
|
||||||
|
{
|
||||||
|
ChangeDisplaySettings(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbwingraph_RegisterResetResolution(void)
|
||||||
|
{
|
||||||
|
static int done=0;
|
||||||
|
if (!done) {
|
||||||
|
done = 1;
|
||||||
|
atexit(stbwingraph_ResetResolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box)
|
||||||
|
{
|
||||||
|
DEVMODE mode;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
int i, tries=0;
|
||||||
|
for (i=0; ; ++i) {
|
||||||
|
int success = EnumDisplaySettings(NULL, i, &mode);
|
||||||
|
if (!success) break;
|
||||||
|
if (mode.dmBitsPerPel == bits && mode.dmPelsWidth == w && mode.dmPelsHeight == h) {
|
||||||
|
++tries;
|
||||||
|
success = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
|
||||||
|
if (success == DISP_CHANGE_SUCCESSFUL) {
|
||||||
|
stbwingraph_RegisterResetResolution();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tries) {
|
||||||
|
if (use_message_box)
|
||||||
|
stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we tried but failed, so try explicitly doing it without specifying refresh rate
|
||||||
|
|
||||||
|
// Win95 support logic
|
||||||
|
mode.dmBitsPerPel = bits;
|
||||||
|
mode.dmPelsWidth = w;
|
||||||
|
mode.dmPelsHeight = h;
|
||||||
|
mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||||
|
|
||||||
|
res = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case DISP_CHANGE_SUCCESSFUL:
|
||||||
|
stbwingraph_RegisterResetResolution();
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case DISP_CHANGE_RESTART:
|
||||||
|
if (use_message_box)
|
||||||
|
stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "Please set your desktop to %d-bit color and then try again.");
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case DISP_CHANGE_FAILED:
|
||||||
|
if (use_message_box)
|
||||||
|
stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The hardware failed to change modes.");
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case DISP_CHANGE_BADMODE:
|
||||||
|
if (use_message_box)
|
||||||
|
stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits);
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (use_message_box)
|
||||||
|
stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "An unknown error prevented a change to a %d x %d x %d-bit display.", w, h, bits);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits)
|
||||||
|
{
|
||||||
|
HDC dc = GetDC(win);
|
||||||
|
PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) };
|
||||||
|
int pixel_format;
|
||||||
|
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
||||||
|
pfd.dwLayerMask = PFD_MAIN_PLANE;
|
||||||
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||||
|
pfd.cColorBits = color_bits;
|
||||||
|
pfd.cAlphaBits = alpha_bits;
|
||||||
|
pfd.cDepthBits = depth_bits;
|
||||||
|
pfd.cStencilBits = stencil_bits;
|
||||||
|
pfd.cAccumBits = accum_bits;
|
||||||
|
|
||||||
|
pixel_format = ChoosePixelFormat(dc, &pfd);
|
||||||
|
if (!pixel_format) return FALSE;
|
||||||
|
|
||||||
|
if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
|
||||||
|
return FALSE;
|
||||||
|
SetPixelFormat(dc, pixel_format, &pfd);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// app data
|
||||||
|
stbwingraph_window_proc func;
|
||||||
|
void *data;
|
||||||
|
// creation parameters
|
||||||
|
int color, alpha, depth, stencil, accum;
|
||||||
|
HWND share_window;
|
||||||
|
HWND window;
|
||||||
|
// internal data
|
||||||
|
HGLRC rc;
|
||||||
|
HDC dc;
|
||||||
|
int hide_mouse;
|
||||||
|
int in_client;
|
||||||
|
int active;
|
||||||
|
int did_share_lists;
|
||||||
|
int mx,my; // last mouse positions
|
||||||
|
} stbwingraph__window;
|
||||||
|
|
||||||
|
static void stbwingraph__inclient(stbwingraph__window *win, int state)
|
||||||
|
{
|
||||||
|
if (state != win->in_client) {
|
||||||
|
win->in_client = state;
|
||||||
|
if (win->hide_mouse)
|
||||||
|
ShowCursor(!state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbwingraph__key(stbwingraph_event *e, int type, int key, stbwingraph__window *z)
|
||||||
|
{
|
||||||
|
e->type = type;
|
||||||
|
e->key = key;
|
||||||
|
e->shift = (GetKeyState(VK_SHIFT) < 0);
|
||||||
|
e->ctrl = (GetKeyState(VK_CONTROL) < 0);
|
||||||
|
e->alt = (GetKeyState(VK_MENU) < 0);
|
||||||
|
if (z) {
|
||||||
|
e->mx = z->mx;
|
||||||
|
e->my = z->my;
|
||||||
|
} else {
|
||||||
|
e->mx = e->my = 0;
|
||||||
|
}
|
||||||
|
e->dx = e->dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbwingraph__mouse(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z)
|
||||||
|
{
|
||||||
|
static int captured = 0;
|
||||||
|
e->type = type;
|
||||||
|
e->mx = (short) LOWORD(lparam);
|
||||||
|
e->my = (short) HIWORD(lparam);
|
||||||
|
if (!z || z->mx == -(1 << 30)) {
|
||||||
|
e->dx = e->dy = 0;
|
||||||
|
} else {
|
||||||
|
e->dx = e->mx - z->mx;
|
||||||
|
e->dy = e->my - z->my;
|
||||||
|
}
|
||||||
|
e->shift = (wparam & MK_SHIFT) != 0;
|
||||||
|
e->ctrl = (wparam & MK_CONTROL) != 0;
|
||||||
|
e->alt = (wparam & MK_ALT) != 0;
|
||||||
|
if (z) {
|
||||||
|
z->mx = e->mx;
|
||||||
|
z->my = e->my;
|
||||||
|
}
|
||||||
|
if (capture) {
|
||||||
|
if (!captured && capture == 1)
|
||||||
|
SetCapture(wnd);
|
||||||
|
captured += capture;
|
||||||
|
if (!captured && capture == -1)
|
||||||
|
ReleaseCapture();
|
||||||
|
if (captured < 0) captured = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stbwingraph__mousewheel(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z)
|
||||||
|
{
|
||||||
|
// lparam seems bogus!
|
||||||
|
static int captured = 0;
|
||||||
|
e->type = type;
|
||||||
|
if (z) {
|
||||||
|
e->mx = z->mx;
|
||||||
|
e->my = z->my;
|
||||||
|
}
|
||||||
|
e->dx = e->dy = 0;
|
||||||
|
e->shift = (wparam & MK_SHIFT) != 0;
|
||||||
|
e->ctrl = (wparam & MK_CONTROL) != 0;
|
||||||
|
e->alt = (GetKeyState(VK_MENU) < 0);
|
||||||
|
e->key = ((int) wparam >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbwingraph_force_update;
|
||||||
|
static int WINAPI stbwingraph_WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
int allow_default = TRUE;
|
||||||
|
stbwingraph_event e = { STBWGE__none };
|
||||||
|
// the following line is wrong for 64-bit windows, but VC6 doesn't have GetWindowLongPtr
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(wnd, GWL_USERDATA);
|
||||||
|
|
||||||
|
switch (msg) {
|
||||||
|
|
||||||
|
case WM_CREATE:
|
||||||
|
{
|
||||||
|
LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam;
|
||||||
|
assert(z == NULL);
|
||||||
|
z = (stbwingraph__window *) lpcs->lpCreateParams;
|
||||||
|
SetWindowLong(wnd, GWL_USERDATA, (LONG) z);
|
||||||
|
z->dc = GetDC(wnd);
|
||||||
|
if (stbwingraph_SetPixelFormat(wnd, z->color, z->alpha, z->depth, z->stencil, z->accum)) {
|
||||||
|
z->rc = wglCreateContext(z->dc);
|
||||||
|
if (z->rc) {
|
||||||
|
e.type = STBWGE_create;
|
||||||
|
z->did_share_lists = FALSE;
|
||||||
|
if (z->share_window) {
|
||||||
|
stbwingraph__window *y = (stbwingraph__window *) GetWindowLong(z->share_window, GWL_USERDATA);
|
||||||
|
if (wglShareLists(z->rc, y->rc))
|
||||||
|
z->did_share_lists = TRUE;
|
||||||
|
}
|
||||||
|
wglMakeCurrent(z->dc, z->rc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_PAINT: {
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
HDC hdc = BeginPaint(wnd, &ps);
|
||||||
|
SelectObject(hdc, GetStockObject(NULL_BRUSH));
|
||||||
|
e.type = STBWGE_draw;
|
||||||
|
e.handle = wnd;
|
||||||
|
z->func(z->data, &e);
|
||||||
|
EndPaint(wnd, &ps);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
e.type = STBWGE_destroy;
|
||||||
|
e.handle = wnd;
|
||||||
|
if (z && z->func)
|
||||||
|
z->func(z->data, &e);
|
||||||
|
wglMakeCurrent(NULL, NULL) ;
|
||||||
|
if (z) {
|
||||||
|
if (z->rc) wglDeleteContext(z->rc);
|
||||||
|
z->dc = 0;
|
||||||
|
z->rc = 0;
|
||||||
|
}
|
||||||
|
if (wnd == stbwingraph_primary_window)
|
||||||
|
PostQuitMessage (0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_CHAR: stbwingraph__key(&e, STBWGE_char , wparam, z); break;
|
||||||
|
case WM_KEYDOWN: stbwingraph__key(&e, STBWGE_keydown, wparam, z); break;
|
||||||
|
case WM_KEYUP: stbwingraph__key(&e, STBWGE_keyup , wparam, z); break;
|
||||||
|
|
||||||
|
case WM_NCMOUSEMOVE: stbwingraph__inclient(z,0); break;
|
||||||
|
case WM_MOUSEMOVE: stbwingraph__inclient(z,1); stbwingraph__mouse(&e, STBWGE_mousemove, wparam, lparam,0,wnd, z); break;
|
||||||
|
case WM_LBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_leftdown, wparam, lparam,1,wnd, z); break;
|
||||||
|
case WM_MBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_middledown, wparam, lparam,1,wnd, z); break;
|
||||||
|
case WM_RBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_rightdown, wparam, lparam,1,wnd, z); break;
|
||||||
|
case WM_LBUTTONUP: stbwingraph__mouse(&e, STBWGE_leftup, wparam, lparam,-1,wnd, z); break;
|
||||||
|
case WM_MBUTTONUP: stbwingraph__mouse(&e, STBWGE_middleup, wparam, lparam,-1,wnd, z); break;
|
||||||
|
case WM_RBUTTONUP: stbwingraph__mouse(&e, STBWGE_rightup, wparam, lparam,-1,wnd, z); break;
|
||||||
|
case WM_MOUSEWHEEL: stbwingraph__mousewheel(&e, STBWGE_mousewheel, wparam, lparam,0,wnd, z); break;
|
||||||
|
|
||||||
|
case WM_ACTIVATE:
|
||||||
|
allow_default = FALSE;
|
||||||
|
if (LOWORD(wparam)==WA_INACTIVE ) {
|
||||||
|
wglMakeCurrent(z->dc, NULL);
|
||||||
|
e.type = STBWGE_deactivate;
|
||||||
|
z->active = FALSE;
|
||||||
|
} else {
|
||||||
|
wglMakeCurrent(z->dc, z->rc);
|
||||||
|
e.type = STBWGE_activate;
|
||||||
|
z->active = TRUE;
|
||||||
|
}
|
||||||
|
e.handle = wnd;
|
||||||
|
z->func(z->data, &e);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_SIZE: {
|
||||||
|
RECT rect;
|
||||||
|
allow_default = FALSE;
|
||||||
|
GetClientRect(wnd, &rect);
|
||||||
|
e.type = STBWGE_size;
|
||||||
|
e.width = rect.right;
|
||||||
|
e.height = rect.bottom;
|
||||||
|
e.handle = wnd;
|
||||||
|
z->func(z->data, &e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProc (wnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.type != STBWGE__none) {
|
||||||
|
int n;
|
||||||
|
e.handle = wnd;
|
||||||
|
n = z->func(z->data, &e);
|
||||||
|
if (n == STBWINGRAPH_winproc_exit) {
|
||||||
|
PostQuitMessage(0);
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
if (n == STBWINGRAPH_winproc_update) {
|
||||||
|
stbwingraph_force_update = TRUE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (n != STBWINGRAPH_unprocessed)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return DefWindowProc (wnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbwingraph_DefineClass(HINSTANCE hInstance, char *iconname)
|
||||||
|
{
|
||||||
|
WNDCLASSEX wndclass;
|
||||||
|
|
||||||
|
stbwingraph_app = hInstance;
|
||||||
|
|
||||||
|
wndclass.cbSize = sizeof(wndclass);
|
||||||
|
wndclass.style = CS_OWNDC;
|
||||||
|
wndclass.lpfnWndProc = (WNDPROC) stbwingraph_WinProc;
|
||||||
|
wndclass.cbClsExtra = 0;
|
||||||
|
wndclass.cbWndExtra = 0;
|
||||||
|
wndclass.hInstance = hInstance;
|
||||||
|
wndclass.hIcon = LoadIcon(hInstance, iconname);
|
||||||
|
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||||
|
wndclass.hbrBackground = GetStockObject(NULL_BRUSH);
|
||||||
|
wndclass.lpszMenuName = "zwingraph";
|
||||||
|
wndclass.lpszClassName = "zwingraph";
|
||||||
|
wndclass.hIconSm = NULL;
|
||||||
|
|
||||||
|
if (!RegisterClassEx(&wndclass))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_ShowWindow(void *window)
|
||||||
|
{
|
||||||
|
stbwingraph_event e = { STBWGE_create_postshow };
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA);
|
||||||
|
ShowWindow(window, SW_SHOWNORMAL);
|
||||||
|
InvalidateRect(window, NULL, TRUE);
|
||||||
|
UpdateWindow(window);
|
||||||
|
e.handle = window;
|
||||||
|
z->func(z->data, &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text,
|
||||||
|
int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil)
|
||||||
|
{
|
||||||
|
HWND win;
|
||||||
|
DWORD dwstyle;
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) malloc(sizeof(*z));
|
||||||
|
|
||||||
|
if (z == NULL) return NULL;
|
||||||
|
memset(z, 0, sizeof(*z));
|
||||||
|
z->color = 24;
|
||||||
|
z->depth = 24;
|
||||||
|
z->alpha = dest_alpha;
|
||||||
|
z->stencil = stencil;
|
||||||
|
z->func = func;
|
||||||
|
z->data = data;
|
||||||
|
z->mx = -(1 << 30);
|
||||||
|
z->my = 0;
|
||||||
|
|
||||||
|
if (primary) {
|
||||||
|
if (stbwingraph_request_windowed)
|
||||||
|
fullscreen = FALSE;
|
||||||
|
else if (stbwingraph_request_fullscreen)
|
||||||
|
fullscreen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
|
#ifdef STB_SIMPLE
|
||||||
|
stbwingraph_ChangeResolution(width, height, 32, 1);
|
||||||
|
#else
|
||||||
|
if (!stbwingraph_ChangeResolution(width, height, 32, 0))
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
dwstyle = WS_POPUP | WS_CLIPSIBLINGS;
|
||||||
|
} else {
|
||||||
|
RECT rect;
|
||||||
|
dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||||
|
if (resizeable)
|
||||||
|
dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX;
|
||||||
|
rect.top = 0;
|
||||||
|
rect.left = 0;
|
||||||
|
rect.right = width;
|
||||||
|
rect.bottom = height;
|
||||||
|
AdjustWindowRect(&rect, dwstyle, FALSE);
|
||||||
|
width = rect.right - rect.left;
|
||||||
|
height = rect.bottom - rect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
win = CreateWindow("zwingraph", text ? text : "sample", dwstyle,
|
||||||
|
CW_USEDEFAULT,0, width, height,
|
||||||
|
NULL, NULL, stbwingraph_app, z);
|
||||||
|
|
||||||
|
if (win == NULL) return win;
|
||||||
|
|
||||||
|
if (primary) {
|
||||||
|
if (stbwingraph_primary_window)
|
||||||
|
stbwingraph_DestroyWindow(stbwingraph_primary_window);
|
||||||
|
stbwingraph_primary_window = win;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
stbwingraph_event e = { STBWGE_create };
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
|
||||||
|
z->window = win;
|
||||||
|
e.did_share_lists = z->did_share_lists;
|
||||||
|
e.handle = win;
|
||||||
|
if (z->func(z->data, &e) != STBWINGRAPH_do_not_show)
|
||||||
|
stbwingraph_ShowWindow(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height)
|
||||||
|
{
|
||||||
|
int fullscreen = 0;
|
||||||
|
#ifndef _DEBUG
|
||||||
|
if (width == 640 && height == 480) fullscreen = 1;
|
||||||
|
if (width == 800 && height == 600) fullscreen = 1;
|
||||||
|
if (width == 1024 && height == 768) fullscreen = 1;
|
||||||
|
if (width == 1280 && height == 1024) fullscreen = 1;
|
||||||
|
if (width == 1600 && height == 1200) fullscreen = 1;
|
||||||
|
//@TODO: widescreen widths
|
||||||
|
#endif
|
||||||
|
return stbwingraph_CreateWindow(1, func, NULL, NULL, width, height, fullscreen, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh)
|
||||||
|
{
|
||||||
|
if (fullscreen == -1) {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
fullscreen = 0;
|
||||||
|
#else
|
||||||
|
fullscreen = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
|
if (fw) ww = fw;
|
||||||
|
if (fh) wh = fh;
|
||||||
|
}
|
||||||
|
return stbwingraph_CreateWindow(1, func, NULL, NULL, ww, wh, fullscreen, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_DestroyWindow(void *window)
|
||||||
|
{
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA);
|
||||||
|
DestroyWindow(window);
|
||||||
|
free(z);
|
||||||
|
if (stbwingraph_primary_window == window)
|
||||||
|
stbwingraph_primary_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_ShowCursor(void *window, int visible)
|
||||||
|
{
|
||||||
|
int hide;
|
||||||
|
stbwingraph__window *win;
|
||||||
|
if (!window)
|
||||||
|
window = stbwingraph_primary_window;
|
||||||
|
win = (stbwingraph__window *) GetWindowLong((HWND) window, GWL_USERDATA);
|
||||||
|
hide = !visible;
|
||||||
|
if (hide != win->hide_mouse) {
|
||||||
|
win->hide_mouse = hide;
|
||||||
|
if (!hide)
|
||||||
|
ShowCursor(TRUE);
|
||||||
|
else if (win->in_client)
|
||||||
|
ShowCursor(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float stbwingraph_GetTimestep(float minimum_time)
|
||||||
|
{
|
||||||
|
float elapsedTime;
|
||||||
|
double thisTime;
|
||||||
|
static double lastTime = -1;
|
||||||
|
|
||||||
|
if (lastTime == -1)
|
||||||
|
lastTime = timeGetTime() / 1000.0 - minimum_time;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
thisTime = timeGetTime() / 1000.0;
|
||||||
|
elapsedTime = (float) (thisTime - lastTime);
|
||||||
|
if (elapsedTime >= minimum_time) {
|
||||||
|
lastTime = thisTime;
|
||||||
|
return elapsedTime;
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
Sleep(2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_SetGLWindow(void *win)
|
||||||
|
{
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
|
||||||
|
if (z)
|
||||||
|
wglMakeCurrent(z->dc, z->rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_MakeFonts(void *window, int font_base)
|
||||||
|
{
|
||||||
|
wglUseFontBitmaps(GetDC(window ? window : stbwingraph_primary_window), 0, 256, font_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns 1 if WM_QUIT, 0 if 'func' returned 0
|
||||||
|
int stbwingraph_MainLoop(stbwingraph_update func, float mintime)
|
||||||
|
{
|
||||||
|
int needs_drawing = FALSE;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
int is_animating = TRUE;
|
||||||
|
if (mintime <= 0) mintime = 0.01f;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
is_animating = TRUE;
|
||||||
|
// wait for a message if: (a) we're animating and there's already a message
|
||||||
|
// or (b) we're not animating
|
||||||
|
if (!is_animating || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
||||||
|
stbwingraph_force_update = FALSE;
|
||||||
|
if (GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
} else {
|
||||||
|
return 1; // WM_QUIT
|
||||||
|
}
|
||||||
|
|
||||||
|
// only force a draw for certain messages...
|
||||||
|
// if I don't do this, we peg at 50% for some reason... must
|
||||||
|
// be a bug somewhere, because we peg at 100% when rendering...
|
||||||
|
// very weird... looks like NVIDIA is pumping some messages
|
||||||
|
// through our pipeline? well, ok, I guess if we can get
|
||||||
|
// non-user-generated messages we have to do this
|
||||||
|
if (!stbwingraph_force_update) {
|
||||||
|
switch (msg.message) {
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
case WM_NCMOUSEMOVE:
|
||||||
|
break;
|
||||||
|
case WM_CHAR:
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_TIMER:
|
||||||
|
case WM_SIZE:
|
||||||
|
case WM_ACTIVATE:
|
||||||
|
needs_drawing = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
needs_drawing = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if another message, process that first
|
||||||
|
// @TODO: i don't think this is working, because I can't key ahead
|
||||||
|
// in the SVT demo app
|
||||||
|
if (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// and now call update
|
||||||
|
if (needs_drawing || is_animating) {
|
||||||
|
int real=1, in_client=1;
|
||||||
|
if (stbwingraph_primary_window) {
|
||||||
|
stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(stbwingraph_primary_window, GWL_USERDATA);
|
||||||
|
if (z && !z->active) {
|
||||||
|
real = 0;
|
||||||
|
}
|
||||||
|
if (z)
|
||||||
|
in_client = z->in_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stbwingraph_primary_window)
|
||||||
|
stbwingraph_SetGLWindow(stbwingraph_primary_window);
|
||||||
|
n = func(stbwingraph_GetTimestep(mintime), real, in_client);
|
||||||
|
if (n == STBWINGRAPH_update_exit)
|
||||||
|
return 0; // update_quit
|
||||||
|
|
||||||
|
is_animating = (n != STBWINGRAPH_update_pause);
|
||||||
|
|
||||||
|
needs_drawing = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stbwingraph_SwapBuffers(void *win)
|
||||||
|
{
|
||||||
|
stbwingraph__window *z;
|
||||||
|
if (win == NULL) win = stbwingraph_primary_window;
|
||||||
|
z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
|
||||||
|
if (z && z->dc)
|
||||||
|
SwapBuffers(z->dc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STB_WINMAIN
|
||||||
|
void stbwingraph_main(void);
|
||||||
|
|
||||||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
// add spaces to either side of the string
|
||||||
|
buffer[0] = ' ';
|
||||||
|
strcpy(buffer+1, lpCmdLine);
|
||||||
|
strcat(buffer, " ");
|
||||||
|
if (strstr(buffer, " -reset ")) {
|
||||||
|
ChangeDisplaySettings(NULL, 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (strstr(buffer, " -window ") || strstr(buffer, " -windowed "))
|
||||||
|
stbwingraph_request_windowed = TRUE;
|
||||||
|
else if (strstr(buffer, " -full ") || strstr(buffer, " -fullscreen "))
|
||||||
|
stbwingraph_request_fullscreen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stbwingraph_DefineClass(hInstance, "appicon");
|
||||||
|
stbwingraph_main();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef STB_EXTERN
|
||||||
|
#ifdef STB_WINGRAPH_DISABLE_DEFINE_AT_END
|
||||||
|
#undef STB_DEFINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INCLUDE_STB_WINGRAPH_H
|
@ -42,7 +42,7 @@ RSC=rc.exe
|
|||||||
# PROP Ignore_Export_Lib 0
|
# PROP Ignore_Export_Lib 0
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "MAIN_TEST" /FD /c
|
# ADD CPP /nologo /G6 /MT /W3 /GX /Z7 /O2 /Ob2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /FD /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
@ -41,7 +41,7 @@ RSC=rc.exe
|
|||||||
# PROP Intermediate_Dir "Release"
|
# PROP Intermediate_Dir "Release"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD CPP /nologo /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
@ -41,7 +41,7 @@ RSC=rc.exe
|
|||||||
# PROP Intermediate_Dir "Release"
|
# PROP Intermediate_Dir "Release"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD CPP /nologo /W3 /GX /O2 /I "..\.." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "TT_TEST" /YX /FD /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
@ -63,8 +63,8 @@ LINK32=link.exe
|
|||||||
# PROP Output_Dir "Debug"
|
# PROP Output_Dir "Debug"
|
||||||
# PROP Intermediate_Dir "Debug\stretch_test"
|
# PROP Intermediate_Dir "Debug\stretch_test"
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
|
@ -20,9 +20,10 @@ void debug(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define BITMAP_W 256
|
#define BITMAP_W 256
|
||||||
#define BITMAP_H 400
|
#define BITMAP_H 512
|
||||||
unsigned char temp_bitmap[BITMAP_H][BITMAP_W];
|
unsigned char temp_bitmap[BITMAP_H][BITMAP_W];
|
||||||
stbtt_bakedchar cdata[256*2]; // ASCII 32..126 is 95 glyphs
|
stbtt_bakedchar cdata[256*2]; // ASCII 32..126 is 95 glyphs
|
||||||
|
stbtt_packedchar pdata[256*2];
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
stbtt_fontinfo font;
|
stbtt_fontinfo font;
|
||||||
@ -37,13 +38,11 @@ int main(int argc, char **argv)
|
|||||||
stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits!
|
stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits!
|
||||||
stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
stbi_write_png("fonttest1.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
||||||
|
|
||||||
stbtt_BakeFontBitmap(ttf_buffer,stbtt_GetFontOffsetForIndex(ttf_buffer,0), 40.0, temp_bitmap[0],BITMAP_W,BITMAP_H, 32,96, cdata); // no guarantee this fits!
|
|
||||||
|
|
||||||
{
|
{
|
||||||
stbtt_pack_context pc;
|
stbtt_pack_context pc;
|
||||||
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, NULL);
|
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
|
||||||
stbtt_PackFontRange(&pc, ttf_buffer, 0, 40.0, 32, 95, cdata);
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 32, 95, pdata);
|
||||||
stbtt_PackFontRange(&pc, ttf_buffer, 0, 40.0, 0xa0, 0x100-0xa0, cdata);
|
stbtt_PackFontRange(&pc, ttf_buffer, 0, 20.0, 0xa0, 0x100-0xa0, pdata);
|
||||||
stbtt_PackEnd(&pc);
|
stbtt_PackEnd(&pc);
|
||||||
stbi_write_png("fonttest2.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
stbi_write_png("fonttest2.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
||||||
}
|
}
|
||||||
@ -51,17 +50,18 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
stbtt_pack_context pc;
|
stbtt_pack_context pc;
|
||||||
stbtt_pack_range pr[2];
|
stbtt_pack_range pr[2];
|
||||||
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, NULL);
|
stbtt_PackBegin(&pc, temp_bitmap[0], BITMAP_W, BITMAP_H, 0, 1, NULL);
|
||||||
|
|
||||||
pr[0].chardata_for_range = cdata;
|
pr[0].chardata_for_range = pdata;
|
||||||
pr[0].first_unicode_char_in_range = 32;
|
pr[0].first_unicode_char_in_range = 32;
|
||||||
pr[0].num_chars_in_range = 95;
|
pr[0].num_chars_in_range = 95;
|
||||||
pr[0].font_size = 40.0;
|
pr[0].font_size = 20.0f;
|
||||||
pr[1].chardata_for_range = cdata+256;
|
pr[1].chardata_for_range = pdata+256;
|
||||||
pr[1].first_unicode_char_in_range = 0xa0;
|
pr[1].first_unicode_char_in_range = 0xa0;
|
||||||
pr[1].num_chars_in_range = 0x100 - 0xa0;
|
pr[1].num_chars_in_range = 0x100 - 0xa0;
|
||||||
pr[1].font_size = 40.0;
|
pr[1].font_size = 20.0f;
|
||||||
|
|
||||||
|
stbtt_PackSetOversampling(&pc, 2, 2);
|
||||||
stbtt_PackFontRanges(&pc, ttf_buffer, 0, pr, 2);
|
stbtt_PackFontRanges(&pc, ttf_buffer, 0, pr, 2);
|
||||||
stbtt_PackEnd(&pc);
|
stbtt_PackEnd(&pc);
|
||||||
stbi_write_png("fonttest3.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
stbi_write_png("fonttest3.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user