5 if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA))
8 + if (!_XftDefaultInitInteger (dpy, pat, FC_LCD_FILTER))
11 if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS))
15 XftDefaultGetInteger (dpy, FC_RGBA, screen,
19 + if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
21 + FcPatternAddInteger (pattern, FC_LCD_FILTER,
22 + XftDefaultGetInteger (dpy, FC_LCD_FILTER, screen,
26 if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch)
28 FcPatternAddBool (pattern, FC_MINSPACE,
29 --- a/src/xftfreetype.c
30 +++ b/src/xftfreetype.c
37 + * Get lcd_filter value
39 + switch (FcPatternGetInteger (pattern, FC_LCD_FILTER, 0, &fi->lcd_filter)) {
40 + case FcResultNoMatch:
41 + fi->lcd_filter = FC_LCD_DEFAULT;
51 * Get matrix and transform values
59 -#include <freetype/ftoutln.h>
61 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
62 #include <freetype/ftsynth.h>
65 -static const int filters[3][3] = {
68 -{ 65538*4/7,65538*2/7,65538*1/7 },
70 -{ 65536*1/4, 65536*2/4, 65537*1/4 },
72 -{ 65538*1/7,65538*2/7,65538*4/7 },
73 +#if FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH < 20202
74 +# error "FreeType 2.2.2 or later required to compile this version of libXft"
76 -{ 65538*9/13,65538*3/13,65538*1/13 },
78 -{ 65538*1/6, 65538*4/6, 65538*1/6 },
80 -{ 65538*1/13,65538*3/13,65538*9/13 },
83 +#include FT_OUTLINE_H
84 +#include FT_LCD_FILTER_H
85 +#include FT_SYNTHESIS_H
88 * Validate the memory info for a font
90 font->glyph_memory, glyph_memory);
94 +/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
95 + * into a different format. For example, we want to convert a
96 + * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
97 + * ARGB or ABGR bitmap.
99 + * this function prepares a target descriptor for this operation.
101 + * input :: target bitmap descriptor. The function will set its
102 + * 'width', 'rows' and 'pitch' fields, and only these
104 + * slot :: the glyph slot containing the source bitmap. this
105 + * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
107 + * mode :: the requested final rendering mode. supported values are
108 + * MONO, NORMAL (i.e. gray), LCD and LCD_V
110 + * the function returns the size in bytes of the corresponding buffer,
111 + * it's up to the caller to allocate the corresponding memory block
112 + * before calling _fill_xrender_bitmap
114 + * it also returns -1 in case of error (e.g. incompatible arguments,
115 + * like trying to convert a gray bitmap into a monochrome one)
118 +_compute_xrender_bitmap_size( FT_Bitmap* target,
120 + FT_Render_Mode mode )
123 + int width, height, pitch;
125 + if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
128 + // compute the size of the final bitmap
129 + ftbit = &slot->bitmap;
131 + width = ftbit->width;
132 + height = ftbit->rows;
133 + pitch = (width+3) & ~3;
135 + switch ( ftbit->pixel_mode )
137 + case FT_PIXEL_MODE_MONO:
138 + if ( mode == FT_RENDER_MODE_MONO )
140 + pitch = (((width+31) & ~31) >> 3);
145 + case FT_PIXEL_MODE_GRAY:
146 + if ( mode == FT_RENDER_MODE_LCD ||
147 + mode == FT_RENDER_MODE_LCD_V )
149 + /* each pixel is replicated into a 32-bit ARGB value */
154 + case FT_PIXEL_MODE_LCD:
155 + if ( mode != FT_RENDER_MODE_LCD )
158 + /* horz pixel triplets are packed into 32-bit ARGB values */
163 + case FT_PIXEL_MODE_LCD_V:
164 + if ( mode != FT_RENDER_MODE_LCD_V )
167 + /* vert pixel triplets are packed into 32-bit ARGB values */
172 + default: /* unsupported source format */
176 + target->width = width;
177 + target->rows = height;
178 + target->pitch = pitch;
179 + target->buffer = NULL;
181 + return pitch * height;
184 +/* this functions converts the glyph bitmap found in a FT_GlyphSlot
185 + * into a different format (see _compute_xrender_bitmap_size)
187 + * you should call this function after _compute_xrender_bitmap_size
189 + * target :: target bitmap descriptor. Note that its 'buffer' pointer
190 + * must point to memory allocated by the caller
192 + * slot :: the glyph slot containing the source bitmap
194 + * mode :: the requested final rendering mode
196 + * bgr :: boolean, set if BGR or VBGR pixel ordering is needed
199 +_fill_xrender_bitmap( FT_Bitmap* target,
201 + FT_Render_Mode mode,
204 + FT_Bitmap* ftbit = &slot->bitmap;
207 + unsigned char* srcLine = ftbit->buffer;
208 + unsigned char* dstLine = target->buffer;
209 + int src_pitch = ftbit->pitch;
210 + int width = target->width;
211 + int height = target->rows;
212 + int pitch = target->pitch;
216 + subpixel = ( mode == FT_RENDER_MODE_LCD ||
217 + mode == FT_RENDER_MODE_LCD_V );
219 + if ( src_pitch < 0 )
220 + srcLine -= src_pitch*(ftbit->rows-1);
222 + switch ( ftbit->pixel_mode )
224 + case FT_PIXEL_MODE_MONO:
225 + if ( subpixel ) /* convert mono to ARGB32 values */
227 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
231 + for ( x = 0; x < width; x++ )
233 + if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
234 + ((unsigned int*)dstLine)[x] = 0xffffffffU;
238 + else if ( mode == FT_RENDER_MODE_NORMAL ) /* convert mono to 8-bit gray */
240 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
244 + for ( x = 0; x < width; x++ )
246 + if ( srcLine[(x >> 3)] & (0x80 >> (x & 7)) )
251 + else /* copy mono to mono */
253 + int bytes = (width+7) >> 3;
255 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
256 + memcpy( dstLine, srcLine, bytes );
260 + case FT_PIXEL_MODE_GRAY:
261 + if ( subpixel ) /* convert gray to ARGB32 values */
263 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
266 + unsigned int* dst = (unsigned int*)dstLine;
268 + for ( x = 0; x < width; x++ )
270 + unsigned int pix = srcLine[x];
273 + pix |= (pix << 16);
279 + else /* copy gray into gray */
281 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
282 + memcpy( dstLine, srcLine, width );
286 + case FT_PIXEL_MODE_LCD:
289 + /* convert horizontal RGB into ARGB32 */
290 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
293 + unsigned char* src = srcLine;
294 + unsigned int* dst = (unsigned int*)dstLine;
296 + for ( x = 0; x < width; x++, src += 3 )
300 + pix = ((unsigned int)src[0] << 16) |
301 + ((unsigned int)src[1] << 8) |
302 + ((unsigned int)src[2] ) |
303 + ((unsigned int)src[1] << 24) ;
311 + /* convert horizontal BGR into ARGB32 */
312 + for ( h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch )
315 + unsigned char* src = srcLine;
316 + unsigned int* dst = (unsigned int*)dstLine;
318 + for ( x = 0; x < width; x++, src += 3 )
322 + pix = ((unsigned int)src[2] << 16) |
323 + ((unsigned int)src[1] << 8) |
324 + ((unsigned int)src[0] ) |
325 + ((unsigned int)src[1] << 24) ;
333 + default: /* FT_PIXEL_MODE_LCD_V */
334 + /* convert vertical RGB into ARGB32 */
337 + for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
340 + unsigned char* src = srcLine;
341 + unsigned int* dst = (unsigned int*)dstLine;
343 + for ( x = 0; x < width; x++, src += 1 )
347 + pix = ((unsigned int)src[0] << 16) |
348 + ((unsigned int)src[src_pitch] << 8) |
349 + ((unsigned int)src[src_pitch*2] ) |
350 + ((unsigned int)src[src_pitch] << 24) ;
358 + for ( h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch )
361 + unsigned char* src = srcLine;
362 + unsigned int* dst = (unsigned int*)dstLine;
364 + for ( x = 0; x < width; x++, src += 1 )
368 + pix = ((unsigned int)src[src_pitch*2] << 16) |
369 + ((unsigned int)src[src_pitch] << 8) |
370 + ((unsigned int)src[0] ) |
371 + ((unsigned int)src[src_pitch] << 24) ;
383 XftFontLoadGlyphs (Display *dpy,
386 unsigned char *bufBitmap = bufLocal;
387 int bufSize = sizeof (bufLocal);
389 - unsigned char bufLocalRgba[4096];
390 - unsigned char *bufBitmapRgba = bufLocalRgba;
391 - int bufSizeRgba = sizeof (bufLocalRgba);
392 - int sizergba, pitchrgba, widthrgba;
395 int left, right, top, bottom;
403 - Bool subpixel = False;
405 + FT_Render_Mode mode = FT_RENDER_MODE_MONO;
409 @@ -110,24 +384,19 @@
413 - matrix.xx = matrix.yy = 0x10000L;
414 - matrix.xy = matrix.yx = 0;
416 if (font->info.antialias)
418 switch (font->info.rgba) {
424 + mode = FT_RENDER_MODE_LCD;
431 + mode = FT_RENDER_MODE_LCD_V;
434 + mode = FT_RENDER_MODE_NORMAL;
439 if (xftg->glyph_memory)
442 + FT_Library_SetLcdFilter( _XftFTlibrary, font->info.lcd_filter);
444 error = FT_Load_Glyph (face, glyphindex, font->info.load_flags);
451 * Compute glyph metrics from FreeType information
453 - if(font->info.transform && glyphslot->format != ft_glyph_format_bitmap)
454 + if(font->info.transform && glyphslot->format != FT_GLYPH_FORMAT_BITMAP)
457 * calculate the true width by transforming all four corners.
458 @@ -260,17 +532,14 @@
462 - if (font->info.antialias)
463 - pitch = (width * hmul + 3) & ~3;
465 - pitch = ((width + 31) & ~31) >> 3;
467 - size = pitch * height * vmul;
468 + if ( glyphslot->format != FT_GLYPH_FORMAT_BITMAP )
470 + error = FT_Render_Glyph( face->glyph, mode );
475 - xftg->metrics.width = width;
476 - xftg->metrics.height = height;
477 - xftg->metrics.x = -TRUNC(left);
478 - xftg->metrics.y = TRUNC(top);
479 + FT_Library_SetLcdFilter( _XftFTlibrary, FT_LCD_FILTER_NONE );
481 if (font->info.spacing >= FC_MONO)
483 @@ -310,103 +579,13 @@
484 xftg->metrics.yOff = -TRUNC(ROUND(glyphslot->advance.y));
488 - * If the glyph is relatively large (> 1% of server memory),
489 - * don't send it until necessary
491 - if (!need_bitmaps && size > info->max_glyph_memory / 100)
495 - * Make sure there's enough buffer space for the glyph
497 - if (size > bufSize)
499 - if (bufBitmap != bufLocal)
501 - bufBitmap = (unsigned char *) malloc (size);
506 - memset (bufBitmap, 0, size);
509 - * Rasterize into the local buffer
511 - switch (glyphslot->format) {
512 - case ft_glyph_format_outline:
513 - ftbit.width = width * hmul;
514 - ftbit.rows = height * vmul;
515 - ftbit.pitch = pitch;
516 - if (font->info.antialias)
517 - ftbit.pixel_mode = ft_pixel_mode_grays;
519 - ftbit.pixel_mode = ft_pixel_mode_mono;
521 - ftbit.buffer = bufBitmap;
524 - FT_Outline_Transform (&glyphslot->outline, &matrix);
525 + // compute the size of the final bitmap
526 + ftbit = &glyphslot->bitmap;
528 - FT_Outline_Translate ( &glyphslot->outline, -left*hmul, -bottom*vmul );
530 - FT_Outline_Get_Bitmap( _XftFTlibrary, &glyphslot->outline, &ftbit );
532 - case ft_glyph_format_bitmap:
533 - if (font->info.antialias)
535 - unsigned char *srcLine, *dstLine;
540 - srcLine = glyphslot->bitmap.buffer;
541 - dstLine = bufBitmap;
542 - height = glyphslot->bitmap.rows;
545 - for (x = 0; x < glyphslot->bitmap.width; x++)
547 - /* always MSB bitmaps */
548 - unsigned char a = ((srcLine[x >> 3] & (0x80 >> (x & 7))) ?
552 - for (v = 0; v < vmul; v++)
553 - for (h = 0; h < hmul; h++)
554 - dstLine[v * pitch + x*hmul + h] = a;
559 - dstLine += pitch * vmul;
560 - srcLine += glyphslot->bitmap.pitch;
565 - unsigned char *srcLine, *dstLine;
568 - srcLine = glyphslot->bitmap.buffer;
569 - dstLine = bufBitmap;
570 - h = glyphslot->bitmap.rows;
571 - bytes = (glyphslot->bitmap.width + 7) >> 3;
574 - memcpy (dstLine, srcLine, bytes);
576 - srcLine += glyphslot->bitmap.pitch;
581 - if (XftDebug() & XFT_DBG_GLYPH)
582 - printf ("glyph %d is not in a usable format\n",
586 + width = ftbit->width;
587 + height = ftbit->rows;
588 + pitch = (width+3) & ~3;
590 if (XftDebug() & XFT_DBG_GLYPH)
592 @@ -423,29 +602,72 @@
597 - for (y = 0; y < height * vmul; y++)
598 + line = ftbit->buffer;
600 + if (ftbit->pitch < 0)
601 + line -= ftbit->pitch*(height-1);
603 + for (y = 0; y < height; y++)
605 if (font->info.antialias)
607 - static char den[] = { " .:;=+*#" };
608 - for (x = 0; x < pitch; x++)
609 + static const char den[] = { " .:;=+*#" };
610 + for (x = 0; x < width; x++)
611 printf ("%c", den[line[x] >> 5]);
615 - for (x = 0; x < pitch * 8; x++)
616 + for (x = 0; x < width * 8; x++)
618 printf ("%c", line[x>>3] & (1 << (x & 7)) ? '#' : ' ');
623 + line += ftbit->pitch;
629 + size = _compute_xrender_bitmap_size( &local, glyphslot, mode );
633 + xftg->metrics.width = local.width;
634 + xftg->metrics.height = local.rows;
635 + xftg->metrics.x = - glyphslot->bitmap_left;
636 + xftg->metrics.y = glyphslot->bitmap_top;
639 + * If the glyph is relatively large (> 1% of server memory),
640 + * don't send it until necessary
642 + if (!need_bitmaps && size > info->max_glyph_memory / 100)
646 + * Make sure there's enough buffer space for the glyph
648 + if (size > bufSize)
650 + if (bufBitmap != bufLocal)
652 + bufBitmap = (unsigned char *) malloc (size);
657 + memset (bufBitmap, 0, size);
659 + local.buffer = bufBitmap;
661 + _fill_xrender_bitmap( &local, glyphslot, mode,
662 + (font->info.rgba == FC_RGBA_BGR ||
663 + font->info.rgba == FC_RGBA_VBGR ) );
665 + * Copy or convert into local buffer
669 * Use the glyph index as the wire encoding; it
670 * might be more efficient for some locales to map
671 @@ -455,121 +677,23 @@
673 glyph = (Glyph) glyphindex;
678 - unsigned char *in_line, *out_line, *in;
680 - unsigned int red, green, blue;
686 - * Filter the glyph to soften the color fringes
689 - pitchrgba = (widthrgba * 4 + 3) & ~3;
690 - sizergba = pitchrgba * height;
693 - switch (font->info.rgba) {
710 - if (sizergba > bufSizeRgba)
712 - if (bufBitmapRgba != bufLocalRgba)
713 - free (bufBitmapRgba);
714 - bufBitmapRgba = (unsigned char *) malloc (sizergba);
715 - if (!bufBitmapRgba)
717 - bufSizeRgba = sizergba;
719 - memset (bufBitmapRgba, 0, sizergba);
720 - in_line = bufBitmap;
721 - out_line = bufBitmapRgba;
722 - for (y = 0; y < height; y++)
725 - out = (unsigned int *) out_line;
726 - in_line += pitch * vmul;
727 - out_line += pitchrgba;
728 - for (x = 0; x < width * hmul; x += hmul)
730 - red = green = blue = 0;
732 - for (s = 0; s < 3; s++)
734 - red += filters[rf][s]*in[x+o];
735 - green += filters[gf][s]*in[x+o];
736 - blue += filters[bf][s]*in[x+o];
740 - green = green / 65536;
741 - blue = blue / 65536;
742 - *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
746 - xftg->glyph_memory = sizergba + sizeof (XftGlyph);
748 + xftg->glyph_memory = size + sizeof (XftGlyph);
752 font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
753 - if (ImageByteOrder (dpy) != XftNativeByteOrder ())
754 - XftSwapCARD32 ((CARD32 *) bufBitmapRgba, sizergba >> 2);
755 - XRenderAddGlyphs (dpy, font->glyphset, &glyph,
757 - (char *) bufBitmapRgba, sizergba);
763 - xftg->bitmap = malloc (sizergba);
765 - memcpy (xftg->bitmap, bufBitmapRgba, sizergba);
768 - xftg->bitmap = NULL;
773 - xftg->glyph_memory = size + sizeof (XftGlyph);
777 - * swap bit order around; FreeType is always MSBFirst
779 - if (!font->info.antialias)
780 + if ( mode == FT_RENDER_MODE_MONO )
782 + /* swap bits in each byte */
783 if (BitmapBitOrder (dpy) != MSBFirst)
785 - unsigned char *line;
788 + unsigned char *line = (unsigned char*)bufBitmap;
791 - line = (unsigned char *) bufBitmap;
798 c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55);
799 c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33);
800 c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f);
805 - if (!font->glyphset)
806 - font->glyphset = XRenderCreateGlyphSet (dpy, font->format);
807 + else if ( mode != FT_RENDER_MODE_NORMAL )
809 + /* invert ARGB <=> BGRA */
810 + if (ImageByteOrder (dpy) != XftNativeByteOrder ())
811 + XftSwapCARD32 ((CARD32 *) bufBitmap, size >> 2);
813 XRenderAddGlyphs (dpy, font->glyphset, &glyph,
815 (char *) bufBitmap, size);
822 font->glyph_memory += xftg->glyph_memory;
823 info->glyph_memory += xftg->glyph_memory;
824 if (XftDebug() & XFT_DBG_CACHE)
827 if (bufBitmap != bufLocal)
829 - if (bufBitmapRgba != bufLocalRgba)
830 - free (bufBitmapRgba);
831 XftUnlockFace (&font->public);
837 FcBool antialias; /* doing antialiasing */
838 FcBool embolden; /* force emboldening */
839 int rgba; /* subpixel order */
840 + int lcd_filter; /* lcd filter */
841 FT_Matrix matrix; /* glyph transformation matrix */
842 FcBool transform; /* non-identify matrix? */
843 FT_Int load_flags; /* glyph load flags */