comparison src/glyphs.c @ 438:84b14dcb0985 r21-2-27

Import from CVS: tag r21-2-27
author cvs
date Mon, 13 Aug 2007 11:32:25 +0200
parents 9d177e8d4150
children 8de8e3f6228a
comparison
equal deleted inserted replaced
437:e2a4e8b94b82 438:84b14dcb0985
1 /* Generic glyph/image implementation + display tables 1 /* Generic glyph/image implementation + display tables
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Tinker Systems 3 Copyright (C) 1995 Tinker Systems
4 Copyright (C) 1995, 1996 Ben Wing 4 Copyright (C) 1995, 1996 Ben Wing
5 Copyright (C) 1995 Sun Microsystems 5 Copyright (C) 1995 Sun Microsystems
6 Copyright (C) 1998, 1999 Andy Piper 6 Copyright (C) 1998, 1999, 2000 Andy Piper
7 7
8 This file is part of XEmacs. 8 This file is part of XEmacs.
9 9
10 XEmacs is free software; you can redistribute it and/or modify it 10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the 11 under the terms of the GNU General Public License as published by the
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */ 23 Boston, MA 02111-1307, USA. */
24 24
25 /* Synched up with: Not in FSF. */ 25 /* Synched up with: Not in FSF. */
26 26
27 /* Written by Ben Wing and Chuck Thompson. */ 27 /* Written by Ben Wing and Chuck Thompson. Heavily modified /
28 rewritten by Andy Piper. */
28 29
29 #include <config.h> 30 #include <config.h>
30 #include "lisp.h" 31 #include "lisp.h"
31 32
32 #include "buffer.h" 33 #include "buffer.h"
120 } image_instantiator_format_entry_dynarr; 121 } image_instantiator_format_entry_dynarr;
121 122
122 image_instantiator_format_entry_dynarr * 123 image_instantiator_format_entry_dynarr *
123 the_image_instantiator_format_entry_dynarr; 124 the_image_instantiator_format_entry_dynarr;
124 125
125 static Lisp_Object allocate_image_instance (Lisp_Object device); 126 static Lisp_Object allocate_image_instance (Lisp_Object device, Lisp_Object glyph);
126 static void image_validate (Lisp_Object instantiator); 127 static void image_validate (Lisp_Object instantiator);
127 static void glyph_property_was_changed (Lisp_Object glyph, 128 static void glyph_property_was_changed (Lisp_Object glyph,
128 Lisp_Object property, 129 Lisp_Object property,
129 Lisp_Object locale); 130 Lisp_Object locale);
130 static void register_ignored_expose (struct frame* f, int x, int y, int width, int height); 131 static void register_ignored_expose (struct frame* f, int x, int y, int width, int height);
573 574
574 static Lisp_Object 575 static Lisp_Object
575 instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain, 576 instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain,
576 Lisp_Object instantiator, 577 Lisp_Object instantiator,
577 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 578 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
578 int dest_mask) 579 int dest_mask, Lisp_Object glyph)
579 { 580 {
580 Lisp_Object ii = allocate_image_instance (device); 581 Lisp_Object ii = allocate_image_instance (device, glyph);
581 struct image_instantiator_methods *meths; 582 struct image_instantiator_methods *meths;
582 struct gcpro gcpro1; 583 struct gcpro gcpro1;
583 int methp = 0; 584 int methp = 0;
584 585
585 GCPRO1 (ii); 586 GCPRO1 (ii);
620 mark_image_instance (Lisp_Object obj) 621 mark_image_instance (Lisp_Object obj)
621 { 622 {
622 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); 623 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
623 624
624 mark_object (i->name); 625 mark_object (i->name);
626 /* We don't mark the glyph reference since that would create a
627 circularity preventing GC. */
625 switch (IMAGE_INSTANCE_TYPE (i)) 628 switch (IMAGE_INSTANCE_TYPE (i))
626 { 629 {
627 case IMAGE_TEXT: 630 case IMAGE_TEXT:
628 mark_object (IMAGE_INSTANCE_TEXT_STRING (i)); 631 mark_object (IMAGE_INSTANCE_TEXT_STRING (i));
629 break; 632 break;
752 write_c_string (")", printcharfun); 755 write_c_string (")", printcharfun);
753 } 756 }
754 break; 757 break;
755 758
756 case IMAGE_WIDGET: 759 case IMAGE_WIDGET:
757 /*
758 if (!NILP (IMAGE_INSTANCE_WIDGET_CALLBACK (ii)))
759 {
760 print_internal (IMAGE_INSTANCE_WIDGET_CALLBACK (ii), printcharfun, 0);
761 write_c_string (", ", printcharfun);
762 }
763 */
764 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii))) 760 if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
765 { 761 {
766 write_c_string (" (", printcharfun); 762 write_c_string (" (", printcharfun);
767 print_internal 763 print_internal
768 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0); 764 (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
840 struct device *d1 = XDEVICE (i1->device); 836 struct device *d1 = XDEVICE (i1->device);
841 struct device *d2 = XDEVICE (i2->device); 837 struct device *d2 = XDEVICE (i2->device);
842 838
843 if (d1 != d2) 839 if (d1 != d2)
844 return 0; 840 return 0;
845 if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)) 841 if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
842 || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
843 || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
844 || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
845 || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
846 return 0; 846 return 0;
847 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2), 847 if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
848 depth + 1)) 848 depth + 1))
849 return 0; 849 return 0;
850 850
861 break; 861 break;
862 862
863 case IMAGE_MONO_PIXMAP: 863 case IMAGE_MONO_PIXMAP:
864 case IMAGE_COLOR_PIXMAP: 864 case IMAGE_COLOR_PIXMAP:
865 case IMAGE_POINTER: 865 case IMAGE_POINTER:
866 if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) == 866 if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
867 IMAGE_INSTANCE_PIXMAP_WIDTH (i2) &&
868 IMAGE_INSTANCE_PIXMAP_HEIGHT (i1) ==
869 IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) &&
870 IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
871 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && 867 IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
872 IMAGE_INSTANCE_PIXMAP_SLICE (i1) == 868 IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
873 IMAGE_INSTANCE_PIXMAP_SLICE (i2) && 869 IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
874 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), 870 EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1),
875 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && 871 IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) &&
885 break; 881 break;
886 882
887 case IMAGE_WIDGET: 883 case IMAGE_WIDGET:
888 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), 884 if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
889 IMAGE_INSTANCE_WIDGET_TYPE (i2)) 885 IMAGE_INSTANCE_WIDGET_TYPE (i2))
886 && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
887 IMAGE_INSTANCE_SUBWINDOW_ID (i2)
890 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1), 888 && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
891 IMAGE_INSTANCE_WIDGET_ITEMS (i2), 889 IMAGE_INSTANCE_WIDGET_ITEMS (i2),
892 depth + 1) 890 depth + 1)
893 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), 891 && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
894 IMAGE_INSTANCE_WIDGET_PROPS (i2), 892 IMAGE_INSTANCE_WIDGET_PROPS (i2),
895 depth + 1) 893 depth + 1)
896 )) 894 ))
897 return 0; 895 return 0;
896 break;
897
898 case IMAGE_LAYOUT: 898 case IMAGE_LAYOUT:
899 if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT 899 if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT
900 && 900 &&
901 !(EQ (IMAGE_INSTANCE_LAYOUT_BORDER (i1), 901 !(EQ (IMAGE_INSTANCE_LAYOUT_BORDER (i1),
902 IMAGE_INSTANCE_LAYOUT_BORDER (i2)) 902 IMAGE_INSTANCE_LAYOUT_BORDER (i2))
903 && 903 &&
904 internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1), 904 internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1),
905 IMAGE_INSTANCE_LAYOUT_CHILDREN (i2), 905 IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
906 depth + 1))) 906 depth + 1)))
907 return 0; 907 return 0;
908 break;
909
908 case IMAGE_SUBWINDOW: 910 case IMAGE_SUBWINDOW:
909 if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) == 911 if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
910 IMAGE_INSTANCE_SUBWINDOW_WIDTH (i2) &&
911 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i1) ==
912 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i2) &&
913 IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
914 IMAGE_INSTANCE_SUBWINDOW_ID (i2))) 912 IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
915 return 0; 913 return 0;
916 break; 914 break;
917 915
918 default: 916 default:
925 static unsigned long 923 static unsigned long
926 image_instance_hash (Lisp_Object obj, int depth) 924 image_instance_hash (Lisp_Object obj, int depth)
927 { 925 {
928 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); 926 struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
929 struct device *d = XDEVICE (i->device); 927 struct device *d = XDEVICE (i->device);
930 unsigned long hash = (unsigned long) d; 928 unsigned long hash = HASH3 ((unsigned long) d,
929 IMAGE_INSTANCE_WIDTH (i),
930 IMAGE_INSTANCE_HEIGHT (i));
931 931
932 switch (IMAGE_INSTANCE_TYPE (i)) 932 switch (IMAGE_INSTANCE_TYPE (i))
933 { 933 {
934 case IMAGE_NOTHING: 934 case IMAGE_NOTHING:
935 break; 935 break;
940 break; 940 break;
941 941
942 case IMAGE_MONO_PIXMAP: 942 case IMAGE_MONO_PIXMAP:
943 case IMAGE_COLOR_PIXMAP: 943 case IMAGE_COLOR_PIXMAP:
944 case IMAGE_POINTER: 944 case IMAGE_POINTER:
945 hash = HASH6 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), 945 hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
946 IMAGE_INSTANCE_PIXMAP_HEIGHT (i),
947 IMAGE_INSTANCE_PIXMAP_DEPTH (i),
948 IMAGE_INSTANCE_PIXMAP_SLICE (i), 946 IMAGE_INSTANCE_PIXMAP_SLICE (i),
949 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), 947 internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
950 depth + 1)); 948 depth + 1));
951 break; 949 break;
952 950
953 case IMAGE_WIDGET: 951 case IMAGE_WIDGET:
954 hash = HASH4 (hash, 952 hash = HASH4 (hash,
955 internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), 953 internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1),
956 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), 954 internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
957 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1)); 955 internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1));
956 case IMAGE_SUBWINDOW:
957 hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
958 break;
959
958 case IMAGE_LAYOUT: 960 case IMAGE_LAYOUT:
959 if (IMAGE_INSTANCE_TYPE (i) == IMAGE_LAYOUT) 961 hash = HASH3 (hash,
960 hash = HASH3 (hash, 962 internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1),
961 internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1), 963 internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i),
962 internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), 964 depth + 1));
963 depth + 1));
964 case IMAGE_SUBWINDOW:
965 hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i),
966 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i),
967 (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
968 break; 965 break;
969 966
970 default: 967 default:
971 abort (); 968 abort ();
972 } 969 }
980 finalize_image_instance, image_instance_equal, 977 finalize_image_instance, image_instance_equal,
981 image_instance_hash, 0, 978 image_instance_hash, 0,
982 struct Lisp_Image_Instance); 979 struct Lisp_Image_Instance);
983 980
984 static Lisp_Object 981 static Lisp_Object
985 allocate_image_instance (Lisp_Object device) 982 allocate_image_instance (Lisp_Object device, Lisp_Object glyph)
986 { 983 {
987 struct Lisp_Image_Instance *lp = 984 struct Lisp_Image_Instance *lp =
988 alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance); 985 alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance);
989 Lisp_Object val; 986 Lisp_Object val;
990 987
992 lp->device = device; 989 lp->device = device;
993 lp->type = IMAGE_NOTHING; 990 lp->type = IMAGE_NOTHING;
994 lp->name = Qnil; 991 lp->name = Qnil;
995 lp->x_offset = 0; 992 lp->x_offset = 0;
996 lp->y_offset = 0; 993 lp->y_offset = 0;
994 lp->width = 0;
995 lp->height = 0;
996 lp->glyph = glyph;
997 MARK_IMAGE_INSTANCE_CHANGED (lp); /* So that layouts get done. */
997 XSETIMAGE_INSTANCE (val, lp); 998 XSETIMAGE_INSTANCE (val, lp);
999 MARK_GLYPHS_CHANGED; /* So that the dirty flag gets reset. */
998 return val; 1000 return val;
999 } 1001 }
1000 1002
1001 static enum image_instance_type 1003 static enum image_instance_type
1002 decode_image_instance_type (Lisp_Object type, Error_behavior errb) 1004 decode_image_instance_type (Lisp_Object type, Error_behavior errb)
1174 make_int (dest_mask)); 1176 make_int (dest_mask));
1175 GCPRO1 (data); 1177 GCPRO1 (data);
1176 if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit)) 1178 if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit))
1177 signal_simple_error ("Inheritance not allowed here", data); 1179 signal_simple_error ("Inheritance not allowed here", data);
1178 ii = instantiate_image_instantiator (device, device, data, 1180 ii = instantiate_image_instantiator (device, device, data,
1179 Qnil, Qnil, dest_mask); 1181 Qnil, Qnil, dest_mask, Qnil);
1180 RETURN_UNGCPRO (ii); 1182 RETURN_UNGCPRO (ii);
1181 } 1183 }
1182 1184
1183 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /* 1185 DEFUN ("make-image-instance", Fmake_image_instance, 1, 4, 0, /*
1184 Return a new `image-instance' object. 1186 Return a new `image-instance' object.
1448 switch (XIMAGE_INSTANCE_TYPE (image_instance)) 1450 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1449 { 1451 {
1450 case IMAGE_MONO_PIXMAP: 1452 case IMAGE_MONO_PIXMAP:
1451 case IMAGE_COLOR_PIXMAP: 1453 case IMAGE_COLOR_PIXMAP:
1452 case IMAGE_POINTER: 1454 case IMAGE_POINTER:
1453 return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance));
1454
1455 case IMAGE_SUBWINDOW: 1455 case IMAGE_SUBWINDOW:
1456 case IMAGE_WIDGET: 1456 case IMAGE_WIDGET:
1457 case IMAGE_LAYOUT: 1457 case IMAGE_LAYOUT:
1458 return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); 1458 return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
1459 1459
1460 default: 1460 default:
1461 return Qnil; 1461 return Qnil;
1462 } 1462 }
1463 } 1463 }
1472 switch (XIMAGE_INSTANCE_TYPE (image_instance)) 1472 switch (XIMAGE_INSTANCE_TYPE (image_instance))
1473 { 1473 {
1474 case IMAGE_MONO_PIXMAP: 1474 case IMAGE_MONO_PIXMAP:
1475 case IMAGE_COLOR_PIXMAP: 1475 case IMAGE_COLOR_PIXMAP:
1476 case IMAGE_POINTER: 1476 case IMAGE_POINTER:
1477 return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance));
1478
1479 case IMAGE_SUBWINDOW: 1477 case IMAGE_SUBWINDOW:
1480 case IMAGE_WIDGET: 1478 case IMAGE_WIDGET:
1481 case IMAGE_LAYOUT: 1479 case IMAGE_LAYOUT:
1482 return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); 1480 return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
1483 1481
1484 default: 1482 default:
1485 return Qnil; 1483 return Qnil;
1486 } 1484 }
1487 } 1485 }
1609 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance)) 1607 if (!HAS_DEVMETH_P (XDEVICE (device), colorize_image_instance))
1610 return image_instance; 1608 return image_instance;
1611 1609
1612 /* #### There should be a copy_image_instance(), which calls a 1610 /* #### There should be a copy_image_instance(), which calls a
1613 device-specific method to copy the window-system subobject. */ 1611 device-specific method to copy the window-system subobject. */
1614 new = allocate_image_instance (device); 1612 new = allocate_image_instance (device, Qnil);
1615 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance)); 1613 copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
1616 /* note that if this method returns non-zero, this method MUST 1614 /* note that if this method returns non-zero, this method MUST
1617 copy any window-system resources, so that when one image instance is 1615 copy any window-system resources, so that when one image instance is
1618 freed, the other one is not hosed. */ 1616 freed, the other one is not hosed. */
1619 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground, 1617 if (!DEVMETH (XDEVICE (device), colorize_image_instance, (new, foreground,
1620 background))) 1618 background)))
1621 return image_instance; 1619 return image_instance;
1622 return new; 1620 return new;
1623 } 1621 }
1624 1622
1623
1624 /************************************************************************/
1625 /* Geometry calculations */
1626 /************************************************************************/
1627
1628 /* Find out desired geometry of the image instance. If there is no
1629 special function then just return the width and / or height. */
1630 void
1631 image_instance_query_geometry (Lisp_Object image_instance,
1632 unsigned int* width, unsigned int* height,
1633 enum image_instance_geometry disp,
1634 Lisp_Object domain)
1635 {
1636 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1637 Lisp_Object type;
1638 struct image_instantiator_methods* meths;
1639
1640 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1641 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1642
1643 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1644 {
1645 IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
1646 disp, domain));
1647 }
1648 else
1649 {
1650 if (width)
1651 *width = IMAGE_INSTANCE_WIDTH (ii);
1652 if (height)
1653 *height = IMAGE_INSTANCE_HEIGHT (ii);
1654 }
1655 }
1656
1657 /* Layout the image instance using the provided dimensions. Layout
1658 widgets are going to do different kinds of calculations to
1659 determine what size to give things so we could make the layout
1660 function relatively simple to take account of that. An alternative
1661 approach is to consider separately the two cases, one where you
1662 don't mind what size you have (normal widgets) and one where you
1663 want to specifiy something (layout widgets). */
1664 void
1665 image_instance_layout (Lisp_Object image_instance,
1666 unsigned int width, unsigned int height,
1667 Lisp_Object domain)
1668 {
1669 struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
1670 Lisp_Object type;
1671 struct image_instantiator_methods* meths;
1672
1673 type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
1674 meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
1675
1676 /* If geometry is unspecified then get some reasonable values for it. */
1677 if (width == IMAGE_UNSPECIFIED_GEOMETRY
1678 ||
1679 height == IMAGE_UNSPECIFIED_GEOMETRY)
1680 {
1681 unsigned int dwidth, dheight;
1682
1683 /* Get the desired geometry. */
1684 if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
1685 {
1686 IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
1687 IMAGE_DESIRED_GEOMETRY,
1688 domain));
1689 }
1690 else
1691 {
1692 dwidth = IMAGE_INSTANCE_WIDTH (ii);
1693 dheight = IMAGE_INSTANCE_HEIGHT (ii);
1694 }
1695
1696 /* Compare with allowed geometry. */
1697 if (width == IMAGE_UNSPECIFIED_GEOMETRY)
1698 width = dwidth;
1699 if (height == IMAGE_UNSPECIFIED_GEOMETRY)
1700 height = dheight;
1701 }
1702
1703 /* At this point width and height should contain sane values. Thus
1704 we set the glyph geometry and lay it out. */
1705 IMAGE_INSTANCE_WIDTH (ii) = width;
1706 IMAGE_INSTANCE_HEIGHT (ii) = height;
1707
1708 if (meths && HAS_IIFORMAT_METH_P (meths, layout))
1709 {
1710 IIFORMAT_METH (meths, layout, (image_instance, width, height, domain));
1711 }
1712 /* else no change to the geometry. */
1713 }
1714
1625 1715
1626 /************************************************************************/ 1716 /************************************************************************/
1627 /* error helpers */ 1717 /* error helpers */
1628 /************************************************************************/ 1718 /************************************************************************/
1629 DOESNT_RETURN 1719 DOESNT_RETURN
1716 string_possible_dest_types (void) 1806 string_possible_dest_types (void)
1717 { 1807 {
1718 return IMAGE_TEXT_MASK; 1808 return IMAGE_TEXT_MASK;
1719 } 1809 }
1720 1810
1721 /* called from autodetect_instantiate() */ 1811 /* Called from autodetect_instantiate() */
1722 void 1812 void
1723 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 1813 string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1724 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 1814 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1725 int dest_mask, Lisp_Object domain) 1815 int dest_mask, Lisp_Object domain)
1726 { 1816 {
1727 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data); 1817 Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
1728 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1818 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1729 1819
1730 assert (!NILP (string)); 1820 /* Should never get here with a domain other than a window. */
1821 assert (!NILP (string) && WINDOWP (domain));
1731 if (dest_mask & IMAGE_TEXT_MASK) 1822 if (dest_mask & IMAGE_TEXT_MASK)
1732 { 1823 {
1733 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; 1824 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
1734 IMAGE_INSTANCE_TEXT_STRING (ii) = string; 1825 IMAGE_INSTANCE_TEXT_STRING (ii) = string;
1735 } 1826 }
1736 else 1827 else
1737 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); 1828 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
1829 }
1830
1831 /* Sort out the size of the text that is being displayed. Calculating
1832 it dynamically allows us to change the text and still see
1833 everything. Note that the following methods are for text not string
1834 since that is what the instantiated type is. The first method is a
1835 helper that is used elsewhere for calculating text geometry. */
1836 void
1837 query_string_geometry (Lisp_Object string, Lisp_Object face,
1838 unsigned int* width, unsigned int* height,
1839 unsigned int* descent, Lisp_Object domain)
1840 {
1841 struct font_metric_info fm;
1842 unsigned char charsets[NUM_LEADING_BYTES];
1843 struct face_cachel frame_cachel;
1844 struct face_cachel *cachel;
1845 Lisp_Object frame = FW_FRAME (domain);
1846
1847 /* Compute height */
1848 if (height)
1849 {
1850 /* Compute string metric info */
1851 find_charsets_in_bufbyte_string (charsets,
1852 XSTRING_DATA (string),
1853 XSTRING_LENGTH (string));
1854
1855 /* Fallback to the default face if none was provided. */
1856 if (!NILP (face))
1857 {
1858 reset_face_cachel (&frame_cachel);
1859 update_face_cachel_data (&frame_cachel, frame, face);
1860 cachel = &frame_cachel;
1861 }
1862 else
1863 {
1864 cachel = WINDOW_FACE_CACHEL (XWINDOW (domain), DEFAULT_INDEX);
1865 }
1866
1867 ensure_face_cachel_complete (cachel, domain, charsets);
1868 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
1869
1870 *height = fm.ascent + fm.descent;
1871 /* #### descent only gets set if we query the height as well. */
1872 if (descent)
1873 *descent = fm.descent;
1874 }
1875
1876 /* Compute width */
1877 if (width)
1878 {
1879 if (!NILP (face))
1880 *width = redisplay_frame_text_width_string (XFRAME (frame),
1881 face,
1882 0, string, 0, -1);
1883 else
1884 *width = redisplay_frame_text_width_string (XFRAME (frame),
1885 Vdefault_face,
1886 0, string, 0, -1);
1887 }
1888 }
1889
1890 Lisp_Object
1891 query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
1892 {
1893 unsigned char charsets[NUM_LEADING_BYTES];
1894 struct face_cachel frame_cachel;
1895 struct face_cachel *cachel;
1896 int i;
1897 Lisp_Object frame = FW_FRAME (domain);
1898
1899 /* Compute string font info */
1900 find_charsets_in_bufbyte_string (charsets,
1901 XSTRING_DATA (string),
1902 XSTRING_LENGTH (string));
1903
1904 reset_face_cachel (&frame_cachel);
1905 update_face_cachel_data (&frame_cachel, frame, face);
1906 cachel = &frame_cachel;
1907
1908 ensure_face_cachel_complete (cachel, domain, charsets);
1909
1910 for (i = 0; i < NUM_LEADING_BYTES; i++)
1911 {
1912 if (charsets[i])
1913 {
1914 return FACE_CACHEL_FONT (cachel,
1915 CHARSET_BY_LEADING_BYTE (i +
1916 MIN_LEADING_BYTE));
1917
1918 }
1919 }
1920
1921 return Qnil; /* NOT REACHED */
1922 }
1923
1924 static void
1925 text_query_geometry (Lisp_Object image_instance,
1926 unsigned int* width, unsigned int* height,
1927 enum image_instance_geometry disp, Lisp_Object domain)
1928 {
1929 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1930 unsigned int descent = 0;
1931
1932 query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
1933 IMAGE_INSTANCE_FACE (ii),
1934 width, height, &descent, domain);
1935
1936 /* The descent gets set as a side effect of querying the
1937 geometry. */
1938 IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
1738 } 1939 }
1739 1940
1740 /* set the properties of a string */ 1941 /* set the properties of a string */
1741 static Lisp_Object 1942 static Lisp_Object
1742 text_set_property (Lisp_Object image_instance, Lisp_Object prop, 1943 text_set_property (Lisp_Object image_instance, Lisp_Object prop,
1775 formatted_string_instantiate (Lisp_Object image_instance, 1976 formatted_string_instantiate (Lisp_Object image_instance,
1776 Lisp_Object instantiator, 1977 Lisp_Object instantiator,
1777 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 1978 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1778 int dest_mask, Lisp_Object domain) 1979 int dest_mask, Lisp_Object domain)
1779 { 1980 {
1780 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1781 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1782
1783 assert (!NILP (data));
1784 /* #### implement this */ 1981 /* #### implement this */
1785 warn_when_safe (Qunimplemented, Qnotice, 1982 warn_when_safe (Qunimplemented, Qnotice,
1786 "`formatted-string' not yet implemented; assuming `string'"); 1983 "`formatted-string' not yet implemented; assuming `string'");
1787 if (dest_mask & IMAGE_TEXT_MASK) 1984
1788 { 1985 string_instantiate (image_instance, instantiator,
1789 IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT; 1986 pointer_fg, pointer_bg, dest_mask, domain);
1790 IMAGE_INSTANCE_TEXT_STRING (ii) = data;
1791 }
1792 else
1793 incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
1794 } 1987 }
1795 1988
1796 1989
1797 /************************************************************************/ 1990 /************************************************************************/
1798 /* pixmap file functions */ 1991 /* pixmap file functions */
2445 Lisp_Object domain, Lisp_Object instantiator, 2638 Lisp_Object domain, Lisp_Object instantiator,
2446 Lisp_Object depth) 2639 Lisp_Object depth)
2447 { 2640 {
2448 Lisp_Object device = DFW_DEVICE (domain); 2641 Lisp_Object device = DFW_DEVICE (domain);
2449 struct device *d = XDEVICE (device); 2642 struct device *d = XDEVICE (device);
2643 Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
2450 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier); 2644 int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
2451 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER); 2645 int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
2452 2646
2453 if (IMAGE_INSTANCEP (instantiator)) 2647 if (IMAGE_INSTANCEP (instantiator))
2454 { 2648 {
2567 locative); 2761 locative);
2568 instance = instantiate_image_instantiator (device, 2762 instance = instantiate_image_instantiator (device,
2569 domain, 2763 domain,
2570 instantiator, 2764 instantiator,
2571 pointer_fg, pointer_bg, 2765 pointer_fg, pointer_bg,
2572 dest_mask); 2766 dest_mask,
2767 glyph);
2573 2768
2574 Fsetcar (locative, instance); 2769 Fsetcar (locative, instance);
2575 /* only after the image has been instantiated do we know 2770 /* only after the image has been instantiated do we know
2576 whether we need to put it in the per-window image instance 2771 whether we need to put it in the per-window image instance
2577 cache. */ 2772 cache. */
3161 XIMAGE_SPECIFIER_ALLOWED (g->image) = 3356 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3162 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK; 3357 IMAGE_NOTHING_MASK | IMAGE_POINTER_MASK;
3163 break; 3358 break;
3164 case GLYPH_ICON: 3359 case GLYPH_ICON:
3165 XIMAGE_SPECIFIER_ALLOWED (g->image) = 3360 XIMAGE_SPECIFIER_ALLOWED (g->image) =
3166 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK; 3361 IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
3362 | IMAGE_COLOR_PIXMAP_MASK;
3167 break; 3363 break;
3168 default: 3364 default:
3169 abort (); 3365 abort ();
3170 } 3366 }
3171 3367
3294 case GLYPH_POINTER: return Qpointer; 3490 case GLYPH_POINTER: return Qpointer;
3295 case GLYPH_ICON: return Qicon; 3491 case GLYPH_ICON: return Qicon;
3296 } 3492 }
3297 } 3493 }
3298 3494
3495 Lisp_Object
3496 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3497 Error_behavior errb, int no_quit)
3498 {
3499 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3500
3501 /* This can never return Qunbound. All glyphs have 'nothing as
3502 a fallback. */
3503 Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
3504 domain, errb, no_quit, 0,
3505 Qzero);
3506
3507 return image_instance;
3508 }
3509
3510 static Lisp_Object
3511 glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
3512 {
3513 Lisp_Object instance = glyph_or_image;
3514
3515 if (GLYPHP (glyph_or_image))
3516 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3517
3518 return instance;
3519 }
3520
3299 /***************************************************************************** 3521 /*****************************************************************************
3300 glyph_width 3522 glyph_width
3301 3523
3302 Return the width of the given GLYPH on the given WINDOW. If the 3524 Return the width of the given GLYPH on the given WINDOW.
3303 instance is a string then the width is calculated using the font of 3525 Calculations are done based on recursively querying the geometry of
3304 the given FACE, unless a face is defined by the glyph itself. 3526 the associated image instances.
3305 ****************************************************************************/ 3527 ****************************************************************************/
3306 unsigned short 3528 unsigned short
3307 glyph_width (Lisp_Object glyph_or_image, Lisp_Object frame_face, 3529 glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
3308 face_index window_findex, Lisp_Object window) 3530 {
3309 { 3531 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3310 Lisp_Object instance = glyph_or_image; 3532 domain);
3311 Lisp_Object frame = XWINDOW (window)->frame;
3312
3313 /* #### We somehow need to distinguish between the user causing this
3314 error condition and a bug causing it. */
3315 if (GLYPHP (glyph_or_image))
3316 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3317
3318 if (!IMAGE_INSTANCEP (instance)) 3533 if (!IMAGE_INSTANCEP (instance))
3319 return 0; 3534 return 0;
3320 3535
3321 switch (XIMAGE_INSTANCE_TYPE (instance)) 3536 if (XIMAGE_INSTANCE_DIRTYP (instance))
3322 { 3537 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3323 case IMAGE_TEXT: 3538 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3324 { 3539
3325 Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); 3540 return XIMAGE_INSTANCE_WIDTH (instance);
3326 Lisp_Object private_face = Qnil;
3327
3328 if (GLYPHP (glyph_or_image))
3329 private_face = XGLYPH_FACE(glyph_or_image);
3330
3331 if (!NILP (private_face))
3332 return redisplay_frame_text_width_string (XFRAME (frame),
3333 private_face,
3334 0, str, 0, -1);
3335 else
3336 if (!NILP (frame_face))
3337 return redisplay_frame_text_width_string (XFRAME (frame),
3338 frame_face,
3339 0, str, 0, -1);
3340 else
3341 return redisplay_text_width_string (XWINDOW (window),
3342 window_findex,
3343 0, str, 0, -1);
3344 }
3345
3346 case IMAGE_MONO_PIXMAP:
3347 case IMAGE_COLOR_PIXMAP:
3348 case IMAGE_POINTER:
3349 return XIMAGE_INSTANCE_PIXMAP_WIDTH (instance);
3350
3351 case IMAGE_NOTHING:
3352 return 0;
3353
3354 case IMAGE_SUBWINDOW:
3355 case IMAGE_WIDGET:
3356 case IMAGE_LAYOUT:
3357 return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance);
3358
3359 default:
3360 abort ();
3361 return 0;
3362 }
3363 } 3541 }
3364 3542
3365 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /* 3543 DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
3366 Return the width of GLYPH on WINDOW. 3544 Return the width of GLYPH on WINDOW.
3367 This may not be exact as it does not take into account all of the context 3545 This may not be exact as it does not take into account all of the context
3370 (glyph, window)) 3548 (glyph, window))
3371 { 3549 {
3372 XSETWINDOW (window, decode_window (window)); 3550 XSETWINDOW (window, decode_window (window));
3373 CHECK_GLYPH (glyph); 3551 CHECK_GLYPH (glyph);
3374 3552
3375 return make_int (glyph_width (glyph, Qnil, DEFAULT_INDEX, window)); 3553 return make_int (glyph_width (glyph, window));
3376 } 3554 }
3377 3555
3378 #define RETURN_ASCENT 0 3556 unsigned short
3379 #define RETURN_DESCENT 1 3557 glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
3380 #define RETURN_HEIGHT 2 3558 {
3381 3559 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3382 Lisp_Object 3560 domain);
3383 glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
3384 Error_behavior errb, int no_quit)
3385 {
3386 Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
3387
3388 /* This can never return Qunbound. All glyphs have 'nothing as
3389 a fallback. */
3390 return specifier_instance (specifier, Qunbound, domain, errb, no_quit, 0,
3391 Qzero);
3392 }
3393
3394 static unsigned short
3395 glyph_height_internal (Lisp_Object glyph_or_image, Lisp_Object frame_face,
3396 face_index window_findex, Lisp_Object window,
3397 int function)
3398 {
3399 Lisp_Object instance = glyph_or_image;
3400 Lisp_Object frame = XWINDOW (window)->frame;
3401
3402 if (GLYPHP (glyph_or_image))
3403 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3404
3405 if (!IMAGE_INSTANCEP (instance)) 3561 if (!IMAGE_INSTANCEP (instance))
3406 return 0; 3562 return 0;
3407 3563
3408 switch (XIMAGE_INSTANCE_TYPE (instance)) 3564 if (XIMAGE_INSTANCE_DIRTYP (instance))
3409 { 3565 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3410 case IMAGE_TEXT: 3566 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3411 { 3567
3412 struct font_metric_info fm; 3568 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3413 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); 3569 return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
3414 unsigned char charsets[NUM_LEADING_BYTES]; 3570 else
3415 struct face_cachel frame_cachel; 3571 return XIMAGE_INSTANCE_HEIGHT (instance);
3416 struct face_cachel *cachel;
3417
3418 find_charsets_in_bufbyte_string (charsets,
3419 XSTRING_DATA (string),
3420 XSTRING_LENGTH (string));
3421
3422 if (!NILP (frame_face))
3423 {
3424 reset_face_cachel (&frame_cachel);
3425 update_face_cachel_data (&frame_cachel, frame, frame_face);
3426 cachel = &frame_cachel;
3427 }
3428 else
3429 cachel = WINDOW_FACE_CACHEL (XWINDOW (window), window_findex);
3430 ensure_face_cachel_complete (cachel, window, charsets);
3431
3432 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
3433
3434 switch (function)
3435 {
3436 case RETURN_ASCENT: return fm.ascent;
3437 case RETURN_DESCENT: return fm.descent;
3438 case RETURN_HEIGHT: return fm.ascent + fm.descent;
3439 default:
3440 abort ();
3441 return 0; /* not reached */
3442 }
3443 }
3444
3445 case IMAGE_MONO_PIXMAP:
3446 case IMAGE_COLOR_PIXMAP:
3447 case IMAGE_POINTER:
3448 /* #### Ugh ugh ugh -- temporary crap */
3449 if (function == RETURN_ASCENT || function == RETURN_HEIGHT)
3450 return XIMAGE_INSTANCE_PIXMAP_HEIGHT (instance);
3451 else
3452 return 0;
3453
3454 case IMAGE_NOTHING:
3455 return 0;
3456
3457 case IMAGE_SUBWINDOW:
3458 case IMAGE_WIDGET:
3459 case IMAGE_LAYOUT:
3460 /* #### Ugh ugh ugh -- temporary crap */
3461 if (function == RETURN_ASCENT || function == RETURN_HEIGHT)
3462 return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance);
3463 else
3464 return 0;
3465
3466 default:
3467 abort ();
3468 return 0;
3469 }
3470 } 3572 }
3471 3573
3472 unsigned short 3574 unsigned short
3473 glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face, 3575 glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
3474 face_index window_findex, Lisp_Object window) 3576 {
3475 { 3577 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3476 return glyph_height_internal (glyph, frame_face, window_findex, window, 3578 domain);
3477 RETURN_ASCENT); 3579 if (!IMAGE_INSTANCEP (instance))
3478 } 3580 return 0;
3479 3581
3480 unsigned short 3582 if (XIMAGE_INSTANCE_DIRTYP (instance))
3481 glyph_descent (Lisp_Object glyph, Lisp_Object frame_face, 3583 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3482 face_index window_findex, Lisp_Object window) 3584 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3483 { 3585
3484 return glyph_height_internal (glyph, frame_face, window_findex, window, 3586 if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
3485 RETURN_DESCENT); 3587 return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
3588 else
3589 return 0;
3486 } 3590 }
3487 3591
3488 /* strictly a convenience function. */ 3592 /* strictly a convenience function. */
3489 unsigned short 3593 unsigned short
3490 glyph_height (Lisp_Object glyph, Lisp_Object frame_face, 3594 glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
3491 face_index window_findex, Lisp_Object window) 3595 {
3492 { 3596 Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
3493 return glyph_height_internal (glyph, frame_face, window_findex, window, 3597 domain);
3494 RETURN_HEIGHT); 3598
3599 if (!IMAGE_INSTANCEP (instance))
3600 return 0;
3601
3602 if (XIMAGE_INSTANCE_DIRTYP (instance))
3603 image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
3604 IMAGE_UNSPECIFIED_GEOMETRY, domain);
3605
3606 return XIMAGE_INSTANCE_HEIGHT (instance);
3495 } 3607 }
3496 3608
3497 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /* 3609 DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
3498 Return the ascent value of GLYPH on WINDOW. 3610 Return the ascent value of GLYPH on WINDOW.
3499 This may not be exact as it does not take into account all of the context 3611 This may not be exact as it does not take into account all of the context
3502 (glyph, window)) 3614 (glyph, window))
3503 { 3615 {
3504 XSETWINDOW (window, decode_window (window)); 3616 XSETWINDOW (window, decode_window (window));
3505 CHECK_GLYPH (glyph); 3617 CHECK_GLYPH (glyph);
3506 3618
3507 return make_int (glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window)); 3619 return make_int (glyph_ascent (glyph, window));
3508 } 3620 }
3509 3621
3510 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /* 3622 DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
3511 Return the descent value of GLYPH on WINDOW. 3623 Return the descent value of GLYPH on WINDOW.
3512 This may not be exact as it does not take into account all of the context 3624 This may not be exact as it does not take into account all of the context
3515 (glyph, window)) 3627 (glyph, window))
3516 { 3628 {
3517 XSETWINDOW (window, decode_window (window)); 3629 XSETWINDOW (window, decode_window (window));
3518 CHECK_GLYPH (glyph); 3630 CHECK_GLYPH (glyph);
3519 3631
3520 return make_int (glyph_descent (glyph, Qnil, DEFAULT_INDEX, window)); 3632 return make_int (glyph_descent (glyph, window));
3521 } 3633 }
3522 3634
3523 /* This is redundant but I bet a lot of people expect it to exist. */ 3635 /* This is redundant but I bet a lot of people expect it to exist. */
3524 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /* 3636 DEFUN ("glyph-height", Fglyph_height, 1, 2, 0, /*
3525 Return the height of GLYPH on WINDOW. 3637 Return the height of GLYPH on WINDOW.
3529 (glyph, window)) 3641 (glyph, window))
3530 { 3642 {
3531 XSETWINDOW (window, decode_window (window)); 3643 XSETWINDOW (window, decode_window (window));
3532 CHECK_GLYPH (glyph); 3644 CHECK_GLYPH (glyph);
3533 3645
3534 return make_int (glyph_height (glyph, Qnil, DEFAULT_INDEX, window)); 3646 return make_int (glyph_height (glyph, window));
3535 } 3647 }
3536
3537 #undef RETURN_ASCENT
3538 #undef RETURN_DESCENT
3539 #undef RETURN_HEIGHT
3540 3648
3541 static unsigned int 3649 static unsigned int
3542 glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window) 3650 glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window)
3543 { 3651 {
3544 Lisp_Object instance = glyph_or_image; 3652 return XIMAGE_INSTANCE_DIRTYP (glyph_image_instance_maybe
3545 3653 (glyph_or_image, window));
3546 if (GLYPHP (glyph_or_image))
3547 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3548
3549 return XIMAGE_INSTANCE_DIRTYP (instance);
3550 } 3654 }
3551 3655
3552 static void 3656 static void
3553 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty) 3657 set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
3554 { 3658 {
3619 { 3723 {
3620 if (XGLYPH (glyph)->after_change) 3724 if (XGLYPH (glyph)->after_change)
3621 (XGLYPH (glyph)->after_change) (glyph, property, locale); 3725 (XGLYPH (glyph)->after_change) (glyph, property, locale);
3622 } 3726 }
3623 3727
3728 #if 0 /* Not used for now */
3729 static void
3730 glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
3731 unsigned int* width, unsigned int* height,
3732 enum image_instance_geometry disp, Lisp_Object domain)
3733 {
3734 Lisp_Object instance = glyph_or_image;
3735
3736 if (GLYPHP (glyph_or_image))
3737 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3738
3739 image_instance_query_geometry (instance, width, height, disp, domain);
3740 }
3741
3742 static void
3743 glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
3744 unsigned int width, unsigned int height, Lisp_Object domain)
3745 {
3746 Lisp_Object instance = glyph_or_image;
3747
3748 if (GLYPHP (glyph_or_image))
3749 instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
3750
3751 image_instance_layout (instance, width, height, domain);
3752 }
3753 #endif
3754
3624 3755
3625 /***************************************************************************** 3756 /*****************************************************************************
3626 * glyph cachel functions * 3757 * glyph cachel functions *
3627 *****************************************************************************/ 3758 *****************************************************************************/
3628 3759
3660 cachel->glyph = glyph; 3791 cachel->glyph = glyph;
3661 /* Speed things up slightly by grabbing the glyph instantiation 3792 /* Speed things up slightly by grabbing the glyph instantiation
3662 and passing it to the size functions. */ 3793 and passing it to the size functions. */
3663 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); 3794 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
3664 cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window); 3795 cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window);
3665 cachel->width = glyph_width (instance, Qnil, DEFAULT_INDEX, window); 3796 cachel->width = glyph_width (instance, window);
3666 cachel->ascent = glyph_ascent (instance, Qnil, DEFAULT_INDEX, window); 3797 cachel->ascent = glyph_ascent (instance, window);
3667 cachel->descent = glyph_descent (instance, Qnil, DEFAULT_INDEX, window); 3798 cachel->descent = glyph_descent (instance, window);
3668 } 3799 }
3669 3800
3670 cachel->updated = 1; 3801 cachel->updated = 1;
3671 } 3802 }
3672 3803
3779 3910
3780 3911
3781 /***************************************************************************** 3912 /*****************************************************************************
3782 * subwindow cachel functions * 3913 * subwindow cachel functions *
3783 *****************************************************************************/ 3914 *****************************************************************************/
3784 /* subwindows are curious in that you have to physically unmap them to 3915 /* Subwindows are curious in that you have to physically unmap them to
3785 not display them. It is problematic deciding what to do in 3916 not display them. It is problematic deciding what to do in
3786 redisplay. We have two caches - a per-window instance cache that 3917 redisplay. We have two caches - a per-window instance cache that
3787 keeps track of subwindows on a window, these are linked to their 3918 keeps track of subwindows on a window, these are linked to their
3788 instantiator in the hashtable and when the instantiator goes away 3919 instantiator in the hashtable and when the instantiator goes away
3789 we want the instance to go away also. However we also have a 3920 we want the instance to go away also. However we also have a
4049 || 4180 ||
4050 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) 4181 NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
4051 return; 4182 return;
4052 4183
4053 MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii)); 4184 MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii));
4054 } 4185 /* We must update the window's size as it may have been changed by
4055 4186 the the layout routines. We also do this here so that explicit resizing
4187 from lisp does not result in synchronous updates. */
4188 MAYBE_DEVMETH (XDEVICE (ii->device), resize_subwindow, (ii,
4189 IMAGE_INSTANCE_WIDTH (ii),
4190 IMAGE_INSTANCE_HEIGHT (ii)));
4191 }
4192
4193 /* Update all the subwindows on a frame. */
4056 void 4194 void
4057 update_frame_subwindows (struct frame *f) 4195 update_frame_subwindows (struct frame *f)
4058 { 4196 {
4059 int elt; 4197 int elt;
4060 4198
4092 elt = get_subwindow_cachel_index (f, subwindow); 4230 elt = get_subwindow_cachel_index (f, subwindow);
4093 cachel = Dynarr_atp (f->subwindow_cachels, elt); 4231 cachel = Dynarr_atp (f->subwindow_cachels, elt);
4094 4232
4095 /* make sure we don't get expose events */ 4233 /* make sure we don't get expose events */
4096 register_ignored_expose (f, cachel->x, cachel->y, cachel->width, cachel->height); 4234 register_ignored_expose (f, cachel->x, cachel->y, cachel->width, cachel->height);
4097 cachel->x = -1; 4235 cachel->x = ~0;
4098 cachel->y = -1; 4236 cachel->y = ~0;
4099 cachel->being_displayed = 0; 4237 cachel->being_displayed = 0;
4100 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; 4238 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4101 4239
4102 MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii)); 4240 MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii));
4103 } 4241 }
4131 cachel->y = y; 4269 cachel->y = y;
4132 cachel->width = dga->width; 4270 cachel->width = dga->width;
4133 cachel->height = dga->height; 4271 cachel->height = dga->height;
4134 cachel->being_displayed = 1; 4272 cachel->being_displayed = 1;
4135 4273
4274 /* This forces any pending display changes to happen to the image
4275 before we show it. I'm not sure whether or not we need mark as
4276 clean here, but for now we will. */
4277 if (IMAGE_INSTANCE_DIRTYP (ii))
4278 {
4279 update_subwindow (subwindow);
4280 IMAGE_INSTANCE_DIRTYP (ii) = 0;
4281 }
4282
4136 MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga)); 4283 MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga));
4137 } 4284 }
4138 4285
4139 static int 4286 static int
4140 subwindow_possible_dest_types (void) 4287 subwindow_possible_dest_types (void)
4163 ii->data = 0; 4310 ii->data = 0;
4164 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; 4311 IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
4165 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; 4312 IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
4166 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; 4313 IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame;
4167 4314
4168 /* this stuff may get overidden by the widget code */ 4315 /* #### This stuff may get overidden by the widget code and is
4316 actually really dumb now that we have dynamic geometry
4317 calculations. What should really happen is that the subwindow
4318 should query its child for and appropriate geometry. */
4169 if (NILP (width)) 4319 if (NILP (width))
4170 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20; 4320 IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20;
4171 else 4321 else
4172 { 4322 {
4173 int w = 1; 4323 int w = 1;
4215 int neww, newh; 4365 int neww, newh;
4216 4366
4217 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); 4367 CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
4218 4368
4219 if (NILP (width)) 4369 if (NILP (width))
4220 neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); 4370 neww = XIMAGE_INSTANCE_WIDTH (subwindow);
4221 else 4371 else
4222 neww = XINT (width); 4372 neww = XINT (width);
4223 4373
4224 if (NILP (height)) 4374 if (NILP (height))
4225 newh = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); 4375 newh = XIMAGE_INSTANCE_HEIGHT (subwindow);
4226 else 4376 else
4227 newh = XINT (height); 4377 newh = XINT (height);
4228 4378
4229 4379 /* The actual resizing gets done asychronously by
4230 MAYBE_DEVMETH (XDEVICE (XIMAGE_INSTANCE_DEVICE (subwindow)), 4380 update_subwindow. */
4231 resize_subwindow, (XIMAGE_INSTANCE (subwindow), neww, newh)); 4381 XIMAGE_INSTANCE_HEIGHT (subwindow) = newh;
4232 4382 XIMAGE_INSTANCE_WIDTH (subwindow) = neww;
4233 XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh;
4234 XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww;
4235 4383
4236 /* need to update the cachels as redisplay will not do this */ 4384 /* need to update the cachels as redisplay will not do this */
4237 update_subwindow_cachel (subwindow); 4385 update_subwindow_cachel (subwindow);
4238 4386
4239 return subwindow; 4387 return subwindow;
4368 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii); 4516 % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
4369 /* We might need to kick redisplay at this point - but we 4517 /* We might need to kick redisplay at this point - but we
4370 also might not. */ 4518 also might not. */
4371 MARK_DEVICE_FRAMES_GLYPHS_CHANGED 4519 MARK_DEVICE_FRAMES_GLYPHS_CHANGED
4372 (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))); 4520 (XDEVICE (IMAGE_INSTANCE_DEVICE (ii)));
4373 IMAGE_INSTANCE_DIRTYP (ii) = 1; 4521 MARK_IMAGE_INSTANCE_CHANGED (ii);
4374 } 4522 }
4375 } 4523 }
4376 } 4524 }
4377 return Qnil; 4525 return Qnil;
4378 } 4526 }
4643 4791
4644 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string); 4792 IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string);
4645 /* Do this so we can set strings. */ 4793 /* Do this so we can set strings. */
4646 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text"); 4794 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
4647 IIFORMAT_HAS_METHOD (text, set_property); 4795 IIFORMAT_HAS_METHOD (text, set_property);
4796 IIFORMAT_HAS_METHOD (text, query_geometry);
4648 4797
4649 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); 4798 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
4650 4799
4651 IIFORMAT_HAS_METHOD (formatted_string, validate); 4800 IIFORMAT_HAS_METHOD (formatted_string, validate);
4652 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types); 4801 IIFORMAT_HAS_METHOD (formatted_string, possible_dest_types);
4812 */ ); 4961 */ );
4813 Vcurrent_display_table = Fmake_specifier (Qdisplay_table); 4962 Vcurrent_display_table = Fmake_specifier (Qdisplay_table);
4814 set_specifier_fallback (Vcurrent_display_table, 4963 set_specifier_fallback (Vcurrent_display_table,
4815 list1 (Fcons (Qnil, Qnil))); 4964 list1 (Fcons (Qnil, Qnil)));
4816 set_specifier_caching (Vcurrent_display_table, 4965 set_specifier_caching (Vcurrent_display_table,
4817 slot_offset (struct window, 4966 offsetof (struct window, display_table),
4818 display_table),
4819 some_window_value_changed, 4967 some_window_value_changed,
4820 0, 0); 4968 0, 0);
4821 } 4969 }
4822 4970
4823 void 4971 void