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