/* 
   XRFont.m

   NSFont Backend

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:	Scott Christley
   Author:	Ovidiu Predescu <ovidiu@bx.logicnet.ro>
   Date: 	February 1997
   Author:  Felipe A. Rodriguez <far@pcmagic.net>
   Date: 	May 1998
   Author:	Michael Hanni <mhanni@sprintmail.com>
   Date: 	August 1998
   
   This file is part of the mySTEP Library and is provided
   under the terms of the GNU Library General Public License.
*/ 

#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSUserDefaults.h>

#include <AppKit/NSFontManager.h>
#include <AppKit/NSFont.h>
#include <AppKit/NSGraphicsContext.h>

#import "NSAppKitPrivate.h"
#import "NSBackendPrivate.h"

// Class variables

NSString *NSAntialiasThresholdChangedNotification=@"NSAntialiasThresholdChangedNotification";
NSString *NSFontSetChangedNotification=@"NSFontSetChangedNotification";

static NSFont *_getNSFont(NSString *key, NSString *defaultFontName, float size, float deflt)
{
	NSFont *f;
#if 0
	NSLog(@"_getFont %@ %lf %lf", key, size, deflt);
	{
#endif
		// FIXME: we should have our own cache!!!
	NSUserDefaults *u = [NSUserDefaults standardUserDefaults];
	NSString *fontName = [u objectForKey:key];	// e.g. NSBoldFont=Helvetica

	if(!fontName)
		fontName = defaultFontName;
	
	if(size <= 0.0 || (size = [u floatForKey:[NSString stringWithFormat:@"%@Size", key]]) <= 0.0)	// e.g. NSBoldFontSize=12
		size = deflt;   // substitute default
	if(size <= 0.0)
		size=12.0;	// final fallback if we still don't know better
	f=[NSFont fontWithName:fontName size:size];
#if 0
	}
	NSLog(@"_gotFont size=%f", size);
#endif
	return f;
}

//*****************************************************************************
//
// 		NSFont 
//
//*****************************************************************************

@implementation NSFont

+ (NSFont *) boldSystemFontOfSize:(float)fontSize
{												
	return _getNSFont(@"NSBoldFont", @"Helvetica-Bold", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) systemFontOfSize:(float)fontSize
{
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) titleBarFontOfSize:(float)fontSize;
{
	return _getNSFont(@"NSBoldFont", @"Helvetica-Bold", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) menuFontOfSize:(float)fontSize
{
	static float size= -1.0;	// cache for default font size
	if(size < 0.0)
		size=floor([NSMenuView menuBarHeight]*0.625+0.25);	// 16 -> 10; 24 -> 15;
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, size);
}

+ (NSFont *) menuBarFontOfSize:(float)fontSize
{
	static float size= -1.0;	// cache for default font size
	if(size <= 0.0)
		size=floor([NSMenuView menuBarHeight]*0.625+0.25);	// 16 -> 10; 24 -> 15;
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, size);
}

+ (NSFont *) toolTipsFontOfSize:(float)fontSize
{
	/* FIXME: according to http://www.macosxhints.com/article.php?story=20061107125819464&query=tooltip
	
	we should read parameters
	NSToolTipsFont	-string	font name
	NSToolTipsFontSize	-int	font size
	*/

	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) paletteFontOfSize:(float)fontSize
{
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) messageFontOfSize:(float)fontSize
{
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) titleFontOfSize:(float)fontSize
{
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) labelFontOfSize:(float)fontSize
{
	return _getNSFont(@"NSFont", @"Helvetica", fontSize, [NSFont labelFontSize]);
}

