[XeTeX] Patch: Add an entry for stemv
Yue Wang
yuleopen at gmail.com
Wed Mar 4 04:44:42 CET 2009
Hi, Jonathan:
Last year we talked about fonts like simsun may get ugly result when
using the dvipdfmx driver. And Jin-Hwan kindly added a -v option to
dvipdfmx driver in order to specify stemv number. So in the
tex->dvipdfmx world, now we can apply fake embolden, fake slant, and
stemv modification to a given font.
Today I hacked xetex three hours and added a new entry for xetex, and
here is the patch.
Usage:
\font\a="foobar:stemv=30" at 10pt
\a foobar font \bye
Index: texk/web2c/xetexdir/XeTeXLayoutInterface.cpp
===================================================================
--- texk/web2c/xetexdir/XeTeXLayoutInterface.cpp (revision 899)
+++ texk/web2c/xetexdir/XeTeXLayoutInterface.cpp (working copy)
@@ -69,6 +69,7 @@
float extend;
float slant;
float embolden;
+ int stemv;
#ifdef XETEX_GRAPHITE
gr::Segment* grSegment;
XeTeXGrFont* grFont;
@@ -545,9 +546,14 @@
return engine->embolden;
}
+int getStemVFactor(XeTeXLayoutEngine engine)
+{
+ return engine->stemv;
+}
+
XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef,
XeTeXFont font, UInt32 scriptTag, UInt32 languageTag,
UInt32* addFeatures, SInt32* addParams, UInt32*
removeFeatures, UInt32 rgbValue,
- float extend, float slant, float embolden)
+ float extend, float slant, float embolden, int stemv)
{
LEErrorCode status = LE_NO_ERROR;
XeTeXLayoutEngine result = new XeTeXLayoutEngine_rec;
@@ -561,6 +567,7 @@
result->extend = extend;
result->slant = slant;
result->embolden = embolden;
+ result->stemv = stemv;
#ifdef XETEX_GRAPHITE
result->grSegment = NULL;
@@ -912,7 +919,7 @@
XeTeXLayoutEngine createGraphiteEngine(PlatformFontRef fontRef, XeTeXFont font,
const char* name,
UInt32 rgbValue, int rtl, UInt32 languageTag,
- float extend, float slant, float embolden,
+ float extend, float slant, float embolden, int stemv,
int nFeatures, const int* featureIDs, const int* featureValues)
{
// check if the font supports graphite, and return NULL if not
@@ -931,6 +938,7 @@
result->extend = extend;
result->slant = slant;
result->embolden = embolden;
+ result->stemv = stemv;
result->layoutEngine = NULL;
result->grFont = new XeTeXGrFont(result->font, name);
Index: texk/web2c/xetexdir/XeTeX_mac.c
===================================================================
--- texk/web2c/xetexdir/XeTeX_mac.c (revision 899)
+++ texk/web2c/xetexdir/XeTeX_mac.c (working copy)
@@ -799,7 +799,7 @@
// didn't find feature or variation, try other options....
- i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue);
+ i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue, &stemv);
if (i == 1)
goto next_option;
else if (i == -1)
Index: texk/web2c/xetexdir/XeTeX_ext.c
===================================================================
--- texk/web2c/xetexdir/XeTeX_ext.c (revision 899)
+++ texk/web2c/xetexdir/XeTeX_ext.c (working copy)
@@ -730,6 +730,51 @@
return neg ? -val : val;
}
+int
+read_integer(const char** s)
+{
+ int neg = 0;
+ int val = 0;
+ const char* cp = *s;
+
+ while (*cp == ' '|| *cp == '\t')
+ ++cp;
+ if (*cp == '-') {
+ neg = 1;
+ ++cp;
+ }
+ else if (*cp == '+') {
+ ++cp;
+ }
+
+ while (*cp >= '0' && *cp <= '9') {
+ val = val * 10 + *cp - '0';
+ ++cp;
+ }
+ *s = cp;
+
+ return neg ? -val : val;
+}
+
+int
+read_unsigned_integer(const char** s)
+{
+ int val = 0;
+ const char* cp = *s;
+
+ while (*cp == ' '|| *cp == '\t')
+ ++cp;
+
+ while (*cp >= '0' && *cp <= '9') {
+ val = val * 10 + *cp - '0';
+ ++cp;
+ }
+ *s = cp;
+
+ return val;
+}
+
+
static UInt32
read_tag(const char* cp, char padChar)
{
@@ -815,7 +860,7 @@
}
int
-readCommonFeatures(const char* feat, const char* end, float* extend,
float* slant, float* embolden, float* letterspace, UInt32* rgbValue)
+readCommonFeatures(const char* feat, const char* end, float* extend,
float* slant, float* embolden, float* letterspace, UInt32* rgbValue,
int* stemv)
// returns 1 to go to next_option, -1 for bad_option, 0 to continue
{
const char* sep;
@@ -878,6 +923,16 @@
return 1;
}
+ if (strncmp(feat, "stemv", 5) == 0) {
+ sep = feat + 5;
+ if (*sep != '=')
+ return -1;
+ ++sep;
+ *stemv = read_unsigned_integer(&sep);
+ return 1;
+ }
+
+
return 0;
}
@@ -906,6 +961,7 @@
float slant = 0.0;
float embolden = 0.0;
float letterspace = 0.0;
+ int stemv = -1;
int i;
@@ -939,7 +995,7 @@
goto next_option;
}
- i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue);
+ i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue, &stemv);
if (i == 1)
goto next_option;
else if (i == -1)
@@ -1010,6 +1066,9 @@
if (letterspace != 0.0)
loadedfontletterspace = (letterspace / 100.0) * scaled_size;
+ if (stemv != -1)
+ stemv = stemv;
+
if ((loadedfontflags & FONT_FLAGS_COLORED) == 0)
rgbValue = 0x000000FF;
@@ -1018,7 +1077,7 @@
engine = createLayoutEngine(fontRef, font, scriptTag, languageTag,
addFeatures, addParams, removeFeatures, rgbValue,
- extend, slant, embolden);
+ extend, slant, embolden, stemv);
if (engine == 0) {
// only free these if creation failed, otherwise the engine now owns them
if (addFeatures)
@@ -1077,6 +1136,7 @@
float slant = 0.0;
float embolden = 0.0;
float letterspace = 0.0;
+ int stemv = -1;
int rtl = 0;
int featureIDs[MAX_GRAPHITE_FEATURES];
@@ -1089,7 +1149,7 @@
/* create a default engine so we can query the font for Graphite features;
because of font caching, it's cheap to discard this and create
the real one later */
engine = createGraphiteEngine(fontRef, font, faceName, rgbValue,
rtl, languageTag,
- extend, slant, embolden, 0, NULL, NULL);
+ extend, slant, embolden, stemv, 0, NULL, NULL);
if (engine == NULL)
return NULL;
@@ -1115,7 +1175,7 @@
goto next_option;
}
- i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue);
+ i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden,
&letterspace, &rgbValue, &stemv);
if (i == 1)
goto next_option;
else if (i == -1)
@@ -1176,6 +1236,9 @@
if (letterspace != 0.0)
loadedfontletterspace = (letterspace / 100.0) * scaled_size;
+ if (stemv != -1)
+ stemv = stemv;
+
if ((loadedfontflags & FONT_FLAGS_COLORED) == 0)
rgbValue = 0x000000FF;
@@ -1184,7 +1247,7 @@
// deleteLayoutEngine(engine);
engine = createGraphiteEngine(fontRef, font, faceName, rgbValue,
rtl, languageTag,
- extend, slant, embolden, nFeatures, &featureIDs[0], &featureValues[0]);
+ extend, slant, embolden, stemv, nFeatures, &featureIDs[0],
&featureValues[0]);
if (engine != NULL)
nativefonttypeflag = OTGR_FONT_FLAG;
@@ -1614,6 +1677,7 @@
#define XDV_FLAG_EXTEND 0x1000
#define XDV_FLAG_SLANT 0x2000
#define XDV_FLAG_EMBOLDEN 0x4000
+#define XDV_FLAG_STEMV 0x8000
#ifdef XETEX_MAC
static UInt32
@@ -1718,6 +1782,7 @@
float extend = 1.0;
float slant = 0.0;
float embolden = 0.0;
+ int stemv = -1;
#ifdef XETEX_MAC
ATSUStyle style = NULL;
@@ -1777,6 +1842,7 @@
extend = getExtendFactor(engine);
slant = getSlantFactor(engine);
embolden = getEmboldenFactor(engine);
+ stemv = getStemVFactor(engine);
size = X2Fix(getPointSize(engine));
}
@@ -1835,6 +1901,11 @@
flags |= XDV_FLAG_EMBOLDEN;
}
+ if (stemv != -1) {
+ fontDefLength += 2;
+ flags |= XDV_FLAG_STEMV;
+ }
+
if (fontDefLength > xdvBufSize) {
if (xdvbuffer != NULL)
free(xdvbuffer);
@@ -1905,6 +1976,11 @@
cp += 4;
}
+ if (flags & XDV_FLAG_STEMV) {
+ *(UInt16*)(cp) = SWAP16(stemv);
+ cp += 2;
+ }
+
return fontDefLength;
}
Index: texk/web2c/xetexdir/XeTeXLayoutInterface.h
===================================================================
--- texk/web2c/xetexdir/XeTeXLayoutInterface.h (revision 899)
+++ texk/web2c/xetexdir/XeTeXLayoutInterface.h (working copy)
@@ -95,7 +95,7 @@
XeTeXLayoutEngine createLayoutEngine(PlatformFontRef fontRef,
XeTeXFont font, UInt32 scriptTag, UInt32 languageTag,
UInt32* addFeatures, SInt32* addParams, UInt32* removeFeatures,
UInt32 rgbValue,
- float extend, float slant, float embolden);
+ float extend, float slant, float embolden, int stemv);
void deleteLayoutEngine(XeTeXLayoutEngine engine);
@@ -105,6 +105,7 @@
float getExtendFactor(XeTeXLayoutEngine engine);
float getSlantFactor(XeTeXLayoutEngine engine);
float getEmboldenFactor(XeTeXLayoutEngine engine);
+int getStemVFactor(XeTeXLayoutEngine engine);
SInt32 layoutChars(XeTeXLayoutEngine engine, UInt16* chars, SInt32
offset, SInt32 count, SInt32 max,
char rightToLeft, float x, float y, SInt32* status);
@@ -155,7 +156,7 @@
XeTeXLayoutEngine createGraphiteEngine(PlatformFontRef fontRef, XeTeXFont font,
const char* name,
UInt32 rgbValue, int rtl, UInt32 languageTag,
- float extend, float slant, float embolden,
+ float extend, float slant, float embolden, int stemv,
int nFeatures, const int* featureIDs, const int* featureValues);
int makeGraphiteSegment(XeTeXLayoutEngine engine, const UniChar*
txtPtr, int txtLen);
void getGraphiteGlyphInfo(XeTeXLayoutEngine engine, int index,
UInt16* glyphID, float* x, float* y);
Index: texk/web2c/xetexdir/XeTeX_ext.h
===================================================================
--- texk/web2c/xetexdir/XeTeX_ext.h (revision 899)
+++ texk/web2c/xetexdir/XeTeX_ext.h (working copy)
@@ -228,7 +228,7 @@
void* load_mapping_file(const char* s, const char* e, char byteMapping);
void* findnativefont(unsigned char* name, integer scaled_size);
void releasefontengine(void* engine, int type_flag);
- int readCommonFeatures(const char* feat, const char* end, float*
extend, float* slant, float* embolden, float* letterspace, UInt32*
rgbValue);
+ int readCommonFeatures(const char* feat, const char* end, float*
extend, float* slant, float* embolden, float* letterspace, UInt32*
rgbValue, int* stemv);
/* the metrics params here are really TeX 'scaled' values, but that
typedef isn't available every place this is included */
void otgetfontmetrics(void* engine, integer* ascent, integer*
descent, integer* xheight, integer* capheight, integer* slant);
Index: texk/xdvipdfmx/src/dvi.c
===================================================================
--- texk/xdvipdfmx/src/dvi.c (revision 899)
+++ texk/xdvipdfmx/src/dvi.c (working copy)
@@ -131,6 +131,7 @@
float extend;
float slant;
float embolden;
+ int stemv;
#endif
} *loaded_fonts = NULL;
static int num_loaded_fonts = 0, max_loaded_fonts = 0;
@@ -159,6 +160,7 @@
int extend;
int slant;
int embolden;
+ int stemv;
#endif
} *def_fonts = NULL;
@@ -172,6 +174,7 @@
#define XDV_FLAG_EXTEND 0x1000
#define XDV_FLAG_SLANT 0x2000
#define XDV_FLAG_EMBOLDEN 0x4000
+#define XDV_FLAG_STEMV 0x8000
#endif
static int num_def_fonts = 0, max_def_fonts = 0;
@@ -618,6 +621,7 @@
def_fonts[num_def_fonts].extend = 0x00010000; /* 1.0 */
def_fonts[num_def_fonts].slant = 0;
def_fonts[num_def_fonts].embolden = 0;
+ def_fonts[num_def_fonts].stemv = -1;
#endif
num_def_fonts++;
@@ -693,6 +697,10 @@
def_fonts[num_def_fonts].embolden = get_signed_quad(dvi_file);
else
def_fonts[num_def_fonts].embolden = 0;
+ if (flags & XDV_FLAG_STEMV)
+ def_fonts[num_def_fonts].stemv = get_unsigned_pair(dvi_file);
+ else
+ def_fonts[num_def_fonts].stemv = -1;
num_def_fonts++;
} else {
ERROR("Unknown native_font flags.");
@@ -1039,7 +1047,7 @@
#ifdef XETEX
static int
dvi_locate_native_font (const char *ps_name, const char *fam_name,
- const char *sty_name, spt_t ptsize, int
layout_dir, int extend, int slant, int embolden)
+ const char *sty_name, spt_t ptsize, int
layout_dir, int extend, int slant, int embolden, int stemv)
{
int cur_id = -1;
fontmap_rec *mrec;
@@ -1053,10 +1061,10 @@
cur_id = num_loaded_fonts++;
- sprintf(fontmap_key, "%s/%c/%d/%d/%d", ps_name, layout_dir == 0 ?
'H' : 'V', extend, slant, embolden);
+ sprintf(fontmap_key, "%s/%c/%d/%d/%d/%d", ps_name, layout_dir == 0
? 'H' : 'V', extend, slant, embolden, stemv);
mrec = pdf_lookup_fontmap_record(fontmap_key);
if (mrec == NULL) {
- if (pdf_load_native_font(ps_name, fam_name, sty_name, layout_dir,
extend, slant, embolden) == -1) {
+ if (pdf_load_native_font(ps_name, fam_name, sty_name, layout_dir,
extend, slant, embolden, stemv) == -1) {
ERROR("Cannot proceed without the \"native\" font: %s (%s %s)...",
ps_name, fam_name, sty_name);
}
@@ -1082,6 +1090,7 @@
loaded_fonts[cur_id].extend = mrec->opt.extend;
loaded_fonts[cur_id].slant = mrec->opt.slant;
loaded_fonts[cur_id].embolden = mrec->opt.bold;
+ loaded_fonts[cur_id].stemv = mrec->opt.stemv;
if (verbose)
MESG(">");
@@ -1720,7 +1729,8 @@
def_fonts[i].layout_dir,
def_fonts[i].extend,
def_fonts[i].slant,
- def_fonts[i].embolden);
+ def_fonts[i].embolden,
+ def_fonts[i].stemv);
} else {
font_id = dvi_locate_font(def_fonts[i].font_name,
def_fonts[i].point_size);
Index: texk/xdvipdfmx/src/fontmap.c
===================================================================
--- texk/xdvipdfmx/src/fontmap.c (revision 899)
+++ texk/xdvipdfmx/src/fontmap.c (working copy)
@@ -1049,7 +1049,7 @@
static int
pdf_insert_native_fontmap_record (const char *name, const char *path,
int index, FT_Face face,
- int layout_dir, int extend, int
slant, int embolden)
+ int layout_dir, int extend, int
slant, int embolden, int stemv)
{
char *fontmap_key;
fontmap_rec *mrec;
@@ -1058,7 +1058,7 @@
ASSERT(path || face);
fontmap_key = malloc(strlen(name) + 40); // CHECK
- sprintf(fontmap_key, "%s/%c/%d/%d/%d", name, layout_dir == 0 ? 'H'
: 'V', extend, slant, embolden);
+ sprintf(fontmap_key, "%s/%c/%d/%d/%d/%d", name, layout_dir == 0 ?
'H' : 'V', extend, slant, embolden, stemv);
if (verbose)
MESG("<NATIVE-FONTMAP:%s", fontmap_key);
@@ -1080,6 +1080,7 @@
mrec->opt.extend = extend / 65536.0;
mrec->opt.slant = slant / 65536.0;
mrec->opt.bold = embolden / 65536.0;
+ mrec->opt.stemv = stemv ;
pdf_insert_fontmap_record(mrec->map_name, mrec);
pdf_clear_fontmap_record(mrec);
@@ -1094,7 +1095,7 @@
static FT_Library ftLib;
static int
-pdf_load_native_font_from_path(const char *ps_name, int layout_dir,
int extend, int slant, int embolden)
+pdf_load_native_font_from_path(const char *ps_name, int layout_dir,
int extend, int slant, int embolden, int stemv)
{
const char *p;
char *filename = NEW(strlen(ps_name), char);
@@ -1134,7 +1135,7 @@
if (error == 0)
return pdf_insert_native_fontmap_record(ps_name, filename, index, face,
- layout_dir, extend, slant,
embolden);
+ layout_dir, extend, slant,
embolden, stemv);
else
return error;
}
@@ -1146,7 +1147,7 @@
int
pdf_load_native_font (const char *ps_name,
const char *fam_name, const char *sty_name,
- int layout_dir, int extend, int slant, int embolden)
+ int layout_dir, int extend, int slant, int
embolden, int stemv)
{
static int sInitialized = 0;
int error = -1;
@@ -1163,7 +1164,7 @@
}
if (ps_name[0] == '[') {
- error = pdf_load_native_font_from_path(ps_name, layout_dir,
extend, slant, embolden);
+ error = pdf_load_native_font_from_path(ps_name, layout_dir,
extend, slant, embolden, stemv);
}
else {
CFStringRef theName = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault,
@@ -1185,7 +1186,7 @@
ftErr = FT_New_Face(ftLib, (char*)path, index, &face);
if (ftErr == 0) {
error = pdf_insert_native_fontmap_record(ps_name, NULL, 0, face,
- layout_dir,
extend, slant, embolden);
+ layout_dir,
extend, slant, embolden, stemv);
}
}
}
@@ -1218,7 +1219,7 @@
}
if (ps_name[0] == '[') {
- error = pdf_load_native_font_from_path(ps_name, layout_dir,
extend, slant, embolden);
+ error = pdf_load_native_font_from_path(ps_name, layout_dir,
extend, slant, embolden, stemv);
}
else {
os = FcObjectSetBuild(FC_FILE, FC_INDEX, FC_FAMILY, FC_STYLE, NULL);
@@ -1242,7 +1243,7 @@
name = (char *)FT_Get_Postscript_Name(face);
if (!strcmp(name, ps_name)) {
error = pdf_insert_native_fontmap_record(ps_name,
(char*)path, index, face,
- layout_dir,
extend, slant, embolden);
+ layout_dir,
extend, slant, embolden, stemv);
/* don't dispose of the FT_Face, as we'll be using it to
retrieve font data */
break;
}
Index: texk/xdvipdfmx/src/fontmap.h
===================================================================
--- texk/xdvipdfmx/src/fontmap.h (revision 899)
+++ texk/xdvipdfmx/src/fontmap.h (working copy)
@@ -103,7 +103,7 @@
#ifdef XETEX
extern int pdf_load_native_font (const char *ps_name,
const char *fam_name,
const char *sty_name,
- int layout_dir, int
extend, int slant, int embolden);
+ int layout_dir, int
extend, int slant, int embolden, int stemv);
#endif
#endif /* _FONTMAP_H_ */
Some limitations and bugs:
- I haven't touched Mac support yet. we should also modify xdv2pdf
driver in order to support the modification. but my Mac is broken last
week.... and I do not have time to reinstall the operating system.
- parse_integer and parse_unsigned_integer do not detect number
overflow. but since your parse_double doesn't do that too, I think it
is not urgent.
- It might have other bugs since it is a quick hack... but I have no
time to test.
I hope you can apply the patch to trunk. Thanks!
Yue Wang
More information about the XeTeX
mailing list