version bump
[blackbox.git] / lib / Texture.cc
blobfb5a06b8b6f3e3d7641b3dda666b0bf6225354f6
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // Texture.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
25 #include "Texture.hh"
26 #include "Display.hh"
27 #include "Pen.hh"
28 #include "Resource.hh"
30 #include <algorithm>
32 #include <X11/Xlib.h>
33 #include <ctype.h>
36 void bt::Texture::setColor1(const bt::Color &new_color) {
37 c1 = new_color;
39 unsigned char r, g, b, rr, gg, bb;
40 r = c1.red();
41 g = c1.green();
42 b = c1.blue();
44 // calculate the light color
45 rr = r + (r >> 1);
46 gg = g + (g >> 1);
47 bb = b + (b >> 1);
48 if (rr < r)
49 rr = ~0;
50 if (gg < g)
51 gg = ~0;
52 if (bb < b)
53 bb = ~0;
54 lc.setRGB(rr, gg, bb);
56 // calculate the shadow color
57 rr = (r >> 2) + (r >> 1);
58 gg = (g >> 2) + (g >> 1);
59 bb = (b >> 2) + (b >> 1);
60 if (rr > r)
61 rr = 0;
62 if (gg > g)
63 gg = 0;
64 if (bb > b)
65 bb = 0;
66 sc.setRGB(rr, gg, bb);
70 void bt::Texture::setDescription(const std::string &d) {
71 descr = tolower(d);
72 if (descr.find("parentrelative") != std::string::npos) {
73 setTexture(bt::Texture::Parent_Relative);
74 } else {
75 setTexture(0);
77 if (descr.find("gradient") != std::string::npos) {
78 addTexture(bt::Texture::Gradient);
79 if (descr.find("crossdiagonal") != std::string::npos)
80 addTexture(bt::Texture::CrossDiagonal);
81 else if (descr.find("rectangle") != std::string::npos)
82 addTexture(bt::Texture::Rectangle);
83 else if (descr.find("pyramid") != std::string::npos)
84 addTexture(bt::Texture::Pyramid);
85 else if (descr.find("pipecross") != std::string::npos)
86 addTexture(bt::Texture::PipeCross);
87 else if (descr.find("elliptic") != std::string::npos)
88 addTexture(bt::Texture::Elliptic);
89 else if (descr.find("horizontal") != std::string::npos)
90 addTexture(bt::Texture::Horizontal);
91 else if (descr.find("vertical") != std::string::npos)
92 addTexture(bt::Texture::Vertical);
93 else
94 addTexture(bt::Texture::Diagonal);
95 } else {
96 addTexture(bt::Texture::Solid);
99 if (descr.find("sunken") != std::string::npos)
100 addTexture(bt::Texture::Sunken);
101 else if (descr.find("flat") != std::string::npos)
102 addTexture(bt::Texture::Flat);
103 else
104 addTexture(bt::Texture::Raised);
106 if (descr.find("interlaced") != std::string::npos)
107 addTexture(bt::Texture::Interlaced);
109 if (descr.find("border") != std::string::npos)
110 addTexture(bt::Texture::Border);
115 bt::Texture& bt::Texture::operator=(const bt::Texture &tt) {
116 descr = tt.descr;
118 c1 = tt.c1;
119 c2 = tt.c2;
120 bc = tt.bc;
121 lc = tt.lc;
122 sc = tt.sc;
123 t = tt.t;
124 bw = tt.bw;
126 return *this;
130 bt::Texture bt::textureResource(const Display &display,
131 unsigned int screen,
132 const bt::Resource &resource,
133 const std::string &name,
134 const std::string &className,
135 const std::string &defaultColor)
137 Texture texture;
139 std::string description = resource.read(name + ".appearance",
140 className + ".Appearance",
141 resource.read(name,
142 className));
143 if (description.empty()) {
144 // no such texture, use the default color in a flat solid texture
145 texture.setDescription("flat solid");
146 texture.setColor1(Color::namedColor(display, screen, defaultColor));
147 return texture;
150 texture.setDescription(description);
152 if ((texture.texture() & bt::Texture::Gradient)
153 || (texture.texture() & bt::Texture::Interlaced)) {
154 std::string color1, color2;
155 color1 = resource.read(name + ".color1",
156 className + ".Color1",
157 resource.read(name + ".color",
158 className + ".Color",
159 defaultColor));
160 color2 = resource.read(name + ".color2",
161 className + ".Color2",
162 resource.read(name + ".colorTo",
163 className + ".ColorTo",
164 defaultColor));
165 texture.setColor1(Color::namedColor(display, screen, color1));
166 texture.setColor2(Color::namedColor(display, screen, color2));
167 } else {
168 std::string color1;
169 color1 = resource.read(name + ".backgroundColor",
170 className + ".BackgroundColor",
171 resource.read(name + ".color",
172 className + ".Color",
173 defaultColor));
174 texture.setColor1(Color::namedColor(display, screen, color1));
177 if (texture.texture() & bt::Texture::Border) {
178 Color borderColor =
179 Color::namedColor(display, screen,
180 resource.read(name + ".borderColor",
181 className + ".BorderColor",
182 "black"));
183 texture.setBorderColor(borderColor);
185 const std::string bstr =
186 resource.read(name + ".borderWidth", className + ".BorderWidth", "1");
187 unsigned int bw = static_cast<unsigned int>(strtoul(bstr.c_str(), 0, 0));
188 texture.setBorderWidth(bw);
191 return texture;
195 bt::Texture bt::textureResource(const Display &display,
196 unsigned int screen,
197 const Resource &resource,
198 const std::string &name,
199 const std::string &className,
200 const Texture &defaultTexture)
202 std::string description = resource.read(name + ".appearance",
203 className + ".Appearance",
204 resource.read(name,
205 className));
206 if (description.empty()) {
207 // no such texture, return the default
208 return defaultTexture;
210 return textureResource(display, screen, resource, name, className);
214 void bt::drawTexture(unsigned int screen,
215 const Texture &texture,
216 Drawable drawable,
217 const Rect &trect,
218 const Rect &urect,
219 Pixmap pixmap) {
220 Pen pen(screen, texture.color1());
222 if ((texture.texture() & Texture::Gradient) && pixmap) {
223 XCopyArea(pen.XDisplay(), pixmap, drawable, pen.gc(),
224 urect.x() - trect.x(), urect.y() - trect.y(),
225 urect.width(), urect.height(), urect.x(), urect.y());
226 return;
227 } else if (!(texture.texture() & Texture::Solid)) {
228 XClearArea(pen.XDisplay(), drawable,
229 urect.x(), urect.y(), urect.width(), urect.height(), False);
230 return; // might be Parent_Relative or empty
233 XFillRectangle(pen.XDisplay(), drawable, pen.gc(),
234 urect.x(), urect.y(), urect.width(), urect.height());
236 int bw = static_cast<int>(texture.borderWidth());
237 if (texture.texture() & bt::Texture::Border &&
238 (trect.left() == urect.left() || trect.right() == urect.right() ||
239 trect.top() == urect.top() || trect.bottom() == urect.bottom())) {
240 Pen penborder(screen, texture.borderColor());
241 penborder.setLineWidth(bw);
242 XDrawRectangle(pen.XDisplay(), drawable, penborder.gc(),
243 trect.x() + bw / 2, trect.y() + bw / 2,
244 trect.width() - bw, trect.height() - bw);
247 if (texture.texture() & bt::Texture::Interlaced) {
248 Pen peninterlace(screen, texture.color2());
249 int begin = trect.top() + bw;
250 while (begin < urect.top()) begin += 2;
251 int end = std::min(trect.bottom() - bw, urect.bottom());
253 for (int i = begin; i <= end; i += 2)
254 XDrawLine(pen.XDisplay(), drawable, peninterlace.gc(),
255 std::max(trect.left() + bw, urect.left()), i,
256 std::min(trect.right() - bw, urect.right()), i);
259 if ((trect.left() + bw >= urect.left() ||
260 trect.right() - bw <= urect.right() ||
261 trect.top() + bw >= urect.top() ||
262 trect.bottom() - bw <= urect.bottom())) {
263 // draw bevel
264 Pen penlight(screen, texture.lightColor());
265 Pen penshadow(screen, texture.shadowColor());
267 if (texture.texture() & bt::Texture::Raised) {
268 XDrawLine(pen.XDisplay(), drawable, penshadow.gc(),
269 trect.left() + bw, trect.bottom() - bw,
270 trect.right() - bw, trect.bottom() - bw);
271 XDrawLine(pen.XDisplay(), drawable, penshadow.gc(),
272 trect.right() - bw, trect.bottom() - bw,
273 trect.right() - bw, trect.top() + bw);
275 XDrawLine(pen.XDisplay(), drawable, penlight.gc(),
276 trect.left() + bw, trect.top() + bw,
277 trect.right() - bw, trect.top() + bw);
278 XDrawLine(pen.XDisplay(), drawable, penlight.gc(),
279 trect.left() + bw, trect.bottom() - bw,
280 trect.left() + bw, trect.top() + bw);
281 } else if (texture.texture() & bt::Texture::Sunken) {
282 XDrawLine(pen.XDisplay(), drawable, penlight.gc(),
283 trect.left() + bw, trect.bottom() - bw,
284 trect.right() - bw, trect.bottom() - bw);
285 XDrawLine(pen.XDisplay(), drawable, penlight.gc(),
286 trect.right() - bw, trect.bottom() - bw,
287 trect.right() - bw, trect.top() + bw);
289 XDrawLine(pen.XDisplay(), drawable, penshadow.gc(),
290 trect.left() + bw, trect.top() + bw,
291 trect.right() - bw, trect.top() + bw);
292 XDrawLine(pen.XDisplay(), drawable, penshadow.gc(),
293 trect.left() + bw, trect.bottom() - bw,
294 trect.left() + bw, trect.top() + bw);