"Text has zero width" isn't an error

Hi.

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

Otherwise client code needs to check for this, and pass a "space"
character as a workaround.

Thanks,
Stefan.

By “0x0” I’m guessing you mean a null pointer. That would not be an
empty surface. What are the SDL_ttf APIs which return this sort of
error? Perhaps it’s the error mechanism that is poor, since you seem
to think that providing an explanation of why NULL is being returned
is a poor way of handling this situation. I’m also unsure of where you
get the idea that the client has pass a “space” character as a
workaround.On Wed, Apr 8, 2009 at 11:08 AM, Stefan Monov wrote:

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

Otherwise client code needs to check for this, and pass a “space”
character as a workaround.


http://codebad.com/

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

Otherwise client code needs to check for this, and pass a “space”
character as a workaround.

By “0x0” I’m guessing you mean a null pointer. That would not be an
empty surface.

I think he meant dimensions, a surface 0 pixels wide by 0 pixels high,
not “0x” hex notation.>----- Original Message ----

From: Donny Viszneki <donny.viszneki at gmail.com>
Subject: Re: [SDL] “Text has zero width” isn’t an error.
On Wed, Apr 8, 2009 at 11:08 AM, Stefan Monov wrote:

I’m also unsure of where you get the idea that the client has pass a
“space” character as a workaround.

Heh, I do the same thing. Great (lazy) minds must think alike!

GregoryOn Wed, 8 Apr 2009, Donny Viszneki wrote:

Hi Donny.
As Mason correctly guessed, 0x0 means the dimensions 0px width, 0px height.

Currently, a passing an empty string to RenderUTF8 doesn’t return a
0x0 surface, it returns a NULL pointer and sets an error message.

My point was that this is incorrect (or at least unexpected), as
rendering an empty string is meaningful: it must yield an empty (0px
high and wide) surface.

As to passing the “space” character: it’s just an easy way to
work-around SDL_ttf’s behavior. Another easy way would be to make a
wrapper which checks for an empty string and reacts to it with an
empty surface allocated with SDL_CreateRGBSurface.

StefanOn Wed, Apr 8, 2009 at 6:12 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

By “0x0” I’m guessing you mean a null pointer. That would not be an
empty surface. What are the SDL_ttf APIs which return this sort of
error? Perhaps it’s the error mechanism that is poor, since you seem
to think that providing an explanation of why NULL is being returned
is a poor way of handling this situation. I’m also unsure of where you
get the idea that the client has pass a “space” character as a
workaround.

Hi Donny.
As Mason correctly guessed, 0x0 means the dimensions 0px width, 0px height.

Ah, a surface containing zero pixels a legal SDL construction? I see
how, if SDL supported it, this would decrease your code’s
complexity… like, a little bit.

An alternative to introducing a no-pixel surface would be if you wrote
your own RenderUTF8 wrapper (that would catch the “Text has zero
surface” error condition and simply return a NULL pointer) and your
own blitting wrapper (one that checks for a NULL pointer.) It would
only add a few lines of code to your project.

How is the error reported from RenderUTF8? It isn’t something foolish
like only a string description of the error, is it?

My point was that this is incorrect (or at least unexpected), as
rendering an empty string is meaningful: it must yield an empty (0px
high and wide) surface.

As I mentioned, it’s possible that a no-pixel surface is not a legal
SDL construction.

As to passing the “space” character: it’s just an easy way to
work-around SDL_ttf’s behavior. Another easy way would be to make a
wrapper which checks for an empty string and reacts to it with an
empty surface allocated with SDL_CreateRGBSurface.

I guess that’s what you’re already doing?On Wed, Apr 8, 2009 at 11:33 AM, Stefan Monov wrote:


http://codebad.com/

Ah, a surface containing zero pixels a legal SDL construction? I see
how, if SDL supported it, this would decrease your code’s
complexity… like, a little bit.
Yes.

