Back to index

texmacs  1.0.7.15
basic_renderer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : basic_renderer.cpp
00004 * DESCRIPTION: common drawing interface class
00005 * COPYRIGHT  : (C) 2008 Massimiliano Gubinelli
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "config.h" // for QTTEXMACS and AQUATEXMACS
00013 #if (defined(QTTEXMACS) || defined(AQUATEXMACS))
00014 
00015 #include "basic_renderer.hpp"
00016 #include "analyze.hpp"
00017 #include "gui.hpp" // for INTERRUPT_EVENT, INTERRUPTED_EVENT
00018 #include "font.hpp" // for the definition of font
00019 #include "rgb_colors.hpp"
00020 #include "iterator.hpp"
00021 #include <string.h>
00022 
00023 /******************************************************************************
00024 * structure for caching font pixmaps
00025 ******************************************************************************/
00026 
00027 basic_character::operator tree () {
00028   tree t (TUPLE,  as_string (rep->c), rep->fng->res_name);
00029   t << as_string (rep->sf) << as_string (rep->fg) << as_string (rep->bg);
00030   return t;
00031 }
00032 
00033 bool
00034 operator == (basic_character xc1, basic_character xc2) {
00035   return
00036     (xc1->c==xc2->c) && (xc1->fng.rep==xc2->fng.rep) &&
00037     (xc1->sf==xc2->sf) && (xc1->fg==xc2->fg) && (xc1->bg==xc2->bg);
00038 }
00039 
00040 bool
00041 operator != (basic_character xc1, basic_character xc2) {
00042   return
00043     (xc1->c!=xc2->c) || (xc1->fng.rep!=xc2->fng.rep) ||
00044     (xc1->sf!=xc2->sf) || (xc1->fg!=xc2->fg) || (xc1->bg!=xc2->bg);
00045 }
00046 
00047 int
00048 hash (basic_character xc) {
00049   return xc->c ^ ((intptr_t) xc->fng.rep) ^ xc->fg ^ xc->bg ^ xc->sf;
00050 }
00051 
00052 /******************************************************************************
00053 * Set up colors
00054 ******************************************************************************/
00055 
00056 bool reverse_colors= false;
00057 
00058 #ifdef QTTEXMACS
00059 #define LARGE_COLORMAP
00060 #else
00061 #define MEDIUM_COLORMAP
00062 #endif
00063 
00064 #ifndef LARGE_COLORMAP
00065 #ifdef SMALL_COLORMAP
00066 int CSCALES= 4;
00067 int CFACTOR= 5;
00068 int GREYS  = 16;
00069 #else
00070 int CSCALES= 8;
00071 int CFACTOR= 9;
00072 int GREYS  = 256;
00073 #endif
00074 int CTOTAL = (CFACTOR*CFACTOR*CFACTOR+GREYS+1);
00075 #endif
00076 
00077 #ifdef LARGE_COLORMAP
00078 
00079 color
00080 rgb_color (int r, int g, int b, int a) {
00081   return (a << 24) + (r << 16) + (g << 8) + b;
00082 }
00083 
00084 void
00085 get_rgb_color (color col, int& r, int& g, int& b, int& a) {
00086   a= (col >> 24) & 255;
00087   r= (col >> 16) & 255;
00088   g= (col >> 8) & 255;
00089   b= col & 255;
00090 }
00091 
00092 #else
00093 
00094 color
00095 rgb_color (int r, int g, int b, int a) {
00096   if ((r==g) && (g==b))
00097     return (a << 24) + (r*GREYS+ 128)/255;
00098   else {
00099     r= (r*CSCALES+ 128)/255;
00100     g= (g*CSCALES+ 128)/255;
00101     b= (b*CSCALES+ 128)/255;
00102     return (a << 24) + r*CFACTOR*CFACTOR+ g*CFACTOR+ b+ GREYS+ 1;
00103   }
00104 }
00105 
00106 void
00107 get_rgb_color (color col, int& r, int& g, int& b, int& a) {
00108   a= (col >> 24) & 255;
00109   col= col & 0xffffff;
00110   if (col <= ((color) GREYS)) {
00111     r= (col*255)/GREYS;
00112     g= (col*255)/GREYS;
00113     b= (col*255)/GREYS;
00114   }
00115   else {
00116     int rr, gg, bb;
00117     col-= (GREYS+1);
00118     bb  = col % CFACTOR;
00119     gg  = (col/CFACTOR) % CFACTOR;
00120     rr  = (col/(CFACTOR*CFACTOR)) % CFACTOR;
00121     r   = (rr*255)/CSCALES;
00122     g   = (gg*255)/CSCALES;
00123     b   = (bb*255)/CSCALES;
00124   }
00125 }
00126 
00127 #endif
00128 
00129 color  black   = rgb_color (0, 0, 0);
00130 color  white   = rgb_color (255, 255, 255);
00131 color  red     = rgb_color (255, 0, 0);
00132 color  blue    = rgb_color (0, 0, 255);
00133 color  yellow  = rgb_color (255, 255, 0);
00134 color  green   = rgb_color (0, 255, 0);
00135 color  magenta = rgb_color (255, 0, 255);
00136 color  orange  = rgb_color (255, 128, 0);
00137 color  brown   = rgb_color (128, 32, 0);
00138 color  pink    = rgb_color (255, 128, 128);
00139 
00140 color  light_grey = rgb_color (208, 208, 208);
00141 color  grey       = rgb_color (184, 184, 184);
00142 color  dark_grey  = rgb_color (112, 112, 112);
00143 
00144 static color
00145 named_color_bis (string s) {
00146   if ((N(s) == 4) && (s[0]=='#')) {
00147     int r= 17 * from_hexadecimal (s (1, 2));
00148     int g= 17 * from_hexadecimal (s (2, 3));
00149     int b= 17 * from_hexadecimal (s (3, 4));
00150     return rgb_color (r, g, b);
00151   }
00152   if ((N(s) == 7) && (s[0]=='#')) {
00153     int r= from_hexadecimal (s (1, 3));
00154     int g= from_hexadecimal (s (3, 5));
00155     int b= from_hexadecimal (s (5, 7));
00156     return rgb_color (r, g, b);
00157   }
00158 #ifdef REDUCED_COLORMAP
00159   unsigned int depth= 8;
00160 #else
00161 #ifdef MEDIUM_COLORMAP
00162   unsigned int depth= 16;
00163 #else
00164   unsigned int depth= 24;
00165 #endif
00166 #endif
00167   int pastel= (depth>=16? 223: 191);
00168   
00169   if ((N(s) > 4) && (s (1,4) == "gray") && (is_numeric (s (5, N(s))))) {
00170     int level, i=5;
00171     if (read_int(s,i,level)) {
00172       level = (level*255) /100;
00173       return rgb_color (level, level, level);
00174     }
00175   }
00176        
00177   if (s == "black")          return black;
00178   if (s == "white")          return white;
00179   if (s == "grey")           return grey;
00180   if (s == "red")            return red;
00181   if (s == "blue")           return blue;
00182   if (s == "yellow")         return yellow;
00183   if (s == "green")          return green;
00184   if (s == "magenta")        return magenta;
00185   if (s == "cyan")           return rgb_color (0, 255, 255);
00186   if (s == "orange")         return orange;
00187   if (s == "brown")          return brown;
00188   if (s == "pink")           return pink;
00189   if (s == "broken white")   return rgb_color (255, 255, pastel);
00190   if (s == "light grey")     return light_grey;
00191   if (s == "darker grey")    return rgb_color (64, 64, 64);
00192   if (s == "dark grey")      return dark_grey;
00193   if (s == "dark red")       return rgb_color (128, 0, 0);
00194   if (s == "dark blue")      return rgb_color (0, 0, 128);
00195   if (s == "dark yellow")    return rgb_color (128, 128, 0);
00196   if (s == "dark green")     return rgb_color (0, 128, 0);
00197   if (s == "dark magenta")   return rgb_color (128, 0, 128);
00198   if (s == "dark cyan")      return rgb_color (0, 128, 128);
00199   if (s == "dark orange")    return rgb_color (128, 64, 0);
00200   if (s == "dark brown")     return rgb_color (64, 16, 0);
00201   if (s == "pastel grey")    return rgb_color (pastel, pastel, pastel);
00202   if (s == "pastel red")     return rgb_color (255, pastel, pastel);
00203   if (s == "pastel blue")    return rgb_color (pastel, pastel, 255);
00204   if (s == "pastel yellow")  return rgb_color (255, 255, pastel);
00205   if (s == "pastel green")   return rgb_color (pastel, 255, pastel);
00206   if (s == "pastel magenta") return rgb_color (255, pastel, 255);
00207   if (s == "pastel cyan")    return rgb_color (pastel, 255, 255);
00208   if (s == "pastel orange")  return rgb_color (255, pastel, 2*pastel-255);
00209   if (s == "pastel brown")   return rgb_color (pastel, 2*pastel-255, 2*pastel-255);
00210   return black;
00211 }
00212 
00213 color
00214 named_color (string s, int a) {
00215   color c= named_color_bis (s);
00216   return (a << 24) + (c & 0xffffff);
00217 }
00218 
00219 string
00220 get_named_color (color c) {
00221   int r, g, b, a;
00222   get_rgb_color (c, r, g, b, a);
00223   return "#" *
00224     as_hexadecimal (r, 2) *
00225     as_hexadecimal (g, 2) *
00226     as_hexadecimal (b, 2);
00227 }
00228 
00229 #define RGBCOLOR(r,g,b) rgb_color(r,g,b)
00230 
00231 color
00232 xpm_to_color (string s) {
00233   if (s == "none") return RGBCOLOR(100,100,100);
00234   if ((N(s) == 4) && (s[0]=='#')) {
00235     int r= 17 * from_hexadecimal (s (1, 2));
00236     int g= 17 * from_hexadecimal (s (2, 3));
00237     int b= 17 * from_hexadecimal (s (3, 4));
00238     return RGBCOLOR(r,g,b);
00239   }
00240   if ((N(s) == 7) && (s[0]=='#')) {
00241     int r= from_hexadecimal (s (1, 3));
00242     int g= from_hexadecimal (s (3, 5));
00243     int b= from_hexadecimal (s (5, 7));
00244     return RGBCOLOR(r,g,b);
00245   }
00246   if ((N(s) == 13) && (s[0]=='#')) {
00247     int r= from_hexadecimal (s (1, 5));
00248     int g= from_hexadecimal (s (5, 9));
00249     int b= from_hexadecimal (s (9, 13));
00250     return RGBCOLOR(r,g,b);
00251   }
00252   char *name = as_charp(s);
00253   for(int i = 0; i<RGBColorsSize; i++) {
00254     if (strcmp(name,RGBColors[i].name)==0) {
00255       tm_delete_array (name);
00256       return RGBCOLOR(RGBColors[i].r,RGBColors[i].g,RGBColors[i].b);
00257     }
00258   }
00259   tm_delete_array (name);
00260   return RGBCOLOR (0, 0, 0);
00261 }
00262 
00263 #undef RGBCOLOR
00264 
00265 
00266 
00267 /******************************************************************************
00268 * Conversion between window and postscript coordinates
00269 ******************************************************************************/
00270 
00271 void
00272 basic_renderer_rep::encode (SI& x, SI& y) {
00273        x= (x*pixel) - ox;
00274        y= ((-y)*pixel) - oy;
00275 }
00276 
00277 void
00278 basic_renderer_rep::decode (SI& x, SI& y) {
00279        x += ox; y += oy;
00280        if (x>=0) x= x/pixel; else x= (x-pixel+1)/pixel;
00281        if (y>=0) y= -(y/pixel); else y= -((y-pixel+1)/pixel);
00282 }
00283 
00284 /*****************************************************************************/
00285 
00286 void
00287 basic_renderer_rep::get_extents (int& w2, int& h2) {
00288        w2 = w; h2 = h;
00289 }
00290 
00291 bool
00292 basic_renderer_rep::interrupted (bool check) {
00293        return check_event (check? INTERRUPT_EVENT: INTERRUPTED_EVENT);
00294 }
00295 
00296 
00297 void basic_renderer_rep::begin (void* handle) { 
00298   (void) handle; 
00299 }
00300 
00301 void basic_renderer_rep::end () {  }
00302 
00303 /******************************************************************************
00304 * Drawing into drawables
00305 ******************************************************************************/
00306 
00307 color
00308 basic_renderer_rep::rgb (int r, int g, int b, int a) {
00309   return rgb_color (r, g, b, a);
00310 }
00311 
00312 void
00313 basic_renderer_rep::get_rgb (color col, int& r, int& g, int& b, int& a) {
00314   get_rgb_color (col, r, g, b, a);
00315 }
00316 
00317 color
00318 basic_renderer_rep::get_color () {
00319   return cur_fg;
00320 }
00321 
00322 #if 0
00323 color
00324 basic_renderer_rep::get_color (string s) {
00325   return named_color (s);
00326 }
00327 #endif
00328 
00329 color
00330 basic_renderer_rep::get_background () {
00331   return cur_bg;
00332 }
00333 
00334 void
00335 basic_renderer_rep::set_color (color c) {
00336   cur_fg= c;
00337 }
00338 
00339 void
00340 basic_renderer_rep::set_background (color c) {
00341   cur_bg= c;
00342 }
00343 
00344 
00345 void
00346 basic_renderer_rep::set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore) {
00347   (void) restore;
00348 //  outer_round (x1, y1, x2, y2);
00349   renderer_rep::set_clipping (x1, y1, x2, y2);
00350 }
00351 
00352 /* shadowing and copying rectangular regions across devices defaults to nothing */
00353 
00354 void
00355 basic_renderer_rep::fetch (SI x1, SI y1, SI x2, SI y2,
00356                         renderer dev, SI x, SI y)
00357 {
00358   (void) x1; (void) y1; (void) x2; (void) y2; (void) dev; (void) x; (void) y; 
00359   if (DEBUG_EVENTS)
00360     cout << "REN fetch (" << x1 << "," << x2 << "," << y1 << "," << y2
00361         << ", dev ," << x << "," << y << ")\n";
00362 }
00363 
00364 void
00365 basic_renderer_rep::new_shadow (renderer& dev) {
00366   dev = this; 
00367   if (DEBUG_EVENTS) cout << "REN new_shadow\n";
00368 }
00369 
00370 void
00371 basic_renderer_rep::delete_shadow (renderer& dev) { dev= NULL; 
00372   if (DEBUG_EVENTS) cout << "REN delete_shadow\n";
00373 }
00374 
00375 void
00376 basic_renderer_rep::get_shadow (renderer dev, SI x1, SI y1, SI x2, SI y2) {
00377   (void) x1; (void) y1; (void) x2; (void) y2; (void) dev; 
00378   if (DEBUG_EVENTS)
00379     cout << "REN get_shadow (" << x1 << "," << x2
00380         << "," << y1 << "," << y2 << ", dev )\n";
00381 }
00382 
00383 void
00384 basic_renderer_rep::put_shadow (renderer dev, SI x1, SI y1, SI x2, SI y2) {
00385   (void) x1; (void) y1; (void) x2; (void) y2; (void) dev; 
00386   if (DEBUG_EVENTS)
00387     cout << "REN put_shadow (dev, " << x1 << "," << x2
00388         << "," << y1 << "," << y2 << ")\n";
00389 }
00390 
00391 void
00392 basic_renderer_rep::apply_shadow (SI x1, SI y1, SI x2, SI y2) {
00393   (void) x1; (void) y1; (void) x2; (void) y2; 
00394   if (DEBUG_EVENTS)
00395     cout << "REN apply_shadow (" << x1 << "," << x2
00396         << "," << y1 << "," << y2 << ")\n";
00397 }
00398 
00399 /******************************************************************************
00400 * Image cache
00401 ******************************************************************************/
00402 
00403 static time_t cache_image_last_gc = 0;
00404 static int    cache_image_tot_size= 0;
00405 static int    cache_image_max_size= 10000;
00406 static hashmap<tree,cache_image_element> cache_image;
00407 
00408 // to inform texmacs about image sizes we need to fill this structure
00409 // see System/Files/image_files.cpp
00410 
00411 extern hashmap<tree,string> ps_bbox; 
00412 
00413 void basic_renderer_rep::image_auto_gc () {
00414   time_t time= texmacs_time ();
00415   if (time-cache_image_last_gc <= 300000) return;
00416   cache_image_last_gc= time;
00417   if (DEBUG_AUTO)
00418     cout << "TeXmacs] Launching garbage collection for unused pictures\n";
00419   
00420   iterator<tree> it= iterate (cache_image);
00421   while (it->busy()) {
00422     tree lookup= it->next();
00423     cache_image_element ci = cache_image [lookup];
00424     time_t diff= time- ci->time;
00425     int fact= ci->nr;
00426     fact= fact * fact * fact;
00427     if ((ci->w * ci->h) < 400) fact= fact * 5;
00428     if ((ci->w * ci->h)  < 6400) fact= fact * 5;
00429     if (diff > 60000*fact) {
00430       cache_image->reset (lookup);
00431       ps_bbox->reset (lookup[0]);
00432     }
00433   }
00434 }
00435 
00436 void basic_renderer_rep::image_gc (string name) {
00437   (void) name;
00438   cache_image_last_gc= texmacs_time ();
00439   iterator<tree> it= iterate (cache_image);
00440   while (it->busy()) {
00441     tree lookup= it->next();
00442     if (!is_ramdisc (as_url (lookup[0]))) {
00443       cache_image_element ci = cache_image [lookup];
00444       cache_image->reset (lookup);
00445       ps_bbox->reset (lookup[0]);
00446     }
00447   }
00448 }
00449 
00450 cache_image_element 
00451 basic_renderer_rep::get_image_cache (tree lookup) {
00452   if (cache_image->contains (lookup)) return cache_image [lookup];
00453   return cache_image_element();
00454 }
00455 
00456 void 
00457 basic_renderer_rep::set_image_cache (tree lookup, cache_image_element ci)  {
00458   if (N(cache_image) == 0) cache_image_last_gc= texmacs_time ();
00459 
00460   cache_image      (lookup)= ci;
00461   cache_image_tot_size += (ci->w)*(ci->h);
00462   if (cache_image_tot_size > cache_image_max_size) {
00463     image_auto_gc ();
00464     if (cache_image_tot_size > cache_image_max_size)
00465       cache_image_max_size= cache_image_tot_size << 1;
00466   }
00467 }
00468 #endif