]> git.localhorst.tv Git - l2e.git/blob - src/graphics/Font.cpp
removed stupid file headers that eclipse put in
[l2e.git] / src / graphics / Font.cpp
1 #include "Font.h"
2
3 #include "../loader/Interpreter.h"
4 #include "../loader/TypeDescription.h"
5
6 #include <cmath>
7 #include <iostream>
8
9 using geometry::Vector;
10 using loader::FieldDescription;
11 using loader::Interpreter;
12 using loader::TypeDescription;
13 using std::pow;
14
15 namespace graphics {
16
17 int Font::StringWidth(const char *s) const {
18         int width(0), col(0);
19         for (int i(0); s[i]; ++i) {
20                 if (s[i] == '\n') {
21                         if (width < col) {
22                                 width = col;
23                         }
24                         col = 0;
25                 } else {
26                         ++col;
27                 }
28         }
29         return (width < col ? col : width) * CharWidth();
30 }
31
32 int Font::StringHeight(const char *s) const {
33         if (*s == '\0') {
34                 return 0;
35         }
36         int height(1);
37         for (; *s; ++s) {
38                 if (*s == '\n') {
39                         ++height;
40                 }
41         }
42         return height * CharHeight();
43 }
44
45
46 void Font::DrawChar(char c, SDL_Surface *dest, const Vector<int> &position) const {
47         if (!sprite) return;
48
49         int col(colOffset + (c % 0x10));
50         int row(rowOffset + (c / 0x10));
51         sprite->Draw(dest, position, col, row);
52 }
53
54 void Font::DrawString(const char *s, SDL_Surface *dest, const Vector<int> &positionIn, int maxWidth) const {
55         if (!sprite) return;
56
57         Vector<int> position(positionIn);
58         Vector<int> lineHead(positionIn);
59         Vector<int> step(CharWidth(), 0);
60         Vector<int> lineBreak(0, CharHeight());
61         for (int i(0), col(0); s[i] && (maxWidth <= 0 || col < maxWidth); ++i) {
62                 if (s[i] == '\n') {
63                         lineHead += lineBreak;
64                         position = lineHead;
65                         col = 0;
66                 } else {
67                         DrawChar(s[i], dest, position);
68                         position += step;
69                         ++col;
70                 }
71         }
72 }
73
74 void Font::DrawStringRight(const char *s, SDL_Surface *dest, const Vector<int> &positionIn, int maxWidth) const {
75         // NOTE: this does not handle line breaks
76         if (!sprite) return;
77
78         int length(0);
79         while (length < maxWidth && s[length] != '\0') {
80                 ++length;
81         }
82         Vector<int> position(positionIn.X() - length * CharWidth(), positionIn.Y());
83
84         DrawString(s, dest, position, length);
85 }
86
87 void Font::DrawDigit(int digit, SDL_Surface *dest, const Vector<int> &position) const {
88         if (!sprite) return;
89
90         DrawChar(digit + 0x30, dest, position);
91 }
92
93 void Font::DrawNumber(int numberIn, SDL_Surface *dest, const Vector<int> &positionIn, int digits) const {
94         if (!sprite) return;
95
96         int number(numberIn);
97         if (digits > 0 && numberIn >= pow(10.0, digits)) {
98                 numberIn = pow(10.0, digits) - 1;
99         }
100
101         Vector<int> position(positionIn);
102         Vector<int> step(sprite->Width(), 0);
103
104         if (digits > 0) {
105                 int i(digits - 1);
106                 while (number < pow(10.0, i) && i > 0) {
107                         position += step;
108                         --i;
109                 }
110         }
111
112         int m(10);
113         while (m <= number) {
114                 m *= 10;
115         }
116
117         while (m > 9) {
118                 m /= 10;
119                 DrawDigit((number / m) % 10, dest, position);
120                 position += step;
121         }
122 }
123
124 void Font::DrawNumberRight(int number, SDL_Surface *dest, const Vector<int> &positionIn, int digits) const {
125         if (!sprite) return;
126
127         Vector<int> position(positionIn.X() - digits * CharWidth(), positionIn.Y());
128
129         DrawNumber(number, dest, position, digits);
130 }
131
132
133 void Font::CreateTypeDescription() {
134         Font f;
135
136         TypeDescription &td(TypeDescription::Create(TYPE_ID, "Font"));
137         td.SetDescription(
138                         "Simple font with fixed-width characters using a sprite for rendering.\n"
139                         "Characters from strings are mapped as follows:\n"
140                         "<pre>sprite column = column offset + (character % 16)\n"
141                         "sprite row    = row    offset + (character / 16)</pre>");
142         td.SetConstructor(&Construct);
143         td.SetSize(sizeof(Font));
144
145         td.AddField("sprite", FieldDescription(((char *)&f.sprite) - ((char *)&f), Sprite::TYPE_ID).SetReferenced().SetDescription("a sprite where each tile corresponds to a character"));
146         td.AddField("columnoffset", FieldDescription(((char *)&f.colOffset) - ((char *)&f), Interpreter::NUMBER_ID).SetDescription("offset of the column of the first character"));
147         td.AddField("rowoffset", FieldDescription(((char *)&f.rowOffset) - ((char *)&f), Interpreter::NUMBER_ID).SetDescription("offset of the row of the first character"));
148 }
149
150 void Font::Construct(void *data) {
151         new (data) Font;
152 }
153
154 }