Files
cdesktop/cde/programs/dtcm/dtcm/font.c
2018-04-28 12:30:20 -06:00

413 lines
10 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: font.c /main/4 1995/11/09 12:59:38 rswiston $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/AtomMgr.h>
#include <stdio.h>
#include <stdlib.h>
#include "calendar.h"
#ifndef ABS
#define ABS(x) (((x) > 0) ? (x) : (-(x)))
#endif /* ABS */
/*
* Walk a font_list looking for a FontSet with the
* XmFONTLIST_DEFAULT_TAG set. If we fail to find a FontSet with this tag,
* return the first FontSet found. If we fail to find a FontSet return
* the first font found.
*
* This function returns either a XFontStruct or a XFontSet. The type can
* be determined by the value of type_return which will equal either
* XmFONT_IS_FONTSET or XmFONT_IS_FONT.
*
* The XFontStruct or XFontSet that is returned is not a copy and should
* not be freed.
*/
static XtPointer
get_font(
XmFontList font_list,
XmFontType *type_return)
{
XmFontContext fl_context;
XmFontListEntry fl_entry;
XtPointer fl_entry_font,
font_to_use;
char *fl_entry_font_tag;
Boolean found_font_set = False,
found_font_struct = False;
*type_return = XmFONT_IS_FONT;
if (!XmFontListInitFontContext(&fl_context, font_list))
return (XtPointer)NULL;
do {
fl_entry = XmFontListNextEntry(fl_context);
if (fl_entry) {
fl_entry_font =
XmFontListEntryGetFont(fl_entry, type_return);
if (*type_return == XmFONT_IS_FONTSET) {
fl_entry_font_tag =
XmFontListEntryGetTag(fl_entry);
/*
* Save the first font set found in-
* case the default tag is not set.
*/
if (!found_font_set) {
font_to_use = fl_entry_font;
found_font_set = True;
found_font_struct = True;
if (!strcmp(XmFONTLIST_DEFAULT_TAG,
fl_entry_font_tag))
break;
} else if (!strcmp(XmFONTLIST_DEFAULT_TAG,
fl_entry_font_tag)) {
/* Found right font set */
font_to_use = fl_entry_font;
break;
}
} else if (!found_font_struct) {
font_to_use = fl_entry_font;
found_font_struct = True;
}
}
} while (fl_entry != NULL);
XmFontListFreeFontContext(fl_context);
if (!found_font_set && !found_font_struct)
return (XtPointer)NULL;
return (XtPointer)font_to_use;
}
extern Boolean
fontlist_to_font(
XmFontList font_list,
Cal_Font *cal_font)
{
XmFontType type_return;
XtPointer font_data;
if (!font_list) return False;
font_data = get_font(font_list, &type_return);
if (!font_data)
return False;
cal_font->cf_type = type_return;
if (type_return == XmFONT_IS_FONTSET)
cal_font->f.cf_fontset = (XFontSet)font_data;
else
cal_font->f.cf_font = (XFontStruct *)font_data;
return True;
}
/*
* Look for a font that is closest to the requested point size and resolution
* using the weight and family name specified.
*/
static Boolean
ProbeForFont(
Calendar *cal,
Font_Weight weight,
unsigned long target_pixel_size,
int with_foundry,
char *font_name)
{
char **font_names,
notused[48];
int i,
nnames,
size = 0,
closest_size_diff = 100000,
closest_size,
closest_index = -1;
if (!strcmp(cal->app_data->app_font_family, "application")) {
sprintf (font_name, "-%s-%s-%s-r-normal-sans-*-*-*-*-p-*",
(with_foundry)?"dt":"*",
cal->app_data->app_font_family,
(weight == BOLD)?"bold":"medium");
} else {
sprintf (font_name, "-%s-%s-%s-r-normal--*-*-*-*-*-*",
(with_foundry)?"dt":"*",
cal->app_data->app_font_family,
(weight == BOLD)?"bold":"medium");
}
/* See if the font exists */
font_names = XListFonts(XtDisplay(cal->frame), font_name, 80, &nnames);
if (!nnames) {
if (with_foundry)
return ProbeForFont(cal, weight, target_pixel_size,
FALSE, font_name);
else
return FALSE;
}
/* For the fonts that match, get their pixel size and
* look for the one with the pixel size closest to the size we are
* looking for.
*/
for (i = 0; i < nnames; i++) {
sscanf(font_names[i],
"-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]-%d-%s",
notused, notused, notused, notused, notused, notused,
&size, notused);
if (!size)
sscanf(font_names[i],
"-%[^-]-%[^-]-%[^-]-%[^-]-%[^-]--%d-%s",
notused, notused, notused, notused, notused,
&size, notused);
if (size) {
if ((ABS((int)(target_pixel_size - size)) <=
closest_size_diff)) {
closest_size_diff =
ABS((int)(target_pixel_size - size));
closest_size = size;
closest_index = i;
if (closest_size_diff == 0)
break;
}
size = 0;
}
}
if (closest_index == -1)
return FALSE;
/* This one is the closest in size */
sprintf (font_name, "-%s-%s-%s-r-normal-%s-%d-*-*-*-*-*",
(with_foundry)?"dt":"*",
cal->app_data->app_font_family,
(weight == BOLD)?"bold":"medium",
(!strcmp(cal->app_data->app_font_family, "application")) ?
"sans": "",
closest_size);
XFreeFontNames(font_names);
return TRUE;
}
extern void
load_app_font(
Calendar *cal,
Font_Weight weight,
Cal_Font *userfont,
Cal_Font *return_font)
{
unsigned long pixel_size;
Display *dpy = XtDisplay(cal->frame);
char font_name[128],
*font_name_ptr = font_name,
**font_names;
int nnames;
XrmValue in_font;
XrmValue out_fontlist;
XmFontList font_list;
Atom pixel_atom = XmInternAtom(dpy, "PIXEL_SIZE", FALSE);
/* First get the pixel size from the User Font */
if (userfont->cf_type == XmFONT_IS_FONT) {
/* If we can't get the pixel size from the user font we
* defaults to a 12 pixel font.
*/
if (!XGetFontProperty(userfont->f.cf_font, pixel_atom,
&pixel_size))
pixel_size = 12;
} else {
XFontStruct **font_struct_list;
char **font_name_list;
int list_size;
if (!(list_size = XFontsOfFontSet(userfont->f.cf_fontset,
&font_struct_list,
&font_name_list))) {
pixel_size = 12;
} else {
int i;
if (!XGetFontProperty(font_struct_list[0],
pixel_atom,
&pixel_size))
pixel_size = 12;
}
}
/* If the font family is not ``application'' then it is probably
* multibyte so we can't assume there is an add-style or a proportional
* version available.
*/
if (!strcmp(cal->app_data->app_font_family, "application")) {
sprintf (font_name, "-dt-%s-%s-r-normal-sans-%lu-*-*-*-p-*",
cal->app_data->app_font_family,
(weight == BOLD)?"bold":"medium",
pixel_size);
} else {
sprintf (font_name, "-dt-%s-%s-r-normal--%lu-*-*-*-*-*",
cal->app_data->app_font_family,
(weight == BOLD)?"bold":"medium",
pixel_size);
}
/* See if the font exists */
font_names = XListFonts(dpy, font_name, 1, &nnames);
if (!nnames) {
if (!ProbeForFont(cal, weight, pixel_size, TRUE,
font_name_ptr)) {
/* We didn't find anything */
*return_font = *userfont;
return;
}
} else
XFreeFontNames(font_names);
strcat(font_name, ":");
in_font.size = strlen(font_name);
in_font.addr = font_name;
out_fontlist.size = sizeof(XmFontList);
out_fontlist.addr = (XPointer)&font_list;
/* Convert font string to a font list. */
if (!XtConvertAndStore(cal->frame, XtRString, &in_font, XmRFontList,
&out_fontlist)) {
*return_font = *userfont;
}
if (!fontlist_to_font(font_list, return_font)) {
*return_font = *userfont;
}
}
/*
* Given a font or fontset, return the extents of the text.
*/
void
CalTextExtents(
Cal_Font *font,
char *string,
int nbytes,
int *x_return,
int *y_return,
int *width_return,
int *height_return)
{
if (!font) return;
if (font->cf_type == XmFONT_IS_FONT) {
int direction,
ascent,
descent;
XCharStruct overall;
XTextExtents(font->f.cf_font, string, nbytes,
&direction, &ascent, &descent, &overall);
*x_return = overall.lbearing;
*y_return = overall.ascent;
*width_return = overall.width;
*height_return = overall.ascent + overall.descent;
} else {
XRectangle ink,
logical;
XmbTextExtents(font->f.cf_fontset, string, nbytes,
&ink, &logical);
*x_return = logical.x;
*y_return = logical.y;
*width_return = logical.width;
*height_return = logical.height;
}
}
/*
* Given a font or fontset, render the text.
*/
void
CalDrawString(
Display *dpy,
Drawable draw,
Cal_Font *font,
GC gc,
int x,
int y,
char *string,
int length)
{
if (font->cf_type == XmFONT_IS_FONT) {
XSetFont(dpy, gc, font->f.cf_font->fid);
XDrawString(dpy, draw, gc, x, y, string, length);
} else {
XmbDrawString(dpy, draw, font->f.cf_fontset, gc, x, y,
string, length);
}
}
void
CalFontExtents(
Cal_Font *font,
XFontSetExtents *fse)
{
if (font->cf_type == XmFONT_IS_FONT) {
/*
* These computations are stolen from _XsimlCreateFontSet()
* in Xlib.
*/
fse->max_ink_extent.x = font->f.cf_font->min_bounds.lbearing;
fse->max_ink_extent.y = - font->f.cf_font->max_bounds.ascent;
fse->max_ink_extent.width = font->f.cf_font->min_bounds.width;
fse->max_ink_extent.height =
font->f.cf_font->max_bounds.ascent +
font->f.cf_font->max_bounds.descent;
fse->max_logical_extent.x = 0;
fse->max_logical_extent.y = - font->f.cf_font->ascent;
fse->max_logical_extent.width =
font->f.cf_font->max_bounds.width;
fse->max_logical_extent.height =
font->f.cf_font->ascent +
font->f.cf_font->descent;
} else {
*fse = *XExtentsOfFontSet(font->f.cf_fontset);
}
}