Be Newsletter
Issue 76, June 4, 1997
Table of Contents
BE EVENTS: Be Demo Tour in Los Angeles, California
June 14, 1997, Los Angeles, California
BeOS Demo at "Digital Experience."
When: June 14 from noon to 6:00pm
Where:
UCLA School of Theater, Film & Television
405 Hilgard Avenue
Melnitz Hall (the main Film/TV dept. building) in
Soundstage #2
Los Angeles, CA 90095
To get more information, please check out:
http://pixels.filmtv.ucla.edu/
BE ENGINEERING INSIGHTS: The new font engine, PART 1:
Drawing characters in the correct position
By Pierre Raynaud-Richard
Believe me, I really wanted to write an interesting article
about a surprising subject but...this is just YAAAAA (yet
another article about Advanced Access Preview Release).
And if you want my opinion, we will probably continue like
this for a few months. :-)
If you've seen the huge list of new features, you've
probably noticed that the font engine has changed. Improving
the appearance of small point size TrueType fonts was our
main goal. The extensive use of anti-aliasing is certainly
the most immediately noticeable part of these changes, but
perhaps not the most effective. Although smoothing the shape
of bitmaps on the screen is clearly a way to make them look
better, optimizing the relative position of each pair of
contiguous characters can also greatly improve the overall
appearance of a string. By extending our "spacing
model" we've introduced some subtleties that you must be
aware of, at least if you want to use its full power
properly.
First, let's run down the list of the goals of the new font
engine:
- It should be as WYSIWYG as possible
- Fonts should scale smoothly
- The spacing mode must be adaptable to get optimal results
for different needs
- It must support Unicode UTF-8 (the only encoding scheme
used throughout the system), and standard 8-bit character
sets like ISO-Latin (which can only be used in a
BView )
Consequence #1: External bitmap fonts are no longer
supported. They're replaced by a private format that's
anti-aliased and that can be hand-tuned. We'll be
distributing a set of utilities (with sources) that will...
- Let you hand-tune specific point sizes of an existing
scalable TrueType font.
- Convert an existing bitmap font into the Be format as
long as you ALSO have the corresponding scalable font for
those bitmaps.
(And just to head off confusion: If ALL you have is a bitmap
font -- in other words, no corresponding scalable version --
then you're out of luck. Back to our story...)
With these tools, you'll be able to get a very nice looking
bitmap font at any size. For example, we will use these
tools to integrate bitmaps for small size TrueType Kanji.
Consequence #2: All metric processing is now done in
floating-point (with the exception of bitmap glyphs -- we
don't support sub-pixel positioning in the current engine).
Floating-point metrics let us define a better character
spacing model. So let me now introduce to you our four
spacing modes:
B_CHAR_SPACING ,
B_STRING_SPACING ,
B_BITMAP_SPACING , and
B_FIXED_SPACING .
Let's go through a quick overview of what these different
modes are supposed to do.
B_CHAR_SPACING Spacing Mode:
This is the old spacing mode used in DR8. It's clearly a
good way to get WYSIWYG printing, it scales smoothly, and
handles rotated and sheared fonts very well. Plus, it's
really easy to use...but it has one big fault: It can't
improve the readability of small point sizes. So, for
drawing a lot of small text, B_CHAR_SPACING is a very bad
choice.
B_STRING_SPACING Spacing Mode:
This mode is also WYSIWYG and it scales smoothly, but it
doesn't handle rotated or sheared fonts. But it does have
one important advantage: It uses a dynamic kerning algorithm
to improve the individual position of each character inside
a string without modifying the string's total width.
This feature makes B_STRING_SPACING the most difficult of
the four modes for the programmer to manage.
B_BITMAP_MODE Spacing Mode:
This mode doesn't care that much about being WYSIWYG, so if
you print, widths and positions can change slightly. Also,
it doesn't scale very smoothly. Its main features are that
it's easy to use, and it gives a very good result when you
draw a lot of small text on the screen.
B_FIXED_SPACING Spacing Mode:
This mode is designed to improve the appearance of
non-proportional fonts by making all glyphs (of such fonts)
share the same width (called "escapement"). This common
escapement is an integer, so you can get perfectly regular
columns of text.
Choosing a Mode
Here's a fast summary of which mode you should use, based on
your needs:
Details
For those who are still not clear about which mode they
should use, or who would like a fuller description of the
consequences of using one mode versus another, it's time to
describe the subtleties of each mode in much more detail.
In the following material, each mode is described thus:
- Metrics: A technical definition of how the mode handles
metric processing.
- Breaking string: The consequences of redrawing only part
of a string.
- On the screen: A description of what quality you can
expect at small point sizes on the screen.
- WYSIWYG Conformance: A description of the conformance
between width and position on the screen and width and
position when printing.
- Fast StringWidth(): A description of how to compute the
width of a string by hand. This problem deserves a bit
more of explanation; see the addendum at the end of this
article for the full story.
- Fast Escapements: This section discusses ways of
optimizing the computation of individual character
escapements (so you can handle caret position and text
selection properly). This usually isn't a performance
problem, but it can't hurt to speed it up.
B_CHAR_SPACING Mode Details:
Metrics:
Respects the exact printing metric for each character. This
mode will put characters on the screen at their most
accurate printing approximation (exactly what DR8 was doing
with scalable fonts). Nothing is done to improve the
readability of text on screen, so it can support all
standard geometric transformation without problem (smooth
scaling, rotated and sheared text).
Breaking string:
< DrawString("microsoft") >
< DrawString("micro") DrawString("soft") >
< DrawString("mic") DrawString("ros") DrawString("oft") >
These three will all give exactly the same result.
On the screen:
Looks bad. Characters can collide at small point sizes.
Spacing between characters is poor.
WYSIWYG Conformance:
Good. The left side of each character is at its best
approximated position, but the right limit of a string or a
line can be offset by more than one pixel. This is because a
small "hinted" glyph could be much wider than the real
glyph.
Fast StringWidth():
Simple. Just add all the escapements and multiply by the
size:
StringWidth = (sum of individual escapements) x
(specific point size)
Since the escapements are size-independent, they can be
cached.
Fast Escapements:
Simple. Multiply the escapement by the size:
RealEscapement = (individual escapement) x
(specific point size)
Again, the escapement can be cached.
B_STRING_SPACING Mode Details:
Metrics:
Respects the printing metric for each string. It uses the
printing width to determine the area that can be used to
display glyphs, then it optimizes the position of each
character within this area to get a better spacing and avoid
collisions as much as possible. Consequently, the exact
position of each character is not predictable without the
context of the string that it's contained in. Also, editing
a string affects the position of all its characters -- the
characters wiggle around as the user types. The problem is
particularly visible if you draw the full line of text with
one DrawString() .
Breaking string:
< DrawString("microsoft") >
< DrawString("micro") DrawString("soft") >
< DrawString("mic") DrawString("ros") DrawString("oft") >
These will all give the same total width, but individual
characters can occupy slightly different positions in each
case. The first case will have the best spacing overall.
On the screen:
Medium/Good. Characters can touch one another, collisions
are unlikely. Spacing between characters is much more
regular.
WYSIWYG Conformance:
Good. The left and right sides of each string are supposed
to be at their best approximation of their printing value.
Individual character position inside the string can be
slightly different. The difference can be really significant
if you draw a full line at a time.
Fast StringWidth():
Simple (sort of). You have to get the individual escapements
as they would be in B_CHAR_SPACING mode, add them up, and
multiply by the size:
StringWidth =
(sum of individual escapement in B_CHAR_SPACING mode) x
(specific point size)
You can cache the string's total escapement.
Fast Escapements:
Not so great. You have to call GetEscapements() for each
size, for each specific string. Nothing can be cached.
B_BITMAP_SPACING Mode Details:
Metrics:
Calculates a specific bitmap escapement for each character,
for each size, depending on its bitmap appearance (NOT on
its printing metric).
Breaking string:
< DrawString("microsoft") >
< DrawString("micro") DrawString("soft") >
< DrawString("mic") DrawString("ros") DrawString("oft") >
These will all give exactly the same result.
On the screen:
Very good. Characters should almost never touch.
Spacing is quite regular.
WYSIWYG Conformance:
Very bad. At small sizes, a string on the screen will be
noticeably wider (a few percents) than when printed. The
opposite is possible, but unlikely.
Fast StringWidth():
Not good. Escapements are per character, per size:
StringWidth =
(sum of individual escapements for one specific
point size) x
(that specific point size)
Note: The measurement of the escapement for a particular
character is given in point size-independent units (this
makes scaling easier). This is why, in the formula shown
here, you have to get the escapement measurement based on
the point size and then multiply that measurement by the
point size.
Fast Escapements:
Not good.
RealEscapement =
(individual escapement for one specific point size) x
(that specific point size).
B_FIXED_SPACING Mode Details:
Metrics:
Rounds the fixed width of each character to an integral
value. Should be used with non-proportional fonts only.
Breaking string:
< DrawString("microsoft") >
< DrawString("micro") DrawString("soft") >
< DrawString("mic") DrawString("ros") DrawString("oft") >
These will all give exactly the same result.
On the screen:
Good. You get the same width for each column. That doesn't
protect you completely against glyphs touching one another,
but such problems should be limited.
WYSIWYG Conformance:
Horrible. You will almost never get the same width. You can
have a typical error up to plus-or-minus 5%, or even 10% at
very small sizes.
Fast StringWidth():
Ideal. You need to cache only one escapement per size.
StringWidth = (count of character) x
(escapement for one specific size) x
(that specific point size).
Fast Escapements:
Ideal. One escapement per size.
RealEscapement = (escapement for one specific size) x
(that specific point size).
Addendum: More on StringWidth()
StringWidth() is a synchronous client/server call.
Consequently, it's quite slow -- it's slowness is one of the
most serious performance problems in the graphics system.
Currently, there are two ways to get around the problem:
- You can reduce the client/server overhead by bundling up
a bunch of strings in the
GetStringWidths() call. The
advantage of this method is that it's easy to use and
(pay attention) IT WILL REMAIN COMPATIBLE WITH FUTURE
ADVANCED SPACING MODES (such as real kerning). However,
this solution may not be as fast as you need.
- A faster approach is to compute the string width yourself.
They're YOUR strings. That's what the "Fast
StringWidth() "
sections were all about.
Next week, I'll comment on a few other subtleties of the new
font engine, but for now I hope this helps you understand
which spacing mode you should use. If you still have
questions about spacing modes, do not hesitate to email me
at: pierre@be.com.
Sailing to Support Nirvana, PART 1
By Ed Romson
In Be Newsletter #72, I wrote about the kind of support we
were establishing to serve developers and end-users. This
time, I'd like to tackle the question of how to set up
support within an organization. Let me start by clarifying
terms; by using the term "support," I am referring to the
technical support of customers. There are other issues
involved in Customer Service; publishing your product, order
taking, money collection and distribution, to name a few.
While those tasks are within the scope of our Customer
Support department here at Be, they are not going to be
covered here.
Many developers "fall" into technical support, that is, they
publish a product -- be it freeware, shareware or a
commercial application -- then sit back and hope that the
phone does not ring. It will, I promise you. Even if you
include a disclaimer in your shareware product that is in 72
point type and says "Technical support is not included with
this product," you'll get a ton of email, and even phone
calls (it is uncanny how some people are able find you). So,
let's start with this premise: Every product needs support.
The level of staffing, expense and effort spent on technical
support varies depending upon the level of sophistication of
both the product and the company that produced it. You can
compare this issue to the concept of sailing. Sailboats come
in various sizes and have varied crew requirements. You can
sail a small day-sailer with one person, zipping around the
Bay all day, having a great time and getting one heck of a
sunburn. You can sail a 40 foot sloop with two or three
people, spend days on board, and go long distances:
Trans-Atlantic or, like Erich -- our Grand Vizier of Code --
out to Hawaii. It costs more, but you experience different
thrills and challenges (notice I did not say "you have more
fun"). A large three masted barkentine, the workhorse of
days past, requires a large crew and a major investment, but
to some people's way of thinking it is the most comfortable
way to travel and will allow the most work to be done.
Are you with a day-sailer kind of company? Most developers
start here. One or two people, probably the same people who
wrote the code, answer inquiries about the product and
writing bug-fixes in between trying to get Version 2.0 out
the door. You can survive like this for awhile, but
eventually you must go with your core strengths. This is a
theme I will return to often. Most programmers are good
at...programming (duh!). Unless you really want to get out
from behind the monitor and deal with <gasp> people, you'll
need to rely on support professionals to help customers.
This brings you up to the 40 foot sloop range. You are still
the skipper; your hand is firmly on the tiller. You may even
haul a line now and then, that is, answer a particularly
thorny question. You leave the day-to-day sailing to your
crew, however. They become very good at answering questions
and even set up a database of frequently asked questions,
posting it to your web site. They become the subject matter
experts, second in knowledge only to the people who actually
write the central code.
Let's look at some of the economics of these support people
and how you might go about deciding how big a crew to press.
To start, you have to agree on a "fully loaded" price for
each person. By fully loaded I'm referring to salary, fringe
benefits, office space, equipment, phones, Internet access
and other miscellaneous costs. I'll take a stab at an
estimate based on my experience (admittedly with a large
hardware and software manufacturer, which shall remain
nameless). Let's use a round figure of US$100,000 per
engineer (don't choke, just adjust the figure to match your
experience and rerun the numbers).
Most good support people can handle between 25 to 40
contacts per day. Lots of factors go into this estimate; the
complexity of the product, sophistication of the customer,
tools that the support person is using and method of contact
(email, phone, fax). I've managed organizations that were
able to average 40 contacts per day. However, we hit that
number after lots of work and with a staff of 29 that had
been working together for over a year and had a constant
flow of similar questions to answer. To be fair, and set
proper expectations, I'll use a figure of 30 contacts per
day per person.
It is my opinion that, in order to provide for contingencies
and for the mental health of your support people, a minimum
staff of 2 is required. Otherwise, vacation, sick time, jury
duty, you name it, hits and one of your people will be off
listening to the defense attorney vehemently state that his
client could not have been anywhere near the scene of the
crime, while your support questions keep rolling in.
These "contingencies" bring up another issue, one that in
Call Center parlance is known as an efficiency, staffing or
load factor. It is a factor that modifies the equation to
provide for the time that the support people are off for
those events mentioned above. I can't tell you the amount of
time Call Center managers spend arguing about this. Suffice
it to say that, the "Theory According to Romson" is that one
must allow for a 20% staffing factor (your mileage may
vary). This factor will affect the number of calls per year
each person will be able to take.
**Chart 1**
Personnel cost (per person)...................$100,000
Number of contacts handled/day/person...............30
Number of people.....................................2
Efficiency factor..................................0.8
Number of work days................................260
Calls handled/person/year.........................6240
Cost per contact................................$16.03
You'll notice that you are able to calculate a rough cost
per contact from this model. Keep that number in mind, you
can compare it to what is available if you decide to hire a
crew from the outside (also known as outsourcing).
Forecasting the number of contacts you will be offered is
like forecasting the weather. Worse, actually, since it
depends on a sales forecast rather than a butterfly flapping
its wings in Brazil. Given this challenge, support managers
use a number of formulas to come up with a forecast. The
factors that figure into this formula are much the same as
mentioned above regarding the type of product, customer, and
contact methods you encounter. Many software companies use
between 35% and 50% for a contact rate. That means for every
100 units sold, you'll get 35 questions. If you include
hardware in that equation (like that unnamed "fruit"
company) the factor could go as high as 150%. Add novice
users, and it soars to 300%. Another reason your call rate
could be as high as 300% is if your product is so complex
that the user must call for installation help. Some LAN
products come to mind.
Experience in taking calls and email will give you a real
contact rate, but the most common dilemma encountered when
setting up support is that you must start with a guess. Make
an educated guess and verify it with experience, but have a
contingency plan, in case the contacts go through the roof.
For our hypothetical voyage upon the Sea of Support, I'll
use a midrange contact rate of 50%.
Given that rate and the calculations we went through above,
it appears that your 2 Support Engineers will be able to
handle the results of the sale of 25,000 copies of your
software (two people taking 6,420 calls per year, each call
being the result of the sale of 2 copies of the product =
24,960 units). Not enough to match your sales forecast?
Congratulations! The formula can extend to millions of
units; just add people.
Aye, but there's the rub. Do you want to invest in
additional high priced support personnel in-house or should
you look to an outside company to do the first-line support
for you? You are quickly moving up to a much larger sailboat
and you'll need to decide if you want to sail her yourself
or let an experienced captain and crew take you into the
future.
That is a discussion for next time. Come on back to the
Be Newsletter next week, and we'll get into outsourcing,
loss of quality control, vendor management, and more sailing
metaphors.
News from the Front
By William Adams
So, what multimedia OS would be complete without pretty good
support for FireWire? If you were at the Be Developer's
Conference and attended the session covering video, you saw
a lot of slides about where to get info on FireWire and a
number of the other technologies that we will be supporting
in the future. One piece of the demo that we did then was
released last week. The VideoMania application didn't do any
FireWire, but it did the Picture-In-Picture thing. Well, how
about camera control, VCR control, and the rest.
What are we missing? Well, FireWire is a relatively new
technology, and there aren't a lot of APIs in OSes to
support it yet. We do have a working framework for it
though.
ftp://ftp.be.com/pub/samples/drivers/obsolete/fire.tgz
This archive contains a driver for the Adaptec FireWire
board, as well as a whole lot of stuff to support the AV/C
command set. We want your input as to how we can make it
better. We want to provide a number of classes that make AV
support relatively trivial in the BeOS. We have the Midi
Kit, the Media Kit, and now the AV Kit in the makings. This
is your chance to get in on it while it's still in the oven.
What will be added over time is support for the various
subtypes available in FireWire, that means cameras, TV
tuners, and monitors. At least according to the spec. Right
now, there is only support for camera and VCR subtypes.
If that's not enough, I hear Geoff Woodcock has been working
on a ISO9660 file system extension. I don't want to steal
his thunder, because it makes for a good tutorial on writing
file system extensions. I will say that it is quite a relief
to be able to mount standard CD and get at my shovelware
easily without having to go through a floppy or network
transfer phase. Keep a lookout in the
ftp://ftp.be.com/pub/samples directory for these goodies.
Well, summer is rapidly upon us here in California. 102
degrees one day, rain the next, followed by fog. Ahhh, what
a life. The DR9 samples are flowing, apps are coming in, and
the world is a wonderful place. If you don't believe it,
then you're not programming on the BeOS. Have you bought
your Hauppauge tuner card yet? If you haven't, you're
missing out on all the fun.
Nice Product, But...
By Jean-Louis Gassée
The dreaded sentence. We heard it often, in various guises.
In the VC trade, the kind condemnation is worded as
"interesting." The "but" is a way to introduce the objection
that the better product won't win. Look at Betamax, look at
the Mac. I won't get into the Macintosh story for today, but
let's take a look at the Betamax story. There is more than
meets the lore.
Yes, when comparing the polar display of VHS and Betamax
video output on an oscilloscope, the Beta standard stood as
clearly superior. And Sony sold much Betacam equipment to
the pros. That didn't happen with the consumer version,
Betamax. Why? Was it a case of the mighty, foxy Matsushita
steamrollering poor little Sony?
Consumer Reports gave us the answer a few years back. Yes,
Betamax looked better on the scope, but... not on the TV.
Using a double blind experiment (where neither the person
running the test nor the subject know which parameters are
used) with ordinary program material, a panel of viewers
could not distinguish between a VHS and a Betamax recording
displayed on a run-of-the-mill TV set. For the consumer,
Betamax didn't yield better viewing than VHS.
Things got worse for Betamax: Consumer Reports then looked
at the repair history of VCRs. All the Matsushita brands
(National, Panasonic, Technics...) stood at the top of the
quality scale, and Sony at the bottom. (At the risk of
angering Sony fans, Sony's conversion to VHS hasn't improved
their standing, they still rank at the bottom of quality
surveys.) QED: the customer is smart. Or to quote a past
Vice-President: "The market's invisible hand has spoken."
Betamax lost fairly.
Now, the above doesn't imply we'll succeed because we have a
superior product. We're working on it, we hope to be on our
way, but we haven't proven that yet. And, as the "product"
word implies, there are many factors involved. The meaning
of "better" is one of them. In a metaphoric view, an
operating system is a musical instrument. As such, "better"
has to be qualified: for whom, for what. As musical
instruments go, not every piece of music written for one
instrument can be felicitously rendered on any other one. An
organ toccata won't play on a flute; string glissandi won't
render on a piano. Our goal always has been to provide an
opportunity for composers, programmers, to write music that
couldn't be easily written elsewhere, or that wouldn't play
as well elsewhere. In addition, Be music can be marketed,
delivered and updated inexpensively on the Web, thus
lowering the cost of entering the market. Basically, all you
need is sweat equity -- I was going to write: "a better
product."
Another way to look at "better" is this: think of three
categories. Better than yesterday, impossible yesterday and
unthinkable yesterday. Place them on a horizontal axis from
left to right. In general, the profit opportunity improves
as one moves towards the right. On the left, marginal
improvements, in the middle, removal of painful obstacles,
on the right, a brain-teaser. Note I wrote "unthinkable
yesterday" in order to afford us the benefit of hindsight,
of retroactive recognition of the inconceivable. Examples
abound: four years ago, who thought of the Web? It has
quickly shifted left at least one column. I'd say two if
there was a T3 line into every home; that's almost
unthinkable.
Back to the original challenge, if we are perceived as
merely offering marginal improvements upon existing OS
platforms, then the "nice product, but" sentence is
justified. The competition will easily catch up with us and
we'll fail. Fortunately, in our chosen field of media
applications, we've been able to locate much of our work in
the "impossible before" (at the PC level). As for the
"unthinkable," we'll have to wait until it becomes
retroactively obvious.
BeDevTalk Summary
BeDevTalk is an unmoderated discussion group that's a forum
for the exchange of technical information, suggestions,
questions, mythology, and suspicions. In this column, we
summarize some of the active threads, listed by their
subject lines as they appear, verbatim, in the group.
To subscribe to BeDevTalk, visit the mailing list page on
our Web site: http://www.be.com/aboutbe/mailinglists.html.
- ----NEW---------------------------
Subject: Get Working Directory
Where should application specific data (settings) be saved?
How do you find these files? As many users pointed out, the
new FindDirectory mechanism (unimplemented in AA:PR) and the
file system layout map will help answer these questions.
Most of them, anyway: Chris Hanson suggested that a
settings API would be even better. Rather than making an
app find the directory in which it would then save its
settings, why not just provide a function that does all that
for you: You pass in the settings data, it finds the correct
place and saves them.
To some, this solution sounds a bit too much like Windows'
registry. The registry concept may be sound, but, as Dave
Haynie put it:
"It's...horrible when you're running the same installation
over a network, or on the same machine under different OSes.
The Windows registry concept, if not implementation, isn't
that bad if you're a single system unnetworked home user,
but it fails in pretty much every other case."
- ----NEW---------------------------
Subject: How to reuse my DesktopImage ?
A number of folks having fun with the new Tracker. Hints,
tips, and requests regarding the Tracker's desktop window,
displaying background images in windows, and so on.
- ----NEW---------------------------
Subject: Generic Printer Driver
Is it possible to provide a generic printer driver (emphasis
on "generic"). Given the number of different printers that
are commonly available (emphasis on "common"), most folks
voted for "no." It's better, at least for starters, to
provide one or two specific drivers for a couple of "de
facto standard" printers than it is to try to generalize the
problem and solve it in the printer architecture.
- ----NEW---------------------------
Subject: Replicants
Do Replicants work if the "parent" app is moved? Not now,
but they will, someday. This led to a larger discussion --
one we're all familiar with by now -- about installation,
registration, and file dependencies. Many folks want a way
to mark dependent files such that when a given file is
deleted or moved, the dependent files are acted upon
appropriately. Again, the forthcoming FindDirectory was
invoked as a feature worth waiting for. And, again, a
"Preferences Manager"-style app (or, at least, API) was
requested.
|