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