mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-15 15:41:24 +01:00
Speed up font calculation by interleaving width and height
constraints; simplify pending score display by using %dp rather than trying to fit two strings in the many possible sizes of tiles.
This commit is contained in:
parent
2dac68f3e8
commit
7d3048bb55
4 changed files with 91 additions and 68 deletions
117
wince/cedraw.c
117
wince/cedraw.c
|
@ -62,6 +62,7 @@ typedef enum {
|
||||||
,RFONTS_TRAYVAL
|
,RFONTS_TRAYVAL
|
||||||
,RFONTS_CELL
|
,RFONTS_CELL
|
||||||
,RFONTS_REM
|
,RFONTS_REM
|
||||||
|
,RFONTS_PTS
|
||||||
,RFONTS_SCORE
|
,RFONTS_SCORE
|
||||||
,RFONTS_SCORE_BOLD
|
,RFONTS_SCORE_BOLD
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ typedef struct _FontCacheEntry {
|
||||||
HFONT setFont;
|
HFONT setFont;
|
||||||
/* NOTE: indexHt >= glyphHt. fontHt will usually be > indexHt */
|
/* NOTE: indexHt >= glyphHt. fontHt will usually be > indexHt */
|
||||||
XP_U16 indexHt; /* the size we match on, the space we have */
|
XP_U16 indexHt; /* the size we match on, the space we have */
|
||||||
|
XP_U16 indexWidth; /* width we match on. 0 if we don't care */
|
||||||
XP_U16 lfHeight; /* What CE thinks is the "size" of the font we
|
XP_U16 lfHeight; /* What CE thinks is the "size" of the font we
|
||||||
found to best fill indexHt */
|
found to best fill indexHt */
|
||||||
XP_U16 glyphHt; /* range from tops to bottoms of glyphs we use */
|
XP_U16 glyphHt; /* range from tops to bottoms of glyphs we use */
|
||||||
|
@ -347,11 +349,14 @@ makeTestBuf( CEDrawCtx* dctx, XP_UCHAR* buf, XP_U16 bufLen, RFIndex index )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RFONTS_TRAYVAL:
|
case RFONTS_TRAYVAL:
|
||||||
strcpy( buf, "Pts0" ); /* all numbers the same :-) */
|
strcpy( buf, "10" ); /* all numbers the same :-) */
|
||||||
break;
|
break;
|
||||||
case RFONTS_REM:
|
case RFONTS_REM:
|
||||||
strcpy( buf, "Rem" );
|
strcpy( buf, "Rem" );
|
||||||
break;
|
break;
|
||||||
|
case RFONTS_PTS:
|
||||||
|
strcpy( buf, "123p" );
|
||||||
|
break;
|
||||||
case RFONTS_SCORE:
|
case RFONTS_SCORE:
|
||||||
case RFONTS_SCORE_BOLD:
|
case RFONTS_SCORE_BOLD:
|
||||||
strcpy( buf, "0:" );
|
strcpy( buf, "0:" );
|
||||||
|
@ -497,7 +502,8 @@ ceFillFontInfo( const CEDrawCtx* dctx, LOGFONT* fontInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
ceBestFitFont( CEDrawCtx* dctx, const XP_U16 soughtHeight,
|
||||||
|
const XP_U16 soughtWidth, /* pass 0 to ignore width */
|
||||||
RFIndex index, FontCacheEntry* fce )
|
RFIndex index, FontCacheEntry* fce )
|
||||||
{
|
{
|
||||||
wchar_t widebuf[65];
|
wchar_t widebuf[65];
|
||||||
|
@ -507,8 +513,11 @@ ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
||||||
HBRUSH white = dctx->brushes[CE_WHITE_COLOR];
|
HBRUSH white = dctx->brushes[CE_WHITE_COLOR];
|
||||||
HDC memDC = CreateCompatibleDC( NULL );
|
HDC memDC = CreateCompatibleDC( NULL );
|
||||||
HBITMAP memBM;
|
HBITMAP memBM;
|
||||||
XP_U16 testHeight;
|
XP_U16 testHeight = soughtHeight * 2;
|
||||||
HFONT testFont = NULL;
|
HFONT testFont = NULL;
|
||||||
|
/* For nextFromHeight and nextFromWidth, 0 means "found" */
|
||||||
|
XP_U16 nextFromHeight = soughtHeight;
|
||||||
|
XP_U16 nextFromWidth = soughtWidth; /* starts at 0 if width ignored */
|
||||||
|
|
||||||
char sample[65];
|
char sample[65];
|
||||||
|
|
||||||
|
@ -516,10 +525,10 @@ ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
||||||
len = 1 + strlen(sample);
|
len = 1 + strlen(sample);
|
||||||
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, sample, len, widebuf, len );
|
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, sample, len, widebuf, len );
|
||||||
|
|
||||||
memBM = CreateCompatibleBitmap( memDC, soughtHeight*2, soughtHeight*2 );
|
memBM = CreateCompatibleBitmap( memDC, testHeight, testHeight );
|
||||||
SelectObject( memDC, memBM );
|
SelectObject( memDC, memBM );
|
||||||
|
|
||||||
for ( firstPass = XP_TRUE, testHeight = soughtHeight*2; ; ) {
|
for ( firstPass = XP_TRUE; ; ) {
|
||||||
XP_U16 prevHeight = testHeight;
|
XP_U16 prevHeight = testHeight;
|
||||||
LOGFONT fontInfo;
|
LOGFONT fontInfo;
|
||||||
|
|
||||||
|
@ -536,7 +545,10 @@ ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
||||||
SelectObject( memDC, testFont );
|
SelectObject( memDC, testFont );
|
||||||
|
|
||||||
/* first time, measure all of them to determine which chars have
|
/* first time, measure all of them to determine which chars have
|
||||||
the set's high and low points */
|
the set's high and low points. Note that we need to measure
|
||||||
|
even if height already fits because that's how glyphHt and top
|
||||||
|
are calculated. */
|
||||||
|
if ( nextFromHeight > 0 || nextFromWidth > 0 ) {
|
||||||
if ( firstPass ) {
|
if ( firstPass ) {
|
||||||
ceMeasureGlyphs( dctx, memDC, widebuf, &hasMinTop,
|
ceMeasureGlyphs( dctx, memDC, widebuf, &hasMinTop,
|
||||||
&hasMaxBottom );
|
&hasMaxBottom );
|
||||||
|
@ -549,26 +561,39 @@ ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
||||||
ceMeasureGlyph( memDC, white, widebuf[hasMaxBottom],
|
ceMeasureGlyph( memDC, white, widebuf[hasMaxBottom],
|
||||||
top, bottom, &top, &bottom );
|
top, bottom, &top, &bottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
thisHeight = bottom - top + 1;
|
thisHeight = bottom - top + 1;
|
||||||
|
|
||||||
/* If we don't meet the height test, continue based on best guess
|
if ( nextFromHeight > 0 ) { /* skip if height already fits */
|
||||||
at height. Only after height looks ok do we try based on
|
/* If we don't meet the height test, continue based on
|
||||||
width */
|
best guess at height. Only after height looks ok do
|
||||||
|
we try based on width */
|
||||||
|
|
||||||
if ( thisHeight > soughtHeight ) { /* height too big... */
|
if ( thisHeight > soughtHeight ) { /* height too big... */
|
||||||
testHeight = 1 + ((testHeight * soughtHeight) / thisHeight);
|
nextFromHeight = 1 + ((testHeight * soughtHeight)
|
||||||
|
/ thisHeight);
|
||||||
} else {
|
} else {
|
||||||
if ( soughtWidth > 0 ) {
|
nextFromHeight = 0; /* we're good */
|
||||||
SIZE size;
|
}
|
||||||
GetTextExtentPoint32( memDC, widebuf, len-1, &size );
|
|
||||||
if ( size.cx > soughtWidth ) { /* width too big... */
|
|
||||||
--testHeight; /* PENDING: do this via a ratio too!! */
|
|
||||||
goto test;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( (soughtWidth > 0) && (nextFromWidth > 0) ) {
|
||||||
|
SIZE size;
|
||||||
|
GetTextExtentPoint32( memDC, widebuf, len-1, &size );
|
||||||
|
|
||||||
|
if ( size.cx > soughtWidth ) { /* width too big... */
|
||||||
|
nextFromWidth = 1 + ((testHeight * soughtWidth) / size.cx);
|
||||||
|
} else {
|
||||||
|
nextFromWidth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (0 == nextFromWidth) && (0 == nextFromHeight) ) {
|
||||||
/* we get here, we have our font */
|
/* we get here, we have our font */
|
||||||
fce->setFont = testFont;
|
fce->setFont = testFont;
|
||||||
fce->indexHt = soughtHeight;
|
fce->indexHt = soughtHeight;
|
||||||
|
fce->indexWidth = soughtWidth;
|
||||||
fce->lfHeight = testHeight;
|
fce->lfHeight = testHeight;
|
||||||
fce->offset = top;
|
fce->offset = top;
|
||||||
fce->glyphHt = thisHeight;
|
fce->glyphHt = thisHeight;
|
||||||
|
@ -577,7 +602,13 @@ ceBestFitFont( CEDrawCtx* dctx, XP_U16 soughtHeight, XP_U16 soughtWidth,
|
||||||
fce->glyphHt );
|
fce->glyphHt );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
test:
|
|
||||||
|
if ( nextFromHeight > 0 ) {
|
||||||
|
testHeight = nextFromHeight;
|
||||||
|
}
|
||||||
|
if ( nextFromWidth > 0 && nextFromWidth < testHeight ) {
|
||||||
|
testHeight = nextFromWidth;
|
||||||
|
}
|
||||||
if ( testHeight >= prevHeight ) {
|
if ( testHeight >= prevHeight ) {
|
||||||
/* guarantee progress regardless of rounding errors */
|
/* guarantee progress regardless of rounding errors */
|
||||||
testHeight = prevHeight - 1;
|
testHeight = prevHeight - 1;
|
||||||
|
@ -594,7 +625,7 @@ ceGetSizedFont( CEDrawCtx* dctx, XP_U16 height, XP_U16 width, RFIndex index )
|
||||||
{
|
{
|
||||||
FontCacheEntry* fce = &dctx->fcEntry[index];
|
FontCacheEntry* fce = &dctx->fcEntry[index];
|
||||||
if ( (0 != height) /* 0 means use what we have */
|
if ( (0 != height) /* 0 means use what we have */
|
||||||
&& fce->indexHt != height ) {
|
&& (fce->indexHt != height || fce->indexWidth != width) ) {
|
||||||
XP_LOGF( "%s: no match for %s (have %d, want %d (width %d) "
|
XP_LOGF( "%s: no match for %s (have %d, want %d (width %d) "
|
||||||
"so recalculating",
|
"so recalculating",
|
||||||
__func__, RFI2Str(index), fce->indexHt, height, width );
|
__func__, RFI2Str(index), fce->indexHt, height, width );
|
||||||
|
@ -1388,25 +1419,21 @@ DRAW_FUNC_NAME(score_pendingScore)( DrawCtx* p_dctx, const XP_Rect* xprect,
|
||||||
XP_S16 score, XP_U16 playerNum,
|
XP_S16 score, XP_U16 playerNum,
|
||||||
CellFlags flags )
|
CellFlags flags )
|
||||||
{
|
{
|
||||||
# define PTS_OFFSET 2
|
|
||||||
CEDrawCtx* dctx = (CEDrawCtx*)p_dctx;
|
CEDrawCtx* dctx = (CEDrawCtx*)p_dctx;
|
||||||
CEAppGlobals* globals = dctx->globals;
|
CEAppGlobals* globals = dctx->globals;
|
||||||
HDC hdc = globals->hdc;
|
HDC hdc = globals->hdc;
|
||||||
|
|
||||||
wchar_t widebuf[5];
|
wchar_t widebuf[5];
|
||||||
XP_UCHAR buf[5];
|
|
||||||
RECT rt;
|
RECT rt;
|
||||||
XP_Bool focussed = TREAT_AS_CURSOR(dctx,flags);
|
XP_Bool focussed = TREAT_AS_CURSOR(dctx,flags);
|
||||||
XP_U16 bkIndex = focussed ? CE_FOCUS_COLOR : CE_BKG_COLOR;
|
XP_U16 bkIndex = focussed ? CE_FOCUS_COLOR : CE_BKG_COLOR;
|
||||||
const FontCacheEntry* fce;
|
const FontCacheEntry* fce;
|
||||||
HFONT oldFont;
|
HFONT oldFont;
|
||||||
XP_U16 valHt;
|
XP_U16 spareHt;
|
||||||
XP_U16 charHt;
|
|
||||||
|
|
||||||
ceGetCharValHts( dctx, xprect, &charHt, &valHt );
|
fce = ceGetSizedFont( dctx, xprect->height, xprect->width, RFONTS_PTS );
|
||||||
|
spareHt = xprect->height - fce->glyphHt;
|
||||||
|
|
||||||
/* Little Pts first up top */
|
|
||||||
fce = ceGetSizedFont( dctx, valHt, 0, RFONTS_TRAYVAL );
|
|
||||||
oldFont = SelectObject( hdc, fce->setFont );
|
oldFont = SelectObject( hdc, fce->setFont );
|
||||||
|
|
||||||
SetTextColor( hdc,
|
SetTextColor( hdc,
|
||||||
|
@ -1417,31 +1444,19 @@ DRAW_FUNC_NAME(score_pendingScore)( DrawCtx* p_dctx, const XP_Rect* xprect,
|
||||||
ceClipToRect( hdc, &rt );
|
ceClipToRect( hdc, &rt );
|
||||||
FillRect( hdc, &rt, dctx->brushes[bkIndex] );
|
FillRect( hdc, &rt, dctx->brushes[bkIndex] );
|
||||||
|
|
||||||
ceDrawTextClipped( hdc, L"Pts", -1, XP_FALSE, fce,
|
|
||||||
xprect->left + PTS_OFFSET, xprect->top + PTS_OFFSET,
|
|
||||||
xprect->width - (PTS_OFFSET*2), DT_CENTER );
|
|
||||||
|
|
||||||
|
|
||||||
fce = ceGetSizedFont( dctx, charHt, 0, RFONTS_TRAY );
|
|
||||||
(void)SelectObject( hdc, fce->setFont );
|
|
||||||
|
|
||||||
if ( score < 0 ) {
|
if ( score < 0 ) {
|
||||||
buf[0] = '?';
|
widebuf[0] = '?';
|
||||||
buf[1] = '?';
|
widebuf[1] = '?';
|
||||||
buf[2] = '\0';
|
widebuf[2] = '\0';
|
||||||
} else {
|
} else {
|
||||||
sprintf( buf, "%d", score );
|
swprintf( widebuf, L"%dp", score );
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, buf, -1,
|
ceDrawTextClipped( hdc, widebuf, -1, XP_FALSE, fce,
|
||||||
widebuf, VSIZE(widebuf) );
|
xprect->left, xprect->top + (spareHt/2),
|
||||||
ceDrawTextClipped( hdc, widebuf, -1, XP_TRUE, fce,
|
xprect->width, DT_CENTER );
|
||||||
xprect->left + PTS_OFFSET,
|
|
||||||
xprect->top + xprect->height - charHt,
|
|
||||||
xprect->width - (PTS_OFFSET*2), DT_CENTER );
|
|
||||||
|
|
||||||
SelectObject( hdc, oldFont );
|
(void)SelectObject( hdc, oldFont );
|
||||||
# undef PTS_OFFSET
|
|
||||||
} /* ce_draw_score_pendingScore */
|
} /* ce_draw_score_pendingScore */
|
||||||
|
|
||||||
DLSTATIC void
|
DLSTATIC void
|
||||||
|
@ -1786,6 +1801,7 @@ ce_draw_toStream( const CEDrawCtx* dctx, XWStreamCtxt* stream )
|
||||||
const FontCacheEntry* fce = &dctx->fcEntry[ii];
|
const FontCacheEntry* fce = &dctx->fcEntry[ii];
|
||||||
stream_putU8( stream, fce->indexHt );
|
stream_putU8( stream, fce->indexHt );
|
||||||
if ( fce->indexHt > 0 ) {
|
if ( fce->indexHt > 0 ) {
|
||||||
|
stream_putU8( stream, fce->indexWidth );
|
||||||
stream_putU8( stream, fce->lfHeight );
|
stream_putU8( stream, fce->lfHeight );
|
||||||
stream_putU8( stream, fce->offset );
|
stream_putU8( stream, fce->offset );
|
||||||
stream_putU8( stream, fce->glyphHt );
|
stream_putU8( stream, fce->glyphHt );
|
||||||
|
@ -1795,7 +1811,7 @@ ce_draw_toStream( const CEDrawCtx* dctx, XWStreamCtxt* stream )
|
||||||
|
|
||||||
//#define DROP_CACHE
|
//#define DROP_CACHE
|
||||||
void
|
void
|
||||||
ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream )
|
ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream, XP_U8 flags )
|
||||||
{
|
{
|
||||||
XP_U16 ii;
|
XP_U16 ii;
|
||||||
XP_U16 nEntries;
|
XP_U16 nEntries;
|
||||||
|
@ -1809,6 +1825,9 @@ ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream )
|
||||||
|
|
||||||
fce.indexHt = (XP_U16)stream_getU8( stream );
|
fce.indexHt = (XP_U16)stream_getU8( stream );
|
||||||
if ( fce.indexHt > 0 ) {
|
if ( fce.indexHt > 0 ) {
|
||||||
|
if ( flags >= CE_GAMEFILE_VERSION2 ) {
|
||||||
|
fce.indexWidth = (XP_U16)stream_getU8( stream );
|
||||||
|
}
|
||||||
fce.lfHeight = (XP_U16)stream_getU8( stream );
|
fce.lfHeight = (XP_U16)stream_getU8( stream );
|
||||||
fce.offset = (XP_U16)stream_getU8( stream );
|
fce.offset = (XP_U16)stream_getU8( stream );
|
||||||
fce.glyphHt = (XP_U16)stream_getU8( stream );
|
fce.glyphHt = (XP_U16)stream_getU8( stream );
|
||||||
|
@ -1823,8 +1842,10 @@ ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream )
|
||||||
ceFillFontInfo( dctx, &fontInfo, fce.lfHeight );
|
ceFillFontInfo( dctx, &fontInfo, fce.lfHeight );
|
||||||
fce.setFont = CreateFontIndirect( &fontInfo );
|
fce.setFont = CreateFontIndirect( &fontInfo );
|
||||||
XP_ASSERT( !!fce.setFont );
|
XP_ASSERT( !!fce.setFont );
|
||||||
|
if ( !!fce.setFont ) {
|
||||||
XP_MEMCPY( &dctx->fcEntry[ii], &fce, sizeof(dctx->fcEntry[ii]) );
|
XP_MEMCPY( &dctx->fcEntry[ii], &fce,
|
||||||
|
sizeof(dctx->fcEntry[ii]) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,6 @@ HBRUSH ce_draw_getFocusBrush( const CEDrawCtx* dctx );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ce_draw_toStream( const CEDrawCtx* dctx, XWStreamCtxt* stream );
|
void ce_draw_toStream( const CEDrawCtx* dctx, XWStreamCtxt* stream );
|
||||||
void ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream );
|
void ce_draw_fromStream( CEDrawCtx* dctx, XWStreamCtxt* stream, XP_U8 flags );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1129,8 +1129,8 @@ ceLoadSavedGame( CEAppGlobals* globals )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
if ( flags >= CE_GAMEFILE_VERSION ) {
|
if ( flags >= CE_GAMEFILE_VERSION1 ) {
|
||||||
ce_draw_fromStream( globals->draw, stream );
|
ce_draw_fromStream( globals->draw, stream, flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_DEBUGF( "calling game_makeFromStream" );
|
XP_DEBUGF( "calling game_makeFromStream" );
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
#include "cesockwr.h"
|
#include "cesockwr.h"
|
||||||
|
|
||||||
#define LCROSSWORDS_DIR_NODBG L"Crosswords"
|
#define LCROSSWORDS_DIR_NODBG L"Crosswords"
|
||||||
#define CE_GAMEFILE_VERSION 0x01 /* means draw gets to save/restore */
|
#define CE_GAMEFILE_VERSION1 0x01 /* means draw gets to save/restore */
|
||||||
|
#define CE_GAMEFILE_VERSION2 0x02 /* save/restore includes width */
|
||||||
|
#define CE_GAMEFILE_VERSION CE_GAMEFILE_VERSION2
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define CROSSWORDS_DIR "Cross_dbg"
|
# define CROSSWORDS_DIR "Cross_dbg"
|
||||||
# define LCROSSWORDS_DIR L"Cross_dbg"
|
# define LCROSSWORDS_DIR L"Cross_dbg"
|
||||||
|
|
Loading…
Reference in a new issue