An alternative to introducing a no-pixel surface would be if you wrote
your own RenderUTF8 wrapper (that would catch the “Text has zero
surface” error condition and simply return a NULL pointer) and your
own blitting wrapper (one that checks for a NULL pointer.) It would
only add a few lines of code to your project.
Yes.

How is the error reported from RenderUTF8? It isn’t something foolish
like only a string description of the error, is it?
A null pointer is returned.

As I mentioned, it’s possible that a no-pixel surface is not a legal
SDL construction.
That would be really unexpected.

As to passing the “space” character: it’s just an easy way to
work-around SDL_ttf’s behavior. Another easy way would be to make a
wrapper which checks for an empty string and reacts to it with an
empty surface allocated with SDL_CreateRGBSurface.
I guess that’s what you’re already doing?
It is.

I detect a “why are you bothering us with peanuts?” tone to your message.
If you (representative of the team?) consider my feedback unimportant
for SDL’s quality, cool, fine, I won’t be back.
:-/

Stefan

Ah, no. Donny’s always skeptical, and no changes that change code are peanuts.

A 0x0 surface is reasonable and I have made them myself (if I remember right).

Jonny DOn Wed, Apr 8, 2009 at 1:01 PM, Stefan Monov wrote:

I detect a “why are you bothering us with peanuts?” tone to your message.

How is the error reported from RenderUTF8? It isn’t something foolish
like only a string description of the error, is it?
A null pointer is returned.

Oh, is “string has zero width” the only error message RenderUTF8 can return?

I detect a “why are you bothering us with peanuts?” tone to your message.

I’m a little confused as to why returning no surface when there is no
data to be on that surface is being interpreted by some as a problem.
This is why I asked about how error feedback is handled by SDL_ttf, to
gauge how troublesome it was.

If you (representative of the team?) consider my feedback unimportant
for SDL’s quality, cool, fine, I won’t be back.
:-/

I represent only myself, and my diverse political constituency of
unrecognized sovereign nations! Long live Kurdistan! Long live
California!On Wed, Apr 8, 2009 at 1:01 PM, Stefan Monov wrote:


http://codebad.com/

Hello !

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

I think the basic reason why SDL_ttf is doing
it in this way, is just because it is also
used in SDL all over the place. If there an error occurs,
the function returns a NULL pointer.

The second thing i can imagine is the speed reason.
It is a little bit faster to check if the pointer is null
then to check if width == 0 && height == 0 in your routines.

Also checking width == 0 && height == 0 means two dereference
operations which also consumes time. The NULL pointer you get back
from a function will stay in a CPU register and the system
does not have to look it up in a cache or in memory.

CU

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

I think the basic reason why SDL_ttf is doing
it in this way, is just because it is also
used in SDL all over the place. If there an error occurs,
the function returns a NULL pointer.

I think his argument is precisely that this is not an error condition,
not that this is an error condition that should be handled in a
special way.

The second thing i can imagine is the speed reason.
It is a little bit faster to check if the pointer is null
then to check if width == 0 && height == 0 in your routines.

You should be checking if it’s null anyway, otherwise you segfault
when you dereference the pointer to get the width and height. This is
a small part of the reason I’m perplexed by the desire for no-pixel
surfaces as the return value.

Also checking width == 0 && height == 0 means two dereference
operations which also consumes time. The NULL pointer you get back
from a function will stay in a CPU register and the system
does not have to look it up in a cache or in memory.

True, but any blitting operation costs an order of magnitude more than
those two operations. It only becomes a real problem if it results in
systemic cache misses, but that’s a separate issue.On Wed, Apr 8, 2009 at 1:30 PM, Torsten Giebl wrote:


http://codebad.com/

Also checking width == 0 && height == 0 means two dereference
operations which also consumes time. The NULL pointer you get back
from a function will stay in a CPU register and the system
does not have to look it up in a cache or in memory.

