gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AA font drawing


From: Fred Kiefer
Subject: AA font drawing
Date: Mon, 10 Sep 2001 14:20:04 +0200

As you remember there have been a few attempts to bring anti alias font
drawing to GNUstep. After XFree86 rendering support for my old graphic
card has been added (which was with 4.10) I played around a bit with the
use of the new Xft functions.
The result of my current attempts is mixed. To be honest, I don't like
anti alias fonts much. So I still have not made up my mind if we should
include any of this into GNUstep. 
To leave the decision to you I will supply the changes I made and you
may discuss in this news group if further progress in this direction
should be made.

Before you try any of the following, make sure that you have a current
release of XFree86 and that AA is working for other applications.

The structure of my changes is simple. We have a new subclass of
GSFontInfo in the xgps/Source directory (The files are attached to this
mail). This class is set as the GSFontInfo class in [initializeBackend]
([GSFontInfo setDefaultClass: [XftFontInfo class]];) So all calls to
create a font end up in this class. As this class uses the old font
cache structure it will ask Xft for exactly the same fonts as XGFontInfo
would.
To get it working you will have to add the Xft library. (In the
GNUmakefile.preamble file set ADDITIONAL_LDFLAGS =  -lXft) And of course
the XftFontInfo.m must be added in GNUmakefile.

What is missing? 
Most for the attributes for a font are not computed. This should be
possible from the pattern structure, but I did not get the idea how to
do it.
There is no clipping for the drawing, so draw operations will overlap
other views or cells. 
Both changes should not be to hard to implement, if anybody thinks AA
worthwhile.

Fred
/*
   XftFontInfo

   NSFont helper for GNUstep GUI X/GPS Backend

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:  Fred Kiefer <address@hidden>
   Date: July 2001

   This file is part of the GNUstep GUI X/GPS Backend.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

// Include this before we include any objC defines, otherwise id is defined
#include <X11/Xft/Xft.h>

#include <AppKit/GSFontInfo.h>

@interface XftFontInfo : GSFontInfo
{
  XftFont *font_info;
}

- (void) drawString:  (NSString*)string
          onDisplay: (Display*) xdpy drawable: (Drawable) draw
               with: (GC) xgcntxt at: (XPoint) xp;
- (void) draw: (const char*) s lenght: (int) len 
    onDisplay: (Display*) xdpy drawable: (Drawable) draw
         with: (GC) xgcntxt at: (XPoint) xp;
- (float) widthOf: (const char*) s lenght: (int) len;
- (void) setActiveFor: (Display*) xdpy gc: (GC) xgcntxt;

@end
/*
   XftFontInfo

   NSFont helper for GNUstep GUI X/GPS Backend

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:  Fred Kiefer <address@hidden>
   Date: July 2001

   This file is part of the GNUstep GUI X/GPS Backend.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "XftFontInfo.h"

#include <gnustep/xgps/XGContext.h>
#include <gnustep/xgps/XGContextPrivate.h>
#include <gnustep/xgps/XGGState.h>
#include <Foundation/NSDebug.h>
// For the encoding functions
#include <base/Unicode.h>


/*
 * class global dictionary of existing fonts
 */
static NSMutableDictionary      *_globalFontDictionary = nil;

@interface XftFontInfo (Private)

- (void) setupAttributes: (NSString*) xfontname;
- (XGlyphInfo *)xGlyphInfo: (NSGlyph) glyph;

@end

@implementation XftFontInfo

- initWithFontName: (NSString*)name matrix: (const float *)fmatrix
{
  NSString      *xfontname;
  XGFontInfo *fontinfo;

  /*
   * Retrieve the XLFD matching the given fontName. DPS->X.
   */
  xfontname = XGXFontName(name, fmatrix[0]);

  /*
   * Do we have an already contructed XGFontInfo for this request? If yes we
   * return it.
   */
  if (_globalFontDictionary == nil)
    _globalFontDictionary = [NSMutableDictionary new];
  if ((fontinfo = [_globalFontDictionary objectForKey: xfontname]))
    {
      RELEASE(self);
      return RETAIN(fontinfo);
    }

  // Use a new XGFontInfo and add to the global fontDict.
  [super init];
  ASSIGN(fontName, name);
  memcpy(matrix, fmatrix, sizeof(matrix));
  [_globalFontDictionary setObject: self forKey: xfontname];

  [self setupAttributes: xfontname];
  return self;
}

- (void) dealloc
{
  if (font_info != NULL)
    XftFontClose([XGContext currentXDisplay], (XftFont *)font_info);
  [super dealloc];
}

- (float) widthOfString: (NSString*)string
{
  XGlyphInfo extents;
  int len = [string length];
  XftChar16 str[len]; 

  [string getCharacters: (unichar*)str];
  XftTextExtents16 ([XGContext currentXDisplay],
                    font_info,
                    str, 
                    len,
                    &extents);

  return extents.width;
}

- (NSMultibyteGlyphPacking)glyphPacking
{
  return NSTwoByteGlyphPacking;
}

