comparison src/font-mgr.c @ 4758:75975fd0b7fc

Implement more of the fontconfig API. Improve implementation, avoiding nonsyntactic macros and compiler warnings. Clean up some documentation. Guard against freeing NULL pointers returned from fonconfig.
author Stephen J. Turnbull <stephen@xemacs.org>
date Wed, 18 Nov 2009 22:44:28 +0900
parents a23ac8f90a49
children ca99a807b025 e0db3c197671
comparison
equal deleted inserted replaced
4757:a23ac8f90a49 4758:75975fd0b7fc
1 /* Lisp font handling implementation for X with Xft. 1 /* Lisp font handling implementation for X with Xft.
2 2
3 Copyright (C) 2003 Eric Knauel and Matthias Neubauer 3 Copyright (C) 2003 Eric Knauel and Matthias Neubauer
4 Copyright (C) 2005 Eric Knauel 4 Copyright (C) 2005 Eric Knauel
5 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 5 Copyright (C) 2004-2009 Free Software Foundation, Inc.
6 6
7 Authors: Eric Knauel <knauel@informatik.uni-tuebingen.de> 7 Authors: Eric Knauel <knauel@informatik.uni-tuebingen.de>
8 Matthias Neubauer <neubauer@informatik.uni-freiburg.de> 8 Matthias Neubauer <neubauer@informatik.uni-freiburg.de>
9 Stephen J. Turnbull <stephen@xemacs.org> 9 Stephen J. Turnbull <stephen@xemacs.org>
10 Created: 27 Oct 2003 10 Created: 27 Oct 2003
11 Updated: 14 April 2007 by Stephen J. Turnbull 11 Updated: 18 November 2009 by Stephen J. Turnbull
12 12
13 This file is part of XEmacs. 13 This file is part of XEmacs.
14 14
15 XEmacs is free software; you can redistribute it and/or modify it 15 XEmacs is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by the 16 under the terms of the GNU General Public License as published by the
72 /* Lisp_Object Qfc_result_match; */ /* FcResultMatch */ 72 /* Lisp_Object Qfc_result_match; */ /* FcResultMatch */
73 Lisp_Object Qfc_result_type_mismatch; /* FcResultTypeMismatch */ 73 Lisp_Object Qfc_result_type_mismatch; /* FcResultTypeMismatch */
74 Lisp_Object Qfc_result_no_match; /* FcResultNoMatch */ 74 Lisp_Object Qfc_result_no_match; /* FcResultNoMatch */
75 Lisp_Object Qfc_result_no_id; /* FcResultNoId */ 75 Lisp_Object Qfc_result_no_id; /* FcResultNoId */
76 Lisp_Object Qfc_internal_error; 76 Lisp_Object Qfc_internal_error;
77 Lisp_Object Qfc_match_pattern;
78 Lisp_Object Qfc_match_font;
77 Lisp_Object Vxlfd_font_name_regexp; /* #### Really needed? */ 79 Lisp_Object Vxlfd_font_name_regexp; /* #### Really needed? */
78 Fixnum xft_version; 80 Fixnum xft_version;
79 Fixnum fc_version; 81 Fixnum fc_version;
80 Fixnum debug_xft; /* Set to 1 enables lots of obnoxious messages. 82 Fixnum debug_xft; /* Set to 1 enables lots of obnoxious messages.
81 Setting it to 2 or 3 enables even more. */ 83 Setting it to 2 or 3 enables even more. */
487 default: 489 default:
488 return Qfc_internal_error; 490 return Qfc_internal_error;
489 } 491 }
490 } 492 }
491 493
492 DEFUN("fc-font-match", Ffc_font_match, 2, 2, 0, /* 494 /* FcConfig handling functions. */
493 Return the font on DEVICE that most closely matches PATTERN. 495
494 496 /* We obviously need to be careful about garbage collecting the current
495 DEVICE is an X11 device. 497 FcConfig. I infer from the documentation of FcConfigDestroy that that
496 PATTERN is a fontconfig pattern object. 498 is the only reference maintained by fontconfig.
497 Returns a fontconfig pattern object representing the closest match to the 499 So we keep track of our own references on a weak list, and only cons a
498 given pattern, or an error code. Possible error codes are 500 new object if we don't already have a reference to it there. */
499 `fc-result-no-match' and `fc-result-no-id'. */ 501
500 (device, pattern)) 502 enum DestroyFontsetP { DestroyNo = 0, DestroyYes = 1 };
501 { 503
502 FcResult res; 504 static Lisp_Object
503 struct fc_pattern *res_fcpat; 505 fc_config_create_using (FcConfig * (*create_function) ())
504 506 {
505 CHECK_FCPATTERN(pattern); 507 FcConfig *fc = (*create_function) ();
506 if (NILP(device)) 508 Lisp_Object configs = XWEAK_LIST_LIST (Vfc_config_weak_list);
509
510 /* Linear search: fc_configs are not going to multiply like conses. */
511 {
512 LIST_LOOP_2 (cfg, configs)
513 if (fc == XFCCONFIG_PTR (cfg))
514 return cfg;
515 }
516
517 {
518 fc_config *fccfg =
519 ALLOC_LCRECORD_TYPE (struct fc_config, &lrecord_fc_config);
520 fccfg->fccfgPtr = fc;
521 configs = Fcons (wrap_fcconfig (fccfg), configs);
522 XWEAK_LIST_LIST (Vfc_config_weak_list) = configs;
523 return wrap_fcconfig (fccfg);
524 }
525 }
526
527 static Lisp_Object
528 fc_strlist_to_lisp_using (FcStrList * (*getter) (FcConfig *),
529 Lisp_Object config)
530 {
531 FcChar8 *thing;
532 Lisp_Object value = Qnil;
533 FcStrList *thing_list;
534
535 CHECK_FCCONFIG (config);
536 thing_list = (*getter) (XFCCONFIG_PTR(config));
537 /* Yes, we need to do this check -- sheesh, Keith! */
538 if (!thing_list)
507 return Qnil; 539 return Qnil;
508 CHECK_X_DEVICE(device); 540 while ((thing = FcStrListNext (thing_list)))
509 if (!DEVICE_LIVE_P(XDEVICE(device))) 541 value = Fcons (build_fcapi_string (thing), value);
510 return Qnil; 542 FcStrListDone (thing_list);
511 543 return value;
512 res_fcpat = ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern); 544 }
513 {
514 FcPattern *p = XFCPATTERN_PTR(pattern);
515 FcConfig *fcc = FcConfigGetCurrent ();
516
517 FcConfigSubstitute (fcc, p, FcMatchPattern);
518 FcDefaultSubstitute (p);
519 res_fcpat->fcpatPtr = FcFontMatch (fcc, p, &res);
520 }
521
522 if (res_fcpat->fcpatPtr == NULL)
523 switch (res) {
524 case FcResultNoMatch:
525 return Qfc_result_no_match;
526 case FcResultNoId:
527 return Qfc_result_no_id;
528 default:
529 return Qfc_internal_error;
530 }
531 else
532 return wrap_fcpattern(res_fcpat);
533 }
534
535 enum DestroyFontsetP { DestroyNo = 0, DestroyYes = 1 };
536 545
537 static Lisp_Object 546 static Lisp_Object
538 fontset_to_list (FcFontSet *fontset, enum DestroyFontsetP destroyp) 547 fontset_to_list (FcFontSet *fontset, enum DestroyFontsetP destroyp)
539 { 548 {
540 int idx; 549 int idx;
555 if (destroyp) 564 if (destroyp)
556 FcFontSetDestroy (fontset); 565 FcFontSetDestroy (fontset);
557 return fontlist; 566 return fontlist;
558 } 567 }
559 568
560 /* #### fix this name to correspond to Ben's new nomenclature */
561 DEFUN("fc-list-fonts-pattern-objects", Ffc_list_fonts_pattern_objects,
562 3, 3, 0, /*
563 Return a list of fonts on DEVICE that match PATTERN for PROPERTIES.
564 Each font is represented by a fontconfig pattern object.
565
566 DEVICE is an X11 device.
567 PATTERN is a fontconfig pattern to be matched.
568 PROPERTIES is a list of property names (strings) that should match.
569
570 #### DEVICE is unused, ignored, and may be removed if it's not needed to
571 match other font-listing APIs. */
572 (UNUSED (device), pattern, properties))
573 {
574 FcObjectSet *os;
575 FcFontSet *fontset;
576
577 CHECK_FCPATTERN (pattern);
578 CHECK_LIST (properties);
579
580 os = FcObjectSetCreate ();
581 string_list_to_fcobjectset (properties, os);
582 /* #### why don't we need to do the "usual substitutions"? */
583 fontset = FcFontList (NULL, XFCPATTERN_PTR (pattern), os);
584 FcObjectSetDestroy (os);
585
586 return fontset_to_list (fontset, DestroyYes);
587
588 }
589
590 /* #### maybe this can/should be folded into fc-list-fonts-pattern-objects? */
591 DEFUN("fc-font-sort", Ffc_font_sort, 2, 4, 0, /*
592 Return a list of all fonts sorted by proximity to PATTERN.
593 Each font is represented by a fontconfig pattern object.
594
595 DEVICE is an X11 device.
596 PATTERN is a fontconfig pattern to be matched.
597 Optional argument TRIM, if non-nil, means to trim trailing fonts that do not
598 contribute new characters to the union repertoire.
599
600 #### Optional argument NOSUB, if non-nil, suppresses some of the usual
601 property substitutions. DON'T USE THIS in production code, it is intended
602 for exploring behavior of fontconfig and will be removed when this code is
603 stable.
604
605 #### DEVICE is unused, ignored, and may be removed if it's not needed to
606 match other font-listing APIs. */
607 (UNUSED (device), pattern, trim, nosub))
608 {
609 CHECK_FCPATTERN (pattern);
610
611 {
612 FcConfig *fcc = FcConfigGetCurrent();
613 FcFontSet *fontset;
614 FcPattern *p = XFCPATTERN_PTR (pattern);
615 FcResult fcresult;
616
617 if (NILP(nosub)) /* #### temporary debug hack */
618 FcDefaultSubstitute (p);
619 FcConfigSubstitute (fcc, p, FcMatchPattern);
620 fontset = FcFontSort (fcc, p, !NILP(trim), NULL, &fcresult);
621
622 return fontset_to_list (fontset, DestroyYes);
623 }
624 }
625
626 #ifdef FONTCONFIG_EXPOSE_CONFIG
627
628 /* Configuration routines --- for debugging
629 Don't depend on these routines being available in the future!
630
631 3.2.10 Initialization
632 ---------------------
633
634 An FcConfig object holds the internal representation of a configuration.
635 There is a default configuration which applications may use by passing
636 0 to any function using the data within an FcConfig.
637 */
638
639 static void
640 finalize_fc_config (void *header, int UNUSED (for_disksave))
641 {
642 struct fc_config *p = (struct fc_config *) header;
643 if (p->fccfgPtr && p->fccfgPtr != FcConfigGetCurrent())
644 {
645 /* If we get here, all of *our* references are garbage (see comment on
646 fc_config_create_using() for why), and the only reference that
647 fontconfig keeps is the current FcConfig. */
648 FcConfigDestroy (p->fccfgPtr);
649 }
650 p->fccfgPtr = 0;
651 }
652
653 static void
654 print_fc_config (Lisp_Object obj, Lisp_Object printcharfun,
655 int UNUSED(escapeflag))
656 {
657 struct fc_config *c = XFCCONFIG (obj);
658 if (print_readably)
659 printing_unreadable_object ("#<fc-config 0x%x>", c->header.uid);
660 write_fmt_string (printcharfun, "#<fc-config 0x%x>", c->header.uid);
661 }
662
663 static const struct memory_description fcconfig_description [] = {
664 /* #### nothing here, is this right?? */
665 { XD_END }
666 };
667
668 DEFINE_LRECORD_IMPLEMENTATION("fc-config", fc_config, 0,
669 0, print_fc_config, finalize_fc_config, 0, 0,
670 fcconfig_description,
671 struct fc_config);
672
673 /* We obviously need to be careful about garbage collecting the current
674 FcConfig. I infer from the documentation of FcConfigDestroy that that
675 is the only reference maintained by fontconfig.
676 So we keep track of our own references on a weak list, and only cons a
677 new object if we don't already have a reference to it there. */
678
679 static Lisp_Object
680 fc_config_create_using (FcConfig * (*create_function) ())
681 {
682 FcConfig *fc = (*create_function) ();
683 Lisp_Object configs = XWEAK_LIST_LIST (Vfc_config_weak_list);
684
685 /* Linear search: fc_configs are not going to multiply like conses. */
686 {
687 LIST_LOOP_2 (cfg, configs)
688 if (fc == XFCCONFIG_PTR (cfg))
689 return cfg;
690 }
691
692 {
693 fc_config *fccfg =
694 ALLOC_LCRECORD_TYPE (struct fc_config, &lrecord_fc_config);
695 fccfg->fccfgPtr = fc;
696 configs = Fcons (wrap_fcconfig (fccfg), configs);
697 XWEAK_LIST_LIST (Vfc_config_weak_list) = configs;
698 return wrap_fcconfig (fccfg);
699 }
700 }
701
702 DEFUN("fc-config-p", Ffc_config_p, 1, 1, 0, /* 569 DEFUN("fc-config-p", Ffc_config_p, 1, 1, 0, /*
703 Returns t if OBJECT is of type fc-config, nil otherwise. 570 Returns t if OBJECT is of type fc-config, nil otherwise.
704 */ 571 */
705 (object)) 572 (object))
706 { 573 {
725 FcConfigGetCurrent will place the library in an indeterminate 592 FcConfigGetCurrent will place the library in an indeterminate
726 state. */ 593 state. */
727 (config)) 594 (config))
728 { 595 {
729 signal_error (Qunimplemented, "No user-servicable parts!", 596 signal_error (Qunimplemented, "No user-servicable parts!",
730 intern ("fc-config-destroy"); 597 intern ("fc-config-destroy"));
731 } 598 }
732 #endif 599 #endif
733
734 DEFUN("fc-config-get-current", Ffc_config_get_current, 0, 0, 0, /*
735 -- Function: FcConfig *FcConfigGetCurrent (void)
736 Returns the current default configuration. */
737 ())
738 {
739 return fc_config_create_using (&FcConfigGetCurrent);
740 }
741 600
742 DEFUN("fc-config-up-to-date", Ffc_config_up_to_date, 1, 1, 0, /* 601 DEFUN("fc-config-up-to-date", Ffc_config_up_to_date, 1, 1, 0, /*
743 -- Function: FcBool FcConfigUptoDate (FcConfig *config) 602 -- Function: FcBool FcConfigUptoDate (FcConfig *config)
744 Checks all of the files related to 'config' and returns whether the 603 Checks all of the files related to 'config' and returns whether the
745 in-memory version is in sync with the disk version. */ 604 in-memory version is in sync with the disk version. */
762 if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse) 621 if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse)
763 out_of_memory ("FcConfigBuildFonts failed", config); 622 out_of_memory ("FcConfigBuildFonts failed", config);
764 return Qnil; 623 return Qnil;
765 } 624 }
766 625
767 /* Calls its argument on `config', which must be defined by the caller. */
768
769 #define FCSTRLIST_TO_LISP_USING(source) do { \
770 FcChar8 *thing; \
771 FcStrList *thing_list; \
772 Lisp_Object value = Qnil; \
773 CHECK_FCCONFIG (config); \
774 thing_list = source (XFCCONFIG_PTR(config)); \
775 /* Yes, we need to do this check -- sheesh, Keith! */ \
776 if (!thing_list) \
777 return Qnil; \
778 while ((thing = FcStrListNext (thing_list))) \
779 value = Fcons (build_fcapi_string (thing), value); \
780 FcStrListDone (thing_list); \
781 return value; \
782 } while (0)
783
784 DEFUN("fc-config-get-config-dirs", Ffc_config_get_config_dirs, 1, 1, 0, /* 626 DEFUN("fc-config-get-config-dirs", Ffc_config_get_config_dirs, 1, 1, 0, /*
785 -- Function: FcStrList *FcConfigGetConfigDirs (FcConfig *config) 627 -- Function: FcStrList *FcConfigGetConfigDirs (FcConfig *config)
786 Returns the list of font directories specified in the 628 Returns the list of font directories specified in the
787 configuration files for 'config'. Does not include any 629 configuration files for 'config'. Does not include any
788 subdirectories. */ 630 subdirectories. */
789 (config)) 631 (config))
790 { 632 {
791 FCSTRLIST_TO_LISP_USING (FcConfigGetConfigDirs); 633 return fc_strlist_to_lisp_using (&FcConfigGetConfigDirs, config);
792 } 634 }
793 635
794 DEFUN("fc-config-get-font-dirs", Ffc_config_get_font_dirs, 1, 1, 0, /* 636 DEFUN("fc-config-get-font-dirs", Ffc_config_get_font_dirs, 1, 1, 0, /*
795 -- Function: FcStrList *FcConfigGetFontDirs (FcConfig *config) 637 -- Function: FcStrList *FcConfigGetFontDirs (FcConfig *config)
796 Returns the list of font directories in 'config'. This includes the 638 Returns the list of font directories in 'config'. This includes the
797 configured font directories along with any directories below those 639 configured font directories along with any directories below those
798 in the filesystem. */ 640 in the filesystem. */
799 (config)) 641 (config))
800 { 642 {
801 FCSTRLIST_TO_LISP_USING (FcConfigGetFontDirs); 643 return fc_strlist_to_lisp_using (&FcConfigGetFontDirs, config);
802 } 644 }
803 645
804 DEFUN("fc-config-get-config-files", Ffc_config_get_config_files, 1, 1, 0, /* 646 DEFUN("fc-config-get-config-files", Ffc_config_get_config_files, 1, 1, 0, /*
805 -- Function: FcStrList *FcConfigGetConfigFiles (FcConfig *config) 647 -- Function: FcStrList *FcConfigGetConfigFiles (FcConfig *config)
806 Returns the list of known configuration files used to generate 648 Returns the list of known configuration files used to generate
807 'config'. Note that this will not include any configuration done 649 'config'. Note that this will not include any configuration done
808 with FcConfigParse. */ 650 with FcConfigParse. */
809 (config)) 651 (config))
810 { 652 {
811 FCSTRLIST_TO_LISP_USING (FcConfigGetConfigFiles); 653 return fc_strlist_to_lisp_using (&FcConfigGetConfigFiles, config);
812 } 654 }
813
814 #undef FCSTRLIST_TO_LISP_USING
815 655
816 DEFUN("fc-config-get-cache", Ffc_config_get_cache, 1, 1, 0, /* 656 DEFUN("fc-config-get-cache", Ffc_config_get_cache, 1, 1, 0, /*
817 -- Function: char *FcConfigGetCache (FcConfig *config) 657 -- Function: char *FcConfigGetCache (FcConfig *config)
818 Returns the name of the file used to store per-user font 658 Returns the name of the file used to store per-user font
819 information. */ 659 information. */
1020 the available fonts. Returns the resulting configuration. */ 860 the available fonts. Returns the resulting configuration. */
1021 ()) 861 ())
1022 { 862 {
1023 return fc_config_create_using (&FcInitLoadConfigAndFonts); 863 return fc_config_create_using (&FcInitLoadConfigAndFonts);
1024 } 864 }
865
866 DEFUN("fc-config-get-current", Ffc_config_get_current, 0, 0, 0, /*
867 -- Function: FcConfig *FcConfigGetCurrent (void)
868 Returns the current default configuration. */
869 ())
870 {
871 return fc_config_create_using (&FcConfigGetCurrent);
872 }
873
874 /* Pattern manipulation functions. */
875
876 DEFUN("fc-default-substitute", Ffc_default_substitute, 1, 1, 0, /*
877 Adds defaults for certain attributes if not specified in PATTERN.
878 FcPattern PATTERN is modified in-place, and nil is returned.
879 * Patterns without a specified style or weight are set to Medium
880 * Patterns without a specified style or slant are set to Roman
881 * Patterns without a specified pixel size are given one computed from any
882 specified point size (default 12), dpi (default 75) and scale (default 1). */
883 (pattern))
884 {
885 CHECK_FCPATTERN (pattern);
886 FcDefaultSubstitute (XFCPATTERN_PTR (pattern));
887 return Qnil;
888 }
889
890 /* -- Function: FcBool FcConfigSubstituteWithPat (FcConfig *config,
891 FcPattern *p, FcPattern *p_pat FcMatchKind kind)
892 OMITTED: use optional arguments in `fc-config-substitute'. */
893
894 DEFUN("fc-config-substitute", Ffc_config_substitute, 1, 4, 0, /*
895 Modifies PATTERN according to KIND and TESTPAT using operations from CONFIG.
896 PATTERN is modified in-place. Returns an undocumented Boolean value.
897 If optional KIND is `fc-match-pattern', then those tagged as pattern operations
898 are applied, else if KIND is `fc-match-font', those tagged as font operations
899 are applied and TESTPAT is used for <test> elements with target=pattern. KIND
900 defaults to `fc-match-font'.
901 If optional TESTPAT is nil, it is ignored. Otherwise it must be an FcPattern.
902 Optional CONFIG must be an FcConfig, defaulting to the current one.
903
904 Note that this function actually corresponds to FcConfigSubstituteWithPat, and
905 the argument order is changed to take advantage of Lisp optional arguments. */
906 (pattern, kind, testpat, config))
907 {
908 FcMatchKind knd;
909
910 /* There ought to be a standard idiom for this.... */
911 if (NILP (kind)
912 || EQ (kind, Qfc_match_font)) {
913 knd = FcMatchFont;
914 }
915 else if (EQ (kind, Qfc_match_pattern)) {
916 knd = FcMatchPattern;
917 }
918 else {
919 Fsignal (Qwrong_type_argument,
920 list2 (build_string ("need `fc-match-pattern' or `fc-match-font'"),
921 kind));
922 }
923
924 /* Typecheck arguments */
925 CHECK_FCPATTERN (pattern);
926 if (!NILP (testpat)) CHECK_FCPATTERN (testpat);
927 if (!NILP (config)) CHECK_FCCONFIG (config);
928
929 return (FcConfigSubstituteWithPat
930 (NILP (config) ? FcConfigGetCurrent () : XFCCONFIG_PTR (config),
931 XFCPATTERN_PTR (pattern),
932 NILP (testpat) ? NULL : XFCPATTERN_PTR (testpat),
933 knd) == FcTrue)
934 ? Qt : Qnil;
935 }
936
937 /* Pattern matching functions. */
938
939 /* The following functions return fonts that match a certain pattern.
940 `FcFontRenderPrepare' and `FcFontMatch' always return a single best
941 match. `FcFontList' returns the list of fonts that match a given
942 pattern on a certain set of properties. `FcFontSort' returns the
943 entire list of fonts, sorted in order of match quality, possibly
944 filtering out fonts that do not provide additional characters beyond
945 those provided by preferred fonts. */
946
947 DEFUN("fc-font-render-prepare", Ffc_font_render_prepare, 2, 3, 0, /*
948 Return a new pattern blending PATTERN and FONT.
949 Optional CONFIG is an FcConfig, defaulting to the current one.
950 The returned pattern consists of elements of FONT not appearing in PATTERN,
951 elements of PATTERN not appearing in FONT, and the best matching value from
952 PATTERN for elements appearing in both. The result is passed to
953 FcConfigSubstitute with 'kind' FcMatchFont and then returned. */
954 (pattern, font, config))
955 {
956 if (NILP (config)) {
957 config = Ffc_config_get_current ();
958 }
959 CHECK_FCPATTERN (pattern);
960 CHECK_FCPATTERN (font);
961 CHECK_FCCONFIG (config);
962
963 /* I don't think this can fail? */
964 return wrap_fcpattern (FcFontRenderPrepare (XFCCONFIG_PTR(config),
965 XFCPATTERN_PTR(font),
966 XFCPATTERN_PTR(pattern)));
967 }
968
969 DEFUN("fc-font-match", Ffc_font_match, 2, 3, 0, /*
970 Return the font on DEVICE that most closely matches PATTERN.
971
972 DEVICE is an X11 device.
973 PATTERN is a fontconfig pattern object.
974 Optional CONFIG is an FcConfig, defaulting to the current one.
975 Returns a fontconfig pattern object representing the closest match to the
976 given pattern, or an error code. Possible error codes are
977 `fc-result-no-match' and `fc-result-no-id'.
978 PATTERN is massaged with FcConfigSubstitute and FcDefaultSubstitute before
979 being processed by FcFontMatch. */
980 (device, pattern, config))
981 {
982 FcResult res;
983 struct fc_pattern *res_fcpat;
984 FcPattern *p;
985 FcConfig *fcc;
986
987 CHECK_FCPATTERN(pattern);
988 if (NILP(device))
989 return Qnil;
990 CHECK_X_DEVICE(device);
991 if (!DEVICE_LIVE_P(XDEVICE(device)))
992 return Qnil;
993 if (!NILP (config))
994 CHECK_FCCONFIG (config);
995
996 res_fcpat = ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
997 p = XFCPATTERN_PTR(pattern);
998 fcc = NILP (config) ? FcConfigGetCurrent () : XFCCONFIG_PTR (config);
999
1000 FcConfigSubstitute (fcc, p, FcMatchPattern);
1001 FcDefaultSubstitute (p);
1002 res_fcpat->fcpatPtr = FcFontMatch (fcc, p, &res);
1003
1004 if (res_fcpat->fcpatPtr == NULL)
1005 switch (res) {
1006 case FcResultNoMatch:
1007 return Qfc_result_no_match;
1008 case FcResultNoId:
1009 return Qfc_result_no_id;
1010 default:
1011 return Qfc_internal_error;
1012 }
1013 else
1014 return wrap_fcpattern(res_fcpat);
1015 }
1016
1017 /* #### fix this name to correspond to Ben's new nomenclature */
1018 DEFUN("fc-list-fonts-pattern-objects", Ffc_list_fonts_pattern_objects,
1019 3, 3, 0, /*
1020 Return a list of fonts on DEVICE that match PATTERN for PROPERTIES.
1021 Each font is represented by a fontconfig pattern object.
1022
1023 DEVICE is an X11 device.
1024 PATTERN is a fontconfig pattern to be matched.
1025 PROPERTIES is a list of property names (strings) that should match.
1026
1027 #### DEVICE is unused, ignored, and may be removed if it's not needed to
1028 match other font-listing APIs. */
1029 (UNUSED (device), pattern, properties))
1030 {
1031 FcObjectSet *os;
1032 FcFontSet *fontset;
1033
1034 CHECK_FCPATTERN (pattern);
1035 CHECK_LIST (properties);
1036
1037 os = FcObjectSetCreate ();
1038 string_list_to_fcobjectset (properties, os);
1039 /* #### why don't we need to do the "usual substitutions"? */
1040 fontset = FcFontList (NULL, XFCPATTERN_PTR (pattern), os);
1041 FcObjectSetDestroy (os);
1042
1043 return fontset_to_list (fontset, DestroyYes);
1044
1045 }
1046
1047 /* #### maybe this can/should be folded into fc-list-fonts-pattern-objects? */
1048 DEFUN("fc-font-sort", Ffc_font_sort, 2, 4, 0, /*
1049 Return a list of all fonts sorted by proximity to PATTERN.
1050 Each font is represented by a fontconfig pattern object.
1051
1052 DEVICE is an X11 device.
1053 PATTERN is a fontconfig pattern to be matched.
1054 Optional argument TRIM, if non-nil, means to trim trailing fonts that do not
1055 contribute new characters to the union repertoire.
1056
1057 #### Optional argument NOSUB, if non-nil, suppresses some of the usual
1058 property substitutions. DON'T USE THIS in production code, it is intended
1059 for exploring behavior of fontconfig and will be removed when this code is
1060 stable.
1061
1062 #### DEVICE is unused, ignored, and may be removed if it's not needed to
1063 match other font-listing APIs. */
1064 (UNUSED (device), pattern, trim, nosub))
1065 {
1066 CHECK_FCPATTERN (pattern);
1067
1068 {
1069 FcConfig *fcc = FcConfigGetCurrent();
1070 FcFontSet *fontset;
1071 FcPattern *p = XFCPATTERN_PTR (pattern);
1072 FcResult fcresult;
1073
1074 if (NILP(nosub)) /* #### temporary debug hack */
1075 FcDefaultSubstitute (p);
1076 FcConfigSubstitute (fcc, p, FcMatchPattern);
1077 fontset = FcFontSort (fcc, p, !NILP(trim), NULL, &fcresult);
1078
1079 return fontset_to_list (fontset, DestroyYes);
1080 }
1081 }
1082
1083 #ifdef FONTCONFIG_EXPOSE_CONFIG
1084
1085 /* Configuration routines --- for debugging
1086 Don't depend on these routines being available in the future!
1087
1088 3.2.10 Initialization
1089 ---------------------
1090
1091 An FcConfig object holds the internal representation of a configuration.
1092 There is a default configuration which applications may use by passing
1093 0 to any function using the data within an FcConfig.
1094 */
1095
1096 static void
1097 finalize_fc_config (void *header, int UNUSED (for_disksave))
1098 {
1099 struct fc_config *p = (struct fc_config *) header;
1100 if (p->fccfgPtr && p->fccfgPtr != FcConfigGetCurrent())
1101 {
1102 /* If we get here, all of *our* references are garbage (see comment on
1103 fc_config_create_using() for why), and the only reference that
1104 fontconfig keeps is the current FcConfig. */
1105 FcConfigDestroy (p->fccfgPtr);
1106 }
1107 p->fccfgPtr = 0;
1108 }
1109
1110 static void
1111 print_fc_config (Lisp_Object obj, Lisp_Object printcharfun,
1112 int UNUSED(escapeflag))
1113 {
1114 struct fc_config *c = XFCCONFIG (obj);
1115 if (print_readably)
1116 printing_unreadable_object ("#<fc-config 0x%x>", c->header.uid);
1117 write_fmt_string (printcharfun, "#<fc-config 0x%x>", c->header.uid);
1118 }
1119
1120 static const struct memory_description fcconfig_description [] = {
1121 /* #### nothing here, is this right?? */
1122 { XD_END }
1123 };
1124
1125 DEFINE_LRECORD_IMPLEMENTATION("fc-config", fc_config, 0,
1126 0, print_fc_config, finalize_fc_config, 0, 0,
1127 fcconfig_description,
1128 struct fc_config);
1025 1129
1026 DEFUN("fc-init", Ffc_init, 0, 0, 0, /* 1130 DEFUN("fc-init", Ffc_init, 0, 0, 0, /*
1027 -- Function: FcBool FcInit (void) 1131 -- Function: FcBool FcInit (void)
1028 Loads the default configuration file and the fonts referenced 1132 Loads the default configuration file and the fonts referenced
1029 therein and sets the default configuration to that result. 1133 therein and sets the default configuration to that result.
1190 FcObjectSetAdd (os, s); 1294 FcObjectSetAdd (os, s);
1191 } 1295 }
1192 } 1296 }
1193 1297
1194 void 1298 void
1195 syms_of_font_mgr (void) 1299 syms_of_font_mgr (void) {
1196 {
1197 INIT_LRECORD_IMPLEMENTATION(fc_pattern); 1300 INIT_LRECORD_IMPLEMENTATION(fc_pattern);
1198 1301
1199 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_patternp); 1302 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_patternp);
1200 1303
1201 DEFSYMBOL(Qfc_result_type_mismatch); 1304 DEFSYMBOL(Qfc_result_type_mismatch);
1202 DEFSYMBOL(Qfc_result_no_match); 1305 DEFSYMBOL(Qfc_result_no_match);
1203 DEFSYMBOL(Qfc_result_no_id); 1306 DEFSYMBOL(Qfc_result_no_id);
1204 DEFSYMBOL(Qfc_internal_error); 1307 DEFSYMBOL(Qfc_internal_error);
1308 DEFSYMBOL(Qfc_match_pattern);
1309 DEFSYMBOL(Qfc_match_font);
1205 DEFSYMBOL(Qfont_mgr); 1310 DEFSYMBOL(Qfont_mgr);
1206 1311
1207 DEFSUBR(Ffc_pattern_p); 1312 DEFSUBR(Ffc_pattern_p);
1208 DEFSUBR(Ffc_pattern_create); 1313 DEFSUBR(Ffc_pattern_create);
1209 DEFSUBR(Ffc_name_parse); 1314 DEFSUBR(Ffc_name_parse);
1213 DEFSUBR(Ffc_pattern_del); 1318 DEFSUBR(Ffc_pattern_del);
1214 DEFSUBR(Ffc_pattern_get); 1319 DEFSUBR(Ffc_pattern_get);
1215 DEFSUBR(Ffc_list_fonts_pattern_objects); 1320 DEFSUBR(Ffc_list_fonts_pattern_objects);
1216 DEFSUBR(Ffc_font_sort); 1321 DEFSUBR(Ffc_font_sort);
1217 DEFSUBR(Ffc_font_match); 1322 DEFSUBR(Ffc_font_match);
1323 DEFSUBR(Ffc_default_substitute);
1324 DEFSUBR(Ffc_config_substitute);
1325 DEFSUBR(Ffc_font_render_prepare);
1218 DEFSUBR(Fxlfd_font_name_p); 1326 DEFSUBR(Fxlfd_font_name_p);
1219 1327
1220 #ifdef FONTCONFIG_EXPOSE_CONFIG 1328 #ifdef FONTCONFIG_EXPOSE_CONFIG
1221 INIT_LRECORD_IMPLEMENTATION(fc_config); 1329 INIT_LRECORD_IMPLEMENTATION(fc_config);
1222 1330