New to Typophile? Accounts are free, and easy to set up.

Posted by peterbruhn in

24 May 2003 — 4:21am

24 May 2003 — 4:21am

I'm slowly trying to come to terms with Fontlab, even though it's not a intinutive GUI.

I still do most of my work in Fog and only use Fontlab for the last bits. However,

when opening my files in Fontlab, some of my tangent points

are gone and replaced. (see image below)

Why is that? Is it just a preference that I missed?

Or doesn't Fontlab handle tangent points? How will I then be able to make smooth transitions?

Anyone out there with FL wisdom?

24 May 2003 — 5:22am

Peter --

I'm going to guess that what is happening is the translation from FOG to Postscript to FL. Postscript doesn't make a distinction about point types, coding only the coordinates of the on-curve points and the associated control points. If I'm not mistaken, PS doesn't handle decimal places, so coordinates are rounded to the nearest integer when a PS font is generated. Non-orthogonal curves and tangents are particularly susceptible to this.

When FL reads the PS data from the font, I'm guessing that if the points aren't exactly colinear (due to rounding) that FL will not interpret them as tangent points per se. I would presume that your points and controls are still in the proper places (allowing for rounding). I'd be curious to see a screenshot with the control handles showing. For instance, did FL add a handle to the bottom side of that lower, outside curve point?

I'm just starting the arduous transition to FL myself and am by no means an expert. Someone more technically savvy, like John Hudson, might have a better explanation.

-- Kent.

24 May 2003 — 7:15am

Hi Kent,

I know I read somewhere about different types of round points in FL.

I thought I read it here at Typophile but I can't find it.

But even if that's the case, I would

like to know which curve points are tangent like points by just looking.

Here's a closer example (Fog version to the left).

Sorry about the large image, but otherwise it's hard to see.

/p

24 May 2003 — 5:10pm

Peter --

I've been thinking about this and spending some time with the FontLab manual.

I had an insight that I think might help.

The FOG model is point-based. But the FontLab model is segment-based.

What I mean is that in FOG you are usually focused on what kind of point

you're placing. Whereas in FL, the emphasis is on what kind of line segment

is being operated on. FOG has three kinds of points -- corner, curve, and

tangent. FL doesn't make these distinctions.

FL distinguishes between two different kinds of line segment -- a straight line

(which they also call a

vector) and a curve (a bezier curve). A curve is describedby four points -- two end points on the curve (

nodes) and the two beziercontrol points on the handles. A straight line is controlled by only two nodes --

one at either end, with no control handles.

FL also distinguishes two different kinds of transitions between line segments --

a node can either be a smooth connection or a sharp connection.

So, if you have a curve meeting another curve, then the node will have two

control handles, one contributing to each of the two curves. If the connection

is smooth, then the two handles will be co-linear -- that is, they are linked

and stay aligned with each other -- so this kind of node is what FOG would call

a curve point.

If two curves meet and the connection is sharp, then the two control handles

can be moved independent from one another. This node would then constitute

a corner point in FOG.

If two straight line segments meet, then the node does not have any control

handles and is necessarily sharp. This would also be considered a corner point

in FOG.

If a straight line meets a curve, then the node will have one control handle on

the curve side. If the connection is sharp, then this control handle can move

any which way and the node would be considered a corner point in FOG.

But if the connection is smooth, then the control handle on the curve side

will be co-linear with the vector segment meeting up with the curve and will

only move in a line with this vector -- and this is what FOG would call

a tangent point.

Does this help?

So, you need to notice whether the node between a straight line and a curve

is smooth or sharp. When it is selected, you will see off to the side of the

node either a circle (smooth connection) or an x (sharp connection). You can

also turn on all connection types for every node, whether selected or not, by

selecting the button from the View/Show Layers toolbar.

So, for example, if you select the node on the top of the inside of your

counter, you will see whether it is a smooth connection or not. If it isn't,

then double click the node to toggle the connection style. When the connection

is smooth, then you can change the "curve" on the right side to a straight line

by selecting the right control handle of the node and deleting it. (Deleting

either control handle of a segment will convert it to a straight line vector, since

a curve needs to be defined by two control handles.)

Once the right-hand segment is a straight line and the left-hand segment is a

curve and the node is a smooth connection, then the handle on the left will

only move in line with the straight segment and you will have, in effect, a

tangent point.

I hope this makes sense and is helpful.

-- Kent.

24 May 2003 — 6:55pm

To follow up on Kent's thorough description, I wanted to add that FL has an excellent way of keeping users on their toes with regard to what is allowed in the world of PostScript Type 1 fonts:

FL doesn't let you form a curve by anything other than two points with control handles. In Fontographer, you're allowed to create a curve that has a BCP handle on one end, and an "empty" point on the other end. But this can produce errors, since it is effectively creating a point-on-top-of-point situation. FL shows you that this is happening by immediately introducing a complimentary BCP handle when you create a curved segment. It invites you to define the curve properly.

FL also makes you aware of the nature of Type 1 curves, by making the "closepath" and start/end points a tangible part of the path. This can be disorienting at first, and seem like a hassle, but it reveals the nature of the curves and allows greater control.

