/
symbolChooser.h
204 lines (194 loc) · 8.14 KB
/
symbolChooser.h
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
195
196
197
198
199
200
201
202
203
204
//
// Copyright 2010, 2011 Tom Klein.
//
// This file is part of cstitch.
//
// cstitch is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef SYMBOLCHOOSER_H
#define SYMBOLCHOOSER_H
#include <QFont>
#include "triC.h"
#include "stepIndex.h"
#include "imageUtility.h"
extern const int MAX_NUM_SYMBOL_TYPES;
//
// symbolChooser makes the initial choice of the color->symbol
// correspondence for a user-supplied list of colors (symbolChooser
// holds the color list, which cannot be changed).
//
// Each symbol is made up of a symbol pixmap, a border (always
// specified by the width of the border, not of the symbol plus its
// border), and a numerical index that can be used to identify a
// particular image (cf. patternSymbolIndex, which is used to pass
// around symbols). symbolChooser will initially generate all symbols
// at a base dimension and border; after the initial construction the
// user can either request symbols with a new overall icon size with
// the default border width or symbols with no border and a specified
// size.
//
//// Implementation notes
//
// The (const) color list is provided at construction, at which time
// we also make the initial choice of color-->symbol associations,
// since we want that initial association to always be the same for a
// given list of colors.
//
// Image creation: Symbols come from a predefined list of unicode
// characters; the actual number of symbols available will depend on
// which of those symbols is actually available for the given font on
// the given computer in use (but should always include at least a
// subset of the standard ascii characters). Each unicode symbol can
// be paired with up to four different distinct outlines. The
// outlines used depend on the number of symbols required: the actual
// number of symbols available will be at least the number required
// for the given colors, but not necessarily all symbols that could be
// created.
//
// Each time the user requests a symbol that doesn't already exist for
// the requested color with the given dimension and border, a new
// symbol is added to the symbolMap_. In other words, only one
// version of a symbol is ever stored at a time, and there may be
// multiple combinations of size/border stored in the symbol map at
// any given time.
//
class symbolChooser {
public:
// <symbolDimension> is the overall size of the final symbol,
// <borderDim> is the width of the border, <colors> are the colors to
// create symbols for
symbolChooser(int symbolDimension, const QVector<triC>& colors,
int borderDim = 4);
// run through a predefined list of unicode characters to determine
// which are defined in the current system font and save the list to
// unicodeCharacters_
static void initializeSymbolList();
// set the current symbolDimension_, used as the default for all
// subsequent requests for symbols
void setSymbolDimension(int dimension);
// return the symbol for <color> with total size <symbolDim> and no
// border
patternSymbolIndex getSymbolNoBorder(const triC& color, int symbolDim) {
int savedBorderDim = borderDimension_;
borderDimension_ = 0;
patternSymbolIndex returnIndex(getSymbol(color, symbolDim));
borderDimension_ = savedBorderDim;
return returnIndex;
}
// return the index for <color> if it exists, else return -1
int colorIndex(const triC& color) const {
const QHash<QRgb, patternSymbolIndex>::const_iterator it =
symbolMap_.find(color.qrgb());
if (it != symbolMap_.end()) {
return it.value().index();
}
else {
return -1;
}
}
// return the symbol for <color> with total size <symbolDim> and the
// current borderDimension_
patternSymbolIndex getSymbol(const triC& color, int symbolDim);
// return the symbol for <color> using the current symbolSize_ and
// borderDimension_
patternSymbolIndex getSymbolCurDim(const triC& color) {
return getSymbol(color, symbolDimension_);
}
// return a hash of symbols for all colors, using total symbol size <symbolDim>
// and border size <colorBorderWidth>
QHash<QRgb, QPixmap> getSymbolsWithBorder(int symbolDim, int colorBorderWidth) {
int savedBorderDim = borderDimension_;
borderDimension_ = colorBorderWidth;
QHash<QRgb, QPixmap> returnHash(getSymbols(symbolDim));
borderDimension_ = savedBorderDim;
return returnHash;
}
// return a hash of symbols for all colors with total size <symbolDim> and
// the current borderDimension_
QHash<QRgb, QPixmap> getSymbols(int symbolDim);
// return a hash of symbols for all colors using the current
// symbolDimension_ and borderDimension_
QHash<QRgb, QPixmap> getSymbolsCurDim() { return getSymbols(symbolDimension_); }
// remove the old symbol map entry for <color> and insert a new symbol
// for <color> with symbol <newIndex>
// returns true if the switch was sucessful
bool changeSymbol(const triC& color, int newIndex);
// return a list of all in play symbols that aren't currently assigned
// to a color
QVector<patternSymbolIndex>
symbolsAvailable(const triC& symbolBackgroundColor, int symbolDim);
// return the total number of possible symbols at our disposal
static int maxNumberOfSymbols() {
initializeSymbolList();
return MAX_NUM_SYMBOL_TYPES * unicodeCharacters_.size();
}
// return a sample symbol of size <symbolSize> using the symbol font
static QPixmap getSampleSymbol(int symbolSize);
private:
// return the next available index;
// returns numberOfSymbols() if all indices have been used
int getNewIndex() { return colorIndex_.next(); }
// MUST only be called if <color> has not yet been assigned a symbol
patternSymbolIndex createNewSymbolCurDims(QRgb color);
// create and return the symbol for index <index> using the current
// symbolDim and borderDim and <color> for the background if there's a
// border; doesn't update symbolMap_
QPixmap createSymbol(int index,
const triC& color = triC(255, 255, 255)) const;
// draw the background pixmap for the different types of symbols
// (type1 is "plain")
void createSymbolType2(QPainter* painter, int drawDim) const;
void createSymbolType3(QPainter* painter, int drawDim) const;
void createSymbolType4(QPainter* painter, int drawDim) const;
// return the total number of possible symbols
int numberOfSymbols() const {
return unicodeCharacters_.size() * numSymbolTypes_;
}
// [In Qt 4.something unicodeFont_ was a static QFont with no
// problems, but in QT5.2, initializing the static unicodeFont_
// prior to creation of the application window causes sigfault, so
// here we are.]
class cheapFont {
public:
cheapFont() : family_(""), pointSize_(-1), weight_(-1) {}
void setFont(const QFont& f) {
family_ = f.family();
pointSize_ = f.pointSize();
weight_ = f.weight();
}
QFont qFont() {
return QFont(family_, pointSize_, weight_, false);
}
private:
QString family_;
int pointSize_;
int weight_;
};
private:
// the unicode characters to be used as symbols
static QVector<QChar> unicodeCharacters_;
// the font we're using for symbols (chosen for max # of symbols)
static cheapFont unicodeFont_;
// the total number of symbol types we're using (with light and dark
// types counted separately)
int numSymbolTypes_;
QVector<triC> colors_;
// the most recently created symbols for the hash's color keys
QHash<QRgb, patternSymbolIndex> symbolMap_;
stepIndex colorIndex_; // available symbol indices
int symbolDimension_; // size of the symbols (with border)
// size of a border around the symbol (0 means no border)
int borderDimension_;
};
#endif