summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fontforge/python.c218
-rw-r--r--htdocs/python.html100
2 files changed, 316 insertions, 2 deletions
diff --git a/fontforge/python.c b/fontforge/python.c
index 37ba263b..5ce08b78 100644
--- a/fontforge/python.c
+++ b/fontforge/python.c
@@ -1043,7 +1043,7 @@ return( NULL );
return( NULL );
}
for ( i=0; i<cnt; ++i ) {
- PyObject *utf8_name = PYBYTES_UTF8(PyTuple_GetItem(answero,i));
+ PyObject *utf8_name = PYBYTES_UTF8(PySequence_GetItem(answero,i));
if ( utf8_name==NULL )
return( NULL );
answers[i] = copy(PyBytes_AsString(utf8_name));
@@ -14748,7 +14748,7 @@ static PyObject *PyFFFont_addSmallCaps(PyObject *self, PyObject *args, PyObject
memset(&genchange,0,sizeof(genchange));
SmallCapsFindConstants(&small,fv->sf,fv->active_layer);
genchange.small = &small;
- genchange.gc = gc_subsuper;
+ genchange.gc = gc_smallcaps;
genchange.extension_for_letters = "sc";
genchange.extension_for_symbols = "taboldstyle";
if ( !PyArg_ParseTupleAndKeywords(args,keywds,"|ddddissddd",smallcaps_keywords,
@@ -14788,6 +14788,219 @@ return( NULL );
Py_RETURN( self );
}
+static char *genchange_keywords[] = {
+/* Stem info */
+ "stemType",
+ "thickThreshold",
+ "stemScale", "stemAdd",
+ "stemHeightScale", "thinStemScale",
+ "stemHeightAdd", "thinStemAdd",
+ "stemWidthScale", "thickStemScale",
+ "stemWidthAdd", "thickStemAdd",
+ "processDiagonalStems",
+/* Horizontal counter info */
+ "hCounterType",
+ "hCounterScale", "hCounterAdd",
+ "lsbScale", "lsbAdd",
+ "rsbScale", "rsbAdd",
+/* Vertical counter info */
+ "vCounterType",
+ "vCounterScale", "vCounterAdd",
+ "vScale",
+ "vMap",
+ NULL};
+
+static PyObject *PyFFFont_genericGlyphChange(PyObject *self, PyObject *args, PyObject *keywds) {
+ FontViewBase *fv = ((PyFF_Font *) self)->fv;
+ struct smallcaps small;
+ struct genericchange genchange;
+ char *stemtype = "uniform", *hcountertype="uniform", *vCounterType="mapped";
+ double thickthreshold=0,
+ stemscale=0, stemadd=0,
+ stemheightscale=0, thinstemscale=0,
+ stemheightadd=0, thinstemadd=0,
+ stemwidthscale=0, thickstemscale=0,
+ stemwidthadd=0, thickstemadd=0;
+ int processdiagonalstems=1;
+ double counterScale=0, counterAdd=0,
+ lsbScale=0, lsbAdd=0,
+ rsbScale=0, rsbAdd=0;
+ double vCounterScale=0, vCounterAdd=0,
+ vScale=1.0;
+ PyObject *vMap=NULL;
+
+ memset(&genchange,0,sizeof(genchange));
+ SmallCapsFindConstants(&small,fv->sf,fv->active_layer);
+ genchange.small = &small;
+ genchange.gc = gc_generic;
+ if ( !PyArg_ParseTupleAndKeywords(args,keywds,"|sdddddddddddisddddddsdddO",genchange_keywords,
+/* Stem info */
+ &stemtype,
+ &thickthreshold,
+ &stemscale, &stemadd,
+ &stemheightscale,&thinstemscale,
+ &stemheightadd, &thinstemadd,
+ &stemwidthscale, &thickstemscale,
+ &stemwidthadd, &thickstemadd,
+ &processdiagonalstems,
+/* Horizontal counter info */
+ &hcountertype,
+ &counterScale, &counterAdd,
+ &lsbScale, &lsbAdd,
+ &rsbScale, &rsbAdd,
+/* Vertical counter info */
+ &vCounterType,
+ &vCounterScale, vCounterAdd,
+ &vScale,
+ &vMap
+ ))
+return( NULL );
+
+/* Stem info */
+ if ( strcasecmp(stemtype,"uniform")==0 ) {
+ if ( stemscale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for stemScale: %g.", stemscale );
+return( NULL );
+ }
+ genchange.stem_width_scale = genchange.stem_height_scale = stemscale;
+ genchange.stem_width_add = genchange.stem_height_add = stemadd;
+ } else if ( strcasecmp( stemtype, "thickThin" )==0 ) {
+ if ( thinstemscale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for thinStemScale: %g.", thinstemscale );
+return( NULL );
+ }
+ if ( thickstemscale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for thickStemScale: %g.", thickstemscale );
+return( NULL );
+ }
+ if ( thickthreshold<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for thickThreshold: %g.", thickthreshold );
+return( NULL );
+ }
+ genchange.stem_width_scale = thickstemscale;
+ genchange.stem_width_add = thickstemadd;
+ genchange.stem_height_scale = thinstemscale;
+ genchange.stem_height_add = thinstemadd;
+ genchange.stem_threshold = thickthreshold;
+ } else if ( strcasecmp( stemtype, "horizontalVertical" )==0 ) {
+ if ( stemheightscale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for stemHeightScale: %g.", stemheightscale );
+return( NULL );
+ }
+ if ( stemwidthscale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for stemWidthScale: %g.", stemwidthscale );
+return( NULL );
+ }
+ genchange.stem_width_scale = stemwidthscale;
+ genchange.stem_width_add = stemwidthadd;
+ genchange.stem_height_scale = stemheightscale;
+ genchange.stem_height_add = stemheightadd;
+ } else {
+ PyErr_Format(PyExc_TypeError, "Unexpected value for stemType: %s\n (Try: 'uniform', 'thickThin', or 'horizontalVertical')", stemtype );
+return( NULL );
+ }
+ genchange.dstem_control = processdiagonalstems;
+ if ( genchange.stem_height_add!=genchange.stem_width_add ) {
+ if (( genchange.stem_height_add==0 && genchange.stem_width_add!=0 ) ||
+ ( genchange.stem_height_add!=0 && genchange.stem_width_add==0 )) {
+ PyErr_Format(PyExc_TypeError, _("The horizontal and vertical stem add amounts must either both be zero, or neither may be 0"));
+return( NULL );
+ }
+ /* if width_add has a different sign than height_add that's also */
+ /* a problem, but this test will catch that too */
+ if (( genchange.stem_height_add/genchange.stem_width_add>4 ) ||
+ ( genchange.stem_height_add/genchange.stem_width_add<.25 )) {
+ PyErr_Format(PyExc_TypeError, _("The horizontal and vertical stem add amounts may not differ by more than a factor of 4"));
+return( NULL );
+ }
+ }
+
+/* Horizontal counter info */
+ if ( strcasecmp(hcountertype,"uniform")==0 ) {
+ if ( counterScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for hCounterScale: %g.", counterScale );
+return( NULL );
+ }
+ genchange.hcounter_scale = genchange.lsb_scale = genchange.rsb_scale = counterScale;
+ genchange.hcounter_add = genchange.lsb_add = genchange.rsb_add = counterAdd;
+ } else if ( strcasecmp(hcountertype,"nonUniform")==0 ) {
+ if ( counterScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for hCounterScale: %g.", counterScale );
+return( NULL );
+ }
+ if ( lsbScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for lsbScale: %g.", lsbScale );
+return( NULL );
+ }
+ if ( rsbScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for rsbScale: %g.", rsbScale );
+return( NULL );
+ }
+ genchange.hcounter_scale = counterScale;
+ genchange.lsb_scale = lsbScale;
+ genchange.rsb_scale = rsbScale;
+ genchange.hcounter_add = counterAdd;
+ genchange.lsb_add = lsbAdd;
+ genchange.rsb_add = rsbAdd;
+ } else if ( strcasecmp(hcountertype,"center")==0 ) {
+ genchange.center_in_hor_advance = 1;
+ } else if ( strcasecmp(hcountertype,"retainScale")==0 ) {
+ genchange.center_in_hor_advance = 2;
+ } else {
+ PyErr_Format(PyExc_TypeError, "Unexpected value for hCounterType: %s\n (Try: 'uniform', 'nonUniform', 'retain', or 'scale')", hcountertype );
+return( NULL );
+ }
+
+/* Vertical counter info */
+ if ( strcasecmp(vCounterType,"scaled")==0 ) {
+ if ( vCounterScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for vCounterScale: %g.", vCounterScale );
+return( NULL );
+ }
+ genchange.vcounter_scale = vCounterScale;
+ genchange.vcounter_add = vCounterAdd;
+ genchange.use_vert_mapping = false;
+ } else if ( strcasecmp(vCounterType,"mapped")==0 ) {
+ int cnt,i;
+ genchange.use_vert_mapping = true;
+ if ( vScale<=0 ) {
+ PyErr_Format(PyExc_TypeError, "Unexpected (or unspecified) value for vScale: %g.", vScale );
+return( NULL );
+ }
+ genchange.v_scale = vScale;
+ if ( vMap==NULL || !PySequence_Check(vMap) || STRING_CHECK(vMap)) {
+ PyErr_Format(PyExc_TypeError, "vMap should be a tuple (or some other sequence type)." );
+return( NULL );
+ }
+ cnt = PySequence_Size(vMap);
+ genchange.m.cnt = cnt;
+ genchange.m.maps = galloc(cnt*sizeof(struct position_maps));
+ for ( i=0; i<cnt; ++i ) {
+ PyObject *subTuple = PySequence_GetItem(vMap,i);
+ if ( subTuple==NULL || !PySequence_Check(subTuple) || STRING_CHECK(subTuple) || PySequence_Size(subTuple)!=3 ) {
+ PyErr_Format(PyExc_TypeError, "vMap should be a tuple of 3-tuples." );
+ free(genchange.m.maps);
+return( NULL );
+ }
+ if ( !PyArg_ParseTuple(subTuple,"ddd",
+ &genchange.m.maps[i].current,
+ &genchange.m.maps[i].desired,
+ &genchange.m.maps[i].cur_width) ) {
+ free(genchange.m.maps);
+return( NULL );
+ }
+ }
+ } else {
+ PyErr_Format(PyExc_TypeError, "Unexpected value for vCounterType: %s\n (Try: 'scaled', or 'mapped')", vCounterType );
+return( NULL );
+ }
+
+ FVGenericChange( fv, &genchange );
+ free(genchange.m.maps);
+
+Py_RETURN( self );
+}
+
static PyObject *PyFFFont_autoHint(PyObject *self, PyObject *args) {
FontViewBase *fv = ((PyFF_Font *) self)->fv;
@@ -15107,6 +15320,7 @@ static PyMethodDef PyFF_Font_methods[] = {
/*{ "compareGlyphs", (PyCFunction) PyFFFont_compareGlyphs, METH_VARARGS, "Compares two sets of glyphs"},*/
/* compareGlyphs assumes an old scripting context */
{ "correctDirection", (PyCFunction) PyFFFont_Correct, METH_NOARGS, "Orient a layer so that external contours are clockwise and internal counter clockwise." },
+ { "genericGlyphChange", (PyCFunction) PyFFFont_genericGlyphChange, METH_VARARGS | METH_KEYWORDS, "Rather like changeWeight or condenseExtend but with more options."},
{ "italicize", (PyCFunction) PyFFFont_italicize, METH_VARARGS | METH_KEYWORDS, "Italicize the selected glyphs"},
{ "intersect", (PyCFunction) PyFFFont_Intersect, METH_NOARGS, "Leaves the areas where the contours of a glyph overlap."},
{ "removeOverlap", (PyCFunction) PyFFFont_RemoveOverlap, METH_NOARGS, "Remove overlapping areas from a glyph"},
diff --git a/htdocs/python.html b/htdocs/python.html
index 75b417ba..9da7aac1 100644
--- a/htdocs/python.html
+++ b/htdocs/python.html
@@ -4211,6 +4211,106 @@ pen = None; # Finalize the pen. This tells FontForge
is specified then only data for that lookup will be generated.</TD>
</TR>
<TR>
+ <TD><CODE>genericGlyphChange</CODE></TD>
+ <TD><CODE>(stemType=&lt;str>,<BR>
+ &nbsp;thickThreshold=&lt;double>,<BR>
+ &nbsp;stemScale=&lt;double>,<BR>
+ &nbsp;stemAdd=&lt;double>,<BR>
+ &nbsp;stemHeightScale=&lt;double>,<BR>
+ &nbsp;stemHeightAdd=&lt;double>,<BR>
+ &nbsp;stemWidthScale=&lt;double>,<BR>
+ &nbsp;stemWidthAdd=&lt;double>,<BR>
+ &nbsp;thinStemScale=&lt;double>,<BR>
+ &nbsp;thinStemAdd=&lt;double>,<BR>
+ &nbsp;thickStemScale=&lt;double>,<BR>
+ &nbsp;thickStemAdd=&lt;double>,<BR>
+ &nbsp;processDiagonalStems=&lt;boolean>,<BR>
+ &nbsp;<BR>
+ &nbsp;hCounterType=&lt;str>,<BR>
+ &nbsp;hCounterScale=&lt;double>,<BR>
+ &nbsp;hCounterAdd=&lt;double>,<BR>
+ &nbsp;lsbScale=&lt;double>,<BR>
+ &nbsp;lsbAdd=&lt;double>,<BR>
+ &nbsp;rsbScale=&lt;double>,<BR>
+ &nbsp;rsbAdd=&lt;double>,<BR>
+ &nbsp;<BR>
+ &nbsp;vCounterType=&lt;str>,<BR>
+ &nbsp;vCounterScale=&lt;double>,<BR>
+ &nbsp;vCounterAdd=&lt;double>,<BR>
+ &nbsp;vScale=&lt;double>,<BR>
+ &nbsp;vMap=&lt;tuple of tuples>)</CODE></TD>
+ <TD>This function uses keyword parameters. Which ones are required depends
+ on the three type arguments (<CODE>stemType, hCounterType,
+ vCounterType</CODE>).
+ <P>
+ If <CODE>stemType</CODE> is omitted, or is the string "uniform", then
+ the <CODE>stemScale</CODE> parameter must be specified (and
+ <CODE>stemAdd</CODE> may be). <CODE>stemScale</CODE> specifies a
+ scaling factor by which all stems (horizontal and vertical, thick and
+ thin) will be scaled. A value of 1.0 means no change. While
+ <CODE>stemAdd</CODE> specifies the number of em-units to add to the
+ width of each stem.
+ <P>
+ If <CODE>stemType</CODE> is the string "horizontalVertical",
+ then values must be specified for <CODE>stemHeightScale</CODE> and
+ <CODE>stemWidthScale</CODE> (and may be for <CODE>stemHeightAdd,
+ stemWidthAdd</CODE>). The first of these specifies scaling for the
+ height of horizontal stems, and the second scaling for the width
+ of vertical stems.
+ <P>
+ If <CODE>stemType</CODE> is the string "thickThin",
+ then values must be specified for <CODE>thinStemScale</CODE>,
+ <CODE>thickStemScale</CODE> and <CODE>thickThreshold</CODE>
+ (and may be for <CODE>thinStemAdd, thickStemAdd</CODE>). The
+ first of these specifies scaling for the width/height of thin
+ stems, and the second scaling for the width/height of thick
+ stems. While the <CODE>thickThreshold</CODE> argument specifies
+ the size (in em-units) at which a stem is classified as "thick".
+ <P>
+ <P>
+ If <CODE>hCounterType</CODE> is omitted, or is the string "uniform",
+ then horizontal counters, and the left and right side bearings will
+ all be scaled using the same rules, and <CODE>hCounterScale</CODE>
+ must be specified to provide the scaling factor (while
+ <CODE>hCounterAdd</CODE> may be specified).
+ <P>
+ If <CODE>hCounterType</CODE> is the string "nonUniform",
+ then horizontal counters, and the left and right side bearings may
+ all be scaled using different rules, and <CODE>hCounterScale,
+ lsbScale</CODE> and <CODE>rsbScale</CODE> must be specified to
+ provide the scaling factors (while <CODE>hCounterAdd, lsbAdd,</CODE>
+ and <CODE>rsbAdd</CODE> may be specified).
+ <P>
+ If <CODE>hCounterType</CODE> is the string "center", then the left
+ and right side-bearings will be set so the new glyph is centered
+ within the original glyph's width. (Probably more useful for CJK
+ fonts than LGC fonts).
+ <P>
+ If <CODE>hCounterType</CODE> is the string "retainScale", then the
+ left and right side-bearings will be set so the new glyph is within
+ within the original glyph's width, and the side-bearings remain in
+ the same proportion to each other as before.
+ <P>
+ <P>
+ If <CODE>vCounterType</CODE> is omitted, or is the string "mapped",
+ then certain zones on the glyph may be placed at new (or the same)
+ locations -- similar to BlueValues. So you can specify a zone for
+ the baseline, one for the
+ x-height and another for the top of capitals and ascenders (and perhaps
+ a fourth for descenders). Each such zone is specified by the
+ <CODE>vMap</CODE> argument which is a tuple of 3-tuples, each
+ 3-tuple specifying a zone with: Original location, original width, and
+ final location. <strong>No default value is provided for this argument
+ you must figure out all the values yourself</strong>.
+ <P>
+ If <CODE>vCounterType</CODE> is the string "scaled",
+ then vertical counters, and the top and bottom side bearings will
+ all be scaled using the same rules, and <CODE>vCounterScale</CODE>
+ must be specified to provide the scaling factor (while
+ <CODE>vCounterAdd</CODE> may be specified). This is probably most
+ useful for CJK fonts.</TD>
+ </TR>
+ <TR>
<TD><CODE>getKerningClass</CODE></TD>
<TD><CODE>(subtable-name)</CODE></TD>
<TD>Returns a tuple whose entries are: (first-classes, second-classes, offsets).