How to create your own cFosSpeed skin
All cFosSpeed versions do come with their own standard skins. Still, you are free to modify and change them to better suit your own needs and aesthetic preferences. In fact, we strongly encourage you to send us your own custom designs and share them with others!
This tutorial will guide you through the process of creating a new basic skin. Do note that most of the graphics used for this are already part of your cFosSpeed distribution, which is why the focus will be on teaching you several ways to integrate them into your own design.
Hint: When working on your skin, you may want to activate the cFosSpeed “test mode.” This will provide you with a quick and easy way to check if everything is working properly and in the right place.
(See the skin definition reference for details on skin testing.)
The INI file / [all] section
The INI file is a plain text file that determines how cFosSpeed displays status information on screen. Let’s just name ours skin.ini and save it to MySkin, a new folder we should first create as a subdirectory of the cFosSpeed main directory (e.g., C:Program FilescFosSpeedMySkin). The new INI file must contain an [all] section listing version information, a skin name and background definition, much like the one shown below:
[all]
version=cFosSkin V1.0
name=MyFirstSkin
background=back.bmp
background_mask=backmask.bmp
Since there is only one version number at this point (V1.0), we’ll just go ahead and use it.
The skin will show up later in the program’s context menu under “Select Skin” by the name given to it in the second entry above.
The background for this skin is built from a simple square image filled with a color gradient (back.bmp) and a grayscale mask defining the skin’s actual shape (backmask.bmp).
For each individual pixel, the grayscale value of the background_mask determines the alpha value (i.e., opacity) of the resulting skin background, whereas the actual color information is taken from the background image. In the mask, black (0) denotes total transparency, while white (255) means full opacity.
square gradient image
+ grayscale mask
= skin background
If you get a chance to work with 32-bit *.TGA or *.BMP files, you can achieve the same result more easily by using a single image for both color and alpha information. In this case, all mask information is taken directly from that image, meaning there’s no need to define a separate background_mask section. For additional background-definition techniques, please refer to our skin definition reference page.
What we’ll do now to add some eye candy is have the skin blend in and out when it is being started. We’ll also take this opportunity to define a global R,G,B transparentcolor:
blend_time=300
blend_out_time=500
transparentcolor=255,0,0
A transparentcolor value doesn’t really need to be specified here, but doing so may help during skin creation by making it easier to check which pixels of an image are fully transparent. Remember that it remains valid for all the images we’ll use as part of this skin.
The font definition
Skins usually contain several text sections for conveying alphanumeric status information. The required parameters are typically entered individually for each respective section. However, there are some parameters that do depend on the font image chosen for a section rather than the section itself. Since such parameters are the same for all sections using a particular font image, it would be redundant – even nonsensical – to repeat them over and over again for each section. Thus, for the sake of economy, we use a font definition to write them down once and then refer back to this section as needed:
[font1]
fontbitmap=num_chars3.tga
framewidth=5
frameheight=8
fontbitmapchars=0 123456789KMGT.?
In this section, font1 is the name of the font. This will come into play later on when it’s used to assign that font to different text sections.
The fontbitmap is the bitmap containing the font image. For this tutorial, we chose a font that is part of the cFosSpeed “Numerical” skin and can either be found in the default_skin subdirectory of your cFosSpeed installation (e.g., C:Program FilescFosSpeeddefault_skin) or downloaded from here(unzip).
It contains a small frame for every character listed after fontbitmapchars – aligned from top to bottom.
Each frame is as wide and high as defined under framewidth and frameheight, respectively.
Note that the space (i.e., the “blank” character) should not be put at the beginning or end of the character list, as the program would not recognize it there.
And don’t worry about the “?” not being properly displayed – this is just a dummy we’ll later use to format text output.
There are also a lot of other advanced text definition methods available on our skin definition reference page.
The animation method
Now, we are ready to add the first graphical disp section to our skin. Let’s start with an animation. This method uses an image consisting of multiple frames, where the value of the assigned parameter determines which frame is being displayed at any given time. This new section will indicate incoming data traffic by moving a bullet each time a packet is received. For this purpose, we’ll use the rx_bullet.tga(unzip) image from the cFosSpeed “Liquid Crystal” skin:
[disp1]
value=rx_data_cnt
method=animation
rect=44,41,55,59
bitmap=rx_bullet.tga
mod=14
min=0
max=13
frames=14
The bitmap contains 14 frames to comprise a complete up-and-down cycle that can be run indefinitely. Because the rx_data_cnt parameter is a simple counter (meaning it will increase continuously while cFosSpeed is running), we’ll need to perform a mod(ulo) calculation to keep the value within the range of min and max.
Positioning the motion is done by setting rect to the coordinates of the frame’s upper left corner and to those of a pixel just right of and below the frame’s lower right corner (both shown bright red in the magnified part of the sample image).
If we want a similar display for outgoing packets, this can be accomplished simply enough by copying this section and changing the disp name along with the value and rect entries:
[disp2]
value=tx_data_cnt
method=animation
rect=44,58,55,76
bitmap=rx_bullet.tga
mod=14
min=0
max=13
frames=14
What we have now are two displays representing two different parameters but still looking the same. We can improve on this design by making use of the transform key. One of the most powerful assets the skin definition language has to offer, this key permits mapping one color range to another (the correct notation for each range is Hue, Saturation, Value). Thus, source and destination range would have to be combined into one comma-separated list like this: Range1_Hue_Start, Range1_Sat_Start , Range1_Val_Start, Range1_Hue_End, Range1_Sat_End , Range1_Val_End, Range2_Hue_Start, Range2_Sat_Start , Range2_Val_Start, Range2_Hue_End, Range2_Sat_End , Range2_Val_End.
So, adding
transform1=15,0,0,40,255,255,100,0,0,120,230,210
to the parameters above would transform the color from orange to green, while also reducing saturation and brightness.
The history method
For displaying incoming connection speed (rx_speed) as a bar graph, we’ll need another animation. Since it contains a 26-frame animation, the rx_bar.tga(unzip) image from the cFosSpeed “Liquid Crystal” skin lends itself particularly well to this.
Keep in mind though that the parameter here may change very rapidly, which could cause the animation to behave slightly erratically. So, we’ll have to smooth things out a bit. This can be accomplished with the history method. Not only does it offer a number of ways for displaying the progression of a value (consult our skin definition reference for a more detailed description), but it can also be used to calculate and display the arithmetic mean of the values a parameter assumes over any given time period.
[disp3]
value=rx_speed
method=history updatetime=240
historysize=1
hdisp1=rx_speed_disp
You may have noticed there is no bitmap but a hdisp1 entry instead. This is because the history method can handle multiple display sections for rendering value progression. These are defined as hdisp1,…,hdispN and can be used to create effects like the scrolling bar graphs of the moving fish-shaped packets of the cFosSpeed “Default” skin. For this bar graph, however, only one such section is needed. It should be given its own name though (to distinguish it from regular disp sections). Note that there is no need to enter a value here, because the value in the history section will be used for this section as well.
[rx_speed_disp]
method=animation
rect=54,41,108,59
bitmap=rx_bar.tga
min=0
max=100
frames=26
The min and max values define the range of the rx_speed parameter, which is best thought of as the percentage of available bandwidth.
Again, adding a similar display for the speed (tx_speed) of outgoing connections can be done simply by copying the previous sections, changing disp name, value and rect entries, and applying the same color transformation as for the tx_packet.
[disp4]
value=tx_speed
method=history
updatetime=240
historysize=1
hdisp1=tx_speed_disp
[tx_speed_disp]
method=animation
rect=54,58,108,76
bitmap=rx_bar.tga
min=0
max=100
frames=26
transform1=15,0,0,40,255,255,100,0,0,120,230,210
The text method
As great as a spiffy graphical display is, it often makes sense to have some more specific information displayed about a parameter’s current value as well. This is where the text method comes in handy (using the font definition we drew up earlier). Let’s say, for instance, we want to have incoming CPS shown as a numeric value. Then, we would have to add the following section:
[disp5]
value=rx_cps
method=text
font=font1
rect=50,32,80,40
style=d
flags=r
digits=6
decimals=1
unitchar=?
transform1=60,0,0,60,255,255,33,0,0,33,220,255
transform2=0,0,0,10,255,255,225,190,140,226,191,141
What this does is display the rx_cps parameter of cFosSpeed, which keeps track of the current CPS reception rate. By setting method to text and font to font1, we make sure the disp section uses the font we’ve already defined in step two.
The style is set to “d” (=decimal) with one digit after the comma. Setting the “r” flag will have the text right-aligned. Numeric value and measuring unit may take up to 6 digits. Seeing then how our font definition clearly specifies each digit to have a width of 5 and a height of 8 pixels, this would result in a rect of 30×8 pixels to be placed above the bar defined in [disp3].
Having the unitchar point to a “blank” character bitmap will prevent displayed numbers from shifting to the right when there is no measuring unit available. This happens when transfer rates fall outside available (T)era, (G)iga, (M)ega or (K)ilo byte ranges (e.g., when showing bytes only).
While transform1 shifts the color of the text from yellow to orange, transform2 decreases the intensity of the drop shadow, which is also part of the font bitmap.
For outgoing CPS, let’s now add the following:
[disp6]
value=tx_cps
method=text
font=font1
rect=50,77,80,85
style=d
flags=r
digits=6
decimals=1
unitchar=?
transform1=60,0,0,60,255,255,100,0,0,100,200,220
transform2=0,0,0,10,255,255,225,190,120,226,191,121
It should be obvious by now that this is basically the same as above – just with other rect coordinates. What’s also different here is that the transform1 key changes the color to green, while transform2 creates a slightly darker shadow.
The slider method
What we are going to do now is add a little LED-like display emitting a brief flash when changing states. Let’s just go with the led_green.bmp .
[disp7]
value=latency
method=slider
rect=111,50,117,56
bitmap=led_green.bmp
scale=2
stepsize=1
frames=3
min=0
max=2
updatetime=200
transform1=170,0,0,205,255,255,224,0,0,225,255,150
transform2=0,0,0,10,255,255,225,190,140,226,191,141
This section displays the value of the latency parameter (see our skin definition reference page), which can either be 0 (low latency is off) or 1 (low latency is on). With scale set to 2, the original parameter is projected onto a range from 0 to 2. In combination with stepsize, frames, min and max, this will have the animation run through all of its three frames each time the original value changes from 0 to 1. Animation speed is controlled by the value entered for updatetime, which determines the time each frame is shown in milliseconds.
Color transformations are used here to correct some minor glitches in the original bitmap’s shadow colors.
The activearea method
An activearea acts as a switch that can be put to a number of uses (see the skin definition reference page). It can, for instance, be used to start a program, open a URL, or toggle other disp sections’ visibility. And this is exactly what we’re going for here.
Let’s use the switch.tga(unzip) from the cFosSpeed “Default” skin, as it comes with “inactive”, “clicked” and “mouseover” states already in place.
[disp8]
method=activearea
bitmap=switch.tga
rect=110,58,119,65
action=toggle
target=disp7
blend_time=250
To have this section toggle the visibility of another, we first need to set action to “toggle” and target to the name of the section we want to control. Having the activearea fade in and out, as the mouse cursor enters or leaves it, can be done simply by assigning a value to blend_time (in milliseconds).
The motion method
A motion is an animation that is being played for as long as the assigned value stays within a certain range. Let’s use tcp3.tga from the cFosSpeed “Liquid Crystal” skin for displaying active TCP connections.
[disp9]
value=tcp_cnt
method=motion
bitmap=tcp3.tga
rect=30,13,46,30
min=1
idleframe=1
transform1=225,0,0,230,255,255,10,0,0,15,255,255
What this does is use the tcp_cnt parameter of cFosSpeed, which tracks the number of current TCP connections, while setting the min value to “1.” In other words, it will become active whenever one or more TCP connections are open.
The bitmap contains two frames. The first is completely transparent (i.e., filled with transparentcolor). This frame serves as the idleframe, meaning it will be displayed when the tcp_cnt is “0” and thus falls outside the range between min and max. Note that for what we’re trying to accomplish in this step, we can skip defining max altogether, because there is really no need to specify an upper limit here.
By contrast, the second frame is the image that will be shown if the tcp_cnt is “1” or more.
To make sure the motion stands out nicely from the background, we use transform1 to change its color from blue to red. And for providing precise numeric information, we also add a small text section displaying the number of active TCP connections.
[disp10]
value=tcp_cnt
method=text
font=font1
rect=46,21,61,29
style=n
digits=3
flags=br
transform1=50,0,0,70,255,255,50,0,0,70,230,220
transform2=0,0,0,10,255,255,225,190,140,226,191,141
Now, let’s do something a little more ambitious by adding the following motion:
[disp11]
value=ping_time
method=motion
bitmap=connect.bmp
rect=35,87,48,99
min=1
idleframe=1
updatetime=120
pause=2000
transform1=205,0,0,212,255,255,225,0,0,227,255,220
transform2=0,0,0,200,255,255,0,0,0,200,200,200
This one (connect.bmp ) contains seven rather than just two frames. Again, the first is a fully transparent idleframe.
The other frames compose an animation that is being played continuously while ping_time stays above zero. To control animation speed, updatetime is set to 120 ms. What we’ve also done is add a pause of 2,000 ms after each time the animation has run through (i.e., after its last frame finished playing).
Transformations are again used here to handle some problems with the original bitmap’s shadow colors.
For conveying accurate numeric values, we’ll again need a brief text section like the one below:
[disp12]
value=ping_time
method=text
font=font1
rect=50,87,65,95
style=n
digits=3
flags=br
transform1=50,0,0,70,255,255,200,0,0,201,64,255
transform2=0,0,0,10,255,255,225,190,120,226,191,121
Note that both text sections contain a “b” flag. What this does is make those sections empty (and thus invisible) while their value is zero.
The fader method
Now that the display is complete, there’s only one thing left for us to do – see to it that elements still remaining visible even when the status window is not in the “open” state (cFosSpeed: the network port is closed) disappear from the display. This is where we can employ the fader method provided by cFosSpeed:
[disp13]
value=open
method=fader
min=0
max=1
min_alpha=0
max_alpha=255
blend_time=1000
target=disp1,disp2,disp5,disp6,disp7
This fader changes the alpha value of all sections listed under target depending on the state of the “open” parameter – with min and max delimiting the range that activates the fader.
Initial and final alpha values for the fading process are set by min_alpha and max_alpha, respectively, while blend_time determines the duration of the fading process.
So, we now have a totally empty background when the program starts and no network connections are active.
This is the end of our short tutorial on how to create a cFosSpeed skin. Still, there are lots of additional options available for each method to further adapt your skin to your own individual needs and aesthetic preferences. Much more information on this is available on the skin definition reference page.
Have fun designing your own skins! 🙂