-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGlyphMap.cpp
More file actions
197 lines (168 loc) · 4.33 KB
/
Copy pathGlyphMap.cpp
File metadata and controls
197 lines (168 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//
// GlyphMap.cpp
// xwall
//
// Created by Tim Medcalf on 19/04/2011.
// Copyright 2011 ErgoThis Ltd. All rights reserved.
//
#include "GlyphMap.h"
#include "Global.h"
#include "Rect.h"
GlyphMap::GlyphMap(string glyph) : _glyph(glyph)
{
scan_glyph();
rects = new vector<Rect*>;
create_rects();
}
GlyphMap::~GlyphMap()
{
for(vector<Rect*>::iterator itG = rects->begin(); itG < rects->end(); itG++)
{
delete *itG;
}
delete rects;
}
void GlyphMap::set(int x, int y)
{
if ((x >= settings.glyph_map_width) || (y >= settings.glyph_map_height))
{
cout << "Error - invalid coordinates sent to glyphmap" << endl;
exit(EXIT_FAILURE);
}
bits[x + (settings.glyph_map_width * y)] = 1;
}
void GlyphMap::clear(int x,int y)
{
if ((x >= settings.glyph_map_width) || (y >= settings.glyph_map_height))
{
cout << "Error - invalid coordinates sent to glyphmap" << endl;
exit(EXIT_FAILURE);
}
bits[x + (settings.glyph_map_width * y)] = 0;
}
bool GlyphMap::val(int x, int y)
{
if ((x >= settings.glyph_map_width) || (y >= settings.glyph_map_height))
{
cout << "Error - invalid coordinates sent to glyphmap" << endl;
exit(EXIT_FAILURE);
}
return bits[x + (settings.glyph_map_width * y)];
}
int GlyphMap::width()
{
return settings.glyph_map_width;
}
int GlyphMap::height()
{
return settings.glyph_map_height;
}
void GlyphMap::scan_glyph()
{
//create the cairo surfaces
cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0,0);
cairo_t *cr = cairo_create(surface);
cairo_select_font_face (cr, settings.font.c_str(), settings.font_style, settings.font_weight);
cairo_set_font_size(cr,settings.font_size);
cairo_text_extents(cr,_glyph.c_str(),&_letter_te);
//draw the letter so its top left is at 0,0
cairo_move_to(cr,0 - _letter_te.x_bearing, 0 -_letter_te.y_bearing);
cairo_text_path(cr,_glyph.c_str());
//work out the values to map the mapping to pixel dimensions
double xmodifier = _letter_te.width / (double) width();
double ymodifier = _letter_te.height / (double) height();
//loop through the map's columns and rows
for (int mapX = 0; mapX < width(); mapX++)
{
for (int mapY = 0; mapY < height(); mapY++)
{
//now we need to loop through all the pixels that this area maps to to check if there's anything "active" in this box
for (double pixelX = (mapX * xmodifier); pixelX < ((mapX + 1) * xmodifier); pixelX++)
{
for (double pixelY = (mapY * ymodifier); pixelY < ((mapY + 1) * ymodifier); pixelY++)
{
if (cairo_in_fill(cr, pixelX, pixelY))
{
set(mapX,mapY);
break;
}
}
if (val(mapX,mapY)) break;
}
}
}
cairo_destroy(cr);
cairo_surface_destroy(surface);
//test_output();
}
//scan down the
void GlyphMap::create_rects()
{
bool clear = false;
while (!clear)
{
clear = true;
for (int x = 0; x < width(); x++)
{
for (int y = 0; y < height(); y++)
{
if (val(x,y))
{
clear = false;
scan_rect(x,y);
}
}
}
}
}
void GlyphMap::scan_rect(int start_x, int start_y)
{
if (!val(start_x,start_y)) return;
int tl_x = start_x;
int tl_y = start_y;
int br_x = start_x;
int br_y = start_y;
//can we go lower?
while ( (br_y < (height()-1)) && (val(br_x,br_y +1))) br_y++;
//so we've got the lowest point we can go downwards
//now, can we go wider?
bool valid = true;
while ((br_x < (width()-1)) && valid)
{
for (int tmpy = tl_y; tmpy <= br_y; tmpy++)
{
if (!val(br_x+1,tmpy))
{
valid = false;
break;
}
}
if (valid) br_x++;
}
//okay now we should have width and height of a rect...
//lets create a Rect object to store it
Rect *newRect = new Rect((tl_x)*10,(tl_y)*10, ((br_x - tl_x) + 1) * 10, ((br_y - tl_y) + 1) * 10,false,0);
rects->push_back(newRect);
//now lets clear the rects in this section
for (int i = tl_x; i<= br_x; i++)
{
for (int j = tl_y; j<= br_y; j++)
{
clear(i, j);
}
}
//test_output();
}
void GlyphMap::test_output()
{
cout << endl;
cout << _glyph.c_str() << endl;
for (int row = 0; row < height(); row++)
{
for (int col = 0; col < width(); col++)
{
val(col,row) ? cout << "*" : cout << " ";
}
cout << endl;
}
}