]> git.lyx.org Git - lyx.git/blob - src/ColorHandler.C
Remove debug message
[lyx.git] / src / ColorHandler.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  * 
5  *           LyX, The Document Processor
6  *       
7  *          Copyright 1998-2000 The LyX Team
8  *
9  *======================================================*/
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include <cmath>
18
19 #include FORMS_H_LOCATION
20 #include "debug.h"
21
22 #include "ColorHandler.h"
23 #include "LColor.h"
24 #include "gettext.h"
25
26 using std::endl;
27
28 LyXColorHandler::LyXColorHandler() 
29 {
30         display = fl_get_display();
31         drawable = XCreatePixmap(display, fl_root, 10, 10,
32                                  fl_get_visual_depth());
33         
34         colormap = fl_state[fl_get_vclass()].colormap;
35         // Clear the GC cache
36         for (int i = 0; i <= LColor::ignore; ++i) {
37                 colorGCcache[i] = 0;
38         }
39 }
40
41
42 LyXColorHandler::~LyXColorHandler()
43 {
44         // Release all the registered GCs
45         for (int i = 0; i <= LColor::ignore; ++i) {
46                 if (colorGCcache[i] != 0) {
47                         XFreeGC(display, colorGCcache[i]);
48                 }
49         }
50         // Iterate over the line cache and Free the GCs
51         for (LineGCCache::iterator lit = lineGCcache.begin();
52              lit != lineGCcache.end(); ++lit) {
53                 XFreeGC(display, (*lit).second);
54         }
55 }
56
57
58 unsigned long LyXColorHandler::colorPixel(LColor::color c)
59 {
60         XGCValues val;
61         XGetGCValues(display, getGCForeground(c), GCForeground, &val);
62         return val.foreground;
63 }
64
65
66 // Gets GC according to color
67 // Uses caching
68 GC LyXColorHandler::getGCForeground(LColor::color c)
69 {
70         //if (lyxerr.debugging()) {
71         //      lyxerr << "Painter drawable: " << drawable() << endl;
72         //}
73         
74         if (colorGCcache[c] != 0) return colorGCcache[c];
75
76         XColor xcol, ccol;
77         string s = lcolor.getX11Name(c);
78         XGCValues val;
79
80         // Look up the RGB values for the color, and an approximate
81         // color that we can hope to get on this display.
82         if (XLookupColor(display, colormap, s.c_str(), &xcol, &ccol) == 0) {
83                 lyxerr << _("LyX: Unknown X11 color ") << s
84                        << _(" for ") << lcolor.getGUIName(c) << '\n'
85                        << _("     Using black instead, sorry!.") << endl;
86                 unsigned long bla = BlackPixel(display,
87                                                DefaultScreen(display));
88                 val.foreground = bla;
89         // Try the exact RGB values first, then the approximate.
90         } else if (XAllocColor(display, colormap, &xcol) != 0) {
91                 if (lyxerr.debugging()) {
92                         lyxerr << _("LyX: X11 color ") << s
93                                << _(" allocated for ") 
94                                << lcolor.getGUIName(c) << endl;
95                 }
96                 val.foreground = xcol.pixel;
97         } else if (XAllocColor(display, colormap, &ccol)) {
98                 lyxerr << _("LyX: Using approximated X11 color ") << s
99                        << _(" allocated for ")
100                        << lcolor.getGUIName(c) << endl;
101                 val.foreground = xcol.pixel;
102         } else {
103                 // Here we are traversing the current colormap to find
104                 // the color closest to the one we want.
105                 Visual * vi = DefaultVisual(display, DefaultScreen(display));
106
107                 XColor * cmap = new XColor[vi->map_entries];
108
109                 for (int i = 0; i < vi->map_entries; ++i) {
110                         cmap[i].pixel = i;
111                 }
112                 XQueryColors(display, colormap, cmap, vi->map_entries);
113
114                 // Walk through the cmap and look for close colors.
115                 int closest_pixel = 0;
116                 double closest_distance = 1e20; // we want to minimize this
117                 double distance = 0;
118                 for (int t = 0; t < vi->map_entries; ++t) {
119                         // The Euclidean distance between two points in 
120                         // a three-dimensional space, the RGB color-cube,
121                         // is used as the distance measurement between two
122                         // colors.
123
124                         // Since square-root is monotonous, we don't have to
125                         // take the square-root to find the minimum, and thus 
126                         // we use the squared distance instead to be faster.
127
128                         // If we want to get fancy, we could convert the RGB
129                         // coordinates to a different color-cube, maybe HSV,
130                         // but the RGB cube seems to work great.  (Asger)
131                         distance = pow(cmap[t].red   - xcol.red,   2.0) +
132                                    pow(cmap[t].green - xcol.green, 2.0) +
133                                    pow(cmap[t].blue  - xcol.blue,  2.0);
134                         if (distance < closest_distance) {
135                                 closest_distance = distance;
136                                 closest_pixel = t;
137                         }
138                 }
139                 lyxerr << _("LyX: Couldn't allocate '") << s 
140                        << _("' for ") << lcolor.getGUIName(c)
141                        << _(" with (r,g,b)=(") 
142                        << xcol.red << "," << xcol.green << ","
143                        << xcol.blue << ").\n"
144                        << _("     Using closest allocated "
145                             "color with (r,g,b)=(") 
146                        << cmap[closest_pixel].red << ","
147                        << cmap[closest_pixel].green << ","
148                        << cmap[closest_pixel].blue << _(") instead.\n")
149                        << _("Pixel [") << closest_pixel << _("] is used.") 
150                        << endl;
151                 val.foreground = cmap[closest_pixel].pixel;
152                 delete[] cmap;
153         }
154
155         val.function = GXcopy;
156         return colorGCcache[c] = XCreateGC(display, drawable,
157                                     GCForeground | GCFunction, &val);
158 }
159
160
161 // Gets GC for line
162 GC LyXColorHandler::getGCLinepars(PainterBase::line_style ls,
163                           PainterBase::line_width lw, LColor::color c)
164 {
165         //if (lyxerr.debugging()) {
166         //      lyxerr << "Painter drawable: " << drawable() << endl;
167         //}
168         
169         int index = lw + (ls << 1) + (c << 3);
170
171         if (lineGCcache.find(index) != lineGCcache.end())
172                 return lineGCcache[index];
173
174         XGCValues val;
175         XGetGCValues(display, getGCForeground(c), GCForeground, &val);
176         
177         switch (lw) {
178         case PainterBase::line_thin:    val.line_width = 0; break;
179         case PainterBase::line_thick:   val.line_width = 2; break;
180         }
181         
182         switch (ls) {
183         case PainterBase::line_solid:   val.line_style = LineSolid; break;
184         case PainterBase::line_onoffdash:       val.line_style = LineOnOffDash; break;
185         case PainterBase::line_doubledash:      val.line_style = LineDoubleDash; break;
186         }
187
188
189         val.cap_style = CapRound;
190         val.join_style = JoinRound;
191         val.function = GXcopy;
192
193         return lineGCcache[index] =
194                 XCreateGC(display, drawable, 
195                           GCForeground | GCLineStyle | GCLineWidth | 
196                           GCCapStyle | GCJoinStyle | GCFunction, &val);
197 }
198
199
200 // update GC cache after color redefinition
201 void LyXColorHandler::updateColor (LColor::color c)
202 {
203         // color GC cache
204         GC gc = colorGCcache[c];
205         if (gc != NULL) {
206                 XFreeGC(display, gc);
207                 colorGCcache[c] = NULL;
208                 getGCForeground(c);
209         }
210
211         // line GC cache
212
213         int index, ls, lw;
214         for (ls=0; ls<3; ++ls)
215                 for (lw=0; lw<2; ++lw) {
216                         index = lw + (ls << 1) + (c << 3);
217                         if (lineGCcache.find(index) != lineGCcache.end()) {
218                                 gc = lineGCcache[index];
219                                 XFreeGC(display,gc);
220                                 lineGCcache.erase(index);
221                                 getGCLinepars(PainterBase::line_style(ls),
222                                                 PainterBase::line_width(lw), c);
223                         }
224                 }
225  
226 }
227
228 //
229 boost::scoped_ptr<LyXColorHandler> lyxColorHandler;