diff options
| author | Kenichi Handa | 2007-04-25 12:05:28 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2007-04-25 12:05:28 +0000 |
| commit | 733fd013f650474c6104b6b4f05c1db52a068a9b (patch) | |
| tree | aaa6c879e69b785195ecd49cbfe751f59b4314a6 /src | |
| parent | c927d1df98dfd0ce154d32372ae10577c89f3308 (diff) | |
| download | emacs-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.c | 627 |
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 | ||
| 1486 | struct otf_list | 1486 | Lisp_Object otf_list; |
| 1487 | { | ||
| 1488 | Lisp_Object entity; | ||
| 1489 | OTF *otf; | ||
| 1490 | struct otf_list *next; | ||
| 1491 | }; | ||
| 1492 | |||
| 1493 | static struct otf_list *otf_list; | ||
| 1494 | 1487 | ||
| 1495 | static Lisp_Object | 1488 | static Lisp_Object |
| 1496 | otf_tag_symbol (tag) | 1489 | otf_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 | |||
| 1600 | static void | 1597 | static void |
| 1601 | parse_gsub_gpos_spec (spec, script, langsys, features, nbytes) | 1598 | generate_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 | ||
| 1660 | static void | ||
| 1661 | check_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 | |||
| 1687 | Lisp_Object | ||
| 1688 | font_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 | |||
| 1697 | Lisp_Object | ||
| 1698 | font_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 | |||
| 1723 | Lisp_Object | ||
| 1724 | font_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 | ||
| 1690 | int | 1747 | int |
| 1691 | font_otf_gsub (font, gsub_spec, gstring_in, from, to, gstring_out, idx, | 1748 | font_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 | |||
| 1798 | int | ||
| 1799 | font_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 | ||
| 2662 | Lisp_Object | 2688 | Lisp_Object |
| 2663 | font_open_for_lface (f, lface, entity) | 2689 | font_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: | |||
| 3237 | HEADER is a vector of this form: | 3270 | HEADER is a vector of this form: |
| 3238 | [FONT-OBJECT LBEARING RBEARING WIDTH ASCENT DESCENT] | 3271 | [FONT-OBJECT LBEARING RBEARING WIDTH ASCENT DESCENT] |
| 3239 | where | 3272 | where |
| 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. |
| 3242 | GLYPH is a vector of this form: | 3275 | GLYPH 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 | ||
| 3352 | DEFUN ("font-otf-gsub", Ffont_otf_gsub, Sfont_otf_gsub, 6, 6, 0, | 3385 | DEFUN ("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. |
| 3354 | FEATURE-SPEC specifies which featuress to apply in this format: | 3387 | OTF-SPEC specifies which featuress to apply in this format: |
| 3355 | (SCRIPT LANGSYS FEATURE ...) | 3388 | (SCRIPT LANGSYS GSUB GPOS) |
| 3356 | where | 3389 | where |
| 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 | ||
| 3361 | If LANGYS is nil, the default langsys is selected. | 3394 | If LANGYS is nil, the default langsys is selected. |
| 3362 | 3395 | ||
| 3363 | The features are applied in the order appeared in the list. FEATURE | 3396 | The features are applied in the order appeared in the list. The |
| 3364 | may be a symbol `*', in which case all available features not appeared | 3397 | symbol `*' means to apply all available features not appeared in this |
| 3365 | in this list are applied, and the remaining FEATUREs are not ignored. | 3398 | list, and the remaining features are ignored. For instance, (vatu |
| 3366 | For instance, (mlym nil vatu pstf * haln) means to apply vatu and pstf | 3399 | pstf * haln) is to apply vatu and pstf in this order, then to apply |
| 3367 | in this order, then to apply all available features other than vatu, | 3400 | all available features other than vatu, pstf, and haln. |
| 3368 | pstf, and haln. | ||
| 3369 | 3401 | ||
| 3370 | The features are applied to the glyphs in the range FROM and TO of | 3402 | The features are applied to the glyphs in the range FROM and TO of |
| 3371 | GSTRING-IN. | 3403 | the glyph-string GSTRING-IN. |
| 3372 | 3404 | ||
| 3373 | If some of a feature is actually applicable, the resulting glyphs are | 3405 | If some of a feature is actually applicable, the resulting glyphs are |
| 3374 | produced in the glyph-string GSTRING-OUT from the index INDEX. In | 3406 | produced 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 | ||
| 3383 | See the documentation of `font-make-gstring' for the format of | 3415 | See the documentation of `font-make-gstring' for the format of |
| 3384 | glyph-string. */) | 3416 | glyph-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 | |||
| 3416 | DEFUN ("font-otf-gpos", Ffont_otf_gpos, Sfont_otf_gpos, 4, 4, 0, | ||
| 3417 | doc: /* Apply OpenType "GPOS" features on glyph-string GSTRING. | ||
| 3418 | FEATURE-SPEC specifies which features to apply in this format: | ||
| 3419 | (SCRIPT LANGSYS FEATURE ...) | ||
| 3420 | See the documentation of `font-otf-gsub' for more detail. | ||
| 3421 | |||
| 3422 | The features are applied to the glyphs in the range FROM and TO of | ||
| 3423 | GSTRING. */) | ||
| 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 | |||
| 3448 | DEFUN ("font-otf-alternates", Ffont_otf_alternates, Sfont_otf_alternates, | 3455 | DEFUN ("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), | |||
| 3457 | where GLYPH-ID is a glyph index of the font, and CHARACTER is a | 3464 | where GLYPH-ID is a glyph index of the font, and CHARACTER is a |
| 3458 | character code corresponding to the glyph or nil if there's no | 3465 | character code corresponding to the glyph or nil if there's no |
| 3459 | corresponding character. */) | 3466 | corresponding 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 |