3 * Copyright 2002 the LyX Team
4 * Read the file COPYING
6 * \author Angus Leeming, a.leeming@ic.ac.uk
12 #pragma implementation
15 #include "xformsGImage.h"
16 #include "graphics/GraphicsParams.h"
18 #include "converter.h" // formats
20 #include "frontends/GUIRunTime.h" // x11Display, x11Screen
21 #include "support/LAssert.h"
22 #include "support/lyxfunctional.h" // compare_memfun
30 unsigned int packedcolor(LColor::color c);
37 /// Access to this class is through this static method.
38 ImagePtr xformsGImage::newImage()
43 ptr.reset(new xformsGImage());
48 /// Return the list of loadable formats.
49 GImage::FormatList xformsGImage::loadableFormats()
51 static FormatList fmts;
57 // The formats recognised by LyX
58 Formats::const_iterator begin = formats.begin();
59 Formats::const_iterator end = formats.end();
61 lyxerr[Debug::GRAPHICS]
62 << "\nThe image loader can load the following directly:\n";
64 // Don't forget the Fortran numbering used by xforms!
65 int const nformats = flimage_get_number_of_formats();
66 for (int i = 1; i <= nformats; ++i) {
68 FLIMAGE_FORMAT_INFO const * info = flimage_get_format_info(i);
69 string const formal_name =
70 info->formal_name ? info->formal_name : string();
72 info->extension ? info->extension : string();
74 if (ext.empty() || ext == "gz")
77 if (ext == "rgb") ext = "sgi";
79 lyxerr[Debug::GRAPHICS]
80 << formal_name << ", extension \"" << ext << "\"\n";
82 Formats::const_iterator it =
84 lyx::compare_memfun(&Format::extension, ext));
86 fmts.push_back(it->name());
89 lyxerr[Debug::GRAPHICS]
90 << "\nOf these, LyX recognises the following formats:\n";
92 FormatList::const_iterator fbegin = fmts.begin();
93 FormatList::const_iterator fend = fmts.end();
94 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
96 lyxerr[Debug::GRAPHICS] << ", ";
97 lyxerr[Debug::GRAPHICS] << *fit;
99 lyxerr[Debug::GRAPHICS] << '\n' << std::endl;
105 xformsGImage::xformsGImage()
108 pixmap_status_(PIXMAP_UNINITIALISED)
112 xformsGImage::xformsGImage(xformsGImage const & other)
116 pixmap_status_(PIXMAP_UNINITIALISED)
119 image_ = flimage_dup(other.image_);
120 image_->u_vdata = this;
125 xformsGImage::~xformsGImage()
128 flimage_free(image_);
130 XFreePixmap(GUIRunTime::x11Display(), pixmap_);
134 GImage * xformsGImage::clone() const
136 return new xformsGImage(*this);
140 unsigned int xformsGImage::getWidth() const
148 unsigned int xformsGImage::getHeight() const
156 Pixmap xformsGImage::getPixmap() const
158 if (!pixmap_status_ == PIXMAP_SUCCESS)
164 void xformsGImage::load(string const & filename, SignalTypePtr on_finish)
167 lyxerr[Debug::GRAPHICS]
168 << "Image is loaded already!" << std::endl;
169 on_finish->emit(false);
173 image_ = flimage_open(filename.c_str());
175 lyxerr[Debug::GRAPHICS]
176 << "Unable to open image" << std::endl;
177 on_finish->emit(false);
181 // Store the Signal that will be emitted once the image is loaded.
182 on_finish_ = on_finish;
184 // Set this now and we won't need to bother again.
185 image_->fill_color = packedcolor(LColor::graphicsbg);
187 // Used by the callback routines to return to this
188 image_->u_vdata = this;
190 // Begin the reading process.
191 flimage_read(image_);
195 bool xformsGImage::setPixmap(GParams const & params)
197 if (!image_ || params.display == GParams::NONE)
200 Display * display = GUIRunTime::x11Display();
202 if (pixmap_ && pixmap_status_ == PIXMAP_SUCCESS)
203 XFreePixmap(display, pixmap_);
206 switch (params.display) {
207 case GParams::MONOCHROME:
208 color_key = FL_IMAGE_MONO;
210 case GParams::GRAYSCALE:
211 color_key = FL_IMAGE_GRAY;
214 default: // NONE cannot happen!
215 color_key = FL_IMAGE_RGB;
219 if (color_key != FL_IMAGE_RGB) {
220 flimage_convert(image_, color_key, 0);
223 unsigned int fill = packedcolor(LColor::graphicsbg);
224 if (fill != image_->fill_color) {
225 // the background color has changed.
226 // Note that in grayscale/monochrome images the background is
227 // grayed also, so this call will have no visible effect. Sorry!
228 flimage_replace_pixel(image_, image_->fill_color, fill);
229 image_->fill_color = fill;
232 image_->xdisplay = display;
233 Screen * screen = ScreenOfDisplay(display, GUIRunTime::x11Screen());
235 pixmap_ = flimage_to_pixmap(image_, XRootWindowOfScreen(screen));
236 pixmap_status_ = pixmap_ ? PIXMAP_SUCCESS : PIXMAP_FAILED;
238 return pixmap_status_ == PIXMAP_SUCCESS;
242 void xformsGImage::clip(GParams const & params)
247 if (params.bb.empty())
248 // No clipping is necessary.
251 int const new_width = params.bb.xr - params.bb.xl;
252 int const new_height = params.bb.yt - params.bb.yb;
254 if (new_width > image_->w || new_height > image_->h)
255 // Bounds are invalid.
258 if (new_width == image_->w && new_height == image_->h)
259 // Bounds are unchanged.
262 int const xoffset_l = params.bb.xl;
263 int const xoffset_r = image_->w - params.bb.xr;
264 int const yoffset_t = image_->h - params.bb.yt;
265 int const yoffset_b = params.bb.yb;
267 flimage_crop(image_, xoffset_l, yoffset_t, xoffset_r, yoffset_b);
271 void xformsGImage::rotate(GParams const & params)
277 // No rotation is necessary.
280 // The angle passed to flimage_rotate is the angle in one-tenth of a
282 flimage_rotate(image_, params.angle * 10, FLIMAGE_SUBPIXEL);
286 void xformsGImage::scale(GParams const & params)
291 // boost::tie produces horrible compilation errors on my machine
293 std::pair<unsigned int, unsigned int> d = getScaledDimensions(params);
294 unsigned int const width = d.first;
295 unsigned int const height = d.second;
297 if (width == getWidth() && height == getHeight())
301 flimage_scale(image_, width, height, FLIMAGE_SUBPIXEL);
305 void xformsGImage::statusCB(string const & status_message)
307 if (status_message.empty() || !on_finish_.get())
310 if (prefixIs(status_message, "Done Reading")) {
312 flimage_close(image_);
315 if (on_finish_.get()) {
316 on_finish_->emit(true);
323 void xformsGImage::errorCB(string const & error_message)
325 if (error_message.empty() || !on_finish_.get())
329 flimage_close(image_);
332 if (on_finish_.get()) {
333 on_finish_->emit(false);
345 int status_report(FL_IMAGE * ob, const char *s)
347 lyx::Assert(ob && ob->u_vdata);
349 string const str = s ? strip(s) : string();
353 lyxerr[Debug::GRAPHICS]
354 << "xforms image loader. Status : " << str << std::endl;
356 grfx::xformsGImage * ptr =
357 static_cast<grfx::xformsGImage *>(ob->u_vdata);
364 static void error_report(FL_IMAGE * ob, const char *s)
366 lyx::Assert(ob && ob->u_vdata);
368 string const str = s ? strip(s) : string();
372 lyxerr[Debug::GRAPHICS]
373 << "xforms image loader. Error : " << str << std::endl;
375 grfx::xformsGImage * ptr =
376 static_cast<grfx::xformsGImage *>(ob->u_vdata);
386 static bool initialised = false;
391 flimage_enable_bmp();
392 flimage_enable_fits();
393 flimage_enable_gif();
394 flimage_enable_jpeg();
396 // xforms itself uses pngtopnm to convert to a loadable format.
397 // We prefer to use our own conversion mechanism, therefore.
398 // flimage_enable_png();
400 flimage_enable_pnm();
402 #ifdef HAVE_FLIMAGE_ENABLE_PS
403 // xforms recognises PS but not EPS
407 flimage_enable_sgi();
408 flimage_enable_tiff();
409 flimage_enable_xbm();
410 flimage_enable_xwd();
411 flimage_enable_xpm();
413 // xforms stores this permanently (does not make a copy) so
414 // this should never be destroyed.
415 static FLIMAGE_SETUP setup;
416 setup.visual_cue = status_report;
417 setup.error_message = error_report;
418 flimage_setup(&setup);
422 unsigned int packedcolor(LColor::color c)
424 string const x11color = lcolor.getX11Name(c);
426 Display * display = GUIRunTime::x11Display();
427 Colormap cmap = GUIRunTime::x11Colormap();
430 if (XLookupColor(display, cmap, x11color.c_str(), &xcol, &ccol) == 0)
431 // Unable to parse x11color.
432 return FL_PACK(255,255,255);
434 // Note that X stores the RGB values in the range 0 - 65535
435 // whilst we require them in the range 0 - 255.
436 unsigned int const r = xcol.red / 256;
437 unsigned int const g = xcol.green / 256;
438 unsigned int const b = xcol.blue / 256;
440 return FL_PACK(r, g, b);