True, but any blitting operation costs an order of magnitude more than
those two operations. It only becomes a real problem if it results in
systemic cache misses, but that’s a separate issue.

Do you mean width==0 || height==0?

What would width==0 and height!=0 mean? (or vice versa.)

This is the reason I disagree with Stefan when he says:On Wed, Apr 8, 2009 at 1:40 PM, Donny Viszneki <@Donny_Viszneki> wrote:

On Wed, Apr 8, 2009 at 1:30 PM, Torsten Giebl wrote:

On Wed, Apr 8, 2009 at 1:01 PM, Stefan Monov wrote:

As I mentioned, it’s possible that a no-pixel surface is not a legal
SDL construction.
That would be really unexpected.


http://codebad.com/

Torsten, that’s a good point. It is a lot less computation to return
NULL rather than a fully-initialised 0x0 surface with all its
fields…

Actually, now that I think of it, if you’re using SDL_BlitSurface(),
it doesn’t care if you pass a NULL surface. What is the use case
here? Does the non-unicode function work differently?

Jonny DOn Wed, Apr 8, 2009 at 1:30 PM, Torsten Giebl wrote:

Hello !

Currently rendering an empty UTF8/Unicode string errors out with “Text
has zero width”. I think it should return a valid empty (0x0) surface
instead.

I think the basic reason why SDL_ttf is doing
it in this way, is just because it is also
used in SDL all over the place. If there an error occurs,
the function returns a NULL pointer.

The second thing i can imagine is the speed reason.
It is a little bit faster to check if the pointer is null
then to check if width == 0 && height == 0 in your routines.

Also checking width == 0 && height == 0 means two dereference
operations which also consumes time. The NULL pointer you get back
from a function will stay in a CPU register and the system
does not have to look it up in a cache or in memory.

CU


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

How is the error reported from RenderUTF8? It isn’t something foolish
like only a string description of the error, is it?
A null pointer is returned.
Oh, is “string has zero width” the only error message RenderUTF8 can return?
I see what you mean.

First, to answer your question. Currently RenderUTF8 can produce the
following errors:

  • “string has zero width”
  • “failed to allocate text surface”
  • “failed to find glyph”

Of those, only the first one sets the error-string (queried with
TTF_GetError). The second and third don’t (which is a bug).
There is no real() way to know which one of those happened.
(
) The only way is to call TTF_SetError(“dummy”), then call
RenderUTF8, then check whether the error-string has changed to “string
has zero width”. This is clearly unacceptable, and does not let you
detect the other two errors. But that’s another discussion.

I’m a little confused as to why returning no surface when there is no
data to be on that surface is being interpreted by some as a problem.
Here’s where we diverge: I say there is data to be on the surface,
and the data happens to be an empty string.
For example, the following should be correct usage of SDL_ttf:
SDL_Surface* surface = TTF_RenderUTF8_Blended(font, myTextVar, myColorVar);
myButton.resize(surface->w, surface->h);
SDL_BlitSurface(surface, NULL, screen, NULL);
SDL_FreeSurface(surface);

Here I am ignoring the possibility for errors other than “string has
zero width”. If those were reported properly, the code would become:
TTF_ErrorCode err;
SDL_Surface* surface = TTF_RenderUTF8_Blended(font, myTextVar,
myColorVar, &err);
if(err == TTF_SurfaceAllocationError) /* handle error /;
if(err == TTF_GlyphNotFound) /
handle error /;
/
note lack of check for “err == TTF_ZeroWidthError” */
myButton.resize(surface->w, surface->h);
SDL_BlitSurface(surface, NULL, screen, NULL);
SDL_FreeSurface(surface);

You should be checking if it’s null anyway, otherwise you segfault
when you dereference the pointer to get the width and height. This is
a small part of the reason I’m perplexed by the desire for no-pixel
surfaces as the return value.
This desire is merely the application of the Principle of Least
Surprise. I consider it to make SDL more difficult to use.
I think this is pretty self-explanatory.
I will try to make available a patch shortly as I’ve no desire of
arguing further. From there I leave the decision to you.

