how to use multiple fonts?

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

 



This is a multi-part message in MIME format.
--------------89A6484203A15FCE7F7A254B
Content-Type: text/plain; charset=gb2312
Content-Transfer-Encoding: 7bit

Keith Packard wrote:

> Around 11 o'clock on Mar 5, Federic Zhang wrote:
>
> > Thanks for this information.  I will refer to the corresponding implemention
> > in Pango, using low-level FcFontSort is too complicated at least for me.
>
> Yes, it is rather complicated.  Perhaps your experience can serve as a
> guide for a higher level interface that could be integrated into Xft.
>

I finished one by following implementation within Pango.

The attached APIs can be used as reference to implement  the new API
with multiple fonts, it would be great if they can be integreated into Xft.
They can be used as like:

        XftText *text = XftCreateText(dpy, scr, pattern, str, count_chars,
StringUtf8);
        XftDrawText(draw, color, text, x, y);

Of course, its performance is one outstanding issue.

-federic


--------------89A6484203A15FCE7F7A254B
Content-Type: text/plain; charset=gb2312;
 name="xfttext.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="xfttext.c"

#include <glib.h>
#include <fontconfig/fontconfig.h>
#include <Xfttext.h>

typedef struct _XftPatternSet {
   int num_patterns;
   FcPattern **patterns;
} XftPatternSet;

typedef struct _CharProp {
   int pattern_index; /* index of "patterns" */ 
   int count_chars;   /* number of characters sharing the same pattern */
} CharProp;

static void
XftFreePatternSet(XftPatternSet *set)
{
   int n;
   
   for (n=0; n < set->num_patterns; ++n)
       FcPatternDestroy(set->patterns[n]);
     
    g_free(set->patterns);
    g_free(set);
}

static XftPatternSet *
XftCreatePatternSet(FcPattern *pattern)
{
   XftPatternSet *set;
   FcFontSet     *font_patterns;
   int f;
   
   font_patterns = FcFontSort(NULL, pattern, FcTrue, 0, NULL);
   if (!font_patterns) return NULL;
 
   set = g_new0(XftPatternSet, 1);
   set->patterns = g_new0(FcPattern *, font_patterns->nfont);
   set->num_patterns = font_patterns->nfont;

   for (f=0; f < font_patterns->nfont; f++)
	set->patterns[f] = FcFontRenderPrepare(NULL, pattern, font_patterns->fonts[f]);
    
   FcFontSetDestroy(font_patterns);

   return set;
}
   
