From 9e768713066af94340bcde2250b14f3c89034acf Mon Sep 17 00:00:00 2001 From: ehouse Date: Thu, 7 Jul 2005 03:46:07 +0000 Subject: [PATCH] (conditionally) modify dicts to support getting height of platform glyphs, pass into drawing code so can be fetched and cached, and implement for Palm. This is to allow drawing glyphs (like Danish's A-with-circle) that are taller than normal without the visual padding the rest can have. So far works for 68K/non-highres. Will not compile for ARM yet. --- xwords4/common/board.c | 6 ++- xwords4/common/dictnry.c | 20 ++++++++++ xwords4/common/dictnry.h | 28 ++++++++++++- xwords4/common/draw.h | 22 ++++++++--- xwords4/palm/palmdict.c | 85 +++++++++++++++++++++++++++++++++++++++- xwords4/palm/palmdraw.c | 76 ++++++++++++++++++++++++++++++----- xwords4/palm/palmmain.h | 5 +++ 7 files changed, 223 insertions(+), 19 deletions(-) diff --git a/xwords4/common/board.c b/xwords4/common/board.c index d3543d7c3..74c887c3a 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -1006,7 +1006,9 @@ board_draw( BoardCtxt* board ) drawScoreBoard( board ); if ( board->needsDrawing - && draw_boardBegin( board->draw, &board->boardBounds, + && draw_boardBegin( board->draw, + model_getDictionary( board->model ), + &board->boardBounds, board->focussed == OBJ_BOARD ) ) { XP_Bool allDrawn = XP_TRUE; @@ -1681,7 +1683,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks ) bonus = util_getSquareBonus( board->util, model, col, row ); hintAtts = figureHintAtts( board, col, row ); return draw_drawCell( board->draw, &cellRect, textP, bitmap, - owner, bonus, hintAtts, isBlank, invert, + tile, owner, bonus, hintAtts, isBlank, invert, (isEmpty && (col==board->star_row) && (row==board->star_row))); } diff --git a/xwords4/common/dictnry.c b/xwords4/common/dictnry.c index 3b29a22b3..1fd0b33c8 100644 --- a/xwords4/common/dictnry.c +++ b/xwords4/common/dictnry.c @@ -282,6 +282,15 @@ common_destructor( DictionaryCtxt* dict ) XP_FREE( dict->mpool, dict ); } /* dict */ +#if defined TALL_FONTS && defined DEBUG +static void +dict_getFaceBounds_assert( DictionaryCtxt* dict, XP_UCHAR i, + XP_FontBounds* bounds ) +{ + XP_ASSERT(0); +} +#endif + void dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ) { @@ -293,6 +302,9 @@ dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ) XP_ASSERT( !dict->destructor ); dict->destructor = common_destructor; dict->func_dict_getShortName = dict_getName; /* default */ +#if defined TALL_FONTS && defined DEBUG + dict->func_dict_getFaceBounds = dict_getFaceBounds_assert; +#endif nFaces = (XP_U8)stream_getBits( stream, 6 ); maxCountBits = (XP_U16)stream_getBits( stream, 3 ); @@ -368,6 +380,14 @@ dict_getFaceBitmap( DictionaryCtxt* dict, Tile tile, XP_Bool isLarge ) return isLarge? bitmaps->largeBM:bitmaps->smallBM; } /* dict_getFaceBitmap */ +#ifdef TALL_FONTS +XP_LangCode +dict_getLangCode( DictionaryCtxt* dict ) +{ + return dict->langCode; +} +#endif + #ifdef STUBBED_DICT #define BLANK_FACE '\0' diff --git a/xwords4/common/dictnry.h b/xwords4/common/dictnry.h index 6d5b2fba9..2eb628aef 100644 --- a/xwords4/common/dictnry.h +++ b/xwords4/common/dictnry.h @@ -54,6 +54,20 @@ typedef struct SpecialBitmaps { XP_Bitmap smallBM; } SpecialBitmaps; +#ifdef TALL_FONTS + /* This guy's used to vertically center glyphs within cells. The impetus + is the circle-A char in Danish which starts higher than most and must + be drawn (on Palm) starting at a smaller y value if the bottom is to be + visible. */ +typedef struct XP_FontBounds { + XP_S16 topOffset; /* how many pixels from the top of the drawing + area is the first pixel set in the glyph */ + XP_U16 height; /* How many rows tall is the image? */ +} XP_FontBounds; + +typedef XP_U16 XP_LangCode; /* corresponds to the XLOC_HEADER field in + dawg/./info.txt files */ +#endif struct DictionaryCtxt { void (*destructor)( DictionaryCtxt* dict ); @@ -61,6 +75,10 @@ struct DictionaryCtxt { array_edge* (*func_edge_for_index)( DictionaryCtxt* dict, XP_U32 index ); array_edge* (*func_dict_getTopEdge)( DictionaryCtxt* dict ); XP_UCHAR* (*func_dict_getShortName)( DictionaryCtxt* dict ); +#ifdef TALL_FONTS + void (*func_dict_getFaceBounds)( DictionaryCtxt* dict, Tile tile, + XP_FontBounds* bounds ); +#endif array_edge* topEdge; array_edge* base; /* the physical beginning of the dictionary; not @@ -72,6 +90,10 @@ struct DictionaryCtxt { SpecialBitmaps* bitmaps; XP_UCHAR** chars; +#ifdef TALL_FONTS + XP_LangCode langCode; +#endif + XP_U8 nFaces; #ifdef NODE_CAN_4 XP_U8 nodeSize; @@ -115,7 +137,7 @@ struct DictionaryCtxt { #define dict_edge_for_index(d, i) (*((d)->func_edge_for_index))((d), (i)) #define dict_getTopEdge(d) (*((d)->func_dict_getTopEdge))(d) #define dict_getShortName(d) (*((d)->func_dict_getShortName))(d) - +#define dict_getFaceBounds(d,n,p) (*((d)->func_dict_getFaceBounds))((d),(n),(p)) XP_Bool dict_tilesAreSame( DictionaryCtxt* dict1, DictionaryCtxt* dict2 ); @@ -135,6 +157,10 @@ XP_Bool dict_faceIsBitmap( DictionaryCtxt* dict, Tile tile ); XP_Bitmap dict_getFaceBitmap( DictionaryCtxt* dict, Tile tile, XP_Bool isLarge ); +#ifdef TALL_FONTS +XP_LangCode dict_getLangCode( DictionaryCtxt* dict ); +#endif + void dict_writeToStream( DictionaryCtxt* ctxt, XWStreamCtxt* stream ); void dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ); diff --git a/xwords4/common/draw.h b/xwords4/common/draw.h index 49e15c093..90f25ba95 100644 --- a/xwords4/common/draw.h +++ b/xwords4/common/draw.h @@ -69,8 +69,8 @@ typedef struct DrawCtxVTable { void (*m_draw_destroyCtxt)( DrawCtx* dctx ); - XP_Bool (*m_draw_boardBegin)( DrawCtx* dctx, XP_Rect* rect, - XP_Bool hasfocus ); + XP_Bool (*m_draw_boardBegin)( DrawCtx* dctx, DictionaryCtxt* dict, + XP_Rect* rect, XP_Bool hasfocus ); void (*m_draw_boardFinished)( DrawCtx* dctx ); XP_Bool (*m_draw_vertScrollBoard)(DrawCtx* dctx, XP_Rect* rect, @@ -106,6 +106,9 @@ typedef struct DrawCtxVTable { XP_Bool (*m_draw_drawCell)( DrawCtx* dctx, XP_Rect* rect, /* at least one of these two will be null */ XP_UCHAR* text, XP_Bitmap bitmap, +#ifdef TALL_FONTS + Tile tile, +#endif XP_S16 owner, /* -1 means don't use */ XWBonusType bonus, HintAtts hintAtts, XP_Bool isBlank, XP_Bool highlight, @@ -150,8 +153,8 @@ struct DrawCtx { #define draw_destroyCtxt(dc) \ (dc)->vtable->m_draw_destroyCtxt(dc) -#define draw_boardBegin( dc, r, f ) \ - (dc)->vtable->m_draw_boardBegin((dc), (r), (f)) +#define draw_boardBegin( dc, d, r, f ) \ + (dc)->vtable->m_draw_boardBegin((dc), (d), (r), (f)) #define draw_boardFinished( dc ) \ (dc)->vtable->m_draw_boardFinished(dc) @@ -191,9 +194,16 @@ struct DrawCtx { /* (dc)->vtable->m_draw_frameBoard((dc),(rect)) */ /* #define draw_frameTray( dc, rect ) (dc)->vtable->m_draw_frameTray((dc),(rect)) */ -#define draw_drawCell( dc, rect, txt, bmap, o, bon, hi, bl, h, s ) \ +#ifdef TALL_FONTS +/* Both of these have same sig, but one drops the Tile arg */ +# define draw_drawCell( dc, rect, txt, bmap, t, o, bon, hi, bl, h, s ) \ + (dc)->vtable->m_draw_drawCell((dc),(rect),(txt),(bmap),(t),(o),(bon),\ + (hi),(bl),(h),(s)) +#else +# define draw_drawCell( dc, rect, txt, bmap, t, o, bon, hi, bl, h, s ) \ (dc)->vtable->m_draw_drawCell((dc),(rect),(txt),(bmap),(o),(bon),\ - (hi),(bl),(h),(s)) + (hi),(bl),(h),(s)) +#endif #define draw_invertCell( dc, rect ) \ (dc)->vtable->m_draw_invertCell((dc),(rect)) diff --git a/xwords4/palm/palmdict.c b/xwords4/palm/palmdict.c index 5c92e7767..829f45bb0 100644 --- a/xwords4/palm/palmdict.c +++ b/xwords4/palm/palmdict.c @@ -1,6 +1,6 @@ /* -*-mode: C; fill-column: 78; c-basic-offset: 4;-*- */ /* - * Copyright 1997-2001 by Eric House (fixin@peak.org). All rights reserved. + * Copyright 1997-2005 by Eric House (fixin@peak.org). All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -64,6 +64,10 @@ static void setupSpecials( MPFORMAL PalmDictionaryCtxt* ctxt, Xloc_specialEntry* specialStart, XP_U16 nSpecials ); static array_edge* palm_dict_edge_for_index_multi( DictionaryCtxt* dict, XP_U32 index ); +#ifdef TALL_FONTS +static void palm_dict_getFaceBounds( DictionaryCtxt* dict, Tile tile, + XP_FontBounds* bounds ); +#endif DictionaryCtxt* palm_dictionary_make( MPFORMAL PalmAppGlobals* globals, @@ -186,6 +190,10 @@ palm_dictionary_make( MPFORMAL PalmAppGlobals* globals, charPtr = (unsigned char*)MemHandleLock(tmpH); XP_ASSERT( MemHandleLockCount( tmpH ) == 1 ); // use 2; ARM thinks sizeof(Xloc_header) is 4. +#ifdef TALL_FONTS + ctxt->super.langCode = XP_NTOHS(*(XP_U16*)charPtr); + XP_LOGF( "read langCode of %x", ctxt->super.langCode ); +#endif ctxt->super.countsAndValues = charPtr + 2; /* for those dicts with special chars */ @@ -291,6 +299,10 @@ palm_dictionary_make( MPFORMAL PalmAppGlobals* globals, #endif ctxt->super.func_edge_for_index = palm_dict_edge_for_index_multi; +#ifdef TALL_FONTS + ctxt->super.func_dict_getFaceBounds + = palm_dict_getFaceBounds; +#endif } } @@ -376,6 +388,77 @@ setupSpecials( MPFORMAL PalmDictionaryCtxt* ctxt, XP_LOGF( "setupSpecials done" ); } /* setupSpecials */ +#ifdef TALL_FONTS +#define BMP_WIDTH 16 +#define BMP_HT 16 +static void +measureFace( XP_CHAR16 face, XP_U16* top, XP_U16* bottom ) +{ + WinHandle win; + BitmapType* bitmap; + Coord x, y; + Err err; + XP_Bool gotIt; + + bitmap = BmpCreate( BMP_WIDTH, BMP_HT, 1, NULL, &err ); + if ( err == errNone ) { + win = WinCreateBitmapWindow( bitmap, &err ); + if ( err == errNone ) { + WinHandle oldWin = WinSetDrawWindow( win ); + WinSetBackColor( 0 ); /* white */ + (void)WinSetTextColor( 1 ); /* black */ + (void)WinSetDrawMode( winOverlay ); + + WinDrawChar( face, 0, 0 ); + + /* Scan from top for top, then from bottom for botton */ + gotIt = XP_FALSE; + for ( y = 0; !gotIt && y < BMP_HT; ++y ) { + for ( x = 0; !gotIt && x < BMP_WIDTH; ++x ) { + IndexedColorType pxl = WinGetPixel( x, y ); + if ( pxl != 0 ) { + *top = y; + gotIt = XP_TRUE; + } + } + } + + gotIt = XP_FALSE; + for ( y = BMP_HT - 1; !gotIt && y >= 0; --y ) { + for ( x = 0; !gotIt && x < BMP_WIDTH; ++x ) { + IndexedColorType pxl = WinGetPixel( x, y ); + if ( pxl != 0 ) { + *bottom = y; + gotIt = XP_TRUE; + } + } + } + + (void)WinSetDrawWindow( oldWin ); + WinDeleteWindow( win, false ); + } + BmpDelete( bitmap ); + } +} /* measureFace */ + +static void +palm_dict_getFaceBounds( DictionaryCtxt* ctxt, Tile tile, + XP_FontBounds* bounds ) +{ + XP_CHAR16 face = ctxt->faces16[tile]; + + if ( !IS_SPECIAL(face) ) { + XP_U16 top, bottom; + measureFace( face, &top, &bottom ); + bounds->topOffset = top; + bounds->height = bottom - top + 1; + + XP_LOGF( "Char %c ranges from %d to %d", + (char)face, top, bottom ); + } +} /* palm_dict_getFaceBounds */ +#endif + static void palm_dictionary_destroy( DictionaryCtxt* dict ) { diff --git a/xwords4/palm/palmdraw.c b/xwords4/palm/palmdraw.c index 7ee0c82c5..b8d75740b 100644 --- a/xwords4/palm/palmdraw.c +++ b/xwords4/palm/palmdraw.c @@ -39,6 +39,9 @@ static XP_Bool palm_common_draw_drawCell( DrawCtx* p_dctx, XP_Rect* rect, XP_UCHAR* letters, XP_Bitmap bitmap, +#ifdef TALL_FONTS + Tile tile, +#endif XP_S16 owner, XWBonusType bonus, HintAtts hintAtts, XP_Bool isBlank, XP_Bool isPending, XP_Bool isStar ); @@ -129,20 +132,55 @@ bitmapInRect( PalmDrawCtx* dctx, Int16 resID, XP_Rect* rectP ) drawBitmapAt( (DrawCtx*)dctx, resID, left, top ); } /* bitmapInRect */ +#ifdef TALL_FONTS +static void +checkFontOffsets( PalmDrawCtx* dctx, DictionaryCtxt* dict ) +{ + XP_LangCode code; + XP_U16 nFaces; + Tile tile; + + code = dict_getLangCode( dict ); + if ( code != dctx->fontLangCode ) { + + if ( !!dctx->fontLangInfo ) { + XP_FREE( dctx->mpool, dctx->fontLangInfo ); + } + + nFaces = dict_numTileFaces( dict ); + dctx->fontLangInfo = XP_MALLOC( dctx->mpool, + nFaces * sizeof(*dctx->fontLangInfo) ); + + for ( tile = 0; tile < nFaces; ++tile ) { + dict_getFaceBounds( dict, tile, &dctx->fontLangInfo[tile] ); + } + + dctx->fontLangCode = code; + } +} +#else +# define checkFontOffsets(a,b) +#endif + static XP_Bool -palm_common_draw_boardBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool hasfocus ) +palm_common_draw_boardBegin( DrawCtx* p_dctx, DictionaryCtxt* dict, + XP_Rect* rect, XP_Bool hasfocus ) { PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx; PalmAppGlobals* globals = dctx->globals; if ( !globals->gState.showGrid ) { WinDrawRectangleFrame(rectangleFrame, (RectangleType*)rect); } + + checkFontOffsets( dctx, dict ); + return XP_TRUE; } /* palm_common_draw_boardBegin */ #ifdef COLOR_SUPPORT static XP_Bool -palm_clr_draw_boardBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool hasfocus ) +palm_clr_draw_boardBegin( DrawCtx* p_dctx, DictionaryCtxt* dict, + XP_Rect* rect, XP_Bool hasfocus ) { PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx; @@ -154,7 +192,7 @@ palm_clr_draw_boardBegin( DrawCtx* p_dctx, XP_Rect* rect, XP_Bool hasfocus ) HIGHRES_PUSH_NOPOP(dctx); - palm_common_draw_boardBegin( p_dctx, rect, hasfocus ); + palm_common_draw_boardBegin( p_dctx, dict, rect, hasfocus ); return XP_TRUE; } /* palm_clr_draw_boardBegin */ @@ -168,6 +206,9 @@ palm_clr_draw_boardFinished( DrawCtx* p_dctx ) static XP_Bool palm_clr_draw_drawCell( DrawCtx* p_dctx, XP_Rect* rect, XP_UCHAR* letters, XP_Bitmap bitmap, +#ifdef TALL_FONTS + Tile tile, +#endif XP_S16 owner, XWBonusType bonus, HintAtts hintAtts, XP_Bool isBlank, XP_Bool isPending, XP_Bool isStar ) @@ -200,8 +241,12 @@ palm_clr_draw_drawCell( DrawCtx* p_dctx, XP_Rect* rect, WinSetTextColor( color ); } - return palm_common_draw_drawCell( p_dctx, rect, letters, bitmap, owner, - bonus, hintAtts, isBlank, isPending, isStar ); + return palm_common_draw_drawCell( p_dctx, rect, letters, bitmap, +#ifdef TALL_FONTS + tile, +#endif + owner, bonus, hintAtts, isBlank, isPending, + isStar ); } /* palm_clr_draw_drawCell */ static void @@ -257,6 +302,9 @@ palmDrawHintBorders( XP_Rect* rect, HintAtts hintAtts ) static XP_Bool palm_common_draw_drawCell( DrawCtx* p_dctx, XP_Rect* rect, XP_UCHAR* letters, XP_Bitmap bitmap, +#ifdef TALL_FONTS + Tile tile, +#endif XP_S16 owner, XWBonusType bonus, HintAtts hintAtts, XP_Bool isBlank, XP_Bool isPending, XP_Bool isStar ) { @@ -309,8 +357,14 @@ palm_common_draw_drawCell( DrawCtx* p_dctx, XP_Rect* rect, len = XP_STRLEN( (const char*)letters ); if ( len > 0 ) { XP_S16 strWidth = FntCharsWidth( (const char*)letters, len ); - XP_U16 x = localR.left + ((localR.width-strWidth) / 2); - XP_U16 y = localR.top-1; + XP_U16 x, y; + x = localR.left + ((localR.width-strWidth) / 2); +#ifdef TALL_FONTS + y = localR.top - dctx->fontLangInfo[tile].topOffset; + y += (localR.height - dctx->fontLangInfo[tile].height) / 2; +#else + y = localR.top-1; +#endif if ( len == 1 ) { ++x; } @@ -522,10 +576,9 @@ palm_draw_drawTile( DrawCtx* p_dctx, XP_Rect* rect, if ( *letters != LETTER_NONE ) { /* blank */ RectangleType charRect = {{0,0}, {CHARRECT_WIDTH*2, CHARRECT_HEIGHT*2}}; - FontID curFont = FntGetFont(); WinHandle curWind; WinHandle offScreenCharWin = dctx->offScreenCharWin; - FntSetFont( largeFont ); + FontID curFont = FntSetFont( largeFont ); XP_ASSERT( !!offScreenCharWin ); curWind = WinSetDrawWindow( offScreenCharWin ); @@ -1369,5 +1422,10 @@ palm_drawctxt_destroy( DrawCtx* p_dctx ) WinDeleteWindow( dctx->offScreenCharWin, false ); XP_FREE( dctx->mpool, p_dctx->vtable ); +#ifdef TALL_FONTS + if ( !!dctx->fontLangInfo ) { + XP_FREE( dctx->mpool, dctx->fontLangInfo ); + } +#endif XP_FREE( dctx->mpool, dctx ); } /* palm_drawctxt_destroy */ diff --git a/xwords4/palm/palmmain.h b/xwords4/palm/palmmain.h index 4004b269e..bdb07b946 100644 --- a/xwords4/palm/palmmain.h +++ b/xwords4/palm/palmmain.h @@ -80,6 +80,11 @@ typedef struct PalmDrawCtx { XP_Bool oneDotFiveAvail; #endif +#ifdef TALL_FONTS + XP_LangCode fontLangCode; + XP_FontBounds* fontLangInfo; +#endif + union { struct { XP_U8 reserved; /* make CW compiler happy */