What would width==0 and height!=0 mean? (or vice versa.)
This is the reason I disagree with Stefan […]
It would mean that blitting the surface is a no-op and querying
“surface->w” and “surface->h” is a legal operation yielding 0 and a
nonzero value.

Torsen says:

I think the basic reason why SDL_ttf is doing it in this way, is just because it is also
used in SDL all over the place. If there an error occurs, the function returns a NULL pointer.
As Donny said, I don’t consider it an error, so NULL must not be returned.

The second thing i can imagine is the speed reason.
It is a little bit faster to check if the pointer is null
then to check if width == 0 && height == 0 in your routines.
No, that’s wrong: I won’t do any checking at all. I’ll simply use the
surface as usual. See code example above.

Jonathan says:

It is a lot less computation to return NULL rather than
a fully-initialised 0x0 surface with all its fields…
True. However, is this not a pointless thing to optimize? The cost of
constructing a 0x0 surface is dwarfed even by that of say, blitting a
32x32 sprite of which there are thousands in an application…

Actually, now that I think of it, if you’re using SDL_BlitSurface(),
it doesn’t care if you pass a NULL surface. What is the use case
here?
Mainly, to be able to query width and height without needless checks.
See code sample above.
Also, not all functions in real-world code are documented to be no-ops
when passed a NULL surface.
For example, SDL_gfx’s rotozoomSurface just might crash if passed
NULL. You can’t know.

Stefan.On Wed, Apr 8, 2009 at 10:23 AM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

On Wed, Apr 8, 2009 at 1:01 PM, Stefan Monov <@Stefan_Monov> wrote:

First, to answer your question. Currently RenderUTF8 can produce the
following errors:

  • “string has zero width”
  • “failed to allocate text surface”
  • “failed to find glyph”

How annoying. I am always thrown for a loop whenever software returns
any error as string-only so that the program cannot comfortably handle
the error.

I’m a little confused as to why returning no surface when there is no
data to be on that surface is being interpreted by some as a problem.
Here’s where we diverge: I say there is data to be on the surface,

Where we diverge is that when you say “surface” you mean SDL_Surface,
and when I say it I mean the notional surface/canvas represented by
that struct.

and the data happens to be an empty string.
For example, the following should be correct usage of SDL_ttf:
SDL_Surface* surface = TTF_RenderUTF8_Blended(font, myTextVar, myColorVar);
myButton.resize(surface->w, surface->h);
SDL_BlitSurface(surface, NULL, screen, NULL);
SDL_FreeSurface(surface);

I understand. I think this proves, however, that there are examples
which favor both approaches. In your situation, since you seem to be
using C++, why not just create a wrapper around SDL_Surface which will
return 0 for its dimensions when its internal SDL_Surface pointer is
NULL?

Jonathan says:

It is a lot less computation to return NULL rather than
a fully-initialised 0x0 surface with all its fields…
True. However, is this not a pointless thing to optimize? The cost of
constructing a 0x0 surface is dwarfed even by that of say, blitting a
32x32 sprite of which there are thousands in an application…

Well, you can’t predict the allocation overhead for all platforms.

Actually, now that I think of it, if you’re using SDL_BlitSurface(),
it doesn’t care if you pass a NULL surface. ?What is the use case
here?
Mainly, to be able to query width and height without needless checks.

For clarity: there are cases which favor both approaches.

See code sample above.
Also, not all functions in real-world code are documented to be no-ops
when passed a NULL surface.
For example, SDL_gfx’s rotozoomSurface just might crash if passed
NULL. You can’t know.

Stefan presents a lot of cases which favor his approach.

Am I being stubborn if I say rotozoomSurface should crash if passed
a NULL pointer or a no-pixel surface? I frequently argue in favor of
more checking when they aren’t very expensive, but secretly I wonder
if we’re all such bad hackers that we can’t accept a segfault to show
us exactly where the one check should have been…

