Be Newsletter
Issue 77, June 11, 1997
Table of Contents
- BE EVENTS: European Events in Paris, London, Frankfurt, Be Demo Tour in Los Angeles, California
- BE ENGINEERING INSIGHTS: The new font engine, PART 2: Porting font code from DR8 to the Preview Release, By Pierre Raynaud-Richard
- Sailing to Support Nirvana, PART 2, By Ed Romson
- News From the Front, By William Adams
- Modem Wars, By Jean-Louis Gassée
BE EVENTS: Be Demo Tour in Los Angeles, California
June 13, 1997, Paris, France.
GeekTea at Be Europe headquarters in Paris.
To encourage contacts between developers, we organize
regular meetings at Be Europe. All Be developers are
invited to come with their friends. The goal is to meet
other Geeks, exchange tricks and codes, view/demo the
latest versions of programs and maybe also, the latest
products from Be...
To get more information, please check out:
http://www.beeurope.com/index.html or
http://www.beeurope.com/Developers/index.html#GeekTea
European Be Developers' Conferences in London and Frankfurt:
- Wednesday, June 25, 1997
Be Developers' Conference in London, UK
- Sunday, June 28, 1997
Be Developers' Conference in Frankfurt/Main, Germany
To get more information, please check out:
http://www.beeurope.com/Developers/index.html#Meetings
June 13, 1997, Los Angeles, California
BeOS Demo at "Digital Experience."
When: Friday June 13 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 2:
Porting font code from DR8 to the Preview Release
By Pierre Raynaud-Richard
(...The stranger stood up, but they still couldn't see his
face. The leader of the security team looked one last time
at his boss before taking action. But his gaze was fixed on
the stranger, captivated. No instruction. So he barked the
order he had been holding back...
"FIR--"
A thin beam of energy shot up from the stranger's belt,
widening with distance to a tenth of an inch. It sliced
diagonally through the neck of the security leader. A final
groan burbbled from his gaping throat, then his body
collapsed slowly; the head, neatly detached, rolled on the
ground...)
Perhaps the link to "Porting Font Code from DR8 to the
Preview Release" is not clear. But at least it's not just
another boring introduction. So first, let's go through a
quick overview of the main API changes:
- The font interface has been extracted from
BView , and put
in its own BFont class. The class gives you an easy way to
keep track of different font settings, and lets you ask
for metric information without having to create a BView .
This model is much more efficient for serious text
drawing/editing, at the price of being a minor annoyance
for people who just want to do basic stuff.
- The single font name is replaced by a name pair: The
family name (Courier, Times, etc.) and the style name
(plain, bold, italic, etc.).
- Three default, global
BFont objects have been defined:
be_plain_font , be_bold_font and be_fixed_font . These
abstract the most common "styles" of font used inside a
standard application. The definitions of these fonts are
set by the user, through the Font Preferences app. Apps
should use the default fonts rather than hard coded font
names (as we had been doing in DR8 with Erich, Emily and
Kate). The values of the default fonts are set when an app
is launched; they won't change (for that app) thereafter.
To pick up new settings in an app, the user has to quit
and restart the app.
Let's give more details about BView and BFont .
WHAT HAPPENED TO BVIEW
What happened to BView is quite simple: Almost all the font
related functions have been moved (and in some cases
modified or enhanced) to the BFont class. Here are the
functions that have moved:
BView::GetCharEscapement(...)
BView::GetCharEdges(...)
BView::GetFontInfo(...)
BView::SetFontName(...)
BView::SetFontRotation(...)
BView::SetFontShear(...)
BView::SetSymbolSet(...)
A logical exception, BView->DrawChar(...) is unchanged, and
BView->DrawString(...) is just slightly enhanced with the
introduction of escapements_delta . Those optional parameters
define an additional escapement, different for space
characters and non-space characters, allowing easy
justification of a full line of text.
We were reluctant to force everyone to use the BFont API for
every single font-related operation, so we decided to keep a
subset of the BFont API in BView . Specifically,
StringWidth() and GetFontHeight() are retained so that you
can easily get the dimensions of the rect used by a string.
Additionally, SetFontSize() was so commonly used that we
decided to keep it in BView as well.
All other font setting changes must be done by modifying the
BView 's BFont object; you use GetFont() and SetFont() to
access and set the object.
BFONT PROPERTIES
Here are the standard properties of the new BFont API:
Family and Style names: you can get the complete list
from global functions:
count_font_families()
get_font_family(index, &font_family)
count_font_styles(font_family)
get_font_style(font_family, index, &font_style).
The list of families is cached for each application after
the first use. As the user is allow to add and remove fonts
files at any time, this list could change at any time. But,
for technical reasons -- and because the user really
shouldn't be changing the font all that much anyway -- this
list is not updated automatically in the Preview Release.
You can force a "font update" by calling:
bool update_font_families(bool check_only)
If check_only is TRUE, the function lets you know (through
the return value) if the global font list has changed, but
it doesn't actually update your app's version of the list.
If check_only is FALSE, it will go ahead and update your
app, if necessary. Updating can take a long time, and it
blocks the calling thread, so the "check only" option gives
your app a chance to put up a warning to the user, or spawn
a thread to do the updating in the background.
The list of styles can be different (and usually is) for
each different family. A lot of different names exist for
something representing the same "style." For example, plain
is often called "roman" or "regular." Because of this,
family and style should always be set at the same time, in
one call:
BFont::SetFamilyAndStyle(const font_family,
const font_style)
Nevertheless, if you just want to change the style of the
current family, you pass NULL as the family. Or if you just
want to select the "standard" style of a font (the plain
equivalent, if available), you pass NULL as the style.
- Size: In points, any positive floating-point value smaller
than 10,000. The global
BFont objects have individual
default sizes.
- Rotation: In degrees, with a default value of 0.
- Shear: In degrees, in the range [45, 135] with a default
value of 90.
- Encoding: This is the character set encoding used to
describe characters when talking with the font engine. The
BeOS should use only
B_UNICODE_UTF8 (the default value)
for now. Other encodings may be supported later.
- Encoding: This is the character set encoding used to
describe characters when talking to the font engine. The
BeOS should use only
B_UNICODE_UTF8 (the default value)
for now. A small set of standard 8 bit encodings are also
supported for compatibility (ISO-8859-1 to 10, and
Macintosh Roman).
- Spacing_mode: This parameter was described in great detail
in the previous newsletter.
- Faces: This parameter is currently reserved for future
extensions, such as underline or strikethrough.
- Flags: This controls the selection of special options. The
only one available for now is
B_DISABLE_ANTI_ALIASING .
Furthermore, anti-aliasing should ONLY be turned off by
the rare application that displays monocolor bitmap fonts
in large point sizes.
When using BView::SetFont() , you can set a subset of these
parameters by using the setting_mask . This gives you two
ways modify a BView 's font setting:
A. GetFont() -> modify the parameter -> SetFont()
B. Set the parameter in a dummy BFont object -> SetFont()
using a setting flag to modify only this parameter
Typically, A is written in 3 lines of code, B in only 2.
PORTING EXAMPLES
That's enough general information for now (you can find more
in the documentation and code examples). Let's take a look
at a few practical cases:
To do: selecting a standard font:
Before: SetFontName("Erich");
Now: SetFont(be_plain_font);
To do: changing the point size:
Before: SetFontSize(12.0);
Now: SetFontSize(12.0);
To do: getting the width of a string:
Before: StringWidth("The string I prefer");
Now: StringWidth("My beloved string");
To do: getting the ascent of the current font:
Before: GetFontInfo(&info); info.ascent;
Now: GetFontHeight(&height); height.ascent;
To do: changing the rotation of the font:
Before: SetFontRotation(110.0);
Now: GetFont(&tmpFont); tmpFont.SetRotation(110.0);
SetFont(&tmpFont);
Or: fooFont.SetRotation(110.0);
SetFont(&fooFont, B_FONT_ROTATION);
To do: saving a font setting:
Before: GetFontInfo(&curInfo);
Now: GetFont(&curFont);
To do: restoring a font setting:
Before: SetFontName(oldInfo.name);
SetFontSize(oldInfo.size);
SetFontRotation(oldInfo.rotation);
SetFontShear(oldInfo.shear);
Now: SetFont(&oldFont);
And you will find much more in future sample code.
DRAWING MODES
The last thing I want to talk about is a small but very
important detail: The first two drawing modes used in the
BView (COPY and OVER ) were equivalent for text in DR8.
That's no longer the case in the Preview Release. And the
bad thing is that an incorrect usage of those modes will
make the anti-aliasing look REALLY BAD. So please, read the
following carefully and update your code if necessary.
BEFORE: Both COPY and OVER were basically doing what the
OVER mode was supposed to do. Their performance was similar,
and many people used one or the other without seeing any
real difference on the screen.
NOW: The mode OVER reads the background before drawing, as
the anti-aliasing is done using alpha blending. But,
depending on the user configuration, the cost of reading
back the frame buffer of the graphic card can be
prohibitive.
This is where the COPY mode shows the power of its
simplified definition: By computing the alpha-blending
between the HighColor of the glyph itself and the LowColor
of the BView (which represents the color of the uniform
background), COPY is much faster than OVER . However, you can
only use COPY on a uniform background, and you ABSOLUTELY
NEED TO HAVE THE LOWCOLOR SET PROPERLY (it's the
responsibility of the programmer).
I hope you understand now why many quick ports from DR8 to
the Preview Release (probably including a few apps of our
own) displayed ugly looking anti-aliased fonts here and
there...
Here's another good reason to use the fast COPY mode as much
as possible: Fonts never erase their background (for the
simple reason that there is no consistent way to define the
limits of the background of a character). Consequently, the
programmer is responsible for erasing the background
properly before calling DrawBitmap .
For example, let's say you just want to change the color of
>>the font; you may be tempted to just redraw the text in the
new color, thinking it will overwrite the previously drawn
text (some Be engineers were doing that). This was true in
both modes (COPY and OVER ) in DR8.
With the Preview Release, it's still true in COPY mode, but
doesn't work anymore in OVER mode: The rasterizer will use
the already anti-aliased background, increasing the amount
of anti-aliasing with each redraw, until it reaches a
saturation point. This doesn't look good at all (the poor
guinea pigs who got the alpha version of Advanced Access
probably remember the ugly text in menubars).
To conclude these two articles on the new font engine, I
would say there are still many areas that could be improved
in terms of both quality and performance. Be assured that
we're thinking about it, but improvements probably won't be
published before the next release. In the meantime, I will
be happy to answer any other questions at: pierre@be.com.
Sailing to Support Nirvana, PART 2
By Ed Romson
Welcome back to our discussion about sailing towards
technical support Nirvana. This week I'll share some
thoughts on outsourcing, and on how to maximize the
satisfaction of your customers while holding down support
costs.
Let's recap the last "Sailing to Support Nirvana" article
before we start. I discussed piloting your own day-sailer
with a limited support staff, and captaining a larger
organization that provided "soup to nuts" support to your
customers. We explored a formula that showed the base cost
of handling contacts and a method of that black magic art,
forecasting contact volume. Let's reproduce here the chart
we used, because the result (cost of each support contact)
will be important to our discussion of outsourcing:
** 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
I'd like to start off with an exploration of the controversy
over whether or not to outsource. Believe me, I have been
all over the map on this one. Five years ago, I was a major
opponent of outsourcing. I felt that we would lose control
over the quality of information provided to our customers. I
mean, who understood our products better than the people who
had supported them for years? How could an outside company
ever gain enough knowledge to effectively support our
beloved products? Over the years, I have changed my position
almost 100 percent. I've seen outsourcing work in the US,
Japan and Europe.
The secret is to realize that outsourcing is not a panacea.
Some (less than successful) companies think that they can
outsource and forget. They outsource and never have to worry
about that work again. After all, isn't that the work which
they are contracting for? Well, yes, however you must keep
management control over the outsource vendor. A strong
vendor manager, someone who knows the support business and
is excellent at managing projects, is essential for the
success of an outsourcing project. The thing you are really
contracting for is the "production line" work of answering
the questions.
Another requirement is that there must be someone inside the
company to handle the calls escalated from the first-line
people. Remember those first two sailors you brought aboard
to help sail your original sloop? Those guys and gals are
now invaluable at teaching your new vendor the ropes, and
they are there to serve as the masters of escalation. This
not only makes effective use of your higher paid resources,
but also allows for job enrichment for those poor swabs who
have been slogging away, answering the first-level
questions.
What is your involvement in all of this? You own the fleet.
You have contracted with a company to provide the sails and
the manpower. You are setting the course and determining the
cargo to carry; that is, what is supported, and how it is
supported. You keep an eye on the fleet, making sure your
customers are satisfied, and your ships don't run aground.
You take soundings with a regular customer survey, and you
make course corrections based on what your customers are
telling you.
You may be asking whether this outsourcing is more expensive
than growing your support capacity in-house. I'll share some
of the pricing I've seen in the recent past. I must admit
that I've changed some of the numbers to protect the guilty,
but the numbers in Chart 2 below reflect bids you might
receive if you were to ask for quotes from some of the
larger outsource vendors:
** Chart 2 **
Sample outsource quote -- 8 minute call (10 x 5 support)
Contacts/ Team Price/ Price/
Day Size Minute Contact
50 3 $1.70 $13.60
100 5 $1.40 $11.20
150 7 $1.30 $10.40
200 8 $1.15 $ 9.20
250 10 $1.10 $ 8.80
300 11 $1.05 $ 8.40
450 14 $0.99 $ 7.92
This chart needs some explanation. The assumptions are
listed at the top, and the chart assumes that the average
telephone call will be 8 minutes in length (a good
assumption for software contacts with reasonably
sophisticated users). It also assumes that you are accepting
contacts from 8am to 6pm (10 hours a day), Monday through
Friday (five days a week).
The "Price per Minute" and "Price per Contact" are figures
that the outsource company gives you to say "this is what it
will cost you." You may remember that I came up with a cost
per contact of $16.03 when I did the calculation for
in-house staff. That makes sense; you are paying those
"fully loaded costs" and you have very little economy of
scale with just a few support people. You also want to pay
more for your internal or "institutional" knowledge keepers.
In this scenario, you are going to use your internal people
as information resources, and as second level support
resources -- natural tasks for higher cost people.
Now, what does all this mean? The decision that needs to be
made regards the point at which it makes sense to outsource,
rather than grow your support resources inside the company.
You will need internal support resources for higher level
support, the "Masters" or "Chiefs" on your boat. The crew
can be pressed from outside and it makes sense to do so when
the volume of your contacts (calls and email) grows beyond
the capacity of your core of support engineers. This "break
point" will be unique to your circumstance.
The only advice I can give is to look at the ability to
scale up Customer Support as your product sells and grows in
complexity. This lack of ability to scale up without
astronomical costs has crippled many companies. In today's
business environment, keeping core strengths within the
company, and outsourcing everything else is the winning
solution.
Outsourcing is never the easy way out. As I've said, I've
done it a few times, and I am (obviously) not shy about
sharing my thoughts and opinions. If you are considering
this route for technical support and need someone off whom
to bounce ideas, I'd be happy to help. Here at Be, we are
also looking at various scenarios where we can establish a
framework for support (and printing, packaging and
distribution for that matter) while allowing our developers
to join in and enjoy some of the benefits of the economy of
scale. If you are interested in discussing that concept, I'd
be happy to help with that as well.
In the Be Newsletter #72, I invoked the ghost of Mayor Koch
and asked for feedback on our support of your efforts. I am
still interested. How are we doing? It's romson@be.com.
News from the Front
By William Adams
Pssstt... Hey buddy. Come here. I've got a secret for you.
Have you ever walked into a fine jewelry shop in the dark
and tried to find the crown jewels? Well, to continue our
barrage of sample and useful documentation, I submit to you
a little tool to help you do your best. There are quite a
few ways to deal with images in the world. There is the
Datatypes library, there are resource files, and there is
the Rraster application.
Rraster and Datatypes allow you to at run-time read in any
image file of any type the user so happens to have a codec
for. The image resource allows you to pack a known image in
along with the executable so that it's always there. Packing
things into resources is a good way to go because you can
use one of the various resource editing tools like
InterfaceElements and IconWorld to manipulate them.
Another technique for getting images into your application
is the embedded graphic. That is, you do something like:
#define width 64
#define height 64
#define cspace B_RGB_32_BIT
#define bytesperpixel 3
unsigned char bits[] = {0,0,0,0,...};
BRect aRect(0,0,width-1,height-1);
BBitmap bitmap = new BBitmap(aRect, cspace);
int bytesperrow = bytesperpixel*width;
for (int row=0; row<height; row++)
{
int bitoffset = row*bytesperpixel*width;
int bitmapoffset = row*bitmap->BytesPerRow();
bitmap->SetBits((char *)bits+bitsoffset, bytesperrow,
bitmapoffset, cspace);
}
This is nifty if you have some sort of tool that allows you
to convert any image into an easy format which is simply a
"C" structure. Well... we have such a thing:
ftp://ftp.be.com/pub/samples/interface_kit/obsolete/mkimghdr.tgz
This little utility utilizes the codecs of the Rraster
application to turn just about any graphic into this useful
format. The codecs that shipped with the Advanced Access
release were for Targa and Gif images. There are a whole
slew of new codecs for other formats that will show up in
the Preview Release. These include JFIF, TIFF, PCX, PBM,
XBM, and PNG. The same technique can be utilized with the
Datatypes library. Thus for all those codecs that everyone
is hard at work producing for Datatypes, you will be able to
create simple "C" structures and include them in your app.
Of course, using Datatypes, there is already a "C" structure
Datatype, but there you have it.
You know, one thing about life with a 2 year old is that
there is never a dull moment. My current schedule gives me
the night duty. That means, from about 6:00pm until 9:30pm
I'm in charge of entertaining and eventually putting to bed
a fiery bundle of joy. Well, how do you entertain a 2 year
old? Use the BeOS of course, but the mouse is a horrible
little rodent to be avoided at all costs, so do you prefer a
graphics tablet? I do. I've been playing with the Wacom
tablets and driver... Oops, did I say that? Well, nothing
has changed in the system to make it easy for any pointing
device to show up as a mouse, but that doesn't mean we can't
play anyway:
ftp://ftp.be.com/pub/samples/drivers/obsolete/wacom.tgz
These tablets are neat things. They tell you positional and
button information like a mouse, but then there's things
like proximity, pressure and tilt. Somebody slap me with
something killer using this stuff please!! Oh, does that
look like a device driver sample? Why yes it is.
If you're a real programmer,
code is your documentation
-- a well-known Be engineer
It's the beginning of summer. I have been told that
VideoMania has been bad to the pocket books of a few
developers. That's a good thing. It's this excitement to do
neat things that drives the leapfrog development cycle. Keep
up the good work and we'll be inspired to pump out the
killer code to support you.
Modem Wars
By Jean-Louis Gassée
It looks like we averted a standards war with the new generation of 56 Kbps
modems. The two-and-a-half warring factions managed to agree on something
without either directly agreeing or exactly knowing what they agreed on.
Trust me, I'll explain in a moment. Before doing so, I need to disclose I'm
a director of 3Com. The company has announced an agreement to acquire US
Robotics, one of the companies mentioned below.
The fight got off to an uglier start than usual. The previous generation of
33.6 Kbps modems had seen a small scale attempt to preempt the V.something
standard with a V.Fast offering, but the International Telecommunications
Union (ITU) ratified a norm soon enough for everyone to quickly comply and
customers to buy in peace.
Not so with the 56K generation. Last year, Rockwell, whose chips powered
about 80% of V.34 modems, announced their new K56Plus standard; AT&T
announced their own V.flex2 and US Robotics their X2 modulation. Each one
with the firm intent of "owning" the new norm in the absence one sanctioned
by the ITU.
Rockwell announced first but USR quickly took the lead. Their strategy is
retroactively obvious: they figured out buyers needed to connect their
modem at the higher speed they were paying for. Before you e-mail me with
therapeutic advice for platitudinous thoughts, I beg you to consider what
USR did and their opposition didn't, or did much later.
USR preemptively "convinced" a number of ISPs, big and small, to announce
support, meaning access for X2 modems. Besides actually providing means to
instantiate the function customers were paying for, USR also wanted to
create a perception, they wanted a self-fulfilling prophecy. "We are
winning, join the winner and, as a result, we'll all win." Somehow, the
promoters of the other two standards never got around to such an energetic
unfurling of their standard. They agreed to make K56Plus and V.flex2
"interoperable" (that's where the "two-and-a-half" above comes from), thus
reducing the confusion; but they were two or three months behind USR in
actually delivering modems to the retail channel.
Let's stop for a moment and look at the difference between USR and their
opponents. Lucent or Rockwell produce the technology, others adopt it and
make modems. A division of labor and energy. USR "makes" the technology
(Motorola disagrees, they say some of it comes from their patent
portfolio...) as well as the device. No division here, no questioning whose
job it is to promote the standard and whose it is to sell the devices.
Still, there were potential losers in this war, not manufacturers, but
losers of the worst possible kind: customers, people with our money in
their pockets. What if the ITU, when a few million modems have already been
sold, decides for the "wrong" standard, meaning the "other one" my modem
and my ISP don't use? Worse, the ITU could decide to bless neither
K56Plus/V.flex2 nor X2.
Fear, Uncertainty and Doubt, FUD, is usually deployed by the dominant
player against a pesky interloper when the latter threatens to take too
much business away from the former: don't buy this because it will become
obsolete, incompatible, or any such reason. In the case of 56K modems, FUD
worked against everyone because a third party, the ITU, holds the keys to
the norm.
As a result, the "double blind" agreement mentioned at the beginning
magically appeared in order to create peace of mind and more sales. Most
56K modem suppliers have independently or competitively come to offer a
guaranteed upgrade to the as yet unknown standard (see Motorola's and USR's
Web pages for examples of their guarantees). Hopefully, DSP flexibility and
software permitting, this isn't as bold as one might think, but I always
wince when the future is presented as "a mere matter of software." And,
somehow, I wonder if ISPs aren't, in fact, the primary target of such
promises. If ISPs refuse to take the plunge, the 56K business will die once
all people like me have bought one and found a paucity of responding access
points.
As we depend on Web marketing and delivery of application software, we're
happy to see one obstacle to faster downloads on its way to oblivion. While
we wait for the XDSL messiah, we'll continue to adore the good old
telephone system.
|