Viser innlegg med etiketten Cpp11. Vis alle innlegg
Viser innlegg med etiketten Cpp11. Vis alle innlegg

onsdag 30. juli 2014

[ SDL2 - Part 11 ] Text styling

Text styles in TTF


In the last post we looked at how to render text. Now let's take this a step further and change the appearance of the font. There are two ways you can change how the font looks. Font style and font outline.

Fon styles


SDL TTF allows you to set the style of the font. It supports the following font styles

  • bold 
  • italic 
  • underlined 
  • underlined

You can combine these in any way you like. We'll start of with just setting a single font style at a time, and then move on to see how we can apply several of them at once.

Font styles


Settnig font styles in TTF is easy, it just requires a single function. The function let's you set one or more font styles. Let's start off by looking at how to set just one font style

Setting the font style


We can set the font style using the following function
void TTF_SetFontStyle
(
    TTF_Font *font,
    int style
)
The arguments are :
  •  TTF_Font *font - the font to set the style on
  • int style       - the style to set on the font

As you can see, the style parameter is an int and not an enum. I'll get back to why that is later, but for now let's look at the possible values for style, these are all self-explanatory so I won't be adding a description.

  • TTF_STYLE_NORMAL
  • TTF_STYLE_BOLD
  • TTF_STYLE_ITALIC
  • TTF_STYLE_UNDERLINE
  • TTF_STYLE_STRIKETRHOUGH

Any text you render after setting this font style will have the new effect, but it won't change any text you have written with a different style. So when you set the style to TTF_STYLE_BOLD, all text you render from that point and until you set a different style will be bold. And as long as you pass any of the above values to the function, the font will only have the one last style you set.

Let's to a simple example
Init TTF and load a font
TTF_Init();
TTF_Font font = TFF_LoadFont("font.ttf", 16);
Any text rendered at this point will be normal with no font styles
TTF_SetFontStyle( font, TTF_STYLE_BOLD );
Any text rendered at this point will be bold
TTF_SetFontStyle( font, TTF_STYLE_ITALIC );
Any text rendered at this point will be in italics, but not bold
TTF_SetFontStyle( font, TTF_STYLE_NORMAL );
Any text rendered at this point will be normal with no font styles
TTF_SetFontStyle( font, STYLE_UNDERLINE );
Any text rendered at this point will be underlined

As you can see, this is pretty straight forwards. So let's make things a little bit trickier by setting multiple font styles at once. But first we need to take a look at how to combine several flags like TTF_STYLE_ITALICS and TTF_STYLE_BOLD

Binary numbers


In order to learn about how to combine these flags, we need to look at binary numbers first of all. If you don't already know about binary numbers, you should take a look at the above link. It's not crucial, but it is highly recommended to know a little about them. I might create a blog post about them at some point.

A computer stores numbers as individual bits ( 0's and 1's ). They correspond to on / off or true / false. Yup, that's right, we can use the individual bits of any number as a boolean variable.

Let's take a look at an 8 bit binary number ( 1 byte )

1010 0101

As you can see, it has 8 digits. So that's eight different flags. Each of these flags have two different possible values : 0 / 1 or false / true. So that's 8 bools for the price of a single byte!

Bitwise operations


