aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa2010-04-23 21:29:11 +0900
committerKenichi Handa2010-04-23 21:29:11 +0900
commitc4170e32d184c0e3d7b81045b74d2fe5a3e2fe7b (patch)
tree1252157d00e6741ad0da0224d75b91f25a575cd0 /src
parent5315723bbea1e7b65c3e5f3aed0ad716fa169d28 (diff)
downloademacs-c4170e32d184c0e3d7b81045b74d2fe5a3e2fe7b.tar.gz
emacs-c4170e32d184c0e3d7b81045b74d2fe5a3e2fe7b.zip
Use new features of libotf and m17n-lib if available.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/ftfont.c370
2 files changed, 385 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4f97e09f8f9..d061857bc3a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
12010-04-23 Kenichi Handa <handa@m17n.org>
2
3 * ftfont.c (M17N_FLT_USE_NEW_FEATURE): Define it if we can use the
4 new feature of libotf and m17n-flt.
5 (ftfont_check_otf) [M17N_FLT_USE_NEW_FEATURE]: Call
6 OTF_check_features even if no specific feature is given.
7 (PACK_OTF_TAG) [M17N_FLT_USE_NEW_FEATURE]: New macro.
8 (ftfont_drive_otf) [M17N_FLT_USE_NEW_FEATURE]: Handle the case
9 that OUT is NULL. Use OTF_drive_gsub_with_log and
10 OTF_drive_gpos_with_log instead of OTF_drive_gsub and
11 OTF_drive_gpos.
12 (ftfont_try_otf) [M17N_FLT_USE_NEW_FEATURE]: New function.
13 (ftfont_shape_by_flt) [M17N_FLT_USE_NEW_FEATURE]: Setup
14 mflt_enable_new_feature and mflt_try_otf.
15
12010-04-19 Juanma Barranquero <lekktu@gmail.com> 162010-04-19 Juanma Barranquero <lekktu@gmail.com>
2 17
3 * dired.c (Ffile_attributes): Fix typo in docstring. 18 * dired.c (Ffile_attributes): Fix typo in docstring.
diff --git a/src/ftfont.c b/src/ftfont.c
index f4fe5b8e5c0..6956c134a7c 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1578,6 +1578,14 @@ ftfont_otf_capability (font)
1578 1578
1579#ifdef HAVE_M17N_FLT 1579#ifdef HAVE_M17N_FLT
1580 1580
1581#if ((LIBOTF_MAJOR_VERSION > 1) || (LIBOTF_RELEASE_NUMBER >= 10) \
1582 && (M17NLIB_MAJOR_VERSION > 1) || (M17NLIB_MINOR_VERSION >= 6))
1583/* We can use the new feature of libotf and m17n-flt to handle the
1584 character encoding scheme introduced in Unicode 5.1 and 5.2 for
1585 some Agian scripts. */
1586#define M17N_FLT_USE_NEW_FEATURE
1587#endif
1588
1581struct MFLTFontFT 1589struct MFLTFontFT
1582{ 1590{
1583 MFLTFont flt_font; 1591 MFLTFont flt_font;
@@ -1696,10 +1704,16 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
1696 else 1704 else
1697 tags[n] = spec->features[i][n]; 1705 tags[n] = spec->features[i][n];
1698 } 1706 }
1707#ifdef M17N_FLT_USE_NEW_FEATURE
1708 if (OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1709 tags, n - negative) != 1)
1710 return 0;
1711#else /* not M17N_FLT_USE_NEW_FEATURE */
1699 if (n - negative > 0 1712 if (n - negative > 0
1700 && OTF_check_features (otf, i == 0, spec->script, spec->langsys, 1713 && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
1701 tags, n - negative) != 1) 1714 tags, n - negative) != 1)
1702 return 0; 1715 return 0;
1716#endif /* not M17N_FLT_USE_NEW_FEATURE */
1703 } 1717 }
1704 return 1; 1718 return 1;
1705} 1719}
@@ -1757,6 +1771,356 @@ setup_otf_gstring (int size)
1757 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size); 1771 memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
1758} 1772}
1759 1773
1774#ifdef M17N_FLT_USE_NEW_FEATURE
1775
1776/* Pack 32-bit OTF tag (0x7F7F7F7F) into 28-bit (0x0FFFFFFF). */
1777#define PACK_OTF_TAG(TAG) \
1778 ((((TAG) & 0x7F000000) >> 3) \
1779 | (((TAG) & 0x7F0000) >> 2) \
1780 | (((TAG) & 0x7F00) >> 1) \
1781 | ((TAG) & 0x7F))
1782
1783/* Assuming that FONT is an OpenType font, apply OpenType features
1784 specified in SPEC on glyphs between FROM and TO of IN, and record
1785 the lastly applied feature in each glyph of IN. If OUT is not
1786 NULL, append the resulting glyphs to OUT while storing glyph
1787 position adjustment information in ADJUSTMENT. */
1788
1789static int
1790ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
1791 MFLTFont *font;
1792 MFLTOtfSpec *spec;
1793 MFLTGlyphString *in;
1794 int from, to;
1795 MFLTGlyphString *out;
1796 MFLTGlyphAdjustment *adjustment;
1797{
1798 struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
1799 FT_Face ft_face = flt_font_ft->ft_face;
1800 OTF *otf = flt_font_ft->otf;
1801 int len = to - from;
1802 int i, j, gidx;
1803 OTF_Glyph *otfg;
1804 char script[5], *langsys = NULL;
1805 char *gsub_features = NULL, *gpos_features = NULL;
1806 OTF_Feature *features;
1807
1808 if (len == 0)
1809 return from;
1810 OTF_tag_name (spec->script, script);
1811 if (spec->langsys)
1812 {
1813 langsys = alloca (5);
1814 OTF_tag_name (spec->langsys, langsys);
1815 }
1816 for (i = 0; i < 2; i++)
1817 {
1818 char *p;
1819
1820 if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
1821 {
1822 for (j = 0; spec->features[i][j]; j++);
1823 if (i == 0)
1824 p = gsub_features = alloca (6 * j);
1825 else
1826 p = gpos_features = alloca (6 * j);
1827 for (j = 0; spec->features[i][j]; j++)
1828 {
1829 if (spec->features[i][j] == 0xFFFFFFFF)
1830 *p++ = '*', *p++ = ',';
1831 else
1832 {
1833 OTF_tag_name (spec->features[i][j], p);
1834 p[4] = ',';
1835 p += 5;
1836 }
1837 }
1838 *--p = '\0';
1839 }
1840 }
1841
1842 setup_otf_gstring (len);
1843 for (i = 0; i < len; i++)
1844 {
1845 otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
1846 otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
1847 }
1848
1849 OTF_drive_gdef (otf, &otf_gstring);
1850 gidx = out ? out->used : from;
1851
1852 if (gsub_features && out)
1853 {
1854 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1855 gsub_features) < 0)
1856 goto simple_copy;
1857 if (out->allocated < out->used + otf_gstring.used)
1858 return -2;
1859 features = otf->gsub->FeatureList.Feature;
1860 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
1861 {
1862 MFLTGlyph *g;
1863 int min_from, max_to;
1864 int j;
1865 int feature_idx = otfg->positioning_type >> 4;
1866
1867 g = out->glyphs + out->used;
1868 *g = in->glyphs[from + otfg->f.index.from];
1869 if (g->code != otfg->glyph_id)
1870 {
1871 g->c = 0;
1872 g->code = otfg->glyph_id;
1873 g->measured = 0;
1874 }
1875 out->used++;
1876 min_from = g->from;
1877 max_to = g->to;
1878 if (otfg->f.index.from < otfg->f.index.to)
1879 {
1880 /* OTFG substitutes multiple glyphs in IN. */
1881 for (j = from + otfg->f.index.from + 1;
1882 j <= from + otfg->f.index.to; j++)
1883 {
1884 if (min_from > in->glyphs[j].from)
1885 min_from = in->glyphs[j].from;
1886 if (max_to < in->glyphs[j].to)
1887 max_to = in->glyphs[j].to;
1888 }
1889 g->from = min_from;
1890 g->to = max_to;
1891 }
1892 if (feature_idx)
1893 {
1894 unsigned int tag = features[feature_idx - 1].FeatureTag;
1895 tag = PACK_OTF_TAG (tag);
1896 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1897 }
1898 for (i++, otfg++; (i < otf_gstring.used
1899 && otfg->f.index.from == otfg[-1].f.index.from);
1900 i++, otfg++)
1901 {
1902 g = out->glyphs + out->used;
1903 *g = in->glyphs[from + otfg->f.index.to];
1904 if (g->code != otfg->glyph_id)
1905 {
1906 g->c = 0;
1907 g->code = otfg->glyph_id;
1908 g->measured = 0;
1909 }
1910 feature_idx = otfg->positioning_type >> 4;
1911 if (feature_idx)
1912 {
1913 unsigned int tag = features[feature_idx - 1].FeatureTag;
1914 tag = PACK_OTF_TAG (tag);
1915 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1916 }
1917 out->used++;
1918 }
1919 }
1920 }
1921 else if (gsub_features)
1922 {
1923 /* Just for checking which features will be applied. */
1924 if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys,
1925 gsub_features) < 0)
1926 goto simple_copy;
1927 features = otf->gsub->FeatureList.Feature;
1928 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++,
1929 otfg++)
1930 {
1931 int feature_idx = otfg->positioning_type >> 4;
1932
1933 if (feature_idx)
1934 {
1935 unsigned int tag = features[feature_idx - 1].FeatureTag;
1936 tag = PACK_OTF_TAG (tag);
1937 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
1938 {
1939 MFLTGlyph *g = in->glyphs + (from + j);
1940 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1941 }
1942 }
1943 }
1944 }
1945 else if (out)
1946 {
1947 if (out->allocated < out->used + len)
1948 return -2;
1949 for (i = 0; i < len; i++)
1950 out->glyphs[out->used++] = in->glyphs[from + i];
1951 }
1952
1953 if (gpos_features && out)
1954 {
1955 MFLTGlyph *base = NULL, *mark = NULL, *g;
1956 int x_ppem, y_ppem, x_scale, y_scale;
1957
1958 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
1959 gpos_features) < 0)
1960 return to;
1961 features = otf->gpos->FeatureList.Feature;
1962 x_ppem = ft_face->size->metrics.x_ppem;
1963 y_ppem = ft_face->size->metrics.y_ppem;
1964 x_scale = ft_face->size->metrics.x_scale;
1965 y_scale = ft_face->size->metrics.y_scale;
1966
1967 for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
1968 i < otf_gstring.used; i++, otfg++, g++)
1969 {
1970 MFLTGlyph *prev;
1971 int feature_idx = otfg->positioning_type >> 4;
1972
1973 if (feature_idx)
1974 {
1975 unsigned int tag = features[feature_idx - 1].FeatureTag;
1976 tag = PACK_OTF_TAG (tag);
1977 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
1978 }
1979
1980 if (! otfg->glyph_id)
1981 continue;
1982 switch (otfg->positioning_type & 0xF)
1983 {
1984 case 0:
1985 break;
1986 case 1: /* Single */
1987 case 2: /* Pair */
1988 {
1989 int format = otfg->f.f1.format;
1990
1991 if (format & OTF_XPlacement)
1992 adjustment[i].xoff
1993 = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
1994 if (format & OTF_XPlaDevice)
1995 adjustment[i].xoff
1996 += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
1997 if (format & OTF_YPlacement)
1998 adjustment[i].yoff
1999 = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
2000 if (format & OTF_YPlaDevice)
2001 adjustment[i].yoff
2002 -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
2003 if (format & OTF_XAdvance)
2004 adjustment[i].xadv
2005 += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
2006 if (format & OTF_XAdvDevice)
2007 adjustment[i].xadv
2008 += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
2009 if (format & OTF_YAdvance)
2010 adjustment[i].yadv
2011 += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
2012 if (format & OTF_YAdvDevice)
2013 adjustment[i].yadv
2014 += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
2015 adjustment[i].set = 1;
2016 }
2017 break;
2018 case 3: /* Cursive */
2019 /* Not yet supported. */
2020 break;
2021 case 4: /* Mark-to-Base */
2022 case 5: /* Mark-to-Ligature */
2023 if (! base)
2024 break;
2025 prev = base;
2026 goto label_adjust_anchor;
2027 default: /* i.e. case 6 Mark-to-Mark */
2028 if (! mark)
2029 break;
2030 prev = mark;
2031
2032 label_adjust_anchor:
2033 {
2034 int base_x, base_y, mark_x, mark_y;
2035 int this_from, this_to;
2036
2037 base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
2038 base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
2039 mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
2040 mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
2041
2042 if (otfg->f.f4.base_anchor->AnchorFormat != 1)
2043 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
2044 prev->code, x_ppem, y_ppem, &base_x, &base_y);
2045 if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
2046 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
2047 x_ppem, y_ppem, &mark_x, &mark_y);
2048 adjustment[i].xoff = (base_x - mark_x);
2049 adjustment[i].yoff = - (base_y - mark_y);
2050 adjustment[i].back = (g - prev);
2051 adjustment[i].xadv = 0;
2052 adjustment[i].advance_is_absolute = 1;
2053 adjustment[i].set = 1;
2054 this_from = g->from;
2055 this_to = g->to;
2056 for (j = 0; prev + j < g; j++)
2057 {
2058 if (this_from > prev[j].from)
2059 this_from = prev[j].from;
2060 if (this_to < prev[j].to)
2061 this_to = prev[j].to;
2062 }
2063 for (; prev <= g; prev++)
2064 {
2065 prev->from = this_from;
2066 prev->to = this_to;
2067 }
2068 }
2069 }
2070 if (otfg->GlyphClass == OTF_GlyphClass0)
2071 base = mark = g;
2072 else if (otfg->GlyphClass == OTF_GlyphClassMark)
2073 mark = g;
2074 else
2075 base = g;
2076 }
2077 }
2078 else if (gpos_features)
2079 {
2080 if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
2081 gpos_features) < 0)
2082 return to;
2083 features = otf->gpos->FeatureList.Feature;
2084 for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
2085 i++, otfg++)
2086 if (otfg->positioning_type & 0xF)
2087 {
2088 int feature_idx = otfg->positioning_type >> 4;
2089
2090 if (feature_idx)
2091 {
2092 unsigned int tag = features[feature_idx - 1].FeatureTag;
2093 tag = PACK_OTF_TAG (tag);
2094 for (j = otfg->f.index.from; j <= otfg->f.index.to; j++)
2095 {
2096 MFLTGlyph *g = in->glyphs + (from + j);
2097 g->internal = (g->internal & ~0x1FFFFFFF) | tag;
2098 }
2099 }
2100 }
2101 }
2102 return to;
2103
2104 simple_copy:
2105 if (! out)
2106 return to;
2107 if (out->allocated < out->used + len)
2108 return -2;
2109 font->get_metrics (font, in, from, to);
2110 memcpy (out->glyphs + out->used, in->glyphs + from,
2111 sizeof (MFLTGlyph) * len);
2112 out->used += len;
2113 return to;
2114}
2115
2116static int
2117ftfont_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
2118 MFLTGlyphString *in, int from, int to)
2119{
2120 return ftfont_drive_otf (font, spec, in, from, to, NULL, NULL);
2121}
2122
2123#else /* not M17N_FLT_USE_NEW_FEATURE */
1760 2124
1761static int 2125static int
1762ftfont_drive_otf (font, spec, in, from, to, out, adjustment) 2126ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
@@ -2011,6 +2375,8 @@ ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
2011 return to; 2375 return to;
2012} 2376}
2013 2377
2378#endif /* not M17N_FLT_USE_NEW_FEATURE */
2379
2014static MFLTGlyphString gstring; 2380static MFLTGlyphString gstring;
2015 2381
2016static int m17n_flt_initialized; 2382static int m17n_flt_initialized;
@@ -2034,6 +2400,10 @@ ftfont_shape_by_flt (lgstring, font, ft_face, otf, matrix)
2034 if (! m17n_flt_initialized) 2400 if (! m17n_flt_initialized)
2035 { 2401 {
2036 M17N_INIT (); 2402 M17N_INIT ();
2403#ifdef M17N_FLT_USE_NEW_FEATURE
2404 mflt_enable_new_feature = 1;
2405 mflt_try_otf = ftfont_try_otf;
2406#endif /* M17N_FLT_USE_NEW_FEATURE */
2037 m17n_flt_initialized = 1; 2407 m17n_flt_initialized = 1;
2038 } 2408 }
2039 2409