1999-02-02 06:13:40 -05:00
|
|
|
|
/*
|
|
|
|
|
* tkWinFont.c --
|
|
|
|
|
*
|
|
|
|
|
* Contains the Windows implementation of the platform-independant
|
|
|
|
|
* font package interface.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
|
|
|
|
* Copyright (c) 1994 Software Research Associates, Inc.
|
|
|
|
|
*
|
|
|
|
|
* See the file "license.terms" for information on usage and redistribution
|
|
|
|
|
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
|
*
|
|
|
|
|
* SCCS: @(#) tkWinFont.c 1.20 97/05/14 15:45:30
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "tkWinInt.h"
|
|
|
|
|
#include "tkFont.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The following structure represents Windows' implementation of a font.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct WinFont {
|
|
|
|
|
TkFont font; /* Stuff used by generic font package. Must
|
|
|
|
|
* be first in structure. */
|
|
|
|
|
HFONT hFont; /* Windows information about font. */
|
|
|
|
|
HWND hwnd; /* Toplevel window of application that owns
|
|
|
|
|
* this font, used for getting HDC. */
|
|
|
|
|
} WinFont;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The following structure is used as to map between the Tcl strings
|
|
|
|
|
* that represent the system fonts and the numbers used by Windows.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static TkStateMap systemMap[] = {
|
|
|
|
|
{ANSI_FIXED_FONT, "ansifixed"},
|
|
|
|
|
{ANSI_VAR_FONT, "ansi"},
|
|
|
|
|
{DEVICE_DEFAULT_FONT, "device"},
|
|
|
|
|
{OEM_FIXED_FONT, "oemfixed"},
|
|
|
|
|
{SYSTEM_FIXED_FONT, "systemfixed"},
|
|
|
|
|
{SYSTEM_FONT, "system"},
|
|
|
|
|
{-1, NULL}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define ABS(x) (((x) < 0) ? -(x) : (x))
|
|
|
|
|
|
|
|
|
|
static TkFont * AllocFont _ANSI_ARGS_((TkFont *tkFontPtr,
|
|
|
|
|
Tk_Window tkwin, HFONT hFont));
|
|
|
|
|
static char * GetProperty _ANSI_ARGS_((CONST TkFontAttributes *faPtr,
|
|
|
|
|
CONST char *option));
|
|
|
|
|
static int CALLBACK WinFontFamilyEnumProc _ANSI_ARGS_((ENUMLOGFONT *elfPtr,
|
|
|
|
|
NEWTEXTMETRIC *ntmPtr, int fontType,
|
|
|
|
|
LPARAM lParam));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpGetNativeFont --
|
|
|
|
|
*
|
|
|
|
|
* Map a platform-specific native font name to a TkFont.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is a pointer to a TkFont that represents the
|
|
|
|
|
* native font. If a native font by the given name could not be
|
|
|
|
|
* found, the return value is NULL.
|
|
|
|
|
*
|
|
|
|
|
* Every call to this procedure returns a new TkFont structure,
|
|
|
|
|
* even if the name has already been seen before. The caller should
|
|
|
|
|
* call TkpDeleteFont() when the font is no longer needed.
|
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for initializing the memory associated
|
|
|
|
|
* with the generic TkFont when this function returns and releasing
|
|
|
|
|
* the contents of the generic TkFont before calling TkpDeleteFont().
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
TkFont *
|
|
|
|
|
TkpGetNativeFont(tkwin, name)
|
|
|
|
|
Tk_Window tkwin; /* For display where font will be used. */
|
|
|
|
|
CONST char *name; /* Platform-specific font name. */
|
|
|
|
|
{
|
|
|
|
|
int object;
|
|
|
|
|
HFONT hFont;
|
|
|
|
|
|
|
|
|
|
object = TkFindStateNum(NULL, NULL, systemMap, name);
|
|
|
|
|
if (object < 0) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
hFont = GetStockObject(object);
|
|
|
|
|
if (hFont == NULL) {
|
|
|
|
|
panic("TkpGetNativeFont: can't allocate stock font");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return AllocFont(NULL, tkwin, hFont);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpGetFontFromAttributes --
|
|
|
|
|
*
|
|
|
|
|
* Given a desired set of attributes for a font, find a font with
|
|
|
|
|
* the closest matching attributes.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is a pointer to a TkFont that represents the
|
|
|
|
|
* font with the desired attributes. If a font with the desired
|
|
|
|
|
* attributes could not be constructed, some other font will be
|
|
|
|
|
* substituted automatically. NULL is never returned.
|
|
|
|
|
*
|
|
|
|
|
* Every call to this procedure returns a new TkFont structure,
|
|
|
|
|
* even if the specified attributes have already been seen before.
|
|
|
|
|
* The caller should call TkpDeleteFont() to free the platform-
|
|
|
|
|
* specific data when the font is no longer needed.
|
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for initializing the memory associated
|
|
|
|
|
* with the generic TkFont when this function returns and releasing
|
|
|
|
|
* the contents of the generic TkFont before calling TkpDeleteFont().
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
TkFont *
|
|
|
|
|
TkpGetFontFromAttributes(tkFontPtr, tkwin, faPtr)
|
|
|
|
|
TkFont *tkFontPtr; /* If non-NULL, store the information in
|
|
|
|
|
* this existing TkFont structure, rather than
|
|
|
|
|
* allocating a new structure to hold the
|
|
|
|
|
* font; the existing contents of the font
|
|
|
|
|
* will be released. If NULL, a new TkFont
|
|
|
|
|
* structure is allocated. */
|
|
|
|
|
Tk_Window tkwin; /* For display where font will be used. */
|
|
|
|
|
CONST TkFontAttributes *faPtr; /* Set of attributes to match. */
|
|
|
|
|
{
|
|
|
|
|
LOGFONT lf;
|
|
|
|
|
HFONT hFont;
|
|
|
|
|
Window window;
|
|
|
|
|
HWND hwnd;
|
|
|
|
|
HDC hdc;
|
|
|
|
|
|
|
|
|
|
window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
|
|
|
|
|
hwnd = (window == None) ? NULL : TkWinGetHWND(window);
|
|
|
|
|
|
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
|
lf.lfHeight = -faPtr->pointsize;
|
|
|
|
|
if (lf.lfHeight < 0) {
|
|
|
|
|
lf.lfHeight = MulDiv(lf.lfHeight,
|
|
|
|
|
254 * WidthOfScreen(Tk_Screen(tkwin)),
|
|
|
|
|
720 * WidthMMOfScreen(Tk_Screen(tkwin)));
|
|
|
|
|
}
|
|
|
|
|
lf.lfWidth = 0;
|
|
|
|
|
lf.lfEscapement = 0;
|
|
|
|
|
lf.lfOrientation = 0;
|
|
|
|
|
lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
|
|
|
|
|
lf.lfItalic = faPtr->slant;
|
|
|
|
|
lf.lfUnderline = faPtr->underline;
|
|
|
|
|
lf.lfStrikeOut = faPtr->overstrike;
|
|
|
|
|
lf.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
|
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
|
|
|
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
|
|
|
lf.lfQuality = DEFAULT_QUALITY;
|
|
|
|
|
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
|
|
|
|
if (faPtr->family == NULL) {
|
|
|
|
|
lf.lfFaceName[0] = '\0';
|
|
|
|
|
} else {
|
|
|
|
|
lstrcpyn(lf.lfFaceName, faPtr->family, sizeof(lf.lfFaceName));
|
|
|
|
|
}
|
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Replace the standard X and Mac family names with the names that
|
|
|
|
|
* Windows likes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((stricmp(lf.lfFaceName, "Times") == 0)
|
|
|
|
|
|| (stricmp(lf.lfFaceName, "New York") == 0)) {
|
|
|
|
|
strcpy(lf.lfFaceName, "Times New Roman");
|
|
|
|
|
} else if ((stricmp(lf.lfFaceName, "Courier") == 0)
|
|
|
|
|
|| (stricmp(lf.lfFaceName, "Monaco") == 0)) {
|
|
|
|
|
strcpy(lf.lfFaceName, "Courier New");
|
|
|
|
|
} else if ((stricmp(lf.lfFaceName, "Helvetica") == 0)
|
|
|
|
|
|| (stricmp(lf.lfFaceName, "Geneva") == 0)) {
|
|
|
|
|
strcpy(lf.lfFaceName, "Arial");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hFont = CreateFontIndirect(&lf);
|
|
|
|
|
if (hFont == NULL) {
|
|
|
|
|
hFont = GetStockObject(SYSTEM_FONT);
|
|
|
|
|
if (hFont == NULL) {
|
|
|
|
|
panic("TkpGetFontFromAttributes: cannot get system font");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return AllocFont(tkFontPtr, tkwin, hFont);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpDeleteFont --
|
|
|
|
|
*
|
|
|
|
|
* Called to release a font allocated by TkpGetNativeFont() or
|
|
|
|
|
* TkpGetFontFromAttributes(). The caller should have already
|
|
|
|
|
* released the fields of the TkFont that are used exclusively by
|
|
|
|
|
* the generic TkFont code.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* TkFont is deallocated.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpDeleteFont(tkFontPtr)
|
|
|
|
|
TkFont *tkFontPtr; /* Token of font to be deleted. */
|
|
|
|
|
{
|
|
|
|
|
WinFont *fontPtr;
|
|
|
|
|
|
|
|
|
|
fontPtr = (WinFont *) tkFontPtr;
|
|
|
|
|
DeleteObject(fontPtr->hFont);
|
|
|
|
|
ckfree((char *) fontPtr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* TkpGetFontFamilies, WinFontEnumFamilyProc --
|
|
|
|
|
*
|
|
|
|
|
* Return information about the font families that are available
|
|
|
|
|
* on the display of the given window.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* interp->result is modified to hold a list of all the available
|
|
|
|
|
* font families.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
TkpGetFontFamilies(interp, tkwin)
|
|
|
|
|
Tcl_Interp *interp; /* Interp to hold result. */
|
|
|
|
|
Tk_Window tkwin; /* For display to query. */
|
|
|
|
|
{
|
|
|
|
|
Window window;
|
|
|
|
|
HWND hwnd;
|
|
|
|
|
HDC hdc;
|
|
|
|
|
|
|
|
|
|
window = Tk_WindowId(tkwin);
|
|
|
|
|
hwnd = (window == (Window) NULL) ? NULL : TkWinGetHWND(window);
|
|
|
|
|
|
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
|
#ifdef STk_CODE
|
|
|
|
|
Tcl_AppendResult(interp, "(", NULL);
|
|
|
|
|
#endif
|
|
|
|
|
EnumFontFamilies(hdc, NULL, (FONTENUMPROC) WinFontFamilyEnumProc,
|
|
|
|
|
(LPARAM) interp);
|
|
|
|
|
#ifdef STk_CODE
|
|
|
|
|
Tcl_AppendResult(interp, ")", NULL);
|
|
|
|
|
#endif
|
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
|
|
|
|
|
|
static int CALLBACK
|
|
|
|
|
WinFontFamilyEnumProc(elfPtr, ntmPtr, fontType, lParam)
|
|
|
|
|
ENUMLOGFONT *elfPtr; /* Logical-font data. */
|
|
|
|
|
NEWTEXTMETRIC *ntmPtr; /* Physical-font data (not used). */
|
|
|
|
|
int fontType; /* Type of font (not used). */
|
|
|
|
|
LPARAM lParam; /* Interp to hold result. */
|
|
|
|
|
{
|
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
|
|
|
|
|
|
interp = (Tcl_Interp *) lParam;
|
1999-09-05 07:16:41 -04:00
|
|
|
|
#ifdef STk_CODE
|
|
|
|
|
Tcl_AppendResult(interp, " \"", elfPtr->elfLogFont.lfFaceName, "\"", NULL);
|
|
|
|
|
#else
|
1999-02-02 06:13:40 -05:00
|
|
|
|
Tcl_AppendElement(interp, elfPtr->elfLogFont.lfFaceName);
|
1999-09-05 07:16:41 -04:00
|
|
|
|
#endif
|
1999-02-02 06:13:40 -05:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* Tk_MeasureChars --
|
|
|
|
|
*
|
|
|
|
|
* Determine the number of characters from the string that will fit
|
|
|
|
|
* in the given horizontal span. The measurement is done under the
|
|
|
|
|
* assumption that Tk_DrawChars() will be used to actually display
|
|
|
|
|
* the characters.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* The return value is the number of characters from source that
|
|
|
|
|
* fit into the span that extends from 0 to maxLength. *lengthPtr is
|
|
|
|
|
* filled with the x-coordinate of the right edge of the last
|
|
|
|
|
* character that did fit.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
Tk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr)
|
|
|
|
|
Tk_Font tkfont; /* Font in which characters will be drawn. */
|
|
|
|
|
CONST char *source; /* Characters to be displayed. Need not be
|
|
|
|
|
* '\0' terminated. */
|
|
|
|
|
int numChars; /* Maximum number of characters to consider
|
|
|
|
|
* from source string. */
|
|
|
|
|
int maxLength; /* If > 0, maxLength specifies the longest
|
|
|
|
|
* permissible line length; don't consider any
|
|
|
|
|
* character that would cross this
|
|
|
|
|
* x-position. If <= 0, then line length is
|
|
|
|
|
* unbounded and the flags argument is
|
|
|
|
|
* ignored. */
|
|
|
|
|
int flags; /* Various flag bits OR-ed together:
|
|
|
|
|
* TK_PARTIAL_OK means include the last char
|
|
|
|
|
* which only partially fit on this line.
|
|
|
|
|
* TK_WHOLE_WORDS means stop on a word
|
|
|
|
|
* boundary, if possible.
|
|
|
|
|
* TK_AT_LEAST_ONE means return at least one
|
|
|
|
|
* character even if no characters fit. */
|
|
|
|
|
int *lengthPtr; /* Filled with x-location just after the
|
|
|
|
|
* terminating character. */
|
|
|
|
|
{
|
|
|
|
|
WinFont *fontPtr;
|
|
|
|
|
HDC hdc;
|
|
|
|
|
HFONT hFont;
|
|
|
|
|
int curX, curIdx;
|
|
|
|
|
|
|
|
|
|
fontPtr = (WinFont *) tkfont;
|
|
|
|
|
|
|
|
|
|
hdc = GetDC(fontPtr->hwnd);
|
|
|
|
|
hFont = SelectObject(hdc, fontPtr->hFont);
|
|
|
|
|
|
|
|
|
|
if (numChars == 0) {
|
|
|
|
|
curX = 0;
|
|
|
|
|
curIdx = 0;
|
|
|
|
|
} else if (maxLength <= 0) {
|
|
|
|
|
SIZE size;
|
|
|
|
|
|
|
|
|
|
GetTextExtentPoint32(hdc, source, numChars, &size);
|
|
|
|
|
curX = size.cx;
|
|
|
|
|
curIdx = numChars;
|
|
|
|
|
} else {
|
|
|
|
|
int max;
|
|
|
|
|
int *partials;
|
|
|
|
|
SIZE size;
|
|
|
|
|
|
|
|
|
|
partials = (int *) ckalloc(numChars * sizeof (int));
|
|
|
|
|
GetTextExtentExPoint(hdc, source, numChars, maxLength, &max,
|
|
|
|
|
partials, &size);
|
|
|
|
|
|
|
|
|
|
if ((flags & TK_WHOLE_WORDS) && max < numChars) {
|
|
|
|
|
int sawSpace;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
sawSpace = 0;
|
|
|
|
|
i = max;
|
|
|
|
|
while (i >= 0 && !isspace(source[i])) {
|
|
|
|
|
--i;
|
|
|
|
|
}
|
|
|
|
|
while (i >= 0 && isspace(source[i])) {
|
|
|
|
|
sawSpace = 1;
|
|
|
|
|
--i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If a space char was not found, and the flag for forcing
|
|
|
|
|
* at least on (or more) chars to be drawn is false, then
|
|
|
|
|
* set MAX to zero so no text is drawn. Otherwise, if a
|
|
|
|
|
* space was found, set max to be one char past the space.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ((i < 0) && !(flags & TK_AT_LEAST_ONE)) {
|
|
|
|
|
max = 0;
|
|
|
|
|
} else if (sawSpace) {
|
|
|
|
|
max = i + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (max == 0) {
|
|
|
|
|
curX = 0;
|
|
|
|
|
} else {
|
|
|
|
|
curX = partials[max - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (((flags & TK_PARTIAL_OK) && max < numChars && curX < maxLength)
|
|
|
|
|
|| ((flags & TK_AT_LEAST_ONE) && max == 0 && numChars > 0)) {
|
|
|
|
|
/*
|
|
|
|
|
* We want to include the first character that didn't
|
|
|
|
|
* quite fit. Call the function again to include the
|
|
|
|
|
* width of the extra character.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
GetTextExtentExPoint(hdc, source, max + 1, 0, NULL, partials,
|
|
|
|
|
&size);
|
|
|
|
|
curX = partials[max];
|
|
|
|
|
++max;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ckfree((char *) partials);
|
|
|
|
|
curIdx = max;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectObject(hdc, hFont);
|
|
|
|
|
ReleaseDC(fontPtr->hwnd, hdc);
|
|
|
|
|
|
|
|
|
|
*lengthPtr = curX;
|
|
|
|
|
return curIdx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* Tk_DrawChars --
|
|
|
|
|
*
|
|
|
|
|
* Draw a string of characters on the screen.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* None.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Information gets drawn on the screen.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Tk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y)
|
|
|
|
|
Display *display; /* Display on which to draw. */
|
|
|
|
|
Drawable drawable; /* Window or pixmap in which to draw. */
|
|
|
|
|
GC gc; /* Graphics context for drawing characters. */
|
|
|
|
|
Tk_Font tkfont; /* Font in which characters will be drawn;
|
|
|
|
|
* must be the same as font used in GC. */
|
|
|
|
|
CONST char *source; /* Characters to be displayed. Need not be
|
|
|
|
|
* '\0' terminated. All Tk meta-characters
|
|
|
|
|
* (tabs, control characters, and newlines)
|
|
|
|
|
* should be stripped out of the string that
|
|
|
|
|
* is passed to this function. If they are
|
|
|
|
|
* not stripped out, they will be displayed as
|
|
|
|
|
* regular printing characters. */
|
|
|
|
|
int numChars; /* Number of characters in string. */
|
|
|
|
|
int x, y; /* Coordinates at which to place origin of
|
|
|
|
|
* string when drawing. */
|
|
|
|
|
{
|
|
|
|
|
HDC dc;
|
|
|
|
|
HFONT hFont;
|
|
|
|
|
TkWinDCState state;
|
|
|
|
|
WinFont *fontPtr;
|
|
|
|
|
|
|
|
|
|
fontPtr = (WinFont *) gc->font;
|
|
|
|
|
display->request++;
|
|
|
|
|
|
|
|
|
|
if (drawable == None) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dc = TkWinGetDrawableDC(display, drawable, &state);
|
|
|
|
|
|
|
|
|
|
SetROP2(dc, tkpWinRopModes[gc->function]);
|
|
|
|
|
|
|
|
|
|
if ((gc->fill_style == FillStippled
|
|
|
|
|
|| gc->fill_style == FillOpaqueStippled)
|
|
|
|
|
&& gc->stipple != None) {
|
|
|
|
|
TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
|
|
|
|
|
HBRUSH oldBrush, stipple;
|
|
|
|
|
HBITMAP oldBitmap, bitmap;
|
|
|
|
|
HDC dcMem;
|
|
|
|
|
TEXTMETRIC tm;
|
|
|
|
|
SIZE size;
|
|
|
|
|
|
|
|
|
|
if (twdPtr->type != TWD_BITMAP) {
|
|
|
|
|
panic("unexpected drawable type in stipple");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Select stipple pattern into destination dc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
dcMem = CreateCompatibleDC(dc);
|
|
|
|
|
|
|
|
|
|
stipple = CreatePatternBrush(twdPtr->bitmap.handle);
|
|
|
|
|
SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
|
|
|
|
|
oldBrush = SelectObject(dc, stipple);
|
|
|
|
|
|
|
|
|
|
SetTextAlign(dcMem, TA_LEFT | TA_TOP);
|
|
|
|
|
SetTextColor(dcMem, gc->foreground);
|
|
|
|
|
SetBkMode(dcMem, TRANSPARENT);
|
|
|
|
|
SetBkColor(dcMem, RGB(0, 0, 0));
|
|
|
|
|
|
|
|
|
|
hFont = SelectObject(dcMem, fontPtr->hFont);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Compute the bounding box and create a compatible bitmap.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
GetTextExtentPoint(dcMem, source, numChars, &size);
|
|
|
|
|
GetTextMetrics(dcMem, &tm);
|
|
|
|
|
size.cx -= tm.tmOverhang;
|
|
|
|
|
bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
|
|
|
|
|
oldBitmap = SelectObject(dcMem, bitmap);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The following code is tricky because fonts are rendered in multiple
|
|
|
|
|
* colors. First we draw onto a black background and copy the white
|
|
|
|
|
* bits. Then we draw onto a white background and copy the black bits.
|
|
|
|
|
* Both the foreground and background bits of the font are ANDed with
|
|
|
|
|
* the stipple pattern as they are copied.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
|
|
|
|
|
TextOut(dcMem, 0, 0, source, numChars);
|
|
|
|
|
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
|
|
|
|
|
0, 0, 0xEA02E9);
|
|
|
|
|
PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
|
|
|
|
|
TextOut(dcMem, 0, 0, source, numChars);
|
|
|
|
|
BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
|
|
|
|
|
0, 0, 0x8A0E06);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Destroy the temporary bitmap and restore the device context.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
SelectObject(dcMem, hFont);
|
|
|
|
|
SelectObject(dcMem, oldBitmap);
|
|
|
|
|
DeleteObject(bitmap);
|
|
|
|
|
DeleteDC(dcMem);
|
|
|
|
|
SelectObject(dc, oldBrush);
|
|
|
|
|
DeleteObject(stipple);
|
|
|
|
|
} else {
|
|
|
|
|
SetTextAlign(dc, TA_LEFT | TA_BASELINE);
|
|
|
|
|
SetTextColor(dc, gc->foreground);
|
|
|
|
|
SetBkMode(dc, TRANSPARENT);
|
|
|
|
|
hFont = SelectObject(dc, fontPtr->hFont);
|
|
|
|
|
TextOut(dc, x, y, source, numChars);
|
|
|
|
|
SelectObject(dc, hFont);
|
|
|
|
|
}
|
|
|
|
|
TkWinReleaseDrawableDC(drawable, dc, &state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* AllocFont --
|
|
|
|
|
*
|
|
|
|
|
* Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
|
|
|
|
|
* Allocates and intializes the memory for a new TkFont that
|
|
|
|
|
* wraps the platform-specific data.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns pointer to newly constructed TkFont.
|
|
|
|
|
*
|
|
|
|
|
* The caller is responsible for initializing the fields of the
|
|
|
|
|
* TkFont that are used exclusively by the generic TkFont code, and
|
|
|
|
|
* for releasing those fields before calling TkpDeleteFont().
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* Memory allocated.
|
|
|
|
|
*
|
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static TkFont *
|
|
|
|
|
AllocFont(tkFontPtr, tkwin, hFont)
|
|
|
|
|
TkFont *tkFontPtr; /* If non-NULL, store the information in
|
|
|
|
|
* this existing TkFont structure, rather than
|
|
|
|
|
* allocating a new structure to hold the
|
|
|
|
|
* font; the existing contents of the font
|
|
|
|
|
* will be released. If NULL, a new TkFont
|
|
|
|
|
* structure is allocated. */
|
|
|
|
|
Tk_Window tkwin; /* For display where font will be used. */
|
|
|
|
|
HFONT hFont; /* Windows information about font. */
|
|
|
|
|
{
|
|
|
|
|
HWND hwnd;
|
|
|
|
|
WinFont *fontPtr;
|
|
|
|
|
HDC hdc;
|
|
|
|
|
TEXTMETRIC tm;
|
|
|
|
|
Window window;
|
|
|
|
|
char buf[LF_FACESIZE];
|
|
|
|
|
TkFontAttributes *faPtr;
|
|
|
|
|
|
|
|
|
|
if (tkFontPtr != NULL) {
|
|
|
|
|
fontPtr = (WinFont *) tkFontPtr;
|
|
|
|
|
DeleteObject(fontPtr->hFont);
|
|
|
|
|
} else {
|
|
|
|
|
fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window = Tk_WindowId(((TkWindow *) tkwin)->mainPtr->winPtr);
|
|
|
|
|
hwnd = (window == None) ? NULL : TkWinGetHWND(window);
|
|
|
|
|
|
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
|
hFont = SelectObject(hdc, hFont);
|
|
|
|
|
GetTextFace(hdc, sizeof(buf), buf);
|
|
|
|
|
GetTextMetrics(hdc, &tm);
|
|
|
|
|
|
|
|
|
|
fontPtr->font.fid = (Font) fontPtr;
|
|
|
|
|
|
|
|
|
|
faPtr = &fontPtr->font.fa;
|
|
|
|
|
faPtr->family = Tk_GetUid(buf);
|
|
|
|
|
faPtr->pointsize = MulDiv(tm.tmHeight - tm.tmInternalLeading,
|
|
|
|
|
720 * WidthMMOfScreen(Tk_Screen(tkwin)),
|
|
|
|
|
254 * WidthOfScreen(Tk_Screen(tkwin)));
|
|
|
|
|
faPtr->weight = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
|
|
|
|
|
faPtr->slant = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;
|
|
|
|
|
faPtr->underline = (tm.tmUnderlined != 0) ? 1 : 0;
|
|
|
|
|
faPtr->overstrike = (tm.tmStruckOut != 0) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
fontPtr->font.fm.ascent = tm.tmAscent;
|
|
|
|
|
fontPtr->font.fm.descent = tm.tmDescent;
|
|
|
|
|
fontPtr->font.fm.maxWidth = tm.tmMaxCharWidth;
|
|
|
|
|
fontPtr->font.fm.fixed = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
|
|
|
|
|
|
|
|
|
|
hFont = SelectObject(hdc, hFont);
|
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
|
|
|
|
|
|
fontPtr->hFont = hFont;
|
|
|
|
|
fontPtr->hwnd = hwnd;
|
|
|
|
|
|
|
|
|
|
return (TkFont *) fontPtr;
|
|
|
|
|
}
|
|
|
|
|
|