mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-31 02:07:07 +02:00
Added a ARG_UNUSED macro in utils/magic.h, which produces a simple cast to void to silence the warnings. The reasons this is used as opposed to an attribute is that most compilers should support this. Besides this, the macro can be easily searched for in the future to potentially remove (where possible) the unused parameters.
375 lines
9.9 KiB
C
375 lines
9.9 KiB
C
/* grText.c -
|
|
*
|
|
* Contains functions for manipulating text that are not dependent
|
|
* upon the display type.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/graphics/grText.c,v 1.3 2008/12/11 04:20:06 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/geometry.h"
|
|
#include "database/database.h"
|
|
#include "windows/windows.h"
|
|
#include "graphics/graphics.h"
|
|
#include "graphics/graphicsInt.h"
|
|
#include "utils/utils.h"
|
|
|
|
/*---------------------------------------------------------
|
|
*
|
|
* GrFontText ---
|
|
*
|
|
* This routine is a glorified version of GrPutText
|
|
* that draws vector outline fonts according to
|
|
* information loaded and stored into the font lists
|
|
* (see DBLoadFont() in DBlabel.c). In addition to
|
|
* the properties used by GrPutText(), GrFontText()
|
|
* uses label scale, rotation, offset, and font.
|
|
*
|
|
*---------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrFontText(str, style, p, font, size, rotate, clip)
|
|
char *str; /* The text to be drawn. */
|
|
int style; /* Display style to use for the text */
|
|
Point *p; /* Point of origin */
|
|
int font; /* Font to use */
|
|
int size; /* Scale */
|
|
int rotate; /* Rotation (in degrees) */
|
|
Rect *clip; /* Clipping area */
|
|
{
|
|
Rect nClip;
|
|
|
|
/* Fall back on X11 text if vectored text unavailable */
|
|
if (!grFontTextPtr)
|
|
{
|
|
GrPutText(str, style, p, GEO_CENTER, GR_TEXT_MEDIUM, FALSE, clip, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
nClip = *clip;
|
|
GeoClip(&nClip, &grCurClip);
|
|
|
|
GR_CHECK_LOCK();
|
|
if (!grDriverInformed) grInformDriver();
|
|
|
|
if (style >= 0)
|
|
(*grSetWMandCPtr)(GrStyleTable[style].mask, GrStyleTable[style].color);
|
|
|
|
(*grFontTextPtr)(str, font, size, rotate, p, &nClip, grCurObscure);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* The following definition defines how much text is offset from
|
|
* its positioning point when it isn't centered.
|
|
*/
|
|
|
|
#define TEXTOFFSET 5
|
|
|
|
|
|
/*---------------------------------------------------------
|
|
* GrPutText:
|
|
* This routine puts a chunk of text on the screen in the given
|
|
* color, size, and position. It is clipped to a rectangle.
|
|
*
|
|
* Results:
|
|
* True if the text was able to be displayed.
|
|
*
|
|
* Side Effects:
|
|
* The text is drawn on the screen at pos relative to p, using
|
|
* style (text can also be erased by passing a suitable style).
|
|
* The rectangle 'actual' is filled in with the actual location of
|
|
* the text on the screen (if actual is a non-null pointer). The
|
|
* text will be shrunk to a smaller font, if that will help it to
|
|
* fit into the clipping rectangle.
|
|
*---------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
GrPutText(str, style, p, pos, size, adjust, clip, actual)
|
|
char *str; /* The text to be drawn. */
|
|
int style; /* The style for drawing text; if -1 then
|
|
* the caller has already set the style
|
|
* and we don't have to.
|
|
*/
|
|
|
|
Point *p; /* The point to align with */
|
|
int pos; /* The alignment desired (GR_NORTH,
|
|
* GR_NORTHEAST, etc.)
|
|
*/
|
|
int size; /* The desired size of the text
|
|
* (such as GR_TEXT_MEDIUM).
|
|
*/
|
|
bool adjust; /* TRUE means adjust the text (either by
|
|
* sliding it around or using a smaller font)
|
|
* if that is necessary to make it fit into
|
|
* the clipping rectangle. FALSE means
|
|
* display the text exactly as instructed,
|
|
* clipping it if it doesn't fit.
|
|
*/
|
|
Rect *clip; /* A clipping rectangle for the text */
|
|
Rect *actual; /* To be filled in with the location of the
|
|
* text.
|
|
*/
|
|
{
|
|
Rect posR;
|
|
Point drawPoint;
|
|
int xpos, ypos, hangBelow;
|
|
Rect nClip;
|
|
|
|
nClip = *clip;
|
|
GeoClip(&nClip, &grCurClip);
|
|
|
|
GR_CHECK_LOCK();
|
|
if (!grDriverInformed) grInformDriver();
|
|
|
|
if (actual != (Rect *) NULL)
|
|
{
|
|
actual->r_xbot = actual->r_ybot = 0;
|
|
actual->r_xtop = actual->r_ytop = 0;
|
|
}
|
|
|
|
/* The following loop sees if the text will fit in the clipping
|
|
* area. If not, and shrinking is allowed, we try again and
|
|
* again with smaller sizes.
|
|
*/
|
|
|
|
while (TRUE)
|
|
{
|
|
/* what portion of the screen is taken up by the text? */
|
|
GrTextSize(str, size, &posR);
|
|
hangBelow = -posR.r_ybot;
|
|
|
|
/* figure out where the text will go, including a border on 1 side */
|
|
|
|
switch (pos) /* horizontal centering */
|
|
{
|
|
case GEO_NORTHWEST:
|
|
case GEO_WEST:
|
|
case GEO_SOUTHWEST:
|
|
xpos = p->p_x - TEXTOFFSET - posR.r_xtop;
|
|
break;
|
|
case GEO_NORTH:
|
|
case GEO_CENTER:
|
|
case GEO_SOUTH:
|
|
xpos = p->p_x - posR.r_xtop/2;
|
|
break;
|
|
case GEO_NORTHEAST:
|
|
case GEO_EAST:
|
|
case GEO_SOUTHEAST:
|
|
xpos = p->p_x + TEXTOFFSET;
|
|
break;
|
|
default:
|
|
TxError("Illegal position (%d) for text (internal error)\n",
|
|
pos);
|
|
return FALSE;
|
|
break;
|
|
}
|
|
switch (pos) /* vertical centering */
|
|
{
|
|
case GEO_NORTH:
|
|
case GEO_NORTHEAST:
|
|
case GEO_NORTHWEST:
|
|
ypos = p->p_y + TEXTOFFSET;
|
|
break;
|
|
case GEO_CENTER:
|
|
case GEO_WEST:
|
|
case GEO_EAST:
|
|
ypos = p->p_y - (posR.r_ytop / 2);
|
|
break;
|
|
case GEO_SOUTH:
|
|
case GEO_SOUTHEAST:
|
|
case GEO_SOUTHWEST:
|
|
ypos = p->p_y - posR.r_ytop - TEXTOFFSET;
|
|
break;
|
|
}
|
|
|
|
/* move area to screen coordinates */
|
|
posR.r_xbot += xpos;
|
|
posR.r_xtop += xpos;
|
|
posR.r_ybot += ypos;
|
|
posR.r_ytop += ypos;
|
|
|
|
/* will that area fit within the clipping rectangle? */
|
|
if ( (posR.r_xtop <= nClip.r_xtop) && (posR.r_xbot >= nClip.r_xbot) &&
|
|
(posR.r_ytop <= nClip.r_ytop) && (posR.r_ybot >= nClip.r_ybot) )
|
|
{
|
|
/* it fits! */
|
|
break;
|
|
}
|
|
|
|
/* it doesn't fit, will sliding it be enough? */
|
|
if (adjust)
|
|
{
|
|
if ( ((nClip.r_xtop-nClip.r_xbot) >= (posR.r_xtop - posR.r_xbot)) &&
|
|
((nClip.r_ytop - nClip.r_ybot) >= (posR.r_ytop - posR.r_ybot)) )
|
|
{
|
|
/* it will fit */
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/* Won't fit even with sliding, so shrink if possible. */
|
|
if (adjust && (size > 0) )
|
|
{
|
|
/* maybe shrinking it will help */
|
|
size -= 1;
|
|
}
|
|
else break;
|
|
|
|
} /* while */
|
|
|
|
|
|
/* ASSERTION: We've shrunk things to the proper size at this point. */
|
|
|
|
/* Slide the text, if that is allowable and needed. We'll only
|
|
* slide the text if there's available space on one side and
|
|
* insufficient space on the other.
|
|
*/
|
|
|
|
if (adjust)
|
|
{
|
|
int top, bottom, left, right; /* Space needed on each side. */
|
|
int slide;
|
|
|
|
right = posR.r_xtop - nClip.r_xtop;
|
|
left = nClip.r_xbot - posR.r_xbot;
|
|
top = posR.r_ytop - nClip.r_ytop;
|
|
bottom = nClip.r_ybot - posR.r_ybot;
|
|
|
|
slide = 0;
|
|
if (right > 0)
|
|
{
|
|
if (left < 0) slide = MAX(-right, left);
|
|
}
|
|
else if (left > 0) slide = MIN(left, -right);
|
|
posR.r_xbot += slide;
|
|
posR.r_xtop += slide;
|
|
|
|
slide = 0;
|
|
if (top > 0)
|
|
{
|
|
if (bottom < 0) slide = MAX(-top, bottom);
|
|
}
|
|
else if (bottom > 0) slide = MIN(bottom, -top);
|
|
posR.r_ybot += slide;
|
|
posR.r_ytop += slide;
|
|
}
|
|
|
|
/* ASSERTION: By now the text is positioned properly. */
|
|
|
|
/* do all clipping within the grPutTextPtr routine */
|
|
|
|
(*grSetCharSizePtr)(size);
|
|
if (style >= 0)
|
|
(*grSetWMandCPtr)(GrStyleTable[style].mask, GrStyleTable[style].color);
|
|
|
|
drawPoint.p_x = posR.r_xbot;
|
|
drawPoint.p_y = posR.r_ybot + hangBelow;
|
|
(*grPutTextPtr)(str, &drawPoint, &nClip, grCurObscure);
|
|
|
|
if (actual != (Rect *) NULL)
|
|
*actual = posR;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* GrLabelSize --
|
|
*
|
|
* Determines the total size, in pixels, of a label.
|
|
* Used to compute how much to redisplay when a label changes.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* The parameter "area" is modified to contain the size, in pixels,
|
|
* of the given label, relative to its positioning point. This
|
|
* size includes just the text, and not any marker (e.g. cross
|
|
* displayed at the label position).
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
GrLabelSize(text, pos, size, area)
|
|
char *text; /* Text of the label. */
|
|
int pos; /* Position of the label relative
|
|
* to its positioning point.
|
|
*/
|
|
int size; /* Text size. */
|
|
Rect *area; /* To be filled in with label size. */
|
|
{
|
|
int xoffset, yoffset; /* Offsets due to label position. */
|
|
|
|
GrTextSize(text, size, area);
|
|
|
|
/* Now we now the text's size... but if it's positioned to one
|
|
* side of the point, we have to offset it.
|
|
*/
|
|
|
|
switch (pos) /* Get x offset first. */
|
|
{
|
|
case GEO_NORTHWEST:
|
|
case GEO_WEST:
|
|
case GEO_SOUTHWEST:
|
|
xoffset = - TEXTOFFSET - area->r_xtop;
|
|
break;
|
|
case GEO_NORTH:
|
|
case GEO_CENTER:
|
|
case GEO_SOUTH:
|
|
xoffset = - area->r_xtop/2;
|
|
break;
|
|
case GEO_NORTHEAST:
|
|
case GEO_EAST:
|
|
case GEO_SOUTHEAST:
|
|
xoffset = TEXTOFFSET;
|
|
break;
|
|
}
|
|
switch (pos) /* Now get y offset. */
|
|
{
|
|
case GEO_NORTH:
|
|
case GEO_NORTHEAST:
|
|
case GEO_NORTHWEST:
|
|
yoffset = TEXTOFFSET;
|
|
break;
|
|
case GEO_CENTER:
|
|
case GEO_WEST:
|
|
case GEO_EAST:
|
|
yoffset = - area->r_ytop/2;
|
|
break;
|
|
case GEO_SOUTH:
|
|
case GEO_SOUTHEAST:
|
|
case GEO_SOUTHWEST:
|
|
yoffset = - area->r_ytop - TEXTOFFSET;
|
|
break;
|
|
}
|
|
|
|
area->r_xbot += xoffset;
|
|
area->r_xtop += xoffset;
|
|
area->r_ybot += yoffset;
|
|
area->r_ytop += yoffset;
|
|
}
|