diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/font.c | 701 |
1 files changed, 353 insertions, 348 deletions
diff --git a/src/font.c b/src/font.c index 23dcb4f2033..43af7345c33 100644 --- a/src/font.c +++ b/src/font.c | |||
| @@ -25,6 +25,9 @@ Boston, MA 02110-1301, USA. */ | |||
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 27 | #include <ctype.h> | 27 | #include <ctype.h> |
| 28 | #ifdef HAVE_M17N_FLT | ||
| 29 | #include <m17n-flt.h> | ||
| 30 | #endif | ||
| 28 | 31 | ||
| 29 | #include "lisp.h" | 32 | #include "lisp.h" |
| 30 | #include "buffer.h" | 33 | #include "buffer.h" |
| @@ -109,6 +112,24 @@ Lisp_Object QCantialias; | |||
| 109 | /* Symbols representing values of font spacing property. */ | 112 | /* Symbols representing values of font spacing property. */ |
| 110 | Lisp_Object Qc, Qm, Qp, Qd; | 113 | Lisp_Object Qc, Qm, Qp, Qd; |
| 111 | 114 | ||
| 115 | /* Alist of font registry symbol and the corresponding charsets | ||
| 116 | information. The information is retrieved from | ||
| 117 | Vfont_encoding_alist on demand. | ||
| 118 | |||
| 119 | Eash element has the form: | ||
| 120 | (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID)) | ||
| 121 | or | ||
| 122 | (REGISTRY . nil) | ||
| 123 | |||
| 124 | In the former form, ENCODING-CHARSET-ID is an ID of a charset that | ||
| 125 | encodes a character code to a glyph code of a font, and | ||
| 126 | REPERTORY-CHARSET-ID is an ID of a charset that tells if a | ||
| 127 | character is supported by a font. | ||
| 128 | |||
| 129 | The latter form means that the information for REGISTRY couldn't be | ||
| 130 | retrieved. */ | ||
| 131 | static Lisp_Object font_charset_alist; | ||
| 132 | |||
| 112 | /* List of all font drivers. Each font-backend (XXXfont.c) calls | 133 | /* List of all font drivers. Each font-backend (XXXfont.c) calls |
| 113 | register_font_driver in syms_of_XXXfont to register its font-driver | 134 | register_font_driver in syms_of_XXXfont to register its font-driver |
| 114 | here. */ | 135 | here. */ |
| @@ -251,6 +272,69 @@ build_font_family_alist () | |||
| 251 | } | 272 | } |
| 252 | } | 273 | } |
| 253 | 274 | ||
| 275 | extern Lisp_Object find_font_encoding P_ ((Lisp_Object)); | ||
| 276 | |||
| 277 | /* Return encoding charset and repertory charset for REGISTRY in | ||
| 278 | ENCODING and REPERTORY correspondingly. If correct information for | ||
| 279 | REGISTRY is available, return 0. Otherwise return -1. */ | ||
| 280 | |||
| 281 | int | ||
| 282 | font_registry_charsets (registry, encoding, repertory) | ||
| 283 | Lisp_Object registry; | ||
| 284 | struct charset **encoding, **repertory; | ||
| 285 | { | ||
| 286 | Lisp_Object val; | ||
| 287 | int encoding_id, repertory_id; | ||
| 288 | |||
| 289 | val = assq_no_quit (registry, font_charset_alist); | ||
| 290 | if (! NILP (val)) | ||
| 291 | { | ||
| 292 | val = XCDR (val); | ||
| 293 | if (NILP (val)) | ||
| 294 | return -1; | ||
| 295 | encoding_id = XINT (XCAR (val)); | ||
| 296 | repertory_id = XINT (XCDR (val)); | ||
| 297 | } | ||
| 298 | else | ||
| 299 | { | ||
| 300 | val = find_font_encoding (SYMBOL_NAME (registry)); | ||
| 301 | if (SYMBOLP (val) && CHARSETP (val)) | ||
| 302 | { | ||
| 303 | encoding_id = repertory_id = XINT (CHARSET_SYMBOL_ID (val)); | ||
| 304 | } | ||
| 305 | else if (CONSP (val)) | ||
| 306 | { | ||
| 307 | if (! CHARSETP (XCAR (val))) | ||
| 308 | goto invalid_entry; | ||
| 309 | encoding_id = XINT (CHARSET_SYMBOL_ID (XCAR (val))); | ||
| 310 | if (NILP (XCDR (val))) | ||
| 311 | repertory_id = -1; | ||
| 312 | else | ||
| 313 | { | ||
| 314 | if (! CHARSETP (XCDR (val))) | ||
| 315 | goto invalid_entry; | ||
| 316 | repertory_id = XINT (CHARSET_SYMBOL_ID (XCDR (val))); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | else | ||
| 320 | goto invalid_entry; | ||
| 321 | val = Fcons (make_number (encoding_id), make_number (repertory_id)); | ||
| 322 | font_charset_alist | ||
| 323 | = nconc2 (font_charset_alist, Fcons (Fcons (registry, val), Qnil)); | ||
| 324 | } | ||
| 325 | |||
| 326 | if (encoding) | ||
| 327 | *encoding = CHARSET_FROM_ID (encoding_id); | ||
| 328 | if (repertory) | ||
| 329 | *repertory = repertory_id >= 0 ? CHARSET_FROM_ID (repertory_id) : NULL; | ||
| 330 | return 0; | ||
| 331 | |||
| 332 | invalid_entry: | ||
| 333 | font_charset_alist | ||
| 334 | = nconc2 (font_charset_alist, Fcons (Fcons (registry, Qnil), Qnil)); | ||
| 335 | return -1; | ||
| 336 | } | ||
| 337 | |||
| 254 | 338 | ||
| 255 | /* Font property value validaters. See the comment of | 339 | /* Font property value validaters. See the comment of |
| 256 | font_property_table for the meaning of the arguments. */ | 340 | font_property_table for the meaning of the arguments. */ |
| @@ -329,6 +413,41 @@ font_prop_validate_spacing (prop, val) | |||
| 329 | return Qerror; | 413 | return Qerror; |
| 330 | } | 414 | } |
| 331 | 415 | ||
| 416 | static Lisp_Object | ||
| 417 | font_prop_validate_otf (prop, val) | ||
| 418 | Lisp_Object prop, val; | ||
| 419 | { | ||
| 420 | Lisp_Object tail, tmp; | ||
| 421 | int i; | ||
| 422 | |||
| 423 | /* VAL = (SCRIPT [ LANGSYS [ GSUB-FEATURES [ GPOS-FEATURES ]]]) | ||
| 424 | GSUB-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil | ||
| 425 | GPOS-FEATURES = (FEATURE ... [ nil FEATURE ... ]) | nil */ | ||
| 426 | if (! CONSP (val)) | ||
| 427 | return Qerror; | ||
| 428 | if (! SYMBOLP (XCAR (val))) | ||
| 429 | return Qerror; | ||
| 430 | tail = XCDR (val); | ||
| 431 | if (NILP (tail)) | ||
| 432 | return val; | ||
| 433 | if (! CONSP (tail) || ! SYMBOLP (XCAR (val))) | ||
| 434 | return Qerror; | ||
| 435 | for (i = 0; i < 2; i++) | ||
| 436 | { | ||
| 437 | tail = XCDR (tail); | ||
| 438 | if (NILP (tail)) | ||
| 439 | return val; | ||
| 440 | if (! CONSP (tail)) | ||
| 441 | return Qerror; | ||
| 442 | for (tmp = XCAR (tail); CONSP (tmp); tmp = XCDR (tmp)) | ||
| 443 | if (! SYMBOLP (XCAR (tmp))) | ||
| 444 | return Qerror; | ||
| 445 | if (! NILP (tmp)) | ||
| 446 | return Qerror; | ||
| 447 | } | ||
| 448 | return val; | ||
| 449 | } | ||
| 450 | |||
| 332 | /* Structure of known font property keys and validater of the | 451 | /* Structure of known font property keys and validater of the |
| 333 | values. */ | 452 | values. */ |
| 334 | struct | 453 | struct |
| @@ -354,7 +473,7 @@ struct | |||
| 354 | { &QCdpi, font_prop_validate_non_neg }, | 473 | { &QCdpi, font_prop_validate_non_neg }, |
| 355 | { &QCspacing, font_prop_validate_spacing }, | 474 | { &QCspacing, font_prop_validate_spacing }, |
| 356 | { &QCscalable, NULL }, | 475 | { &QCscalable, NULL }, |
| 357 | { &QCotf, font_prop_validate_symbol }, | 476 | { &QCotf, font_prop_validate_otf }, |
| 358 | { &QCantialias, font_prop_validate_symbol } | 477 | { &QCantialias, font_prop_validate_symbol } |
| 359 | }; | 478 | }; |
| 360 | 479 | ||
| @@ -1662,31 +1781,6 @@ generate_otf_features (spec, features) | |||
| 1662 | error ("OTF spec too long"); | 1781 | error ("OTF spec too long"); |
| 1663 | } | 1782 | } |
| 1664 | 1783 | ||
| 1665 | #define DEVICE_DELTA(table, size) \ | ||
| 1666 | (((size) >= (table).StartSize && (size) <= (table).EndSize) \ | ||
| 1667 | ? (table).DeltaValue[(size) - (table).StartSize] \ | ||
| 1668 | : 0) | ||
| 1669 | |||
| 1670 | void | ||
| 1671 | adjust_anchor (struct font *font, OTF_Anchor *anchor, | ||
| 1672 | unsigned code, int size, int *x, int *y) | ||
| 1673 | { | ||
| 1674 | if (anchor->AnchorFormat == 2 && font->driver->anchor_point) | ||
| 1675 | { | ||
| 1676 | int x0, y0; | ||
| 1677 | |||
| 1678 | if (font->driver->anchor_point (font, code, anchor->f.f1.AnchorPoint, | ||
| 1679 | &x0, &y0) >= 0) | ||
| 1680 | *x = x0, *y = y0; | ||
| 1681 | } | ||
| 1682 | else if (anchor->AnchorFormat == 3) | ||
| 1683 | { | ||
| 1684 | if (anchor->f.f2.XDeviceTable.offset) | ||
| 1685 | *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size); | ||
| 1686 | if (anchor->f.f2.YDeviceTable.offset) | ||
| 1687 | *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size); | ||
| 1688 | } | ||
| 1689 | } | ||
| 1690 | 1784 | ||
| 1691 | Lisp_Object | 1785 | Lisp_Object |
| 1692 | font_otf_DeviceTable (device_table) | 1786 | font_otf_DeviceTable (device_table) |
| @@ -1743,244 +1837,6 @@ font_otf_Anchor (anchor) | |||
| 1743 | return val; | 1837 | return val; |
| 1744 | } | 1838 | } |
| 1745 | 1839 | ||
| 1746 | #define REPLACEMENT_CHARACTER 0xFFFD | ||
| 1747 | |||
| 1748 | /* Drive FONT's OpenType FEATURES. See the comment of (sturct | ||
| 1749 | font_driver).drive_otf. */ | ||
| 1750 | |||
| 1751 | int | ||
| 1752 | font_drive_otf (font, otf_features, gstring_in, from, to, gstring_out, idx, | ||
| 1753 | alternate_subst) | ||
| 1754 | struct font *font; | ||
| 1755 | Lisp_Object otf_features; | ||
| 1756 | Lisp_Object gstring_in; | ||
| 1757 | int from, to; | ||
| 1758 | Lisp_Object gstring_out; | ||
| 1759 | int idx, alternate_subst; | ||
| 1760 | { | ||
| 1761 | Lisp_Object val; | ||
| 1762 | int len; | ||
| 1763 | int i; | ||
| 1764 | OTF *otf; | ||
| 1765 | OTF_GlyphString otf_gstring; | ||
| 1766 | OTF_Glyph *g; | ||
| 1767 | char *script, *langsys = NULL, *gsub_features = NULL, *gpos_features = NULL; | ||
| 1768 | int need_cmap; | ||
| 1769 | |||
| 1770 | val = XCAR (otf_features); | ||
| 1771 | script = SDATA (SYMBOL_NAME (val)); | ||
| 1772 | otf_features = XCDR (otf_features); | ||
| 1773 | val = XCAR (otf_features); | ||
| 1774 | langsys = NILP (val) ? NULL : SDATA (SYMBOL_NAME (val)); | ||
| 1775 | otf_features = XCDR (otf_features); | ||
| 1776 | val = XCAR (otf_features); | ||
| 1777 | if (! NILP (val)) | ||
| 1778 | { | ||
| 1779 | gsub_features = alloca (XINT (Flength (val)) * 6); | ||
| 1780 | generate_otf_features (val, &script, &langsys, gsub_features); | ||
| 1781 | } | ||
| 1782 | otf_features = XCDR (otf_features); | ||
| 1783 | val = XCAR (otf_features); | ||
| 1784 | if (! NILP (val)) | ||
| 1785 | { | ||
| 1786 | gpos_features = alloca (XINT (Flength (val)) * 6); | ||
| 1787 | generate_otf_features (val, &script, &langsys, gpos_features); | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | otf = otf_open (font->entity, font->file_name); | ||
| 1791 | if (! otf) | ||
| 1792 | return 0; | ||
| 1793 | if (OTF_get_table (otf, "head") < 0) | ||
| 1794 | return 0; | ||
| 1795 | if (OTF_get_table (otf, "cmap") < 0) | ||
| 1796 | return 0; | ||
| 1797 | if ((! gsub_features || OTF_check_table (otf, "GSUB") < 0) | ||
| 1798 | && (! gpos_features || OTF_check_table (otf, "GPOS") < 0)) | ||
| 1799 | return 0; | ||
| 1800 | |||
| 1801 | len = to - from; | ||
| 1802 | otf_gstring.size = otf_gstring.used = len; | ||
| 1803 | otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len); | ||
| 1804 | memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len); | ||
| 1805 | for (i = 0, need_cmap = 0; i < len; i++) | ||
| 1806 | { | ||
| 1807 | Lisp_Object g = LGSTRING_GLYPH (gstring_in, from + i); | ||
| 1808 | |||
| 1809 | otf_gstring.glyphs[i].c = XINT (LGLYPH_CHAR (g)); | ||
| 1810 | if (otf_gstring.glyphs[i].c == REPLACEMENT_CHARACTER) | ||
| 1811 | otf_gstring.glyphs[i].c = 0; | ||
| 1812 | if (NILP (LGLYPH_CODE (g))) | ||
| 1813 | { | ||
| 1814 | otf_gstring.glyphs[i].glyph_id = 0; | ||
| 1815 | need_cmap = 1; | ||
| 1816 | } | ||
| 1817 | else | ||
| 1818 | otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (g)); | ||
| 1819 | } | ||
| 1820 | if (need_cmap) | ||
| 1821 | OTF_drive_cmap (otf, &otf_gstring); | ||
| 1822 | OTF_drive_gdef (otf, &otf_gstring); | ||
| 1823 | |||
| 1824 | if (gsub_features) | ||
| 1825 | { | ||
| 1826 | if ((alternate_subst | ||
| 1827 | ? OTF_drive_gsub_alternate (otf, &otf_gstring, script, langsys, | ||
| 1828 | gsub_features) | ||
| 1829 | : OTF_drive_gsub (otf, &otf_gstring, script, langsys, | ||
| 1830 | gsub_features)) < 0) | ||
| 1831 | { | ||
| 1832 | free (otf_gstring.glyphs); | ||
| 1833 | return 0; | ||
| 1834 | } | ||
| 1835 | if (ASIZE (gstring_out) < idx + otf_gstring.used) | ||
| 1836 | { | ||
| 1837 | free (otf_gstring.glyphs); | ||
| 1838 | return -1; | ||
| 1839 | } | ||
| 1840 | for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used;) | ||
| 1841 | { | ||
| 1842 | int i0 = g->f.index.from, i1 = g->f.index.to; | ||
| 1843 | Lisp_Object glyph = LGSTRING_GLYPH (gstring_in, from + i0); | ||
| 1844 | Lisp_Object min_idx = AREF (glyph, 0); | ||
| 1845 | Lisp_Object max_idx = AREF (glyph, 1); | ||
| 1846 | |||
| 1847 | if (i0 < i1) | ||
| 1848 | { | ||
| 1849 | int min_idx_i = XINT (min_idx), max_idx_i = XINT (max_idx); | ||
| 1850 | |||
| 1851 | for (i0++; i0 <= i1; i0++) | ||
| 1852 | { | ||
| 1853 | glyph = LGSTRING_GLYPH (gstring_in, from + i0); | ||
| 1854 | if (min_idx_i > XINT (AREF (glyph, 0))) | ||
| 1855 | min_idx_i = XINT (AREF (glyph, 0)); | ||
| 1856 | if (max_idx_i < XINT (AREF (glyph, 1))) | ||
| 1857 | max_idx_i = XINT (AREF (glyph, 1)); | ||
| 1858 | } | ||
| 1859 | min_idx = make_number (min_idx_i); | ||
| 1860 | max_idx = make_number (max_idx_i); | ||
| 1861 | i0 = g->f.index.from; | ||
| 1862 | } | ||
| 1863 | for (; i < otf_gstring.used && g->f.index.from == i0; i++, g++) | ||
| 1864 | { | ||
| 1865 | glyph = LGSTRING_GLYPH (gstring_out, idx + i); | ||
| 1866 | ASET (glyph, 0, min_idx); | ||
| 1867 | ASET (glyph, 1, max_idx); | ||
| 1868 | if (g->c > 0) | ||
| 1869 | LGLYPH_SET_CHAR (glyph, make_number (g->c)); | ||
| 1870 | else | ||
| 1871 | LGLYPH_SET_CHAR (glyph, make_number (REPLACEMENT_CHARACTER)); | ||
| 1872 | LGLYPH_SET_CODE (glyph, make_number (g->glyph_id)); | ||
| 1873 | } | ||
| 1874 | } | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | if (gpos_features) | ||
| 1878 | { | ||
| 1879 | Lisp_Object glyph; | ||
| 1880 | int u = otf->head->unitsPerEm; | ||
| 1881 | int size = font->pixel_size; | ||
| 1882 | Lisp_Object base = Qnil, mark = Qnil; | ||
| 1883 | |||
| 1884 | if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, | ||
| 1885 | gpos_features) < 0) | ||
| 1886 | { | ||
| 1887 | free (otf_gstring.glyphs); | ||
| 1888 | return 0; | ||
| 1889 | } | ||
| 1890 | for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used; i++, g++) | ||
| 1891 | { | ||
| 1892 | Lisp_Object prev; | ||
| 1893 | int xoff = 0, yoff = 0, width_adjust = 0; | ||
| 1894 | |||
| 1895 | if (! g->glyph_id) | ||
| 1896 | continue; | ||
| 1897 | |||
| 1898 | switch (g->positioning_type) | ||
| 1899 | { | ||
| 1900 | case 0: | ||
| 1901 | break; | ||
| 1902 | case 1: case 2: | ||
| 1903 | { | ||
| 1904 | int format = g->f.f1.format; | ||
| 1905 | |||
| 1906 | if (format & OTF_XPlacement) | ||
| 1907 | xoff = g->f.f1.value->XPlacement * size / u; | ||
| 1908 | if (format & OTF_XPlaDevice) | ||
| 1909 | xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, size); | ||
| 1910 | if (format & OTF_YPlacement) | ||
| 1911 | yoff = - (g->f.f1.value->YPlacement * size / u); | ||
| 1912 | if (format & OTF_YPlaDevice) | ||
| 1913 | yoff -= DEVICE_DELTA (g->f.f1.value->YPlaDevice, size); | ||
| 1914 | if (format & OTF_XAdvance) | ||
| 1915 | width_adjust += g->f.f1.value->XAdvance * size / u; | ||
| 1916 | if (format & OTF_XAdvDevice) | ||
| 1917 | width_adjust += DEVICE_DELTA (g->f.f1.value->XAdvDevice, size); | ||
| 1918 | } | ||
| 1919 | break; | ||
| 1920 | case 3: | ||
| 1921 | /* Not yet supported. */ | ||
| 1922 | break; | ||
| 1923 | case 4: case 5: | ||
| 1924 | if (NILP (base)) | ||
| 1925 | break; | ||
| 1926 | prev = base; | ||
| 1927 | goto label_adjust_anchor; | ||
| 1928 | default: /* i.e. case 6 */ | ||
| 1929 | if (NILP (mark)) | ||
| 1930 | break; | ||
| 1931 | prev = mark; | ||
| 1932 | |||
| 1933 | label_adjust_anchor: | ||
| 1934 | { | ||
| 1935 | int base_x, base_y, mark_x, mark_y, width; | ||
| 1936 | unsigned code; | ||
| 1937 | |||
| 1938 | base_x = g->f.f4.base_anchor->XCoordinate * size / u; | ||
| 1939 | base_y = g->f.f4.base_anchor->YCoordinate * size / u; | ||
| 1940 | mark_x = g->f.f4.mark_anchor->XCoordinate * size / u; | ||
| 1941 | mark_y = g->f.f4.mark_anchor->YCoordinate * size / u; | ||
| 1942 | |||
| 1943 | code = XINT (LGLYPH_CODE (prev)); | ||
| 1944 | if (g->f.f4.base_anchor->AnchorFormat != 1) | ||
| 1945 | adjust_anchor (font, g->f.f4.base_anchor, | ||
| 1946 | code, size, &base_x, &base_y); | ||
| 1947 | if (g->f.f4.mark_anchor->AnchorFormat != 1) | ||
| 1948 | adjust_anchor (font, g->f.f4.mark_anchor, | ||
| 1949 | code, size, &mark_x, &mark_y); | ||
| 1950 | |||
| 1951 | if (NILP (LGLYPH_WIDTH (prev))) | ||
| 1952 | { | ||
| 1953 | width = font->driver->text_extents (font, &code, 1, NULL); | ||
| 1954 | LGLYPH_SET_WIDTH (prev, make_number (width)); | ||
| 1955 | } | ||
| 1956 | else | ||
| 1957 | width = XINT (LGLYPH_WIDTH (prev)); | ||
| 1958 | xoff = XINT (LGLYPH_XOFF (prev)) + (base_x - width) - mark_x; | ||
| 1959 | yoff = XINT (LGLYPH_YOFF (prev)) + mark_y - base_y; | ||
| 1960 | } | ||
| 1961 | } | ||
| 1962 | if (xoff || yoff || width_adjust) | ||
| 1963 | { | ||
| 1964 | Lisp_Object adjustment = Fmake_vector (make_number (3), Qnil); | ||
| 1965 | |||
| 1966 | ASET (adjustment, 0, make_number (xoff)); | ||
| 1967 | ASET (adjustment, 1, make_number (yoff)); | ||
| 1968 | ASET (adjustment, 2, make_number (width_adjust)); | ||
| 1969 | LGLYPH_SET_ADJUSTMENT (glyph, adjustment); | ||
| 1970 | } | ||
| 1971 | if (g->GlyphClass == OTF_GlyphClass0) | ||
| 1972 | base = mark = glyph; | ||
| 1973 | else if (g->GlyphClass == OTF_GlyphClassMark) | ||
| 1974 | mark = glyph; | ||
| 1975 | else | ||
| 1976 | base = glyph; | ||
| 1977 | } | ||
| 1978 | } | ||
| 1979 | |||
| 1980 | free (otf_gstring.glyphs); | ||
| 1981 | return i; | ||
| 1982 | } | ||
| 1983 | |||
| 1984 | #endif /* HAVE_LIBOTF */ | 1840 | #endif /* HAVE_LIBOTF */ |
| 1985 | 1841 | ||
| 1986 | /* G-string (glyph string) handler */ | 1842 | /* G-string (glyph string) handler */ |
| @@ -1989,55 +1845,26 @@ font_drive_otf (font, otf_features, gstring_in, from, to, gstring_out, idx, | |||
| 1989 | See the docstring of `font-make-gstring' for more detail. */ | 1845 | See the docstring of `font-make-gstring' for more detail. */ |
| 1990 | 1846 | ||
| 1991 | struct font * | 1847 | struct font * |
| 1992 | font_prepare_composition (cmp) | 1848 | font_prepare_composition (cmp, f) |
| 1993 | struct composition *cmp; | 1849 | struct composition *cmp; |
| 1850 | FRAME_PTR f; | ||
| 1994 | { | 1851 | { |
| 1995 | Lisp_Object gstring | 1852 | Lisp_Object gstring |
| 1996 | = AREF (XHASH_TABLE (composition_hash_table)->key_and_value, | 1853 | = AREF (XHASH_TABLE (composition_hash_table)->key_and_value, |
| 1997 | cmp->hash_index * 2); | 1854 | cmp->hash_index * 2); |
| 1998 | struct font *font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer; | ||
| 1999 | int len = LGSTRING_LENGTH (gstring); | ||
| 2000 | int i; | ||
| 2001 | |||
| 2002 | cmp->font = font; | ||
| 2003 | cmp->lbearing = cmp->rbearing = cmp->pixel_width = 0; | ||
| 2004 | cmp->ascent = font->ascent; | ||
| 2005 | cmp->descent = font->descent; | ||
| 2006 | 1855 | ||
| 2007 | for (i = 0; i < len; i++) | 1856 | cmp->font = XSAVE_VALUE (LGSTRING_FONT (gstring))->pointer; |
| 2008 | { | 1857 | cmp->glyph_len = LGSTRING_LENGTH (gstring); |
| 2009 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); | 1858 | cmp->pixel_width = LGSTRING_WIDTH (gstring); |
| 2010 | unsigned code; | 1859 | cmp->lbearing = LGSTRING_LBEARING (gstring); |
| 2011 | struct font_metrics metrics; | 1860 | cmp->rbearing = LGSTRING_RBEARING (gstring); |
| 1861 | cmp->ascent = LGSTRING_ASCENT (gstring); | ||
| 1862 | cmp->descent = LGSTRING_DESCENT (gstring); | ||
| 1863 | cmp->width = cmp->pixel_width / FRAME_COLUMN_WIDTH (f); | ||
| 1864 | if (cmp->width == 0) | ||
| 1865 | cmp->width = 1; | ||
| 2012 | 1866 | ||
| 2013 | if (NILP (LGLYPH_FROM (g))) | 1867 | return cmp->font; |
| 2014 | break; | ||
| 2015 | code = XINT (LGLYPH_CODE (g)); | ||
| 2016 | font->driver->text_extents (font, &code, 1, &metrics); | ||
| 2017 | LGLYPH_SET_WIDTH (g, make_number (metrics.width)); | ||
| 2018 | metrics.lbearing += LGLYPH_XOFF (g); | ||
| 2019 | metrics.rbearing += LGLYPH_XOFF (g); | ||
| 2020 | metrics.ascent += LGLYPH_YOFF (g); | ||
| 2021 | metrics.descent += LGLYPH_YOFF (g); | ||
| 2022 | |||
| 2023 | if (cmp->lbearing > cmp->pixel_width + metrics.lbearing) | ||
| 2024 | cmp->lbearing = cmp->pixel_width + metrics.lbearing; | ||
| 2025 | if (cmp->rbearing < cmp->pixel_width + metrics.rbearing) | ||
| 2026 | cmp->rbearing = cmp->pixel_width + metrics.rbearing; | ||
| 2027 | if (cmp->ascent < metrics.ascent) | ||
| 2028 | cmp->ascent = metrics.ascent; | ||
| 2029 | if (cmp->descent < metrics.descent) | ||
| 2030 | cmp->descent = metrics.descent; | ||
| 2031 | cmp->pixel_width += metrics.width + LGLYPH_WADJUST (g); | ||
| 2032 | } | ||
| 2033 | cmp->glyph_len = i; | ||
| 2034 | LGSTRING_SET_LBEARING (gstring, make_number (cmp->lbearing)); | ||
| 2035 | LGSTRING_SET_RBEARING (gstring, make_number (cmp->rbearing)); | ||
| 2036 | LGSTRING_SET_WIDTH (gstring, make_number (cmp->pixel_width)); | ||
| 2037 | LGSTRING_SET_ASCENT (gstring, make_number (cmp->ascent)); | ||
| 2038 | LGSTRING_SET_DESCENT (gstring, make_number (cmp->descent)); | ||
| 2039 | |||
| 2040 | return font; | ||
| 2041 | } | 1868 | } |
| 2042 | 1869 | ||
| 2043 | int | 1870 | int |
| @@ -2559,7 +2386,8 @@ font_close_object (f, font_object) | |||
| 2559 | } | 2386 | } |
| 2560 | 2387 | ||
| 2561 | 2388 | ||
| 2562 | /* Return 1 iff FONT on F has a glyph for character C. */ | 2389 | /* Return 1 if FONT on F has a glyph for character C, 0 if not, -1 if |
| 2390 | FONT is a font-entity and it must be opened to check. */ | ||
| 2563 | 2391 | ||
| 2564 | int | 2392 | int |
| 2565 | font_has_char (f, font, c) | 2393 | font_has_char (f, font, c) |
| @@ -2658,13 +2486,15 @@ font_get_frame (font) | |||
| 2658 | 2486 | ||
| 2659 | 2487 | ||
| 2660 | /* Find a font entity best matching with LFACE. If SPEC is non-nil, | 2488 | /* Find a font entity best matching with LFACE. If SPEC is non-nil, |
| 2661 | the font must exactly match with it. */ | 2489 | the font must exactly match with it. C, if not negative, is a |
| 2490 | character that the entity must support. */ | ||
| 2662 | 2491 | ||
| 2663 | Lisp_Object | 2492 | Lisp_Object |
| 2664 | font_find_for_lface (f, lface, spec) | 2493 | font_find_for_lface (f, lface, spec, c) |
| 2665 | FRAME_PTR f; | 2494 | FRAME_PTR f; |
| 2666 | Lisp_Object *lface; | 2495 | Lisp_Object *lface; |
| 2667 | Lisp_Object spec; | 2496 | Lisp_Object spec; |
| 2497 | int c; | ||
| 2668 | { | 2498 | { |
| 2669 | Lisp_Object frame, entities; | 2499 | Lisp_Object frame, entities; |
| 2670 | int i; | 2500 | int i; |
| @@ -2673,6 +2503,8 @@ font_find_for_lface (f, lface, spec) | |||
| 2673 | 2503 | ||
| 2674 | if (NILP (spec)) | 2504 | if (NILP (spec)) |
| 2675 | { | 2505 | { |
| 2506 | if (c >= 0x100) | ||
| 2507 | return Qnil; | ||
| 2676 | for (i = 0; i < FONT_SPEC_MAX; i++) | 2508 | for (i = 0; i < FONT_SPEC_MAX; i++) |
| 2677 | ASET (scratch_font_spec, i, Qnil); | 2509 | ASET (scratch_font_spec, i, Qnil); |
| 2678 | ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1); | 2510 | ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1); |
| @@ -2700,10 +2532,32 @@ font_find_for_lface (f, lface, spec) | |||
| 2700 | } | 2532 | } |
| 2701 | else | 2533 | else |
| 2702 | { | 2534 | { |
| 2535 | Lisp_Object registry = AREF (spec, FONT_REGISTRY_INDEX); | ||
| 2536 | |||
| 2537 | if (NILP (registry)) | ||
| 2538 | registry = Qiso8859_1; | ||
| 2539 | |||
| 2540 | if (c >= 0) | ||
| 2541 | { | ||
| 2542 | struct charset *repertory; | ||
| 2543 | |||
| 2544 | if (font_registry_charsets (registry, NULL, &repertory) < 0) | ||
| 2545 | return Qnil; | ||
| 2546 | if (repertory) | ||
| 2547 | { | ||
| 2548 | if (ENCODE_CHAR (repertory, c) | ||
| 2549 | == CHARSET_INVALID_CODE (repertory)) | ||
| 2550 | return Qnil; | ||
| 2551 | /* Any font of this registry support C. So, let's | ||
| 2552 | suppress the further checking. */ | ||
| 2553 | c = -1; | ||
| 2554 | } | ||
| 2555 | else if (c > MAX_UNICODE_CHAR) | ||
| 2556 | return Qnil; | ||
| 2557 | } | ||
| 2703 | for (i = 0; i < FONT_SPEC_MAX; i++) | 2558 | for (i = 0; i < FONT_SPEC_MAX; i++) |
| 2704 | ASET (scratch_font_spec, i, AREF (spec, i)); | 2559 | ASET (scratch_font_spec, i, AREF (spec, i)); |
| 2705 | if (NILP (AREF (spec, FONT_REGISTRY_INDEX))) | 2560 | ASET (scratch_font_spec, FONT_REGISTRY_INDEX, registry); |
| 2706 | ASET (scratch_font_spec, FONT_REGISTRY_INDEX, Qiso8859_1); | ||
| 2707 | entities = font_list_entities (frame, scratch_font_spec); | 2561 | entities = font_list_entities (frame, scratch_font_spec); |
| 2708 | } | 2562 | } |
| 2709 | 2563 | ||
| @@ -2729,10 +2583,27 @@ font_find_for_lface (f, lface, spec) | |||
| 2729 | font_sort_entites (entities, prefer, frame, spec); | 2583 | font_sort_entites (entities, prefer, frame, spec); |
| 2730 | } | 2584 | } |
| 2731 | 2585 | ||
| 2732 | return AREF (entities, 0); | 2586 | if (c < 0) |
| 2733 | } | 2587 | return AREF (entities, 0); |
| 2734 | 2588 | for (i = 0; i < ASIZE (entities); i++) | |
| 2589 | { | ||
| 2590 | int result = font_has_char (f, AREF (entities, i), c); | ||
| 2591 | Lisp_Object font_object; | ||
| 2735 | 2592 | ||
| 2593 | if (result > 0) | ||
| 2594 | return AREF (entities, i); | ||
| 2595 | if (result <= 0) | ||
| 2596 | continue; | ||
| 2597 | font_object = font_open_for_lface (f, AREF (entities, i), lface, spec); | ||
| 2598 | if (NILP (font_object)) | ||
| 2599 | continue; | ||
| 2600 | result = font_has_char (f, font_object, c); | ||
| 2601 | font_close_object (f, font_object); | ||
| 2602 | if (result > 0) | ||
| 2603 | return AREF (entities, i); | ||
| 2604 | } | ||
| 2605 | return Qnil; | ||
| 2606 | } | ||
| 2736 | 2607 | ||
| 2737 | 2608 | ||
| 2738 | Lisp_Object | 2609 | Lisp_Object |
| @@ -2770,7 +2641,7 @@ font_load_for_face (f, face) | |||
| 2770 | 2641 | ||
| 2771 | if (NILP (font_object)) | 2642 | if (NILP (font_object)) |
| 2772 | { | 2643 | { |
| 2773 | Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil); | 2644 | Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil, -1); |
| 2774 | 2645 | ||
| 2775 | if (! NILP (entity)) | 2646 | if (! NILP (entity)) |
| 2776 | font_object = font_open_for_lface (f, entity, face->lface, Qnil); | 2647 | font_object = font_open_for_lface (f, entity, face->lface, Qnil); |
| @@ -3433,18 +3304,19 @@ G-string is sequence of glyphs of a specific font, | |||
| 3433 | and is a vector of this form: | 3304 | and is a vector of this form: |
| 3434 | [ HEADER GLYPH ... ] | 3305 | [ HEADER GLYPH ... ] |
| 3435 | HEADER is a vector of this form: | 3306 | HEADER is a vector of this form: |
| 3436 | [FONT-OBJECT LBEARING RBEARING WIDTH ASCENT DESCENT] | 3307 | [FONT-OBJECT WIDTH LBEARING RBEARING ASCENT DESCENT] |
| 3437 | where | 3308 | where |
| 3438 | FONT-OBJECT is a font-object for all glyphs in the g-string, | 3309 | FONT-OBJECT is a font-object for all glyphs in the g-string, |
| 3439 | LBEARING thry DESCENT is the metrics (in pixels) of the whole G-string. | 3310 | WIDTH thry DESCENT are the metrics (in pixels) of the whole G-string. |
| 3440 | GLYPH is a vector of this form: | 3311 | GLYPH is a vector of this form: |
| 3441 | [ FROM-IDX TO-IDX C CODE WIDTH [ [X-OFF Y-OFF WADJUST] | nil] ] | 3312 | [ FROM-IDX TO-IDX C CODE WIDTH LBEARING RBEARING ASCENT DESCENT |
| 3313 | [ [X-OFF Y-OFF WADJUST] | nil] ] | ||
| 3442 | where | 3314 | where |
| 3443 | FROM-IDX and TO-IDX are used internally and should not be touched. | 3315 | FROM-IDX and TO-IDX are used internally and should not be touched. |
| 3444 | C is the character of the glyph. | 3316 | C is the character of the glyph. |
| 3445 | CODE is the glyph-code of C in FONT-OBJECT. | 3317 | CODE is the glyph-code of C in FONT-OBJECT. |
| 3318 | WIDTH thry DESCENT are the metrics (in pixels) of the glyph. | ||
| 3446 | X-OFF and Y-OFF are offests to the base position for the glyph. | 3319 | X-OFF and Y-OFF are offests to the base position for the glyph. |
| 3447 | WIDTH is the normal width of the glyph. | ||
| 3448 | WADJUST is the adjustment to the normal width of the glyph. */) | 3320 | WADJUST is the adjustment to the normal width of the glyph. */) |
| 3449 | (font_object, num) | 3321 | (font_object, num) |
| 3450 | Lisp_Object font_object, num; | 3322 | Lisp_Object font_object, num; |
| @@ -3463,7 +3335,7 @@ where | |||
| 3463 | ASET (g, 0, font_object); | 3335 | ASET (g, 0, font_object); |
| 3464 | ASET (gstring, 0, g); | 3336 | ASET (gstring, 0, g); |
| 3465 | for (i = 1; i < len; i++) | 3337 | for (i = 1; i < len; i++) |
| 3466 | ASET (gstring, i, Fmake_vector (make_number (8), Qnil)); | 3338 | ASET (gstring, i, Fmake_vector (make_number (10), Qnil)); |
| 3467 | return gstring; | 3339 | return gstring; |
| 3468 | } | 3340 | } |
| 3469 | 3341 | ||
| @@ -3494,7 +3366,7 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */) | |||
| 3494 | if (XINT (start) > XINT (end) | 3366 | if (XINT (start) > XINT (end) |
| 3495 | || XINT (end) > ASIZE (object) | 3367 | || XINT (end) > ASIZE (object) |
| 3496 | || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring)) | 3368 | || XINT (end) - XINT (start) > LGSTRING_LENGTH (gstring)) |
| 3497 | args_out_of_range (start, end); | 3369 | args_out_of_range_3 (object, start, end); |
| 3498 | 3370 | ||
| 3499 | len = XINT (end) - XINT (start); | 3371 | len = XINT (end) - XINT (start); |
| 3500 | p = SDATA (object) + string_char_to_byte (object, XINT (start)); | 3372 | p = SDATA (object) + string_char_to_byte (object, XINT (start)); |
| @@ -3506,10 +3378,10 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */) | |||
| 3506 | code = font->driver->encode_char (font, c); | 3378 | code = font->driver->encode_char (font, c); |
| 3507 | if (code > MOST_POSITIVE_FIXNUM) | 3379 | if (code > MOST_POSITIVE_FIXNUM) |
| 3508 | error ("Glyph code 0x%X is too large", code); | 3380 | error ("Glyph code 0x%X is too large", code); |
| 3509 | LGLYPH_SET_FROM (g, make_number (i)); | 3381 | LGLYPH_SET_FROM (g, i); |
| 3510 | LGLYPH_SET_TO (g, make_number (i + 1)); | 3382 | LGLYPH_SET_TO (g, i); |
| 3511 | LGLYPH_SET_CHAR (g, make_number (c)); | 3383 | LGLYPH_SET_CHAR (g, c); |
| 3512 | LGLYPH_SET_CODE (g, make_number (code)); | 3384 | LGLYPH_SET_CODE (g, code); |
| 3513 | } | 3385 | } |
| 3514 | } | 3386 | } |
| 3515 | else | 3387 | else |
| @@ -3532,19 +3404,123 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */) | |||
| 3532 | code = font->driver->encode_char (font, c); | 3404 | code = font->driver->encode_char (font, c); |
| 3533 | if (code > MOST_POSITIVE_FIXNUM) | 3405 | if (code > MOST_POSITIVE_FIXNUM) |
| 3534 | error ("Glyph code 0x%X is too large", code); | 3406 | error ("Glyph code 0x%X is too large", code); |
| 3535 | LGLYPH_SET_FROM (g, make_number (i)); | 3407 | LGLYPH_SET_FROM (g, i); |
| 3536 | LGLYPH_SET_TO (g, make_number (i + 1)); | 3408 | LGLYPH_SET_TO (g, i); |
| 3537 | LGLYPH_SET_CHAR (g, make_number (c)); | 3409 | LGLYPH_SET_CHAR (g, c); |
| 3538 | LGLYPH_SET_CODE (g, make_number (code)); | 3410 | LGLYPH_SET_CODE (g, code); |
| 3539 | } | 3411 | } |
| 3540 | } | 3412 | } |
| 3541 | for (i = LGSTRING_LENGTH (gstring) - 1; i >= len; i--) | 3413 | for (i = LGSTRING_LENGTH (gstring) - 1; i >= len; i--) |
| 3414 | LGSTRING_SET_GLYPH (gstring, i, Qnil); | ||
| 3415 | return Qnil; | ||
| 3416 | } | ||
| 3417 | |||
| 3418 | DEFUN ("font-shape-text", Ffont_shape_text, Sfont_shape_text, 3, 4, 0, | ||
| 3419 | doc: /* Shape text between FROM and TO by FONT-OBJECT. | ||
| 3420 | If optional 4th argument STRING is non-nil, it is a string to shape, | ||
| 3421 | and FROM and TO are indices to the string. | ||
| 3422 | The value is the end position of the shaped text. */) | ||
| 3423 | (from, to, font_object, string) | ||
| 3424 | Lisp_Object from, to, font_object, string; | ||
| 3425 | { | ||
| 3426 | struct font *font; | ||
| 3427 | struct font_metrics metrics; | ||
| 3428 | EMACS_INT start, end; | ||
| 3429 | Lisp_Object gstring, n; | ||
| 3430 | int i; | ||
| 3431 | |||
| 3432 | if (NILP (string)) | ||
| 3433 | { | ||
| 3434 | validate_region (&from, &to); | ||
| 3435 | start = XFASTINT (from); | ||
| 3436 | end = XFASTINT (to); | ||
| 3437 | modify_region (current_buffer, start, end, 0); | ||
| 3438 | } | ||
| 3439 | else | ||
| 3440 | { | ||
| 3441 | CHECK_STRING (string); | ||
| 3442 | start = XINT (from); | ||
| 3443 | end = XINT (to); | ||
| 3444 | if (start < 0 || start > end || end > SCHARS (string)) | ||
| 3445 | args_out_of_range_3 (string, from, to); | ||
| 3446 | } | ||
| 3447 | |||
| 3448 | CHECK_FONT_GET_OBJECT (font_object, font); | ||
| 3449 | if (! font->driver->shape) | ||
| 3450 | return from; | ||
| 3451 | |||
| 3452 | gstring = Ffont_make_gstring (font_object, make_number (end - start)); | ||
| 3453 | Ffont_fill_gstring (gstring, font_object, from, to, string); | ||
| 3454 | n = font->driver->shape (gstring); | ||
| 3455 | if (NILP (n)) | ||
| 3456 | return Qnil; | ||
| 3457 | for (i = 0; i < XINT (n);) | ||
| 3542 | { | 3458 | { |
| 3459 | Lisp_Object gstr; | ||
| 3543 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); | 3460 | Lisp_Object g = LGSTRING_GLYPH (gstring, i); |
| 3461 | EMACS_INT this_from = LGLYPH_FROM (g); | ||
| 3462 | EMACS_INT this_to = LGLYPH_TO (g) + 1; | ||
| 3463 | int j, k; | ||
| 3464 | |||
| 3465 | metrics.lbearing = LGLYPH_LBEARING (g); | ||
| 3466 | metrics.rbearing = LGLYPH_RBEARING (g); | ||
| 3467 | metrics.ascent = LGLYPH_ASCENT (g); | ||
| 3468 | metrics.descent = LGLYPH_DESCENT (g); | ||
| 3469 | if (NILP (LGLYPH_ADJUSTMENT (g))) | ||
| 3470 | metrics.width = LGLYPH_WIDTH (g); | ||
| 3471 | else | ||
| 3472 | { | ||
| 3473 | metrics.width = LGLYPH_WADJUST (g); | ||
| 3474 | metrics.lbearing += LGLYPH_XOFF (g); | ||
| 3475 | metrics.rbearing += LGLYPH_XOFF (g); | ||
| 3476 | metrics.ascent -= LGLYPH_YOFF (g); | ||
| 3477 | metrics.descent += LGLYPH_YOFF (g); | ||
| 3478 | } | ||
| 3479 | for (j = i + 1; j < XINT (n); j++) | ||
| 3480 | { | ||
| 3481 | int x; | ||
| 3482 | |||
| 3483 | g = LGSTRING_GLYPH (gstring, j); | ||
| 3484 | if (this_from != LGLYPH_FROM (g)) | ||
| 3485 | break; | ||
| 3486 | x = metrics.width + LGLYPH_LBEARING (g) + LGLYPH_XOFF (g); | ||
| 3487 | if (metrics.lbearing > x) | ||
| 3488 | metrics.lbearing = x; | ||
| 3489 | x = metrics.width + LGLYPH_RBEARING (g) + LGLYPH_XOFF (g); | ||
| 3490 | if (metrics.rbearing < x) | ||
| 3491 | metrics.rbearing = x; | ||
| 3492 | x = LGLYPH_ASCENT (g) - LGLYPH_YOFF (g); | ||
| 3493 | if (metrics.ascent < x) | ||
| 3494 | metrics.ascent = x; | ||
| 3495 | x = LGLYPH_DESCENT (g) - LGLYPH_YOFF (g); | ||
| 3496 | if (metrics.descent < x) | ||
| 3497 | metrics.descent = x; | ||
| 3498 | if (NILP (LGLYPH_ADJUSTMENT (g))) | ||
| 3499 | metrics.width += LGLYPH_WIDTH (g); | ||
| 3500 | else | ||
| 3501 | metrics.width += LGLYPH_WADJUST (g); | ||
| 3502 | } | ||
| 3544 | 3503 | ||
| 3545 | LGLYPH_SET_FROM (g, Qnil); | 3504 | gstr = Ffont_make_gstring (font_object, make_number (j - i)); |
| 3505 | LGSTRING_SET_WIDTH (gstr, metrics.width); | ||
| 3506 | LGSTRING_SET_LBEARING (gstr, metrics.lbearing); | ||
| 3507 | LGSTRING_SET_RBEARING (gstr, metrics.rbearing); | ||
| 3508 | LGSTRING_SET_ASCENT (gstr, metrics.ascent); | ||
| 3509 | LGSTRING_SET_DESCENT (gstr, metrics.descent); | ||
| 3510 | for (k = i; i < j; i++) | ||
| 3511 | LGSTRING_SET_GLYPH (gstr, i - k, LGSTRING_GLYPH (gstring, i)); | ||
| 3512 | if (NILP (string)) | ||
| 3513 | Fcompose_region_internal (make_number (start + this_from), | ||
| 3514 | make_number (start + this_to), | ||
| 3515 | gstr, Qnil); | ||
| 3516 | else | ||
| 3517 | Fcompose_string_internal (string, | ||
| 3518 | make_number (start + this_from), | ||
| 3519 | make_number (start + this_to), | ||
| 3520 | gstr, Qnil); | ||
| 3546 | } | 3521 | } |
| 3547 | return Qnil; | 3522 | |
| 3523 | return make_number (start + XINT (n)); | ||
| 3548 | } | 3524 | } |
| 3549 | 3525 | ||
| 3550 | DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0, | 3526 | DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0, |
| @@ -3687,6 +3663,8 @@ DEFUN ("open-font", Fopen_font, Sopen_font, 1, 3, 0, | |||
| 3687 | CHECK_LIVE_FRAME (frame); | 3663 | CHECK_LIVE_FRAME (frame); |
| 3688 | 3664 | ||
| 3689 | isize = XINT (size); | 3665 | isize = XINT (size); |
| 3666 | if (isize == 0) | ||
| 3667 | isize = 120; | ||
| 3690 | if (isize < 0) | 3668 | if (isize < 0) |
| 3691 | isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy); | 3669 | isize = POINT_TO_PIXEL (- isize, XFRAME (frame)->resy); |
| 3692 | 3670 | ||
| @@ -3832,23 +3810,41 @@ FONT is a font-spec, font-entity, or font-object. */) | |||
| 3832 | return (font_match_p (spec, font) ? Qt : Qnil); | 3810 | return (font_match_p (spec, font) ? Qt : Qnil); |
| 3833 | } | 3811 | } |
| 3834 | 3812 | ||
| 3835 | DEFUN ("font-at", Ffont_at, Sfont_at, 1, 2, 0, | 3813 | DEFUN ("font-at", Ffont_at, Sfont_at, 1, 3, 0, |
| 3836 | doc: /* Return a font-object for displaying a character at POSISTION. | 3814 | doc: /* Return a font-object for displaying a character at POSISTION. |
| 3837 | Optional second arg WINDOW, if non-nil, is a window displaying | 3815 | Optional second arg WINDOW, if non-nil, is a window displaying |
| 3838 | the current buffer. It defaults to the currently selected window. */) | 3816 | the current buffer. It defaults to the currently selected window. */) |
| 3839 | (position, window) | 3817 | (position, window, string) |
| 3840 | Lisp_Object position, window; | 3818 | Lisp_Object position, window, string; |
| 3841 | { | 3819 | { |
| 3842 | struct window *w; | 3820 | struct window *w; |
| 3843 | EMACS_INT pos, pos_byte; | 3821 | EMACS_INT pos, pos_byte; |
| 3844 | int c; | 3822 | int c; |
| 3845 | 3823 | ||
| 3846 | CHECK_NUMBER_COERCE_MARKER (position); | 3824 | if (NILP (string)) |
| 3847 | pos = XINT (position); | 3825 | { |
| 3848 | if (pos < BEGV || pos >= ZV) | 3826 | CHECK_NUMBER_COERCE_MARKER (position); |
| 3849 | args_out_of_range_3 (position, make_number (BEGV), make_number (ZV)); | 3827 | pos = XINT (position); |
| 3850 | pos_byte = CHAR_TO_BYTE (pos); | 3828 | if (pos < BEGV || pos >= ZV) |
| 3851 | c = FETCH_CHAR (pos_byte); | 3829 | args_out_of_range_3 (position, make_number (BEGV), make_number (ZV)); |
| 3830 | pos_byte = CHAR_TO_BYTE (pos); | ||
| 3831 | c = FETCH_CHAR (pos_byte); | ||
| 3832 | } | ||
| 3833 | else | ||
| 3834 | { | ||
| 3835 | EMACS_INT len; | ||
| 3836 | unsigned char *str; | ||
| 3837 | |||
| 3838 | CHECK_NUMBER (position); | ||
| 3839 | CHECK_STRING (string); | ||
| 3840 | pos = XINT (position); | ||
| 3841 | if (pos < 0 || pos >= SCHARS (string)) | ||
| 3842 | args_out_of_range (string, position); | ||
| 3843 | pos_byte = string_char_to_byte (string, pos); | ||
| 3844 | str = SDATA (string) + pos_byte; | ||
| 3845 | len = SBYTES (string) - pos_byte; | ||
| 3846 | c = STRING_CHAR (str, eln); | ||
| 3847 | } | ||
| 3852 | if (NILP (window)) | 3848 | if (NILP (window)) |
| 3853 | window = selected_window; | 3849 | window = selected_window; |
| 3854 | CHECK_LIVE_WINDOW (window); | 3850 | CHECK_LIVE_WINDOW (window); |
| @@ -3929,6 +3925,9 @@ syms_of_font () | |||
| 3929 | staticpro (&font_family_alist); | 3925 | staticpro (&font_family_alist); |
| 3930 | font_family_alist = Qnil; | 3926 | font_family_alist = Qnil; |
| 3931 | 3927 | ||
| 3928 | staticpro (&font_charset_alist); | ||
| 3929 | font_charset_alist = Qnil; | ||
| 3930 | |||
| 3932 | DEFSYM (Qopentype, "opentype"); | 3931 | DEFSYM (Qopentype, "opentype"); |
| 3933 | 3932 | ||
| 3934 | DEFSYM (Qiso8859_1, "iso8859-1"); | 3933 | DEFSYM (Qiso8859_1, "iso8859-1"); |
| @@ -3981,6 +3980,7 @@ syms_of_font () | |||
| 3981 | defsubr (&Sinternal_set_font_style_table); | 3980 | defsubr (&Sinternal_set_font_style_table); |
| 3982 | defsubr (&Sfont_make_gstring); | 3981 | defsubr (&Sfont_make_gstring); |
| 3983 | defsubr (&Sfont_fill_gstring); | 3982 | defsubr (&Sfont_fill_gstring); |
| 3983 | defsubr (&Sfont_shape_text); | ||
| 3984 | defsubr (&Sfont_drive_otf); | 3984 | defsubr (&Sfont_drive_otf); |
| 3985 | defsubr (&Sfont_otf_alternates); | 3985 | defsubr (&Sfont_otf_alternates); |
| 3986 | 3986 | ||
| @@ -3996,29 +3996,34 @@ syms_of_font () | |||
| 3996 | #endif | 3996 | #endif |
| 3997 | #endif /* FONT_DEBUG */ | 3997 | #endif /* FONT_DEBUG */ |
| 3998 | 3998 | ||
| 3999 | #ifdef USE_FONT_BACKEND | ||
| 4000 | if (enable_font_backend) | ||
| 4001 | { | ||
| 3999 | #ifdef HAVE_FREETYPE | 4002 | #ifdef HAVE_FREETYPE |
| 4000 | syms_of_ftfont (); | 4003 | syms_of_ftfont (); |
| 4001 | #ifdef HAVE_X_WINDOWS | 4004 | #ifdef HAVE_X_WINDOWS |
| 4002 | syms_of_xfont (); | 4005 | syms_of_xfont (); |
| 4003 | syms_of_ftxfont (); | 4006 | syms_of_ftxfont (); |
| 4004 | #ifdef HAVE_XFT | 4007 | #ifdef HAVE_XFT |
| 4005 | syms_of_xftfont (); | 4008 | syms_of_xftfont (); |
| 4006 | #endif /* HAVE_XFT */ | 4009 | #endif /* HAVE_XFT */ |
| 4007 | #endif /* HAVE_X_WINDOWS */ | 4010 | #endif /* HAVE_X_WINDOWS */ |
| 4008 | #else /* not HAVE_FREETYPE */ | 4011 | #else /* not HAVE_FREETYPE */ |
| 4009 | #ifdef HAVE_X_WINDOWS | 4012 | #ifdef HAVE_X_WINDOWS |
| 4010 | syms_of_xfont (); | 4013 | syms_of_xfont (); |
| 4011 | #endif /* HAVE_X_WINDOWS */ | 4014 | #endif /* HAVE_X_WINDOWS */ |
| 4012 | #endif /* not HAVE_FREETYPE */ | 4015 | #endif /* not HAVE_FREETYPE */ |
| 4013 | #ifdef HAVE_BDFFONT | 4016 | #ifdef HAVE_BDFFONT |
| 4014 | syms_of_bdffont (); | 4017 | syms_of_bdffont (); |
| 4015 | #endif /* HAVE_BDFFONT */ | 4018 | #endif /* HAVE_BDFFONT */ |
| 4016 | #ifdef WINDOWSNT | 4019 | #ifdef WINDOWSNT |
| 4017 | syms_of_w32font (); | 4020 | syms_of_w32font (); |
| 4018 | #endif /* WINDOWSNT */ | 4021 | #endif /* WINDOWSNT */ |
| 4019 | #ifdef MAC_OS | 4022 | #ifdef MAC_OS |
| 4020 | syms_of_atmfont (); | 4023 | syms_of_atmfont (); |
| 4021 | #endif /* MAC_OS */ | 4024 | #endif /* MAC_OS */ |
| 4025 | } | ||
| 4026 | #endif /* USE_FONT_BACKEND */ | ||
| 4022 | } | 4027 | } |
| 4023 | 4028 | ||
| 4024 | /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846 | 4029 | /* arch-tag: 74c9475d-5976-4c93-a327-942ae3072846 |