Lastly, if you turn on the "connection type" layer as Kent suggests, FL does another neat thing: when two consecutive BCP handles cross each other's paths, the connection type indicator flips to the opposite side of the point, notifying you that the curve is not constructed as well as it could be.

Lastly lastly, setting the preferences to show points in color is another handy visual cue.

26 May 2003 — 1:13am

Thank you Kent (and Alan) for the thorough explanation, I finally got it sorted out.

I realise that I will have to learn a whole new concept on how to work on my faces...sigh.

Or hoping for a more Fog-like interface in the upcoming versions. I guess it will have to be a gradual transition

1 Jun 2003 — 4:07pm

> In Fontographer, you're allowed to create a curve that has a BCP handle on one end, and an "empty" point on the other end.

And this is "illegal"? Are you sure?

What a bummer. I use that structure all the time, mostly because it's much more elegant: less redundant data -> more control.

On the other hand, I have noticed that strange things happen when such structures are output as a TT font from Fog, for some reason.

hhp

1 Jun 2003 — 5:47pm

Yes, Hrant. To the best of my knowledge, that is considered a Type 1 no-no. It's my understanding that BCPs are considered points, along with vertices. When you create a one-sided curve, you are invisibly creating a BCP on the opposite end of the curve. That invisible BCP (invisible in Fog, at least) is located directly on top of the vertex, so then you have a point-on-point situation. Whether or not this is as likely to cause spiking as two vertices on top of each other, I'm not sure. But it's worth staying away from it (yeah, it's annoying, I agree).

Alan

2 Jun 2003 — 7:17am

Alan, could you post an illustration? I'm having trouble visualizing the situation you describe.

2 Jun 2003 — 8:25am

Alan, Hrant --

I'm not a real Postscript jockey, but to the best of my

understanding I'm not so sure that the one-bcp-handled

curve is necessarily "illegal." The thing is that the

various Postscript

curvetocommands require aset number of arguments, based on the assumption of

two handles and endpoints (actually, the first point is a

given, so generally only six arguments are required.

You can reference the T1 Font Format, Ch. 6, pg 52.)

The thing about FL is that it constructs curves with the

same assumption. But if you create a single-handled

curve in FOG, all that means is that the generated PS

instruction will contain a few arguments whose values

are zero. There's no restriction or caution about these

arguments being non-zero, as far as I can tell.

I think that since these arguments only seem to be

calculation values, this construction wouldn't constitute

any point-on-point sort of violation. But who knows

what happens when Hrant tries to convert to TT.

But Hrant, you don't gain any worthwhile savings in

terms of data points in the actual PS-generated font.

Maybe a digit here or there, but who's counting? Again,

I don't know about TT.

-- K.

2 Jun 2003 — 8:30am

> you don't gain any worthwhile savings

I didn't mean in the actual font data, but in the user's head: when you're making/adjusting a curve, there's less to handle (at least up to a point).

hhp

2 Jun 2003 — 1:03pm

Mark - I've attached a series of images demonstrating the issue with the BCPs. The first image is how you might construct a curve in Fog (the point with the red circle is "empty"). The second image is how this exact outline opens in FL 4.5. The yellow dot you see in the middle of that point is a BCP that is lying directly on top of its vertex. (This is how FL translates the "empty" point when the other side has a BCP.) The third image is ideally how it should be constructed.

However, if what Kent says is correct, then this is all a moot point. But this is just how I've learned it.

Alan

2 Jun 2003 — 1:59pm

Even if it's actually legal, I guess it's still probably better to avoid "empty" curve-recieving points, at least in the final result. Hmmm, Python script, anyone?

A similar thing (legal but ill-advised) is to leave off explicit inflection points (like in the spines of an "s"), although this is actually commonly done by some otherwise fine designers (if rarely in very obvious spots such as the "s" spines). One good reason to define all your inflection points explicitly is TT output/conversion - it consistently blows up, at least in Fog. But I think there are other reasons too. Fortunately, you can easily spot a missing inflection point: the BCPs will be on opposite sides of the curve.

hhp

2 Jun 2003 — 2:38pm

> Fortunately, you can easily spot a missing inflection point: the BCPs will be on opposite sides of the curve.

FL 4.5 used to be able to point them out with the FontAudit layer turned on. But it doesn't work for me any more. Any idea why? (It also won't let me turn *off* checking for semi-horizontal and vertical vectors, even though it's unchecked in the prefs.)

Alan

2 Jun 2003 — 4:38pm

Alan --

I've been noticing the exact same problem with font

audit. I appreciate the feature, but I wish turning off

the semi-horizontal and semi-vertical vector alert really

worked. Very annoying.

From your diagram above, the Postscript instruction for

the first would end up something like

0 0 -66 -81 -103 0 rrcurveto*(Note: I'm assuming this is the bottom curve of a

counter and thus the direction is clockwise. I don't

know your actual coordinates, so this is just an

approximation based on the pixel dimensions of your

screenshot.)

The instruction for the second would be more like

