[cairo] Re: Patch to improve the rule for artificial emboldening

sunmoon1997 sunmoon1997 at gmail.com
Thu Sep 29 07:07:19 PDT 2005


hi,
  I vote for adding embeddedbitmap option to official fontconfig.
  Several distros have shiped patched version of fontconfig which adds
an option like rh_prefer_bitmap or embeddedbitmap. Because we need a way
to explictly tell Xft/Cairo to load bitmaps embedded in fonts or not.
And for cairo, if i want to cairo transform a font to pretend as an
oblique one, and when i disable antialias for the font, then cairo will
always load embedded bitmaps if available, latter cairo(exactly to say
it's freetype) will be unable to transform the font glyphs because they
are bitmaps. If option embeddedbitmap is available, we can tell freetype
to load outlines rather than embedded bitmaps by set embeddedbitmap to
false and then can transform font glyphs as expected. Xft is smart
enough in this case, it add FC_LOAD_NO_BITMAP to load flags when loading
glyphs. But that is not easily to implement in cairo, because cairo
doesn't handle FC_MATRIX itself.
Mike FABIAN wrote:
> For details please see
> 
> http://bugzilla.novell.com/show_bug.cgi?id=118727
> 
> This patch makes two small changes to the rule for artificial
> emboldening in /etc/fonts/fonts.conf:
> 
> 1)
>     don't check for "weight >= 200" but for "weight > 100",
>     i.e. instead of 
> 
>                 <!-- check to see if the pattern requests bold -->
>                 <test target="pattern" name="weight" compare="more_eq">
>                         <int>200</int>
>                 </test>
> 
>     use
> 
>                 <!-- check to see if the pattern requests bold -->
>                 <test target="pattern" name="weight" compare="more">
>                         <int>100</int>
>                 </test>
> 
>     This is necessary to make <strong>foo</strong> appear bold
>     in firefox. When checking "weight >= 200", emboldening will work for
> 
>         <span style="font-weight:bold;">foo</span>
> 
>     in firefox but not for <strong>foo</strong>
> 
>     (To make it a better readable I used "<const>medium</const>"
>     instead of "<int>100</int>". This makes no functional difference
>     it only enhances the readability).
> 
> 2)
>     in addition to setting "embolden" to "true", also set
>     "weight" to "bold", i.e. add:
> 
> 		<!--
> 		 set weight to bold
> 		 needed for applications using Xft directly, e.g. Firefox, ...
> 		-->
> 		<edit name="weight" mode="assign">
> 			<const>bold</const>
> 		</edit>
> 
>     to the rule. This is necessary to make artificial emboldening
>     work in applications who do no (yet) use cairo but use
>     Xft directly[1]
> 
> Footnotes: 
> [1]  to make this work Xft needs to have the patch for embedded bitmap
> support and artificial emboldening applied which I attach here as well
> for reference.
> 
> 
> 
> ------------------------------------------------------------------------
> 
> diff -ru fontconfig-2.3.2.20050721.orig/fonts.conf.in fontconfig-2.3.2.20050721/fonts.conf.in
> --- fontconfig-2.3.2.20050721.orig/fonts.conf.in	2005-04-21 21:03:53.000000000 +0200
> +++ fontconfig-2.3.2.20050721/fonts.conf.in	2005-09-27 15:04:33.000000000 +0200
> @@ -346,16 +361,26 @@
>  	<match target="font">
>  		<!-- check to see if the font is just regular -->
>  		<test name="weight" compare="less_eq">
> -			<int>100</int>
> +			<const>medium</const>
>  		</test>
>  		<!-- check to see if the pattern requests bold -->
> -		<test target="pattern" name="weight" compare="more_eq">
> -			<int>200</int>
> +		<test target="pattern" name="weight" compare="more">
> +			<const>medium</const>
>  		</test>
> -		<!-- set the embolden flag -->
> +		<!--
> +		  set the embolden flag
> +		  needed for applications using cairo, e.g. gucharmap, gedit, ...
> +		-->
>  		<edit name="embolden" mode="assign">
>  			<bool>true</bool>
>  		</edit>
> +		<!--
> +		 set weight to bold
> +		 needed for applications using Xft directly, e.g. Firefox, ...
> +		-->
> +		<edit name="weight" mode="assign">
> +			<const>bold</const>
> +		</edit>
>  	</match>
>  
>  
> 
> 
> ------------------------------------------------------------------------
> 
> diff -urN xc/lib/Xft.old/xftfreetype.c xc/lib/Xft/xftfreetype.c
> --- xc/lib/Xft.old/xftfreetype.c	2004-03-12 19:29:52.000000000 +0800
> +++ xc/lib/Xft/xftfreetype.c	2004-04-01 17:15:35.376042784 +0800
> @@ -379,6 +379,7 @@
>      FcChar32	    hash, *hashp;
>      FT_Face	    face;
>      int		    nhash;
> +    FcBool	    bitmap;
>  
>      if (!info)
>  	return FcFalse;
> @@ -501,8 +502,22 @@
>       */
>      fi->load_flags = FT_LOAD_DEFAULT;
>  
> +#ifndef XFT_EMBEDDED_BITMAP
> +#define XFT_EMBEDDED_BITMAP "embeddedbitmap"
> +#endif
> +
> +    switch (FcPatternGetBool (pattern, XFT_EMBEDDED_BITMAP, 0, &bitmap)) {
> +    case FcResultNoMatch:
> +	bitmap = FcFalse;
> +	break;
> +    case FcResultMatch:
> +	break;
> +    default:
> +	goto bail1;
> +    }
> +
>      /* disable bitmaps when anti-aliasing or transforming glyphs */
> -    if (fi->antialias || fi->transform)
> +    if ((!bitmap && fi->antialias) || fi->transform)
>  	fi->load_flags |= FT_LOAD_NO_BITMAP;
>      
>      /* disable hinting if requested */
> @@ -658,6 +673,19 @@
>      default:
>  	goto bail1;
>      }
> +    
> +    /*
> +     * Check for weight
> +     */
> +    switch (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &fi->weight_value)) {
> +    case FcResultNoMatch:
> +	fi->weight_value = FC_WEIGHT_MEDIUM;
> +	break;
> +    case FcResultMatch:
> +	break;
> +    default:
> +	goto bail1;
> +    }
>  
>      /*
>       * Step over hash value in the structure
> @@ -969,6 +997,54 @@
>      font->max_glyph_memory = max_glyph_memory;
>      font->use_free_glyphs = info->use_free_glyphs;
>      
> +    /*
> +     * Extra bitmap strokes
> +     */
> +    font->extra_strokes = 0;
> +    font->extra_advanceX = 0;
> +    if (fi->weight_value >= FC_WEIGHT_DEMIBOLD &&
> +	(face->style_flags & FT_STYLE_FLAG_BOLD) == 0)
> +    {
> +	font->extra_strokes =
> +	    32 + FT_MulDiv (fi->xsize, fi->weight_value - 160, 1600);
> +
> +	if (fi->weight_value >= FC_WEIGHT_BOLD)
> +	    font->extra_advanceX =
> +		(font->extra_strokes > 64)? font->extra_strokes : 64;
> +    }
> +    
> +    /*
> +     * CJK fixed widths fields
> +     */
> +    font->long_advance.x = 0;
> +    font->long_advance.y = 0;
> +    font->short_advance.x = 0;
> +    font->short_advance.y = 0;
> +    if (font->info.spacing == FC_MONO && fi->char_width == 0 &&
> +	(fi->load_flags & FT_LOAD_VERTICAL_LAYOUT) == 0 &&
> +	(fi->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) != 0)
> +    {
> +	if (!FT_Select_Charmap (face, ft_encoding_unicode))
> +	{
> +	    font->long_advance.x =
> +		face->size->metrics.max_advance + font->extra_advanceX;
> +	    if (fi->transform)
> +		FT_Vector_Transform (&font->long_advance, &fi->matrix);
> +	    font->long_advance.x = (font->long_advance.x + 32) >> 6;
> +	    font->long_advance.y = (font->long_advance.y + 32) >> 6;
> +
> +	    if (font->long_advance.x > 0)
> +		font->short_advance.x = (font->long_advance.x + 1) >> 1;
> +	    else
> +		font->short_advance.x = font->long_advance.x >> 1;
> +
> +	    if (font->long_advance.y > 0)
> +		font->short_advance.y = (font->long_advance.y + 1) >> 1;
> +	    else
> +		font->short_advance.y = font->long_advance.y >> 1;
> +	}
> +    }
> +
>      _XftUnlockFile (fi->file);
>  
>      return &font->public;
> diff -urN xc/lib/Xft.old/xftglyphs.c xc/lib/Xft/xftglyphs.c
> --- xc/lib/Xft.old/xftglyphs.c	2004-03-12 04:48:19.000000000 +0800
> +++ xc/lib/Xft/xftglyphs.c	2004-04-01 17:15:35.381042024 +0800
> @@ -216,6 +216,7 @@
>  	    bottom = FLOOR( glyphslot->metrics.horiBearingY - glyphslot->metrics.height );
>  	}
>  
> +	right += CEIL(font->extra_strokes);
>  	width = TRUNC(right - left);
>  	height = TRUNC( top - bottom );
>  
> @@ -223,7 +224,8 @@
>  	 * Try to keep monospace fonts ink-inside
>  	 * XXX transformed?
>  	 */
> -	if (font->info.spacing != FC_PROPORTIONAL && !font->info.transform)
> +	if (font->info.spacing != FC_PROPORTIONAL && !font->info.transform &&
> +	    font->long_advance.x == 0 && font->long_advance.y == 0)
>  	{
>  	    if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
>  	    {
> @@ -264,12 +266,26 @@
>  
>  	xftg->metrics.width = width;
>  	xftg->metrics.height = height;
> -	xftg->metrics.x = -TRUNC(left);
> +	xftg->metrics.x = -TRUNC(left) + TRUNC((font->extra_strokes +32) * 1/2);
>  	xftg->metrics.y = TRUNC(top);
>  
>  	if (font->info.spacing != FC_PROPORTIONAL)
>  	{
> -	    if (font->info.transform)
> +	    if (font->long_advance.x != 0 || font->long_advance.y != 0)
> +	    {
> +		if (glyphslot->metrics.horiAdvance >
> +		    face->size->metrics.max_advance * 3/4)
> +		{
> +		    xftg->metrics.xOff = font->long_advance.x;
> +		    xftg->metrics.yOff = -font->long_advance.y;
> +		}
> +		else
> +		{
> +		    xftg->metrics.xOff = font->short_advance.x;
> +		    xftg->metrics.yOff = -font->short_advance.y;
> +		}
> +	    }
> +	    else if (font->info.transform)
>  	    {
>  		if (font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT)
>  		{
> @@ -301,6 +317,15 @@
>  	}
>  	else
>  	{
> +	    if (font->extra_advanceX > 0 &&
> +		(font->info.load_flags & FT_LOAD_VERTICAL_LAYOUT) == 0)
> +	    {
> +		glyphslot->advance.x =
> +		    glyphslot->metrics.horiAdvance + font->extra_advanceX;
> +		glyphslot->advance.y = 0;
> +		if (font->info.transform)
> +		    FT_Vector_Transform (&glyphslot->advance, &font->info.matrix);
> +	    }
>  	    xftg->metrics.xOff = TRUNC(ROUND(glyphslot->advance.x));
>  	    xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y));
>  	}
> @@ -403,6 +428,53 @@
>  	    continue;
>  	}
>  	
> +	if (font->extra_strokes > 0)
> +	{
> +	    int extra = font->extra_strokes;
> +	    int degree;
> +	    int i, h, g, d, k;
> +
> +	    if (glyphslot->format == ft_glyph_format_bitmap)
> +		extra += 8;
> +	    extra *= hmul;
> +	    degree = TRUNC(CEIL(extra));
> +
> +	    for (i = 0; i < degree; i++)
> +	    {
> +		d = (i == 0)? (extra % 64) : 64;
> +		if (d == 0)
> +		    d = 64;
> +		for (h = 0; h < height; h++)
> +		{
> +		    unsigned char *pos = bufBitmap + h * pitch;
> +		    k = pitch;
> +		    if (font->info.antialias)
> +		    {
> +			if (i > 0)
> +			    while (--k > 0)
> +				pos[k] = (pos[k] > pos[k - 1])? pos[k] : pos[k - 1];
> +			else
> +			{
> +			    while (--k > 0)
> +			    {
> +				g = pos[k];
> +				g += d * ((pos[k - 1] > 0)? pos[k - 1]/64 : g/128);
> +				pos[k] = (g > 0xff)? 0xff : g;
> +			    }
> +			    g = pos[0] + pos[0] * d / 128;
> +			    pos[0] = (g > 0xff)? 0xff : g;
> +			}
> +		    }
> +		    else
> +		    {
> +			while (--k > 0)
> +			    pos[k] = pos[k] | (pos[k] >> 1) | (pos[k - 1] << 7);
> +			pos[0] = pos[0] | (pos[0] >> 1);
> +		    }
> +		}
> +	    }
> +        }
> +
>  	if (XftDebug() & XFT_DBG_GLYPH)
>  	{
>  	    printf ("glyph %d:\n", (int) glyphindex);
> diff -urN xc/lib/Xft.old/xftint.h xc/lib/Xft/xftint.h
> --- xc/lib/Xft.old/xftint.h	2004-03-12 04:48:19.000000000 +0800
> +++ xc/lib/Xft/xftint.h	2004-04-01 17:15:35.383041720 +0800
> @@ -120,6 +120,7 @@
>      int			spacing;
>      FcBool		minspace;
>      int			char_width;
> +    int			weight_value;
>  };
>  
>  /*
> @@ -156,6 +157,16 @@
>      unsigned long	glyph_memory;
>      unsigned long	max_glyph_memory;
>      FcBool		use_free_glyphs;   /* Use XRenderFreeGlyphs */
> +    /*
> +     * CJK fixed widths infomation
> +     */
> +    FT_Vector		long_advance;
> +    FT_Vector		short_advance;
> +    /*
> +     * Extra bitmap strokes
> +     */
> +    int			extra_strokes;
> +    int			extra_advanceX;
>  } XftFontInt;
>  
>  typedef enum _XftClipType {
> diff -urN xc/lib/Xft.old/xftname.c xc/lib/Xft/xftname.c
> --- xc/lib/Xft.old/xftname.c	2004-03-12 04:48:19.000000000 +0800
> +++ xc/lib/Xft/xftname.c	2004-04-01 17:10:22.294638392 +0800
> @@ -33,7 +33,7 @@
>  
>  #define NUM_OBJECT_TYPES    (sizeof _XftObjectTypes / sizeof _XftObjectTypes[0])
>  
> -FcBool	_XftNameInitialized;
> +FcBool	_XftNameInitialized =FcFalse;
>  
>  void 
>  _XftNameInit (void)
> 
> 
> ------------------------------------------------------------------------
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Fontconfig mailing list
> Fontconfig at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/fontconfig

-------------- next part --------------
A non-text attachment was scrubbed...
Name: fontconfig-add-embedded-bitmap-option.diff
Type: text/x-patch
Size: 2629 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050929/63d40d39/fontconfig-add-embedded-bitmap-option-0001.bin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cairo-ft-font-embbedbitmap-options.diff
Type: text/x-patch
Size: 784 bytes
Desc: not available
Url : http://lists.freedesktop.org/archives/cairo/attachments/20050929/63d40d39/cairo-ft-font-embbedbitmap-options-0001.bin


More information about the cairo mailing list