- (NSSize) advancementForGlyph: (NSGlyph)glyph
{
  XGlyphInfo *pc = [self xGlyphInfo: glyph];

  // if per_char is NULL assume max bounds
  if (!pc)
    return  NSMakeSize((float)(font_info)->max_advance_width, 0);

  return NSMakeSize((float)pc->xOff, (float)pc->yOff);
}

- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
{
  XGlyphInfo *pc = [self xGlyphInfo: glyph];

  // if per_char is NULL assume max bounds
  if (!pc)
      return NSMakeRect(0.0, 0.0,
                    (float)font_info->max_advance_width,
                    (float)(font_info->ascent + font_info->descent));

  return NSMakeRect((float)pc->x, (float)-pc->y, 
                    (float)(pc->width), 
                    (float)(pc->height));
}

- (BOOL) glyphIsEncoded: (NSGlyph)glyph
{
  return XftGlyphExists([XGContext currentXDisplay],
                        (XftFont *)font_info, glyph);
}

- (NSGlyph) glyphWithName: (NSString*)glyphName
{
  // FIXME: There is a mismatch between PS names and X names, that we should 
  // try to correct here
  KeySym k = XStringToKeysym([glyphName cString]);

  if (k == NoSymbol)
    return 0;
  else
    return (NSGlyph)k;
}

- (NSPoint) positionOfGlyph: (NSGlyph)curGlyph
            precededByGlyph: (NSGlyph)prevGlyph
                  isNominal: (BOOL*)nominal
{
  if (nominal)
    *nominal = YES;

  if (curGlyph == NSControlGlyph || prevGlyph == NSControlGlyph)
    return NSZeroPoint;

//  if (curGlyph == NSNullGlyph)
    {
      NSSize advance = [self advancementForGlyph: prevGlyph];
      return NSMakePoint(advance.width, advance.height);
    }
}

/*
- (float) pointSize
{
  Display       *xdpy = [XGContext currentXDisplay];

  return XGFontPointSize(xdpy, font_info);
}
*/

- (void) drawString:  (NSString*)string
          onDisplay: (Display*) xdpy drawable: (Drawable) draw
               with: (GC) xgcntxt at: (XPoint) xp
{
  NSData *d = [string dataUsingEncoding: mostCompatibleStringEncoding
                      allowLossyConversion: YES];
  int length = [d length];
  const char *cstr = (const char*)[d bytes];
  XftDraw *xftdraw;
  XftColor xftcolor;
  XColor dummyc;
  XGCValues values;
  Region xregion;
  int defaultScreen = DefaultScreen(xdpy);
  Colormap colmap = DefaultColormap(xdpy, defaultScreen);

  /* ready to draw */
  xftdraw = XftDrawCreate(xdpy, draw,
                          DefaultVisual(xdpy, defaultScreen),
                          colmap);
  if(xftdraw == NULL) 
    return;

  /* sort out the drawing colour */
  XGetGCValues(xdpy, xgcntxt,
               GCForeground | GCBackground,
               &values);
       
  dummyc.pixel = values.foreground;
  XQueryColor(xdpy, colmap, &dummyc);
  xftcolor.color.red = dummyc.red;
  xftcolor.color.green = dummyc.green;
  xftcolor.color.blue = dummyc.blue;
  xftcolor.color.alpha =  0xffff;
  xftcolor.pixel = values.foreground;
  
  /* set up clipping
  xregion = ;
  if(xregion != None)
    XftDrawSetClip(xftdraw, xregion);
   */

  /* do it */
  XftDrawString16(xftdraw, &xftcolor, font_info, 
                  xp.x, xp.y, (XftChar16*)cstr, length);

  /* tidy up */
  XftDrawDestroy(xftdraw);
}

- (void) draw: (const char*) s lenght: (int) len 
    onDisplay: (Display*) xdpy drawable: (Drawable) draw
         with: (GC) xgcntxt at: (XPoint) xp
{
  int length = strlen(s);
  XftDraw *xftdraw;
  XftColor xftcolor;
  XColor dummyc;
  XGCValues values;
  Region xregion;
  int defaultScreen = DefaultScreen(xdpy);
  Colormap colmap = DefaultColormap(xdpy, defaultScreen);

  /* ready to draw */
  xftdraw = XftDrawCreate(xdpy, draw,
                          DefaultVisual(xdpy, defaultScreen),
                          colmap);
  if(xftdraw == NULL) 
    return;

  /* sort out the drawing colour */
  XGetGCValues(xdpy, xgcntxt,
               GCForeground | GCBackground,
               &values);
       
  dummyc.pixel = values.foreground;
  XQueryColor(xdpy, colmap, &dummyc);
  xftcolor.color.red = dummyc.red;
  xftcolor.color.green = dummyc.green;
  xftcolor.color.blue = dummyc.blue;
  xftcolor.color.alpha =  0xffff;
  xftcolor.pixel = values.foreground;
  
  /* set up clipping
  xregion = ;
  if(xregion != None)
    XftDrawSetClip(xftdraw, xregion);
   */

  /* do it */
  XftDrawString8(xftdraw, &xftcolor, font_info, 
                 xp.x, xp.y, (XftChar8*)s, length);

  /* tidy up */
  XftDrawDestroy(xftdraw);
}

- (float) widthOf: (const char*) s lenght: (int) len
{
  XGlyphInfo extents;

  XftTextExtents8([XGContext currentXDisplay],
                  font_info,
                  (XftChar8*)s, 
                  len,
                  &extents);

  return extents.width;
}

- (void) setActiveFor: (Display*) xdpy gc: (GC) xgcntxt
{
}

@end

@implementation XftFontInfo (Private)

- (void) setupAttributes: (NSString*)xfontname
{
  Display *xdpy = [XGContext currentXDisplay];
  int defaultScreen = DefaultScreen(xdpy);
  NSString *weightString;
  NSString *reg;
  long height;      
  XftPattern *pattern;

  if (!xdpy)
    return;

  // Load X font and get font info structure.
  if ((font_info = XftFontOpenXlfd(xdpy, defaultScreen, [xfontname cString])) 
== NULL)
    {
      NSLog(@"Selected font: %@ is not available.\n"
            @"Using system fixed font instead", xfontname);

      // Shouldn't get here, but still try default font
      if ((font_info = XftFontOpenXlfd(xdpy, defaultScreen, "9x15")) == NULL)
        {
          NSLog(@"Unable to open fixed font");
          return;
        }
    }
  else
    NSDebugLog(@"Loaded font: %@", xfontname);

  // Fill the afmDitionary and ivars
/*
  pattern = font_info->pattern;
  XftPatternGetString (pattern, (const char *)object, int n, char **s);

  [fontDictionary setObject: fontName forKey: NSAFMFontName];
  ASSIGN(familyName, XGFontFamily(xdpy, font_info));
  [fontDictionary setObject: familyName forKey: NSAFMFamilyName];
  isFixedPitch = XGFontIsFixedPitch(xdpy, font_info);
*/
  isBaseFont = NO;
  ascender = font_info->ascent;
  [fontDictionary setObject: [NSNumber numberWithFloat: ascender] 
                  forKey: NSAFMAscender];
  descender = -(font_info->descent);
  [fontDictionary setObject: [NSNumber numberWithFloat: descender]
                  forKey: NSAFMDescender];
  fontBBox = NSMakeRect(
    (float)(0),
    (float)(0 - font_info->ascent),
    (float)(font_info->max_advance_width),
    (float)(font_info->ascent + font_info->descent));
  maximumAdvancement = NSMakeSize(font_info->max_advance_width,
    (font_info->ascent + font_info->descent));
  minimumAdvancement = NSMakeSize(0,0);
/*
  weight = XGWeightOfFont(xdpy, font_info);
  traits = XGTraitsOfFont(xdpy, font_info);

  weightString = [GSFontInfo stringForWeight: weight];
  
  if (weightString != nil)
    {
      [fontDictionary setObject: weightString forKey: NSAFMWeight];
    }

  reg = XGFontPropString(xdpy, font_info, XA_CHARSET_REGISTRY);
  if (reg != nil)
    { 
      NSString *enc = XGFontPropString(xdpy, font_info, XA_CHARSET_ENCODING);

      if (enc != nil)
        {
          mostCompatibleStringEncoding = [GSFontInfo encodingForRegistry: reg
                                                     encoding: enc];
          encodingScheme = [NSString stringWithFormat: @"address@hidden@", 
                                     reg, enc];
          //NSLog(@"Found encoding %d for %@", mostCompatibleStringEncoding, 
encodingScheme);
          RETAIN(encodingScheme);
          [fontDictionary setObject: encodingScheme
                          forKey: NSAFMEncodingScheme];
        }
    }

  height = XGFontPropULong(xdpy, font_info, XA_X_HEIGHT);
  if (height != 0)
    {
      xHeight = (float)height;
      [fontDictionary setObject: [NSNumber numberWithFloat: xHeight]
                      forKey: NSAFMXHeight];
    }

  height = XGFontPropULong(xdpy, font_info, XA_CAP_HEIGHT);
  if (height != 0)
    {
      capHeight = (float)height;
      [fontDictionary setObject: [NSNumber numberWithFloat: capHeight]
                      forKey: NSAFMCapHeight];
    }
*/  
  // FIXME: italicAngle, underlinePosition, underlineThickness are not set.
  // Should use XA_ITALIC_ANGLE, XA_UNDERLINE_POSITION, XA_UNDERLINE_THICKNESS
}

- (XGlyphInfo *)xGlyphInfo: (NSGlyph) glyph
{
  static XGlyphInfo glyphInfo;

  XftTextExtents32 ([XGContext currentXDisplay],
                    (XftFont *)font_info,
                    &glyph,
                    1,
                    &glyphInfo);
  return &glyphInfo;
}

@end

reply via email to

[Prev in Thread] Current Thread [Next in Thread]