aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2007-04-25 12:05:28 +0000
committerKenichi Handa2007-04-25 12:05:28 +0000
commit733fd013f650474c6104b6b4f05c1db52a068a9b (patch)
treeaaa6c879e69b785195ecd49cbfe751f59b4314a6 /src
parentc927d1df98dfd0ce154d32372ae10577c89f3308 (diff)
downloademacs-733fd013f650474c6104b6b4f05c1db52a068a9b.tar.gz
emacs-733fd013f650474c6104b6b4f05c1db52a068a9b.zip
(struct otf_list): Delete it.
(otf_list): Make it a lisp variable.. (otf_open): Use lispy otf_list. (generate_otf_features): Renamed from parse_gsub_gpos_spec. (check_otf_features): New function. (font_otf_DeviceTable, font_otf_ValueRecord, font_otf_Anchor): New functinos. (font_drive_otf): New function merging font_otf_gsub and font_otf_gpos. (font_open_for_lface): New arg spec. Change argument order. (font_load_for_face): Adjusted for the change of font_open_for_lface. (Ffont_drive_otf): New function merging Ffont_otf_gsub and Ffont_otf_gpos. (syms_of_font): Staticpro otf_list. Delete defsubr of Sfont_otf_gsub and Sfont_otf_gpos. Defsubr Sfont_drive_otf.
Diffstat (limited to 'src')
-rw-r--r--src/font.c627
1 files changed, 319 insertions, 308 deletions
diff --git a/src/font.c b/src/font.c
index e6d38dee2fb..1eedbe04bbc 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1483,14 +1483,7 @@ check_gstring (gstring)
1483#ifdef HAVE_LIBOTF 1483#ifdef HAVE_LIBOTF
1484#include <otf.h> 1484#include <otf.h>
1485 1485
1486struct otf_list 1486Lisp_Object otf_list;
1487{
1488 Lisp_Object entity;
1489 OTF *otf;
1490 struct otf_list *next;
1491};
1492
1493static struct otf_list *otf_list;
1494 1487
1495static Lisp_Object 1488static Lisp_Object
1496otf_tag_symbol (tag) 1489otf_tag_symbol (tag)
@@ -1507,19 +1500,18 @@ otf_open (entity, file)
1507 Lisp_Object entity; 1500 Lisp_Object entity;
1508 char *file; 1501 char *file;
1509{ 1502{
1510 struct otf_list *list = otf_list; 1503 Lisp_Object val = Fassoc (entity, otf_list);
1511 1504 OTF *otf;
1512 while (list && ! EQ (list->entity, entity)) 1505
1513 list = list->next; 1506 if (! NILP (val))
1514 if (! list) 1507 otf = XSAVE_VALUE (XCDR (val))->pointer;
1508 else
1515 { 1509 {
1516 list = malloc (sizeof (struct otf_list)); 1510 otf = file ? OTF_open (file) : NULL;
1517 list->entity = entity; 1511 val = make_save_value (otf, 0);
1518 list->otf = file ? OTF_open (file) : NULL; 1512 otf_list = Fcons (Fcons (entity, val), otf_list);
1519 list->next = otf_list;
1520 otf_list = list;
1521 } 1513 }
1522 return list->otf; 1514 return otf;
1523} 1515}
1524 1516
1525 1517
@@ -1597,58 +1589,41 @@ font_otf_capability (font)
1597 return capability; 1589 return capability;
1598} 1590}
1599 1591
1592/* Parse OTF features in SPEC and write a proper features spec string
1593 in FEATURES for the call of OTF_drive_gsub/gpos (of libotf). It is
1594 assured that the sufficient memory has already allocated for
1595 FEATURES. */
1596
1600static void 1597static void
1601parse_gsub_gpos_spec (spec, script, langsys, features, nbytes) 1598generate_otf_features (spec, features)
1602 Lisp_Object spec; 1599 Lisp_Object spec;
1603 char **script, **langsys, *features; 1600 char *features;
1604 int nbytes;
1605{ 1601{
1606 Lisp_Object val; 1602 Lisp_Object val;
1607 char *p, *pend; 1603 char *p, *pend;
1608 int asterisk; 1604 int asterisk;
1609 1605
1610 CHECK_CONS (spec); 1606 p = features;
1611 val = XCAR (spec);
1612 CHECK_SYMBOL (val);
1613 *script = (char *) SDATA (SYMBOL_NAME (val));
1614 spec = XCDR (spec);
1615 CHECK_CONS (spec);
1616 val = XCAR (spec);
1617 CHECK_SYMBOL (val);
1618 *langsys = NILP (val) ? NULL : (char *) SDATA (SYMBOL_NAME (val));
1619 spec = XCDR (spec);
1620
1621 p = features, pend = p + nbytes - 1;
1622 *p = '\0'; 1607 *p = '\0';
1623 for (asterisk = 0; CONSP (spec); spec = XCDR (spec)) 1608 for (asterisk = 0; CONSP (spec); spec = XCDR (spec))
1624 { 1609 {
1625 val = XCAR (spec); 1610 val = XCAR (spec);
1626 CHECK_SYMBOL (val); 1611 CHECK_SYMBOL (val);
1627 if (p > features) 1612 if (p > features)
1628 { 1613 *p++ = ',';
1629 if (p >= pend)
1630 break;
1631 *p++ = ',';
1632 }
1633 if (SREF (SYMBOL_NAME (val), 0) == '*') 1614 if (SREF (SYMBOL_NAME (val), 0) == '*')
1634 { 1615 {
1635 asterisk = 1; 1616 asterisk = 1;
1636 if (p >= pend)
1637 break;
1638 *p++ = '*'; 1617 *p++ = '*';
1639 } 1618 }
1640 else if (! asterisk) 1619 else if (! asterisk)
1641 { 1620 {
1642 val = SYMBOL_NAME (val); 1621 val = SYMBOL_NAME (val);
1643 if (p + SBYTES (val) >= pend)
1644 break;
1645 p += sprintf (p, "%s", SDATA (val)); 1622 p += sprintf (p, "%s", SDATA (val));
1646 } 1623 }
1647 else 1624 else
1648 { 1625 {
1649 val = SYMBOL_NAME (val); 1626 val = SYMBOL_NAME (val);
1650 if (p + 1 + SBYTES (val)>= pend)
1651 break;
1652 p += sprintf (p, "~%s", SDATA (val)); 1627 p += sprintf (p, "~%s", SDATA (val));
1653 } 1628 }
1654 } 1629 }
@@ -1682,30 +1657,131 @@ adjust_anchor (struct font *font, OTF_Anchor *anchor,
1682 } 1657 }
1683} 1658}
1684 1659
1660static void
1661check_otf_features (otf_features)
1662 Lisp_Object otf_features;
1663{
1664 Lisp_Object val, elt;
1665
1666 CHECK_CONS (otf_features);
1667 CHECK_SYMBOL (XCAR (otf_features));
1668 otf_features = XCDR (otf_features);
1669 CHECK_CONS (otf_features);
1670 CHECK_SYMBOL (XCAR (otf_features));
1671 otf_features = XCDR (otf_features);
1672 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1673 {
1674 CHECK_SYMBOL (Fcar (val));
1675 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1676 error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
1677 }
1678 otf_features = XCDR (otf_features);
1679 for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
1680 {
1681 CHECK_SYMBOL (Fcar (val));
1682 if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
1683 error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
1684 }
1685}
1686
1687Lisp_Object
1688font_otf_DeviceTable (device_table)
1689 OTF_DeviceTable *device_table;
1690{
1691 int len = device_table->StartSize - device_table->EndSize + 1;
1692
1693 return Fcons (make_number (len),
1694 make_unibyte_string (device_table->DeltaValue, len));
1695}
1696
1697Lisp_Object
1698font_otf_ValueRecord (value_format, value_record)
1699 int value_format;
1700 OTF_ValueRecord *value_record;
1701{
1702 Lisp_Object val = Fmake_vector (make_number (8), Qnil);
1703
1704 if (value_format & OTF_XPlacement)
1705 ASET (val, 0, value_record->XPlacement);
1706 if (value_format & OTF_YPlacement)
1707 ASET (val, 1, value_record->YPlacement);
1708 if (value_format & OTF_XAdvance)
1709 ASET (val, 2, value_record->XAdvance);
1710 if (value_format & OTF_YAdvance)
1711 ASET (val, 3, value_record->YAdvance);
1712 if (value_format & OTF_XPlaDevice)
1713 ASET (val, 4, font_otf_DeviceTable (&value_record->XPlaDevice));
1714 if (value_format & OTF_YPlaDevice)
1715 ASET (val, 4, font_otf_DeviceTable (&value_record->YPlaDevice));
1716 if (value_format & OTF_XAdvDevice)
1717 ASET (val, 4, font_otf_DeviceTable (&value_record->XAdvDevice));
1718 if (value_format & OTF_YAdvDevice)
1719 ASET (val, 4, font_otf_DeviceTable (&value_record->YAdvDevice));
1720 return val;
1721}
1722
1723Lisp_Object
1724font_otf_Anchor (anchor)
1725 OTF_Anchor *anchor;
1726{
1727 Lisp_Object val;
1728
1729 val = Fmake_vector (make_number (anchor->AnchorFormat + 1), Qnil);
1730 ASET (val, 0, make_number (anchor->XCoordinate));
1731 ASET (val, 1, make_number (anchor->YCoordinate));
1732 if (anchor->AnchorFormat == 2)
1733 ASET (val, 2, make_number (anchor->f.f1.AnchorPoint));
1734 else
1735 {
1736 ASET (val, 3, font_otf_DeviceTable (&anchor->f.f2.XDeviceTable));
1737 ASET (val, 4, font_otf_DeviceTable (&anchor->f.f2.YDeviceTable));
1738 }
1739 return val;
1740}
1741
1685#define REPLACEMENT_CHARACTER 0xFFFD 1742#define REPLACEMENT_CHARACTER 0xFFFD
1686 1743
1687/* Drive FONT's OTF GSUB features according to GSUB_SPEC. See the 1744/* Drive FONT's OpenType FEATURES. See the comment of (sturct
1688 comment of (sturct font_driver).otf_gsub. */ 1745 font_driver).drive_otf. */
1689 1746
1690int 1747int
1691font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx, 1748font_drive_otf (font, otf_features, gstring_in, from, to, gstring_out, idx,
1692 alternate_subst) 1749 alternate_subst)
1693 struct font *font; 1750 struct font *font;
1694 Lisp_Object gsub_spec; 1751 Lisp_Object otf_features;
1695 Lisp_Object gstring_in; 1752 Lisp_Object gstring_in;
1696 int from, to; 1753 int from, to;
1697 Lisp_Object gstring_out; 1754 Lisp_Object gstring_out;
1698 int idx, alternate_subst; 1755 int idx, alternate_subst;
1699{ 1756{
1757 Lisp_Object val;
1700 int len; 1758 int len;
1701 int i; 1759 int i;
1702 OTF *otf; 1760 OTF *otf;
1703 OTF_GlyphString otf_gstring; 1761 OTF_GlyphString otf_gstring;
1704 OTF_Glyph *g; 1762 OTF_Glyph *g;
1705 char *script, *langsys, features[256]; 1763 char *script, *langsys = NULL, *gsub_features = NULL, *gpos_features = NULL;
1706 int need_cmap; 1764 int need_cmap;
1707 1765
1708 parse_gsub_gpos_spec (gsub_spec, &script, &langsys, features, 256); 1766 val = XCAR (otf_features);
1767 script = SDATA (SYMBOL_NAME (val));
1768 otf_features = XCDR (otf_features);
1769 val = XCAR (otf_features);
1770 langsys = NILP (val) ? NULL : SDATA (SYMBOL_NAME (val));
1771 otf_features = XCDR (otf_features);
1772 val = XCAR (otf_features);
1773 if (! NILP (val))
1774 {
1775 gsub_features = alloca (XINT (Flength (val)) * 6);
1776 generate_otf_features (val, &script, &langsys, gsub_features);
1777 }
1778 otf_features = XCDR (otf_features);
1779 val = XCAR (otf_features);
1780 if (! NILP (val))
1781 {
1782 gpos_features = alloca (XINT (Flength (val)) * 6);
1783 generate_otf_features (val, &script, &langsys, gpos_features);
1784 }
1709 1785
1710 otf = otf_open (font->entity, font->file_name); 1786 otf = otf_open (font->entity, font->file_name);
1711 if (! otf) 1787 if (! otf)
@@ -1714,8 +1790,10 @@ font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx,
1714 return 0; 1790 return 0;
1715 if (OTF_get_table (otf, "cmap") < 0) 1791 if (OTF_get_table (otf, "cmap") < 0)
1716 return 0; 1792 return 0;
1717 if (OTF_check_table (otf, "GSUB") < 0) 1793 if ((! gsub_features || OTF_check_table (otf, "GSUB") < 0)
1718 return 0; 1794 && (! gpos_features || OTF_check_table (otf, "GPOS") < 0))
1795 return 0;
1796
1719 len = to - from; 1797 len = to - from;
1720 otf_gstring.size = otf_gstring.used = len; 1798 otf_gstring.size = otf_gstring.used = len;
1721 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len); 1799 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
@@ -1735,216 +1813,164 @@ font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx,
1735 else 1813 else
1736 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (g)); 1814 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (g));
1737 } 1815 }
1738
1739 if (need_cmap) 1816 if (need_cmap)
1740 OTF_drive_cmap (otf, &otf_gstring); 1817 OTF_drive_cmap (otf, &otf_gstring);
1741 OTF_drive_gdef (otf, &otf_gstring); 1818 OTF_drive_gdef (otf, &otf_gstring);
1742 if ((alternate_subst
1743 ? OTF_drive_gsub_alternate (otf, &otf_gstring, script, langsys, features)
1744 : OTF_drive_gsub (otf, &otf_gstring, script, langsys, features)) < 0)
1745 {
1746 free (otf_gstring.glyphs);
1747 return 0;
1748 }
1749 if (ASIZE (gstring_out) < idx + otf_gstring.used)
1750 {
1751 free (otf_gstring.glyphs);
1752 return -1;
1753 }
1754 1819
1755 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used;) 1820 if (gsub_features)
1756 { 1821 {
1757 int i0 = g->f.index.from, i1 = g->f.index.to; 1822 if ((alternate_subst
1758 Lisp_Object glyph = LGSTRING_GLYPH (gstring_in, from + i0); 1823 ? OTF_drive_gsub_alternate (otf, &otf_gstring, script, langsys,
1759 Lisp_Object min_idx = AREF (glyph, 0); 1824 gsub_features)
1760 Lisp_Object max_idx = AREF (glyph, 1); 1825 : OTF_drive_gsub (otf, &otf_gstring, script, langsys,
1761 1826 gsub_features)) < 0)
1762 if (i0 < i1)
1763 { 1827 {
1764 int min_idx_i = XINT (min_idx), max_idx_i = XINT (max_idx); 1828 free (otf_gstring.glyphs);
1765 1829 return 0;
1766 for (i0++; i0 <= i1; i0++)
1767 {
1768 glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1769 if (min_idx_i > XINT (AREF (glyph, 0)))
1770 min_idx_i = XINT (AREF (glyph, 0));
1771 if (max_idx_i < XINT (AREF (glyph, 1)))
1772 max_idx_i = XINT (AREF (glyph, 1));
1773 }
1774 min_idx = make_number (min_idx_i);
1775 max_idx = make_number (max_idx_i);
1776 i0 = g->f.index.from;
1777 } 1830 }
1778 for (; i < otf_gstring.used && g->f.index.from == i0; i++, g++) 1831 if (ASIZE (gstring_out) < idx + otf_gstring.used)
1779 { 1832 {
1780 glyph = LGSTRING_GLYPH (gstring_out, idx + i); 1833 free (otf_gstring.glyphs);
1781 ASET (glyph, 0, min_idx); 1834 return -1;
1782 ASET (glyph, 1, max_idx);
1783 if (g->c > 0)
1784 LGLYPH_SET_CHAR (glyph, make_number (g->c));
1785 else
1786 LGLYPH_SET_CHAR (glyph, make_number (REPLACEMENT_CHARACTER));
1787 LGLYPH_SET_CODE (glyph, make_number (g->glyph_id));
1788 } 1835 }
1789 } 1836 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used;)
1790 1837 {
1791 free (otf_gstring.glyphs); 1838 int i0 = g->f.index.from, i1 = g->f.index.to;
1792 return i; 1839 Lisp_Object glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1793} 1840 Lisp_Object min_idx = AREF (glyph, 0);
1794 1841 Lisp_Object max_idx = AREF (glyph, 1);
1795/* Drive FONT's OTF GPOS features according to GPOS_SPEC. See the
1796 comment of (sturct font_driver).otf_gpos. */
1797
1798int
1799font_otf_gpos (font, gpos_spec, gstring, from, to)
1800 struct font *font;
1801 Lisp_Object gpos_spec;
1802 Lisp_Object gstring;
1803 int from, to;
1804{
1805 int len;
1806 int i;
1807 OTF *otf;
1808 OTF_GlyphString otf_gstring;
1809 OTF_Glyph *g;
1810 char *script, *langsys, features[256];
1811 int need_cmap;
1812 Lisp_Object glyph;
1813 int u, size;
1814 Lisp_Object base, mark;
1815 1842
1816 parse_gsub_gpos_spec (gpos_spec, &script, &langsys, features, 256); 1843 if (i0 < i1)
1844 {
1845 int min_idx_i = XINT (min_idx), max_idx_i = XINT (max_idx);
1817 1846
1818 otf = otf_open (font->entity, font->file_name); 1847 for (i0++; i0 <= i1; i0++)
1819 if (! otf) 1848 {
1820 return 0; 1849 glyph = LGSTRING_GLYPH (gstring_in, from + i0);
1821 if (OTF_get_table (otf, "head") < 0) 1850 if (min_idx_i > XINT (AREF (glyph, 0)))
1822 return 0; 1851 min_idx_i = XINT (AREF (glyph, 0));
1823 if (OTF_get_table (otf, "cmap") < 0) 1852 if (max_idx_i < XINT (AREF (glyph, 1)))
1824 return 0; 1853 max_idx_i = XINT (AREF (glyph, 1));
1825 if (OTF_check_table (otf, "GPOS") < 0) 1854 }
1826 return 0; 1855 min_idx = make_number (min_idx_i);
1827 len = to - from; 1856 max_idx = make_number (max_idx_i);
1828 otf_gstring.size = otf_gstring.used = len; 1857 i0 = g->f.index.from;
1829 otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len); 1858 }
1830 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len); 1859 for (; i < otf_gstring.used && g->f.index.from == i0; i++, g++)
1831 for (i = 0, need_cmap = 0; i < len; i++) 1860 {
1832 { 1861 glyph = LGSTRING_GLYPH (gstring_out, idx + i);
1833 glyph = LGSTRING_GLYPH (gstring, from + i); 1862 ASET (glyph, 0, min_idx);
1834 otf_gstring.glyphs[i].c = XINT (LGLYPH_CHAR (glyph)); 1863 ASET (glyph, 1, max_idx);
1835 if (otf_gstring.glyphs[i].c == REPLACEMENT_CHARACTER) 1864 if (g->c > 0)
1836 otf_gstring.glyphs[i].c = 0; 1865 LGLYPH_SET_CHAR (glyph, make_number (g->c));
1837 if (NILP (LGLYPH_CODE (glyph))) 1866 else
1838 { 1867 LGLYPH_SET_CHAR (glyph, make_number (REPLACEMENT_CHARACTER));
1839 otf_gstring.glyphs[i].glyph_id = 0; 1868 LGLYPH_SET_CODE (glyph, make_number (g->glyph_id));
1840 need_cmap = 1; 1869 }
1841 } 1870 }
1842 else
1843 otf_gstring.glyphs[i].glyph_id = XINT (LGLYPH_CODE (glyph));
1844 }
1845 if (need_cmap)
1846 OTF_drive_cmap (otf, &otf_gstring);
1847 OTF_drive_gdef (otf, &otf_gstring);
1848
1849 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, features) < 0)
1850 {
1851 free (otf_gstring.glyphs);
1852 return 0;
1853 } 1871 }
1854 1872
1855 u = otf->head->unitsPerEm; 1873 if (gpos_features)
1856 size = font->pixel_size;
1857 base = mark = Qnil;
1858 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used; i++, g++)
1859 { 1874 {
1860 Lisp_Object prev; 1875 Lisp_Object glyph;
1861 int xoff = 0, yoff = 0, width_adjust = 0; 1876 int u = otf->head->unitsPerEm;
1862 1877 int size = font->pixel_size;
1863 if (! g->glyph_id) 1878 Lisp_Object base = Qnil, mark = Qnil;
1864 continue;
1865 1879
1866 glyph = LGSTRING_GLYPH (gstring, from + i); 1880 if (OTF_drive_gpos (otf, &otf_gstring, script, langsys,
1867 switch (g->positioning_type) 1881 gpos_features) < 0)
1868 { 1882 {
1869 case 0: 1883 free (otf_gstring.glyphs);
1870 break; 1884 return 0;
1871 case 1: case 2: 1885 }
1872 { 1886 for (i = 0, g = otf_gstring.glyphs; i < otf_gstring.used; i++, g++)
1873 int format = g->f.f1.format; 1887 {
1874 1888 Lisp_Object prev;
1875 if (format & OTF_XPlacement) 1889 int xoff = 0, yoff = 0, width_adjust = 0;
1876 xoff = g->f.f1.value->XPlacement * size / u;
1877 if (format & OTF_XPlaDevice)
1878 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, size);
1879 if (format & OTF_YPlacement)
1880 yoff = - (g->f.f1.value->YPlacement * size / u);
1881 if (format & OTF_YPlaDevice)
1882 yoff -= DEVICE_DELTA (g->f.f1.value->YPlaDevice, size);
1883 if (format & OTF_XAdvance)
1884 width_adjust += g->f.f1.value->XAdvance * size / u;
1885 if (format & OTF_XAdvDevice)
1886 width_adjust += DEVICE_DELTA (g->f.f1.value->XAdvDevice, size);
1887 }
1888 break;
1889 case 3:
1890 /* Not yet supported. */
1891 break;
1892 case 4: case 5:
1893 if (NILP (base))
1894 break;
1895 prev = base;
1896 goto label_adjust_anchor;
1897 default: /* i.e. case 6 */
1898 if (NILP (mark))
1899 break;
1900 prev = mark;
1901 1890
1902 label_adjust_anchor: 1891 if (! g->glyph_id)
1903 { 1892 continue;
1904 int base_x, base_y, mark_x, mark_y, width; 1893
1905 unsigned code; 1894 switch (g->positioning_type)
1906 1895 {
1907 base_x = g->f.f4.base_anchor->XCoordinate * size / u; 1896 case 0:
1908 base_y = g->f.f4.base_anchor->YCoordinate * size / u; 1897 break;
1909 mark_x = g->f.f4.mark_anchor->XCoordinate * size / u; 1898 case 1: case 2:
1910 mark_y = g->f.f4.mark_anchor->YCoordinate * size / u;
1911
1912 code = XINT (LGLYPH_CODE (prev));
1913 if (g->f.f4.base_anchor->AnchorFormat != 1)
1914 adjust_anchor (font, g->f.f4.base_anchor,
1915 code, size, &base_x, &base_y);
1916 if (g->f.f4.mark_anchor->AnchorFormat != 1)
1917 adjust_anchor (font, g->f.f4.mark_anchor,
1918 code, size, &mark_x, &mark_y);
1919
1920 if (NILP (LGLYPH_WIDTH (prev)))
1921 { 1899 {
1922 width = font->driver->text_extents (font, &code, 1, NULL); 1900 int format = g->f.f1.format;
1923 LGLYPH_SET_WIDTH (prev, make_number (width)); 1901
1902 if (format & OTF_XPlacement)
1903 xoff = g->f.f1.value->XPlacement * size / u;
1904 if (format & OTF_XPlaDevice)
1905 xoff += DEVICE_DELTA (g->f.f1.value->XPlaDevice, size);
1906 if (format & OTF_YPlacement)
1907 yoff = - (g->f.f1.value->YPlacement * size / u);
1908 if (format & OTF_YPlaDevice)
1909 yoff -= DEVICE_DELTA (g->f.f1.value->YPlaDevice, size);
1910 if (format & OTF_XAdvance)
1911 width_adjust += g->f.f1.value->XAdvance * size / u;
1912 if (format & OTF_XAdvDevice)
1913 width_adjust += DEVICE_DELTA (g->f.f1.value->XAdvDevice, size);
1924 } 1914 }
1925 else 1915 break;
1926 width = XINT (LGLYPH_WIDTH (prev)); 1916 case 3:
1927 xoff = XINT (LGLYPH_XOFF (prev)) + (base_x - width) - mark_x; 1917 /* Not yet supported. */
1928 yoff = XINT (LGLYPH_YOFF (prev)) + mark_y - base_y; 1918 break;
1929 } 1919 case 4: case 5:
1930 } 1920 if (NILP (base))
1921 break;
1922 prev = base;
1923 goto label_adjust_anchor;
1924 default: /* i.e. case 6 */
1925 if (NILP (mark))
1926 break;
1927 prev = mark;
1931 1928
1932 if (xoff || yoff || width_adjust) 1929 label_adjust_anchor:
1933 { 1930 {
1934 Lisp_Object adjustment = Fmake_vector (make_number (3), Qnil); 1931 int base_x, base_y, mark_x, mark_y, width;
1932 unsigned code;
1933
1934 base_x = g->f.f4.base_anchor->XCoordinate * size / u;
1935 base_y = g->f.f4.base_anchor->YCoordinate * size / u;
1936 mark_x = g->f.f4.mark_anchor->XCoordinate * size / u;
1937 mark_y = g->f.f4.mark_anchor->YCoordinate * size / u;
1938
1939 code = XINT (LGLYPH_CODE (prev));
1940 if (g->f.f4.base_anchor->AnchorFormat != 1)
1941 adjust_anchor (font, g->f.f4.base_anchor,
1942 code, size, &base_x, &base_y);
1943 if (g->f.f4.mark_anchor->AnchorFormat != 1)
1944 adjust_anchor (font, g->f.f4.mark_anchor,
1945 code, size, &mark_x, &mark_y);
1946
1947 if (NILP (LGLYPH_WIDTH (prev)))
1948 {
1949 width = font->driver->text_extents (font, &code, 1, NULL);
1950 LGLYPH_SET_WIDTH (prev, make_number (width));
1951 }
1952 else
1953 width = XINT (LGLYPH_WIDTH (prev));
1954 xoff = XINT (LGLYPH_XOFF (prev)) + (base_x - width) - mark_x;
1955 yoff = XINT (LGLYPH_YOFF (prev)) + mark_y - base_y;
1956 }
1957 }
1958 if (xoff || yoff || width_adjust)
1959 {
1960 Lisp_Object adjustment = Fmake_vector (make_number (3), Qnil);
1935 1961
1936 ASET (adjustment, 0, make_number (xoff)); 1962 ASET (adjustment, 0, make_number (xoff));
1937 ASET (adjustment, 1, make_number (yoff)); 1963 ASET (adjustment, 1, make_number (yoff));
1938 ASET (adjustment, 2, make_number (width_adjust)); 1964 ASET (adjustment, 2, make_number (width_adjust));
1939 LGLYPH_SET_ADJUSTMENT (glyph, adjustment); 1965 LGLYPH_SET_ADJUSTMENT (glyph, adjustment);
1966 }
1967 if (g->GlyphClass == OTF_GlyphClass0)
1968 base = mark = glyph;
1969 else if (g->GlyphClass == OTF_GlyphClassMark)
1970 mark = glyph;
1971 else
1972 base = glyph;
1940 } 1973 }
1941
1942 if (g->GlyphClass == OTF_GlyphClass0)
1943 base = mark = glyph;
1944 else if (g->GlyphClass == OTF_GlyphClassMark)
1945 mark = glyph;
1946 else
1947 base = glyph;
1948 } 1974 }
1949 1975
1950 free (otf_gstring.glyphs); 1976 free (otf_gstring.glyphs);
@@ -2660,16 +2686,23 @@ font_find_for_lface (f, lface, spec)
2660} 2686}
2661 2687
2662Lisp_Object 2688Lisp_Object
2663font_open_for_lface (f, lface, entity) 2689font_open_for_lface (f, entity, lface, spec)
2664 FRAME_PTR f; 2690 FRAME_PTR f;
2665 Lisp_Object *lface;
2666 Lisp_Object entity; 2691 Lisp_Object entity;
2692 Lisp_Object *lface;
2693 Lisp_Object spec;
2667{ 2694{
2668 double pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2669 int size; 2695 int size;
2670 2696
2671 pt /= 10; 2697 if (FONT_SPEC_P (spec) && INTEGERP (AREF (spec, FONT_SIZE_INDEX)))
2672 size = POINT_TO_PIXEL (pt, f->resy); 2698 size = XINT (AREF (spec, FONT_SIZE_INDEX));
2699 else
2700 {
2701 double pt = XINT (lface[LFACE_HEIGHT_INDEX]);
2702
2703 pt /= 10;
2704 size = POINT_TO_PIXEL (pt, f->resy);
2705 }
2673 return font_open_entity (f, entity, size); 2706 return font_open_entity (f, entity, size);
2674} 2707}
2675 2708
@@ -2685,7 +2718,7 @@ font_load_for_face (f, face)
2685 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil); 2718 Lisp_Object entity = font_find_for_lface (f, face->lface, Qnil);
2686 2719
2687 if (! NILP (entity)) 2720 if (! NILP (entity))
2688 font_object = font_open_for_lface (f, face->lface, entity); 2721 font_object = font_open_for_lface (f, entity, face->lface, Qnil);
2689 } 2722 }
2690 2723
2691 if (! NILP (font_object)) 2724 if (! NILP (font_object))
@@ -3237,7 +3270,7 @@ and is a vector of this form:
3237HEADER is a vector of this form: 3270HEADER is a vector of this form:
3238 [FONT-OBJECT LBEARING RBEARING WIDTH ASCENT DESCENT] 3271 [FONT-OBJECT LBEARING RBEARING WIDTH ASCENT DESCENT]
3239where 3272where
3240 FONT-OBJECT is a font-object for all glyphs in the G-string, 3273 FONT-OBJECT is a font-object for all glyphs in the g-string,
3241 LBEARING thry DESCENT is the metrics (in pixels) of the whole G-string. 3274 LBEARING thry DESCENT is the metrics (in pixels) of the whole G-string.
3242GLYPH is a vector of this form: 3275GLYPH is a vector of this form:
3243 [ FROM-IDX TO-IDX C CODE WIDTH [ [X-OFF Y-OFF WADJUST] | nil] ] 3276 [ FROM-IDX TO-IDX C CODE WIDTH [ [X-OFF Y-OFF WADJUST] | nil] ]
@@ -3349,26 +3382,25 @@ FONT-OBJECT may be nil if GSTRING already already contains one. */)
3349 return Qnil; 3382 return Qnil;
3350} 3383}
3351 3384
3352DEFUN ("font-otf-gsub", Ffont_otf_gsub, Sfont_otf_gsub, 6, 6, 0, 3385DEFUN ("font-drive-otf", Ffont_drive_otf, Sfont_drive_otf, 6, 6, 0,
3353 doc: /* Apply OpenType "GSUB" features on glyph-string GSTRING-IN. 3386 doc: /* Apply OpenType features on glyph-string GSTRING-IN.
3354FEATURE-SPEC specifies which featuress to apply in this format: 3387OTF-SPEC specifies which featuress to apply in this format:
3355 (SCRIPT LANGSYS FEATURE ...) 3388 (SCRIPT LANGSYS GSUB GPOS)
3356where 3389where
3357 SCRIPT is a symbol specifying a script tag of OpenType, 3390 SCRIPT is a symbol specifying a script tag of OpenType,
3358 LANGSYS is a symbol specifying a langsys tag of OpenType, 3391 LANGSYS is a symbol specifying a langsys tag of OpenType,
3359 FEATURE is a symbol specifying a feature tag of Opentype. 3392 GSUB and GPOS, if non-nil, are lists of symbols specifying feature tags.
3360 3393
3361If LANGYS is nil, the default langsys is selected. 3394If LANGYS is nil, the default langsys is selected.
3362 3395
3363The features are applied in the order appeared in the list. FEATURE 3396The features are applied in the order appeared in the list. The
3364may be a symbol `*', in which case all available features not appeared 3397symbol `*' means to apply all available features not appeared in this
3365in this list are applied, and the remaining FEATUREs are not ignored. 3398list, and the remaining features are ignored. For instance, (vatu
3366For instance, (mlym nil vatu pstf * haln) means to apply vatu and pstf 3399pstf * haln) is to apply vatu and pstf in this order, then to apply
3367in this order, then to apply all available features other than vatu, 3400all available features other than vatu, pstf, and haln.
3368pstf, and haln.
3369 3401
3370The features are applied to the glyphs in the range FROM and TO of 3402The features are applied to the glyphs in the range FROM and TO of
3371GSTRING-IN. 3403the glyph-string GSTRING-IN.
3372 3404
3373If some of a feature is actually applicable, the resulting glyphs are 3405If some of a feature is actually applicable, the resulting glyphs are
3374produced in the glyph-string GSTRING-OUT from the index INDEX. In 3406produced in the glyph-string GSTRING-OUT from the index INDEX. In
@@ -3382,18 +3414,26 @@ produced in GSTRING-OUT, and the value is nil.
3382 3414
3383See the documentation of `font-make-gstring' for the format of 3415See the documentation of `font-make-gstring' for the format of
3384glyph-string. */) 3416glyph-string. */)
3385 (feature_spec, gstring_in, from, to, gstring_out, index) 3417 (otf_features, gstring_in, from, to, gstring_out, index)
3386 Lisp_Object feature_spec, gstring_in, from, to, gstring_out, index; 3418 Lisp_Object otf_features, gstring_in, from, to, gstring_out, index;
3387{ 3419{
3388 Lisp_Object font_object = LGSTRING_FONT (gstring_in); 3420 Lisp_Object font_object = LGSTRING_FONT (gstring_in);
3389 struct font *font = XSAVE_VALUE (font_object)->pointer; 3421 Lisp_Object val;
3422 struct font *font;
3390 int len, num; 3423 int len, num;
3391 3424
3425 check_otf_features (otf_features);
3392 CHECK_FONT_GET_OBJECT (font_object, font); 3426 CHECK_FONT_GET_OBJECT (font_object, font);
3393 if (! font->driver->otf_gsub) 3427 if (! font->driver->otf_drive)
3394 error ("Font backend %s can't drive OpenType GSUB table", 3428 error ("Font backend %s can't drive OpenType GSUB table",
3395 SDATA (SYMBOL_NAME (font->driver->type))); 3429 SDATA (SYMBOL_NAME (font->driver->type)));
3396 CHECK_CONS (feature_spec); 3430 CHECK_CONS (otf_features);
3431 CHECK_SYMBOL (XCAR (otf_features));
3432 val = XCDR (otf_features);
3433 CHECK_SYMBOL (XCAR (val));
3434 val = XCDR (otf_features);
3435 if (! NILP (val))
3436 CHECK_CONS (val);
3397 len = check_gstring (gstring_in); 3437 len = check_gstring (gstring_in);
3398 CHECK_VECTOR (gstring_out); 3438 CHECK_VECTOR (gstring_out);
3399 CHECK_NATNUM (from); 3439 CHECK_NATNUM (from);
@@ -3404,47 +3444,14 @@ glyph-string. */)
3404 args_out_of_range_3 (from, to, make_number (len)); 3444 args_out_of_range_3 (from, to, make_number (len));
3405 if (XINT (index) >= ASIZE (gstring_out)) 3445 if (XINT (index) >= ASIZE (gstring_out))
3406 args_out_of_range (index, make_number (ASIZE (gstring_out))); 3446 args_out_of_range (index, make_number (ASIZE (gstring_out)));
3407 num = font->driver->otf_gsub (font, feature_spec, 3447 num = font->driver->otf_drive (font, otf_features,
3408 gstring_in, XINT (from), XINT (to), 3448 gstring_in, XINT (from), XINT (to),
3409 gstring_out, XINT (index), 0); 3449 gstring_out, XINT (index), 0);
3410 if (num < 0) 3450 if (num < 0)
3411 return Qnil; 3451 return Qnil;
3412 return make_number (num); 3452 return make_number (num);
3413} 3453}
3414 3454
3415
3416DEFUN ("font-otf-gpos", Ffont_otf_gpos, Sfont_otf_gpos, 4, 4, 0,
3417 doc: /* Apply OpenType "GPOS" features on glyph-string GSTRING.
3418FEATURE-SPEC specifies which features to apply in this format:
3419 (SCRIPT LANGSYS FEATURE ...)
3420See the documentation of `font-otf-gsub' for more detail.
3421
3422The features are applied to the glyphs in the range FROM and TO of
3423GSTRING. */)
3424 (gpos_spec, gstring, from, to)
3425 Lisp_Object gpos_spec, gstring, from, to;
3426{
3427 Lisp_Object font_object = LGSTRING_FONT (gstring);
3428 struct font *font;
3429 int len, num;
3430
3431 CHECK_FONT_GET_OBJECT (font_object, font);
3432 if (! font->driver->otf_gpos)
3433 error ("Font backend %s can't drive OpenType GPOS table",
3434 SDATA (SYMBOL_NAME (font->driver->type)));
3435 CHECK_CONS (gpos_spec);
3436 len = check_gstring (gstring);
3437 CHECK_NATNUM (from);
3438 CHECK_NATNUM (to);
3439
3440 if (XINT (from) >= XINT (to) || XINT (to) > len)
3441 args_out_of_range_3 (from, to, make_number (len));
3442 num = font->driver->otf_gpos (font, gpos_spec,
3443 gstring, XINT (from), XINT (to));
3444 return (num <= 0 ? Qnil : Qt);
3445}
3446
3447
3448DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates, 3455DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates,
3449 3, 3, 0, 3456 3, 3, 0,
3450 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT. 3457 doc: /* Return a list of alternate glyphs of CHARACTER in FONT-OBJECT.
@@ -3457,8 +3464,8 @@ The value is a list of cons cells of the format (GLYPH-ID . CHARACTER),
3457where GLYPH-ID is a glyph index of the font, and CHARACTER is a 3464where GLYPH-ID is a glyph index of the font, and CHARACTER is a
3458character code corresponding to the glyph or nil if there's no 3465character code corresponding to the glyph or nil if there's no
3459corresponding character. */) 3466corresponding character. */)
3460 (font_object, character, feature_spec) 3467 (font_object, character, otf_features)
3461 Lisp_Object font_object, character, feature_spec; 3468 Lisp_Object font_object, character, otf_features;
3462{ 3469{
3463 struct font *font; 3470 struct font *font;
3464 Lisp_Object gstring_in, gstring_out, g; 3471 Lisp_Object gstring_in, gstring_out, g;
@@ -3466,18 +3473,18 @@ corresponding character. */)
3466 int i, num; 3473 int i, num;
3467 3474
3468 CHECK_FONT_GET_OBJECT (font_object, font); 3475 CHECK_FONT_GET_OBJECT (font_object, font);
3469 if (! font->driver->otf_gsub) 3476 if (! font->driver->otf_drive)
3470 error ("Font backend %s can't drive OpenType GSUB table", 3477 error ("Font backend %s can't drive OpenType GSUB table",
3471 SDATA (SYMBOL_NAME (font->driver->type))); 3478 SDATA (SYMBOL_NAME (font->driver->type)));
3472 CHECK_CHARACTER (character); 3479 CHECK_CHARACTER (character);
3473 CHECK_CONS (feature_spec); 3480 CHECK_CONS (otf_features);
3474 3481
3475 gstring_in = Ffont_make_gstring (font_object, make_number (1)); 3482 gstring_in = Ffont_make_gstring (font_object, make_number (1));
3476 g = LGSTRING_GLYPH (gstring_in, 0); 3483 g = LGSTRING_GLYPH (gstring_in, 0);
3477 LGLYPH_SET_CHAR (g, character); 3484 LGLYPH_SET_CHAR (g, character);
3478 gstring_out = Ffont_make_gstring (font_object, make_number (10)); 3485 gstring_out = Ffont_make_gstring (font_object, make_number (10));
3479 while ((num = font->driver->otf_gsub (font, feature_spec, gstring_in, 0, 1, 3486 while ((num = font->driver->otf_drive (font, otf_features, gstring_in, 0, 1,
3480 gstring_out, 0, 1)) < 0) 3487 gstring_out, 0, 1)) < 0)
3481 gstring_out = Ffont_make_gstring (font_object, 3488 gstring_out = Ffont_make_gstring (font_object,
3482 make_number (ASIZE (gstring_out) * 2)); 3489 make_number (ASIZE (gstring_out) * 2));
3483 alternates = Qnil; 3490 alternates = Qnil;
@@ -3792,6 +3799,11 @@ syms_of_font ()
3792 staticpro (&scratch_font_prefer); 3799 staticpro (&scratch_font_prefer);
3793 scratch_font_prefer = Ffont_spec (0, NULL); 3800 scratch_font_prefer = Ffont_spec (0, NULL);
3794 3801
3802#ifdef HAVE_LIBOTF
3803 staticpro (&otf_list);
3804 otf_list = Qnil;
3805#endif
3806
3795 defsubr (&Sfontp); 3807 defsubr (&Sfontp);
3796 defsubr (&Sfont_spec); 3808 defsubr (&Sfont_spec);
3797 defsubr (&Sfont_get); 3809 defsubr (&Sfont_get);
@@ -3804,8 +3816,7 @@ syms_of_font ()
3804 defsubr (&Sinternal_set_font_style_table); 3816 defsubr (&Sinternal_set_font_style_table);
3805 defsubr (&Sfont_make_gstring); 3817 defsubr (&Sfont_make_gstring);
3806 defsubr (&Sfont_fill_gstring); 3818 defsubr (&Sfont_fill_gstring);
3807 defsubr (&Sfont_otf_gsub); 3819 defsubr (&Sfont_drive_otf);
3808 defsubr (&Sfont_otf_gpos);
3809 defsubr (&Sfont_otf_alternates); 3820 defsubr (&Sfont_otf_alternates);
3810 3821
3811#ifdef FONT_DEBUG 3822#ifdef FONT_DEBUG