2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1998-2000 The LyX Team
9 *======================================================*/
14 #pragma implementation
19 #include FORMS_H_LOCATION
22 #include "ColorHandler.h"
27 LyXColorHandler::LyXColorHandler()
30 drawable = XCreatePixmap(display, fl_root, 10, 10,
31 fl_get_visual_depth());
33 colormap = fl_state[fl_get_vclass()].colormap;
35 for (int i = 0; i <= LColor::ignore; ++i) {
41 LyXColorHandler::~LyXColorHandler()
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]);
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);
57 unsigned long LyXColorHandler::colorPixel(LColor::color c)
60 XGetGCValues(display, getGCForeground(c), GCForeground, &val);
61 return val.foreground;
65 // Gets GC according to color
67 GC LyXColorHandler::getGCForeground(LColor::color c)
69 //if (lyxerr.debugging()) {
70 // lyxerr << "Painter drawable: " << drawable() << endl;
73 if (colorGCcache[c] != 0) return colorGCcache[c];
76 string s = lcolor.getX11Name(c);
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));
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;
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;
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));
106 XColor * cmap = new XColor[vi->map_entries];
108 for(int i = 0; i < vi->map_entries; ++i) {
111 XQueryColors(display, colormap, cmap, vi->map_entries);
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
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
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.
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;
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." << endl;
149 val.foreground = cmap[closest_pixel].pixel;
153 val.function = GXcopy;
154 return colorGCcache[c] = XCreateGC(display, drawable,
155 GCForeground | GCFunction, &val);
160 GC LyXColorHandler::getGCLinepars(PainterBase::line_style ls,
161 PainterBase::line_width lw, LColor::color c)
163 //if (lyxerr.debugging()) {
164 // lyxerr << "Painter drawable: " << drawable() << endl;
167 int index = lw + (ls << 1) + (c << 3);
169 if (lineGCcache.find(index) != lineGCcache.end())
170 return lineGCcache[index];
173 XGetGCValues(display, getGCForeground(c), GCForeground, &val);
176 case PainterBase::line_thin: val.line_width = 0; break;
177 case PainterBase::line_thick: val.line_width = 2; break;
181 case PainterBase::line_solid: val.line_style = LineSolid; break;
182 case PainterBase::line_onoffdash: val.line_style = LineOnOffDash; break;
183 case PainterBase::line_doubledash: val.line_style = LineDoubleDash; break;
187 val.cap_style = CapRound;
188 val.join_style = JoinRound;
189 val.function = GXcopy;
191 return lineGCcache[index] =
192 XCreateGC(display, drawable,
193 GCForeground | GCLineStyle | GCLineWidth |
194 GCCapStyle | GCJoinStyle | GCFunction, &val);
198 LyXColorHandler * lyxColorHandler;