+ (NSFont *) controlContentFontOfSize:(float)fontSize
{
	return _getNSFont (@"NSFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) userFixedPitchFontOfSize:(float)fontSize
{
	return _getNSFont (@"NSUserFixedPitchFont", @"Courier", fontSize, [NSFont systemFontSize]);
}

+ (NSFont *) userFontOfSize:(float)fontSize
{
	return _getNSFont (@"NSUserFont", @"Helvetica", fontSize, [NSFont systemFontSize]);
}

+ (float) systemFontSize;
{ // return default size of standard system font
	return 12;
}

+ (float) smallSystemFontSize;
{
	return 10.0;
}

+ (float) systemFontSizeForControlSize:(NSControlSize) size
{
	switch(size)
		{
		case NSRegularControlSize:
		default:					return 12;
		case NSSmallControlSize:	return 10;
		case NSMiniControlSize:		return 9;
		}
}

+ (float) labelFontSize;
{ // return default size of standard system font
	return 12;
}

// Set preferred user fonts
+ (void) setUserFixedPitchFont:(NSFont*)font
{												
	[[NSUserDefaults standardUserDefaults] setObject:[font fontName] 
										   forKey:@"NSUserFixedPitchFont"];
	[[NSUserDefaults standardUserDefaults] synchronize];
}

+ (void) setUserFont:(NSFont*)font
{
	[[NSUserDefaults standardUserDefaults] setObject:[font fontName] 
										   forKey:@"NSUserFont"];
	[[NSUserDefaults standardUserDefaults] synchronize];
}

+ (NSFont *) fontWithName:(NSString*)name matrix:(const float*)fontMatrix
{
	NSFont *font=[self new];
	font->_fontName = [name copy];							// set font attr's
	memcpy(font->_matrix, fontMatrix, sizeof(font->_matrix));
	return [font autorelease];
}

+ (NSFont *) fontWithName:(NSString*)name size:(float)fontSize
{
	static NSMutableDictionary *fcache;
	NSFont *f;
	NSString *key;
	if(fontSize <= 0.0 || fontSize > 10000.0)
		return nil;	// raise exception?
	key=[name stringByAppendingFormat:@"-%f", fontSize];	// build cache key
	f=[fcache objectForKey:key];
	if(!f)
		{ // create new entry
		float fontMatrix[6] = { fontSize, 0, 0, fontSize, 0, 0 };
#if 1
		NSLog(@"add font to cache: %@", key);
#endif
		f=[NSFont fontWithName:name matrix:fontMatrix];
		if(!fcache)
			fcache=[[NSMutableDictionary alloc] initWithCapacity:20];	// no cache yet
		[fcache setObject:f forKey:key];
		}
	return f;
}

- (NSString *) fontName							{ return _fontName; }

- (NSString *) familyName						{ return _fontName; }

- (NSString *) displayName						{ return _fontName; }

- (float) pointSize								{ return _matrix[3]; }	// effective vertical size

- (void) encodeWithCoder:(NSCoder *)aCoder
{														// NSCoding protocol
	[aCoder encodeObject:_fontName];
	[aCoder encodeArrayOfObjCType:"f" count:6 at:_matrix];
}

- (id) initWithCoder:(NSCoder *)aDecoder
{
	if([aDecoder allowsKeyedCoding])
		{
		int fFlags=[aDecoder decodeIntForKey:@"NSfFlags"];	// renderingMode?
		float fontSize = [aDecoder decodeFloatForKey:@"NSSize"];
		_fontName = [[aDecoder decodeObjectForKey:@"NSName"] retain];
		_matrix[0] = fontSize;
		_matrix[1] = 0;
		_matrix[2] = 0;
		_matrix[3] = fontSize;
		_matrix[4] = 0;
		_matrix[5] = 0;
#if 0
		NSLog(@"%@ NSfFlags=%08x", self, [aDecoder decodeIntForKey:@"NSfFlags"]);
#endif
		return self;
		}
	_fontName = [[aDecoder decodeObject] retain];
	[aDecoder decodeArrayOfObjCType:"f" count:6 at:_matrix];

	return self;
}

- (NSString *) description;
{
	return [NSString stringWithFormat:@"NSFont: %@", _descriptor];
}

- (void) set
{
	[[NSGraphicsContext currentContext] _setFont:self];
}

- (void) setInContext:(NSGraphicsContext *) context;
{
	[context _setFont:self];
}

+ (NSFont *) fontWithDescriptor:(NSFontDescriptor *) descriptor size:(float) size;
{
	return [self fontWithDescriptor:descriptor size:size textTransform:nil];
}

+ (NSFont *) fontWithDescriptor:(NSFontDescriptor *) descriptor size:(float) size textTransform:(NSAffineTransform *) transform;
{
	NSFont *f=[NSFont new];
	if(f)
		{
		descriptor=[descriptor fontDescriptorWithSize:size];
		if(transform)
			descriptor=[descriptor fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:transform forKey:NSFontMatrixAttribute]];
		f->_descriptor=[descriptor retain];
		}
	return [f autorelease];
}

- (NSSize) advancementForGlyph:(NSGlyph)aGlyph; { BACKEND; return NSZeroSize; }
- (float) ascender; { BACKEND; return 0.0; }
- (NSRect) boundingRectForFont; { BACKEND; return NSZeroRect; }
- (NSRect) boundingRectForGlyph:(NSGlyph)aGlyph; { BACKEND; return NSZeroRect; }
- (float) capHeight; { BACKEND; return 0.0; }

- (NSCharacterSet *) coveredCharacterSet;  { return BACKEND; }

- (float) descender; { BACKEND; return 0.0; }

- (NSFontDescriptor *) fontDescriptor; { return _descriptor; }

- (void) getAdvancements:(NSSizeArray) advancements
			   forGlyphs:(const NSGlyph *) glyphs
				   count:(unsigned) count; { BACKEND; }
- (void) getAdvancements:(NSSizeArray) advancements
		 forPacketGlyphs:(const void *) glyphs
				   count:(unsigned) count; { BACKEND; }

- (void) getBoundingRects:(NSRectArray) bounds
				forGlyphs:(const NSGlyph *) glyphs
					count:(unsigned) count; { BACKEND; }

- (NSGlyph) glyphWithName:(NSString *) name; { BACKEND; return NSNullGlyph; }

- (BOOL) isFixedPitch;	{ BACKEND; return NO; }

- (float) italicAngle; { BACKEND; return 0.0; }

- (float) leading; { BACKEND; return 0.0; }

- (const float *) matrix; { return _matrix; }

- (NSSize) maximumAdvancement; { BACKEND; return NSZeroSize; }

- (NSStringEncoding) mostCompatibleStringEncoding; { BACKEND; return NSASCIIStringEncoding; }

- (unsigned) numberOfGlyphs; { BACKEND; return 0; }

- (NSFont *) printerFont; { return NIMP; }

- (NSFontRenderingMode) renderingMode; { return _renderingMode; }

- (NSFont *) screenFont; { return NIMP; }

- (NSFont *) screenFontWithRenderingMode:(NSFontRenderingMode) mode; { return NIMP; }

- (NSAffineTransform *) textTransform; { return NIMP; }

- (float) underlinePosition; { BACKEND; return 0.0; }

- (float) underlineThickness; { BACKEND; return 0.0; }

- (float) xHeight; { BACKEND; return 0.0; }

+ (NSArray *) preferredFontNames;	{ DEPRECATED; return nil; }
+ (void) setPreferredFontNames:(NSArray *) names;	{ DEPRECATED; }

+ (void) useFont:(NSString*)name
{ // should include font in PDF document
	DEPRECATED;
	[[self fontWithName:name size:12] set];	// just select
}

- (NSDictionary *) afmDictionary;	{ DEPRECATED; return nil; }
- (float) defaultLineHeightForFont;	{ DEPRECATED; return [self leading]; }
- (NSString *) encodingScheme;	{ DEPRECATED; return @"FontSpecificEncoding"; }
- (BOOL) glyphIsEncoded:(NSGlyph)aGlyph;	{ DEPRECATED; return NO; }
- (NSMultibyteGlyphPacking) glyphPacking;	{ DEPRECATED; return NSNativeShortGlyphPacking; }
- (BOOL) isBaseFont;	{ DEPRECATED; return NO; }
- (NSPoint) positionOfGlyph:(NSGlyph)curGlyph forCharacter:(unichar)character struckOverRect:(NSRect)rect;	 { DEPRECATED; return NSZeroPoint; }
- (NSPoint) positionOfGlyph:(NSGlyph)curGlyph precededByGlyph:(NSGlyph)prevGlyph isNominal:(BOOL *)nominal;	 { DEPRECATED; return NSZeroPoint; }
- (NSPoint) positionOfGlyph:(NSGlyph)curGlyph struckOverGlyph:(NSGlyph)prevGlyph metricExists:(BOOL *)flag;	 { DEPRECATED; return NSZeroPoint; }
- (NSPoint) positionOfGlyph:(NSGlyph)curGlyph struckOverRect:(NSRect)rect metricExists:(BOOL *)flag;	 { DEPRECATED; return NSZeroPoint; }
- (NSPoint) positionOfGlyph:(NSGlyph)curGlyph withRelation:(NSGlyphRelation)relation toBaseGlyph:(NSGlyph)otherGlyph totalAdvancement:(NSSizePointer)offset metricExists:(BOOL *)flag;  { DEPRECATED; return NSZeroPoint; }
- (int) positionsForCompositeSequence:(NSGlyph *) glyphs numberOfGlyphs:(int) number pointArray:(NSPointArray) points; { DEPRECATED; return 0; }

- (float) widthOfString:(NSString*) string
{ // calc the size of string in font
	DEPRECATED;
	return [string sizeWithAttributes:[NSDictionary dictionaryWithObject:self forKey:NSFontAttributeName]].width;
}

@end /* NSFont */

NSString *NSFontFamilyAttribute=@"Family";
NSString *NSFontNameAttribute=@"Name";
NSString *NSFontFaceAttribute=@"Face";
NSString *NSFontSizeAttribute=@"Size"; 
NSString *NSFontVisibleNameAttribute=@"VisibleName"; 
NSString *NSFontColorAttribute=@"Color";
NSString *NSFontMatrixAttribute=@"Matrix";
NSString *NSFontVariationAttribute=@"Variation";
NSString *NSFontCharacterSetAttribute=@"CharacterSet";
NSString *NSFontCascadeListAttribute=@"CascadeList";
NSString *NSFontTraitsAttribute=@"Traits";
NSString *NSFontFixedAdvanceAttribute=@"FixedAdvance";

NSString *NSFontSymbolicTrait=@"SymbolicTrait";
NSString *NSFontWeightTrait=@"WeightTrait";
NSString *NSFontWidthTrait=@"WidthTrait";
NSString *NSFontSlantTrait=@"SlantTrait";

NSString *NSFontVariationAxisIdentifierKey=@"VariationAxisIdentifier";
NSString *NSFontVariationAxisMinimumValueKey=@"VariationAxisMinimumValue";
NSString *NSFontVariationAxisMaximumValueKey=@"VariationAxisMaximumValue";
NSString *NSFontVariationAxisDefaultValueKey=@"VariationAxisDefaultValue";
NSString *NSFontVariationAxisNameKey=@"VariationAxisName";

@implementation NSFontDescriptor

+ (NSArray *) _fontDescriptorsWithContentsOfURL:(NSURL *) url; { return BACKEND; }

+ (NSArray *) _fontDescriptors;
{ // all in system (/Library/Fonts, /System/Library/Fonts, ~/Library/Fonts)
	// handle cache
	return nil;
}

+ (id) fontDescriptorWithFontAttributes:(NSDictionary *) attributes;
{
	return NIMP;
}

+ (id) fontDescriptorWithName:(NSString *) name matrix:(NSAffineTransform *) matrix;
{
	return NIMP;
}

+ (id) fontDescriptorWithName:(NSString *) name size:(float) size;
{
	return NIMP;
}

- (NSDictionary *) fontAttributes; { return _attributes; }

- (NSFontDescriptor *) fontDescriptorByAddingAttributes:(NSDictionary *) attributes;
{
	// merge...
	return NIMP;
}

- (NSFontDescriptor *) fontDescriptorWithFace:(NSString *) face;
{
	return [self fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:face forKey:NSFontFaceAttribute]];
}

