/*
* rbcText.c --
*
* This module implements multi-line, rotate-able text for the rbc toolkit.
*
* Copyright (c) 2009 Samuel Green, Nicholas Hudson, Stanton Sievers, Jarrod Stormo
* All rights reserved.
*
* See "license.terms" for details.
*/
#include "rbcInt.h"
#include <X11/Xutil.h>
#include "rbcImage.h"
#include <tkInt.h> /* needed for TkDrawAngledChars */
#define WINDEBUG 0
static Tcl_HashTable bitmapGCTable;
static int initialized;
static void DrawTextLayout (Display *display, Drawable drawable,
GC gc, Tk_Font font, register int x, register int y, TextLayout *textPtr,
double theta);
/*
*--------------------------------------------------------------
*
* DrawTextLayout --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
static void
DrawTextLayout(
Display *display,
Drawable drawable,
GC gc,
Tk_Font font,
int x,
int y, /* Origin of text */
TextLayout *textPtr,
double theta)
{
register TextFragment *fragPtr;
register int i;
int newX = 0, newY = 0, width = 0, height = 0, rW = 0, rH = 0;
double realX, realY;
double sinA, cosA;
double rotWidth, rotHeight;
if (theta != 0.0) {
sinA = sin(theta * M_PI/180.0);
cosA = cos(theta * M_PI/180.0);
width = textPtr->width;
height = textPtr->height;
Rbc_GetBoundingBox(width, height, theta,
&rotWidth, &rotHeight, (Point2D *)NULL);
rW = ROUND(rotWidth);
rH = ROUND(rotHeight);
}
fragPtr = textPtr->fragArr;
for (i = 0; i < textPtr->nFrags; i++, fragPtr++) {
if (theta == 0.0) {
Tk_DrawChars(display, drawable, gc, font, fragPtr->text,
fragPtr->count, x + fragPtr->x, y + fragPtr->y);
} else {
realX = (fragPtr->x - width/2) * cosA + (fragPtr->y - height/2) * sinA;
realY = (fragPtr->y - height/2) * cosA - (fragPtr->x - width/2) * sinA;
newX = ROUND(realX) + x + rW/2;
newY = ROUND(realY) + y + rH/2;
TkDrawAngledChars(display, drawable, gc, font, fragPtr->text,
fragPtr->count, newX, newY, theta);
}
}
}
/*
* -----------------------------------------------------------------
*
* Rbc_GetTextLayout --
*
* Get the extents of a possibly multiple-lined text string.
*
* Results:
* Returns via *widthPtr* and *heightPtr* the dimensions of
* the text string.
*
* Side effects:
* TODO: Side Effects
*
* -----------------------------------------------------------------
*/
TextLayout *
Rbc_GetTextLayout(string, tsPtr)
char string[];
TextStyle *tsPtr;
{
int maxHeight, maxWidth;
int count; /* Count # of characters on each line */
int nFrags;
int width; /* Running dimensions of the text */
TextFragment *fragPtr;
TextLayout *textPtr;
int lineHeight;
int size;
register char *p;
register int i;
Tk_FontMetrics fontMetrics;
Tk_GetFontMetrics(tsPtr->font, &fontMetrics);
lineHeight = fontMetrics.linespace +
tsPtr->leader + tsPtr->shadow.offset;
nFrags = 0;
for (p = string; *p != '\0'; p++) {
if (*p == '\n') {
nFrags++;
}
}
if ((p != string) && (*(p - 1) != '\n')) {
nFrags++;
}
size = sizeof(TextLayout) + (sizeof(TextFragment) * (nFrags - 1));
textPtr = RbcCalloc(1, size);
textPtr->nFrags = nFrags;
nFrags = count = 0;
width = maxWidth = 0;
maxHeight = tsPtr->padTop;
fragPtr = textPtr->fragArr;
for (p = string; *p != '\0'; p++) {
if (*p == '\n') {
if (count > 0) {
width = Tk_TextWidth(tsPtr->font, string, count) +
tsPtr->shadow.offset;
if (width > maxWidth) {
maxWidth = width;
}
}
fragPtr->width = width;
fragPtr->count = count;
fragPtr->y = maxHeight + fontMetrics.ascent;
fragPtr->text = string;
fragPtr++;
nFrags++;
maxHeight += lineHeight;
string = p + 1; /* Start the string on the next line */
count = 0; /* Reset to indicate the start of a new line */
continue;
}
count++;
}
if (nFrags < textPtr->nFrags) {
width = Tk_TextWidth(tsPtr->font, string, count) + tsPtr->shadow.offset;
if (width > maxWidth) {
maxWidth = width;
}
fragPtr->width = width;
fragPtr->count = count;
fragPtr->y = maxHeight + fontMetrics.ascent;
fragPtr->text = string;
maxHeight += lineHeight;
nFrags++;
}
maxHeight += tsPtr->padBottom;
maxWidth += PADDING(tsPtr->padX);
fragPtr = textPtr->fragArr;
for (i = 0; i < nFrags; i++, fragPtr++) {
switch (tsPtr->justify) {
default:
case TK_JUSTIFY_LEFT:
/* No offset for left justified text strings */
fragPtr->x = tsPtr->padLeft;
break;
case TK_JUSTIFY_RIGHT:
fragPtr->x = (maxWidth - fragPtr->width) - tsPtr->padRight;
break;
case TK_JUSTIFY_CENTER:
fragPtr->x = (maxWidth - fragPtr->width) / 2;
break;
}
}
textPtr->width = maxWidth;
textPtr->height = maxHeight - tsPtr->leader;
return textPtr;
}
/*
* -----------------------------------------------------------------
*
* Rbc_GetTextExtents --
*
* Get the extents of a possibly multiple-lined text string.
*
* Results:
* Returns via *widthPtr* and *heightPtr* the dimensions of
* the text string.
*
* Side effects:
* TODO: Side Effects
*
* -----------------------------------------------------------------
*/
void
Rbc_GetTextExtents(tsPtr, string, widthPtr, heightPtr)
TextStyle *tsPtr;
char *string;
int *widthPtr, *heightPtr;
{
int count; /* Count # of characters on each line */
int width, height;
int w, lineHeight;
register char *p;
Tk_FontMetrics fontMetrics;
if (string == NULL) {
return; /* NULL string? */
}
Tk_GetFontMetrics(tsPtr->font, &fontMetrics);
lineHeight = fontMetrics.linespace + tsPtr->leader + tsPtr->shadow.offset;
count = 0;
width = height = 0;
for (p = string; *p != '\0'; p++) {
if (*p == '\n') {
if (count > 0) {
w = Tk_TextWidth(tsPtr->font, string, count) +
tsPtr->shadow.offset;
if (w > width) {
width = w;
}
}
height += lineHeight;
string = p + 1; /* Start the string on the next line */
count = 0; /* Reset to indicate the start of a new line */
continue;
}
count++;
}
if ((count > 0) && (*(p - 1) != '\n')) {
height += lineHeight;
w = Tk_TextWidth(tsPtr->font, string, count) + tsPtr->shadow.offset;
if (w > width) {
width = w;
}
}
*widthPtr = width + PADDING(tsPtr->padX);
*heightPtr = height + PADDING(tsPtr->padY);
}
/*
* -----------------------------------------------------------------
*
* Rbc_GetBoundingBox
*
* Computes the dimensions of the bounding box surrounding a
* rectangle rotated about its center. If pointArr isn't NULL,
* the coordinates of the rotated rectangle are also returned.
*
* The dimensions are determined by rotating the rectangle, and
* doubling the maximum x-coordinate and y-coordinate.
*
* w = 2 * maxX, h = 2 * maxY
*
* Since the rectangle is centered at 0,0, the coordinates of
* the bounding box are (-w/2,-h/2 w/2,-h/2, w/2,h/2 -w/2,h/2).
*
* 0 ------- 1
* | |
* | x |
* | |
* 3 ------- 2
*
* Results:
* The width and height of the bounding box containing the
* rotated rectangle are returned.
*
* Side effects:
* TODO: Side Effects
*
* -----------------------------------------------------------------
*/
void
Rbc_GetBoundingBox(width, height, theta, rotWidthPtr, rotHeightPtr, bbox)
int width; /* Unrotated region */
int height; /* Unrotated region */
double theta; /* Rotation of box */
double *rotWidthPtr; /* (out) Bounding box region */
double *rotHeightPtr; /* (out) Bounding box region */
Point2D *bbox; /* (out) Points of the rotated box */
{
register int i;
double sinTheta, cosTheta;
double xMax, yMax;
register double x, y;
Point2D corner[4];
theta = FMOD(theta, 360.0);
if (FMOD(theta, (double)90.0) == 0.0) {
int ll, ur, ul, lr;
double rotWidth, rotHeight;
int quadrant;
/* Handle right-angle rotations specifically */
quadrant = (int)(theta / 90.0);
switch (quadrant) {
case ROTATE_270: /* 270 degrees */
ul = 3, ur = 0, lr = 1, ll = 2;
rotWidth = (double)height;
rotHeight = (double)width;
break;
case ROTATE_90: /* 90 degrees */
ul = 1, ur = 2, lr = 3, ll = 0;
rotWidth = (double)height;
rotHeight = (double)width;
break;
case ROTATE_180: /* 180 degrees */
ul = 2, ur = 3, lr = 0, ll = 1;
rotWidth = (double)width;
rotHeight = (double)height;
break;
default:
case ROTATE_0: /* 0 degrees */
ul = 0, ur = 1, lr = 2, ll = 3;
rotWidth = (double)width;
rotHeight = (double)height;
break;
}
if (bbox != NULL) {
x = rotWidth * 0.5;
y = rotHeight * 0.5;
bbox[ll].x = bbox[ul].x = -x;
bbox[ur].y = bbox[ul].y = -y;
bbox[lr].x = bbox[ur].x = x;
bbox[ll].y = bbox[lr].y = y;
}
*rotWidthPtr = rotWidth;
*rotHeightPtr = rotHeight;
return;
}
/* Set the four corners of the rectangle whose center is the origin */
corner[1].x = corner[2].x = (double)width *0.5;
corner[0].x = corner[3].x = -corner[1].x;
corner[2].y = corner[3].y = (double)height *0.5;
corner[0].y = corner[1].y = -corner[2].y;
theta = (-theta / 180.0) * M_PI;
sinTheta = sin(theta), cosTheta = cos(theta);
xMax = yMax = 0.0;
/* Rotate the four corners and find the maximum X and Y coordinates */
for (i = 0; i < 4; i++) {
x = (corner[i].x * cosTheta) - (corner[i].y * sinTheta);
y = (corner[i].x * sinTheta) + (corner[i].y * cosTheta);
if (x > xMax) {
xMax = x;
}
if (y > yMax) {
yMax = y;
}
if (bbox != NULL) {
bbox[i].x = x;
bbox[i].y = y;
}
}
/*
* By symmetry, the width and height of the bounding box are
* twice the maximum x and y coordinates.
*/
*rotWidthPtr = xMax + xMax;
*rotHeightPtr = yMax + yMax;
}
/*
* -----------------------------------------------------------------
*
* Rbc_TranslateAnchor --
*
* Translate the coordinates of a given bounding box based
* upon the anchor specified. The anchor indicates where
* the given xy position is in relation to the bounding box.
*
* nw --- n --- ne
* | |
* w center e
* | |
* sw --- s --- se
*
* The coordinates returned are translated to the origin of the
* bounding box (suitable for giving to XCopyArea, XCopyPlane, etc.)
*
* Results:
* The translated coordinates of the bounding box are returned.
*
* Side effects:
* TODO: Side Effects
*
* -----------------------------------------------------------------
*/
void
Rbc_TranslateAnchor(x, y, width, height, anchor, transXPtr, transYPtr)
int x, y; /* Window coordinates of anchor */
int width, height; /* Extents of the bounding box */
Tk_Anchor anchor; /* Direction of the anchor */
int *transXPtr, *transYPtr;
{
switch (anchor) {
case TK_ANCHOR_NULL:
case TK_ANCHOR_NW: /* Upper left corner */
break;
case TK_ANCHOR_W: /* Left center */
y -= (height / 2);
break;
case TK_ANCHOR_SW: /* Lower left corner */
y -= height;
break;
case TK_ANCHOR_N: /* Top center */
x -= (width / 2);
break;
case TK_ANCHOR_CENTER: /* Center */
x -= (width / 2);
y -= (height / 2);
break;
case TK_ANCHOR_S: /* Bottom center */
x -= (width / 2);
y -= height;
break;
case TK_ANCHOR_NE: /* Upper right corner */
x -= width;
break;
case TK_ANCHOR_E: /* Right center */
x -= width;
y -= (height / 2);
break;
case TK_ANCHOR_SE: /* Lower right corner */
x -= width;
y -= height;
break;
}
*transXPtr = x;
*transYPtr = y;
}
/*
* -----------------------------------------------------------------
*
* Rbc_TranslatePoint --
*
* Translate the coordinates of a given bounding box based
* upon the anchor specified. The anchor indicates where
* the given xy position is in relation to the bounding box.
*
* nw --- n --- ne
* | |
* w center e
* | |
* sw --- s --- se
*
* The coordinates returned are translated to the origin of the
* bounding box (suitable for giving to XCopyArea, XCopyPlane, etc.)
*
* Results:
* The translated coordinates of the bounding box are returned.
*
* Side effects:
* TODO: Side Effects
*
* -----------------------------------------------------------------
*/
Point2D
Rbc_TranslatePoint(pointPtr, width, height, anchor)
Point2D *pointPtr; /* Window coordinates of anchor */
int width, height; /* Extents of the bounding box */
Tk_Anchor anchor; /* Direction of the anchor */
{
Point2D trans;
trans = *pointPtr;
switch (anchor) {
case TK_ANCHOR_NULL:
case TK_ANCHOR_NW: /* Upper left corner */
break;
case TK_ANCHOR_W: /* Left center */
trans.y -= (height * 0.5);
break;
case TK_ANCHOR_SW: /* Lower left corner */
trans.y -= height;
break;
case TK_ANCHOR_N: /* Top center */
trans.x -= (width * 0.5);
break;
case TK_ANCHOR_CENTER: /* Center */
trans.x -= (width * 0.5);
trans.y -= (height * 0.5);
break;
case TK_ANCHOR_S: /* Bottom center */
trans.x -= (width * 0.5);
trans.y -= height;
break;
case TK_ANCHOR_NE: /* Upper right corner */
trans.x -= width;
break;
case TK_ANCHOR_E: /* Right center */
trans.x -= width;
trans.y -= (height * 0.5);
break;
case TK_ANCHOR_SE: /* Lower right corner */
trans.x -= width;
trans.y -= height;
break;
}
return trans;
}
/*
*--------------------------------------------------------------
*
* Rbc_InitTextStyle --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_InitTextStyle(tsPtr)
TextStyle *tsPtr;
{
/* Initialize these attributes to zero */
tsPtr->activeColor = (XColor *)NULL;
tsPtr->anchor = TK_ANCHOR_CENTER;
tsPtr->color = (XColor *)NULL;
tsPtr->font = NULL;
tsPtr->justify = TK_JUSTIFY_CENTER;
tsPtr->leader = 0;
tsPtr->padLeft = tsPtr->padRight = 0;
tsPtr->padTop = tsPtr->padBottom = 0;
tsPtr->shadow.color = (XColor *)NULL;
tsPtr->shadow.offset = 0;
tsPtr->state = 0;
tsPtr->theta = 0.0;
}
/*
*--------------------------------------------------------------
*
* Rbc_SetDrawTextStyle --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_SetDrawTextStyle(tsPtr, font, gc, normalColor, activeColor, shadowColor,
theta, anchor, justify, leader, shadowOffset)
TextStyle *tsPtr;
Tk_Font font;
GC gc;
XColor *normalColor, *activeColor, *shadowColor;
double theta;
Tk_Anchor anchor;
Tk_Justify justify;
int leader, shadowOffset;
{
Rbc_InitTextStyle(tsPtr);
tsPtr->activeColor = activeColor;
tsPtr->anchor = anchor;
tsPtr->color = normalColor;
tsPtr->font = font;
tsPtr->gc = gc;
tsPtr->justify = justify;
tsPtr->leader = leader;
tsPtr->shadow.color = shadowColor;
tsPtr->shadow.offset = shadowOffset;
tsPtr->theta = theta;
}
/*
*--------------------------------------------------------------
*
* Rbc_SetPrintTextStyle --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_SetPrintTextStyle(tsPtr, font, fgColor, activeColor, shadowColor, theta,
anchor, justify, leader, shadowOffset)
TextStyle *tsPtr;
Tk_Font font;
XColor *fgColor, *activeColor, *shadowColor;
double theta;
Tk_Anchor anchor;
Tk_Justify justify;
int leader, shadowOffset;
{
Rbc_InitTextStyle(tsPtr);
tsPtr->color = fgColor;
tsPtr->activeColor = activeColor;
tsPtr->shadow.color = shadowColor;
tsPtr->font = font;
tsPtr->theta = theta;
tsPtr->anchor = anchor;
tsPtr->justify = justify;
tsPtr->leader = leader;
tsPtr->shadow.offset = shadowOffset;
}
/*
* -----------------------------------------------------------------
*
* Rbc_DrawTextLayout --
*
* Draw a text string, possibly rotated, using the the given
* window coordinates as an anchor for the text bounding box.
* If the text is not rotated, simply use the X text drawing
* routines. Otherwise, generate a bitmap of the rotated text.
*
* Results:
* Returns the x-coordinate to the right of the text.
*
* Side Effects:
* Text string is drawn using the given font and GC at the
* the given window coordinates.
*
* The Stipple, FillStyle, and TSOrigin fields of the GC are
* modified for rotated text. This assumes the GC is private,
* *not* shared (via Tk_GetGC)
*
* -----------------------------------------------------------------
*/
void
Rbc_DrawTextLayout(
Tk_Window tkwin,
Drawable drawable,
TextLayout *textPtr,
TextStyle *tsPtr, /* Text attribute information */
int x,
int y) /* Window coordinates to draw text */
{
double theta;
Display *display;
int active;
double rotWidth, rotHeight;
int newWidth, newHeight;
display = Tk_Display(tkwin);
theta = FMOD(tsPtr->theta, (double)360.0);
if (theta < 0.0) {
theta += 360.0;
}
tsPtr->theta = theta;
active = tsPtr->state & STATE_ACTIVE;
Rbc_GetBoundingBox(textPtr->width, textPtr->height, theta,
&rotWidth, &rotHeight, (Point2D *)NULL);
newWidth = ROUND(rotWidth);
newHeight = ROUND(rotHeight);
Rbc_TranslateAnchor(x, y, newWidth, newHeight, tsPtr->anchor, &x, &y);
if (tsPtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
XColor xcolor1, xcolor2 , *color1, *color2;
Tk_Get3DBorderColors(tsPtr->border, NULL, &xcolor2, &xcolor1);
color1 = &xcolor1;
color2 = &xcolor2;
if (tsPtr->state & STATE_EMPHASIS) {
XColor *hold;
hold = color1, color1 = color2, color2 = hold;
}
if (color1 != NULL) {
XSetForeground(display, tsPtr->gc, color1->pixel);
}
DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font,
x+1 , y+1, textPtr, theta);
if (color2 != NULL) {
XSetForeground(display, tsPtr->gc, color2->pixel);
}
DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font,
x , y, textPtr, theta);
XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
} else {
if ((tsPtr->shadow.offset > 0) && (tsPtr->shadow.color != NULL)) {
XSetForeground(display, tsPtr->gc, tsPtr->shadow.color->pixel);
DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font,
x + tsPtr->shadow.offset , y + tsPtr->shadow.offset ,
textPtr, theta);
XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
}
if (active) {
XSetForeground(display, tsPtr->gc, tsPtr->activeColor->pixel);
}
DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font,
x , y, textPtr, theta);
if (active) {
XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
}
}
}
/*
*--------------------------------------------------------------
*
* Rbc_DrawText2 --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_DrawText2(tkwin, drawable, string, tsPtr, x, y, areaPtr)
Tk_Window tkwin;
Drawable drawable;
char string[];
TextStyle *tsPtr; /* Text attribute information */
int x, y; /* Window coordinates to draw text */
Dim2D *areaPtr;
{
TextLayout *textPtr;
int width, height;
double theta;
if ((string == NULL) || (*string == '\0')) {
return; /* Empty string, do nothing */
}
textPtr = Rbc_GetTextLayout(string, tsPtr);
Rbc_DrawTextLayout(tkwin, drawable, textPtr, tsPtr, x, y);
theta = FMOD(tsPtr->theta, (double)360.0);
if (theta < 0.0) {
theta += 360.0;
}
width = textPtr->width;
height = textPtr->height;
if (theta != 0.0) {
double rotWidth, rotHeight;
Rbc_GetBoundingBox(width, height, theta, &rotWidth, &rotHeight,
(Point2D *)NULL);
width = ROUND(rotWidth);
height = ROUND(rotHeight);
}
areaPtr->width = width;
areaPtr->height = height;
ckfree((char *)textPtr);
}
/*
*--------------------------------------------------------------
*
* Rbc_DrawText --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_DrawText(tkwin, drawable, string, tsPtr, x, y)
Tk_Window tkwin;
Drawable drawable;
char string[];
TextStyle *tsPtr; /* Text attribute information */
int x, y; /* Window coordinates to draw text */
{
TextLayout *textPtr;
if ((string == NULL) || (*string == '\0')) {
return; /* Empty string, do nothing */
}
textPtr = Rbc_GetTextLayout(string, tsPtr);
Rbc_DrawTextLayout(tkwin, drawable, textPtr, tsPtr, x, y);
ckfree((char *)textPtr);
}
/*
*--------------------------------------------------------------
*
* Rbc_GetBitmapGC --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
GC
Rbc_GetBitmapGC(tkwin)
Tk_Window tkwin;
{
int isNew;
GC gc;
Display *display;
Tcl_HashEntry *hPtr;
if (!initialized) {
Tcl_InitHashTable(&bitmapGCTable, TCL_ONE_WORD_KEYS);
initialized = TRUE;
}
display = Tk_Display(tkwin);
hPtr = Tcl_CreateHashEntry(&bitmapGCTable, (char *)display, &isNew);
if (isNew) {
Pixmap bitmap;
XGCValues gcValues;
unsigned long gcMask;
Window root;
root = RootWindow(display, Tk_ScreenNumber(tkwin));
bitmap = Tk_GetPixmap(display, root, 1, 1, 1);
gcValues.foreground = gcValues.background = 0;
gcMask = (GCForeground | GCBackground);
gc = Rbc_GetPrivateGCFromDrawable(display, bitmap, gcMask, &gcValues);
Tk_FreePixmap(display, bitmap);
Tcl_SetHashValue(hPtr, gc);
} else {
gc = (GC)Tcl_GetHashValue(hPtr);
}
return gc;
}
/*
*--------------------------------------------------------------
*
* Rbc_ResetTextStyle --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_ResetTextStyle(tkwin, tsPtr)
Tk_Window tkwin;
TextStyle *tsPtr;
{
GC newGC;
XGCValues gcValues;
unsigned long gcMask;
gcMask = GCFont;
gcValues.font = Tk_FontId(tsPtr->font);
if (tsPtr->color != NULL) {
gcMask |= GCForeground;
gcValues.foreground = tsPtr->color->pixel;
}
newGC = Tk_GetGC(tkwin, gcMask, &gcValues);
if (tsPtr->gc != NULL) {
Tk_FreeGC(Tk_Display(tkwin), tsPtr->gc);
}
tsPtr->gc = newGC;
}
/*
*--------------------------------------------------------------
*
* Rbc_FreeTextStyle --
*
* TODO: Description
*
* Results:
* TODO: Results
*
* Side effects:
* TODO: Side Effects
*
*--------------------------------------------------------------
*/
void
Rbc_FreeTextStyle(display, tsPtr)
Display *display;
TextStyle *tsPtr;
{
if (tsPtr->gc != NULL) {
Tk_FreeGC(display, tsPtr->gc);
}
}