1 /* BStyles.cpp
2  * Copyright (C) 2018  Sven Jähnichen
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "BStyles.hpp"
19 
20 namespace BStyles
21 {
22 
23 /*****************************************************************************
24  * Class BStyles::Line
25  *****************************************************************************/
26 
Line()27 Line::Line () : Line (BColors::invisible, 0.0) {}
Line(const BColors::Color & color,const double width)28 Line::Line (const BColors::Color& color, const double width) : lineColor (color), lineWidth (width) {}
setColor(const BColors::Color & color)29 void Line::setColor (const BColors::Color& color) {lineColor = color;}
getColor()30 BColors::Color* Line::getColor () {return &lineColor;}
setWidth(const double width)31 void Line::setWidth (const double width) {lineWidth = width;}
getWidth() const32 double Line::getWidth () const {return lineWidth;}
33 
34 /*
35  * End of class BWidgets::Line
36  *****************************************************************************/
37 
38 
39 /*****************************************************************************
40  * Class BStyles::Border
41  *****************************************************************************/
42 
Border()43 Border::Border () : Border (noLine, 0.0, 0.0, 0.0) {}
Border(const Line & line)44 Border::Border (const Line& line) : Border (line, 0.0, 0.0, 0.0) {}
Border(const Line & line,const double margin,const double padding)45 Border::Border (const Line& line, const double margin, const double padding) : Border (line, margin, padding, 0.0) {}
Border(const Line & line,const double margin,const double padding,const double radius)46 Border::Border (const Line& line, const double margin, const double padding, const double radius) :
47 		borderLine (line), borderMargin (margin), borderPadding (padding), borderRadius (radius) {}
48 
setLine(const Line & line)49 void Border::setLine (const Line& line) {borderLine = line;}
getLine()50 Line* Border::getLine () {return &borderLine;}
setMargin(const double margin)51 void Border::setMargin (const double margin) {borderMargin = margin;}
getMargin() const52 double Border::getMargin () const {return borderMargin;}
setPadding(const double padding)53 void Border::setPadding (const double padding) {borderPadding = padding;}
getPadding() const54 double Border::getPadding () const {return borderPadding;}
setRadius(const double radius)55 void Border::setRadius (const double radius) {borderRadius = radius;}
getRadius() const56 double Border::getRadius () const {return borderRadius;}
57 
58 /*
59  * End of class BWidgets::Border
60  *****************************************************************************/
61 
62 
63 /*****************************************************************************
64  * Class BStyles::Fill
65  *****************************************************************************/
66 
Fill()67 Fill::Fill () : fillColor (BColors::invisible), fillSurface (nullptr) {}
Fill(const BColors::Color & color)68 Fill::Fill (const BColors::Color& color) : fillColor (color), fillSurface (nullptr) {}
Fill(const std::string & filename)69 Fill::Fill (const std::string& filename) : fillColor (BColors::invisible), fillSurface (nullptr)
70 {
71 	loadFillFromFile (filename);
72 }
73 
Fill(const Fill & that)74 Fill::Fill (const Fill& that)
75 {
76 	fillColor = that.fillColor;
77 	if (that.fillSurface) fillSurface = cairo_image_surface_clone_from_image_surface (that.fillSurface);
78 	else fillSurface = nullptr;
79 }
80 
operator =(const Fill & that)81 Fill& Fill::operator= (const Fill& that)
82 {
83 	if (this != &that)
84 	{
85 		fillColor = that.fillColor;
86 		if (that.fillSurface) fillSurface = cairo_image_surface_clone_from_image_surface (that.fillSurface);
87 		else fillSurface = nullptr;
88 	}
89 
90 	return *this;
91 }
92 
~Fill()93 Fill::~Fill ()
94 {
95 	if (fillSurface && (cairo_surface_status (fillSurface) == CAIRO_STATUS_SUCCESS)) cairo_surface_destroy (fillSurface);
96 }
97 
setColor(const BColors::Color & color)98 void Fill::setColor (const BColors::Color& color) {fillColor = color;}
99 
getColor()100 BColors::Color* Fill::getColor () {return &fillColor;}
101 
loadFillFromFile(const std::string & filename)102 void Fill::loadFillFromFile (const std::string& filename)
103 {
104 	if (fillSurface) cairo_surface_destroy (fillSurface);
105 	fillSurface = cairo_image_surface_create_from_png (filename.c_str());
106 }
107 
loadFillFromCairoSurface(cairo_surface_t * surface)108 void Fill::loadFillFromCairoSurface (cairo_surface_t* surface)
109 {
110 	if (fillSurface) cairo_surface_destroy (fillSurface);
111 	fillSurface = cairo_image_surface_clone_from_image_surface (surface);
112 }
113 
getCairoSurface()114 cairo_surface_t* Fill::getCairoSurface () {return fillSurface;}
115 
116 /*
117  * End of class BWidgets::Fill
118  *****************************************************************************/
119 
120 
121 /*****************************************************************************
122  * Class BStyles::Font
123  *****************************************************************************/
124 
Font()125 Font::Font () : Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 12.0) {}
Font(const std::string & family,const cairo_font_slant_t slant,const cairo_font_weight_t weight,const double size,TextAlign align,TextVAlign valign,double lineSpacing)126 Font::Font (const std::string& family, const cairo_font_slant_t slant, const cairo_font_weight_t weight, const double size,
127 			TextAlign align, TextVAlign valign, double lineSpacing)
128 	: fontFamily (family), fontSlant (slant), fontWeight (weight), fontSize (size),
129 	  textAlign (align), textVAlign (valign), textLineSpacing (lineSpacing) {}
130 
setFontFamily(const std::string & family)131 void Font::setFontFamily (const std::string& family) {fontFamily = family;}
getFontFamily() const132 std::string Font::getFontFamily () const {return fontFamily;}
setFontSlant(const cairo_font_slant_t slant)133 void Font::setFontSlant (const cairo_font_slant_t slant) {fontSlant = slant;}
getFontSlant() const134 cairo_font_slant_t Font::getFontSlant () const {return fontSlant;}
setFontWeight(const cairo_font_weight_t weight)135 void Font::setFontWeight (const cairo_font_weight_t weight) {fontWeight = weight;}
getFontWeight() const136 cairo_font_weight_t Font::getFontWeight () const {return fontWeight;}
setTextAlign(const TextAlign align)137 void Font::setTextAlign (const TextAlign align) {textAlign = align;}
getTextAlign() const138 TextAlign Font::getTextAlign () const {return textAlign;}
setTextVAlign(const TextVAlign valign)139 void Font::setTextVAlign (const TextVAlign valign) {textVAlign = valign;}
getTextVAlign() const140 TextVAlign Font::getTextVAlign () const {return textVAlign;}
setLineSpacing(const double lineSpacing)141 void Font::setLineSpacing (const double lineSpacing) {textLineSpacing = lineSpacing;}
getLineSpacing() const142 double Font::getLineSpacing () const {return textLineSpacing;}
setFontSize(const double size)143 void Font::setFontSize (const double size) {fontSize = size;}
getFontSize() const144 double Font::getFontSize () const {return fontSize;}
145 
getTextExtents(cairo_t * cr,const std::string & text) const146 cairo_text_extents_t Font::getTextExtents (cairo_t* cr, const std::string& text) const
147 {
148 	if (cr && (! cairo_status (cr)))
149 	{
150 		cairo_save (cr);
151 
152 		cairo_text_extents_t ext;
153 		cairo_select_font_face (cr, fontFamily.c_str (), fontSlant, fontWeight);
154 		cairo_set_font_size (cr, fontSize);
155 		cairo_text_extents (cr, text.c_str(), &ext);
156 
157 		cairo_restore (cr);
158 		return ext;
159 	}
160 	else
161 	{
162 		return {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
163 	}
164 }
165 
166 /*
167  * End of class BWidgets::Font
168  *****************************************************************************/
169 
170 
171 /*****************************************************************************
172  * Class BStyles::StyleSet
173  *****************************************************************************/
174 
StyleSet()175 StyleSet::StyleSet () {}
StyleSet(const std::string & name,const std::vector<Style> & styles)176 StyleSet::StyleSet (const std::string& name, const std::vector<Style>& styles) : stylesetName (name), styleVector (styles) {}
177 
addStyle(const std::string & styleName,void * ptr)178 void StyleSet::addStyle (const std::string& styleName, void* ptr)
179 {
180 	for (Style style : styleVector)
181 	{
182 		if (style.name == styleName)
183 		{
184 			// Overwrite existing style
185 			std::cerr << "Msg from BStyles::StyleSet::addStyle(): Overwrite existing " << stylesetName << "/" << styleName
186 					  << "." << std:: endl;
187 			style.stylePtr = ptr;
188 			return;
189 		}
190 	}
191 
192 	// No hit for styleName? Append style to existing styleset
193 	Style newStyle = {styleName, ptr};
194 	styleVector.push_back (newStyle);
195 	return;
196 }
197 
removeStyle(const std::string & styleName)198 void StyleSet::removeStyle (const std::string& styleName)
199 {
200 	for (std::vector<Style>::iterator it = styleVector.begin (); it !=styleVector.end (); ++it)
201 	{
202 		if (it->name == styleName) // @suppress("Field cannot be resolved")
203 		{
204 			// Delete existing style
205 			styleVector.erase (it);
206 			return;
207 		}
208 	}
209 
210 	// No hit?
211 	std::cerr << "Msg from BStyles::StyleSet::removeStyle(): " << stylesetName << "/" << styleName
212 			  << " doesn't exist. Nothing to delete." << std:: endl;
213 	return;
214 }
215 
getStyle(const std::string & styleName)216 void* StyleSet::getStyle (const std::string& styleName)
217 {
218 	void* ptr = nullptr;
219 	for (Style style : styleVector)
220 	{
221 		if (style.name == "uses")
222 		{
223 			StyleSet* usedSet = (StyleSet*) style.stylePtr;
224 			ptr = usedSet->getStyle (styleName);
225 
226 		}
227 		if (style.name == styleName)
228 		{
229 			return ptr = style.stylePtr;
230 		}
231 	}
232 
233 	// No hit?
234 	// if (!ptr) std::cerr << "Msg from BStyles::StyleSet::getStyle(): " << stylesetName << "/" << styleName << " doesn't exist." << std:: endl;
235 	return ptr;
236 }
237 
setName(const std::string & name)238 void StyleSet::setName (const std::string& name) {stylesetName = name;}
getName() const239 std::string StyleSet::getName () const {return stylesetName;}
240 
241 /*
242  * End of class BWidgets::StyleSet
243  *****************************************************************************/
244 
245 /*****************************************************************************
246  * Class BStyles::Theme
247  *****************************************************************************/
248 
Theme()249 Theme::Theme () {};
Theme(const std::vector<StyleSet> & theme)250 Theme::Theme (const std::vector<StyleSet>& theme): stylesetVector (theme) {};
251 
addStyle(const std::string & setName,const std::string & styleName,void * ptr)252 void Theme::addStyle (const std::string& setName, const std::string& styleName, void* ptr)
253 {
254 	for (StyleSet styleSet : stylesetVector)
255 	{
256 		if (styleSet.getName () == setName)
257 		{
258 			styleSet.addStyle (styleName, ptr);
259 			return;
260 		}
261 	}
262 
263 	// No hit for styleset? Append styleset to existing theme
264 	StyleSet newSet = {setName, {{styleName, ptr}}};
265 	stylesetVector.push_back (newSet);
266 }
267 
removeStyle(const std::string & setName,const std::string & styleName)268 void Theme::removeStyle (const std::string& setName, const std::string& styleName)
269 {
270 	for (StyleSet styleSet : stylesetVector)
271 	{
272 		if (styleSet.getName () == setName)
273 		{
274 			styleSet.removeStyle (styleName);
275 			return;
276 		}
277 	}
278 
279 	// No hit?
280 	// std::cerr << "Msg from BStyles::Theme::removeStyle(): " << setName << "/" << styleName
281 	//		     << " doesn't exist. Nothing to delete." << std:: endl;
282 	return;
283 }
284 
getStyle(const std::string & setName,const std::string & styleName)285 void* Theme::getStyle (const std::string& setName, const std::string& styleName)
286 {
287 	for (StyleSet styleSet : stylesetVector)
288 	{
289 		if (styleSet.getName () == setName)
290 		{
291 			return styleSet.getStyle (styleName);
292 		}
293 	}
294 
295 	// No hit?
296 	// std::cerr << "Msg from BStyles::Theme::getStyle(): " << setName << "/" << styleName
297 	// 		     << " doesn't exist." << std:: endl;
298 	return nullptr;
299 }
300 
301 /*
302  * End of class BWidgets::Theme
303  *****************************************************************************/
304 
305 
306 }
307