- (NSFontDescriptor *) fontDescriptorWithFamily:(NSString *) family;
{
	return [self fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:family forKey:NSFontFamilyAttribute]];
}

- (NSFontDescriptor *) fontDescriptorWithMatrix:(NSAffineTransform *) matrix;
{
	return [self fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:matrix forKey:NSFontMatrixAttribute]];
}

- (NSFontDescriptor *) fontDescriptorWithSize:(float) size;
{
	return [self fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:size] forKey:NSFontSizeAttribute]];
}

- (NSFontDescriptor *) fontDescriptorWithSymbolicTraits:(NSFontSymbolicTraits) traits;
{
//	return [self fontDescriptorByAddingAttributes:[NSDictionary dictionaryWithObject:face forKey:NSFontFaceAttribute]];
	return NIMP;
}

- (id) initWithFontAttributes:(NSDictionary *) attributes;
{
	if((self=[super init]))
		{
		_attributes=[attributes retain];
		}
	return self;
}

- (void) encodeWithCoder:(NSCoder *)aCoder
{
	NIMP;
}

- (id) initWithCoder:(NSCoder *)aDecoder
{
	if(![aDecoder allowsKeyedCoding])
		NIMP;
	_attributes = [[aDecoder decodeObjectForKey:@"NSAttributes"] retain];
	return self;
}
	
- (void) dealloc;
{
	[_attributes release];
	[super dealloc];
}

- (NSArray *) matchingFontDescriptorsWithMandatoryKeys:(NSSet *) keys;
{
	// FIXME: filter by matching attributes
	return [isa _fontDescriptors];
}

- (NSAffineTransform *) matrix; { return [_attributes objectForKey:NSFontMatrixAttribute]; }
- (id) objectForKey:(NSString *) attribute; { return [_attributes objectForKey:attribute]; }
- (float) pointSize; { return [[_attributes objectForKey:NSFontSizeAttribute] floatValue]; }
- (NSString *) postscriptName; { return @"postscript name"; }
- (NSFontSymbolicTraits) symbolicTraits; { NIMP; return 0; }

@end