static int
getFontIdx(FcChar32 ucs4, XftPatternSet *set)
{
   int n;
   
   for (n=0; n < set->num_patterns; ++n)
     {
       FcCharSet *charset;
       FcPattern *pattern = set->patterns[n];
	
       if (FcPatternGetCharSet(pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
         return -1;

       if (FcCharSetHasChar(charset, ucs4)) return n;
     }
	
   return -1;
}

static CharProp *
getCharProp(XftPatternSet *set, void *v, int count_chars, XftTextEncoding encoding)
{
    CharProp *charprop;
    int i, position,prev_index;
   
    charprop = g_new0(CharProp, count_chars);
    for (i = 0; i < count_chars; ++i)
     {
       gunichar ucs4;
       
       switch (encoding)
	  {
	  case String8:
	     {
		char *p = (char *)v;
		ucs4 = (FcChar32)*p;
		v = (void *)(p+1);
	     }	     
	     break;
	  case String16:
	     {
		FcChar16 *p = (FcChar16 *)v;
		ucs4 = (FcChar32)*p;
		v = (void *)(p+1);
	     }
	     break;
	  case String32:
	     {
		FcChar32 *p = (FcChar32 *)v;
		ucs4 = *p;
		v = (void *)(p+1);
	     }	     
	     break;
	  case StringUtf8:
	     {
	        char *p = (char *)v;
	        ucs4 = g_utf8_get_char(p);
	        v = (void *)g_utf8_next_char(p);
	      }
	     break;
	  case StringUtf16:
	     // not implemented yet
	     break;
	  }
	
       charprop[i].pattern_index = getFontIdx(ucs4, set);
     }
   
    position = 0;
    prev_index = charprop[0].pattern_index;
    for(i=1; i < count_chars; ++i)
     {
	if (charprop[i].pattern_index != prev_index)
	  {
	     charprop[position].count_chars = i - position;
	     prev_index = charprop[i].pattern_index;
	     position = i;
	  }	
     }   
   charprop[position].count_chars = i - position;
   
   return charprop;
}

XftText *
XftCreateText(Display *dpy, int scr, FcPattern *pattern, 
	      void *v, int count_chars, XftTextEncoding encoding)
{
   XftPatternSet *set;
   XftText *text;
   CharProp *charprop;
   int i, num_textitems = 0;
   
   set = XftCreatePatternSet(pattern);
   charprop = getCharProp(set, v, count_chars, encoding);
   
   for(i=0; i<count_chars; ++i)
       if (charprop[i].count_chars) ++num_textitems;
   
   text = g_new0(XftText, 1);
   text->num_textitems = num_textitems;
   text->textitems = g_new0(XftTextItem, num_textitems);
   
   num_textitems = 0;
   for(i=0; i < count_chars; ++i)
     {
	if (charprop[i].count_chars)
	  {
	      FcPattern *match;
	      FcResult result;
	      XftTextItem *item = &text->textitems[num_textitems];

	      item->encoding = encoding;
	     
	      switch (encoding)
	       {
		case String8:
		  {
		     char *string = (char *)v;
		     item->text = g_strndup(string, count_chars);
		  }
		  break;
		case String16:
		  {
		     FcChar16 *string = (FcChar16 *)v;

		     item->text = g_new0(FcChar16, count_chars + 1);
		     memcpy(item->text, string, count_chars * sizeof(FcChar16)/sizeof(char));
		  }
		  break;
		case String32:
		  {
		     FcChar32 *string = (FcChar32 *)v;

		     item->text = g_new0(FcChar32, count_chars + 1);
		     memcpy(item->text, string, count_chars * sizeof(FcChar32)/sizeof(char));
		  }
		  break;
		case StringUtf8:
	          {
		     char *string = (char *)v;
	     	     char *start = (char *)g_utf8_offset_to_pointer(string, i);
	             char *end = (char *)g_utf8_offset_to_pointer(string, i + charprop[i].count_chars);
	    
	             item->text = g_new0(char, end - start + 1);
	             g_utf8_strncpy((char *)item->text, start, charprop[i].count_chars);
	    	  } 
		  break;
		case StringUtf16:
		  // not implemented yet
		  break;
	       }

	     match = XftFontMatch(dpy, scr, 
			set->patterns[charprop[i].pattern_index], &result);
	     if (match) 
		 {
	     	    item->font = XftFontOpenPattern(dpy, match);
		    FcPatternDestroy(match);
		 }
	       
	     ++num_textitems;
	  }
     }   
  
   g_free(charprop);
   XftFreePatternSet(set);
   
   return text;
}

void
XftDrawText(XftDraw *draw, _Xconst XftColor *color, XftText *text, int x, int y)
{
   int i, xx = x, yy = y;
   
   for(i=0; i < text->num_textitems; ++i)
     {
	XftFont *font;
	Display *dpy = XftDrawDisplay(draw);
	XGlyphInfo extents;
	int len;
	
	font = text->textitems[i].font;
	switch (text->textitems[i].encoding)
	  {
	   case String8:
	     {
		char *string = (char *)text->textitems[i].text;
		
		len = strlen(string);
		XftDrawString8(draw, color, font, xx, yy, string, len);
		XftTextExtentsUtf8(dpy, font, string, len, &extents);
	     }
	     break;
	   case String16:
	     {
		FcChar16 *string = (FcChar16 *)text->textitems[i].text;

		len = 0;
		while (string[len] != (FcChar16)0) ++len;
		
		XftDrawString16(draw, color, font, xx, yy, string, len);
		XftTextExtents16(dpy, font, string, len, &extents);
	     }
	     break;
	   case String32:
	     {
		FcChar32 *string = (FcChar32 *)text->textitems[i].text;

		len = 0;
		while (string[len] != (FcChar32)0) ++len;
		
		XftDrawString32(draw, color, font, xx, yy, string, len);
		XftTextExtents32(dpy, font, string, len, &extents);
	     }
	     break;
	   case StringUtf8:
	     {
		char *string = (char *)text->textitems[i].text;
		
		len = strlen(string);
		
		XftDrawStringUtf8(draw, color, font, xx, yy, string, len);
		XftTextExtentsUtf8(dpy, font, string, len, &extents);
	     }
	     break;
	   case StringUtf16:
	     // not implemented yet
	     break;
	  }
	
	xx += extents.xOff;
     }
}

void
XftFreeText(Display *dpy, XftText *text)
{
   int i;
   
   if (!text) return;
   
   for (i=0; i < text->num_textitems; ++i)
     {
	XftTextItem textitem = text->textitems[i];
	
	if (textitem.text) g_free(textitem.text);
	XftFontClose(dpy, textitem.font);
     }
   
   g_free(text->textitems);
   g_free(text);
}

--------------89A6484203A15FCE7F7A254B
Content-Type: text/plain; charset=gb2312;
 name="Xfttext.h"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Xfttext.h"

#ifndef _Xfttext_H_
#define _Xfttext_H_

#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include <X11/Xft/XftCompat.h>

typedef enum {String8, String16, String32, StringUtf8, StringUtf16 } XftTextEncoding;

typedef struct _XftTextItem {
   XftFont         *font;
   void            *text;
   XftTextEncoding encoding; /* specify the encoding of 'text' */
} XftTextItem;

typedef struct _XftText {   
   int         num_textitems;
   XftTextItem *textitems;
} XftText;

extern XftText *XftCreateText(Display *, int, FcPattern *, void *, int, XftTextEncoding);
extern void XftDrawText(XftDraw *, _Xconst XftColor *, XftText *, int, int);
extern void XftFreeText(Display *dpy, XftText *);

#endif

--------------89A6484203A15FCE7F7A254B--




[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux