Beispiel #1
0
void*
loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1)
{
	ATSUFontID	fontID = FMGetFontFromATSFontRef(fontRef);
	ATSUStyle	style = 0;
	OSStatus	status = ATSUCreateStyle(&style);
	float		extend = 1.0;
	float		slant = 0.0;
	float		embolden = 0.0;
	float		letterspace = 0.0;
	int i;
	
	if (status == noErr) {
		UInt32	rgbValue;
		Fixed	tracking = 0x80000000;
		Fixed	atsuSize = FixedTeXtoPSPoints(scaled_size);
		
		ATSStyleRenderingOptions	options = kATSStyleNoHinting;
		Fract						hangInhibit = fract1;
		ATSUAttributeTag		tags[] = { kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, kATSUHangingInhibitFactorTag };
		ByteCount				sizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSStyleRenderingOptions), sizeof(Fract) };
		ATSUAttributeValuePtr	attrs[] = { &fontID, &atsuSize, &options, &hangInhibit };
		ATSUSetAttributes(style, sizeof(tags) / sizeof(ATSUAttributeTag), tags, sizes, attrs);
		
#define FEAT_ALLOC_CHUNK	8
#define VAR_ALLOC_CHUNK		4

		if (cp1 != NULL) {
			int	allocFeats = FEAT_ALLOC_CHUNK;
			UInt16*	featureTypes = (UInt16*)xmalloc(allocFeats * sizeof(UInt16));
			UInt16*	selectorValues = (UInt16*)xmalloc(allocFeats * sizeof(UInt16));
			int	numFeatures = 0;
			
			int	allocVars = VAR_ALLOC_CHUNK;
			UInt32*	axes = (UInt32*)xmalloc(allocVars * sizeof(UInt32));
			SInt32*	values = (SInt32*)xmalloc(allocVars * sizeof(SInt32));
			int	numVariations = 0;
			
			// interpret features & variations following ":"
			while (*cp1) {
				// locate beginning of name=value pair
				if (*cp1 == ':' || *cp1 == ';')	// skip over separator
					++cp1;
				while (*cp1 == ' ' || *cp1 == '\t')	// skip leading whitespace
					++cp1;
				if (*cp1 == 0)	// break if end of string
					break;
	
				// scan to end of pair
				const char*	cp2 = cp1;
				while (*cp2 && *cp2 != ';' && *cp2 != ':')
					++cp2;
	
				// look for the '=' separator
				const char*	cp3 = cp1;
				while (cp3 < cp2 && *cp3 != '=')
					++cp3;
				if (cp3 == cp2)
					goto bad_option;
	
				// now cp1 points to option name, cp3 to '=', cp2 to ';' or null
				
				// first try for a feature by this name
				ATSUFontFeatureType	featureType;
				featureType = find_feature_by_name(fontID, cp1, cp3 - cp1);
				if (featureType != 0x0000FFFF) {
					// look past the '=' separator for setting names
					int	featLen = cp3 - cp1;
					++cp3;
					while (cp3 < cp2) {
						// skip leading whitespace
						while (*cp3 == ' ' || *cp3 == '\t')
							++cp3;
					
						// possibly multiple settings...
						int	disable = 0;
						if (*cp3 == '!') {	// check for negation
							disable = 1;
							++cp3;
						}
						
						// scan for end of setting name
						const char*	cp4 = cp3;
						while (cp4 < cp2 && *cp4 != ',')
							++cp4;
						
						// now cp3 points to name, cp4 to ',' or ';' or null
						ATSUFontFeatureSelector	selectorValue = find_selector_by_name(fontID, featureType, cp3, cp4 - cp3);
						if (selectorValue != 0x0000FFFF) {
							if (numFeatures == allocFeats) {
								allocFeats += FEAT_ALLOC_CHUNK;
								featureTypes = xrealloc(featureTypes, allocFeats * sizeof(UInt16));
								selectorValues = xrealloc(selectorValues, allocFeats * sizeof(UInt16));
							}
							featureTypes[numFeatures] = featureType;
							selectorValues[numFeatures] = selectorValue + disable;
							++numFeatures;
						}
						else {
							fontfeaturewarning(cp1, featLen, cp3, cp4 - cp3);
						}
						
						// point beyond setting name terminator
						cp3 = cp4 + 1;
					}
					
					goto next_option;
				}
				
				// try to find a variation by this name
				ATSUFontVariationAxis	axis;
				axis = find_axis_by_name(fontID, cp1, cp3 - cp1);
				if (axis != 0) {
					// look past the '=' separator for the value
					++cp3;
					double	value = 0.0, decimal = 1.0;
					bool		negate = false;
					if (*cp3 == '-') {
						++cp3;
						negate = true;
					}
					while (cp3 < cp2) {
						int	v = *cp3 - '0';
						if (v >= 0 && v <= 9) {
							if (decimal != 1.0) {
								value += v / decimal;
								decimal *= 10.0;
							}
							else
								value = value * 10.0 + v;
						}
						else if (*cp3 == '.') {
							if (decimal != 1.0)
								break;
							decimal = 10.0;
						}
						else
							break;
						++cp3;
					}
					if (negate)
						value = -value;
					if (numVariations == allocVars) {
						allocVars += VAR_ALLOC_CHUNK;
						axes = xrealloc(axes, allocVars * sizeof(UInt32));
						values = xrealloc(values, allocVars * sizeof(SInt32));
					}
					axes[numVariations] = axis;
					values[numVariations] = value * 65536.0;	//	X2Fix(value);
					++numVariations;
					
					goto next_option;
				}
				
				// didn't find feature or variation, try other options....
	
				i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue);
				if (i == 1)
					goto next_option;
				else if (i == -1)
					goto bad_option;
				
				if (strncmp(cp1, "tracking", 8) == 0) {
					cp3 = cp1 + 8;
					if (*cp3 != '=')
						goto bad_option;
					++cp3;
					double	val = read_double(&cp3);
					tracking = X2Fix(val);
					goto next_option;
				}
				
			bad_option:
				// not a name=value pair, or not recognized.... 
				// check for plain "vertical" before complaining
				if (strncmp(cp1, "vertical", 8) == 0) {
					cp3 = cp2;
					if (*cp3 == ';' || *cp3 == ':')
						--cp3;
					while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t')
						--cp3;
					if (*cp3)
						++cp3;
					if (cp3 == cp1 + 8) {
						ATSUVerticalCharacterType	vert = kATSUStronglyVertical;
						tags[0] = kATSUVerticalCharacterTag;
						sizes[0] = sizeof(ATSUVerticalCharacterType);
						attrs[0] = &vert;
						ATSUSetAttributes(style, 1, tags, sizes, attrs);
						goto next_option;
					}
				}
			
				fontfeaturewarning(cp1, cp2 - cp1, 0, 0);
				
			next_option:
				// go to next name=value pair
				cp1 = cp2;
			}
		
			if (numFeatures > 0)
				ATSUSetFontFeatures(style, numFeatures, featureTypes, selectorValues);
	
			if (numVariations > 0)
				ATSUSetVariations(style, numVariations, axes, values);
	
			if ((loadedfontflags & FONT_FLAGS_COLORED) != 0) {
				ATSURGBAlphaColor	rgba;
				rgba.red	= ((rgbValue & 0xFF000000) >> 24) / 255.0;
				rgba.green	= ((rgbValue & 0x00FF0000) >> 16) / 255.0;
				rgba.blue	= ((rgbValue & 0x0000FF00) >> 8 ) / 255.0;
				rgba.alpha	= ((rgbValue & 0x000000FF)      ) / 255.0;
				tags[0] = kATSURGBAlphaColorTag;
				sizes[0] = sizeof(ATSURGBAlphaColor);
				attrs[0] = &rgba;
				ATSUSetAttributes(style, 1, tags, sizes, attrs);
			}