So how do we use these 8 bools? As you know, we have the following boolean operations in C++ :
  • and ( &&
  • or ( ||

These work on an entire variable. And int, for instance will be false if its value is 0, otherwise its true. But there are similar operations that does this on all bits of a variable. These are called bitwise, simply because they operate on a simple byte. To do a bitwise operation, we need two variables of equal size ( same number of digits ), for instance two bytes.

Let's create two bytes, we'll use these for a few examples
Byte 1 : 0101 0011 ( 64 + 16 + 2 + 1 = 85 )
Byte 2 : 0110 0010 ( 32 + 64 + 2 = 98 )
Here is a simple example of bitwise OR between two bytes
0101 0011
OR
0110 0010
=
0111 0011
And here's the AND operation between the same two bytes :
0101 0011
AND
0110 0010
=
0100 0010

We also have the a bitwise version of the NOT opeartion ( ! in C++ ). This operation only takes a single element and flips all bits ( turns 1's into 0's and 0's into 1's. ). Let's test it on our two bytes

Byte 1 :
NOT 0101 0011
=    1010 1100

Byte 2 :
NOT 0110 0010
=    1001 1101
Finally, there's a fourth operation called XOR or exclusive or. XOR is true when the first and second bool are different ( ie one is true, the other false ). It can be compared to the != operator which is true when the left and right sides are different. Here are the four possibilities :
false XOR false = false
false XOR true  = true
true  XOR true  = false
true  XOR false = false

An here is the XOR between our two bytes:
0101 0011
XOR
0110 0010
=
0011 0001

As you can see, the positions where the bits are different is true, the others are false.

Setting and cheking individual bits


So now that we know how to do bitwise operations, we need a way of checking and setting the individual bits. This is done simply by using OR, AND and XOR. Before we take a look at how to do this, let's define a few values to check.

Recall that the different font styles are ints? This is because they are used to perform bitwise operations to set and unset different bits. Here they are again, this time with their values. For simplicity, I'll only list the last four bits ( the others are always 0 ). The values are in decimal with the binary representation in parenthesis

  • TTF_STYLE_NORMAL               = 0 ( 0000 )
  • TTF_STYLE_BOLD                  = 1 ( 0001 )
  • TTF_STYLE_ITALIC                   = 2 ( 0010 )
  • TTF_STYLE_UNDERLINE          = 4 ( 0100 )
  • TTF_STYLE_STRIKETRHOUGH = 8 ( 1000 )

As you can see, they all have only one ( or zero ) bit set. This means we can use AND, OR or XOR on just one bit.

Setting a bit


To set a bit ( without affect any other bit ) we use the ORoperation. So say that we have four 0 bits, 0000 and we want to set the bit for bold on it. In other words, we want the result 0001. What we do is : that we take our original 4 bits ( 0001 ) and set it to the original 4 bits ( 0001 ) OR'ed with the bitmask for bold ( 0001 ) :

0000
OR
0001 ( value of TTF_STYLE_BOLD )
=
0001

Simple as that! This woks for any of the other flags in the same way. They all will end up setting one bit.

Note that this will not change any other bits. If we try set the italics font style on the above variable we get

0001
OR
0010 ( value of TTF_STYLE_ITALIC )
=
0011 ( TTF_STYLE_BOLD and TTF_STYLE_ITALIC set )

Now that we know how to set the bits, we need a way of checking them

Unsetting a bit


Sometimes we want to remove a bit. Say for instance we want to remove the italics from the font above. How do we do that without affection the other values? This is a tiny bit more complex, because it requires two operations. What we are trying to do is the following. Say we have a bitmask ( 0000 1011 ) and we want to unset the bit for bold text, but leave the rest uncanged. So we need to be able to go from
0000 1011
to
0000 1010
Here we need to do an AND operation. This is because we have a bit that we want to set to 0. This would work fine if the bit already 0. But if it was 1, then any OR operation with that bit would be true since an OR operation only requires one of the elements to be 1 in order to return true.

So we need to do an AND operation. But how? If we just used the TTF_STYLE_BOLD value ( 0000 0001 ) as the second element, we would end up with :

0000 0101
AND
0000 0001
=
0000 0001
Which is clearly wrong. So what we need to do is to AND it with a value that would not affect any bits except the one we want to unset. An AND operation with 1 will do this as 0 AND 1 is 0 and 1 AND 1 is 0. And a AND operation with 0 is guaranteed to unset the bit since 0 AND 0 is 0, and 1 AND 0 is 0. So what we need is a bit mask with one 0 ( the value we want to unset ) and the rest 1 ( the values we don't want to change. ) So this leaves us with the value 1111 1110. And AND operation with this value will unset the last bit and leave the others as they were. And since 1111 1110 is the same as 0000 0001 ( TTF_STYLE_BOLD ) with all bits flipped, we can get this value by using the NOT operation :
NOT 0000 0001 ( TTF_STYLE_BOLD )
=    1111 1110

Now that we have our bitmask to AND with we get :
0000 0101
AND
1111 1110
0000 0100

Checking a bit


To check a bit, we need to use the bitwise AND operation. And since we are only checking and not setting, we don't have to store the value anywhere which means we don't have to worry about changing anything.

To check a bitmask, simply do an AND operation with the value you want to change for ( in this cae, any of the TTF_STYLE_.... values ). So, to check if a text is bold, we do an AND between our mask an TTF_STYLE_BOLD :

0011 ( our bit mask, TTF_STYLE_BOLD and TTF_STYLE_ITALIC set )
AND
0001
=
0001

As you can see, we only set the bit that's set in our variable ( TTF_STYLE_ITALIC set ) the others will be 0 no matter what our mask is. The value 0001 is not 0, and thus this evaluates to true and we now know that the font is bold. If our mask didn't have the bold bit set, our mask would be 0010. An AND between 0010 AND 0001 is true ( they have no bit set to one in common ) and the result is 0 aka false.

Putting it all to use


Now that we know about binary number and setting, getting and checking the bits, we can put it into use. Below is a simple class that serves as a wrapper for TTF_Font. It enables to set, get and check for flags using enum. I hope this will make it easier to understand and use TTF_Fonts.



For a full list of my tutorials / posts, click here. Feel free to comment if you have anything to say, any suggestion or any questions. I always appreciate getting comments.

mandag 7. juli 2014

[ C++11 - Part 2 ] Timing with chrono

std::chrono


The chrono library is a new part of C++11. It's used for timing functionality. It supports a variety of different operations and can be quite daunting in the beginning. I wrote a little about it in the previous part of my SDL2 tutorial, but I thought I'd add some more details and try to explain things a bit more throughly here. The library contains several new types, but I'll try to explain all of them shortly. But first a few practical tips that will make using std::chrono easier.

Some helpful tips


My first recommendation is that you write using namespace std::chrono somewhere your code ( preferably at the top ). Usually, using namespace statements are discouraged to avoid name collisions, but this is less likely to occur when you write using namespace std::[something] where something can be anything like string or cout or indeed chrono. The reason why we use this is quite simple. If we didn't use it, we'd end up with code with std::chrono all over the place. It's a lot easier ( at least for me ) to read

time_point p = high_resolution_clock::now();

Than it is to read

std::chrono::time_point p = std::chrono::high_resolution_clock::now();

Includes


To make sure everything compiles as it should, please add the headers and using to the top of your file :

#include
#include

using namespace std::chrono: // So we don't have to write std::chrono everywhere!

About this part


I also want to point out that this guide is rather comprehensive. This is because it's a good idea to have deep understanding how the various components of the chrono library works. Just writing this guide helped me to understand a lot of it. My hope is that it will help you to.

If you want more information, you can look at the en.cppreference documentation for chrono.

en.cppreference covers most, if not all of the features in C++11 with details information and good examples. It's very useful for learning and as a reference.

Overview


Here is a quick overview of the chrono library.


I will now go over each of these components, starting with the basic one, ratio

ratio


The ratio is actually not a direct part of chrono but it's very useful for working with chrono and just useful in genera. ration is define in it's own header file, simply called ratio

The class is self is template. The definition looks like the following :

template
<
    std::intmax_t Num,
    std::intmax_t Denom = 1
>
class ratio;
Even though this is a templated class, which can be complicated and hard to understand, this one is quite simple. The first part ( Num )is the numerator, or simply the top part of a fraction. And naturally, the second one, ( Denom ) is the denomerator. These two numbers forms a fractions : Num / Denom, usually these numbers are dividable by 10, so you end up with numbers like 1000 or 0.001

Both variables are of the type std::intmax_t, which means they are the biggest possible type of signed int available, usually at least 64 bits.

In the chrono library ticks are stored in fractions of second. A few examples :
  • A second : ratio < 1 /1 >
    • A second is 1 /1 of a second.  
    • Can also be written as std::ratio< 1 > since the denomerator defaults to 1
  • A millisecond :  ratio< 1 /1000 >
    • A millisecond is 1 / 1000 of a second
  • A minute : ratio< 60 /1 >
    • A minute is 60 / 1 seconds. 
    • Can also be written as ratio< 60 > since the denomerator defaults to 1

As a part of the ratio header, there's a lot of predefined ratios ( milli, nano, kilo, mega, ... ). Because ratio is not directly a part of the chrono library ( it has other uses than just chrono ), there is no predefined values for minutes, hours, etc. There's just the ones based on the standard units that's used for distance or weight. You can refer to either of these using the std:: prefix. Since the ratios are not part of the chrono library, it's just std:: and not std::chrono::.

For a full list of the predefined values, take a look at the documentation.

duration


duration( or std::chrono::duration ) is one of the basic classes of the chrono library. As the name suggests, it stores a time duration or a distance between to points in time if you like.

Member variables


It's quite simple in its structure, it only has two member variables :
  • rep
    • an arithmetic type ( basically any unit that can hold a number ) that stores the number of ticks.
  • period
    • a ration containing the type of unit rep stores. In effects this means "how many seconds is one tick."

Constructing a duration


The constructor for a duration is rather complex as it involves both rep ( the type of the variable to hold the tick ) And setting the period i.e. how long each tick is ( millisecond, second, minute, ... )

The actual constructor looks like this :
template
<
    class Rep,
    class Period = std::ratio<1>
>
class duration;
The ratio defaults to 1 / 1, meaning seconds. The number of ticks the duration should use are sent to the constructor in the ordinary way using the parenthesis after the variable name

So to create a duration for containing seconds, you can do :
duration< int64_t > durSec( 10 );
This duration is for 10 seconds. Nice and simple!

To create different durations we can use the ration like above.  For example 10 millisecond becomes :
duration< int64_t, std::ratio< 1, 1000 > > durMSec( 10 );
Okay, but how about 10 minutes? This is quite similar to the above :
duration< int64_t, std::ratio< 60, 1 > > durMin( 10 );

We do std::ratio< 60, 1 > because a minute is 60 / 1 seconds which is the same as 60 seconds.

As I mentioned above, there are predefined ratios already in C++11. So you can simplify a duration of 10 milliseconds to :
duration< int32_t, std::milli > dur( 10 );
But there is an even simpler way! Just like in ratio there are predefined values in duration And they're very simple to use.

So say you wanted a duration of 10 milliseconds :
milliseconds mSec( 10 );

Member functions


Duration has a few functions, but I'll just cover two of them now
  • count
    • Returns the number of ticks (rep , see the documentation above )
  • duration_cast 
    • Converts a duration of duration into another.

    duration_cast


    When we're working with two different types of durations things can get a bit weird. A simple example : what's 3 minutes minus 36 seconds. The answer is quite simple for a human to figure out. But the results in your program needs to be a duration but which unit? Since 3:24 can't be expressed exactly in minutes, we need to change either the 3 minutes to seconds, or the 36 seconds to minutes. Here's where duration_cast<> comes in.

    minutes min( 3 );
    seconds sec( 36 );
    minutes minToSec = duration_cast< std::chrono::seconds > ( min );
    This simply casts our 3 minutes into 180 seconds. After doing that, you can simply do

    seconds result = minToSec - sec;
    And you'll get the result in seconds ( 144. ) If you had converted this to minutes, it would take the whole minutes and strip the seconds. Meaning you would end up with 2

    Floating points


    Up until now, we've only used integer values for representing ticks. This means we can only represent whole tick. So a duration of seconds using an int to represent ticks means it can only represent whole seconds. Consider the following code :

    Create a duration of milliseconds represented as int :
    duration< int32_t, std::milli > msAsInt( 16 );c
    This is equal to the std::milliseconds

    Create a duration of seconds represented as int :
    duration< int32_t, std::ratio< 1, 1> > secAsInt( msAsInt );c
    This is equal to std::seconds. This will fail ( won't compile ) because you loose precision. You could use a duration_cast to fix this, but you'll loose the precision and end up with 0. duration_cast is way of telling the compiler "yeah, I know this will fail loose precision, just do it!"

    Create a duration of seconds represented as a double :
    duration< double, std::ratio< 1, 1> > secAsDouble(msAsInt);
    This is not the same as std::seconds because std::second uses int. If you did secondsAsFloat.count() you would get 0.016, because ticks are stored in a double.

    Unlike the previous line, this won't fail because you don't loose precision. In fact, you could change the std::ratio to store years :
    duration< double, std::ratio< 60 * 60 * 24 * 365, 1 > > yearsAsDouble( millisecondsAsInt ); // 0.016 sec
    This will convert the 16 ms to years. If you did yearsAsDouble.count() you would get roughly 5.07356672 × 10^-9 ( 0.00000000507356672 ) years.

    Clocks


    In order to set the time for a time_point you use clocks. Clocks are just object that has a starting point ( or epoch ) and a tick rate. The starting point is often 1.1.1970 ( UNIX timestamp ) and the tick rate can be 1 second for instance.

    There are three available clocks in the chrono library.
    • system_clock
      • The wall clock, use this if you just want to know the current time and date
      • This clock may be adjusted by either daylight saving time ( DST ) or leap seconds.
      • Can be mapped to C-style points and can therefore be easily printed.
    •  steady_clock
      • This clock is monotonic, this means will never be adjusted, so it'll never be affected by things like DST and leap seconds
      • Best suited for measuring intervals
    •  high_resolution_clock
      • Shortest tick available ( will be updated most often )
      • Might be alias of std::chrono::system_clock or std::chrono::steady_clock, or a third, independent clock.  
        • This means it's not guaranteed to be monotonic like steady_clock
      • Use this for benchmarking

    time_point


    time_point ( or std::chrono::time_point) is the central class of the chrono library. I'll spare the implementation details for now and just say that it contains various information about the current point it in time.

    Construction


    The constructor for a time point looks something like this :

    template
    <
        class Clock,
        class Duration = typename Clock::duration
    >
    class time_point;
    As you can see, its a templated class that takes both a clock, and a duration. The duration is the duration the time_point uses. This defaults to the duration of the clock ( as you can see from the n = typename Clock::duration part. ) Luckily though don't have to specify either of the arguments. SO a really simple way to construct a time_point is :
    high_resolution_clock::time_point timePoint1;
    You can use stady_clock or system_clock instead of high_resolution_clock.

    This is equal to writing :
    time_point < high_resolution_clock > timePoint1;
    A bit more complex, but it means the exact same time : a time_point that uses a high_resolution_clock and has the same duration as the high_resolution_clock. I see no reason to use this method as opposed to the simpler one, but I want to explain the template arguments as well as I can.

    But what if we wanted to specify our own duration? Well then we have to set the second template argument as well. Say we wanted to specify milliseconds as our duration time unit. Remember that duration has predefined constants for this. This means we can simply do :
    time_point < high_resolution_clock, milliseconds >
    Now let's do something even worse. Say we wanted a time_point that uses half minutes ( 30 seconds ) as the time units. I have no idea why anyone would want this, but it's just a ( somewhat contrived ) example. As with some other examples, I do not encourage writing code like this. It's horribly hard to read and very hard to understand unless you know the different part of the chrono librarer. Okay, here we go :
    time_point
    <
        high_resolution_clock,
        std::chrono::duration
        <
            int64_t,
            std::ratio
            <
                30,
                1000
            >
         >
    >
    Yup, that's a template argument, inside a template argument, inside a template argument! Don't write code like this! If you need a specific time ration, at least put the ration and duration in separate objects ( I've shown you how to use the constructors above. ) Also make sure they're well named like ratio30sec and duration30sec. That should give the reader at least a small hope at knowing what's going on.

    Functions


    With that out of the way, let's move on to some functions, shall we? Well actually there's just one member function in the three different clocks :
    now()
    The function returns the current time as a time_point. As a time_point, you say? Well that means we can just use auto to create one!
    auto time = high_resolution_clock::now()

    Simple as that, we've created a time point. The type of this object will be exactly the same as
    high_resolution_clock::time_point timePoint1;

    Only it's even simpler. And we've initialized it to the current point in time at the same time!

    Difference between two time_points


    Time points supports arithmetic operations. This means you can say time_point x - time_point y. This will result in a duration But what is the kind of duration. Seconds? Milliseconds? Years? Actually there is no one answer, it's implementation defined. But the result is almost certain to be less than one second.

    Since we can't know what the resulting value is, we have two options. Say we have the following code :

    clock::time_point t1 = std::chrono::system_clock::now() ;
    // ...
    clock::time_point t2 = std::chrono::system_clock::now() ;

    And wanted to know the result of t1 - t2 Our two options are :

    1. Use atuto
      •  auto result = t2 - t1 ;
        • Nice and simple
        • But we can't control the type of result.
    2. Use duration_cast
      •  milliseconds result =  duration_cast< milliseconds > ( t2 - t1 ) ;
        • Takes the result of t2 - t1 and casts it into a duration of milliseconds and uses it to set result
        • This is a bit harder, but now we have full control over the type of duration.


      For a full list of my tutorials / posts, click here.

      Feel free to comment if you have anything to say, any suggestion or any questions. I always appreciate getting comments.


      onsdag 9. april 2014

      [ C++11 - Part 1 ] Enum classes

      Introduction to the series


      I thought I'd start of by talking about my favorite thing that's new about C++11 standard. C++11 has a lot of useful new features : auto, initializer lists, lambda, shared_ptr, unique_ptr, move semantics, etc. Some of these are quite comprehensive and complicated, and I'm still working on understanding all of them. But this one is actually quite simple.

      About enum classes


      Enum classes are basically enumerations that can't implicitly be converted to integer types. So basically you can't write :



      Why is this such a good thing?


      First of all it helps code clarity. A simple question : Say you have an enum of card suits, which would you prefer?



      So it helps code clairty. Is that all?


      No, there are more serious issues. Say you have the following code


      This might look okay, they both set the card to Suit::Clover. But here comes the big issue. Someone changes the order of the elements in Suit.



      What's the issue?


      It might seem a very subtle change. But you let's say you implemented reset method a long time ago. It's been working fine ever since, and you've completely forgotten that it uses and integer value to set suit. It'll now do something different from the constructor! So you end up with cards being different when you reset them from when you create them. And issues like this can be very confusing to debug.

      This is just a minimal example to showcase the issue. But this can happen just as easily in huge projects where the enum is used hundreds of places. Debugging such issues will waste a huge amount of time and cause a whole lot of pain and agony. All because of using an integer to assign an enum! Using enum class prevents these issues.

      Conclusion


      Use enum classes! It might be a bit annoying having to write the full enumeration name sometimes. But it's a lot better than spending hours upon hours debugging when someone changes the order of the enumeration items or adds a new value in front of others!


      Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

      For a full list of my tutorials / posts, click here.