-33 -37 -60 -44 -76 0 rrcurvetoI don't really follow the *math* for applying the Bezier

equation, so I don't know if those initial zeros in the

first instruction would pose any potential weirdness.

I do know that trying to geometrically construct a

single-handled bezier is a little odd.

For whatever it's worth.

-- K.

* I suppose, technically, this first instruction could even

be written as

0 -66 -81 -103 vhcurveto, but I betthat would really lead to interpretive weirdness.

2 Jun 2003 — 8:08pm

Even if it's actually legal, I guess it's still probably better to avoid "empty" curve-recieving points, at least in the final result.Not least because this is illegal in a TrueType font, so if your outline is going to be the source for any TT format conversion such constructions should be avoided. The MS Font Validator will report such constructions as outline errors.

3 Jun 2003 — 2:44am

FontLab will convert "single-handed" cubic curve into correct TT curve using the alternative curve conversion algorithm. There was a problem with version 4.0.x and maybe early releases of the 4.5, but now it works fine.

There is no trouble to render single-handed curve to series of short straight lines (as most rasterizes do before filling the outline), so I don't think PostScript or ATM will have any problems rendering these curves.

Theoretically single-handed curves may cause a problem during conversion to the quadratics when this case is not separately handled, which means that I'd recommend to avoid this type of curves where possible.

I think some algorithm may be developed which will convert single-handed curves to normal ones using some form of approximation. It might be a good example of nice Python programming in FontLab :-)

3 Jun 2003 — 7:57am

> I think some algorithm may be developed which will convert single-handed curves to normal ones

But above that you wrote: "FontLab will convert 'single-handed' cubic curve into correct TT curve" so don't you have the algorithm already?

BTW, a possibly related question:

I'm curious, where did you get the factor of 0.55197 when making a "perfect" circle?

hhp

3 Jun 2003 — 9:29am

>But above that you wrote: "FontLab will convert 'single-handed' cubic curve into correct TT curve" so don't you have the algorithm already?

Well, you can convert single-handed curve to quadratic curve and back, but as a result you will get 2 cubic curves. I mean that I can imagine algorithm which will convert single-handed curve to one "normal" curve. Alan Dague-Greene provided good example of what I mean.

>I'm curious, where did you get the factor of 0.55197 when making a "perfect" circle?

Did we publish this number somewhere or you just draw a very big circle in FL? :-)

Actually I don't remember how it was calcualted in the early days of FL, but now I would do it this way (pardon my math): measure a distance (along x or y direction) from the point located at 45 degrees on a curve and a midlle point of the one-quarter curve. On a curve it is: R * (4 + 3 * X) / 8 [where X is a value we want to find], on a circle: R / sqrt(2).

Finally our X is [in C math notation]: (8 / sqrt(2) - 4) / 3

Precise value is: 0.55228474983079339840225, which is quite close to the value we use in FL (and which history I don't remember).

3 Jun 2003 — 9:36am

> 0.55197

I saw it in some Python scripts that come with FL.

> now I would do it this way ....

Nice.

hhp

3 Jun 2003 — 1:41pm

Hmmm, I really want to follow this bit, but I'm not sure

what factor (= 0.55197) you're referring to, Hrant. So I

don't quite follow Yuri's explanation. Could you back up

a step and let me in on what you're calculating here?

Thanks.

-- K.

3 Jun 2003 — 1:52pm

There is no way to draw a precise circle with the cubic Bezier curve, but it is possible to approximate it. You can draw a 1/4 of a circle (90 degrees) with a single curve with a minimal error: to do that you need to set a length of each BCP to that magical factor multiplied to circle radius. As an experiment you can draw a circle in FL (it will produce 4 curves) and measure the length of each curve's BCP. Then take a calculator and divide it to half of the curve's diameter.

Btw, it looks that calcualtion in my previous message may not give the best approximation. It will place the middle point of the curve exactly on the circle, but total approximation error may not be minimal. To calculate the ideal "factor" you need to render a curve and then approximate it with the curve minimizing the

totalerror. As I understand it is how we got the original value.3 Jun 2003 — 1:53pm

Well, it's probably not really related to the main issue. But here's an explanation: if you draw a "perfect" circle (using the application's tool, or maybe a physical one and then trace it), and you measure the length of the BCP arms in each quadrant, they are about 0.552 of the whole length. This is the value required in cubic bezier math to get a "perfect" circle. BTW, "perfect" is in quotes because you really can't represent a true circle in beziers (of any order).

The way this

mightbe related to the main issue is this: if you were to convert a one-sided curve to a near-equivalent two-sided one, some sort of preset factor values might be the trick.hhp

3 Jun 2003 — 4:42pm

Okay, thanks; I thought that might be what you guys were talking about.

(I still don't quite understand how you derived your formula, but that's okay.)

-- K.

13 Sep 2003 — 6:10pm

Hi,

I know that this is an old, dead thread, but I have an observation about tangent curves.

As far as I know, FreeHand and Fontographer (both developed by Alstys) were the only PostScript drawing programs that have ever supported tangent curves