This file is part of GNU Emacs.
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-#ifdef USE_FONT_BACKEND
#include <config.h>
/* Override API version - Uniscribe is only available as standard since
uniscribe_list (frame, font_spec)
Lisp_Object frame, font_spec;
{
- return w32font_list_internal (frame, font_spec, 1);
+ Lisp_Object fonts = w32font_list_internal (frame, font_spec, 1);
+ font_add_log ("uniscribe-list", font_spec, fonts);
+ return fonts;
}
static Lisp_Object
uniscribe_match (frame, font_spec)
Lisp_Object frame, font_spec;
{
- return w32font_match_internal (frame, font_spec, 1);
+ Lisp_Object entity = w32font_match_internal (frame, font_spec, 1);
+ font_add_log ("uniscribe-match", font_spec, entity);
+ return entity;
}
static Lisp_Object
return list;
}
-static struct font *
+static Lisp_Object
uniscribe_open (f, font_entity, pixel_size)
FRAME_PTR f;
Lisp_Object font_entity;
int pixel_size;
{
+ Lisp_Object font_object
+ = font_make_object (VECSIZE (struct uniscribe_font_info));
struct uniscribe_font_info *uniscribe_font
- = xmalloc (sizeof (struct uniscribe_font_info));
-
- if (uniscribe_font == NULL)
- return NULL;
+ = (struct uniscribe_font_info *) XFONT_OBJECT (font_object);
- if (!w32font_open_internal (f, font_entity, pixel_size,
- (struct w32font_info *) uniscribe_font))
+ if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
{
- xfree (uniscribe_font);
- return NULL;
+ return Qnil;
}
/* Initialize the cache for this font. */
uniscribe_font->cache = NULL;
/* Mark the format as opentype */
- uniscribe_font->w32_font.font.format = Qopentype;
+ uniscribe_font->w32_font.font.props[FONT_FORMAT_INDEX] = Qopentype;
uniscribe_font->w32_font.font.driver = &uniscribe_font_driver;
- return (struct font *) uniscribe_font;
+ return font_object;
}
static void
f = XFRAME (selected_frame);
context = get_frame_dc (f);
- old_font = SelectObject (context,
- ((W32FontStruct *) (font->font.font))->hfont);
+ old_font = SelectObject (context, FONT_HANDLE(font));
features = otf_features (context, "GSUB");
XSETCAR (capability, features);
struct font * font;
struct uniscribe_font_info * uniscribe_font;
EMACS_UINT nchars;
- int nitems, max_items, i, max_glyphs, done_glyphs, done_chars;
+ int nitems, max_items, i, max_glyphs, done_glyphs;
wchar_t *chars;
WORD *glyphs, *clusters;
SCRIPT_ITEM *items;
/* Get the chars from lgstring in a form we can use with uniscribe. */
max_glyphs = nchars = LGSTRING_LENGTH (lgstring);
- done_glyphs = done_chars = 0;
+ done_glyphs = 0;
chars = (wchar_t *) alloca (nchars * sizeof (wchar_t));
for (i = 0; i < nchars; i++)
{
/* First we need to break up the glyph string into runs of glyphs that
can be treated together. First try a single run. */
max_items = 2;
- items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items);
+ items = (SCRIPT_ITEM *) xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
bzero (&control, sizeof (control));
while ((result = ScriptItemize (chars, nchars, max_items, &control, NULL,
/* If that wasn't enough, keep trying with one more run. */
max_items++;
items = (SCRIPT_ITEM *) xrealloc (items,
- sizeof (SCRIPT_ITEM) * max_items);
+ sizeof (SCRIPT_ITEM) * max_items + 1);
}
/* 0 = success in Microsoft's backwards world. */
return Qnil;
}
+ /* TODO: When we get BIDI support, we need to call ScriptLayout here.
+ Requires that we know the surrounding context. */
+
f = XFRAME (selected_frame);
context = get_frame_dc (f);
- old_font = SelectObject (context,
- ((W32FontStruct *) (font->font.font))->hfont);
+ old_font = SelectObject (context, FONT_HANDLE(font));
glyphs = alloca (max_glyphs * sizeof (WORD));
clusters = alloca (nchars * sizeof (WORD));
for (i = 0; i < nitems; i++)
{
- int nglyphs, nchars_in_run;
+ int nglyphs, nchars_in_run, rtl = items[i].a.fRTL ? -1 : 1;
nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
result = ScriptShape (context, &(uniscribe_font->cache),
lgstring = Qnil;
break;
}
- else if (result)
+ else if (result) /* Failure. */
{
/* Can't shape this run - return results so far if any. */
break;
}
+ else if (items[i].a.fNoGlyphIndex)
+ {
+ /* Glyph indices not supported by this font (or OS), means we
+ can't really do any meaningful shaping. */
+ break;
+ }
else
{
result = ScriptPlace (context, &(uniscribe_font->cache),
glyphs, nglyphs, attributes, &(items[i].a),
advances, offsets, &overall_metrics);
- if (!result)
+ if (result == 0) /* Success. */
{
- int j, nclusters;
+ int j, nclusters, from, to;
+
+ from = rtl > 0 ? 0 : nchars_in_run - 1;
+ to = from;
for (j = 0; j < nglyphs; j++)
{
int lglyph_index = j + done_glyphs;
Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, lglyph_index);
- GLYPHMETRICS metrics;
+ ABC char_metric;
if (NILP (lglyph))
{
LGSTRING_SET_GLYPH (lgstring, lglyph_index, lglyph);
}
LGLYPH_SET_CODE (lglyph, glyphs[j]);
- LGLYPH_SET_WIDTH (lglyph, advances[j]);
- if (offsets[j].du || offsets[j].dv)
+
+ /* Detect clusters, for linking codes back to characters. */
+ if (attributes[j].fClusterStart)
{
- Lisp_Object vec;
- /* Convert from logical inches. */
- int dpi = FRAME_W32_DISPLAY_INFO (f)->resy;
- int dx = (int)(offsets[j].du * dpi / 72.27 + 0.5);
- int dy = (int)(offsets[j].dv * dpi / 72.27 + 0.5);
- vec = Fmake_vector (make_number (3), Qnil);
- ASET (vec, 0, make_number (dx));
- ASET (vec, 1, make_number (dy));
- /* Based on what ftfont.c does... */
- ASET (vec, 2, make_number (advances[j]));
- LGLYPH_SET_ADJUSTMENT (lglyph, vec);
+ while (from >= 0 && from < nchars_in_run
+ && clusters[from] < j)
+ from += rtl;
+ if (from < 0)
+ from = to = 0;
+ else if (from >= nchars_in_run)
+ from = to = nchars_in_run - 1;
+ else
+ {
+ int k;
+ to = rtl > 0 ? nchars_in_run - 1 : 0;
+ for (k = from + rtl; k >= 0 && k < nchars_in_run;
+ k += rtl)
+ {
+ if (clusters[k] > j)
+ {
+ to = k - 1;
+ break;
+ }
+ }
+ }
}
- else
- LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
- if (GetGlyphOutlineW (context, glyphs[j],
- GGO_METRICS | GGO_GLYPH_INDEX,
- &metrics, 0, NULL, &transform)
- != GDI_ERROR)
+ LGLYPH_SET_CHAR (lglyph, chars[items[i].iCharPos
+ + from]);
+ LGLYPH_SET_FROM (lglyph, items[i].iCharPos + from);
+ LGLYPH_SET_TO (lglyph, items[i].iCharPos + to);
+
+ /* Metrics. */
+ LGLYPH_SET_WIDTH (lglyph, advances[j]);
+ LGLYPH_SET_ASCENT (lglyph, font->ascent);
+ LGLYPH_SET_DESCENT (lglyph, font->descent);
+
+ result = ScriptGetGlyphABCWidth (context,
+ &(uniscribe_font->cache),
+ glyphs[j], &char_metric);
+
+ if (result == 0) /* Success. */
{
- LGLYPH_SET_LBEARING (lglyph, metrics.gmptGlyphOrigin.x);
- LGLYPH_SET_RBEARING (lglyph,
- metrics.gmBlackBoxX
- + metrics.gmptGlyphOrigin.x);
- LGLYPH_SET_ASCENT (lglyph, metrics.gmBlackBoxY);
- LGLYPH_SET_DESCENT (lglyph,
- (metrics.gmCellIncY
- - metrics.gmptGlyphOrigin.y
- - metrics.gmBlackBoxY));
+ LGLYPH_SET_LBEARING (lglyph, char_metric.abcA);
+ LGLYPH_SET_RBEARING (lglyph, (char_metric.abcA
+ + char_metric.abcB));
}
else
{
- /* Defaults based on what we know from elsewhere. */
LGLYPH_SET_LBEARING (lglyph, 0);
LGLYPH_SET_RBEARING (lglyph, advances[j]);
- LGLYPH_SET_ASCENT (lglyph, font->ascent);
- LGLYPH_SET_DESCENT (lglyph, font->descent);
}
- }
-
- /* Set character codes as indicated in clusters. */
- for (j = 0; j < nchars_in_run - 1; j++)
- {
- int k, start, end;
- wchar_t this_char = *(chars + items[i].iCharPos + j);
- start = clusters[i];
- end = clusters[i+1];
- if (start > end)
- {
- int temp = start;
- start = end;
- end = temp;
- }
- for (k = start; k < end; k++)
+ if (offsets[j].du || offsets[j].dv)
{
- Lisp_Object lglyph = LGSTRING_GLYPH (lgstring,
- done_glyphs + k);
- LGLYPH_SET_CHAR (lglyph, this_char);
+ Lisp_Object vec;
+ vec = Fmake_vector (make_number (3), Qnil);
+ ASET (vec, 0, make_number (offsets[j].du));
+ ASET (vec, 1, make_number (offsets[j].dv));
+ /* Based on what ftfont.c does... */
+ ASET (vec, 2, make_number (advances[j]));
+ LGLYPH_SET_ADJUSTMENT (lglyph, vec);
}
- }
- /* Last one until end (or beginning) of string. */
- {
- int k, start, end;
- wchar_t last_char = *(chars + items[i].iCharPos
- + nchars_in_run - 1);
- start = clusters[nchars_in_run - 1];
- end = nglyphs;
- if (start < clusters[nchars_in_run - 2])
- {
- end = start + 1;
- start = 0;
- }
- for (k = start; k < end; k++)
- {
- Lisp_Object lglyph = LGSTRING_GLYPH (lgstring,
- done_glyphs + k);
- LGLYPH_SET_CHAR (lglyph, last_char);
- }
- }
- }
+ else
+ LGLYPH_SET_ADJUSTMENT (lglyph, Qnil);
+ } }
}
done_glyphs += nglyphs;
- done_chars += nchars_in_run;
}
xfree (items);
if (NILP (lgstring))
return Qnil;
else
- return make_number (done_chars);
+ return make_number (done_glyphs);
}
/* Uniscribe implementation of encode_char for font backend.
/* Use selected frame until API is updated to pass the frame. */
f = XFRAME (selected_frame);
context = get_frame_dc (f);
- old_font = SelectObject (context,
- ((W32FontStruct *)(font->font.font))->hfont);
+ old_font = SelectObject (context, FONT_HANDLE(font));
retval = GetGlyphIndicesW (context, chars, 1, indices,
GGI_MARK_NONEXISTING_GLYPHS);
&& font_type != TRUETYPE_FONTTYPE)
return 1;
- family = intern_downcase (logical_font->elfLogFont.lfFaceName,
- strlen (logical_font->elfLogFont.lfFaceName));
+ /* Skip fonts that have no unicode coverage. */
+ if (!physical_font->ntmFontSig.fsUsb[3]
+ && !physical_font->ntmFontSig.fsUsb[2]
+ && !physical_font->ntmFontSig.fsUsb[1]
+ && !(physical_font->ntmFontSig.fsUsb[0] & 0x3fffffff))
+ return 1;
+
+ family = font_intern_prop (logical_font->elfLogFont.lfFaceName,
+ strlen (logical_font->elfLogFont.lfFaceName), 1);
if (! memq_no_quit (family, *list))
*list = Fcons (family, *list);
static char* NOTHING = " ";
-#define SNAME(VAL) SDATA (STRINGP (VAL) ? VAL : SYMBOL_NAME (VAL))
+#define SNAME(VAL) SDATA (SYMBOL_NAME (VAL))
/* Check if font supports the otf script/language/features specified.
OTF_SPEC is in the format
struct font_driver uniscribe_font_driver =
{
0, /* Quniscribe */
+ 0, /* case insensitive */
w32font_get_cache,
uniscribe_list,
uniscribe_match,
register_font_driver (&uniscribe_font_driver, NULL);
}
-#endif /* USE_FONT_BACKEND */
-
/* arch-tag: 9530f0e1-7471-47dd-a780-94330af87ea0
(do not change this comment) */