Beispiel #2
0
static
OSStatus AddFunkyVariationsAndFeatures(
	ATSUStyle	styleToMangle )
{
	OSStatus				err;
	ItemCount				i;
	ATSUFontID				fontID;
	ItemCount				count;
	ItemCount				selectorCount;
	ATSUFontVariationAxis	variationAxis;
	ATSUFontVariationValue	variationMinimum;
	ATSUFontVariationValue	variationMaximum;
	ATSUFontVariationValue	variationDefault;
	Boolean					selectorMutex;
	ATSUFontFeatureType		*typeBuffer = NULL;
	ATSUFontFeatureSelector	*selectorBuffer = NULL;
	Boolean					*defaultBuffer = NULL;
	ItemCount				selectorBufferSize = 0;
	
	
	// get the fontID from the style
	err = ATSUGetAttribute( styleToMangle, kATSUFontTag, sizeof( ATSUStyle ),
		&fontID, NULL );
	require_noerr( err, AddFunkyVariationsAndFeatures_err );

	// get a count of all of the variations supported by the current font
	err = ATSUCountFontVariations( fontID, &count );
	require_noerr( err, AddFunkyVariationsAndFeatures_err );
	
	// loop through, setting all of the variations to the max!
	for ( i = 0; i < count; i++ )
	{
		// get the settings for the variations
		err = ATSUGetIndFontVariation( fontID, i, &variationAxis,
			&variationMinimum, &variationMaximum, &variationDefault );
		require_noerr( err, AddFunkyVariationsAndFeatures_err );
		
		// set the variation for this font to the max!
		err = ATSUSetVariations( styleToMangle, 1, &variationAxis,
			&variationMaximum );
		require_noerr( err, AddFunkyVariationsAndFeatures_err );
		
	}
	
	
	// get a count of all of the features
	err = ATSUCountFontFeatureTypes( fontID, &count );
	require_noerr( err, AddFunkyVariationsAndFeatures_err );
	
	// allocate a buffer for the feature types
	typeBuffer = (ATSUFontFeatureType *) malloc( sizeof( ATSUFontFeatureType )
		* count );
	require_action( typeBuffer != NULL, AddFunkyVariationsAndFeatures_err,
		err = paramErr );
		
	// get all of the font features
	err = ATSUGetFontFeatureTypes( fontID, count, typeBuffer, &selectorCount );
	require_noerr( err, AddFunkyVariationsAndFeatures_err );
	
	// loop through, setting all of the features
	for ( i = 0; i < count; i++ )
	{
		// get the selector count
		err = ATSUCountFontFeatureSelectors( fontID, typeBuffer[i],
			&selectorCount );
		require_noerr( err, AddFunkyVariationsAndFeatures_err );
		
		// if the selector buffer size is greater than what we had before,
		// then allocate some new buffers. Just use realloc, as when
		// the buffers are pointing to NULL, it will simply act as malloc.
		if ( selectorBufferSize < count ) 
		{
			ItemCount		newCount;
			
			// set the new size to be twice the old size
			newCount = 2 * count;
			
			// allocate  the selectorBuffer
			selectorBuffer = (ATSUFontFeatureSelector *) realloc( 
				selectorBuffer, newCount * sizeof( ATSUFontFeatureSelector ) );
			require_action( selectorBuffer != NULL,
				AddFunkyVariationsAndFeatures_err, err = memFullErr );
				
			// allocate the defaultBuffer
			defaultBuffer = (Boolean  *) realloc( defaultBuffer,
				newCount * sizeof( Boolean ) );
			require_action( defaultBuffer != NULL,
				AddFunkyVariationsAndFeatures_err, err = memFullErr );
				
			selectorBufferSize = newCount;
		}
		
		// get the font feature selectors
		err = ATSUGetFontFeatureSelectors( fontID, typeBuffer[i],
			selectorBufferSize, selectorBuffer, defaultBuffer, &selectorCount,
			&selectorMutex );
		require_noerr( err, AddFunkyVariationsAndFeatures_err );
		
		// if the features are not mutually exclusive, then go ahead and
		// set them all.
		if ( selectorMutex == false )
		{
			ItemCount	j;
			
			// loop through and set all of the features
			for ( j = 0; j < selectorCount; j++ )
			{
				if ( defaultBuffer[j] == false )
				{
					err = ATSUSetFontFeatures( styleToMangle, 1, &typeBuffer[i],
						&selectorBuffer[j] );
					require_noerr( err, AddFunkyVariationsAndFeatures_err );
				}
			}
			
		}
		else
		{
			// just set the last option, then since we can't set them all
			err = ATSUSetFontFeatures( styleToMangle, 1, &typeBuffer[i],
				&selectorBuffer[selectorCount - 1] );
			require_noerr( err, AddFunkyVariationsAndFeatures_err );
		}
		
	}
		
	// that should be enough style perversion for now!
	
	
AddFunkyVariationsAndFeatures_err:

	if ( typeBuffer != NULL )
	{
		free( typeBuffer );
	}
	
	if ( selectorBuffer != NULL )
	{
		free( selectorBuffer );
	}
	
	if ( defaultBuffer != NULL )
	{
		free( defaultBuffer );
	}

	return err;
	
}