diff options
author | Tor Lillqvist <tml@iki.fi> | 2000-08-20 08:36:41 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2000-08-20 08:36:41 +0000 |
commit | 79546feb86a232b0d3e01b1f436e258aef32b840 (patch) | |
tree | d35f417b2a3112bb3e0fb18d4fc057a37ab79f40 | |
parent | e95590dd006740ab6bdcf71cae31efbf8404033e (diff) | |
download | pango-79546feb86a232b0d3e01b1f436e258aef32b840.tar.gz |
Add parameter telling whether to print warning or not if string isn't
2000-08-20 Tor Lillqvist <tml@iki.fi>
* pango/pango-utils.c (pango_parse_*): Add parameter telling
whether to print warning or not if string isn't recognised. Use
g_strncasecmp().
* pango/pango-utils.h: Change prototype accordingly.
* pango/pangox-fontmap.c
* pango/pangowin32-fontmap.c: Change calls correspondingly.
* pango/pangowin32.h:
* pango/pangowin32.c: Cosmetic changes, dead code removal.
* pango/pangoft2.h
* pango/pangoft2-private.h
* pango/pangoft2.c
* pango/pangoft2-fontmap.c
* pango/pangoft2-fontcache.c: New files implementing a FreeType2
backend. Used only on Win32 so far, but doesn't contain
Win32-specific code per se, so if somebody wants to try it out on
X11, too, be my guest.
It works, more or less, but there are some details still to sort
out. Performance needs to be improved. Debugging printouts still
present. Font path currently hardcoded to C:\windows\fonts, heh.
Owen says he doesn't think it's a good idea to use ths on Win32,
but I'll try anyway. If it turns out using the native Win32 GDI
backend is better after all, oh well.
* pango/makefile.mingw: Delete. Move contents to
makefile.mingw.in.
* pango/makefile.mingw.in: New file. Add rules for
FreeType2 backend. Add FreeType2 CFLAGS and LIBS.
* pango/Makefile.am: Generate makefile.mingw.
(EXTRA_DIST): Add FreeType2 backend sources, and
makefile.mingw{,.in}
* modules/basic/basic-win32.c: Couple of cosmetic changes.
* modules/basic/Makefile.am: Generate makefile.mingw.
(EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in}
* modules/basic/makefile.mingw: Delete. Move contents to
makefile.mingw.in.
* modules/basic/makefile.mingw.in: New file. Add rule for
basic-ft2. Add FreeType2 CFLAGS and LIBS.
* examples/viewer-win32.c (read_file): Fix error messages.
(draw): Get HDC from GDK once for all paragraphs.
* examples/viewer-ft2.c: New file. The FT_Bitmap (256-level
bitmap) produced by the FreeType2 backend is copied to the
GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes,
this is kinda circular dependency between Pango and GTK+.
* examples/makefile.mingw: Delete. Move contents to
makefile.mingw.in.
* examples/makefile.mingw.in: New file. Add rules for
viewer-ft2. Add FreeType2 CFLAGS and LIBS.
* examples/Makefile.am: Generate makefile.mingw.
(EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and
makefile.mingw{,.in}
30 files changed, 4634 insertions, 257 deletions
@@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-0 b/ChangeLog.pre-1-0 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-0 +++ b/ChangeLog.pre-1-0 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-2 +++ b/ChangeLog.pre-1-2 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-4 +++ b/ChangeLog.pre-1-4 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index 467d701b..6161d83d 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,3 +1,73 @@ +2000-08-20 Tor Lillqvist <tml@iki.fi> + + * pango/pango-utils.c (pango_parse_*): Add parameter telling + whether to print warning or not if string isn't recognised. Use + g_strncasecmp(). + + * pango/pango-utils.h: Change prototype accordingly. + + * pango/pangox-fontmap.c + * pango/pangowin32-fontmap.c: Change calls correspondingly. + + * pango/pangowin32.h: + * pango/pangowin32.c: Cosmetic changes, dead code removal. + + * pango/pangoft2.h + * pango/pangoft2-private.h + * pango/pangoft2.c + * pango/pangoft2-fontmap.c + * pango/pangoft2-fontcache.c: New files implementing a FreeType2 + backend. Used only on Win32 so far, but doesn't contain + Win32-specific code per se, so if somebody wants to try it out on + X11, too, be my guest. + + It works, more or less, but there are some details still to sort + out. Performance needs to be improved. Debugging printouts still + present. Font path currently hardcoded to C:\windows\fonts, heh. + + Owen says he doesn't think it's a good idea to use ths on Win32, + but I'll try anyway. If it turns out using the native Win32 GDI + backend is better after all, oh well. + + * pango/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * pango/makefile.mingw.in: New file. Add rules for + FreeType2 backend. Add FreeType2 CFLAGS and LIBS. + + * pango/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add FreeType2 backend sources, and + makefile.mingw{,.in} + + * modules/basic/basic-win32.c: Couple of cosmetic changes. + + * modules/basic/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add basic-ft2.c, and makefile.mingw{,.in} + + * modules/basic/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * modules/basic/makefile.mingw.in: New file. Add rule for + basic-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/viewer-win32.c (read_file): Fix error messages. + (draw): Get HDC from GDK once for all paragraphs. + + * examples/viewer-ft2.c: New file. The FT_Bitmap (256-level + bitmap) produced by the FreeType2 backend is copied to the + GtkLayout window using gdk_draw_gray_image from GdkRGB (!). Yes, + this is kinda circular dependency between Pango and GTK+. + + * examples/makefile.mingw: Delete. Move contents to + makefile.mingw.in. + + * examples/makefile.mingw.in: New file. Add rules for + viewer-ft2. Add FreeType2 CFLAGS and LIBS. + + * examples/Makefile.am: Generate makefile.mingw. + (EXTRA_DIST): Add viewer-win32.c and viewer-ft2.c, and + makefile.mingw{,.in} + 2000-08-11 Havoc Pennington <hp@redhat.com> * pangox.pc.in (Cflags): remove /usr/include diff --git a/examples/Makefile.am b/examples/Makefile.am index 225498d1..2fbdfc1e 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -34,7 +34,18 @@ pango.modules: ( cd ../modules && \ ../pango/pango-querymodules `find . -name '*.so'` > ../examples/pango.modules ) -EXTRA_DIST=HELLO.utf8 muru.utf pangox.aliases +EXTRA_DIST= \ + viewer-win32.c \ + viewer-ft2.c \ + makefile.mingw \ + makefile.mingw.in \ + HELLO.utf8 \ + muru.utf \ + pangox.aliases alias_DATA = pangox.aliases +makefile.mingw: $(top_builddir)/config.status $(top_srcdir)/examples/makefile.mingw.in + cd $(top_builddir) && CONFIG_FILES=examples/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + diff --git a/examples/makefile.mingw b/examples/makefile.mingw deleted file mode 100644 index b20101d0..00000000 --- a/examples/makefile.mingw +++ /dev/null @@ -1,22 +0,0 @@ -PANGO_VER = 0.12 - -TOP = ../.. - -include $(TOP)/build/win32/make.mingw - -OPTIMIZE = -g - -INCLUDES = -I .. -I . -DEFINES = -DEPCFLAGS = $(GTK_CFLAGS) $(GLIB_CFLAGS) - -all : \ - ../config.h \ - viewer-win32.exe - -../config.h : ../config.h.win32 - cp $< $@ - -viewer-win32.exe : viewer-win32.o - $(CC) -o $@ $< $(OPTIMIZE) -L ../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GTK_LIBS) $(GLIB_LIBS) -gdi32 - diff --git a/examples/makefile.mingw.in b/examples/makefile.mingw.in new file mode 100644 index 00000000..cc086b78 --- /dev/null +++ b/examples/makefile.mingw.in @@ -0,0 +1,31 @@ +TOP = ../.. + +include $(TOP)/build/win32/make.mingw + +# Possibly override Pango version from build/win32/module.defs +PANGO_VER = @VERSION@ + +OPTIMIZE = -g -Wall + +INCLUDES = -I .. -I . +DEFINES = +DEPCFLAGS = $(GTK_CFLAGS) $(GLIB_CFLAGS) $(FREETYPE2_CFLAGS) + +all : \ + ../config.h \ + viewer-win32.exe \ + viewer-ft2.exe \ + +../config.h : ../config.h.win32 + cp $< $@ + +viewer-win32.exe : viewer-win32.o + $(CC) -o $@ $< $(OPTIMIZE) -L ../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GTK_LIBS) $(GLIB_LIBS) -gdi32 + +viewer-ft2.exe : viewer-ft2.o + $(CC) -mwindows -o $@ $< $(OPTIMIZE) -L ../pango -lpango-$(PANGO_VER) -lpangoft2-$(PANGO_VER) $(FREETYPE2_LIBS) $(GTK_LIBS) $(GLIB_LIBS) + +# Hack to get an updated makefile.mingw automatically after updating +# makefile.mingw.in. Only for developer use. +makefile.mingw: makefile.mingw.in + sed -e 's,@VER[S]ION@,@VERSION@,' <$< >$@ diff --git a/examples/viewer-ft2.c b/examples/viewer-ft2.c new file mode 100644 index 00000000..d5235472 --- /dev/null +++ b/examples/viewer-ft2.c @@ -0,0 +1,748 @@ +/* Pango + * viewer-ft2.c: Example program to view a UTF-8 encoding file + * using Pango to render result. + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gtk/gtk.h> +#include <gdk/gdkrgb.h> + +#include <pango/pango.h> +#include <pango/pangoft2.h> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define BUFSIZE 1024 + +typedef struct _Paragraph Paragraph; + +/* Structure representing a paragraph + */ +struct _Paragraph { + char *text; + int length; + int height; /* Height, in pixels */ + PangoLayout *layout; +}; + +GList *paragraphs; + +static PangoFontDescription font_description; +static Paragraph *highlight_para; +static int highlight_offset; + +GtkWidget *styles_combo; + +static GtkWidget *message_label; +GtkWidget *layout; + +PangoContext *context; + +static void fill_styles_combo (GtkWidget *combo); + +/* Read an entire file into a string + */ +static char * +read_file(char *name) +{ + GString *inbuf; + FILE *file; + char *text; + char buffer[BUFSIZE]; + + file = fopen (name, "r"); + if (!file) + { + fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name); + return NULL; + } + + inbuf = g_string_new (NULL); + while (1) + { + char *bp = fgets (buffer, BUFSIZE-1, file); + if (ferror (file)) + { + fprintf(stderr, "%s: Error reading %s\n", g_get_prgname (), name); + g_string_free (inbuf, TRUE); + return NULL; + } + else if (bp == NULL) + break; + + g_string_append (inbuf, buffer); + } + + fclose (file); + + text = inbuf->str; + g_string_free (inbuf, FALSE); + + return text; +} + +/* Take a UTF8 string and break it into paragraphs on \n characters + */ +static GList * +split_paragraphs (char *text) +{ + char *p = text; + char *next; + gunichar wc; + GList *result = NULL; + char *last_para = text; + + while (*p) + { + wc = g_utf8_get_char (p); + next = g_utf8_next_char (p); + if (wc == (gunichar)-1) + { + fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ()); + g_list_foreach (result, (GFunc)g_free, NULL); + return NULL; + } + if (!*p || !wc || wc == '\n') + { + Paragraph *para = g_new (Paragraph, 1); + para->text = last_para; + para->length = p - last_para; + para->layout = pango_layout_new (context); + pango_layout_set_text (para->layout, para->text, para->length); + para->height = 0; + + last_para = next; + + result = g_list_prepend (result, para); + } + if (!wc) /* incomplete character at end */ + break; + p = next; + } + + return g_list_reverse (result); +} + +/* Given an x-y position, return the paragraph and offset + * within the paragraph of the click. + */ +gboolean +xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index) +{ + GList *para_list; + int height = 0; + + *para_return = NULL; + + para_list = paragraphs; + while (para_list && height < y) + { + Paragraph *para = para_list->data; + + if (height + para->height >= y) + { + gboolean result = pango_layout_xy_to_index (para->layout, x * 1000, (y - height) * 1000, + index, NULL); + if (result && para_return) + *para_return = para; + + return result; + } + + height += para->height; + para_list = para_list->next; + } + + return FALSE; +} + +/* Given a paragraph and offset in that paragraph, find the + * bounding rectangle for the character at the offset. + */ +void +char_bounds (Paragraph *para, int index, int width, PangoRectangle *rect) +{ + GList *para_list; + + int height = 0; + + para_list = paragraphs; + while (para_list) + { + Paragraph *cur_para = para_list->data; + + if (cur_para == para) + { + PangoRectangle pos; + + pango_layout_index_to_pos (cur_para->layout, index, &pos); + + rect->x = MIN (pos.x, pos.x + pos.width) / 1000; + rect->width = ABS (pos.width) / 1000; + rect->y = height + pos.y / 1000; + rect->height = pos.height / 1000; + } + + height += cur_para->height; + para_list = para_list->next; + } +} + +/* XOR a rectangle over a given character + */ +void +xor_char (GtkWidget *layout, GdkRectangle *clip_rect, + Paragraph *para, int offset) +{ + static GdkGC *gc; + PangoRectangle rect; /* GdkRectangle in 1.2 is too limited + */ + if (!gc) + { + GdkGCValues values; + values.foreground = layout->style->white.pixel ? + layout->style->white : layout->style->black; + values.function = GDK_XOR; + gc = gdk_gc_new_with_values (GTK_LAYOUT (layout)->bin_window, + &values, + GDK_GC_FOREGROUND | GDK_GC_FUNCTION); + } + + gdk_gc_set_clip_rectangle (gc, clip_rect); + + char_bounds (para, offset, layout->allocation.width, &rect); + + rect.y -= GTK_LAYOUT (layout)->yoffset; + + if ((rect.y + rect.height >= 0) && (rect.y < layout->allocation.height)) + gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, gc, TRUE, + rect.x, rect.y, rect.width, rect.height); +} + +/* Handle a size allocation by re-laying-out each paragraph to + * the new width, setting the new size for the layout and + * then queing a redraw + */ +void +size_allocate (GtkWidget *layout, GtkAllocation *allocation) +{ + GList *tmp_list; + int height = 0; + PangoDirection base_dir = pango_context_get_base_dir (context); + + tmp_list = paragraphs; + while (tmp_list) + { + Paragraph *para = tmp_list->data; + PangoRectangle logical_rect; + + tmp_list = tmp_list->next; + + pango_layout_set_alignment (para->layout, + base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); + pango_layout_set_width (para->layout, layout->allocation.width * 1000); + + pango_layout_get_extents (para->layout, NULL, &logical_rect); + para->height = logical_rect.height / 1000; + + height += para->height; + } + + gtk_layout_set_size (GTK_LAYOUT (layout), allocation->width, height); + + if (GTK_LAYOUT (layout)->yoffset + allocation->height > height) + gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, height - allocation->height); +} + +/* Handle a draw/expose by finding the paragraphs that intersect + * the region and reexposing them. + */ +void +draw (GtkWidget *layout, GdkRectangle *area) +{ + GList *tmp_list; + int height = 0; + GdkVisual *visual = gdk_drawable_get_visual (GTK_LAYOUT (layout)->bin_window); + + g_assert (visual->type == GDK_VISUAL_GRAYSCALE || + visual->type == GDK_VISUAL_TRUE_COLOR); + + gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, + layout->style->base_gc[layout->state], + TRUE, + area->x, area->y, + area->width, area->height); + + gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area); +#if 0 + g_print ("viewer-ft2.c: draw: area: %dx%d, x:%d y:%d layout->yoffset:%d\n", area->width, area->height, area->x, area->y, GTK_LAYOUT (layout)->yoffset); +#endif + tmp_list = paragraphs; + while (tmp_list && + height < area->y + area->height + GTK_LAYOUT (layout)->yoffset) + { + Paragraph *para = tmp_list->data; + tmp_list = tmp_list->next; +#if 0 + g_print (" para->height:%d\n", para->height); +#endif + if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y) + { + FT_Bitmap bitmap; + guchar *buf = g_malloc (area->width * para->height); + + memset (buf, 0xFF, area->width * para->height); + bitmap.rows = para->height; + bitmap.width = area->width; + bitmap.pitch = bitmap.width; + bitmap.buffer = buf; + bitmap.num_grays = 256; + bitmap.pixel_mode = ft_pixel_mode_grays; + + pango_ft2_render_layout (&bitmap, para->layout, + 0, 0); + + gdk_draw_gray_image (GTK_LAYOUT (layout)->bin_window, + layout->style->text_gc[GTK_STATE_NORMAL], + 0, height - GTK_LAYOUT (layout)->yoffset, + bitmap.width, bitmap.rows, + GDK_RGB_DITHER_NORMAL, + bitmap.buffer, + bitmap.pitch); + g_free (buf); + } + + height += para->height; + } + + gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL); + + if (highlight_para) + xor_char (layout, area, highlight_para, highlight_offset); +} + +gboolean +expose (GtkWidget *layout, GdkEventExpose *event) +{ + if (event->window == GTK_LAYOUT (layout)->bin_window) + draw (layout, &event->area); + + return TRUE; +} + +void +button_press (GtkWidget *layout, GdkEventButton *event) +{ + Paragraph *para = NULL; + int offset; + gchar *message; + + xy_to_cp (layout->allocation.width, + event->x, event->y + GTK_LAYOUT (layout)->yoffset, + ¶, &offset); + + if (highlight_para) + xor_char (layout, NULL, highlight_para, highlight_offset); + + highlight_para = para; + highlight_offset = offset; + + if (para) + { + gunichar wc; + + wc = g_utf8_get_char (para->text + offset); + message = g_strdup_printf ("Current char: U%04x", wc); + + xor_char (layout, NULL, highlight_para, highlight_offset); + } + else + message = g_strdup_printf ("Current char:"); + + gtk_label_set_text (GTK_LABEL (message_label), message); + g_free (message); +} + +static void +checkbutton_toggled (GtkWidget *widget, gpointer data) +{ + GList *para_list; + + pango_context_set_base_dir (context, GTK_TOGGLE_BUTTON (widget)->active ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); + + para_list = paragraphs; + while (para_list) + { + Paragraph *para = para_list->data; + + pango_layout_context_changed (para->layout); + para_list = para_list->next; + } + + gtk_widget_queue_resize (layout); +} + +static void +reload_font () +{ + GList *para_list; + + pango_context_set_font_description (context, &font_description); + + para_list = paragraphs; + while (para_list) + { + Paragraph *para = para_list->data; + + pango_layout_context_changed (para->layout); + para_list = para_list->next; + } + + if (layout) + gtk_widget_queue_resize (layout); +} + +void +set_family (GtkWidget *entry, gpointer data) +{ + font_description.family_name = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); + fill_styles_combo (styles_combo); +} + +void +set_style (GtkWidget *entry, gpointer data) +{ + char *str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); + PangoFontDescription *tmp_desc; + + tmp_desc = pango_font_description_from_string (str); + + font_description.style = tmp_desc->style; + font_description.variant = tmp_desc->variant; + font_description.weight = tmp_desc->weight; + font_description.stretch = tmp_desc->stretch; + + pango_font_description_free (tmp_desc); + g_free (str); + + reload_font (); +} + +void +font_size_changed (GtkAdjustment *adj) +{ + font_description.size = (int)(adj->value * PANGO_SCALE + 0.5); + reload_font(); +} + +static int +compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b) +{ + int val = strcmp (a->family_name, b->family_name); + if (val != 0) + return val; + + if (a->weight != b->weight) + return a->weight - b->weight; + + if (a->style != b->style) + return a->style - b->style; + + if (a->stretch != b->stretch) + return a->stretch - b->stretch; + + if (a->variant != b->variant) + return a->variant - b->variant; + + return 0; +} + +static int +font_description_sort_func (const void *a, const void *b) +{ + return compare_font_descriptions (*(PangoFontDescription **)a, *(PangoFontDescription **)b); +} + +typedef struct +{ + PangoFontDescription **descs; + int n_descs; +} FontDescInfo; + +static void +free_info (FontDescInfo *info) +{ + pango_font_descriptions_free (info->descs, info->n_descs); +} + +static void +fill_styles_combo (GtkWidget *combo) +{ + int i; + GList *style_list = NULL; + + FontDescInfo *info = g_new (FontDescInfo, 1); + pango_context_list_fonts (context, font_description.family_name, &info->descs, &info->n_descs); + gtk_object_set_data_full (GTK_OBJECT (combo), "descs", info, (GtkDestroyNotify)free_info); + + qsort (info->descs, info->n_descs, sizeof(PangoFontDescription *), font_description_sort_func); + + for (i=0; i<info->n_descs; i++) + { + char *str; + + PangoFontDescription tmp_desc; + + tmp_desc = *info->descs[i]; + tmp_desc.family_name = NULL; + tmp_desc.size = 0; + + str = pango_font_description_to_string (&tmp_desc); + style_list = g_list_prepend (style_list, str); + } + + style_list = g_list_reverse (style_list); + + gtk_combo_set_popdown_strings (GTK_COMBO (combo), style_list); + g_list_foreach (style_list, (GFunc)g_free, NULL); +} + +static GtkWidget * +make_styles_combo () +{ + GtkWidget *combo; + + combo = gtk_combo_new (); + gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE); + gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE); + + gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed", + GTK_SIGNAL_FUNC (set_style), NULL); + + styles_combo = combo; + fill_styles_combo (combo); + + return combo; +} + +static int +cmp_strings (const void *a, const void *b) +{ + return strcmp (*(const char **)a, *(const char **)b); +} + +GtkWidget * +make_families_menu () +{ + GtkWidget *combo; + gchar **families; + int n_families; + GList *family_list = NULL; + int i; + + pango_context_list_families (context, &families, &n_families); + qsort (families, n_families, sizeof(char *), cmp_strings); + + for (i=0; i<n_families; i++) + family_list = g_list_prepend (family_list, families[i]); + + family_list = g_list_reverse (family_list); + + combo = gtk_combo_new (); + gtk_combo_set_popdown_strings (GTK_COMBO (combo), family_list); + gtk_combo_set_value_in_list (GTK_COMBO (combo), TRUE, FALSE); + gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (combo)->entry), FALSE); + + gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), font_description.family_name); + + gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->entry), "changed", + GTK_SIGNAL_FUNC (set_family), NULL); + + g_list_free (family_list); + pango_font_map_free_families (families, n_families); + + return combo; +} + + +GtkWidget * +make_font_selector (void) +{ + GtkWidget *hbox; + GtkWidget *util_hbox; + GtkWidget *label; + GtkWidget *option_menu; + GtkWidget *spin_button; + GtkAdjustment *adj; + + hbox = gtk_hbox_new (FALSE, 4); + + util_hbox = gtk_hbox_new (FALSE, 2); + label = gtk_label_new ("Family:"); + gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); + option_menu = make_families_menu (); + gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); + + util_hbox = gtk_hbox_new (FALSE, 2); + label = gtk_label_new ("Style:"); + gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); + option_menu = make_styles_combo (); + gtk_box_pack_start (GTK_BOX (util_hbox), option_menu, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); + + util_hbox = gtk_hbox_new (FALSE, 2); + label = gtk_label_new ("Size:"); + gtk_box_pack_start (GTK_BOX (util_hbox), label, FALSE, FALSE, 0); + spin_button = gtk_spin_button_new (NULL, 1., 0); + gtk_box_pack_start (GTK_BOX (util_hbox), spin_button, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), util_hbox, FALSE, FALSE, 0); + + adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (spin_button)); + adj->value = font_description.size / 1000.; + adj->lower = 0; + adj->upper = 1024; + adj->step_increment = 1; + adj->page_size = 10; + gtk_adjustment_changed (adj); + gtk_adjustment_value_changed (adj); + + gtk_signal_connect (GTK_OBJECT (adj), "value_changed", + GTK_SIGNAL_FUNC (font_size_changed), NULL); + + return hbox; +} + +int +main (int argc, char **argv) +{ + char *text; + GtkWidget *window; + GtkWidget *scrollwin; + GtkWidget *vbox, *hbox; + GtkWidget *frame; + GtkWidget *checkbutton; + + gtk_init (&argc, &argv); + + gdk_rgb_init (); + +#if 0 + if (argc != 2) + { + fprintf (stderr, "Usage: %s FILE\n", g_get_prgname ()); + exit(1); + } + + /* Create the list of paragraphs from the supplied file + */ + text = read_file (argv[1]); +#else + text = read_file ("koe2.txt"); +#endif + if (!text) + exit(1); + + context = pango_ft2_get_context (); + + paragraphs = split_paragraphs (text); + + pango_context_set_lang (context, "en_US"); + pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); + + font_description.family_name = g_strdup ("sans"); + font_description.style = PANGO_STYLE_NORMAL; + font_description.variant = PANGO_VARIANT_NORMAL; + font_description.weight = PANGO_WEIGHT_NORMAL; + font_description.stretch = PANGO_STRETCH_NORMAL; + font_description.size = 24000; + + pango_context_set_font_description (context, &font_description); + + /* Create the user interface + */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 400, 400); + + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (gtk_main_quit), NULL); + + vbox = gtk_vbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (window), vbox); + + hbox = make_font_selector (); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + scrollwin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0); + + layout = gtk_layout_new (NULL, NULL); + gtk_widget_set_events (layout, GDK_BUTTON_PRESS_MASK); + gtk_widget_set_app_paintable (layout, TRUE); + + gtk_signal_connect (GTK_OBJECT (layout), "size_allocate", + GTK_SIGNAL_FUNC (size_allocate), paragraphs); + gtk_signal_connect (GTK_OBJECT (layout), "expose_event", + GTK_SIGNAL_FUNC (expose), paragraphs); + gtk_signal_connect (GTK_OBJECT (layout), "draw", + GTK_SIGNAL_FUNC (draw), paragraphs); + gtk_signal_connect (GTK_OBJECT (layout), "button_press_event", + GTK_SIGNAL_FUNC (button_press), paragraphs); + + gtk_container_add (GTK_CONTAINER (scrollwin), layout); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + + message_label = gtk_label_new ("Current char:"); + gtk_misc_set_padding (GTK_MISC (message_label), 1, 1); + gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5); + gtk_container_add (GTK_CONTAINER (frame), message_label); + + checkbutton = gtk_check_button_new_with_label ("Use RTL global direction"); + gtk_signal_connect (GTK_OBJECT (checkbutton), "toggled", + GTK_SIGNAL_FUNC (checkbutton_toggled), NULL); + gtk_box_pack_start (GTK_BOX (vbox), checkbutton, FALSE, FALSE, 0); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} + +int _stdcall +WinMain (struct HINSTANCE__ *hInstance, + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) +{ + return main (__argc, __argv); +} + diff --git a/examples/viewer-win32.c b/examples/viewer-win32.c index 969b6e9b..62086513 100644 --- a/examples/viewer-win32.c +++ b/examples/viewer-win32.c @@ -72,7 +72,7 @@ read_file(char *name) file = fopen (name, "r"); if (!file) { - fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname ()); + fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name); return NULL; } @@ -82,7 +82,7 @@ read_file(char *name) char *bp = fgets (buffer, BUFSIZE-1, file); if (ferror (file)) { - fprintf(stderr, "%s: Error reading %s\n", g_get_prgname ()); + fprintf (stderr, "%s: Error reading %s\n", g_get_prgname (), name); g_string_free (inbuf, TRUE); return NULL; } @@ -281,6 +281,8 @@ draw (GtkWidget *layout, GdkRectangle *area) { GList *tmp_list; int height = 0; + HDC hdc; + const GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND|GDK_GC_FONT; gdk_draw_rectangle (GTK_LAYOUT (layout)->bin_window, layout->style->base_gc[layout->state], @@ -290,6 +292,9 @@ draw (GtkWidget *layout, GdkRectangle *area) gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], area); + hdc = gdk_win32_hdc_get (GTK_LAYOUT (layout)->bin_window, + layout->style->text_gc[GTK_STATE_NORMAL], + mask); tmp_list = paragraphs; while (tmp_list && height < area->y + area->height + GTK_LAYOUT (layout)->yoffset) @@ -298,23 +303,14 @@ draw (GtkWidget *layout, GdkRectangle *area) tmp_list = tmp_list->next; if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y) - { - GdkGCValuesMask mask = GDK_GC_FOREGROUND|GDK_GC_BACKGROUND|GDK_GC_FONT; - HDC hdc; - - hdc = gdk_win32_hdc_get (GTK_LAYOUT (layout)->bin_window, - layout->style->text_gc[GTK_STATE_NORMAL], - mask); - pango_win32_render_layout (hdc, para->layout, - 0, height - GTK_LAYOUT (layout)->yoffset); - gdk_win32_hdc_release (GTK_LAYOUT (layout)->bin_window, - layout->style->text_gc[GTK_STATE_NORMAL], - mask); - } - + pango_win32_render_layout (hdc, para->layout, + 0, height - GTK_LAYOUT (layout)->yoffset); height += para->height; } + gdk_win32_hdc_release (GTK_LAYOUT (layout)->bin_window, + layout->style->text_gc[GTK_STATE_NORMAL], + mask); gdk_gc_set_clip_rectangle (layout->style->text_gc[layout->state], NULL); if (highlight_para) diff --git a/modules/basic/Makefile.am b/modules/basic/Makefile.am index db21f28c..4ccb4869 100644 --- a/modules/basic/Makefile.am +++ b/modules/basic/Makefile.am @@ -21,4 +21,10 @@ libpango_basic_la_SOURCES = $(sources) EXTRA_DIST = \ tables-big.i \ tables-small.i \ - basic-win32.c + basic-win32.c \ + basic-ft2.c \ + makefile.mingw \ + makefile.mingw.in + +makefile.mingw: $(top_builddir)/config.status $(top_srcdir)/modules/basic/makefile.mingw.in + cd $(top_builddir) && CONFIG_FILES=modules/basic/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/modules/basic/basic-ft2.c b/modules/basic/basic-ft2.c new file mode 100644 index 00000000..086ba420 --- /dev/null +++ b/modules/basic/basic-ft2.c @@ -0,0 +1,320 @@ +/* Pango + * basic-ft2.c: + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <glib.h> + +#include "pango.h" +#include "pangoft2.h" + +#include <fribidi/fribidi.h> + +static PangoEngineRange basic_ranges[] = { + /* Language characters */ + { 0x0000, 0x02af, "*" }, + { 0x02b0, 0x02ff, "" }, + { 0x0380, 0x058f, "*" }, + { 0x0591, 0x05f4, "*" }, /* Hebrew */ + { 0x060c, 0x06f9, "" }, /* Arabic */ + { 0x0e01, 0x0e5b, "" }, /* Thai */ + { 0x1e00, 0x1fff, "*" }, + { 0x2000, 0x9fff, "*" }, + { 0xac00, 0xd7a3, "kr" }, + { 0xf900, 0xfa0b, "kr" }, + { 0xff00, 0xffe3, "*" } +}; + +static PangoEngineInfo script_engines[] = { + { + "BasicScriptEngineLang", + PANGO_ENGINE_TYPE_LANG, + PANGO_RENDER_TYPE_NONE, + basic_ranges, G_N_ELEMENTS(basic_ranges) + }, + { + "BasicScriptEngineFT2", + PANGO_ENGINE_TYPE_SHAPE, + PANGO_RENDER_TYPE_FT2, + basic_ranges, G_N_ELEMENTS(basic_ranges) + } +}; + +static gint n_script_engines = G_N_ELEMENTS (script_engines); + +/* + * Language script engine + */ + +static void +basic_engine_break (const char *text, + gint len, + PangoAnalysis *analysis, + PangoLogAttr *attrs) +{ +} + +static PangoEngine * +basic_engine_lang_new (void) +{ + PangoEngineLang *result; + + result = g_new (PangoEngineLang, 1); + + result->engine.id = "BasicScriptEngine"; + result->engine.type = PANGO_ENGINE_TYPE_LANG; + result->engine.length = sizeof (result); + result->script_break = basic_engine_break; + + return (PangoEngine *)result; +} + +/* + * FT2 system script engine portion + */ + +static PangoGlyph +find_char (PangoFont *font, + gunichar wc) +{ + int i; + int n_subfonts; + + n_subfonts = pango_ft2_n_subfonts (font); + + for (i = 0; i < n_subfonts; i++) + { + PangoGlyph glyph; + + glyph = PANGO_FT2_MAKE_GLYPH (i+1, wc); + + if (pango_ft2_has_glyph (font, glyph)) + return glyph; + } + + return 0; +} + +static void +set_glyph (PangoFont *font, + PangoGlyphString *glyphs, + int i, + int offset, + PangoGlyph glyph) +{ + PangoRectangle logical_rect; + + glyphs->glyphs[i].glyph = glyph; + + glyphs->glyphs[i].geometry.x_offset = 0; + glyphs->glyphs[i].geometry.y_offset = 0; + + glyphs->log_clusters[i] = offset; + + pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect); + glyphs->glyphs[i].geometry.width = logical_rect.width; + + if (i > 0) + { + glyphs->glyphs[i-1].geometry.width += + pango_ft2_font_get_kerning (font, + glyphs->glyphs[i-1].glyph, + glyphs->glyphs[i].glyph); + } +} + +static void +swap_range (PangoGlyphString *glyphs, + int start, + int end) +{ + int i, j; + + for (i = start, j = end - 1; i < j; i++, j--) + { + PangoGlyphInfo glyph_info; + gint log_cluster; + + glyph_info = glyphs->glyphs[i]; + glyphs->glyphs[i] = glyphs->glyphs[j]; + glyphs->glyphs[j] = glyph_info; + + log_cluster = glyphs->log_clusters[i]; + glyphs->log_clusters[i] = glyphs->log_clusters[j]; + glyphs->log_clusters[j] = log_cluster; + } +} + +static void +basic_engine_shape (PangoFont *font, + const char *text, + gint length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs) +{ + int n_chars; + int i; + const char *p; + + g_return_if_fail (font != NULL); + g_return_if_fail (text != NULL); + g_return_if_fail (length >= 0); + g_return_if_fail (analysis != NULL); + + n_chars = g_utf8_strlen (text, length); + pango_glyph_string_set_size (glyphs, n_chars); + + p = text; + for (i = 0; i < n_chars; i++) + { + gunichar wc; + FriBidiChar mirrored_ch; + PangoGlyph index; + + wc = g_utf8_get_char (p); + + if (analysis->level % 2) + if (fribidi_get_mirror_char (wc, &mirrored_ch)) + wc = mirrored_ch; + + if (wc == 0x200B || wc == 0x200E || wc == 0x200F) /* Zero-width characters */ + { + set_glyph (font, glyphs, i, p - text, 0); + } + else + { + index = find_char (font, wc); + if (index) + { + set_glyph (font, glyphs, i, p - text, index); + + if (g_unichar_type (wc) == G_UNICODE_NON_SPACING_MARK) + { + if (i > 0) + { + PangoRectangle logical_rect, ink_rect; + + glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width, + glyphs->glyphs[i].geometry.width); + glyphs->glyphs[i-1].geometry.width = 0; + glyphs->log_clusters[i] = glyphs->log_clusters[i-1]; + + /* Some heuristics to try to guess how overstrike glyphs are + * done and compensate + */ + pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, &ink_rect, &logical_rect); + if (logical_rect.width == 0 && ink_rect.x == 0) + glyphs->glyphs[i].geometry.x_offset = (glyphs->glyphs[i].geometry.width - ink_rect.width) / 2; + } + } + } + else + set_glyph (font, glyphs, i, p - text, pango_ft2_get_unknown_glyph (font)); + } + + p = g_utf8_next_char (p); + } + + /* Simple bidi support... may have separate modules later */ + + if (analysis->level % 2) + { + int start, end; + + /* Swap all glyphs */ + swap_range (glyphs, 0, n_chars); + + /* Now reorder glyphs within each cluster back to LTR */ + for (start = 0; start < n_chars;) + { + end = start; + while (end < n_chars && + glyphs->log_clusters[end] == glyphs->log_clusters[start]) + end++; + + swap_range (glyphs, start, end); + start = end; + } + } +} + +static PangoCoverage * +basic_engine_get_coverage (PangoFont *font, + const char *lang) +{ + PangoCoverage *result = pango_coverage_new (); + gunichar wc; + + for (wc = 0; wc < 65536; wc++) + if (find_char (font, wc)) + pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT); + + return result; +} + +static PangoEngine * +basic_engine_ft2_new (void) +{ + PangoEngineShape *result; + + result = g_new (PangoEngineShape, 1); + + result->engine.id = "BasicScriptEngine"; + result->engine.type = PANGO_ENGINE_TYPE_LANG; + result->engine.length = sizeof (result); + result->script_shape = basic_engine_shape; + result->get_coverage = basic_engine_get_coverage; + + return (PangoEngine *)result; +} + +/* The following three functions provide the public module API for + * Pango + */ +#ifdef MODULE_PREFIX +#define MODULE_ENTRY(func) _pango_basic_##func +#else +#define MODULE_ENTRY(func) func +#endif + +void +MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, + gint *n_engines) +{ + *engines = script_engines; + *n_engines = n_script_engines; +} + +PangoEngine * +MODULE_ENTRY(script_engine_load) (const char *id) +{ + g_print ("basic-ft2: LOAD\n"); + if (!strcmp (id, "BasicScriptEngineLang")) + return basic_engine_lang_new (); + else if (!strcmp (id, "BasicScriptEngineFT2")) + return basic_engine_ft2_new (); + else + return NULL; +} + +void +MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) +{ + g_print ("basic-ft2: UNLOAD\n"); +} diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c index 410fa971..ea4f6f0f 100644 --- a/modules/basic/basic-win32.c +++ b/modules/basic/basic-win32.c @@ -69,7 +69,7 @@ basic_engine_break (const char *text, } static PangoEngine * -basic_engine_lang_new () +basic_engine_lang_new (void) { PangoEngineLang *result; @@ -88,7 +88,8 @@ basic_engine_lang_new () */ static PangoGlyph -find_char (PangoFont *font, gunichar wc) +find_char (PangoFont *font, + gunichar wc) { PangoWin32UnicodeSubrange subrange; PangoWin32Subfont *subfonts; @@ -113,7 +114,11 @@ find_char (PangoFont *font, gunichar wc) } static void -set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph) +set_glyph (PangoFont *font, + PangoGlyphString *glyphs, + int i, + int offset, + PangoGlyph glyph) { PangoRectangle logical_rect; @@ -129,7 +134,9 @@ set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGl } static void -swap_range (PangoGlyphString *glyphs, int start, int end) +swap_range (PangoGlyphString *glyphs, + int start, + int end) { int i, j; @@ -256,7 +263,7 @@ basic_engine_get_coverage (PangoFont *font, } static PangoEngine * -basic_engine_win32_new () +basic_engine_win32_new (void) { PangoEngineShape *result; @@ -281,7 +288,8 @@ basic_engine_win32_new () #endif void -MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines) +MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, + gint *n_engines) { *engines = script_engines; *n_engines = n_script_engines; @@ -302,4 +310,3 @@ void MODULE_ENTRY(script_engine_unload) (PangoEngine *engine) { } - diff --git a/modules/basic/makefile.mingw b/modules/basic/makefile.mingw deleted file mode 100644 index 43d48465..00000000 --- a/modules/basic/makefile.mingw +++ /dev/null @@ -1,21 +0,0 @@ -PANGO_VER = 0.12 - -TOP = ../../.. - -include $(TOP)/build/win32/make.mingw - -OPTIMIZE = -g - -INCLUDES = -I ../../pango -I ../.. -DEFINES = -DEPCFLAGS = $(GLIB_CFLAGS) $(FRIBIDI_CFLAGS) - -all : \ - ../../config.h \ - pango-basic-win32.dll - -../../config.h : ../../config.h.win32 - cp $< $@ - -pango-basic-win32.dll : basic-win32.o - $(GLIB)/build-dll pango-basic-win32 - ../module.def $< -L ../../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) diff --git a/modules/basic/makefile.mingw.in b/modules/basic/makefile.mingw.in new file mode 100644 index 00000000..64cb1a51 --- /dev/null +++ b/modules/basic/makefile.mingw.in @@ -0,0 +1,31 @@ +TOP = ../../.. + +include $(TOP)/build/win32/make.mingw + +# Possibly override Pango version from build/win32/module.defs +PANGO_VER = @VERSION@ + +OPTIMIZE = -g -Wall + +INCLUDES = -I ../../pango -I ../.. +DEFINES = +DEPCFLAGS = $(GLIB_CFLAGS) $(FRIBIDI_CFLAGS) $(FREETYPE2_CFLAGS) + +all : \ + ../../config.h \ + pango-basic-win32.dll \ + pango-basic-ft2.dll + +../../config.h : ../../config.h.win32 + cp $< $@ + +pango-basic-win32.dll : basic-win32.o + $(GLIB)/build-dll pango-basic-win32 - ../module.def $< -L ../../pango -lpango-$(PANGO_VER) -lpangowin32-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) + +pango-basic-ft2.dll : basic-ft2.o + $(GLIB)/build-dll pango-basic-ft2 - ../module.def $< -L ../../pango -lpango-$(PANGO_VER) -lpangoft2-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) $(FREETYPE2_LIBS) + +# Hack to get an updated makefile.mingw automatically after updating +# makefile.mingw.in. Only for developer use. +makefile.mingw: makefile.mingw.in + sed -e 's,@VER[S]ION@,@VERSION@,' <$< >$@ diff --git a/pango/Makefile.am b/pango/Makefile.am index ee780e98..df653b17 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -66,10 +66,19 @@ pango_querymodules_SOURCES = \ querymodules.c pango_querymodules_LDADD = libpangox.la libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(UNICODE_LIBS) $(X_LIBS) -EXTRA_DIST = \ - pangowin32.h \ - pangowin32.c \ - pangowin32-private.h \ - pangowin32-fontcache.c \ - pangowin32-fontmap.c +EXTRA_DIST = \ + pangowin32.h \ + pangowin32.c \ + pangowin32-private.h \ + pangowin32-fontcache.c \ + pangowin32-fontmap.c \ + pangoft2.h \ + pangoft2.c \ + pangoft2-private.h \ + pangoft2-fontcache.c \ + pangoft2-fontmap.c \ + makefile.mingw \ + makefile.mingw.in +makefile.mingw: $(top_builddir)/config.status $(top_srcdir)/pango/makefile.mingw.in + cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/pango/makefile.mingw b/pango/makefile.mingw.in index dca8e55d..3bcc4beb 100644 --- a/pango/makefile.mingw +++ b/pango/makefile.mingw.in @@ -1,44 +1,51 @@ -PANGO_VER = 0.12 - TOP = ../.. include $(TOP)/build/win32/make.mingw -OPTIMIZE = -g +# Possibly override Pango version from build/win32/module.defs +PANGO_VER = @VERSION@ + +OPTIMIZE = -g -Wall INCLUDES = -I .. -I . DEFINES = -DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FRIBIDI_CFLAGS) +DEPCFLAGS = $(GLIB_CFLAGS) $(LIBICONV_CFLAGS) $(FRIBIDI_CFLAGS) $(FREETYPE2_CFLAGS) -all : \ - ../config.h \ - pango-$(PANGO_VER).dll \ - pangowin32-$(PANGO_VER).dll \ +all : \ + ../config.h \ + pango-$(PANGO_VER).dll \ + pangowin32-$(PANGO_VER).dll \ + pangoft2-$(PANGO_VER).dll \ pango-querymodules.exe -PANGO_OBJS = \ - break.o \ - fonts.o \ - glyphstring.o \ - mapping.o \ - modules.o \ - module-defs.o \ - pango-attributes.o \ - pango-context.o \ - pango-coverage.o \ - pango-fontmap.o \ - pango-item.o \ - pango-layout.o \ - pango-utils.o \ - reorder-items.o \ +PANGO_OBJS = \ + break.o \ + fonts.o \ + glyphstring.o \ + mapping.o \ + modules.o \ + module-defs.o \ + pango-attributes.o \ + pango-context.o \ + pango-coverage.o \ + pango-fontmap.o \ + pango-item.o \ + pango-layout.o \ + pango-utils.o \ + reorder-items.o \ shape.o -PANGOWIN32_OBJS = \ - pangowin32.o \ - pangowin32-fontcache.o \ +PANGOWIN32_OBJS = \ + pangowin32.o \ + pangowin32-fontcache.o \ pangowin32-fontmap.o -PANGO_QUERYMODULES_OBJS = \ +PANGOFT2_OBJS = \ + pangoft2.o \ + pangoft2-fontcache.o \ + pangoft2-fontmap.o + +PANGO_QUERYMODULES_OBJS = \ querymodules.o ../config.h : ../config.h.win32 @@ -53,7 +60,10 @@ pango-$(PANGO_VER).dll : $(PANGO_OBJS) pango.def pangowin32-$(PANGO_VER).dll : $(PANGOWIN32_OBJS) pangowin32.def $(GLIB)/build-dll pangowin32 $(PANGO_VER) pangowin32.def $(OPTIMIZE) $(PANGOWIN32_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) -lgdi32 -pango-querymodules.exe : $(PANGO_QUERYMODULES_OBJS) pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll +pangoft2-$(PANGO_VER).dll : $(PANGOFT2_OBJS) pangoft2.def + $(GLIB)/build-dll pangoft2 $(PANGO_VER) pangoft2.def $(OPTIMIZE) $(PANGOFT2_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS) $(FRIBIDI_LIBS) $(FREETYPE2_LIBS) -lgdi32 + +pango-querymodules.exe : $(PANGO_QUERYMODULES_OBJS) pango-$(PANGO_VER).dll $(CC) -o $@ $(PANGO_QUERYMODULES_OBJS) -L . -lpango-$(PANGO_VER) $(GLIB_LIBS) test1.exe : test1.o pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll @@ -71,3 +81,7 @@ test4.exe : test4.o pango-$(PANGO_VER).dll pangowin32-$(PANGO_VER).dll test5.exe : test5.o $(CC) -o $@ $(CFLAGS) test5.o -lgdi32 +# Hack to get an updated makefile.mingw automatically after updating +# makefile.mingw.in. Only for developer use. +makefile.mingw: makefile.mingw.in + sed -e 's,@VER[S]ION@,@VERSION@,' <$< >$@ diff --git a/pango/pango-utils.c b/pango/pango-utils.c index f48b197b..807adac8 100644 --- a/pango/pango-utils.c +++ b/pango/pango-utils.c @@ -657,7 +657,8 @@ pango_get_lib_subdirectory (void) gboolean pango_parse_style (GString *str, - PangoFontDescription *desc) + PangoFontDescription *desc, + gboolean warn) { if (str->len == 0) return FALSE; @@ -666,35 +667,37 @@ pango_parse_style (GString *str, { case 'n': case 'N': - if (strncasecmp (str->str, "normal", str->len) == 0) + if (g_strncasecmp (str->str, "normal", str->len) == 0) { desc->style = PANGO_STYLE_NORMAL; return TRUE; } break; case 'i': - if (strncasecmp (str->str, "italic", str->len) == 0) + if (g_strncasecmp (str->str, "italic", str->len) == 0) { desc->style = PANGO_STYLE_ITALIC; return TRUE; } break; case 'o': - if (strncasecmp (str->str, "oblique", str->len) == 0) + if (g_strncasecmp (str->str, "oblique", str->len) == 0) { desc->style = PANGO_STYLE_OBLIQUE; return TRUE; } break; } - g_warning ("Style must be normal, italic, or oblique"); + if (warn) + g_warning ("Style must be normal, italic, or oblique"); return FALSE; } gboolean pango_parse_variant (GString *str, - PangoFontDescription *desc) + PangoFontDescription *desc, + gboolean warn) { if (str->len == 0) return FALSE; @@ -703,7 +706,7 @@ pango_parse_variant (GString *str, { case 'n': case 'N': - if (strncasecmp (str->str, "normal", str->len) == 0) + if (g_strncasecmp (str->str, "normal", str->len) == 0) { desc->variant = PANGO_VARIANT_NORMAL; return TRUE; @@ -711,7 +714,8 @@ pango_parse_variant (GString *str, break; case 's': case 'S': - if (strncasecmp (str->str, "small_caps", str->len) == 0) + if (g_strncasecmp (str->str, "small_caps", str->len) == 0 || + g_strncasecmp (str->str, "smallcaps", str->len) == 0) { desc->variant = PANGO_VARIANT_SMALL_CAPS; return TRUE; @@ -719,13 +723,15 @@ pango_parse_variant (GString *str, break; } - g_warning ("Variant must be normal, or small_caps"); + if (warn) + g_warning ("Variant must be normal or small_caps"); return FALSE; } gboolean pango_parse_weight (GString *str, - PangoFontDescription *desc) + PangoFontDescription *desc, + gboolean warn) { if (str->len == 0) return FALSE; @@ -734,7 +740,7 @@ pango_parse_weight (GString *str, { case 'b': case 'B': - if (strncasecmp (str->str, "bold", str->len) == 0) + if (g_strncasecmp (str->str, "bold", str->len) == 0) { desc->weight = PANGO_WEIGHT_BOLD; return TRUE; @@ -742,7 +748,7 @@ pango_parse_weight (GString *str, break; case 'h': case 'H': - if (strncasecmp (str->str, "heavy", str->len) == 0) + if (g_strncasecmp (str->str, "heavy", str->len) == 0) { desc->weight = PANGO_WEIGHT_HEAVY; return TRUE; @@ -750,7 +756,7 @@ pango_parse_weight (GString *str, break; case 'l': case 'L': - if (strncasecmp (str->str, "light", str->len) == 0) + if (g_strncasecmp (str->str, "light", str->len) == 0) { desc->weight = PANGO_WEIGHT_LIGHT; return TRUE; @@ -758,7 +764,7 @@ pango_parse_weight (GString *str, break; case 'n': case 'N': - if (strncasecmp (str->str, "normal", str->len) == 0) + if (g_strncasecmp (str->str, "normal", str->len) == 0) { desc->weight = PANGO_WEIGHT_NORMAL; return TRUE; @@ -766,12 +772,12 @@ pango_parse_weight (GString *str, break; case 'u': case 'U': - if (strncasecmp (str->str, "ultralight", str->len) == 0) + if (g_strncasecmp (str->str, "ultralight", str->len) == 0) { desc->weight = PANGO_WEIGHT_ULTRALIGHT; return TRUE; } - else if (strncasecmp (str->str, "ultrabold", str->len) == 0) + else if (g_strncasecmp (str->str, "ultrabold", str->len) == 0) { desc->weight = PANGO_WEIGHT_ULTRABOLD; return TRUE; @@ -795,7 +801,8 @@ pango_parse_weight (GString *str, desc->weight = strtol (numstr, &end, 0); if (*end != '\0') { - g_warning ("Cannot parse numerical weight '%s'", numstr); + if (warn) + g_warning ("Cannot parse numerical weight '%s'", numstr); g_free (numstr); return FALSE; } @@ -805,13 +812,15 @@ pango_parse_weight (GString *str, } } - g_warning ("Weight must be ultralight, light, normal, bold, ultrabold, heavy, or an integer"); + if (warn) + g_warning ("Weight must be ultralight, light, normal, bold, ultrabold, heavy, or an integer"); return FALSE; } gboolean pango_parse_stretch (GString *str, - PangoFontDescription *desc) + PangoFontDescription *desc, + gboolean warn) { if (str->len == 0) return FALSE; @@ -820,7 +829,7 @@ pango_parse_stretch (GString *str, { case 'c': case 'C': - if (strncasecmp (str->str, "condensed", str->len) == 0) + if (g_strncasecmp (str->str, "condensed", str->len) == 0) { desc->stretch = PANGO_STRETCH_CONDENSED; return TRUE; @@ -828,17 +837,19 @@ pango_parse_stretch (GString *str, break; case 'e': case 'E': - if (strncasecmp (str->str, "extra_condensed", str->len) == 0) + if (g_strncasecmp (str->str, "extra_condensed", str->len) == 0 || + g_strncasecmp (str->str, "extracondensed", str->len) == 0) { desc->stretch = PANGO_STRETCH_EXTRA_CONDENSED; return TRUE; } - if (strncasecmp (str->str, "extra_expanded", str->len) == 0) + if (g_strncasecmp (str->str, "extra_expanded", str->len) == 0 || + g_strncasecmp (str->str, "extraexpanded", str->len) == 0) { desc->stretch = PANGO_STRETCH_EXTRA_EXPANDED; return TRUE; } - if (strncasecmp (str->str, "expanded", str->len) == 0) + if (g_strncasecmp (str->str, "expanded", str->len) == 0) { desc->stretch = PANGO_STRETCH_EXPANDED; return TRUE; @@ -846,7 +857,7 @@ pango_parse_stretch (GString *str, break; case 'n': case 'N': - if (strncasecmp (str->str, "normal", str->len) == 0) + if (g_strncasecmp (str->str, "normal", str->len) == 0) { desc->stretch = PANGO_STRETCH_NORMAL; return TRUE; @@ -854,12 +865,14 @@ pango_parse_stretch (GString *str, break; case 's': case 'S': - if (strncasecmp (str->str, "semi_condensed", str->len) == 0) + if (g_strncasecmp (str->str, "semi_condensed", str->len) == 0 || + g_strncasecmp (str->str, "semicondensed", str->len) == 0) { desc->stretch = PANGO_STRETCH_SEMI_CONDENSED; return TRUE; } - if (strncasecmp (str->str, "semi_expanded", str->len) == 0) + if (g_strncasecmp (str->str, "semi_expanded", str->len) == 0 || + g_strncasecmp (str->str, "semiexpanded", str->len) == 0) { desc->stretch = PANGO_STRETCH_SEMI_EXPANDED; return TRUE; @@ -867,12 +880,14 @@ pango_parse_stretch (GString *str, break; case 'u': case 'U': - if (strncasecmp (str->str, "ultra_condensed", str->len) == 0) + if (g_strncasecmp (str->str, "ultra_condensed", str->len) == 0 || + g_strncasecmp (str->str, "ultracondensed", str->len) == 0) { desc->stretch = PANGO_STRETCH_ULTRA_CONDENSED; return TRUE; } - if (strncasecmp (str->str, "ultra_expanded", str->len) == 0) + if (g_strncasecmp (str->str, "ultra_expanded", str->len) == 0 || + g_strncasecmp (str->str, "ultraexpanded", str->len) == 0) { desc->variant = PANGO_STRETCH_ULTRA_EXPANDED; return TRUE; @@ -880,7 +895,8 @@ pango_parse_stretch (GString *str, break; } - g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded"); + if (warn) + g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded"); return FALSE; } diff --git a/pango/pango-utils.h b/pango/pango-utils.h index 941ad515..4891767e 100644 --- a/pango/pango-utils.h +++ b/pango/pango-utils.h @@ -41,16 +41,22 @@ char * pango_config_key_get (const char *key); /* Functions for parsing textual representations * of PangoFontDescription fields. They return TRUE if the input string * contains a valid value, which then has been assigned to the corresponding - * field in the PangoFontDescription. + * field in the PangoFontDescription. If the warn parameter is TRUE, + * a warning is printed (with g_warning) if the string does not + * contain a valid value. */ gboolean pango_parse_style (GString *str, - PangoFontDescription *desc); + PangoFontDescription *desc, + gboolean warn); gboolean pango_parse_variant (GString *str, - PangoFontDescription *desc); + PangoFontDescription *desc, + gboolean warn); gboolean pango_parse_weight (GString *str, - PangoFontDescription *desc); + PangoFontDescription *desc, + gboolean warn); gboolean pango_parse_stretch (GString *str, - PangoFontDescription *desc); + PangoFontDescription *desc, + gboolean warn); /* On Unix, return the name of the "pango" subdirectory of SYSCONFDIR * (which is set at compile time). On Win32, return the Pango diff --git a/pango/pangoft2-fontcache.c b/pango/pangoft2-fontcache.c new file mode 100644 index 00000000..4f7f82b5 --- /dev/null +++ b/pango/pangoft2-fontcache.c @@ -0,0 +1,305 @@ +/* Pango + * pangoft2-fontcache.c: Cache of FreeType2 faces (FT_Face) + * + * Copyright (C) 2000 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "pangoft2-private.h" + +/* Font cache + */ + +/* Number of fonts to retain after they are not otherwise referenced. + */ +#define CACHE_SIZE 3 + +typedef struct _CacheEntry CacheEntry; + +struct _PangoFT2FontCache +{ + FT_Library library; + + GHashTable *forward; + GHashTable *back; + + GList *mru; + GList *mru_tail; + int mru_count; +}; + +struct _CacheEntry +{ + PangoFT2OA oa; + FT_Face face; + + gint ref_count; + GList *mru; +}; + +static void +free_cache_entry (PangoFT2OA *oa, + CacheEntry *entry, + PangoFT2FontCache *cache) +{ + FT_Error error; + + PING (("FT_Done_Face (%p)\n", entry->face)); + + error = FT_Done_Face (entry->face); + if (error != FT_Err_Ok) + g_warning ("Error from FT_Done_Face: %s", + pango_ft2_ft_strerror (error)); + + g_free (entry); +} + +/** + * pango_ft2_font_cache_free: + * @cache: a #PangoFT2FontCache + * + * Free a #PangoFT2FontCache and all associated memory. All fonts loaded + * through this font cache will be freed along with the cache. + **/ +void +pango_ft2_font_cache_free (PangoFT2FontCache *cache) +{ + g_return_if_fail (cache != NULL); + + g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache); + + g_hash_table_destroy (cache->forward); + g_hash_table_destroy (cache->back); + + g_list_free (cache->mru); +} + +static guint +oa_hash (gconstpointer v) +{ + PangoFT2OA *oa = (PangoFT2OA *) v; + + if (oa->open_args->flags & ft_open_memory) + return (guint) oa->open_args->memory_base; + else if (oa->open_args->flags == ft_open_pathname) + return g_str_hash (oa->open_args->pathname); + else if (oa->open_args->flags & ft_open_stream) + return (guint) oa->open_args->stream; + else + return 0; +} + +static gint +oa_equal (gconstpointer v1, + gconstpointer v2) +{ + PangoFT2OA *oa1 = (PangoFT2OA *) v1; + PangoFT2OA *oa2 = (PangoFT2OA *) v2; + + if (oa1->open_args->flags != oa2->open_args->flags) + return 0; + else if (oa1->open_args->flags & ft_open_memory) + return (oa1->open_args->memory_base == oa2->open_args->memory_base && + oa1->face_index == oa2->face_index); + else if (oa1->open_args->flags == ft_open_pathname) + return (strcmp (oa1->open_args->pathname, + oa2->open_args->pathname) == 0 && + oa1->face_index == oa2->face_index); + else if (oa1->open_args->flags & ft_open_stream) + return (oa1->open_args->stream == oa2->open_args->stream && + oa1->face_index == oa2->face_index); + else + return 0; +} + +/** + * pango_ft2_font_cache_new: + * + * Create a font cache. + * + * Return value: The new font cache. This must be freed with + * pango_ft2_font_cache_free(). + **/ +PangoFT2FontCache * +pango_ft2_font_cache_new (FT_Library library) +{ + PangoFT2FontCache *cache; + + cache = g_new (PangoFT2FontCache, 1); + + cache->library = library; + + cache->forward = g_hash_table_new (oa_hash, oa_equal); + cache->back = g_hash_table_new (g_direct_hash, g_direct_equal); + + cache->mru = NULL; + cache->mru_tail = NULL; + cache->mru_count = 0; + + return cache; +} + +static void +cache_entry_unref (PangoFT2FontCache *cache, + CacheEntry *entry) +{ + entry->ref_count--; + PING (("face:%p ref_count:%d\n", entry->face, entry->ref_count)); + if (entry->ref_count == 0) + { + g_hash_table_remove (cache->forward, &entry->oa); + g_hash_table_remove (cache->back, entry->face); + + free_cache_entry (NULL, entry, cache); + } +} + +/** + * pango_ft2_font_cache_load: + * @cache: a #PangoFT2FontCache + * + * Load a #FT_Face from #FT_Open_Args and a face index. The + * result may be newly loaded, or it may have been previously + * stored + * + * Return value: The #FT_Face, or %NULL if the font could + * not be loaded. In order to free this structure, you must call + * pango_ft2_font_cache_unload(). + **/ +FT_Face +pango_ft2_font_cache_load (PangoFT2FontCache *cache, + FT_Open_Args *args, + FT_Long face_index) +{ + CacheEntry *entry; + PangoFT2OA oa; + + g_return_val_if_fail (cache != NULL, NULL); + g_return_val_if_fail (args != NULL, NULL); + + oa.open_args = args; + oa.face_index = face_index; + + entry = g_hash_table_lookup (cache->forward, &oa); + + if (entry) + entry->ref_count++; + else + { + FT_Face face; + FT_Error error; + + PING (("FT_Open_Face (%s,%ld)\n", args->pathname, face_index)); + + error = FT_Open_Face (cache->library, args, face_index, &face); + if (error != FT_Err_Ok) + { + g_warning ("Error from FT_Open_Face: %s", + pango_ft2_ft_strerror (error)); + return NULL; + } + +#if DEBUGGING + g_print (" = %p\n", face); +#endif + + entry = g_new (CacheEntry, 1); + + entry->oa = oa; + entry->face = face; + + entry->ref_count = 1; + entry->mru = NULL; + + g_hash_table_insert (cache->forward, &entry->oa, entry); + g_hash_table_insert (cache->back, entry->face, entry); + } + + if (entry->mru) + { + if (cache->mru_count > 1 && entry->mru->prev) + { + /* Move to the head of the mru list */ + + if (entry->mru == cache->mru_tail) + { + cache->mru_tail = cache->mru_tail->prev; + cache->mru_tail->next = NULL; + } + else + { + entry->mru->prev->next = entry->mru->next; + entry->mru->next->prev = entry->mru->prev; + } + + entry->mru->next = cache->mru; + entry->mru->prev = NULL; + cache->mru->prev = entry->mru; + cache->mru = entry->mru; + } + } + else + { + entry->ref_count++; + + /* Insert into the mru list */ + + if (cache->mru_count == CACHE_SIZE) + { + CacheEntry *old_entry = cache->mru_tail->data; + + cache->mru_tail = cache->mru_tail->prev; + cache->mru_tail->next = NULL; + + g_list_free_1 (old_entry->mru); + old_entry->mru = NULL; + cache_entry_unref (cache, old_entry); + } + else + cache->mru_count++; + + cache->mru = g_list_prepend (cache->mru, entry); + if (!cache->mru_tail) + cache->mru_tail = cache->mru; + entry->mru = cache->mru; + } + + return entry->face; +} + +/** + * pango_ft2_font_cache_unload: + * @cache: a #PangoFT2FontCache + * @face: the face to unload + * + * Free a font structure previously loaded with pango_ft2_font_cache_load() + **/ +void +pango_ft2_font_cache_unload (PangoFT2FontCache *cache, + FT_Face face) +{ + CacheEntry *entry; + + g_return_if_fail (cache != NULL); + g_return_if_fail (face != NULL); + + entry = g_hash_table_lookup (cache->back, face); + g_return_if_fail (entry != NULL); + + PING (("pango_ft2_font_cache_unload\n")); + cache_entry_unref (cache, entry); +} diff --git a/pango/pangoft2-fontmap.c b/pango/pangoft2-fontmap.c new file mode 100644 index 00000000..a81c8639 --- /dev/null +++ b/pango/pangoft2-fontmap.c @@ -0,0 +1,1110 @@ +/* Pango + * pangoft2-fontmap.c: + * + * Copyright (C) 2000 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif +#include <sys/stat.h> + +#include "pango-fontmap.h" +#include "pango-utils.h" +#include "pangoft2-private.h" + +#define PANGO_TYPE_FT2_FONT_MAP (pango_ft2_font_map_get_type ()) +#define PANGO_FT2_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMap)) +#define PANGO_FT2_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMapClass)) +#define PANGO_FT2_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT_MAP)) +#define PANGO_FT2_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT_MAP)) +#define PANGO_FT2_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT_MAP, PangoFontMapClass)) + +typedef struct _PangoFT2FamilyEntry PangoFT2FamilyEntry; +typedef struct _PangoFT2FontMap PangoFT2FontMap; +typedef struct _PangoFT2FontMapClass PangoFT2FontMapClass; +typedef struct _PangoFT2SizeInfo PangoFT2SizeInfo; + +/* Number of freed fonts */ +#define MAX_FREED_FONTS 16 + +struct _PangoFT2FontMap +{ + PangoFontMap parent_instance; + + FT_Library library; + + PangoFT2FontCache *font_cache; + GQueue *freed_fonts; + + /* Maps Pango family names to PangoFT2FamilyEntry structs */ + GHashTable *families; + + /* Maps the family and style of a face to a PangoFT2OA struct */ + GHashTable *faces; + + int n_fonts; + + double resolution; /* (points / pixel) * PANGO_SCALE */ +}; + +struct _PangoFT2FontMapClass +{ + PangoFontMapClass parent_class; +}; + +struct _PangoFT2FamilyEntry +{ + char *family_name; + + /* List of PangoFT2FontEntry structs */ + GSList *font_entries; +}; + +struct _PangoFT2FontEntry +{ + FT_Open_Args **open_args; + FT_Long *face_indices; + int n_fonts; + PangoFontDescription description; + PangoCoverage *coverage; + + GSList *cached_fonts; +}; + +static GType pango_ft2_font_map_get_type (void); + +static void pango_ft2_font_map_init (PangoFT2FontMap *fontmap); + +static void pango_ft2_font_map_class_init (PangoFT2FontMapClass *class); + +static void pango_ft2_font_map_finalize (GObject *object); + +static PangoFont *pango_ft2_font_map_load_font (PangoFontMap *fontmap, + const PangoFontDescription *description); + +static void pango_ft2_font_map_list_fonts (PangoFontMap *fontmap, + const gchar *family, + PangoFontDescription ***descs, + int *n_descs); +static void pango_ft2_font_map_list_families (PangoFontMap *fontmap, + gchar ***families, + int *n_families); + +static void pango_ft2_fontmap_cache_clear (PangoFT2FontMap *ft2fontmap); + +static void pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap); + +static void pango_ft2_insert_face (PangoFT2FontMap *fontmap, + FT_Face face, + const char *path, + int face_index); + +static PangoFontClass *parent_class; /* Parent class structure for PangoFT2FontMap */ + +static PangoFT2FontMap *pango_ft2_global_fontmap = NULL; +static GSList *pango_ft2_font_directories = NULL; + +static GType +pango_ft2_font_map_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (PangoFT2FontMapClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_ft2_font_map_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoFT2FontMap), + 0, /* n_preallocs */ + (GInstanceInitFunc) pango_ft2_font_map_init, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT_MAP, + "PangoFT2FontMap", + &object_info); + } + + return object_type; +} + +static guint +face_style_hash (gconstpointer v) +{ + PangoFontDescription *desc = (PangoFontDescription *)v; + + return g_str_hash (desc->family_name) + + desc->style + desc->variant + desc->weight + desc->stretch; +} + +static gint +face_style_equal (gconstpointer v1, + gconstpointer v2) +{ + PangoFontDescription *desc1 = (PangoFontDescription *)v1; + PangoFontDescription *desc2 = (PangoFontDescription *)v2; + + return (g_strcasecmp (desc1->family_name, desc2->family_name) == 0 && + desc1->style == desc2->style && + desc1->variant == desc2->variant && + desc1->weight == desc2->weight && + desc1->stretch == desc2->stretch); +} + +static void +pango_ft2_font_map_init (PangoFT2FontMap *ft2fontmap) +{ + ft2fontmap->families = g_hash_table_new (g_str_hash, g_str_equal); + ft2fontmap->faces = g_hash_table_new (face_style_hash, face_style_equal); + ft2fontmap->n_fonts = 0; +} + +static void +pango_ft2_font_map_class_init (PangoFT2FontMapClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontMapClass *font_map_class = PANGO_FONT_MAP_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + object_class->finalize = pango_ft2_font_map_finalize; + font_map_class->load_font = pango_ft2_font_map_load_font; + font_map_class->list_fonts = pango_ft2_font_map_list_fonts; + font_map_class->list_families = pango_ft2_font_map_list_families; + + /* FIXME */ + pango_ft2_font_directories = g_slist_append (pango_ft2_font_directories, "C:\\windows\\fonts"); +} + +static gboolean +pango_ft2_is_font_file (const char *name) +{ + struct stat filestat; + int err, len; + + err = stat (name, &filestat); + + if (!err && S_ISREG (filestat.st_mode)) + { + len = strlen (name); + if (len > 4 && + (g_strncasecmp (&name[len-4], ".pfa", 4) == 0 || + g_strncasecmp (&name[len-4], ".pfb", 4) == 0 || + g_strncasecmp (&name[len-4], ".ttf", 4) == 0)) + { + return TRUE; + } + } + + return FALSE; +} + +static void +pango_ft2_scan_directory (const char *path, + PangoFT2FontMap *ft2fontmap) +{ + DIR *dir; + struct dirent *entry; + char *fullname; + FT_Face face; + FT_Error error; + int i; + + dir = opendir (path); + if (!dir) + g_warning ("Error opening directory '%s'", path); + else + { + while ((entry = readdir (dir)) != NULL) + { + fullname = g_strconcat (path, + (path[strlen (path)-1] == G_DIR_SEPARATOR ? + "" : G_DIR_SEPARATOR_S), + entry->d_name, + NULL); + if (pango_ft2_is_font_file (fullname)) + { + error = FT_New_Face (ft2fontmap->library, fullname, 0, &face); + if (error != FT_Err_Ok) + g_warning ("Error loading font from '%s': %s", + fullname, pango_ft2_ft_strerror (error)); + else + { + if (face->face_flags & FT_FACE_FLAG_SCALABLE) + pango_ft2_insert_face (ft2fontmap, face, fullname, 0); + + for (i = 1; i < face->num_faces; i++) + { + error = FT_Done_Face (face); + if (error != FT_Err_Ok) + g_warning ("Error from FT_Done_Face: %s", + pango_ft2_ft_strerror (error)); + error = FT_New_Face (ft2fontmap->library, fullname, i, &face); + if (error != FT_Err_Ok) + g_warning ("Error loading font %d from '%s': %s", + i, fullname, pango_ft2_ft_strerror (error)); + else if (face->face_flags & FT_FACE_FLAG_SCALABLE) + pango_ft2_insert_face (ft2fontmap, face, fullname, i); + } + error = FT_Done_Face (face); + if (error != FT_Err_Ok) + g_warning ("Error from FT_Done_Face: %s", + pango_ft2_ft_strerror (error)); + } + } + g_free (fullname); + } + closedir (dir); + } +} + +PangoFontMap * +pango_ft2_font_map_for_display (void) +{ + GSList *tmp_list; + FT_Error error; + + /* Make sure that the type system is initialized */ + g_type_init(); + + if (pango_ft2_global_fontmap != NULL) + return PANGO_FONT_MAP (pango_ft2_global_fontmap); + + pango_ft2_global_fontmap = (PangoFT2FontMap *)g_type_create_instance (PANGO_TYPE_FT2_FONT_MAP); + + error = FT_Init_FreeType (&pango_ft2_global_fontmap->library); + if (error != FT_Err_Ok) + { + g_warning ("Error from FT_Init_FreeType: %s", + pango_ft2_ft_strerror (error)); + return NULL; + } + + pango_ft2_global_fontmap->font_cache = pango_ft2_font_cache_new (pango_ft2_global_fontmap->library); + pango_ft2_global_fontmap->freed_fonts = g_queue_new (); + + tmp_list = pango_ft2_font_directories; + + while (tmp_list) + { + pango_ft2_scan_directory ((const char *) tmp_list->data, pango_ft2_global_fontmap); + tmp_list = tmp_list->next; + } + + pango_ft2_font_map_read_aliases (pango_ft2_global_fontmap); + + return PANGO_FONT_MAP (pango_ft2_global_fontmap); +} + +/** + * pango_ft2_shutdown_display: + * + * Free cached resources. + **/ +void +pango_ft2_shutdown_display (void) +{ + pango_ft2_fontmap_cache_clear (pango_ft2_global_fontmap); + + g_object_unref (G_OBJECT (pango_ft2_global_fontmap)); + + pango_ft2_global_fontmap = NULL; +} + +static void +pango_ft2_font_map_finalize (GObject *object) +{ + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object); + + g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL); + g_queue_free (ft2fontmap->freed_fonts); + + pango_ft2_font_cache_free (ft2fontmap->font_cache); + + FT_Done_FreeType (ft2fontmap->library); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +typedef struct +{ + int n_found; + PangoFontDescription **descs; +} ListFontsInfo; + +static void +list_fonts_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + PangoFT2FamilyEntry *entry = value; + ListFontsInfo *info = user_data; + + GSList *tmp_list = entry->font_entries; + + while (tmp_list) + { + PangoFT2FontEntry *font_entry = tmp_list->data; + + info->descs[info->n_found++] = pango_font_description_copy (&font_entry->description); + tmp_list = tmp_list->next; + } +} + +static void +pango_ft2_font_map_list_fonts (PangoFontMap *fontmap, + const gchar *family, + PangoFontDescription ***descs, + int *n_descs) +{ + PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap; + ListFontsInfo info; + + if (!n_descs) + return; + + if (family) + { + PangoFT2FamilyEntry *entry = g_hash_table_lookup (ft2fontmap->families, family); + if (entry) + { + *n_descs = g_slist_length (entry->font_entries); + if (descs) + { + *descs = g_new (PangoFontDescription *, *n_descs); + + info.descs = *descs; + info.n_found = 0; + + list_fonts_foreach ((gpointer)family, (gpointer)entry, &info); + } + } + else + { + *n_descs = 0; + if (descs) + *descs = NULL; + } + } + else + { + *n_descs = ft2fontmap->n_fonts; + if (descs) + { + *descs = g_new (PangoFontDescription *, ft2fontmap->n_fonts); + + info.descs = *descs; + info.n_found = 0; + + g_hash_table_foreach (ft2fontmap->families, list_fonts_foreach, &info); + } + } +} + +static void +list_families_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + GSList **list = user_data; + + *list = g_slist_prepend (*list, key); +} + +static void +pango_ft2_font_map_list_families (PangoFontMap *fontmap, + gchar ***families, + int *n_families) +{ + GSList *family_list = NULL; + GSList *tmp_list; + PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap; + + if (!n_families) + return; + + g_hash_table_foreach (ft2fontmap->families, list_families_foreach, &family_list); + + *n_families = g_slist_length (family_list); + + if (families) + { + int i = 0; + + *families = g_new (gchar *, *n_families); + + tmp_list = family_list; + while (tmp_list) + { + (*families)[i] = g_strdup (tmp_list->data); + i++; + tmp_list = tmp_list->next; + } + } + + g_slist_free (family_list); +} + +static PangoFT2FamilyEntry * +pango_ft2_get_family_entry (PangoFT2FontMap *ft2fontmap, + const char *family_name) +{ + PangoFT2FamilyEntry *family_entry = g_hash_table_lookup (ft2fontmap->families, family_name); + if (!family_entry) + { + family_entry = g_new (PangoFT2FamilyEntry, 1); + family_entry->family_name = g_strdup (family_name); + family_entry->font_entries = NULL; + + g_hash_table_insert (ft2fontmap->families, family_entry->family_name, family_entry); + } + + return family_entry; +} + +static PangoFont * +pango_ft2_font_map_load_font (PangoFontMap *fontmap, + const PangoFontDescription *description) +{ + PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap; + PangoFT2FamilyEntry *family_entry; + PangoFont *result = NULL; + GSList *tmp_list; + gchar *name; + + g_return_val_if_fail (description != NULL, NULL); + g_return_val_if_fail (description->size > 0, NULL); + + name = g_strdup (description->family_name); + g_strdown (name); + + family_entry = g_hash_table_lookup (ft2fontmap->families, name); + if (family_entry) + { + PangoFT2FontEntry *best_match = NULL; + + tmp_list = family_entry->font_entries; + while (tmp_list) + { + PangoFT2FontEntry *font_entry = tmp_list->data; + + if (font_entry->description.style == description->style && + font_entry->description.variant == description->variant && + font_entry->description.stretch == description->stretch) + { + int distance = abs (font_entry->description.weight - description->weight); + int old_distance = best_match ? abs (best_match->description.weight - description->weight) : G_MAXINT; + + if (distance < old_distance) + { + best_match = font_entry; + } + } + + tmp_list = tmp_list->next; + } + + if (best_match) + { + GSList *tmp_list = best_match->cached_fonts; + + while (tmp_list) + { + PangoFT2Font *ft2font = tmp_list->data; + + if (ft2font->size == description->size) + { + result = (PangoFont *)ft2font; + + g_object_ref (G_OBJECT (result)); + if (ft2font->in_cache) + pango_ft2_fontmap_cache_remove (fontmap, ft2font); + break; + } + tmp_list = tmp_list->next; + } + + if (!result) + { + PangoFT2Font *ft2font = + (PangoFT2Font *) pango_ft2_load_font (fontmap, + best_match->open_args, + best_match->face_indices, + best_match->n_fonts, + description->size); + + ft2font->fontmap = fontmap; + ft2font->entry = best_match; + best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, ft2font); + + result = (PangoFont *)ft2font; + } + } + } + + g_free (name); + return result; +} + +static void +pango_ft2_font_map_read_alias_file (PangoFT2FontMap *ft2fontmap, + const char *filename) +{ + FILE *infile; + int lineno = 0; + int nfaces; + int i; + PangoFT2FontEntry *font_entry = NULL; + gchar **faces; + + infile = fopen (filename, "r"); + if (infile) + { + GString *line_buf = g_string_new (NULL); + GString *tmp_buf = g_string_new (NULL); + + while (pango_read_line (infile, line_buf)) + { + PangoFT2FamilyEntry *family_entry; + + const char *p = line_buf->str; + + lineno++; + + if (!pango_skip_space (&p)) + continue; + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + font_entry = g_new (PangoFT2FontEntry, 1); + font_entry->n_fonts = 0; + font_entry->open_args = NULL; + font_entry->face_indices = NULL; + + font_entry->description.family_name = g_strdup (tmp_buf->str); + g_strdown (font_entry->description.family_name); + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE)) + goto error; + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE)) + goto error; + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE)) + goto error; + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE)) + goto error; + + if (!pango_scan_string (&p, tmp_buf)) + goto error; + + /* Remove excess whitespace and check for complete fields */ + + faces = g_strsplit (tmp_buf->str, ",", -1); + nfaces = 0; + for (i = 0; faces[i]; i++) + { + char *trimmed = pango_trim_string (faces[i]); + g_free (faces[i]); + faces[i] = trimmed; + nfaces++; + } + + font_entry->open_args = g_new (FT_Open_Args *, nfaces); + font_entry->face_indices = g_new (FT_Long, nfaces); + + for (i = 0; i < nfaces; i++) + { + PangoFontDescription desc; + PangoFT2OA *oa; + + desc = font_entry->description; + desc.family_name = faces[i]; + oa = g_hash_table_lookup (ft2fontmap->faces, &desc); + if (!oa) + g_warning ("Face '%s' on line %d of '%s' not found", faces[i], lineno, filename); + else + { + font_entry->open_args[font_entry->n_fonts] = oa->open_args; + font_entry->face_indices[font_entry->n_fonts] = oa->face_index; + font_entry->n_fonts++; + } + } + + /* Insert the font entry into our structures */ + + family_entry = pango_ft2_get_family_entry (ft2fontmap, font_entry->description.family_name); + family_entry->font_entries = g_slist_prepend (family_entry->font_entries, font_entry); + ft2fontmap->n_fonts++; + + g_free (font_entry->description.family_name); + font_entry->description.family_name = family_entry->family_name; + font_entry->cached_fonts = NULL; + font_entry->coverage = NULL; + } + + if (ferror (infile)) + g_warning ("Error reading file '%s': %s", filename, g_strerror(errno)); + + goto out; + + error: + if (font_entry) + { + if (font_entry->open_args) + g_free (font_entry->open_args); + if (font_entry->face_indices) + g_free (font_entry->face_indices); + if (font_entry->description.family_name) + g_free (font_entry->description.family_name); + g_free (font_entry); + } + + g_warning ("Error parsing line %d of alias file '%s'", lineno, filename); + + out: + g_string_free (tmp_buf, TRUE); + g_string_free (line_buf, TRUE); + + fclose (infile); + } + +} + +static void +pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap) +{ + char **files; + char *files_str = pango_config_key_get ("PangoFT2/AliasFiles"); + char *home; + char *tmp_str; + int n; + + if (!files_str) + { + home = g_get_home_dir (); + if (home && *home) + files_str = g_strconcat (home, "\\.pangoft2_aliases;", NULL); + + tmp_str = g_strconcat (files_str, pango_get_sysconf_subdirectory (), + "\\pangoft2.aliases", + NULL); + g_free (files_str); + files_str = tmp_str; + } + + files = pango_split_file_list (files_str); + + n = 0; + while (files[n]) + n++; + + while (n-- > 0) + pango_ft2_font_map_read_alias_file (ft2fontmap, files[n]); + + g_strfreev (files); + g_free (files_str); +} + +#if DEBUGGING + +static void +pango_print_desc (PangoFontDescription *desc) +{ + g_print ("%s%s%s%s%s", + desc->family_name, + (desc->style == PANGO_STYLE_NORMAL ? "" : + (desc->style == PANGO_STYLE_OBLIQUE ? " OBLIQUE" : + (desc->style == PANGO_STYLE_ITALIC ? " ITALIC" : " ???"))), + (desc->variant == PANGO_VARIANT_NORMAL ? "" : + (desc->variant == PANGO_VARIANT_SMALL_CAPS ? " SMALL CAPS" : "???")), + (desc->weight >= (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 && + desc->weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 ? "" : + (desc->weight < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 ? " ULTRALIGHT" : + (desc->weight >= (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 && + desc->weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 ? " LIGHT" : + (desc->weight >= (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 && + desc->weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 ? " BOLD" : + (desc->weight >= (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 && + desc->weight < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2 ? " ULTRABOLD" : + " HEAVY"))))), + (desc->stretch == PANGO_STRETCH_ULTRA_CONDENSED ? " ULTRA CONDENSED" : + (desc->stretch == PANGO_STRETCH_EXTRA_CONDENSED ? " EXTRA CONDENSED" : + (desc->stretch == PANGO_STRETCH_CONDENSED ? " CONDENSED" : + (desc->stretch == PANGO_STRETCH_SEMI_CONDENSED ? " SEMI CONDENSED" : + (desc->stretch == PANGO_STRETCH_NORMAL ? "" : + (desc->stretch == PANGO_STRETCH_SEMI_EXPANDED ? " SEMI EXPANDED" : + (desc->stretch == PANGO_STRETCH_EXPANDED ? " EXPANDED" : + (desc->stretch == PANGO_STRETCH_EXTRA_EXPANDED ? " EXTRA EXPANDED" : + (desc->stretch == PANGO_STRETCH_ULTRA_EXPANDED ? " ULTRA EXPANDED" : " ???")))))))))); +} + +static void +pango_ft2_print_oa (PangoFT2OA *oa) +{ + g_print ("%s:%ld", oa->open_args->pathname, oa->face_index); +} + +#endif + +static void +pango_ft2_insert_face (PangoFT2FontMap *ft2fontmap, + FT_Face face, + const char *path, + int face_index) +{ + PangoFontDescription *description; + GSList *tmp_list; + PangoFT2FamilyEntry *family_entry; + PangoFT2FontEntry *font_entry; + PangoFT2OA *oa; + FT_Open_Args *open_args; + + description = g_new (PangoFontDescription, 1); + description->family_name = g_strdup (face->family_name); + g_strdown (description->family_name); + + if (face->style_flags & FT_STYLE_FLAG_ITALIC) + description->style = PANGO_STYLE_ITALIC; + else + description->style = PANGO_STYLE_NORMAL; + + description->variant = PANGO_VARIANT_NORMAL; + + if (face->style_flags & FT_STYLE_FLAG_BOLD) + description->weight = PANGO_WEIGHT_BOLD; + else + description->weight = PANGO_WEIGHT_NORMAL; + + description->stretch = PANGO_STRETCH_NORMAL; + + if (face->style_name) + { + gchar **styles = g_strsplit (face->style_name, " ", 0); + gint i = 0; + + while (styles[i]) + { + GString *s = g_string_new (styles[i]); + (void) (pango_parse_style (s, description, FALSE) || + pango_parse_variant (s, description, FALSE) || + pango_parse_weight (s, description, FALSE) || + pango_parse_stretch (s, description, FALSE)); + g_string_free (s, TRUE); + i++; + } + g_strfreev (styles); + } + + description->size = 0; + +#if 0 + PING (("")); + pango_print_desc (description); +#endif + + family_entry = pango_ft2_get_family_entry (ft2fontmap, description->family_name); + + tmp_list = family_entry->font_entries; + while (tmp_list) + { + font_entry = tmp_list->data; + + if (font_entry->description.style == description->style && + font_entry->description.variant == description->variant && + font_entry->description.weight == description->weight && + font_entry->description.stretch == description->stretch) + { + g_free (description->family_name); + g_free (description); +#if 0 + PING ((" family and description matched (!)\n")); +#endif + return; + } + + tmp_list = tmp_list->next; + } + + oa = g_hash_table_lookup (ft2fontmap->faces, description); + if (!oa) + { + oa = g_new (PangoFT2OA, 1); + open_args = g_new (FT_Open_Args, 1); + open_args->flags = ft_open_pathname; + open_args->pathname = g_strdup (path); + open_args->driver = NULL; + open_args->num_params = 0; + oa->open_args = open_args; + oa->face_index = face_index; +#if 0 + PING (("adding mapping: ")); + pango_ft2_print_oa (oa); +#endif + g_hash_table_insert (ft2fontmap->faces, description, oa); + } +#if 0 + g_print ("\n"); +#endif + + font_entry = g_new (PangoFT2FontEntry, 1); + font_entry->description = *description; + font_entry->description.family_name = family_entry->family_name; + font_entry->cached_fonts = NULL; + font_entry->coverage = NULL; + font_entry->open_args = g_new (FT_Open_Args *, 1); + font_entry->open_args[0] = oa->open_args; + font_entry->face_indices = g_new (FT_Long, 1); + font_entry->face_indices[0] = oa->face_index; + font_entry->n_fonts = 1; + family_entry->font_entries = g_slist_append (family_entry->font_entries, font_entry); + ft2fontmap->n_fonts++; +} + +static void +free_coverages_foreach (gpointer key, + gpointer value, + gpointer data) +{ + pango_coverage_unref (value); +} + +PangoCoverage * +pango_ft2_font_entry_get_coverage (PangoFT2FontEntry *entry, + PangoFont *font, + const char *lang) +{ + guint32 ch; + PangoMap *shape_map; + PangoCoverage *coverage; + PangoCoverage *result; + PangoCoverageLevel font_level; + PangoMapEntry *map_entry; + GHashTable *coverage_hash; + + if (entry) + if (entry->coverage) + { + pango_coverage_ref (entry->coverage); + return entry->coverage; + } + + result = pango_coverage_new (); + + coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); + + shape_map = pango_ft2_get_shaper_map (lang); + + for (ch = 0; ch < 65536; ch++) + { + map_entry = pango_map_get_entry (shape_map, ch); + if (map_entry->info) + { + coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id); + if (!coverage) + { + PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch); + coverage = engine->get_coverage (font, lang); + g_hash_table_insert (coverage_hash, map_entry->info->id, coverage); + } + + font_level = pango_coverage_get (coverage, ch); + if (font_level == PANGO_COVERAGE_EXACT && !map_entry->is_exact) + font_level = PANGO_COVERAGE_APPROXIMATE; + + if (font_level != PANGO_COVERAGE_NONE) + pango_coverage_set (result, ch, font_level); + } + } + + g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL); + g_hash_table_destroy (coverage_hash); + + if (entry) + { + entry->coverage = result; + pango_coverage_ref (result); + } + + return result; +} + +void +pango_ft2_font_entry_remove (PangoFT2FontEntry *entry, + PangoFont *font) +{ + entry->cached_fonts = g_slist_remove (entry->cached_fonts, font); +} + +PangoFT2FontCache * +pango_ft2_font_map_get_font_cache (PangoFontMap *font_map) +{ + g_return_val_if_fail (font_map != NULL, NULL); + g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (font_map), NULL); + + return PANGO_FT2_FONT_MAP (font_map)->font_cache; +} + +void +pango_ft2_fontmap_cache_add (PangoFontMap *fontmap, + PangoFT2Font *ft2font) +{ + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap); + + if (ft2fontmap->freed_fonts->length == MAX_FREED_FONTS) + { + PangoFT2Font *old_font = g_queue_pop_tail (ft2fontmap->freed_fonts); + g_object_unref (G_OBJECT (old_font)); + } + + g_object_ref (G_OBJECT (ft2font)); + g_queue_push_head (ft2fontmap->freed_fonts, ft2font); + ft2font->in_cache = TRUE; +} + +void +pango_ft2_fontmap_cache_remove (PangoFontMap *fontmap, + PangoFT2Font *ft2font) +{ + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap); + + GList *link = g_list_find (ft2fontmap->freed_fonts->head, ft2font); + if (link == ft2fontmap->freed_fonts->tail) + { + ft2fontmap->freed_fonts->tail = ft2fontmap->freed_fonts->tail->prev; + if (ft2fontmap->freed_fonts->tail) + ft2fontmap->freed_fonts->tail->next = NULL; + } + + ft2fontmap->freed_fonts->head = g_list_delete_link (ft2fontmap->freed_fonts->head, link); + ft2fontmap->freed_fonts->length--; + ft2font->in_cache = FALSE; + + g_object_unref (G_OBJECT (ft2font)); +} + +static void +pango_ft2_fontmap_cache_clear (PangoFT2FontMap *ft2fontmap) +{ + g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL); + g_list_free (ft2fontmap->freed_fonts->head); + ft2fontmap->freed_fonts->head = NULL; + ft2fontmap->freed_fonts->tail = NULL; + ft2fontmap->freed_fonts->length = 0; +} + +static void +pango_ft2_font_entry_dump (int indent, + PangoFT2FontEntry *font_entry) +{ + int i; + + printf ("%*sPangoFT2FontEntry@%p:\n" + "%*s lfp:\n", + indent, "", font_entry, + indent, ""); + + for (i = 0; i < font_entry->n_fonts; i++) + printf ("%*s PangoFT2OpenArgs:%s:%ld\n", + indent, "", font_entry->open_args[i]->pathname, font_entry->face_indices[i]); + + printf ("%*s description:\n" + "%*s family_name: %s\n" + "%*s style: %d\n" + "%*s variant: %d\n" + "%*s weight: %d\n" + "%*s stretch: %d\n" + "%*s coverage: %p\n", + indent, "", + indent, "", font_entry->description.family_name, + indent, "", font_entry->description.style, + indent, "", font_entry->description.variant, + indent, "", font_entry->description.weight, + indent, "", font_entry->description.stretch, + indent, "", font_entry->coverage); +} + +static void +pango_ft2_family_entry_dump (int indent, + PangoFT2FamilyEntry *entry) +{ + GSList *tmp_list = entry->font_entries; + + printf ("%*sPangoFT2FamilyEntry@%p:\n" + "%*s family_name: %s\n" + "%*s font_entries:\n", + indent, "", entry, + indent, "", entry->family_name, + indent, ""); + + while (tmp_list) + { + PangoFT2FontEntry *font_entry = tmp_list->data; + + pango_ft2_font_entry_dump (indent + 2, font_entry); + tmp_list = tmp_list->next; + } +} + +static void +dump_family (gpointer key, + gpointer value, + gpointer user_data) +{ + PangoFT2FamilyEntry *entry = value; + int indent = (int) user_data; + + pango_ft2_family_entry_dump (indent, entry); +} + +void +pango_ft2_fontmap_dump (int indent, + PangoFontMap *fontmap) +{ + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap); + + printf ("%*sPangoFT2FontMap@%p:\n", + indent, "", ft2fontmap); + g_hash_table_foreach (ft2fontmap->families, dump_family, (gpointer) (indent + 2)); +} diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h new file mode 100644 index 00000000..92b1c053 --- /dev/null +++ b/pango/pangoft2-private.h @@ -0,0 +1,97 @@ +/* Pango + * pangoft2-private.h: + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOFT2_PRIVATE_H__ +#define __PANGOFT2_PRIVATE_H__ + +#include "pango-modules.h" +#include "pangoft2.h" + +/* Debugging... */ +#define DEBUGGING 1 + +#ifdef DEBUGGING +#define PING(printlist) \ +(g_print ("%s:%d ", __PRETTY_FUNCTION__, __LINE__), \ + g_print printlist) +#else +#define PING(printlist) +#endif + +#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) +#define PANGO_PIXELS_26_6(d) \ + (((d) >= 0) ? \ + ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ + ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) +#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) + +typedef struct _PangoFT2OA PangoFT2OA; +typedef struct _PangoFT2Font PangoFT2Font; +typedef struct _PangoFT2FontEntry PangoFT2FontEntry; +typedef struct _PangoFT2SubfontInfo PangoFT2SubfontInfo; + +struct _PangoFT2OA +{ + FT_Open_Args *open_args; + FT_Long face_index; +}; + +struct _PangoFT2Font +{ + PangoFont font; + + /* A PangoFT2Font consists of one or several FT2 fonts (faces) that + * are assumed to blend visually well, and cover separate parts of + * the Unicode characters. The FT2 faces are not kept unnecessarily + * open, thus also we keep both the FT_Open_Args (and face index), + * and FT_Face. + */ + PangoFT2OA **oa; + FT_Face *faces; + int n_fonts; + + int size; + + GSList *metrics_by_lang; + + PangoFontMap *fontmap; + /* If TRUE, font is in cache of recently unused fonts and not otherwise + * in use. + */ + gboolean in_cache; + + PangoFT2FontEntry *entry; /* Used to remove cached fonts */ +}; + +PangoMap *pango_ft2_get_shaper_map (const char *lang); +PangoCoverage *pango_ft2_font_entry_get_coverage (PangoFT2FontEntry *entry, + PangoFont *font, + const char *lang); +void pango_ft2_font_entry_remove (PangoFT2FontEntry *entry, + PangoFont *font); +FT_Library *pango_ft2_fontmap_get_library (PangoFontMap *fontmap); +void pango_ft2_fontmap_cache_add (PangoFontMap *fontmap, + PangoFT2Font *ft2font); +void pango_ft2_fontmap_cache_remove (PangoFontMap *fontmap, + PangoFT2Font *ft2font); +const char *pango_ft2_ft_strerror (FT_Error error); + +#endif /* __PANGOFT2_PRIVATE_H__ */ diff --git a/pango/pangoft2.c b/pango/pangoft2.c new file mode 100644 index 00000000..faffe580 --- /dev/null +++ b/pango/pangoft2.c @@ -0,0 +1,1126 @@ +/* Pango + * pangoft2.c: Routines for handling FreeType2 fonts + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <glib.h> + +#include <freetype/freetype.h> +#include <fribidi/fribidi.h> + +#include "pangoft2.h" +#include "pangoft2-private.h" + +#define PANGO_TYPE_FT2_FONT (pango_ft2_font_get_type ()) +#define PANGO_FT2_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT, PangoFT2Font)) +#define PANGO_FT2_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_FONT, PangoFT2FontClass)) +#define PANGO_FT2_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT)) +#define PANGO_FT2_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_FONT)) +#define PANGO_FT2_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT, PangoFT2FontClass)) + +typedef struct _PangoFT2FontClass PangoFT2FontClass; +typedef struct _PangoFT2MetricsInfo PangoFT2MetricsInfo; +typedef struct _PangoFT2ContextInfo PangoFT2ContextInfo; + +struct _PangoFT2MetricsInfo +{ + const char *lang; + PangoFontMetrics metrics; +}; + +struct _PangoFT2FontClass +{ + PangoFontClass parent_class; +}; + +static PangoFontClass *parent_class; /* Parent class structure for PangoFT2Font */ + +static void pango_ft2_font_class_init (PangoFT2FontClass *class); +static void pango_ft2_font_init (PangoFT2Font *xfont); +static void pango_ft2_font_shutdown (GObject *object); +static void pango_ft2_font_finalize (GObject *object); + +static PangoFontDescription *pango_ft2_font_describe (PangoFont *font); + +static PangoCoverage * pango_ft2_font_get_coverage (PangoFont *font, + const char *lang); + +static PangoEngineShape * pango_ft2_font_find_shaper (PangoFont *font, + const char *lang, + guint32 ch); + +static void pango_ft2_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +static void pango_ft2_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics); + +static void pango_ft2_get_item_properties (PangoItem *item, + PangoUnderline *uline, + PangoAttrColor *fg_color, + gboolean *fg_set, + PangoAttrColor *bg_color, + gboolean *bg_set); + +static char * +pango_ft2_open_args_describe (PangoFT2OA *oa) +{ + if (oa->open_args->flags & ft_open_memory) + return g_strdup_printf ("memory at %p", oa->open_args->memory_base); + else if (oa->open_args->flags == ft_open_pathname) + return g_strdup_printf ("file '%s'", oa->open_args->pathname); + else if (oa->open_args->flags & ft_open_stream) + return g_strdup_printf ("FT_Stream at %p", oa->open_args->stream); + else + return g_strdup_printf ("open_args at %p, face_index %ld", oa->open_args, oa->face_index); +} + +static inline FT_Face +pango_ft2_get_face (PangoFont *font, + PangoFT2Subfont subfont_index) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)font; + PangoFT2FontCache *cache; + + if (subfont_index < 1 || subfont_index > ft2font->n_fonts) + { + g_warning ("Invalid subfont %d", subfont_index); + return NULL; + } + + if (!ft2font->faces[subfont_index-1]) + { + cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap); + + ft2font->faces[subfont_index-1] = + pango_ft2_font_cache_load (cache, + ft2font->oa[subfont_index-1]->open_args, + ft2font->oa[subfont_index-1]->face_index); + + if (!ft2font->faces[subfont_index-1]) + g_warning ("Cannot load font for %s", + pango_ft2_open_args_describe (ft2font->oa[subfont_index-1])); + } + return ft2font->faces[subfont_index-1]; +} + +/** + * pango_ft2_get_context: + * + * Retrieves a #PangoContext appropriate for rendering with Pango fonts. + * + * Return value: the new #PangoContext + **/ +PangoContext * +pango_ft2_get_context (void) +{ + PangoContext *result; + + result = pango_context_new (); + pango_context_add_font_map (result, pango_ft2_font_map_for_display ()); + + return result; +} + +static GType +pango_ft2_font_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (PangoFT2FontClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_ft2_font_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoFT2Font), + 0, /* n_preallocs */ + (GInstanceInitFunc) pango_ft2_font_init, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT, + "PangoFT2Font", + &object_info); + } + + return object_type; +} + +static void +pango_ft2_font_init (PangoFT2Font *ft2font) +{ + ft2font->oa = NULL; + ft2font->faces = NULL; + + ft2font->n_fonts = 0; + + ft2font->metrics_by_lang = NULL; + + ft2font->entry = NULL; +} + +static void +pango_ft2_font_class_init (PangoFT2FontClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + PangoFontClass *font_class = PANGO_FONT_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + object_class->finalize = pango_ft2_font_finalize; + object_class->shutdown = pango_ft2_font_shutdown; + + font_class->describe = pango_ft2_font_describe; + font_class->get_coverage = pango_ft2_font_get_coverage; + font_class->find_shaper = pango_ft2_font_find_shaper; + font_class->get_glyph_extents = pango_ft2_font_get_glyph_extents; + font_class->get_metrics = pango_ft2_font_get_metrics; +} + +/** + * pango_ft2_load_font: + * + * Loads a logical font based on XXX + * + * Returns a new #PangoFont + */ +PangoFont * +pango_ft2_load_font (PangoFontMap *fontmap, + FT_Open_Args **open_args, + FT_Long *face_indices, + int n_fonts, + int size) +{ + PangoFT2Font *result; + int i; + + g_return_val_if_fail (fontmap != NULL, NULL); + g_return_val_if_fail (open_args != NULL, NULL); + g_return_val_if_fail (face_indices != NULL, NULL); + g_return_val_if_fail (n_fonts > 0, NULL); + + result = (PangoFT2Font *)g_type_create_instance (PANGO_TYPE_FT2_FONT); + + result->fontmap = fontmap; + g_object_ref (G_OBJECT (result->fontmap)); + + result->oa = g_new (PangoFT2OA *, n_fonts); + result->faces = g_new (FT_Face, n_fonts); + result->n_fonts = n_fonts; + result->size = size; + + for (i = 0; i < n_fonts; i++) + { + result->oa[i] = g_new (PangoFT2OA, 1); + result->oa[i]->open_args = open_args[i]; + result->oa[i]->face_index = face_indices[i]; + result->faces[i] = NULL; + } + + return &result->font; +} + +/** + * pango_ft2_render: + * + * @bitmap: the FreeType2 bitmap onto which draw the string + * @font: the font in which to draw the string + * @glyphs: the glyph string to draw + * @x: the x position of start of string (in pixels) + * @y: the y position of baseline (in pixels) + * + * Render a PangoGlyphString onto a FreeType2 bitmap + */ +void +pango_ft2_render (FT_Bitmap *bitmap, + PangoFont *font, + PangoGlyphString *glyphs, + int x, + int y) +{ + FT_Face face; + FT_Face prev_face = NULL; + FT_UInt glyph_index, prev_index; + int i; + int x_position = 0; + int ix, iy, ixoff, iyoff, y_start, y_limit, x_start, x_limit; + guint16 char_index; + PangoFT2Subfont subfont_index; + PangoGlyphInfo *gi; + guchar *p, *q; + + g_return_if_fail (bitmap != NULL); + g_return_if_fail (glyphs != NULL); + + PING (("bitmap: %dx%d@+%d+%d\n", bitmap->width, bitmap->rows, x, y)); + + gi = glyphs->glyphs; + for (i = 0; i < glyphs->num_glyphs; i++, gi++) + { + if (gi->glyph) + { + char_index = PANGO_FT2_GLYPH_INDEX (gi->glyph); + subfont_index = PANGO_FT2_GLYPH_SUBFONT (gi->glyph); + face = pango_ft2_get_face (font, subfont_index); + + if (face) + { + /* Draw glyph */ + glyph_index = FT_Get_Char_Index (face, char_index); + /* FIXME hint or not? */ + FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT); + FT_Render_Glyph (face->glyph, ft_render_mode_normal); + + ixoff = x + PANGO_PIXELS (x_position + gi->geometry.x_offset); + iyoff = y + PANGO_PIXELS (gi->geometry.y_offset); + + x_start = MAX (0, -face->glyph->bitmap_left - ixoff); + x_limit = MIN (face->glyph->bitmap.width, face->glyph->bitmap_left - ixoff + bitmap->width); + + y_start = MAX (0, face->glyph->bitmap_top - iyoff); + y_limit = MIN (face->glyph->bitmap.rows, face->glyph->bitmap_top - iyoff + bitmap->rows); + + + PING (("glyph %d:%d: bitmap: %dx%d, left:%d top:%d\n", + i, glyph_index, + face->glyph->bitmap.width, face->glyph->bitmap.rows, + face->glyph->bitmap_left, face->glyph->bitmap_top)); + PING (("xstart:%d xlim:%d ystart:%d ylim:%d\n", + x_start, x_limit, y_start, y_limit)); + + for (iy = y_start; iy < y_limit; iy++) + { + p = bitmap->buffer + + (iyoff - face->glyph->bitmap_top + iy) * bitmap->pitch + + ixoff + + face->glyph->bitmap_left + x_start; + + q = face->glyph->bitmap.buffer + iy*face->glyph->bitmap.pitch; + for (ix = x_start; ix < x_limit; ix++) + { + *p = MIN (*p, 0xFF - *q); + q++; + p++; + } + } + + prev_face = face; + prev_index = glyph_index; + } + } + + x_position += glyphs->glyphs[i].geometry.width; + } +} + +static FT_Glyph_Metrics * +pango_ft2_get_per_char (PangoFont *font, + PangoFT2Subfont subfont_index, + guint16 char_index) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)font; + FT_Face face; + FT_UInt glyph_index; + FT_Error error; + + if (!(face = pango_ft2_get_face (font, subfont_index))) + return NULL; + + glyph_index = FT_Get_Char_Index (face, char_index); + if (!glyph_index) + return NULL; + + error = FT_Set_Pixel_Sizes (face, PANGO_PIXELS (ft2font->size), 0); + if (error) + g_warning ("Error in FT_Set_Pixel_Sizes: %d", error); + + FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT); + return &face->glyph->metrics; +} + +static void +pango_ft2_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + guint16 char_index = PANGO_FT2_GLYPH_INDEX (glyph); + PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph); + FT_Glyph_Metrics *gm; + + if (glyph && (gm = pango_ft2_get_per_char (font, subfont_index, char_index))) + { + if (ink_rect) + { + ink_rect->x = PANGO_UNITS_26_6 (gm->horiBearingX); + ink_rect->width = PANGO_UNITS_26_6 (gm->width); + ink_rect->y = -PANGO_UNITS_26_6 (gm->horiBearingY); + ink_rect->height = PANGO_UNITS_26_6 (gm->height); + } + if (logical_rect) + { + FT_Face face = pango_ft2_get_face (font, subfont_index); + + logical_rect->x = 0; + logical_rect->width = PANGO_UNITS_26_6 (gm->horiAdvance); + logical_rect->y = -PANGO_UNITS_26_6 (face->size->metrics.ascender + 64); + /* Some fonts report negative descender, some positive ! (?) */ + logical_rect->height = PANGO_UNITS_26_6 (face->size->metrics.ascender + ABS (face->size->metrics.descender) + 128); + } + PING (("glyph:%d logical: %dx%d@%d+%d\n", + char_index, logical_rect->width, logical_rect->height, + logical_rect->x, logical_rect->y)); + } + else + { + if (ink_rect) + { + ink_rect->x = 0; + ink_rect->width = 0; + ink_rect->y = 0; + ink_rect->height = 0; + } + if (logical_rect) + { + logical_rect->x = 0; + logical_rect->width = 0; + logical_rect->y = 0; + logical_rect->height = 0; + } + } +} + +int +pango_ft2_font_get_kerning (PangoFont *font, + PangoGlyph left, + PangoGlyph right) +{ + PangoFT2Subfont subfont_index; + guint16 left_char_index; + guint16 right_char_index; + FT_Face face; + FT_UInt left_glyph_index, right_glyph_index; + FT_Error error; + FT_Vector kerning; + + subfont_index = PANGO_FT2_GLYPH_SUBFONT (left); + if (PANGO_FT2_GLYPH_SUBFONT (right) != subfont_index) + return 0; + + face = pango_ft2_get_face (font, subfont_index); + if (!face) + return 0; + + if (!FT_HAS_KERNING (face)) + return 0; + + left_char_index = PANGO_FT2_GLYPH_INDEX (left); + right_char_index = PANGO_FT2_GLYPH_INDEX (right); + + left_glyph_index = FT_Get_Char_Index (face, left_char_index); + right_glyph_index = FT_Get_Char_Index (face, right_char_index); + if (!left_glyph_index || !right_char_index) + return 0; + + error = FT_Get_Kerning (face, left_glyph_index, right_glyph_index, + ft_kerning_default, &kerning); + if (error != FT_Err_Ok) + g_warning ("FT_Get_Kerning returns error: %s", + pango_ft2_ft_strerror (error)); + + return PANGO_UNITS_26_6 (kerning.x); +} + +/* Get composite font metrics for all subfonts in list + */ +static void +get_font_metrics_from_subfonts (PangoFont *font, + GSList *subfonts, + PangoFontMetrics *metrics) +{ + GSList *tmp_list = subfonts; + gboolean first = TRUE; + + metrics->ascent = 0; + metrics->descent = 0; + + while (tmp_list) + { + FT_Face face = pango_ft2_get_face (font, GPOINTER_TO_UINT (tmp_list->data)); + + g_assert (face != NULL); + + if (first) + { + metrics->ascent = PANGO_UNITS_26_6 (face->ascender); + metrics->descent = PANGO_UNITS_26_6 (face->descender); + first = FALSE; + } + else + { + metrics->ascent = MAX (PANGO_UNITS_26_6 (face->ascender), metrics->ascent); + metrics->descent = MAX (PANGO_UNITS_26_6 (face->descender), metrics->descent); + } + + tmp_list = tmp_list->next; + } +} + +/* Get composite font metrics for all subfonts resulting from shaping + * string str with the given font + * + * This duplicates quite a bit of code from pango_itemize. This function + * should die and we should simply add the ability to specify particular + * fonts when itemizing. + */ +static void +get_font_metrics_from_string (PangoFont *font, + const char *lang, + const char *str, + PangoFontMetrics *metrics) +{ + const char *start, *p; + PangoGlyphString *glyph_str = pango_glyph_string_new (); + PangoEngineShape *shaper, *last_shaper; + int last_level; + gunichar *text_ucs4; + int n_chars, i; + guint8 *embedding_levels; + FriBidiCharType base_dir = PANGO_DIRECTION_LTR; + GSList *subfonts = NULL; + + n_chars = g_utf8_strlen (str, -1); + + text_ucs4 = g_utf8_to_ucs4 (str, strlen (str)); + if (!text_ucs4) + return; + + embedding_levels = g_new (guint8, n_chars); + fribidi_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir, + embedding_levels); + g_free (text_ucs4); + + last_shaper = NULL; + last_level = 0; + + i = 0; + p = start = str; + while (*p) + { + gunichar wc = g_utf8_get_char (p); + p = g_utf8_next_char (p); + + shaper = pango_font_find_shaper (font, lang, wc); + if (p > start && + (shaper != last_shaper || last_level != embedding_levels[i])) + { + PangoAnalysis analysis; + int j; + + analysis.shape_engine = shaper; + analysis.lang_engine = NULL; + analysis.font = font; + analysis.level = last_level; + + pango_shape (start, p - start, &analysis, glyph_str); + + for (j = 0; j < glyph_str->num_glyphs; j++) + { + PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph_str->glyphs[j].glyph); + if (!g_slist_find (subfonts, GUINT_TO_POINTER ((guint)subfont_index))) + subfonts = g_slist_prepend (subfonts, GUINT_TO_POINTER ((guint)subfont_index)); + } + + start = p; + } + + last_shaper = shaper; + last_level = embedding_levels[i]; + i++; + } + + get_font_metrics_from_subfonts (font, subfonts, metrics); + g_slist_free (subfonts); + + pango_glyph_string_free (glyph_str); + g_free (embedding_levels); +} + +typedef struct { + const char *lang; + const char *str; +} LangInfo; + +int +lang_info_compare (const void *key, + const void *val) +{ + const LangInfo *lang_info = val; + + return strncmp (key, lang_info->lang, 2); +} + +/* The following array is supposed to contain enough text to tickle all necessary fonts for each + * of the languages in the following. Yes, it's pretty lame. Not all of the languages + * in the following have sufficient text to excercise all the accents for the language, and + * there are obviously many more languages to include as well. + */ +LangInfo lang_texts[] = { + { "ar", "Arabic ا,DXXم عY(JY,CY(B" }, + { "cs", "Czech (česky) Dobrý den" }, + { "da", "Danish (Dansk) Hej, Goddag" }, + { "el", "Greek ($(GN;ληνικά(B) $(CN5ιά ,CNς(B" }, + { "en", "English Hello" }, + { "eo", "Esperanto Saluton" }, + { "es", "Spanish (Español) ¡Hola!" }, + { "et", "Estonian Tere, Tervist" }, + { "fi", "Finnish (Suomi) Hei, Hyvää päivää" }, + { "fr", "French (Français)" }, + { "de", "German Grüß Gott" }, + { "iw", "Hebrew שלום" }, + { "il", "Italiano Ciao, Buon giorno" }, + { "ja", "Japanese (日語) こん, コン,Foハ(B" }, + { "ko", "Korean (한글) ,Hk하,D8요(B, ,Hk하십j(B" }, + { "mt", "Maltese Ċaw, Saħħa" }, + { "nl", "Nederlands, Vlaams Hallo, Dag" }, + { "no", "Norwegian (Norsk) Hei, God dag" }, + { "pl", "Polish Dzień dobry, Hej" }, + { "ru", "Russian (Р,CQкий(B)" }, + { "sk", "Slovak Dobrý deň" }, + { "sv", "Swedish (Svenska) Hej på dej, Goddag" }, + { "tr", "Turkish (Türkçe) Merhaba" }, + { "zh", "Chinese (中文,$(1.i话(B,(Ih(B)" } +}; + +static void +pango_ft2_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics) +{ + PangoFT2MetricsInfo *info; + PangoFT2Font *ft2font = (PangoFT2Font *)font; + GSList *tmp_list; + + const char *lookup_lang; + const char *str; + + if (lang) + { + LangInfo *lang_info = bsearch (lang, lang_texts, + G_N_ELEMENTS (lang_texts), sizeof (LangInfo), + lang_info_compare); + + if (lang_info) + { + lookup_lang = lang_info->lang; + str = lang_info->str; + } + else + { + lookup_lang = "UNKNOWN"; + str = "French (Français)"; /* Assume iso-8859-1 */ + } + } + else + { + lookup_lang = "NONE"; + + /* Complete junk + */ + str = "ا,DXXم عY(JY,CY č(Besky $(GN;ληνικά (BFrançais 日語 한글 Р,CQкий 中文(B,$(1.i话(B,(Ih (BTürkçe"; + } + + tmp_list = ft2font->metrics_by_lang; + while (tmp_list) + { + info = tmp_list->data; + + if (info->lang == lookup_lang) /* We _don't_ need strcmp */ + break; + + tmp_list = tmp_list->next; + } + + if (!tmp_list) + { + info = g_new (PangoFT2MetricsInfo, 1); + info->lang = lookup_lang; + + ft2font->metrics_by_lang = g_slist_prepend (ft2font->metrics_by_lang, info); + + get_font_metrics_from_string (font, lang, str, &info->metrics); + } + + *metrics = info->metrics; +} + +/** + * pango_ft2_n_subfonts: + * @font: a PangoFont + * Returns number of subfonts in a PangoFT2Font. + **/ +int +pango_ft2_n_subfonts (PangoFont *font) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)font; + + g_return_val_if_fail (font != NULL, 0); + + return ft2font->n_fonts; +} + +/** + * pango_ft2_has_glyph: + * @font: a #PangoFont which must be from the FreeType2 backend. + * @glyph: the index of a glyph in the font. (Formed + * using the PANGO_FT2_MAKE_GLYPH macro) + * + * Check if the given glyph is present in a FT2 font. + * + * Return value: %TRUE if the glyph is present. + **/ +gboolean +pango_ft2_has_glyph (PangoFont *font, + PangoGlyph glyph) +{ + guint16 char_index = PANGO_FT2_GLYPH_INDEX (glyph); + PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph); + FT_Face face = pango_ft2_get_face (font, subfont_index); + + if (!face) + return FALSE; + + if (FT_Get_Char_Index (face, char_index) == 0) + return FALSE; + else + return TRUE; +} + +/** + * pango_ft2_font_subfont_open_args: + * @font: a #PangoFont which must be from the FT2 backend + * @open_args: pointer where to store the #FT_Open_Args for this subfont + * @face_index: pointer where to store the face index for this subfont + * + * Determine the FT_Open_Args and face index for the specified subfont. + **/ +void +pango_ft2_font_subfont_open_args (PangoFont *font, + PangoFT2Subfont subfont_id, + FT_Open_Args **open_args, + FT_Long *face_index) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)font; + *open_args = NULL; + *face_index = 0; + + g_return_if_fail (font != NULL); + g_return_if_fail (PANGO_FT2_IS_FONT (font)); + + if (subfont_id < 1 || subfont_id > ft2font->n_fonts) + g_warning ("pango_ft2_font_subfont_open_args: Invalid subfont_id specified"); + else + { + *open_args = ft2font->oa[subfont_id-1]->open_args; + *face_index = ft2font->oa[subfont_id-1]->face_index; + } +} + +static void +pango_ft2_font_shutdown (GObject *object) +{ + PangoFT2Font *ft2font = PANGO_FT2_FONT (object); + + /* If the font is not already in the freed-fonts cache, add it, + * if it is already there, do nothing and the font will be + * freed. + */ + if (!ft2font->in_cache && ft2font->fontmap) + pango_ft2_fontmap_cache_add (ft2font->fontmap, ft2font); + + G_OBJECT_CLASS (parent_class)->shutdown (object); +} + + +static void +pango_ft2_font_finalize (GObject *object) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)object; + PangoFT2FontCache *cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap); + int i; + + PING (("\n")); + + for (i = 0; i < ft2font->n_fonts; i++) + { + if (ft2font->faces[i]) + pango_ft2_font_cache_unload (cache, ft2font->faces[i]); + } + + g_free (ft2font->oa); + g_free (ft2font->faces); + + g_slist_foreach (ft2font->metrics_by_lang, (GFunc)g_free, NULL); + g_slist_free (ft2font->metrics_by_lang); + + if (ft2font->entry) + pango_ft2_font_entry_remove (ft2font->entry, (PangoFont *)ft2font); + + g_object_unref (G_OBJECT (ft2font->fontmap)); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static PangoFontDescription * +pango_ft2_font_describe (PangoFont *font) +{ + /* FIXME: implement */ + return NULL; +} + +PangoMap * +pango_ft2_get_shaper_map (const char *lang) +{ + static guint engine_type_id = 0; + static guint render_type_id = 0; + + if (engine_type_id == 0) + { + engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE); + render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_FT2); + } + + return pango_find_map (lang, engine_type_id, render_type_id); +} + +static PangoCoverage * +pango_ft2_font_get_coverage (PangoFont *font, + const char *lang) +{ + PangoFT2Font *ft2font = (PangoFT2Font *)font; + + return pango_ft2_font_entry_get_coverage (ft2font->entry, font, lang); +} + +static PangoEngineShape * +pango_ft2_font_find_shaper (PangoFont *font, + const gchar *lang, + guint32 ch) +{ + PangoMap *shape_map = NULL; + + shape_map = pango_ft2_get_shaper_map (lang); + return (PangoEngineShape *)pango_map_get_engine (shape_map, ch); +} + +/* Utility functions */ + +/** + * pango_ft2_get_unknown_glyph: + * @font: a #PangoFont + * + * Return the index of a glyph suitable for drawing unknown characters. + * + * Return value: a glyph index into @font + **/ +PangoGlyph +pango_ft2_get_unknown_glyph (PangoFont *font) +{ + return PANGO_FT2_MAKE_GLYPH (1, 0); +} + +/** + * pango_ft2_render_layout_line: + * @line: a #PangoLayoutLine + * @x: the x position of start of string (in pixels) + * @y: the y position of baseline (in pixels) + * + * Render a #PangoLayoutLine onto a FreeType2 bitmap + */ +void +pango_ft2_render_layout_line (FT_Bitmap *bitmap, + PangoLayoutLine *line, + int x, + int y) +{ + GSList *tmp_list = line->runs; + PangoRectangle overall_rect; + PangoRectangle logical_rect; + PangoRectangle ink_rect; + unsigned char *p; + int ix; + int x_off = 0; + int x_limit; + + pango_layout_line_get_extents (line,NULL, &overall_rect); + + while (tmp_list) + { + PangoUnderline uline = PANGO_UNDERLINE_NONE; + PangoLayoutRun *run = tmp_list->data; + PangoAttrColor fg_color, bg_color; + gboolean fg_set, bg_set; + + tmp_list = tmp_list->next; + + pango_ft2_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set); + + if (uline == PANGO_UNDERLINE_NONE) + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + NULL, &logical_rect); + else + pango_glyph_string_extents (run->glyphs, run->item->analysis.font, + &ink_rect, &logical_rect); + + pango_ft2_render (bitmap, run->item->analysis.font, run->glyphs, + x + PANGO_PIXELS (x_off), y); + + x_limit = PANGO_PIXELS (ink_rect.width); + switch (uline) + { + case PANGO_UNDERLINE_NONE: + break; + case PANGO_UNDERLINE_DOUBLE: + p = bitmap->buffer + + (y + 4) * bitmap->pitch + + x + PANGO_PIXELS (x_off + ink_rect.x) - 1; + + /* Don't drawn the underline through descenders */ + for (ix = 0; ix < x_limit; ix++) + if (*p == 0xFF && + (ix == x_limit - 1 || p[1] == 0xFF)) + *p++ = 0; + /* Fall through */ + case PANGO_UNDERLINE_SINGLE: + p = bitmap->buffer + + (y + 2) * bitmap->pitch + + x + PANGO_PIXELS (x_off + ink_rect.x) - 1; + for (ix = 0; ix < x_limit; ix++) + if (*p == 0xFF && + (ix == x_limit - 1 || p[1] == 0xFF)) + *p++ = 0; + break; + case PANGO_UNDERLINE_LOW: + p = bitmap->buffer + + (y + PANGO_PIXELS (ink_rect.y + ink_rect.height)) * bitmap->pitch + + x + PANGO_PIXELS (x_off + ink_rect.x) - 1; + for (ix = 0; ix < PANGO_PIXELS (ink_rect.width); ix++) + *p++ = 0; + break; + } + + x_off += logical_rect.width; + } +} + +/** + * pango_ft2_render_layout: + * @layout: a #PangoLayout + * @x: the X position of the left of the layout (in pixels) + * @y: the Y position of the top of the layout (in pixels) + * + * Render a #PangoLayoutLine onto a FreeType2 bitmap + */ +void +pango_ft2_render_layout (FT_Bitmap *bitmap, + PangoLayout *layout, + int x, + int y) +{ + PangoRectangle logical_rect; + GSList *tmp_list; + PangoAlignment align; + int indent; + int width; + int y_offset = 0; + + gboolean first = FALSE; + + g_return_if_fail (bitmap != NULL); + g_return_if_fail (layout != NULL); + + indent = pango_layout_get_indent (layout); + width = pango_layout_get_width (layout); + align = pango_layout_get_alignment (layout); + + PING (("x:%d y:%d indent:%d width:%d\n", x, y, indent, width)); + + if (width == -1 && align != PANGO_ALIGN_LEFT) + { + pango_layout_get_extents (layout, NULL, &logical_rect); + width = logical_rect.width; + } + + tmp_list = pango_layout_get_lines (layout); + while (tmp_list) + { + PangoLayoutLine *line = tmp_list->data; + int x_offset; + + pango_layout_line_get_extents (line, NULL, &logical_rect); + + if (width != 1 && align == PANGO_ALIGN_RIGHT) + x_offset = width - logical_rect.width; + else if (width != 1 && align == PANGO_ALIGN_CENTER) + x_offset = (width - logical_rect.width) / 2; + else + x_offset = 0; + + if (first) + { + if (indent > 0) + { + if (align == PANGO_ALIGN_LEFT) + x_offset += indent; + else + x_offset -= indent; + } + + first = FALSE; + } + else + { + if (indent < 0) + { + if (align == PANGO_ALIGN_LEFT) + x_offset -= indent; + else + x_offset += indent; + } + } + + PING (("x_offset:%d y_offset:%d logical_rect.y:%d logical_rect.height:%d\n", x_offset, y_offset, logical_rect.y, logical_rect.height)); + + pango_ft2_render_layout_line (bitmap, line, + x + PANGO_PIXELS (x_offset), + y + PANGO_PIXELS (y_offset - logical_rect.y)); + + y_offset += logical_rect.height; + tmp_list = tmp_list->next; + } +} + +/* This utility function is duplicated here and in pango-layout.c; should it be + * public? Trouble is - what is the appropriate set of properties? + */ +static void +pango_ft2_get_item_properties (PangoItem *item, + PangoUnderline *uline, + PangoAttrColor *fg_color, + gboolean *fg_set, + PangoAttrColor *bg_color, + gboolean *bg_set) +{ + GSList *tmp_list = item->extra_attrs; + + if (fg_set) + *fg_set = FALSE; + + if (bg_set) + *bg_set = FALSE; + + while (tmp_list) + { + PangoAttribute *attr = tmp_list->data; + + switch (attr->klass->type) + { + case PANGO_ATTR_UNDERLINE: + if (uline) + *uline = ((PangoAttrInt *)attr)->value; + break; + + case PANGO_ATTR_FOREGROUND: + if (fg_color) + *fg_color = *((PangoAttrColor *)attr); + if (fg_set) + *fg_set = TRUE; + + break; + + case PANGO_ATTR_BACKGROUND: + if (bg_color) + *bg_color = *((PangoAttrColor *)attr); + if (bg_set) + *bg_set = TRUE; + + break; + + default: + break; + } + tmp_list = tmp_list->next; + } +} + +typedef struct +{ + FT_Error code; + const char* msg; +} ft_error_description; + +static int +ft_error_compare (const void *pkey, + const void *pbase) +{ + return ((ft_error_description *) pkey)->code - ((ft_error_description *) pbase)->code; +} + +const char * +pango_ft2_ft_strerror (FT_Error error) +{ +#undef FTERRORS_H +#define FT_ERRORDEF( e, v, s ) { e, s }, +#define FT_ERROR_START_LIST { +#define FT_ERROR_END_LIST { 0, 0 } } + + const ft_error_description ft_errors[] = +#include <freetype/fterrors.h> + ; + +#undef FT_ERRORDEF +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST + + ft_error_description *found = + bsearch (&error, ft_errors, G_N_ELEMENTS (ft_errors) - 1, + sizeof (ft_errors[0]), ft_error_compare); + if (found != NULL) + return found->msg; + else + { + static char default_msg[100]; + + sprintf (default_msg, "Unknown FreeType2 error %#x", error); + return default_msg; + } +} diff --git a/pango/pangoft2.h b/pango/pangoft2.h new file mode 100644 index 00000000..ededcbc9 --- /dev/null +++ b/pango/pangoft2.h @@ -0,0 +1,107 @@ +/* Pango + * pangoft2.h: + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __PANGOFT2_H__ +#define __PANGOFT2_H__ + +#include <glib.h> +#include <pango/pango.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <freetype/freetype.h> + +#define PANGO_RENDER_TYPE_FT2 "PangoRenderFT2" + +/* Calls for applications + */ +PangoContext *pango_ft2_get_context (void); + +PangoFont *pango_ft2_load_font (PangoFontMap *fontmap, + FT_Open_Args **args, + FT_Long *face_indices, + int n_fonts, + int size); +void pango_ft2_render (FT_Bitmap *bitmap, + PangoFont *font, + PangoGlyphString *glyphs, + gint x, + gint y); +void pango_ft2_render_layout_line (FT_Bitmap *bitmap, + PangoLayoutLine *line, + int x, + int y); +void pango_ft2_render_layout (FT_Bitmap *bitmap, + PangoLayout *layout, + int x, + int y); + + +/* API for rendering modules + */ +typedef guint16 PangoFT2Subfont; + +#define PANGO_FT2_MAKE_GLYPH(subfont,index) ((subfont)<<16 | (index)) +#define PANGO_FT2_GLYPH_SUBFONT(glyph) ((glyph)>>16) +#define PANGO_FT2_GLYPH_INDEX(glyph) ((glyph) & 0xFFFF) + +int pango_ft2_n_subfonts (PangoFont *font); +gboolean pango_ft2_has_glyph (PangoFont *font, + PangoGlyph glyph); +PangoGlyph pango_ft2_get_unknown_glyph (PangoFont *font); +int pango_ft2_font_get_kerning (PangoFont *font, + PangoGlyph left, + PangoGlyph right); + +/* API for libraries that want to use PangoFT2 mixed with classic + * FT2 fonts. + */ +typedef struct _PangoFT2FontCache PangoFT2FontCache; + +PangoFT2FontCache *pango_ft2_font_cache_new (FT_Library library); +void pango_ft2_font_cache_free (PangoFT2FontCache *cache); +FT_Face pango_ft2_font_cache_load (PangoFT2FontCache *cache, + FT_Open_Args *args, + FT_Long face_index); +void pango_ft2_font_cache_unload (PangoFT2FontCache *cache, + FT_Face face); +PangoFontMap *pango_ft2_font_map_for_display (void); +void pango_ft2_shutdown_display (void); +PangoFT2FontCache *pango_ft2_font_map_get_font_cache (PangoFontMap *font_map); +void pango_ft2_font_subfont_open_args (PangoFont *font, + PangoFT2Subfont subfont_id, + FT_Open_Args **open_args, + FT_Long *face_index); + + +/* Debugging. + */ +void pango_ft2_fontmap_dump (int indent, + PangoFontMap *fontmap); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __PANGOFT2_H__ */ diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index 86565d26..3f9caa2d 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -53,7 +53,12 @@ struct _PangoWin32FontMap PangoWin32FontCache *font_cache; GQueue *freed_fonts; + /* Map Pango family names tp PangoWin32FamilyEntry structs */ GHashTable *families; + + /* Map LOGFONTS (taking into account only the lfFaceName, lfItalic + * and lfWeight fields) to PangoWin32SizeInfo structs. + */ GHashTable *size_infos; int n_fonts; @@ -88,18 +93,9 @@ struct _PangoWin32SizeInfo GSList *logfonts; }; -const struct { - const gchar *text; - PangoStretch value; -} stretches_map[] = { - { "normal", PANGO_STRETCH_NORMAL }, - { "semicondensed", PANGO_STRETCH_SEMI_CONDENSED }, - { "condensed", PANGO_STRETCH_CONDENSED }, -}; - -static GType pango_win32_font_map_get_type (void); -static void pango_win32_font_map_init (PangoWin32FontMap *fontmap); -static void pango_win32_font_map_class_init (PangoWin32FontMapClass *class); +static GType pango_win32_font_map_get_type (void); +static void pango_win32_font_map_init (PangoWin32FontMap *fontmap); +static void pango_win32_font_map_class_init (PangoWin32FontMapClass *class); static void pango_win32_font_map_finalize (GObject *object); static PangoFont *pango_win32_font_map_load_font (PangoFontMap *fontmap, @@ -111,12 +107,12 @@ static void pango_win32_font_map_list_fonts (PangoFontMap static void pango_win32_font_map_list_families (PangoFontMap *fontmap, gchar ***families, int *n_families); - -static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap); -static void pango_win32_font_map_read_aliases (PangoWin32FontMap *win32fontmap); - -static void pango_win32_insert_font (PangoWin32FontMap *fontmap, - LOGFONT *lfp); + +static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap); +static void pango_win32_font_map_read_aliases (PangoWin32FontMap *win32fontmap); + +static void pango_win32_insert_font (PangoWin32FontMap *fontmap, + LOGFONT *lfp); static PangoFontClass *parent_class; /* Parent class structure for PangoWin32FontMap */ @@ -226,7 +222,7 @@ pango_win32_enum_proc (LOGFONT *lfp, lf = *lfp; - EnumFontFamiliesEx (pango_win32_hdc, &lf, pango_win32_inner_enum_proc, lParam, 0); + EnumFontFamiliesEx (pango_win32_hdc, &lf, (FONTENUMPROC) pango_win32_inner_enum_proc, lParam, 0); return 1; } @@ -250,7 +246,7 @@ pango_win32_font_map_for_display (void) memset (&logfont, 0, sizeof (logfont)); logfont.lfCharSet = DEFAULT_CHARSET; - EnumFontFamiliesEx (pango_win32_hdc, &logfont, pango_win32_enum_proc, 0, 0); + EnumFontFamiliesEx (pango_win32_hdc, &logfont, (FONTENUMPROC) pango_win32_enum_proc, 0, 0); pango_win32_font_map_read_aliases (fontmap); @@ -270,12 +266,8 @@ pango_win32_font_map_for_display (void) void pango_win32_shutdown_display (void) { - GList *tmp_list; - pango_win32_fontmap_cache_clear (fontmap); g_object_unref (G_OBJECT (fontmap)); - - return; } static void @@ -289,6 +281,7 @@ pango_win32_font_map_finalize (GObject *object) pango_win32_font_cache_free (win32fontmap->font_cache); /* ??? */ + G_OBJECT_CLASS (parent_class)->finalize (object); } typedef struct @@ -298,7 +291,9 @@ typedef struct } ListFontsInfo; static void -list_fonts_foreach (gpointer key, gpointer value, gpointer user_data) +list_fonts_foreach (gpointer key, + gpointer value, + gpointer user_data) { PangoWin32FamilyEntry *entry = value; ListFontsInfo *info = user_data; @@ -364,7 +359,9 @@ pango_win32_font_map_list_fonts (PangoFontMap *fontmap, } static void -list_families_foreach (gpointer key, gpointer value, gpointer user_data) +list_families_foreach (gpointer key, + gpointer value, + gpointer user_data) { GSList **list = user_data; @@ -372,9 +369,9 @@ list_families_foreach (gpointer key, gpointer value, gpointer user_data) } static void -pango_win32_font_map_list_families (PangoFontMap *fontmap, - gchar ***families, - int *n_families) +pango_win32_font_map_list_families (PangoFontMap *fontmap, + gchar ***families, + int *n_families) { GSList *family_list = NULL; GSList *tmp_list; @@ -931,7 +928,7 @@ pango_win32_guess_subranges (UINT charset, return retval; } -static gboolean +static void pango_win32_setup_signature (PangoWin32FontMap *win32fontmap, LOGFONT *lfp, FONTSIGNATURE *sigp) @@ -940,7 +937,6 @@ pango_win32_setup_signature (PangoWin32FontMap *win32fontmap, HFONT hfont; HGDIOBJ oldfont; int charset; - int i; logfont = *lfp; logfont.lfHeight = 40; @@ -948,11 +944,11 @@ pango_win32_setup_signature (PangoWin32FontMap *win32fontmap, &logfont); if (!hfont) { - g_warning ("font \"%s\" (%sweight:%d) not available", + g_warning ("font \"%s\" (%sweight:%ld) not available", + logfont.lfFaceName, (logfont.lfItalic ? "italic," : ""), - logfont.lfWeight, - logfont.lfFaceName); - return FALSE; + logfont.lfWeight); + return; } oldfont = SelectObject (pango_win32_hdc, hfont); memset (sigp, 0, sizeof (*sigp)); @@ -969,9 +965,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap, PangoWin32FontEntry *font_entry = NULL; FILE *infile; char **faces; - char *buf = NULL; int lineno = 0; - int charset; int nfaces; int i; @@ -1002,25 +996,25 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap, if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_style (tmp_buf, &font_entry->description)) + if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_variant (tmp_buf, &font_entry->description)) + if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_weight (tmp_buf, &font_entry->description)) + if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_stretch (tmp_buf, &font_entry->description)) + if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) @@ -1030,7 +1024,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap, faces = g_strsplit (tmp_buf->str, ",", -1); nfaces = 0; - for (i=0; faces[i]; i++) + for (i = 0; faces[i]; i++) { char *trimmed = pango_trim_string (faces[i]); g_free (faces[i]); @@ -1039,7 +1033,7 @@ pango_win32_font_map_read_alias_file (PangoWin32FontMap *win32fontmap, } font_entry->lfp = g_new0 (LOGFONT, nfaces); font_entry->n_fonts = nfaces; - for (i=0; i<nfaces; i++) + for (i = 0; i < nfaces; i++) { strcpy (font_entry->lfp[i].lfFaceName, faces[i]); @@ -1165,9 +1159,8 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, PangoWin32FamilyEntry *family_entry; PangoWin32FontEntry *font_entry; PangoWin32SizeInfo *size_info; - int i; - PING(("lfp.face=%s,wt=%d,ht=%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight)); + PING(("lfp.face=%s,wt=%ld,ht=%ld",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight)); description.size = 0; /* First insert the LOGFONT into the list of LOGFONTs for the typeface name @@ -1251,19 +1244,6 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, win32fontmap->n_fonts++; } -/* Compare the tail of a to b */ -static gboolean -match_end (char *a, char *b) -{ - size_t len_a = strlen (a); - size_t len_b = strlen (b); - - if (len_b > len_a) - return FALSE; - else - return (strcmp (a + len_a - len_b, b) == 0); -} - gboolean pango_win32_logfont_has_subrange (PangoFontMap *fontmap, LOGFONT *lfp, @@ -1298,7 +1278,7 @@ pango_win32_make_matching_logfont (PangoFontMap *fontmap, LOGFONT *result = NULL; gint match_distance = 0; - PING(("lfp.face=%s,wt=%d,ht=%d,size:%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight,size)); + PING(("lfp.face=%s,wt=%ld,ht=%ld,size:%d",lfp->lfFaceName,lfp->lfWeight,lfp->lfHeight,size)); win32fontmap = PANGO_WIN32_FONT_MAP (fontmap); size_info = g_hash_table_lookup (win32fontmap->size_infos, lfp); @@ -1487,7 +1467,7 @@ pango_win32_font_entry_dump (int indent, indent, "", font_entry, indent, ""); - for (i=0; i<font_entry->n_fonts; i++) + for (i = 0; i < font_entry->n_fonts; i++) printf ("%*s LOGFONT:%s\n", indent, "", font_entry->lfp[i].lfFaceName); @@ -1530,7 +1510,9 @@ pango_win32_family_entry_dump (int indent, } static void -dump_family (gpointer key, gpointer value, gpointer user_data) +dump_family (gpointer key, + gpointer value, + gpointer user_data) { PangoWin32FamilyEntry *entry = value; int indent = (int) user_data; diff --git a/pango/pangowin32.c b/pango/pangowin32.c index d5e6663f..9bf2a026 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -90,18 +90,22 @@ static void pango_win32_font_shutdown (GObject *object); static void pango_win32_font_finalize (GObject *object); static PangoFontDescription *pango_win32_font_describe (PangoFont *font); + static PangoCoverage *pango_win32_font_get_coverage (PangoFont *font, const char *lang); + static PangoEngineShape *pango_win32_font_find_shaper (PangoFont *font, const char *lang, guint32 ch); -static void pango_win32_font_get_glyph_extents (PangoFont *font, - PangoGlyph glyph, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); -static void pango_win32_font_get_metrics (PangoFont *font, - const gchar *lang, - PangoFontMetrics *metrics); + +static void pango_win32_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); + +static void pango_win32_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics); static PangoWin32SubfontInfo *pango_win32_find_subfont (PangoFont *font, PangoWin32Subfont subfont_index); @@ -110,9 +114,11 @@ static gboolean pango_win32_find_glyph (PangoFont *font, PangoGlyph glyph, PangoWin32SubfontInfo **subfont_return, SIZE *size_return); + static HFONT pango_win32_get_hfont (PangoFont *font, PangoWin32SubfontInfo *info); + static void pango_win32_get_item_properties (PangoItem *item, PangoUnderline *uline, PangoAttrColor *fg_color, @@ -540,6 +546,8 @@ pango_win32_unicode_classify (wchar_t wc) else return -1; } + /* NOTREACHED */ + return 0; } static void @@ -867,7 +875,7 @@ pango_win32_list_subfonts (PangoFont *font, LOGFONT *lfp; PangoWin32Font *win32font = (PangoWin32Font *)font; PangoWin32Subfont *subfont_list; - int i, j; + int i; int n_subfonts; g_return_val_if_fail (font != NULL, 0); @@ -985,7 +993,7 @@ subfont_has_glyph (PangoFont *font, info->oldfont = SelectObject (info->buf_hdc, info->hfont); SetTextAlign (info->buf_hdc, TA_LEFT|TA_BASELINE|TA_NOUPDATECP); GetTextMetrics (info->buf_hdc, &tm); - PING(("wt:%d,ht:%d",tm.tmMaxCharWidth,tm.tmHeight)); + PING(("wt:%ld,ht:%ld",tm.tmMaxCharWidth,tm.tmHeight)); info->default_char_hbm = create_bitmap_dibsection (info->buf_hdc, &info->default_char_buf, @@ -1279,7 +1287,6 @@ pango_win32_render_layout_line (HDC hdc, PangoRectangle overall_rect; PangoRectangle logical_rect; PangoRectangle ink_rect; - PangoContext *context = pango_layout_get_context (line->layout); int x_off = 0; diff --git a/pango/pangowin32.h b/pango/pangowin32.h index 7d040f5b..64275185 100644 --- a/pango/pangowin32.h +++ b/pango/pangowin32.h @@ -34,7 +34,32 @@ extern "C" { #define PANGO_RENDER_TYPE_WIN32 "PangoRenderWin32" -/* This enum divides Unicode characters according to the Microsoft +/* Calls for applications + */ +PangoContext * pango_win32_get_context (void); + +PangoFont * pango_win32_load_font (LOGFONT *lfp, + int n_fonts); +void pango_win32_render (HDC hdc, + PangoFont *font, + PangoGlyphString *glyphs, + gint x, + gint y); +void pango_win32_render_layout_line (HDC hdc, + PangoLayoutLine *line, + int x, + int y); +void pango_win32_render_layout (HDC hdc, + PangoLayout *layout, + int x, + int y); + + + +/* API for rendering modules + */ + +/* This enum classifies Unicode characters according to the Microsoft * Unicode subrange numbering. This is based on the table in "Developing * International Software for Windows 95 and Windows NT". This is almost, * but not quite, the same as the official Unicode block table in @@ -115,69 +140,45 @@ typedef enum PANGO_WIN32_U_LAST_PLUS_ONE } PangoWin32UnicodeSubrange; -/* Calls for applications - */ -PangoContext * pango_win32_get_context (void); - -PangoFont * pango_win32_load_font (LOGFONT *lfp, - int n_fonts); -void pango_win32_render (HDC hdc, - PangoFont *font, - PangoGlyphString *glyphs, - gint x, - gint y); -void pango_win32_render_layout_line (HDC hdc, - PangoLayoutLine *line, - int x, - int y); -void pango_win32_render_layout (HDC hdc, - PangoLayout *layout, - int x, - int y); - - +PangoWin32UnicodeSubrange pango_win32_unicode_classify (wchar_t wc); -/* API for rendering modules - */ typedef guint16 PangoWin32Subfont; #define PANGO_WIN32_MAKE_GLYPH(subfont,index) ((subfont)<<16 | (index)) #define PANGO_WIN32_GLYPH_SUBFONT(glyph) ((glyph)>>16) #define PANGO_WIN32_GLYPH_INDEX(glyph) ((glyph) & 0xffff) -int pango_win32_list_subfonts (PangoFont *font, - PangoWin32UnicodeSubrange subrange, - PangoWin32Subfont **subfont_ids); -gboolean pango_win32_has_glyph (PangoFont *font, - PangoGlyph glyph); -PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font); - -PangoWin32UnicodeSubrange pango_win32_unicode_classify (wchar_t wc); +int pango_win32_list_subfonts (PangoFont *font, + PangoWin32UnicodeSubrange subrange, + PangoWin32Subfont **subfont_ids); +gboolean pango_win32_has_glyph (PangoFont *font, + PangoGlyph glyph); +PangoGlyph pango_win32_get_unknown_glyph (PangoFont *font); /* API for libraries that want to use PangoWin32 mixed with classic * Win32 fonts. */ typedef struct _PangoWin32FontCache PangoWin32FontCache; -PangoWin32FontCache *pango_win32_font_cache_new (void); -void pango_win32_font_cache_free (PangoWin32FontCache *cache); - -HFONT pango_win32_font_cache_load (PangoWin32FontCache *cache, - const LOGFONT *lfp); -void pango_win32_font_cache_unload (PangoWin32FontCache *cache, - HFONT hfont); +PangoWin32FontCache *pango_win32_font_cache_new (void); +void pango_win32_font_cache_free (PangoWin32FontCache *cache); + +HFONT pango_win32_font_cache_load (PangoWin32FontCache *cache, + const LOGFONT *lfp); +void pango_win32_font_cache_unload (PangoWin32FontCache *cache, + HFONT hfont); -PangoFontMap * pango_win32_font_map_for_display (void); -void pango_win32_shutdown_display (void); -PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *font_map); +PangoFontMap *pango_win32_font_map_for_display (void); +void pango_win32_shutdown_display (void); +PangoWin32FontCache *pango_win32_font_map_get_font_cache (PangoFontMap *font_map); -LOGFONT *pango_win32_font_subfont_logfont (PangoFont *font, - PangoWin32Subfont subfont_id); +LOGFONT *pango_win32_font_subfont_logfont (PangoFont *font, + PangoWin32Subfont subfont_id); /* Debugging. */ -void pango_win32_fontmap_dump (int indent, - PangoFontMap *fontmap); +void pango_win32_fontmap_dump (int indent, + PangoFontMap *fontmap); #ifdef __cplusplus } diff --git a/pango/pangox-fontmap.c b/pango/pangox-fontmap.c index 34a0cc3f..4a92c816 100644 --- a/pango/pangox-fontmap.c +++ b/pango/pangox-fontmap.c @@ -853,25 +853,25 @@ pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap, if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_style (tmp_buf, &font_entry->description)) + if (!pango_parse_style (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_variant (tmp_buf, &font_entry->description)) + if (!pango_parse_variant (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_weight (tmp_buf, &font_entry->description)) + if (!pango_parse_weight (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) goto error; - if (!pango_parse_stretch (tmp_buf, &font_entry->description)) + if (!pango_parse_stretch (tmp_buf, &font_entry->description, TRUE)) goto error; if (!pango_scan_string (&p, tmp_buf)) |