bitscale.c revision 23a0898a
123a0898aSmrg/* $Xorg: bitscale.c,v 1.5 2001/02/09 02:04:02 xorgcvs Exp $ */ 223a0898aSmrg/* 323a0898aSmrg 423a0898aSmrgCopyright 1991, 1994, 1998 The Open Group 523a0898aSmrg 623a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its 723a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that 823a0898aSmrgthe above copyright notice appear in all copies and that both that 923a0898aSmrgcopyright notice and this permission notice appear in supporting 1023a0898aSmrgdocumentation. 1123a0898aSmrg 1223a0898aSmrgThe above copyright notice and this permission notice shall be included 1323a0898aSmrgin all copies or substantial portions of the Software. 1423a0898aSmrg 1523a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1623a0898aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1723a0898aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1823a0898aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 1923a0898aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2023a0898aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2123a0898aSmrgOTHER DEALINGS IN THE SOFTWARE. 2223a0898aSmrg 2323a0898aSmrgExcept as contained in this notice, the name of The Open Group shall 2423a0898aSmrgnot be used in advertising or otherwise to promote the sale, use or 2523a0898aSmrgother dealings in this Software without prior written authorization 2623a0898aSmrgfrom The Open Group. 2723a0898aSmrg 2823a0898aSmrg*/ 2923a0898aSmrg/* $XFree86: xc/lib/font/bitmap/bitscale.c,v 3.29tsi Exp $ */ 3023a0898aSmrg 3123a0898aSmrg/* 3223a0898aSmrg * Author: Keith Packard, MIT X Consortium 3323a0898aSmrg */ 3423a0898aSmrg 3523a0898aSmrg#ifdef HAVE_CONFIG_H 3623a0898aSmrg#include <config.h> 3723a0898aSmrg#endif 3823a0898aSmrg 3923a0898aSmrg/* 4023a0898aSmrg * Translate monolithic #defines to modular definitions 4123a0898aSmrg */ 4223a0898aSmrg 4323a0898aSmrg#ifdef PCFFORMAT 4423a0898aSmrg#define XFONT_PCFFORMAT 1 4523a0898aSmrg#endif 4623a0898aSmrg 4723a0898aSmrg#ifdef SNFFORMAT 4823a0898aSmrg#define XFONT_SNFFORMAT 1 4923a0898aSmrg#endif 5023a0898aSmrg 5123a0898aSmrg#ifdef BDFFORMAT 5223a0898aSmrg#define XFONT_BDFFORMAT 1 5323a0898aSmrg#endif 5423a0898aSmrg 5523a0898aSmrg#include <X11/fonts/fntfilst.h> 5623a0898aSmrg#include <X11/fonts/bitmap.h> 5723a0898aSmrg#include <X11/fonts/fontutil.h> 5823a0898aSmrg#ifndef FONTMODULE 5923a0898aSmrg#ifdef _XOPEN_SOURCE 6023a0898aSmrg#include <math.h> 6123a0898aSmrg#else 6223a0898aSmrg#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ 6323a0898aSmrg#include <math.h> 6423a0898aSmrg#undef _XOPEN_SOURCE 6523a0898aSmrg#endif 6623a0898aSmrg#endif 6723a0898aSmrg 6823a0898aSmrg#ifndef MAX 6923a0898aSmrg#define MAX(a,b) (((a)>(b)) ? a : b) 7023a0898aSmrg#endif 7123a0898aSmrg 7223a0898aSmrg/* Should get this from elsewhere */ 7323a0898aSmrgextern unsigned long serverGeneration; 7423a0898aSmrg 7523a0898aSmrgstatic void bitmapUnloadScalable (FontPtr pFont); 7623a0898aSmrgstatic void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci, 7723a0898aSmrg CharInfoPtr pci, double *inv_xform, 7823a0898aSmrg double widthMult, double heightMult ); 7923a0898aSmrgstatic FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf, 8023a0898aSmrg double widthMult, double heightMult, 8123a0898aSmrg FontScalablePtr vals); 8223a0898aSmrgstatic FontPtr PrinterScaleBitmaps(FontPtr pf, FontPtr opf, 8323a0898aSmrg double widthMult, double heightMult, 8423a0898aSmrg FontScalablePtr vals); 8523a0898aSmrg 8623a0898aSmrgenum scaleType { 8723a0898aSmrg atom, truncate_atom, pixel_size, point_size, resolution_x, 8823a0898aSmrg resolution_y, average_width, scaledX, scaledY, unscaled, fontname, 8923a0898aSmrg raw_ascent, raw_descent, raw_pixelsize, raw_pointsize, 9023a0898aSmrg raw_average_width, uncomputed 9123a0898aSmrg}; 9223a0898aSmrg 9323a0898aSmrgtypedef struct _fontProp { 9423a0898aSmrg char *name; 9523a0898aSmrg Atom atom; 9623a0898aSmrg enum scaleType type; 9723a0898aSmrg} fontProp; 9823a0898aSmrg 9923a0898aSmrgtypedef FontPtr (*ScaleFunc) ( FontPtr /* pf */, 10023a0898aSmrg FontPtr /* opf */, 10123a0898aSmrg double /* widthMult */, 10223a0898aSmrg double /* heightMult */, 10323a0898aSmrg FontScalablePtr /* vals */); 10423a0898aSmrg 10523a0898aSmrg/* These next two arrays must be kept in step with the renderer array */ 10623a0898aSmrgstatic const ScaleFunc scale[] = 10723a0898aSmrg{ 10823a0898aSmrg#if XFONT_PCFFORMAT 10923a0898aSmrg BitmapScaleBitmaps, 11023a0898aSmrg BitmapScaleBitmaps, 11123a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 11223a0898aSmrg BitmapScaleBitmaps, 11323a0898aSmrg#endif 11423a0898aSmrg#endif 11523a0898aSmrg#if XFONT_SNFFORMAT 11623a0898aSmrg BitmapScaleBitmaps, 11723a0898aSmrg BitmapScaleBitmaps, 11823a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 11923a0898aSmrg BitmapScaleBitmaps, 12023a0898aSmrg#endif 12123a0898aSmrg#endif 12223a0898aSmrg#if XFONT_BDFFORMAT 12323a0898aSmrg BitmapScaleBitmaps, 12423a0898aSmrg BitmapScaleBitmaps, 12523a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 12623a0898aSmrg BitmapScaleBitmaps, 12723a0898aSmrg#endif 12823a0898aSmrg#endif 12923a0898aSmrg#if XFONT_PCFFORMAT 13023a0898aSmrg PrinterScaleBitmaps, 13123a0898aSmrg#endif 13223a0898aSmrg}; 13323a0898aSmrg 13423a0898aSmrgstatic FontEntryPtr FindBestToScale ( FontPathElementPtr fpe, 13523a0898aSmrg FontEntryPtr entry, 13623a0898aSmrg FontScalablePtr vals, 13723a0898aSmrg FontScalablePtr best, 13823a0898aSmrg double *dxp, double *dyp, 13923a0898aSmrg double *sdxp, double *sdyp, 14023a0898aSmrg FontPathElementPtr *fpep ); 14123a0898aSmrgstatic FontEntryPtr FindPmfToScale ( FontPathElementPtr fpe, 14223a0898aSmrg FontEntryPtr entry, 14323a0898aSmrg FontScalablePtr vals, 14423a0898aSmrg FontScalablePtr best, 14523a0898aSmrg double *dxp, double *dyp, 14623a0898aSmrg double *sdxp, double *sdyp, 14723a0898aSmrg FontPathElementPtr *fpep ); 14823a0898aSmrg 14923a0898aSmrgtypedef FontEntryPtr (*FindToScale) (FontPathElementPtr fpe, 15023a0898aSmrg FontEntryPtr entry, 15123a0898aSmrg FontScalablePtr vals, 15223a0898aSmrg FontScalablePtr best, 15323a0898aSmrg double *dxp, double *dyp, 15423a0898aSmrg double *sdxp, double *sdyp, 15523a0898aSmrg FontPathElementPtr *fpep); 15623a0898aSmrgstatic const FindToScale find_scale[] = 15723a0898aSmrg{ 15823a0898aSmrg#if XFONT_PCFFORMAT 15923a0898aSmrg FindBestToScale, 16023a0898aSmrg FindBestToScale, 16123a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 16223a0898aSmrg FindBestToScale, 16323a0898aSmrg#endif 16423a0898aSmrg#endif 16523a0898aSmrg#if XFONT_SNFFORMAT 16623a0898aSmrg FindBestToScale, 16723a0898aSmrg FindBestToScale, 16823a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 16923a0898aSmrg FindBestToScale, 17023a0898aSmrg#endif 17123a0898aSmrg#endif 17223a0898aSmrg#if XFONT_BDFFORMAT 17323a0898aSmrg FindBestToScale, 17423a0898aSmrg FindBestToScale, 17523a0898aSmrg#ifdef X_GZIP_FONT_COMPRESSION 17623a0898aSmrg FindBestToScale, 17723a0898aSmrg#endif 17823a0898aSmrg#endif 17923a0898aSmrg#if XFONT_PCFFORMAT 18023a0898aSmrg FindPmfToScale, 18123a0898aSmrg#endif 18223a0898aSmrg}; 18323a0898aSmrg 18423a0898aSmrgstatic unsigned long bitscaleGeneration = 0; /* initialization flag */ 18523a0898aSmrg 18623a0898aSmrgstatic fontProp fontNamePropTable[] = { 18723a0898aSmrg { "FOUNDRY", 0, atom }, 18823a0898aSmrg { "FAMILY_NAME", 0, atom }, 18923a0898aSmrg { "WEIGHT_NAME", 0, atom }, 19023a0898aSmrg { "SLANT", 0, atom }, 19123a0898aSmrg { "SETWIDTH_NAME", 0, atom }, 19223a0898aSmrg { "ADD_STYLE_NAME", 0, atom }, 19323a0898aSmrg { "PIXEL_SIZE", 0, pixel_size }, 19423a0898aSmrg { "POINT_SIZE", 0, point_size }, 19523a0898aSmrg { "RESOLUTION_X", 0, resolution_x }, 19623a0898aSmrg { "RESOLUTION_Y", 0, resolution_y }, 19723a0898aSmrg { "SPACING", 0, atom }, 19823a0898aSmrg { "AVERAGE_WIDTH", 0, average_width }, 19923a0898aSmrg { "CHARSET_REGISTRY", 0, atom }, 20023a0898aSmrg { "CHARSET_ENCODING", 0, truncate_atom }, 20123a0898aSmrg { "FONT", 0, fontname }, 20223a0898aSmrg { "RAW_ASCENT", 0, raw_ascent }, 20323a0898aSmrg { "RAW_DESCENT", 0, raw_descent }, 20423a0898aSmrg { "RAW_PIXEL_SIZE", 0, raw_pixelsize }, 20523a0898aSmrg { "RAW_POINT_SIZE", 0, raw_pointsize }, 20623a0898aSmrg { "RAW_AVERAGE_WIDTH", 0, raw_average_width } 20723a0898aSmrg}; 20823a0898aSmrg 20923a0898aSmrg#define TRANSFORM_POINT(matrix, x, y, dest) \ 21023a0898aSmrg ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ 21123a0898aSmrg (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) 21223a0898aSmrg 21323a0898aSmrg#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ 21423a0898aSmrg ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ 21523a0898aSmrg (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ 21623a0898aSmrg (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ 21723a0898aSmrg (asc) < (data)[1] ? (asc) = (data)[1] : 0) 21823a0898aSmrg 21923a0898aSmrg#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp)) 22023a0898aSmrg 22123a0898aSmrg/* Warning: order of the next two tables is critically interdependent. 22223a0898aSmrg Location of "unscaled" properties at the end of fontPropTable[] 22323a0898aSmrg is important. */ 22423a0898aSmrg 22523a0898aSmrgstatic fontProp fontPropTable[] = { 22623a0898aSmrg { "MIN_SPACE", 0, scaledX }, 22723a0898aSmrg { "NORM_SPACE", 0, scaledX }, 22823a0898aSmrg { "MAX_SPACE", 0, scaledX }, 22923a0898aSmrg { "END_SPACE", 0, scaledX }, 23023a0898aSmrg { "AVG_CAPITAL_WIDTH", 0, scaledX }, 23123a0898aSmrg { "AVG_LOWERCASE_WIDTH", 0, scaledX }, 23223a0898aSmrg { "QUAD_WIDTH", 0, scaledX }, 23323a0898aSmrg { "FIGURE_WIDTH", 0, scaledX }, 23423a0898aSmrg { "SUPERSCRIPT_X", 0, scaledX }, 23523a0898aSmrg { "SUPERSCRIPT_Y", 0, scaledY }, 23623a0898aSmrg { "SUBSCRIPT_X", 0, scaledX }, 23723a0898aSmrg { "SUBSCRIPT_Y", 0, scaledY }, 23823a0898aSmrg { "SUPERSCRIPT_SIZE", 0, scaledY }, 23923a0898aSmrg { "SUBSCRIPT_SIZE", 0, scaledY }, 24023a0898aSmrg { "SMALL_CAP_SIZE", 0, scaledY }, 24123a0898aSmrg { "UNDERLINE_POSITION", 0, scaledY }, 24223a0898aSmrg { "UNDERLINE_THICKNESS", 0, scaledY }, 24323a0898aSmrg { "STRIKEOUT_ASCENT", 0, scaledY }, 24423a0898aSmrg { "STRIKEOUT_DESCENT", 0, scaledY }, 24523a0898aSmrg { "CAP_HEIGHT", 0, scaledY }, 24623a0898aSmrg { "X_HEIGHT", 0, scaledY }, 24723a0898aSmrg { "ITALIC_ANGLE", 0, unscaled }, 24823a0898aSmrg { "RELATIVE_SETWIDTH", 0, unscaled }, 24923a0898aSmrg { "RELATIVE_WEIGHT", 0, unscaled }, 25023a0898aSmrg { "WEIGHT", 0, unscaled }, 25123a0898aSmrg { "DESTINATION", 0, unscaled }, 25223a0898aSmrg { "PCL_FONT_NAME", 0, unscaled }, 25323a0898aSmrg { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled } 25423a0898aSmrg}; 25523a0898aSmrg 25623a0898aSmrg/* sleazy way to shut up the compiler */ 25723a0898aSmrg#define zerohack (enum scaleType)0 25823a0898aSmrg 25923a0898aSmrgstatic fontProp rawFontPropTable[] = { 26023a0898aSmrg { "RAW_MIN_SPACE", 0, }, 26123a0898aSmrg { "RAW_NORM_SPACE", 0, }, 26223a0898aSmrg { "RAW_MAX_SPACE", 0, }, 26323a0898aSmrg { "RAW_END_SPACE", 0, }, 26423a0898aSmrg { "RAW_AVG_CAPITAL_WIDTH", 0, }, 26523a0898aSmrg { "RAW_AVG_LOWERCASE_WIDTH", 0, }, 26623a0898aSmrg { "RAW_QUAD_WIDTH", 0, }, 26723a0898aSmrg { "RAW_FIGURE_WIDTH", 0, }, 26823a0898aSmrg { "RAW_SUPERSCRIPT_X", 0, }, 26923a0898aSmrg { "RAW_SUPERSCRIPT_Y", 0, }, 27023a0898aSmrg { "RAW_SUBSCRIPT_X", 0, }, 27123a0898aSmrg { "RAW_SUBSCRIPT_Y", 0, }, 27223a0898aSmrg { "RAW_SUPERSCRIPT_SIZE", 0, }, 27323a0898aSmrg { "RAW_SUBSCRIPT_SIZE", 0, }, 27423a0898aSmrg { "RAW_SMALL_CAP_SIZE", 0, }, 27523a0898aSmrg { "RAW_UNDERLINE_POSITION", 0, }, 27623a0898aSmrg { "RAW_UNDERLINE_THICKNESS", 0, }, 27723a0898aSmrg { "RAW_STRIKEOUT_ASCENT", 0, }, 27823a0898aSmrg { "RAW_STRIKEOUT_DESCENT", 0, }, 27923a0898aSmrg { "RAW_CAP_HEIGHT", 0, }, 28023a0898aSmrg { "RAW_X_HEIGHT", 0, } 28123a0898aSmrg}; 28223a0898aSmrg 28323a0898aSmrgstatic void 28423a0898aSmrginitFontPropTable(void) 28523a0898aSmrg{ 28623a0898aSmrg int i; 28723a0898aSmrg fontProp *t; 28823a0898aSmrg 28923a0898aSmrg i = sizeof(fontNamePropTable) / sizeof(fontProp); 29023a0898aSmrg for (t = fontNamePropTable; i; i--, t++) 29123a0898aSmrg t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 29223a0898aSmrg 29323a0898aSmrg i = sizeof(fontPropTable) / sizeof(fontProp); 29423a0898aSmrg for (t = fontPropTable; i; i--, t++) 29523a0898aSmrg t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 29623a0898aSmrg 29723a0898aSmrg i = sizeof(rawFontPropTable) / sizeof(fontProp); 29823a0898aSmrg for (t = rawFontPropTable; i; i--, t++) 29923a0898aSmrg t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); 30023a0898aSmrg} 30123a0898aSmrg 30223a0898aSmrg#if 0 30323a0898aSmrgstatic FontEntryPtr 30423a0898aSmrgGetScalableEntry (FontPathElementPtr fpe, FontNamePtr name) 30523a0898aSmrg{ 30623a0898aSmrg FontDirectoryPtr dir; 30723a0898aSmrg 30823a0898aSmrg dir = (FontDirectoryPtr) fpe->private; 30923a0898aSmrg return FontFileFindNameInDir (&dir->scalable, name); 31023a0898aSmrg} 31123a0898aSmrg#endif 31223a0898aSmrg 31323a0898aSmrgstatic double 31423a0898aSmrgget_matrix_horizontal_component(double *matrix) 31523a0898aSmrg{ 31623a0898aSmrg return hypot(matrix[0], matrix[1]); 31723a0898aSmrg} 31823a0898aSmrg 31923a0898aSmrgstatic double 32023a0898aSmrgget_matrix_vertical_component(double *matrix) 32123a0898aSmrg{ 32223a0898aSmrg return hypot(matrix[2], matrix[3]); 32323a0898aSmrg} 32423a0898aSmrg 32523a0898aSmrg 32623a0898aSmrgstatic Bool 32723a0898aSmrgComputeScaleFactors(FontScalablePtr from, FontScalablePtr to, 32823a0898aSmrg double *dx, double *dy, double *sdx, double *sdy, 32923a0898aSmrg double *rescale_x) 33023a0898aSmrg{ 33123a0898aSmrg double srcpixelset, destpixelset, srcpixel, destpixel; 33223a0898aSmrg 33323a0898aSmrg srcpixelset = get_matrix_horizontal_component(from->pixel_matrix); 33423a0898aSmrg destpixelset = get_matrix_horizontal_component(to->pixel_matrix); 33523a0898aSmrg srcpixel = get_matrix_vertical_component(from->pixel_matrix); 33623a0898aSmrg destpixel = get_matrix_vertical_component(to->pixel_matrix); 33723a0898aSmrg 33823a0898aSmrg if (srcpixelset >= EPS) 33923a0898aSmrg { 34023a0898aSmrg *dx = destpixelset / srcpixelset; 34123a0898aSmrg *sdx = 1000.0 / srcpixelset; 34223a0898aSmrg } 34323a0898aSmrg else 34423a0898aSmrg *sdx = *dx = 0; 34523a0898aSmrg 34623a0898aSmrg *rescale_x = 1.0; 34723a0898aSmrg 34823a0898aSmrg /* If client specified a width, it overrides setsize; in this 34923a0898aSmrg context, we interpret width as applying to the font before any 35023a0898aSmrg rotation, even though that's not what is ultimately returned in 35123a0898aSmrg the width field. */ 35223a0898aSmrg if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS) 35323a0898aSmrg { 35423a0898aSmrg double rescale = (double)to->width / (double)from->width; 35523a0898aSmrg 35623a0898aSmrg /* If the client specified a transformation matrix, the rescaling 35723a0898aSmrg for width does *not* override the setsize. Instead, just check 35823a0898aSmrg for consistency between the setsize from the matrix and the 35923a0898aSmrg setsize that would result from rescaling according to the width. 36023a0898aSmrg This assumes (perhaps naively) that the width is correctly 36123a0898aSmrg reported in the name. As an interesting side effect, this test 36223a0898aSmrg may result in choosing a different source bitmap (one that 36323a0898aSmrg scales consistently between the setsize *and* the width) than it 36423a0898aSmrg would choose if a width were not specified. Sort of a hidden 36523a0898aSmrg multiple-master functionality. */ 36623a0898aSmrg if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || 36723a0898aSmrg (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) 36823a0898aSmrg { 36923a0898aSmrg /* Reject if resulting width difference is >= 1 pixel */ 37023a0898aSmrg if (fabs(rescale * from->width - *dx * from->width) >= 10) 37123a0898aSmrg return FALSE; 37223a0898aSmrg } 37323a0898aSmrg else 37423a0898aSmrg { 37523a0898aSmrg *rescale_x = rescale/(*dx); 37623a0898aSmrg *dx = rescale; 37723a0898aSmrg } 37823a0898aSmrg } 37923a0898aSmrg 38023a0898aSmrg if (srcpixel >= EPS) 38123a0898aSmrg { 38223a0898aSmrg *dy = destpixel / srcpixel; 38323a0898aSmrg *sdy = 1000.0 / srcpixel; 38423a0898aSmrg } 38523a0898aSmrg else 38623a0898aSmrg *sdy = *dy = 0; 38723a0898aSmrg 38823a0898aSmrg return TRUE; 38923a0898aSmrg} 39023a0898aSmrg 39123a0898aSmrg/* favor enlargement over reduction because of aliasing resulting 39223a0898aSmrg from reduction */ 39323a0898aSmrg#define SCORE(m,s) \ 39423a0898aSmrgif (m >= 1.0) { \ 39523a0898aSmrg if (m == 1.0) \ 39623a0898aSmrg score += (16 * s); \ 39723a0898aSmrg else if (m == 2.0) \ 39823a0898aSmrg score += (4 * s); \ 39923a0898aSmrg else \ 40023a0898aSmrg score += (int)(((double)(3 * s)) / m); \ 40123a0898aSmrg} else { \ 40223a0898aSmrg score += (int)(((double)(2 * s)) * m); \ 40323a0898aSmrg} 40423a0898aSmrg 40523a0898aSmrg/* don't need to favor enlargement when looking for bitmap that can 40623a0898aSmrg be used unscalable */ 40723a0898aSmrg#define SCORE2(m,s) \ 40823a0898aSmrgif (m >= 1.0) \ 40923a0898aSmrg score += (int)(((double)(8 * s)) / m); \ 41023a0898aSmrgelse \ 41123a0898aSmrg score += (int)(((double)(8 * s)) * m); 41223a0898aSmrg 41323a0898aSmrgstatic FontEntryPtr 41423a0898aSmrgFindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry, 41523a0898aSmrg FontScalablePtr vals, FontScalablePtr best, 41623a0898aSmrg double *dxp, double *dyp, 41723a0898aSmrg double *sdxp, double *sdyp, 41823a0898aSmrg FontPathElementPtr *fpep) 41923a0898aSmrg{ 42023a0898aSmrg FontScalableRec temp; 42123a0898aSmrg int source, i; 42223a0898aSmrg int best_score, best_unscaled_score, 42323a0898aSmrg score; 42423a0898aSmrg double dx = 0.0, sdx = 0.0, dx_amount = 0.0, 42523a0898aSmrg dy = 0.0, sdy = 0.0, dy_amount = 0.0, 42623a0898aSmrg best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0, 42723a0898aSmrg best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0, 42823a0898aSmrg best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0, 42923a0898aSmrg rescale_x = 0.0, best_rescale_x = 0.0, 43023a0898aSmrg best_unscaled_rescale_x = 0.0; 43123a0898aSmrg FontEntryPtr zero; 43223a0898aSmrg FontNameRec zeroName; 43323a0898aSmrg char zeroChars[MAXFONTNAMELEN]; 43423a0898aSmrg FontDirectoryPtr dir; 43523a0898aSmrg FontScaledPtr scaled; 43623a0898aSmrg FontScalableExtraPtr extra; 43723a0898aSmrg FontScaledPtr best_scaled, best_unscaled; 43823a0898aSmrg FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL; 43923a0898aSmrg FontEntryPtr bitmap = NULL; 44023a0898aSmrg FontEntryPtr result; 44123a0898aSmrg int aliascount = 20; 44223a0898aSmrg FontPathElementPtr bitmap_fpe = NULL; 44323a0898aSmrg FontNameRec xlfdName; 44423a0898aSmrg 44523a0898aSmrg /* find the best match */ 44623a0898aSmrg rescale_x = 1.0; 44723a0898aSmrg best_scaled = 0; 44823a0898aSmrg best_score = 0; 44923a0898aSmrg best_unscaled = 0; 45023a0898aSmrg best_unscaled_score = -1; 45123a0898aSmrg best_dx_amount = best_dy_amount = HUGE_VAL; 45223a0898aSmrg memcpy (zeroChars, entry->name.name, entry->name.length); 45323a0898aSmrg zeroChars[entry->name.length] = '\0'; 45423a0898aSmrg zeroName.name = zeroChars; 45523a0898aSmrg FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO); 45623a0898aSmrg zeroName.length = strlen (zeroChars); 45723a0898aSmrg zeroName.ndashes = entry->name.ndashes; 45823a0898aSmrg xlfdName.name = vals->xlfdName; 45923a0898aSmrg xlfdName.length = strlen(xlfdName.name); 46023a0898aSmrg xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length); 46123a0898aSmrg restart_bestscale_loop: ; 46223a0898aSmrg /* 46323a0898aSmrg * Look through all the registered bitmap sources for 46423a0898aSmrg * the same zero name as ours; entries along that one 46523a0898aSmrg * can be scaled as desired. 46623a0898aSmrg */ 46723a0898aSmrg for (source = 0; source < FontFileBitmapSources.count; source++) 46823a0898aSmrg { 46923a0898aSmrg /* There might already be a bitmap that satisfies the request 47023a0898aSmrg but didn't have a zero name that was found by the scalable 47123a0898aSmrg font matching logic. Keep track if there is. */ 47223a0898aSmrg if (bitmap == NULL && vals->xlfdName != NULL) 47323a0898aSmrg { 47423a0898aSmrg bitmap_fpe = FontFileBitmapSources.fpe[source]; 47523a0898aSmrg dir = (FontDirectoryPtr) bitmap_fpe->private; 47623a0898aSmrg bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName); 47723a0898aSmrg if (bitmap && bitmap->type != FONT_ENTRY_BITMAP) 47823a0898aSmrg { 47923a0898aSmrg if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0) 48023a0898aSmrg { 48123a0898aSmrg aliascount--; 48223a0898aSmrg xlfdName.name = bitmap->u.alias.resolved; 48323a0898aSmrg xlfdName.length = strlen(xlfdName.name); 48423a0898aSmrg xlfdName.ndashes = FontFileCountDashes(xlfdName.name, 48523a0898aSmrg xlfdName.length); 48623a0898aSmrg bitmap = NULL; 48723a0898aSmrg goto restart_bestscale_loop; 48823a0898aSmrg } 48923a0898aSmrg else 49023a0898aSmrg bitmap = NULL; 49123a0898aSmrg } 49223a0898aSmrg } 49323a0898aSmrg 49423a0898aSmrg if (FontFileBitmapSources.fpe[source] == fpe) 49523a0898aSmrg zero = entry; 49623a0898aSmrg else 49723a0898aSmrg { 49823a0898aSmrg dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; 49923a0898aSmrg zero = FontFileFindNameInDir (&dir->scalable, &zeroName); 50023a0898aSmrg if (!zero) 50123a0898aSmrg continue; 50223a0898aSmrg } 50323a0898aSmrg extra = zero->u.scalable.extra; 50423a0898aSmrg for (i = 0; i < extra->numScaled; i++) 50523a0898aSmrg { 50623a0898aSmrg scaled = &extra->scaled[i]; 50723a0898aSmrg if (!scaled->bitmap) 50823a0898aSmrg continue; 50923a0898aSmrg if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy, 51023a0898aSmrg &rescale_x)) 51123a0898aSmrg continue; 51223a0898aSmrg score = 0; 51323a0898aSmrg dx_amount = dx; 51423a0898aSmrg dy_amount = dy; 51523a0898aSmrg SCORE(dy_amount, 10); 51623a0898aSmrg SCORE(dx_amount, 1); 51723a0898aSmrg if ((score > best_score) || 51823a0898aSmrg ((score == best_score) && 51923a0898aSmrg ((dy_amount < best_dy_amount) || 52023a0898aSmrg ((dy_amount == best_dy_amount) && 52123a0898aSmrg (dx_amount < best_dx_amount))))) 52223a0898aSmrg { 52323a0898aSmrg best_fpe = FontFileBitmapSources.fpe[source]; 52423a0898aSmrg best_scaled = scaled; 52523a0898aSmrg best_score = score; 52623a0898aSmrg best_dx = dx; 52723a0898aSmrg best_dy = dy; 52823a0898aSmrg best_sdx = sdx; 52923a0898aSmrg best_sdy = sdy; 53023a0898aSmrg best_dx_amount = dx_amount; 53123a0898aSmrg best_dy_amount = dy_amount; 53223a0898aSmrg best_rescale_x = rescale_x; 53323a0898aSmrg } 53423a0898aSmrg /* Is this font a candidate for use without ugly rescaling? */ 53523a0898aSmrg if (fabs(dx) > EPS && fabs(dy) > EPS && 53623a0898aSmrg fabs(vals->pixel_matrix[0] * rescale_x - 53723a0898aSmrg scaled->vals.pixel_matrix[0]) < 1 && 53823a0898aSmrg fabs(vals->pixel_matrix[1] * rescale_x - 53923a0898aSmrg scaled->vals.pixel_matrix[1]) < EPS && 54023a0898aSmrg fabs(vals->pixel_matrix[2] - 54123a0898aSmrg scaled->vals.pixel_matrix[2]) < EPS && 54223a0898aSmrg fabs(vals->pixel_matrix[3] - 54323a0898aSmrg scaled->vals.pixel_matrix[3]) < 1) 54423a0898aSmrg { 54523a0898aSmrg /* Yes. The pixel sizes are close on the diagonal and 54623a0898aSmrg extremely close off the diagonal. */ 54723a0898aSmrg score = 0; 54823a0898aSmrg SCORE2(vals->pixel_matrix[3] / 54923a0898aSmrg scaled->vals.pixel_matrix[3], 10); 55023a0898aSmrg SCORE2(vals->pixel_matrix[0] * rescale_x / 55123a0898aSmrg scaled->vals.pixel_matrix[0], 1); 55223a0898aSmrg if (score > best_unscaled_score) 55323a0898aSmrg { 55423a0898aSmrg best_unscaled_fpe = FontFileBitmapSources.fpe[source]; 55523a0898aSmrg best_unscaled = scaled; 55623a0898aSmrg best_unscaled_sdx = sdx / dx; 55723a0898aSmrg best_unscaled_sdy = sdy / dy; 55823a0898aSmrg best_unscaled_score = score; 55923a0898aSmrg best_unscaled_rescale_x = rescale_x; 56023a0898aSmrg } 56123a0898aSmrg } 56223a0898aSmrg } 56323a0898aSmrg } 56423a0898aSmrg if (best_unscaled) 56523a0898aSmrg { 56623a0898aSmrg *best = best_unscaled->vals; 56723a0898aSmrg *fpep = best_unscaled_fpe; 56823a0898aSmrg *dxp = 1.0; 56923a0898aSmrg *dyp = 1.0; 57023a0898aSmrg *sdxp = best_unscaled_sdx; 57123a0898aSmrg *sdyp = best_unscaled_sdy; 57223a0898aSmrg rescale_x = best_unscaled_rescale_x; 57323a0898aSmrg result = best_unscaled->bitmap; 57423a0898aSmrg } 57523a0898aSmrg else if (best_scaled) 57623a0898aSmrg { 57723a0898aSmrg *best = best_scaled->vals; 57823a0898aSmrg *fpep = best_fpe; 57923a0898aSmrg *dxp = best_dx; 58023a0898aSmrg *dyp = best_dy; 58123a0898aSmrg *sdxp = best_sdx; 58223a0898aSmrg *sdyp = best_sdy; 58323a0898aSmrg rescale_x = best_rescale_x; 58423a0898aSmrg result = best_scaled->bitmap; 58523a0898aSmrg } 58623a0898aSmrg else 58723a0898aSmrg result = NULL; 58823a0898aSmrg 58923a0898aSmrg if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0)) 59023a0898aSmrg { 59123a0898aSmrg *fpep = bitmap_fpe; 59223a0898aSmrg FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE); 59323a0898aSmrg if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x)) 59423a0898aSmrg result = bitmap; 59523a0898aSmrg else 59623a0898aSmrg result = NULL; 59723a0898aSmrg } 59823a0898aSmrg 59923a0898aSmrg if (result && rescale_x != 1.0) 60023a0898aSmrg { 60123a0898aSmrg /* We have rescaled horizontally due to an XLFD width field. Change 60223a0898aSmrg the matrix appropriately */ 60323a0898aSmrg vals->pixel_matrix[0] *= rescale_x; 60423a0898aSmrg vals->pixel_matrix[1] *= rescale_x; 60523a0898aSmrg#ifdef NOTDEF 60623a0898aSmrg /* This would force the pointsize and pixelsize fields in the 60723a0898aSmrg FONT property to display as matrices to more accurately 60823a0898aSmrg report the font being supplied. It might also break existing 60923a0898aSmrg applications that expect a single number in that field. */ 61023a0898aSmrg vals->values_supplied = 61123a0898aSmrg vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) | 61223a0898aSmrg PIXELSIZE_ARRAY; 61323a0898aSmrg#else /* NOTDEF */ 61423a0898aSmrg vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; 61523a0898aSmrg#endif /* NOTDEF */ 61623a0898aSmrg /* Recompute and reround the FontScalablePtr values after 61723a0898aSmrg rescaling for the new width. */ 61823a0898aSmrg FontFileCompleteXLFD(vals, vals); 61923a0898aSmrg } 62023a0898aSmrg 62123a0898aSmrg return result; 62223a0898aSmrg} 62323a0898aSmrg 62423a0898aSmrgstatic FontEntryPtr 62523a0898aSmrgFindPmfToScale(FontPathElementPtr fpe, FontEntryPtr entry, 62623a0898aSmrg FontScalablePtr vals, FontScalablePtr best, 62723a0898aSmrg double *dxp, double *dyp, 62823a0898aSmrg double *sdxp, double *sdyp, 62923a0898aSmrg FontPathElementPtr *fpep) 63023a0898aSmrg{ 63123a0898aSmrg FontEntryPtr result = NULL; 63223a0898aSmrg FontScaledPtr scaled; 63323a0898aSmrg FontScalableExtraPtr extra; 63423a0898aSmrg int i; 63523a0898aSmrg 63623a0898aSmrg extra = entry->u.scalable.extra; 63723a0898aSmrg for (i = 0; i < extra->numScaled; i++) 63823a0898aSmrg { 63923a0898aSmrg double rescale_x; 64023a0898aSmrg 64123a0898aSmrg scaled = &extra->scaled[i]; 64223a0898aSmrg if (!scaled->bitmap) 64323a0898aSmrg continue; 64423a0898aSmrg if (!ComputeScaleFactors(&scaled->vals, vals, dxp, dyp, sdxp, sdyp, 64523a0898aSmrg &rescale_x)) 64623a0898aSmrg continue; 64723a0898aSmrg *best = scaled->vals; 64823a0898aSmrg *fpep = fpe; 64923a0898aSmrg result = scaled->bitmap; 65023a0898aSmrg if (rescale_x != 1.0) 65123a0898aSmrg { 65223a0898aSmrg /* We have rescaled horizontally due to an XLFD width field. Change 65323a0898aSmrg the matrix appropriately */ 65423a0898aSmrg vals->pixel_matrix[0] *= rescale_x; 65523a0898aSmrg vals->pixel_matrix[1] *= rescale_x; 65623a0898aSmrg#ifdef NOTDEF 65723a0898aSmrg /* This would force the pointsize and pixelsize fields in the 65823a0898aSmrg FONT property to display as matrices to more accurately 65923a0898aSmrg report the font being supplied. It might also break existing 66023a0898aSmrg applications that expect a single number in that field. */ 66123a0898aSmrg vals->values_supplied = 66223a0898aSmrg vals->values_supplied & ~(PIXELSIZE_MASK | POINTSIZE_MASK) | 66323a0898aSmrg PIXELSIZE_ARRAY; 66423a0898aSmrg#else /* NOTDEF */ 66523a0898aSmrg vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; 66623a0898aSmrg#endif /* NOTDEF */ 66723a0898aSmrg /* Recompute and reround the FontScalablePtr values after 66823a0898aSmrg rescaling for the new width. */ 66923a0898aSmrg FontFileCompleteXLFD(vals, vals); 67023a0898aSmrg } 67123a0898aSmrg break; 67223a0898aSmrg } 67323a0898aSmrg return result; 67423a0898aSmrg} 67523a0898aSmrg 67623a0898aSmrgstatic long 67723a0898aSmrgdoround(double x) 67823a0898aSmrg{ 67923a0898aSmrg return (x >= 0) ? (long)(x + .5) : (long)(x - .5); 68023a0898aSmrg} 68123a0898aSmrg 68223a0898aSmrgstatic int 68323a0898aSmrgcomputeProps(FontPropPtr pf, char *wasStringProp, 68423a0898aSmrg FontPropPtr npf, char *isStringProp, 68523a0898aSmrg unsigned int nprops, double xfactor, double yfactor, 68623a0898aSmrg double sXfactor, double sYfactor) 68723a0898aSmrg{ 68823a0898aSmrg int n; 68923a0898aSmrg int count; 69023a0898aSmrg fontProp *t; 69123a0898aSmrg double rawfactor = 0.0; 69223a0898aSmrg 69323a0898aSmrg for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) { 69423a0898aSmrg n = sizeof(fontPropTable) / sizeof(fontProp); 69523a0898aSmrg for (t = fontPropTable; n && (t->atom != pf->name); n--, t++); 69623a0898aSmrg if (!n) 69723a0898aSmrg continue; 69823a0898aSmrg 69923a0898aSmrg switch (t->type) { 70023a0898aSmrg case scaledX: 70123a0898aSmrg npf->value = doround(xfactor * (double)pf->value); 70223a0898aSmrg rawfactor = sXfactor; 70323a0898aSmrg break; 70423a0898aSmrg case scaledY: 70523a0898aSmrg npf->value = doround(yfactor * (double)pf->value); 70623a0898aSmrg rawfactor = sYfactor; 70723a0898aSmrg break; 70823a0898aSmrg case unscaled: 70923a0898aSmrg npf->value = pf->value; 71023a0898aSmrg npf->name = pf->name; 71123a0898aSmrg npf++; 71223a0898aSmrg count++; 71323a0898aSmrg *isStringProp++ = *wasStringProp; 71423a0898aSmrg break; 71523a0898aSmrg default: 71623a0898aSmrg break; 71723a0898aSmrg } 71823a0898aSmrg if (t->type != unscaled) 71923a0898aSmrg { 72023a0898aSmrg npf->name = pf->name; 72123a0898aSmrg npf++; 72223a0898aSmrg count++; 72323a0898aSmrg npf->value = doround(rawfactor * (double)pf->value); 72423a0898aSmrg npf->name = rawFontPropTable[t - fontPropTable].atom; 72523a0898aSmrg npf++; 72623a0898aSmrg count++; 72723a0898aSmrg *isStringProp++ = *wasStringProp; 72823a0898aSmrg *isStringProp++ = *wasStringProp; 72923a0898aSmrg } 73023a0898aSmrg } 73123a0898aSmrg return count; 73223a0898aSmrg} 73323a0898aSmrg 73423a0898aSmrg 73523a0898aSmrgstatic int 73623a0898aSmrgComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */ 73723a0898aSmrg char *name, /* name of resulting font */ 73823a0898aSmrg FontScalablePtr vals, 73923a0898aSmrg double dx, double dy, /* scale factors in x and y */ 74023a0898aSmrg double sdx, double sdy, /* directions */ 74123a0898aSmrg long sWidth, /* 1000-pixel average width */ 74223a0898aSmrg FontPropPtr *pProps, /* returns properties; 74323a0898aSmrg preallocated */ 74423a0898aSmrg char **pIsStringProp) /* return booleans; 74523a0898aSmrg preallocated */ 74623a0898aSmrg{ 74723a0898aSmrg int n; 74823a0898aSmrg char *ptr1 = NULL, *ptr2 = NULL; 74923a0898aSmrg char *ptr3; 75023a0898aSmrg FontPropPtr fp; 75123a0898aSmrg fontProp *fpt; 75223a0898aSmrg char *isStringProp; 75323a0898aSmrg int nProps; 75423a0898aSmrg 75523a0898aSmrg if (bitscaleGeneration != serverGeneration) { 75623a0898aSmrg initFontPropTable(); 75723a0898aSmrg bitscaleGeneration = serverGeneration; 75823a0898aSmrg } 75923a0898aSmrg nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) + 76023a0898aSmrg sizeof(rawFontPropTable) / sizeof(fontProp); 76123a0898aSmrg fp = (FontPropPtr) xalloc(sizeof(FontPropRec) * nProps); 76223a0898aSmrg *pProps = fp; 76323a0898aSmrg if (!fp) { 76423a0898aSmrg fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n", 76523a0898aSmrg (unsigned long)sizeof(FontPropRec), nProps); 76623a0898aSmrg return 1; 76723a0898aSmrg } 76823a0898aSmrg isStringProp = (char *) xalloc (nProps); 76923a0898aSmrg *pIsStringProp = isStringProp; 77023a0898aSmrg if (!isStringProp) 77123a0898aSmrg { 77223a0898aSmrg fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps); 77323a0898aSmrg xfree (fp); 77423a0898aSmrg return 1; 77523a0898aSmrg } 77623a0898aSmrg ptr2 = name; 77723a0898aSmrg for (fpt = fontNamePropTable, n = NPROPS; 77823a0898aSmrg n; 77923a0898aSmrg fp++, fpt++, n--, isStringProp++) 78023a0898aSmrg { 78123a0898aSmrg 78223a0898aSmrg if (*ptr2) 78323a0898aSmrg { 78423a0898aSmrg ptr1 = ptr2 + 1; 78523a0898aSmrg if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0'); 78623a0898aSmrg } 78723a0898aSmrg 78823a0898aSmrg *isStringProp = 0; 78923a0898aSmrg switch (fpt->type) { 79023a0898aSmrg case atom: 79123a0898aSmrg fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE); 79223a0898aSmrg *isStringProp = 1; 79323a0898aSmrg break; 79423a0898aSmrg case truncate_atom: 79523a0898aSmrg for (ptr3 = ptr1; *ptr3; ptr3++) 79623a0898aSmrg if (*ptr3 == '[') 79723a0898aSmrg break; 79823a0898aSmrg if (!*ptr3) ptr3 = ptr2; 79923a0898aSmrg fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE); 80023a0898aSmrg *isStringProp = 1; 80123a0898aSmrg break; 80223a0898aSmrg case pixel_size: 80323a0898aSmrg fp->value = doround(vals->pixel_matrix[3]); 80423a0898aSmrg break; 80523a0898aSmrg case point_size: 80623a0898aSmrg fp->value = doround(vals->point_matrix[3] * 10.0); 80723a0898aSmrg break; 80823a0898aSmrg case resolution_x: 80923a0898aSmrg fp->value = vals->x; 81023a0898aSmrg break; 81123a0898aSmrg case resolution_y: 81223a0898aSmrg fp->value = vals->y; 81323a0898aSmrg break; 81423a0898aSmrg case average_width: 81523a0898aSmrg fp->value = vals->width; 81623a0898aSmrg break; 81723a0898aSmrg case fontname: 81823a0898aSmrg fp->value = MakeAtom(name, strlen(name), TRUE); 81923a0898aSmrg *isStringProp = 1; 82023a0898aSmrg break; 82123a0898aSmrg case raw_ascent: 82223a0898aSmrg fp->value = sourceFontInfo->fontAscent * sdy; 82323a0898aSmrg break; 82423a0898aSmrg case raw_descent: 82523a0898aSmrg fp->value = sourceFontInfo->fontDescent * sdy; 82623a0898aSmrg break; 82723a0898aSmrg case raw_pointsize: 82823a0898aSmrg fp->value = (long)(72270.0 / (double)vals->y + .5); 82923a0898aSmrg break; 83023a0898aSmrg case raw_pixelsize: 83123a0898aSmrg fp->value = 1000; 83223a0898aSmrg break; 83323a0898aSmrg case raw_average_width: 83423a0898aSmrg fp->value = sWidth; 83523a0898aSmrg break; 83623a0898aSmrg default: 83723a0898aSmrg break; 83823a0898aSmrg } 83923a0898aSmrg fp->name = fpt->atom; 84023a0898aSmrg } 84123a0898aSmrg n = NPROPS; 84223a0898aSmrg n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp, 84323a0898aSmrg fp, isStringProp, sourceFontInfo->nprops, dx, dy, 84423a0898aSmrg sdx, sdy); 84523a0898aSmrg return n; 84623a0898aSmrg} 84723a0898aSmrg 84823a0898aSmrg 84923a0898aSmrgstatic int 85023a0898aSmrgcompute_xform_matrix(FontScalablePtr vals, double dx, double dy, 85123a0898aSmrg double *xform, double *inv_xform, 85223a0898aSmrg double *xmult, double *ymult) 85323a0898aSmrg{ 85423a0898aSmrg double det; 85523a0898aSmrg double pixel = get_matrix_vertical_component(vals->pixel_matrix); 85623a0898aSmrg double pixelset = get_matrix_horizontal_component(vals->pixel_matrix); 85723a0898aSmrg 85823a0898aSmrg if (pixel < EPS || pixelset < EPS) return 0; 85923a0898aSmrg 86023a0898aSmrg /* Initialize the transformation matrix to the scaling factors */ 86123a0898aSmrg xform[0] = dx / pixelset; 86223a0898aSmrg xform[1] = xform[2] = 0.0; 86323a0898aSmrg xform[3] = dy / pixel; 86423a0898aSmrg 86523a0898aSmrg/* Inline matrix multiply -- somewhat ugly to minimize register usage */ 86623a0898aSmrg#define MULTIPLY_XFORM(a,b,c,d) \ 86723a0898aSmrg{ \ 86823a0898aSmrg register double aa = (a), bb = (b), cc = (c), dd = (d); \ 86923a0898aSmrg register double temp; \ 87023a0898aSmrg temp = aa * xform[0] + cc * xform[1]; \ 87123a0898aSmrg aa = aa * xform[2] + cc * xform[3]; \ 87223a0898aSmrg xform[1] = bb * xform[0] + dd * xform[1]; \ 87323a0898aSmrg xform[3] = bb * xform[2] + dd * xform[3]; \ 87423a0898aSmrg xform[0] = temp; \ 87523a0898aSmrg xform[2] = aa; \ 87623a0898aSmrg} 87723a0898aSmrg 87823a0898aSmrg /* Rescale the transformation matrix for size of source font */ 87923a0898aSmrg MULTIPLY_XFORM(vals->pixel_matrix[0], 88023a0898aSmrg vals->pixel_matrix[1], 88123a0898aSmrg vals->pixel_matrix[2], 88223a0898aSmrg vals->pixel_matrix[3]); 88323a0898aSmrg 88423a0898aSmrg *xmult = xform[0]; 88523a0898aSmrg *ymult = xform[3]; 88623a0898aSmrg 88723a0898aSmrg 88823a0898aSmrg if (inv_xform == NULL) return 1; 88923a0898aSmrg 89023a0898aSmrg /* Compute the determinant for use in inverting the matrix. */ 89123a0898aSmrg det = xform[0] * xform[3] - xform[1] * xform[2]; 89223a0898aSmrg 89323a0898aSmrg /* If the determinant is tiny or zero, give up */ 89423a0898aSmrg if (fabs(det) < EPS) return 0; 89523a0898aSmrg 89623a0898aSmrg /* Compute the inverse */ 89723a0898aSmrg inv_xform[0] = xform[3] / det; 89823a0898aSmrg inv_xform[1] = -xform[1] / det; 89923a0898aSmrg inv_xform[2] = -xform[2] / det; 90023a0898aSmrg inv_xform[3] = xform[0] / det; 90123a0898aSmrg 90223a0898aSmrg return 1; 90323a0898aSmrg} 90423a0898aSmrg 90523a0898aSmrg/* 90623a0898aSmrg * ScaleFont 90723a0898aSmrg * returns a pointer to the new scaled font, or NULL (due to AllocError). 90823a0898aSmrg */ 90923a0898aSmrgstatic FontPtr 91023a0898aSmrgScaleFont(FontPtr opf, /* originating font */ 91123a0898aSmrg double widthMult, /* glyphs width scale factor */ 91223a0898aSmrg double heightMult, /* glyphs height scale factor */ 91323a0898aSmrg double sWidthMult, /* scalable glyphs width scale factor */ 91423a0898aSmrg double sHeightMult, /* scalable glyphs height scale factor */ 91523a0898aSmrg FontScalablePtr vals, 91623a0898aSmrg double *newWidthMult, /* return: X component of glyphs width 91723a0898aSmrg scale factor */ 91823a0898aSmrg double *newHeightMult, /* return: Y component of glyphs height 91923a0898aSmrg scale factor */ 92023a0898aSmrg long *sWidth) /* return: average 1000-pixel width */ 92123a0898aSmrg{ 92223a0898aSmrg FontPtr pf; 92323a0898aSmrg FontInfoPtr pfi, 92423a0898aSmrg opfi; 92523a0898aSmrg BitmapFontPtr bitmapFont, 92623a0898aSmrg obitmapFont; 92723a0898aSmrg CharInfoPtr pci, 92823a0898aSmrg opci; 92923a0898aSmrg int nchars = 0; /* how many characters in the font */ 93023a0898aSmrg int i; 93123a0898aSmrg int firstCol, lastCol, firstRow, lastRow; 93223a0898aSmrg double xform[4], inv_xform[4]; 93323a0898aSmrg double xmult, ymult; 93423a0898aSmrg int totalwidth = 0, totalchars = 0; 93523a0898aSmrg#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \ 93623a0898aSmrg firstRow - opf->info.firstRow) * \ 93723a0898aSmrg (opf->info.lastCol - opf->info.firstCol + 1) + \ 93823a0898aSmrg (i)%(lastCol - firstCol + 1) + \ 93923a0898aSmrg firstCol - opf->info.firstCol) 94023a0898aSmrg 94123a0898aSmrg *sWidth = 0; 94223a0898aSmrg 94323a0898aSmrg opfi = &opf->info; 94423a0898aSmrg obitmapFont = (BitmapFontPtr) opf->fontPrivate; 94523a0898aSmrg 94623a0898aSmrg bitmapFont = 0; 94723a0898aSmrg if (!(pf = CreateFontRec())) { 94823a0898aSmrg fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n", 94923a0898aSmrg (unsigned long)sizeof(FontRec)); 95023a0898aSmrg goto bail; 95123a0898aSmrg } 95223a0898aSmrg pf->refcnt = 0; 95323a0898aSmrg pf->bit = opf->bit; 95423a0898aSmrg pf->byte = opf->byte; 95523a0898aSmrg pf->glyph = opf->glyph; 95623a0898aSmrg pf->scan = opf->scan; 95723a0898aSmrg 95823a0898aSmrg pf->get_glyphs = bitmapGetGlyphs; 95923a0898aSmrg pf->get_metrics = bitmapGetMetrics; 96023a0898aSmrg pf->unload_font = bitmapUnloadScalable; 96123a0898aSmrg pf->unload_glyphs = NULL; 96223a0898aSmrg 96323a0898aSmrg pfi = &pf->info; 96423a0898aSmrg *pfi = *opfi; 96523a0898aSmrg /* If charset subsetting specified in vals, determine what our range 96623a0898aSmrg needs to be for the output font */ 96723a0898aSmrg if (vals->nranges) 96823a0898aSmrg { 96923a0898aSmrg int i; 97023a0898aSmrg 97123a0898aSmrg pfi->allExist = 0; 97223a0898aSmrg firstCol = 255; 97323a0898aSmrg lastCol = 0; 97423a0898aSmrg firstRow = 255; 97523a0898aSmrg lastRow = 0; 97623a0898aSmrg 97723a0898aSmrg for (i = 0; i < vals->nranges; i++) 97823a0898aSmrg { 97923a0898aSmrg if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high) 98023a0898aSmrg { 98123a0898aSmrg firstCol = opfi->firstCol; 98223a0898aSmrg lastCol = opfi->lastCol; 98323a0898aSmrg } 98423a0898aSmrg if (firstCol > vals->ranges[i].min_char_low) 98523a0898aSmrg firstCol = vals->ranges[i].min_char_low; 98623a0898aSmrg if (lastCol < vals->ranges[i].max_char_low) 98723a0898aSmrg lastCol = vals->ranges[i].max_char_low; 98823a0898aSmrg if (firstRow > vals->ranges[i].min_char_high) 98923a0898aSmrg firstRow = vals->ranges[i].min_char_high; 99023a0898aSmrg if (lastRow < vals->ranges[i].max_char_high) 99123a0898aSmrg lastRow = vals->ranges[i].max_char_high; 99223a0898aSmrg } 99323a0898aSmrg 99423a0898aSmrg if (firstCol > lastCol || firstRow > lastRow) 99523a0898aSmrg goto bail; 99623a0898aSmrg 99723a0898aSmrg if (firstCol < opfi->firstCol) 99823a0898aSmrg firstCol = opfi->firstCol; 99923a0898aSmrg if (lastCol > opfi->lastCol) 100023a0898aSmrg lastCol = opfi->lastCol; 100123a0898aSmrg if (firstRow < opfi->firstRow) 100223a0898aSmrg firstRow = opfi->firstRow; 100323a0898aSmrg if (lastRow > opfi->lastRow) 100423a0898aSmrg lastRow = opfi->lastRow; 100523a0898aSmrg } 100623a0898aSmrg else 100723a0898aSmrg { 100823a0898aSmrg firstCol = opfi->firstCol; 100923a0898aSmrg lastCol = opfi->lastCol; 101023a0898aSmrg firstRow = opfi->firstRow; 101123a0898aSmrg lastRow = opfi->lastRow; 101223a0898aSmrg } 101323a0898aSmrg 101423a0898aSmrg bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec)); 101523a0898aSmrg if (!bitmapFont) { 101623a0898aSmrg fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n", 101723a0898aSmrg (unsigned long)sizeof(BitmapFontRec)); 101823a0898aSmrg goto bail; 101923a0898aSmrg } 102023a0898aSmrg nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 102123a0898aSmrg pfi->firstRow = firstRow; 102223a0898aSmrg pfi->lastRow = lastRow; 102323a0898aSmrg pfi->firstCol = firstCol; 102423a0898aSmrg pfi->lastCol = lastCol; 102523a0898aSmrg pf->fontPrivate = (pointer) bitmapFont; 102623a0898aSmrg bitmapFont->version_num = obitmapFont->version_num; 102723a0898aSmrg bitmapFont->num_chars = nchars; 102823a0898aSmrg bitmapFont->num_tables = obitmapFont->num_tables; 102923a0898aSmrg bitmapFont->metrics = 0; 103023a0898aSmrg bitmapFont->ink_metrics = 0; 103123a0898aSmrg bitmapFont->bitmaps = 0; 103223a0898aSmrg bitmapFont->encoding = 0; 103323a0898aSmrg bitmapFont->bitmapExtra = 0; 103423a0898aSmrg bitmapFont->pDefault = 0; 103523a0898aSmrg bitmapFont->metrics = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec)); 103623a0898aSmrg if (!bitmapFont->metrics) { 103723a0898aSmrg fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n", 103823a0898aSmrg nchars, (unsigned long)sizeof(CharInfoRec)); 103923a0898aSmrg goto bail; 104023a0898aSmrg } 104123a0898aSmrg bitmapFont->encoding = 104223a0898aSmrg (CharInfoPtr **) xcalloc(NUM_SEGMENTS(nchars), 104323a0898aSmrg sizeof(CharInfoPtr*)); 104423a0898aSmrg if (!bitmapFont->encoding) { 104523a0898aSmrg fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n", 104623a0898aSmrg nchars, (unsigned long)sizeof(CharInfoPtr)); 104723a0898aSmrg goto bail; 104823a0898aSmrg } 104923a0898aSmrg 105023a0898aSmrg#undef MAXSHORT 105123a0898aSmrg#define MAXSHORT 32767 105223a0898aSmrg#undef MINSHORT 105323a0898aSmrg#define MINSHORT -32768 105423a0898aSmrg 105523a0898aSmrg pfi->anamorphic = FALSE; 105623a0898aSmrg if (heightMult != widthMult) 105723a0898aSmrg pfi->anamorphic = TRUE; 105823a0898aSmrg pfi->cachable = TRUE; 105923a0898aSmrg 106023a0898aSmrg if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 106123a0898aSmrg inv_xform, &xmult, &ymult)) 106223a0898aSmrg goto bail; 106323a0898aSmrg 106423a0898aSmrg pfi->fontAscent = opfi->fontAscent * ymult; 106523a0898aSmrg pfi->fontDescent = opfi->fontDescent * ymult; 106623a0898aSmrg 106723a0898aSmrg pfi->minbounds.leftSideBearing = MAXSHORT; 106823a0898aSmrg pfi->minbounds.rightSideBearing = MAXSHORT; 106923a0898aSmrg pfi->minbounds.ascent = MAXSHORT; 107023a0898aSmrg pfi->minbounds.descent = MAXSHORT; 107123a0898aSmrg pfi->minbounds.characterWidth = MAXSHORT; 107223a0898aSmrg pfi->minbounds.attributes = MAXSHORT; 107323a0898aSmrg 107423a0898aSmrg pfi->maxbounds.leftSideBearing = MINSHORT; 107523a0898aSmrg pfi->maxbounds.rightSideBearing = MINSHORT; 107623a0898aSmrg pfi->maxbounds.ascent = MINSHORT; 107723a0898aSmrg pfi->maxbounds.descent = MINSHORT; 107823a0898aSmrg pfi->maxbounds.characterWidth = MINSHORT; 107923a0898aSmrg pfi->maxbounds.attributes = MINSHORT; 108023a0898aSmrg 108123a0898aSmrg /* Compute the transformation and inverse transformation matrices. 108223a0898aSmrg Can fail if the determinant is zero. */ 108323a0898aSmrg 108423a0898aSmrg pci = bitmapFont->metrics; 108523a0898aSmrg for (i = 0; i < nchars; i++) 108623a0898aSmrg { 108723a0898aSmrg if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) 108823a0898aSmrg { 108923a0898aSmrg double newlsb, newrsb, newdesc, newasc, point[2]; 109023a0898aSmrg 109123a0898aSmrg#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) 109223a0898aSmrg#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) 109323a0898aSmrg 109423a0898aSmrg if (vals->nranges) 109523a0898aSmrg { 109623a0898aSmrg int row = i / (lastCol - firstCol + 1) + firstRow; 109723a0898aSmrg int col = i % (lastCol - firstCol + 1) + firstCol; 109823a0898aSmrg int ch = (row << 8) + col; 109923a0898aSmrg int j; 110023a0898aSmrg for (j = 0; j < vals->nranges; j++) 110123a0898aSmrg if (ch >= minchar(vals->ranges[j]) && 110223a0898aSmrg ch <= maxchar(vals->ranges[j])) 110323a0898aSmrg break; 110423a0898aSmrg if (j == vals->nranges) 110523a0898aSmrg { 110623a0898aSmrg continue; 110723a0898aSmrg } 110823a0898aSmrg } 110923a0898aSmrg 111023a0898aSmrg if (opci->metrics.leftSideBearing == 0 && 111123a0898aSmrg opci->metrics.rightSideBearing == 0 && 111223a0898aSmrg opci->metrics.ascent == 0 && 111323a0898aSmrg opci->metrics.descent == 0 && 111423a0898aSmrg opci->metrics.characterWidth == 0) 111523a0898aSmrg { 111623a0898aSmrg continue; 111723a0898aSmrg } 111823a0898aSmrg 111923a0898aSmrg if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { 112023a0898aSmrg bitmapFont->encoding[SEGMENT_MAJOR(i)]= 112123a0898aSmrg (CharInfoPtr*)xcalloc(BITMAP_FONT_SEGMENT_SIZE, 112223a0898aSmrg sizeof(CharInfoPtr)); 112323a0898aSmrg if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) 112423a0898aSmrg goto bail; 112523a0898aSmrg } 112623a0898aSmrg ACCESSENCODINGL(bitmapFont->encoding, i) = pci; 112723a0898aSmrg 112823a0898aSmrg /* Compute new extents for this glyph */ 112923a0898aSmrg TRANSFORM_POINT(xform, 113023a0898aSmrg opci->metrics.leftSideBearing, 113123a0898aSmrg -opci->metrics.descent, 113223a0898aSmrg point); 113323a0898aSmrg newlsb = point[0]; 113423a0898aSmrg newrsb = newlsb; 113523a0898aSmrg newdesc = -point[1]; 113623a0898aSmrg newasc = -newdesc; 113723a0898aSmrg TRANSFORM_POINT(xform, 113823a0898aSmrg opci->metrics.leftSideBearing, 113923a0898aSmrg opci->metrics.ascent, 114023a0898aSmrg point); 114123a0898aSmrg CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 114223a0898aSmrg TRANSFORM_POINT(xform, 114323a0898aSmrg opci->metrics.rightSideBearing, 114423a0898aSmrg -opci->metrics.descent, 114523a0898aSmrg point); 114623a0898aSmrg CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 114723a0898aSmrg TRANSFORM_POINT(xform, 114823a0898aSmrg opci->metrics.rightSideBearing, 114923a0898aSmrg opci->metrics.ascent, 115023a0898aSmrg point); 115123a0898aSmrg CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); 115223a0898aSmrg 115323a0898aSmrg pci->metrics.leftSideBearing = (int)floor(newlsb); 115423a0898aSmrg pci->metrics.rightSideBearing = (int)floor(newrsb + .5); 115523a0898aSmrg pci->metrics.descent = (int)ceil(newdesc); 115623a0898aSmrg pci->metrics.ascent = (int)floor(newasc + .5); 115723a0898aSmrg /* Accumulate total width of characters before transformation, 115823a0898aSmrg to ascertain predominant direction of font. */ 115923a0898aSmrg totalwidth += opci->metrics.characterWidth; 116023a0898aSmrg pci->metrics.characterWidth = 116123a0898aSmrg doround((double)opci->metrics.characterWidth * xmult); 116223a0898aSmrg pci->metrics.attributes = 116323a0898aSmrg doround((double)opci->metrics.characterWidth * sWidthMult); 116423a0898aSmrg if (!pci->metrics.characterWidth) 116523a0898aSmrg { 116623a0898aSmrg /* Since transformation may shrink width, height, and 116723a0898aSmrg escapement to zero, make sure existing characters 116823a0898aSmrg are not mistaken for undefined characters. */ 116923a0898aSmrg 117023a0898aSmrg if (pci->metrics.rightSideBearing == 117123a0898aSmrg pci->metrics.leftSideBearing) 117223a0898aSmrg pci->metrics.rightSideBearing++; 117323a0898aSmrg if (pci->metrics.ascent == -pci->metrics.descent) 117423a0898aSmrg pci->metrics.ascent++; 117523a0898aSmrg } 117623a0898aSmrg 117723a0898aSmrg pci++; 117823a0898aSmrg } 117923a0898aSmrg } 118023a0898aSmrg 118123a0898aSmrg 118223a0898aSmrg /* 118323a0898aSmrg * For each character, set the per-character metrics, scale the glyph, and 118423a0898aSmrg * check per-font minbounds and maxbounds character information. 118523a0898aSmrg */ 118623a0898aSmrg 118723a0898aSmrg pci = bitmapFont->metrics; 118823a0898aSmrg for (i = 0; i < nchars; i++) 118923a0898aSmrg { 119023a0898aSmrg if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) && 119123a0898aSmrg (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) 119223a0898aSmrg { 119323a0898aSmrg totalchars++; 119423a0898aSmrg *sWidth += abs((int)(INT16)pci->metrics.attributes); 119523a0898aSmrg#define MINMAX(field) \ 119623a0898aSmrg if (pfi->minbounds.field > pci->metrics.field) \ 119723a0898aSmrg pfi->minbounds.field = pci->metrics.field; \ 119823a0898aSmrg if (pfi->maxbounds.field < pci->metrics.field) \ 119923a0898aSmrg pfi->maxbounds.field = pci->metrics.field 120023a0898aSmrg 120123a0898aSmrg MINMAX(leftSideBearing); 120223a0898aSmrg MINMAX(rightSideBearing); 120323a0898aSmrg MINMAX(ascent); 120423a0898aSmrg MINMAX(descent); 120523a0898aSmrg MINMAX(characterWidth); 120623a0898aSmrg 120723a0898aSmrg /* Hack: Cast attributes into a signed quantity. Tread lightly 120823a0898aSmrg for now and don't go changing the global Xproto.h file */ 120923a0898aSmrg if ((INT16)pfi->minbounds.attributes > 121023a0898aSmrg (INT16)pci->metrics.attributes) 121123a0898aSmrg pfi->minbounds.attributes = pci->metrics.attributes; 121223a0898aSmrg if ((INT16)pfi->maxbounds.attributes < 121323a0898aSmrg (INT16)pci->metrics.attributes) 121423a0898aSmrg pfi->maxbounds.attributes = pci->metrics.attributes; 121523a0898aSmrg#undef MINMAX 121623a0898aSmrg } 121723a0898aSmrg } 121823a0898aSmrg pfi->ink_minbounds = pfi->minbounds; 121923a0898aSmrg pfi->ink_maxbounds = pfi->maxbounds; 122023a0898aSmrg if (totalchars) 122123a0898aSmrg { 122223a0898aSmrg *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars; 122323a0898aSmrg if (totalwidth < 0) 122423a0898aSmrg { 122523a0898aSmrg /* Dominant direction is R->L */ 122623a0898aSmrg *sWidth = -*sWidth; 122723a0898aSmrg } 122823a0898aSmrg 122923a0898aSmrg if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth) 123023a0898aSmrg vals->width = pfi->minbounds.characterWidth * 10; 123123a0898aSmrg else 123223a0898aSmrg vals->width = doround((double)*sWidth * vals->pixel_matrix[0] / 123323a0898aSmrg 1000.0); 123423a0898aSmrg } 123523a0898aSmrg else 123623a0898aSmrg { 123723a0898aSmrg vals->width = 0; 123823a0898aSmrg *sWidth = 0; 123923a0898aSmrg } 124023a0898aSmrg FontComputeInfoAccelerators (pfi); 124123a0898aSmrg 124223a0898aSmrg if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) { 124323a0898aSmrg unsigned int r, 124423a0898aSmrg c, 124523a0898aSmrg cols; 124623a0898aSmrg 124723a0898aSmrg r = pfi->defaultCh >> 8; 124823a0898aSmrg c = pfi->defaultCh & 0xFF; 124923a0898aSmrg if (pfi->firstRow <= r && r <= pfi->lastRow && 125023a0898aSmrg pfi->firstCol <= c && c <= pfi->lastCol) { 125123a0898aSmrg cols = pfi->lastCol - pfi->firstCol + 1; 125223a0898aSmrg r = r - pfi->firstRow; 125323a0898aSmrg c = c - pfi->firstCol; 125423a0898aSmrg bitmapFont->pDefault = 125523a0898aSmrg ACCESSENCODING(bitmapFont->encoding, r * cols + c); 125623a0898aSmrg } 125723a0898aSmrg } 125823a0898aSmrg 125923a0898aSmrg *newWidthMult = xmult; 126023a0898aSmrg *newHeightMult = ymult; 126123a0898aSmrg return pf; 126223a0898aSmrgbail: 126323a0898aSmrg if (pf) 126423a0898aSmrg xfree(pf); 126523a0898aSmrg if (bitmapFont) { 126623a0898aSmrg xfree(bitmapFont->metrics); 126723a0898aSmrg xfree(bitmapFont->ink_metrics); 126823a0898aSmrg xfree(bitmapFont->bitmaps); 126923a0898aSmrg if(bitmapFont->encoding) 127023a0898aSmrg for(i=0; i<NUM_SEGMENTS(nchars); i++) 127123a0898aSmrg xfree(bitmapFont->encoding[i]); 127223a0898aSmrg xfree(bitmapFont->encoding); 127323a0898aSmrg } 127423a0898aSmrg return NULL; 127523a0898aSmrg} 127623a0898aSmrg 127723a0898aSmrgstatic void 127823a0898aSmrgScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci, 127923a0898aSmrg double *inv_xform, double widthMult, double heightMult) 128023a0898aSmrg{ 128123a0898aSmrg register char *bitmap, /* The bits */ 128223a0898aSmrg *newBitmap; 128323a0898aSmrg register int bpr, /* Padding information */ 128423a0898aSmrg newBpr; 128523a0898aSmrg int width, /* Extents information */ 128623a0898aSmrg height, 128723a0898aSmrg newWidth, 128823a0898aSmrg newHeight; 128923a0898aSmrg register int row, /* Loop variables */ 129023a0898aSmrg col; 129123a0898aSmrg INT32 deltaX, /* Increments for resampling loop */ 129223a0898aSmrg deltaY; 129323a0898aSmrg INT32 xValue, /* Subscripts for resampling loop */ 129423a0898aSmrg yValue; 129523a0898aSmrg double point[2]; 129623a0898aSmrg unsigned char *char_grayscale = 0; 129723a0898aSmrg INT32 *diffusion_workspace = NULL, *thisrow = NULL, 129823a0898aSmrg *nextrow = NULL, pixmult = 0; 129923a0898aSmrg int box_x = 0, box_y = 0; 130023a0898aSmrg 130123a0898aSmrg static unsigned char masklsb[] = 130223a0898aSmrg { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; 130323a0898aSmrg static unsigned char maskmsb[] = 130423a0898aSmrg { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; 130523a0898aSmrg unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb); 130623a0898aSmrg 130723a0898aSmrg 130823a0898aSmrg bitmap = opci->bits; 130923a0898aSmrg newBitmap = pci->bits; 131023a0898aSmrg width = GLYPHWIDTHPIXELS(opci); 131123a0898aSmrg height = GLYPHHEIGHTPIXELS(opci); 131223a0898aSmrg newWidth = GLYPHWIDTHPIXELS(pci); 131323a0898aSmrg newHeight = GLYPHHEIGHTPIXELS(pci); 131423a0898aSmrg if (!newWidth || !newHeight || !width || !height) 131523a0898aSmrg return; 131623a0898aSmrg 131723a0898aSmrg bpr = BYTES_PER_ROW(width, pFont->glyph); 131823a0898aSmrg newBpr = BYTES_PER_ROW(newWidth, pFont->glyph); 131923a0898aSmrg 132023a0898aSmrg if (widthMult > 0.0 && heightMult > 0.0 && 132123a0898aSmrg (widthMult < 1.0 || heightMult < 1.0)) 132223a0898aSmrg { 132323a0898aSmrg /* We are reducing in one or both dimensions. In an attempt to 132423a0898aSmrg reduce aliasing, we'll antialias by passing the original 132523a0898aSmrg glyph through a low-pass box filter (which results in a 132623a0898aSmrg grayscale image), then use error diffusion to create bitonal 132723a0898aSmrg output in the resampling loop. */ 132823a0898aSmrg 132923a0898aSmrg /* First compute the sizes of the box filter */ 133023a0898aSmrg widthMult = ceil(1.0 / widthMult); 133123a0898aSmrg heightMult = ceil(1.0 / heightMult); 133223a0898aSmrg box_x = width / 2; 133323a0898aSmrg box_y = height / 2; 133423a0898aSmrg if (widthMult < (double)box_x) box_x = (int)widthMult; 133523a0898aSmrg if (heightMult < (double)box_y) box_y = (int)heightMult; 133623a0898aSmrg /* The pixmult value (below) is used to darken the image before 133723a0898aSmrg we perform error diffusion: a necessary concession to the 133823a0898aSmrg fact that it's very difficult to generate readable halftoned 133923a0898aSmrg glyphs. The degree of darkening is proportional to the size 134023a0898aSmrg of the blurring filter, hence inversely proportional to the 134123a0898aSmrg darkness of the lightest gray that results from antialiasing. 134223a0898aSmrg The result is that characters that exercise this logic (those 134323a0898aSmrg generated by reducing from a larger source font) tend to err 134423a0898aSmrg on the side of being too bold instead of being too light to 134523a0898aSmrg be readable. */ 134623a0898aSmrg pixmult = box_x * box_y * 192; 134723a0898aSmrg 134823a0898aSmrg if (box_x > 1 || box_y > 1) 134923a0898aSmrg { 135023a0898aSmrg /* Looks like we need to anti-alias. Create a workspace to 135123a0898aSmrg contain the grayscale character plus an additional row and 135223a0898aSmrg column for scratch */ 135323a0898aSmrg char_grayscale = 135423a0898aSmrg (unsigned char *)xalloc((width + 1) * (height + 1)); 135523a0898aSmrg if (char_grayscale) 135623a0898aSmrg { 135723a0898aSmrg diffusion_workspace = 135823a0898aSmrg (INT32 *)xalloc((newWidth + 2) * 2 * sizeof(int)); 135923a0898aSmrg if (!diffusion_workspace) 136023a0898aSmrg { 136123a0898aSmrg fprintf(stderr, "Warning: Couldn't allocate diffusion" 136223a0898aSmrg " workspace (%ld)\n", 136323a0898aSmrg (newWidth + 2) * 2 * (unsigned long)sizeof(int)); 136423a0898aSmrg xfree(char_grayscale); 136523a0898aSmrg char_grayscale = (unsigned char *)0; 136623a0898aSmrg } 136723a0898aSmrg /* Initialize our error diffusion workspace for later use */ 136823a0898aSmrg bzero((char *)diffusion_workspace + sizeof(INT32), 136923a0898aSmrg (newWidth + 3) * sizeof(int)); 137023a0898aSmrg thisrow = diffusion_workspace + 1; 137123a0898aSmrg nextrow = diffusion_workspace + newWidth + 3; 137223a0898aSmrg } else { 137323a0898aSmrg fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1)); 137423a0898aSmrg } 137523a0898aSmrg } 137623a0898aSmrg } 137723a0898aSmrg 137823a0898aSmrg if (char_grayscale) 137923a0898aSmrg { 138023a0898aSmrg /* We will be doing antialiasing. First copy the bitmap into 138123a0898aSmrg our buffer, mapping input range [0,1] to output range 138223a0898aSmrg [0,255]. */ 138323a0898aSmrg register unsigned char *srcptr, *dstptr; 138423a0898aSmrg srcptr = (unsigned char *)bitmap; 138523a0898aSmrg dstptr = char_grayscale; 138623a0898aSmrg for (row = 0; row < height; row++) 138723a0898aSmrg { 138823a0898aSmrg for (col = 0; col < width; col++) 138923a0898aSmrg *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0; 139023a0898aSmrg srcptr += bpr; /* On to next row of source */ 139123a0898aSmrg dstptr++; /* Skip scratch column in dest */ 139223a0898aSmrg } 139323a0898aSmrg if (box_x > 1) 139423a0898aSmrg { 139523a0898aSmrg /* Our box filter has a width > 1... let's filter the rows */ 139623a0898aSmrg 139723a0898aSmrg int right_width = box_x / 2; 139823a0898aSmrg int left_width = box_x - right_width - 1; 139923a0898aSmrg 140023a0898aSmrg for (row = 0; row < height; row++) 140123a0898aSmrg { 140223a0898aSmrg int sum = 0; 140323a0898aSmrg int left_size = 0, right_size = 0; 140423a0898aSmrg 140523a0898aSmrg srcptr = char_grayscale + (width + 1) * row; 140623a0898aSmrg dstptr = char_grayscale + (width + 1) * height; /* scratch */ 140723a0898aSmrg 140823a0898aSmrg /* We've computed the shape of our full box filter. Now 140923a0898aSmrg compute the right-hand part of the moving sum */ 141023a0898aSmrg for (right_size = 0; right_size < right_width; right_size++) 141123a0898aSmrg sum += srcptr[right_size]; 141223a0898aSmrg 141323a0898aSmrg /* Now start moving the sum, growing the box filter, and 141423a0898aSmrg dropping averages into our scratch buffer */ 141523a0898aSmrg for (left_size = 0; left_size < left_width; left_size++) 141623a0898aSmrg { 141723a0898aSmrg sum += srcptr[right_width]; 141823a0898aSmrg *dstptr++ = sum / (left_size + right_width + 1); 141923a0898aSmrg srcptr++; 142023a0898aSmrg } 142123a0898aSmrg 142223a0898aSmrg /* The box filter has reached full width... continue 142323a0898aSmrg computation of moving average until the right side 142423a0898aSmrg hits the wall. */ 142523a0898aSmrg for (col = left_size; col + right_size < width; col++) 142623a0898aSmrg { 142723a0898aSmrg sum += srcptr[right_width]; 142823a0898aSmrg *dstptr++ = sum / box_x; 142923a0898aSmrg sum -= srcptr[-left_width]; 143023a0898aSmrg srcptr++; 143123a0898aSmrg } 143223a0898aSmrg 143323a0898aSmrg /* Collapse the right side of the box filter */ 143423a0898aSmrg for (; right_size > 0; right_size--) 143523a0898aSmrg { 143623a0898aSmrg *dstptr++ = sum / (left_width + right_size); 143723a0898aSmrg sum -= srcptr[-left_width]; 143823a0898aSmrg srcptr++; 143923a0898aSmrg } 144023a0898aSmrg 144123a0898aSmrg /* Done with the row... copy dest back over source */ 144223a0898aSmrg memmove(char_grayscale + (width + 1) * row, 144323a0898aSmrg char_grayscale + (width + 1) * height, 144423a0898aSmrg width); 144523a0898aSmrg } 144623a0898aSmrg } 144723a0898aSmrg if (box_y > 1) 144823a0898aSmrg { 144923a0898aSmrg /* Our box filter has a height > 1... let's filter the columns */ 145023a0898aSmrg 145123a0898aSmrg int bottom_height = box_y / 2; 145223a0898aSmrg int top_height = box_y - bottom_height - 1; 145323a0898aSmrg 145423a0898aSmrg for (col = 0; col < width; col++) 145523a0898aSmrg { 145623a0898aSmrg int sum = 0; 145723a0898aSmrg int top_size = 0, bottom_size = 0; 145823a0898aSmrg 145923a0898aSmrg srcptr = char_grayscale + col; 146023a0898aSmrg dstptr = char_grayscale + width; /* scratch */ 146123a0898aSmrg 146223a0898aSmrg /* We've computed the shape of our full box filter. Now 146323a0898aSmrg compute the bottom part of the moving sum */ 146423a0898aSmrg for (bottom_size = 0; 146523a0898aSmrg bottom_size < bottom_height; 146623a0898aSmrg bottom_size++) 146723a0898aSmrg sum += srcptr[bottom_size * (width + 1)]; 146823a0898aSmrg 146923a0898aSmrg /* Now start moving the sum, growing the box filter, and 147023a0898aSmrg dropping averages into our scratch buffer */ 147123a0898aSmrg for (top_size = 0; top_size < top_height; top_size++) 147223a0898aSmrg { 147323a0898aSmrg sum += srcptr[bottom_height * (width + 1)]; 147423a0898aSmrg *dstptr = sum / (top_size + bottom_height + 1); 147523a0898aSmrg dstptr += width + 1; 147623a0898aSmrg srcptr += width + 1; 147723a0898aSmrg } 147823a0898aSmrg 147923a0898aSmrg /* The box filter has reached full height... continue 148023a0898aSmrg computation of moving average until the bottom 148123a0898aSmrg hits the wall. */ 148223a0898aSmrg for (row = top_size; row + bottom_size < height; row++) 148323a0898aSmrg { 148423a0898aSmrg sum += srcptr[bottom_height * (width + 1)]; 148523a0898aSmrg *dstptr = sum / box_y; 148623a0898aSmrg dstptr += width + 1; 148723a0898aSmrg sum -= srcptr[-top_height * (width + 1)]; 148823a0898aSmrg srcptr += width + 1; 148923a0898aSmrg } 149023a0898aSmrg 149123a0898aSmrg /* Collapse the bottom of the box filter */ 149223a0898aSmrg for (; bottom_size > 0; bottom_size--) 149323a0898aSmrg { 149423a0898aSmrg *dstptr = sum / (top_height + bottom_size); 149523a0898aSmrg dstptr += width + 1; 149623a0898aSmrg sum -= srcptr[-top_height * (width + 1)]; 149723a0898aSmrg srcptr += width + 1; 149823a0898aSmrg } 149923a0898aSmrg 150023a0898aSmrg /* Done with the column... copy dest back over source */ 150123a0898aSmrg 150223a0898aSmrg dstptr = char_grayscale + col; 150323a0898aSmrg srcptr = char_grayscale + width; /* scratch */ 150423a0898aSmrg for (row = 0; row < height; row++) 150523a0898aSmrg { 150623a0898aSmrg *dstptr = *srcptr; 150723a0898aSmrg dstptr += width + 1; 150823a0898aSmrg srcptr += width + 1; 150923a0898aSmrg } 151023a0898aSmrg } 151123a0898aSmrg } 151223a0898aSmrg 151323a0898aSmrg /* Increase the grayvalue to increase ink a bit */ 151423a0898aSmrg srcptr = char_grayscale; 151523a0898aSmrg for (row = 0; row < height; row++) 151623a0898aSmrg { 151723a0898aSmrg for (col = 0; col < width; col++) 151823a0898aSmrg { 151923a0898aSmrg register int pixvalue = (int)*srcptr * pixmult / 256; 152023a0898aSmrg if (pixvalue > 255) pixvalue = 255; 152123a0898aSmrg *srcptr = pixvalue; 152223a0898aSmrg srcptr++; 152323a0898aSmrg } 152423a0898aSmrg srcptr++; 152523a0898aSmrg } 152623a0898aSmrg } 152723a0898aSmrg 152823a0898aSmrg /* Compute the increment values for the resampling loop */ 152923a0898aSmrg TRANSFORM_POINT(inv_xform, 1, 0, point); 153023a0898aSmrg deltaX = (INT32)(point[0] * 65536.0); 153123a0898aSmrg deltaY = (INT32)(-point[1] * 65536.0); 153223a0898aSmrg 153323a0898aSmrg /* Resampling loop: resamples original glyph for generation of new 153423a0898aSmrg glyph in transformed coordinate system. */ 153523a0898aSmrg 153623a0898aSmrg for (row = 0; row < newHeight; row++) 153723a0898aSmrg { 153823a0898aSmrg /* Compute inverse transformation for start of this row */ 153923a0898aSmrg TRANSFORM_POINT(inv_xform, 154023a0898aSmrg (double)(pci->metrics.leftSideBearing) + .5, 154123a0898aSmrg (double)(pci->metrics.ascent - row) - .5, 154223a0898aSmrg point); 154323a0898aSmrg 154423a0898aSmrg /* Adjust for coordinate system to get resampling point */ 154523a0898aSmrg point[0] -= opci->metrics.leftSideBearing; 154623a0898aSmrg point[1] = opci->metrics.ascent - point[1]; 154723a0898aSmrg 154823a0898aSmrg /* Convert to integer coordinates */ 154923a0898aSmrg xValue = (INT32)(point[0] * 65536.0); 155023a0898aSmrg yValue = (INT32)(point[1] * 65536.0); 155123a0898aSmrg 155223a0898aSmrg if (char_grayscale) 155323a0898aSmrg { 155423a0898aSmrg INT32 *temp; 155523a0898aSmrg for (col = 0; col < newWidth; col++) 155623a0898aSmrg { 155723a0898aSmrg register int x = xValue >> 16, y = yValue >> 16; 155823a0898aSmrg int pixvalue, error; 155923a0898aSmrg 156023a0898aSmrg pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ? 156123a0898aSmrg char_grayscale[x + y * (width + 1)] : 0) + 156223a0898aSmrg thisrow[col] / 16; 156323a0898aSmrg if (pixvalue > 255) pixvalue = 255; 156423a0898aSmrg else if (pixvalue < 0) pixvalue = 0; 156523a0898aSmrg 156623a0898aSmrg /* Choose the bit value and set resulting error value */ 156723a0898aSmrg if (pixvalue >= 128) 156823a0898aSmrg { 156923a0898aSmrg newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; 157023a0898aSmrg error = pixvalue - 255; 157123a0898aSmrg } 157223a0898aSmrg else 157323a0898aSmrg error = -pixvalue; 157423a0898aSmrg 157523a0898aSmrg /* Diffuse the error */ 157623a0898aSmrg thisrow[col + 1] += error * 7; 157723a0898aSmrg nextrow[col - 1] += error * 3; 157823a0898aSmrg nextrow[col] += error * 5; 157923a0898aSmrg nextrow[col + 1] = error; 158023a0898aSmrg 158123a0898aSmrg xValue += deltaX; 158223a0898aSmrg yValue += deltaY; 158323a0898aSmrg } 158423a0898aSmrg 158523a0898aSmrg /* Add in error values that fell off either end */ 158623a0898aSmrg nextrow[0] += nextrow[-1]; 158723a0898aSmrg nextrow[newWidth - 2] += thisrow[newWidth]; 158823a0898aSmrg nextrow[newWidth - 1] += nextrow[newWidth]; 158923a0898aSmrg nextrow[newWidth] = 0; 159023a0898aSmrg 159123a0898aSmrg temp = nextrow; 159223a0898aSmrg nextrow = thisrow; 159323a0898aSmrg thisrow = temp; 159423a0898aSmrg nextrow[-1] = nextrow[0] = 0; 159523a0898aSmrg } 159623a0898aSmrg else 159723a0898aSmrg { 159823a0898aSmrg for (col = 0; col < newWidth; col++) 159923a0898aSmrg { 160023a0898aSmrg register int x = xValue >> 16, y = yValue >> 16; 160123a0898aSmrg 160223a0898aSmrg if (x >= 0 && x < width && y >= 0 && y < height) 160323a0898aSmrg { 160423a0898aSmrg /* Use point-sampling for rescaling. */ 160523a0898aSmrg 160623a0898aSmrg if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7]) 160723a0898aSmrg newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; 160823a0898aSmrg } 160923a0898aSmrg 161023a0898aSmrg xValue += deltaX; 161123a0898aSmrg yValue += deltaY; 161223a0898aSmrg } 161323a0898aSmrg } 161423a0898aSmrg } 161523a0898aSmrg 161623a0898aSmrg 161723a0898aSmrg if (char_grayscale) 161823a0898aSmrg { 161923a0898aSmrg xfree(char_grayscale); 162023a0898aSmrg xfree(diffusion_workspace); 162123a0898aSmrg } 162223a0898aSmrg} 162323a0898aSmrg 162423a0898aSmrgstatic FontPtr 162523a0898aSmrgBitmapScaleBitmaps(FontPtr pf, /* scaled font */ 162623a0898aSmrg FontPtr opf, /* originating font */ 162723a0898aSmrg double widthMult, /* glyphs width scale factor */ 162823a0898aSmrg double heightMult, /* glyphs height scale factor */ 162923a0898aSmrg FontScalablePtr vals) 163023a0898aSmrg{ 163123a0898aSmrg register int i; 163223a0898aSmrg int nchars = 0; 163323a0898aSmrg char *glyphBytes; 163423a0898aSmrg BitmapFontPtr bitmapFont, 163523a0898aSmrg obitmapFont; 163623a0898aSmrg CharInfoPtr pci, 163723a0898aSmrg opci; 163823a0898aSmrg FontInfoPtr pfi; 163923a0898aSmrg int glyph; 164023a0898aSmrg unsigned bytestoalloc = 0; 164123a0898aSmrg int firstCol, lastCol, firstRow, lastRow; 164223a0898aSmrg 164323a0898aSmrg double xform[4], inv_xform[4]; 164423a0898aSmrg double xmult, ymult; 164523a0898aSmrg 164623a0898aSmrg bitmapFont = (BitmapFontPtr) pf->fontPrivate; 164723a0898aSmrg obitmapFont = (BitmapFontPtr) opf->fontPrivate; 164823a0898aSmrg 164923a0898aSmrg if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 165023a0898aSmrg inv_xform, &xmult, &ymult)) 165123a0898aSmrg goto bail; 165223a0898aSmrg 165323a0898aSmrg pfi = &pf->info; 165423a0898aSmrg firstCol = pfi->firstCol; 165523a0898aSmrg lastCol = pfi->lastCol; 165623a0898aSmrg firstRow = pfi->firstRow; 165723a0898aSmrg lastRow = pfi->lastRow; 165823a0898aSmrg 165923a0898aSmrg nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 166023a0898aSmrg glyph = pf->glyph; 166123a0898aSmrg for (i = 0; i < nchars; i++) 166223a0898aSmrg { 166323a0898aSmrg if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) 166423a0898aSmrg bytestoalloc += BYTES_FOR_GLYPH(pci, glyph); 166523a0898aSmrg } 166623a0898aSmrg 166723a0898aSmrg /* Do we add the font malloc stuff for VALUE ADDED ? */ 166823a0898aSmrg /* Will need to remember to free in the Unload routine */ 166923a0898aSmrg 167023a0898aSmrg 167123a0898aSmrg bitmapFont->bitmaps = (char *) xalloc(bytestoalloc); 167223a0898aSmrg if (!bitmapFont->bitmaps) { 167323a0898aSmrg fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); 167423a0898aSmrg goto bail; 167523a0898aSmrg } 167623a0898aSmrg bzero(bitmapFont->bitmaps, bytestoalloc); 167723a0898aSmrg 167823a0898aSmrg glyphBytes = bitmapFont->bitmaps; 167923a0898aSmrg for (i = 0; i < nchars; i++) 168023a0898aSmrg { 168123a0898aSmrg if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && 168223a0898aSmrg (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) 168323a0898aSmrg { 168423a0898aSmrg pci->bits = glyphBytes; 168523a0898aSmrg ScaleBitmap (pf, opci, pci, inv_xform, 168623a0898aSmrg widthMult, heightMult); 168723a0898aSmrg glyphBytes += BYTES_FOR_GLYPH(pci, glyph); 168823a0898aSmrg } 168923a0898aSmrg } 169023a0898aSmrg return pf; 169123a0898aSmrg 169223a0898aSmrgbail: 169323a0898aSmrg if (pf) 169423a0898aSmrg xfree(pf); 169523a0898aSmrg if (bitmapFont) { 169623a0898aSmrg xfree(bitmapFont->metrics); 169723a0898aSmrg xfree(bitmapFont->ink_metrics); 169823a0898aSmrg xfree(bitmapFont->bitmaps); 169923a0898aSmrg if(bitmapFont->encoding) 170023a0898aSmrg for(i=0; i<NUM_SEGMENTS(nchars); i++) 170123a0898aSmrg xfree(bitmapFont->encoding[i]); 170223a0898aSmrg xfree(bitmapFont->encoding); 170323a0898aSmrg } 170423a0898aSmrg return NULL; 170523a0898aSmrg} 170623a0898aSmrg 170723a0898aSmrgstatic FontPtr 170823a0898aSmrgPrinterScaleBitmaps(FontPtr pf, /* scaled font */ 170923a0898aSmrg FontPtr opf, /* originating font */ 171023a0898aSmrg double widthMult, /* glyphs width scale factor */ 171123a0898aSmrg double heightMult, /* glyphs height scale factor */ 171223a0898aSmrg FontScalablePtr vals) 171323a0898aSmrg{ 171423a0898aSmrg register int i; 171523a0898aSmrg int nchars = 0; 171623a0898aSmrg char *glyphBytes; 171723a0898aSmrg BitmapFontPtr bitmapFont, 171823a0898aSmrg obitmapFont; 171923a0898aSmrg CharInfoPtr pci; 172023a0898aSmrg FontInfoPtr pfi; 172123a0898aSmrg int glyph; 172223a0898aSmrg unsigned bytestoalloc = 0; 172323a0898aSmrg int firstCol, lastCol, firstRow, lastRow; 172423a0898aSmrg 172523a0898aSmrg double xform[4], inv_xform[4]; 172623a0898aSmrg double xmult, ymult; 172723a0898aSmrg 172823a0898aSmrg bitmapFont = (BitmapFontPtr) pf->fontPrivate; 172923a0898aSmrg obitmapFont = (BitmapFontPtr) opf->fontPrivate; 173023a0898aSmrg 173123a0898aSmrg if (!compute_xform_matrix(vals, widthMult, heightMult, xform, 173223a0898aSmrg inv_xform, &xmult, &ymult)) 173323a0898aSmrg goto bail; 173423a0898aSmrg 173523a0898aSmrg pfi = &pf->info; 173623a0898aSmrg firstCol = pfi->firstCol; 173723a0898aSmrg lastCol = pfi->lastCol; 173823a0898aSmrg firstRow = pfi->firstRow; 173923a0898aSmrg lastRow = pfi->lastRow; 174023a0898aSmrg 174123a0898aSmrg nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); 174223a0898aSmrg glyph = pf->glyph; 174323a0898aSmrg for (i = 0; i < nchars; i++) 174423a0898aSmrg { 174523a0898aSmrg if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) 174623a0898aSmrg bytestoalloc = MAX(bytestoalloc,BYTES_FOR_GLYPH(pci, glyph)); 174723a0898aSmrg } 174823a0898aSmrg 174923a0898aSmrg /* Do we add the font malloc stuff for VALUE ADDED ? */ 175023a0898aSmrg /* Will need to remember to free in the Unload routine */ 175123a0898aSmrg 175223a0898aSmrg 175323a0898aSmrg bitmapFont->bitmaps = (char *) xalloc(bytestoalloc); 175423a0898aSmrg if (!bitmapFont->bitmaps) { 175523a0898aSmrg fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); 175623a0898aSmrg goto bail; 175723a0898aSmrg } 175823a0898aSmrg bzero(bitmapFont->bitmaps, bytestoalloc); 175923a0898aSmrg 176023a0898aSmrg glyphBytes = bitmapFont->bitmaps; 176123a0898aSmrg for (i = 0; i < nchars; i++) 176223a0898aSmrg { 176323a0898aSmrg if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && 176423a0898aSmrg (ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) 176523a0898aSmrg { 176623a0898aSmrg pci->bits = glyphBytes; 176723a0898aSmrg } 176823a0898aSmrg } 176923a0898aSmrg return pf; 177023a0898aSmrg 177123a0898aSmrgbail: 177223a0898aSmrg if (pf) 177323a0898aSmrg xfree(pf); 177423a0898aSmrg if (bitmapFont) { 177523a0898aSmrg xfree(bitmapFont->metrics); 177623a0898aSmrg xfree(bitmapFont->ink_metrics); 177723a0898aSmrg xfree(bitmapFont->bitmaps); 177823a0898aSmrg if(bitmapFont->encoding) 177923a0898aSmrg for(i=0; i<NUM_SEGMENTS(nchars); i++) 178023a0898aSmrg xfree(bitmapFont->encoding[i]); 178123a0898aSmrg xfree(bitmapFont->encoding); 178223a0898aSmrg } 178323a0898aSmrg return NULL; 178423a0898aSmrg} 178523a0898aSmrg 178623a0898aSmrg#ifdef NOTDEF 178723a0898aSmrg/* 178823a0898aSmrg * exported interfaces 178923a0898aSmrg */ 179023a0898aSmrg 179123a0898aSmrgFontFileLoadName(FontFileDirPtr *dirs, int ndirs, char *name, FontPtr *pfont, 179223a0898aSmrg fsBitmapFormat format, fsBitmapFormatMask fmask) 179323a0898aSmrg{ 179423a0898aSmrg FontFileNamePtr fname; 179523a0898aSmrg char full_name[1024]; 179623a0898aSmrg int ret = BadFontName; 179723a0898aSmrg int i; 179823a0898aSmrg 179923a0898aSmrg i = 0; 180023a0898aSmrg while (i < ndirs) { 180123a0898aSmrg if (fname = FontFileFindNameInDir(dirs[i], name)) { 180223a0898aSmrg if (!fname->alias) { 180323a0898aSmrg if (!fname->font) { 180423a0898aSmrg strcpy(full_name, dirs[i]->dir); 180523a0898aSmrg strcat(full_name, fname->file); 180623a0898aSmrg ret = FontFileLoad(pfont, full_name, format, fmask); 180723a0898aSmrg if (ret == Successful) { 180823a0898aSmrg fname->font = *pfont; 180923a0898aSmrg (*pfont)->fpePrivate = (pointer) fname; 181023a0898aSmrg } 181123a0898aSmrg return ret; 181223a0898aSmrg } 181323a0898aSmrg *pfont = fname->font; 181423a0898aSmrg return Successful; 181523a0898aSmrg } 181623a0898aSmrg name = fname->file; 181723a0898aSmrg i = 0; 181823a0898aSmrg } else 181923a0898aSmrg i++; 182023a0898aSmrg } 182123a0898aSmrg return BadFontName; 182223a0898aSmrg} 182323a0898aSmrg#endif 182423a0898aSmrg 182523a0898aSmrg/* ARGSUSED */ 182623a0898aSmrgint 182723a0898aSmrgBitmapOpenScalable (FontPathElementPtr fpe, 182823a0898aSmrg FontPtr *pFont, 182923a0898aSmrg int flags, 183023a0898aSmrg FontEntryPtr entry, 183123a0898aSmrg char *fileName, /* unused */ 183223a0898aSmrg FontScalablePtr vals, 183323a0898aSmrg fsBitmapFormat format, 183423a0898aSmrg fsBitmapFormatMask fmask, 183523a0898aSmrg FontPtr non_cachable_font) /* We don't do licensing */ 183623a0898aSmrg{ 183723a0898aSmrg FontScalableRec best; 183823a0898aSmrg FontPtr font = NullFont; 183923a0898aSmrg double dx, sdx, 184023a0898aSmrg dy, sdy, 184123a0898aSmrg savedX, savedY; 184223a0898aSmrg FontPropPtr props; 184323a0898aSmrg char *isStringProp = NULL; 184423a0898aSmrg int propCount; 184523a0898aSmrg int status; 184623a0898aSmrg long sWidth; 184723a0898aSmrg 184823a0898aSmrg FontEntryPtr scaleFrom; 184923a0898aSmrg FontPathElementPtr scaleFPE; 185023a0898aSmrg FontPtr sourceFont; 185123a0898aSmrg char fontName[MAXFONTNAMELEN]; 185223a0898aSmrg 185323a0898aSmrg /* Can't deal with mix-endian fonts yet */ 185423a0898aSmrg 185523a0898aSmrg#ifdef NOTDEF /* XXX need better test */ 185623a0898aSmrg if ((format & BitmapFormatByteOrderMask) != 185723a0898aSmrg (format & BitmapFormatBitOrderMask)) 185823a0898aSmrg return NullFontFileName; 185923a0898aSmrg#endif 186023a0898aSmrg 186123a0898aSmrg /* Reject outrageously small font sizes to keep the math from 186223a0898aSmrg blowing up. */ 186323a0898aSmrg if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 || 186423a0898aSmrg get_matrix_horizontal_component(vals->pixel_matrix) < 1.0) 186523a0898aSmrg return BadFontName; 186623a0898aSmrg 186723a0898aSmrg scaleFrom = (*find_scale[BitmapGetRenderIndex(entry->u.bitmap.renderer)]) 186823a0898aSmrg (fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, &scaleFPE); 186923a0898aSmrg 187023a0898aSmrg if (!scaleFrom) 187123a0898aSmrg return BadFontName; 187223a0898aSmrg 187323a0898aSmrg status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, 187423a0898aSmrg format, fmask); 187523a0898aSmrg 187623a0898aSmrg if (status != Successful) 187723a0898aSmrg return BadFontName; 187823a0898aSmrg 187923a0898aSmrg if (!vals->width) 188023a0898aSmrg vals->width = best.width * dx; 188123a0898aSmrg 188223a0898aSmrg /* Compute the scaled font */ 188323a0898aSmrg 188423a0898aSmrg savedX = dx; 188523a0898aSmrg savedY = dy; 188623a0898aSmrg font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth); 188723a0898aSmrg if (font) 188823a0898aSmrg font = (*scale[ BitmapGetRenderIndex(entry->u.bitmap.renderer) ]) 188923a0898aSmrg (font, sourceFont, savedX, savedY, vals); 189023a0898aSmrg 189123a0898aSmrg if (!font) 189223a0898aSmrg { 189323a0898aSmrg if (!sourceFont->refcnt) 189423a0898aSmrg FontFileCloseFont((FontPathElementPtr) 0, sourceFont); 189523a0898aSmrg return AllocError; 189623a0898aSmrg } 189723a0898aSmrg 189823a0898aSmrg /* Prepare font properties for the new font */ 189923a0898aSmrg 190023a0898aSmrg strcpy (fontName, scaleFrom->name.name); 190123a0898aSmrg FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); 190223a0898aSmrg 190323a0898aSmrg propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, 190423a0898aSmrg dx, dy, sdx, sdy, sWidth, &props, 190523a0898aSmrg &isStringProp); 190623a0898aSmrg 190723a0898aSmrg if (!sourceFont->refcnt) 190823a0898aSmrg FontFileCloseFont((FontPathElementPtr) 0, sourceFont); 190923a0898aSmrg 191023a0898aSmrg if (propCount && (!props || !isStringProp)) 191123a0898aSmrg { 191223a0898aSmrg font->info.nprops = 0; 191323a0898aSmrg font->info.props = (FontPropPtr)0; 191423a0898aSmrg font->info.isStringProp = (char *)0; 191523a0898aSmrg bitmapUnloadScalable(font); 191623a0898aSmrg return AllocError; 191723a0898aSmrg } 191823a0898aSmrg 191923a0898aSmrg font->info.props = props; 192023a0898aSmrg font->info.nprops = propCount; 192123a0898aSmrg font->info.isStringProp = isStringProp; 192223a0898aSmrg 192323a0898aSmrg *pFont = font; 192423a0898aSmrg return Successful; 192523a0898aSmrg} 192623a0898aSmrg 192723a0898aSmrgint 192823a0898aSmrgBitmapGetInfoScalable (FontPathElementPtr fpe, 192923a0898aSmrg FontInfoPtr pFontInfo, 193023a0898aSmrg FontEntryPtr entry, 193123a0898aSmrg FontNamePtr fontName, 193223a0898aSmrg char *fileName, 193323a0898aSmrg FontScalablePtr vals) 193423a0898aSmrg{ 193523a0898aSmrg FontPtr pfont; 193623a0898aSmrg int flags = 0; 193723a0898aSmrg long format = 0; /* It doesn't matter what format for just info */ 193823a0898aSmrg long fmask = 0; 193923a0898aSmrg int ret; 194023a0898aSmrg 194123a0898aSmrg ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals, 194223a0898aSmrg format, fmask, NULL); 194323a0898aSmrg if (ret != Successful) 194423a0898aSmrg return ret; 194523a0898aSmrg *pFontInfo = pfont->info; 194623a0898aSmrg 194723a0898aSmrg pfont->info.nprops = 0; 194823a0898aSmrg pfont->info.props = NULL; 194923a0898aSmrg pfont->info.isStringProp = NULL; 195023a0898aSmrg 195123a0898aSmrg (*pfont->unload_font)(pfont); 195223a0898aSmrg return Successful; 195323a0898aSmrg} 195423a0898aSmrg 195523a0898aSmrgstatic void 195623a0898aSmrgbitmapUnloadScalable (FontPtr pFont) 195723a0898aSmrg{ 195823a0898aSmrg BitmapFontPtr bitmapFont; 195923a0898aSmrg FontInfoPtr pfi; 196023a0898aSmrg int i, nencoding; 196123a0898aSmrg 196223a0898aSmrg bitmapFont = (BitmapFontPtr) pFont->fontPrivate; 196323a0898aSmrg pfi = &pFont->info; 196423a0898aSmrg xfree (pfi->props); 196523a0898aSmrg xfree (pfi->isStringProp); 196623a0898aSmrg if(bitmapFont->encoding) { 196723a0898aSmrg nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * 196823a0898aSmrg (pFont->info.lastRow - pFont->info.firstRow + 1); 196923a0898aSmrg for(i=0; i<NUM_SEGMENTS(nencoding); i++) 197023a0898aSmrg xfree(bitmapFont->encoding[i]); 197123a0898aSmrg } 197223a0898aSmrg xfree (bitmapFont->encoding); 197323a0898aSmrg xfree (bitmapFont->bitmaps); 197423a0898aSmrg xfree (bitmapFont->ink_metrics); 197523a0898aSmrg xfree (bitmapFont->metrics); 197623a0898aSmrg xfree (pFont->fontPrivate); 197723a0898aSmrg DestroyFontRec (pFont); 197823a0898aSmrg} 1979