;)On Wed, Apr 8, 2009 at 2:10 PM, Stefan Monov wrote:


http://codebad.com/

Am I being stubborn if I say rotozoomSurface should crash if passed
a NULL pointer or a no-pixel surface? I frequently argue in favor of
more checking when they aren’t very expensive, but secretly I wonder
if we’re all such bad hackers that we can’t accept a segfault to show
us exactly where the one check should have been…

IMO, a well-designed program or library should never segfault. If an
external library routine receives incorrect input, the routine should fail
with some sort of helpful error message. If an internal routine receives
bad input, it ought to no-op if it can, or raise an assertion failure if.
that wouldn’t work. (Not sure if C has those, though…)>----- Original Message ----

From: Donny Viszneki <donny.viszneki at gmail.com>
Subject: Re: [SDL] “Text has zero width” isn’t an error.

By your definition a well designed library should protect users
from all their errors
write code for you.On Wed, Apr 8, 2009 at 11:36 AM, Mason Wheeler wrote:

----- Original Message ----

From: Donny Viszneki <donny.viszneki at gmail.com>
Subject: Re: [SDL] “Text has zero width” isn’t an error.

Am I being stubborn if I say rotozoomSurface should crash if passed
a NULL pointer or a no-pixel surface? I frequently argue in favor of
more checking when they aren’t very expensive, but secretly I wonder
if we’re all such bad hackers that we can’t accept a segfault to show
us exactly where the one check should have been…

IMO, a well-designed program or library should never segfault. If an
external library routine receives incorrect input, the routine should fail
with some sort of helpful error message. If an internal routine receives
bad input, it ought to no-op if it can, or raise an assertion failure if.
that wouldn’t work. (Not sure if C has those, though…)


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Well as I said, when it is cost effective, I generally argue in favor
of this as well. But you’re silly if you would apply this to “fast
path” code, regardless of whether or not it is "an external library
routine."On Wed, Apr 8, 2009 at 2:36 PM, Mason Wheeler wrote:

IMO, a well-designed program or library should never segfault. ?If an
external library routine receives incorrect input, the routine should fail
with some sort of helpful error message. ?If an internal routine receives
bad input, it ought to no-op if it can, or raise an assertion failure if.
that wouldn’t work. ?(Not sure if C has those, though…)


http://codebad.com/

Also this has less to do with design and more to do with policy. If
you could easily turn these sorts of checks on or off with a macro
when you compile the library, that’s a pretty good indication that
it’s not a design issue.On Wed, Apr 8, 2009 at 2:49 PM, Donny Viszneki <@Donny_Viszneki> wrote:

On Wed, Apr 8, 2009 at 2:36 PM, Mason Wheeler wrote:

IMO, a well-designed program or library should never segfault. ?If an
external library routine receives incorrect input, the routine should fail
with some sort of helpful error message. ?If an internal routine receives
bad input, it ought to no-op if it can, or raise an assertion failure if.
that wouldn’t work. ?(Not sure if C has those, though…)


http://codebad.com/

By your definition a well designed library should protect users
from all their errors
write code for you.

Not at all. By my definition, a well-designed library should make
errors easy to find and fix. A segfault that crashes the program and
(maybe) leaves you with a core dump is hardly an easy fix case.
Since C doesn’t have exception handling, (and C++'s version isn’t
worth the bits it’s printed on, so to speak,) the best thing to do is
to return an error code in critical situations, or handle it internally,
usually by doing nothing, if that’s a realistic and feasible option.

It’s still the programmer’s responsibility to write the code to check
for error conditions. That’s why I like assertions. They make
tracking down errors much simpler, and their performance impact
is negligible in most cases. (Unless of course one fails, in which
case you’ve got bigger things to worry about.)>----- Original Message ----

From: Pavel Dudrenov
Subject: Re: [SDL] “Text has zero width” isn’t an error.