Back to index

texmacs  1.0.7.15
renderer.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : renderer.cpp
00004 * DESCRIPTION: Abstract graphical rendering primitives
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
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 "renderer.hpp"
00013 #include "gui.hpp"
00014 #include "rectangles.hpp"
00015 #include "image_files.hpp"
00016 
00017 /******************************************************************************
00018 * Constructors
00019 ******************************************************************************/
00020 
00021 renderer_rep::renderer_rep ():
00022   ox (0), oy (0), cx1 (0), cy1 (0), cx2 (0), cy2 (0),
00023   sfactor (1), pixel (PIXEL), thicken (0),
00024   master (NULL), pattern (UNINIT), pattern_alpha (255) {}
00025 
00026 renderer_rep::~renderer_rep () {}
00027 
00028 /******************************************************************************
00029 * Device specific
00030 ******************************************************************************/
00031 
00032 bool
00033 renderer_rep::is_printer () {
00034   return false;
00035 }
00036 
00037 bool
00038 renderer_rep::is_x_drawable () {
00039   return false;
00040 }
00041 
00042 void
00043 renderer_rep::get_extents (int& w, int& h) {
00044   w= h= 0;
00045 }
00046 
00047 x_drawable_rep*
00048 renderer_rep::as_x_drawable () {
00049   return NULL;
00050 }
00051 
00052 void
00053 renderer_rep::next_page () {
00054 }
00055 
00056 bool
00057 renderer_rep::repainted () {
00058   return true;
00059 }
00060 
00061 bool
00062 renderer_rep::interrupted (bool check) {
00063   (void) check;
00064   return false;
00065 }
00066 
00067 void
00068 renderer_rep::anchor(string label, SI x, SI y) {
00069   (void) label; (void) x; (void) y;
00070   return;
00071 }
00072 
00073 void
00074 renderer_rep::href(string label, SI x1, SI y1, SI x2, SI y2) {
00075   (void) label;
00076   (void) x1; (void) y1; (void) x2; (void) y2;
00077   return;
00078 }
00079 
00080 
00081 /******************************************************************************
00082 * Origin and shrinking factor
00083 ******************************************************************************/
00084 
00085 void
00086 renderer_rep::set_origin (SI x, SI y) {
00087   ox= x;
00088   oy= y;
00089 }
00090 
00091 void
00092 renderer_rep::move_origin (SI dx, SI dy) {
00093   ox += dx;
00094   oy += dy;
00095 }
00096 
00097 void
00098 renderer_rep::set_shrinking_factor (int sf) {
00099   ox  /= sfactor; oy  /= sfactor;
00100   cx1 /= sfactor; cy1 /= sfactor;
00101   cx2 /= sfactor; cy2 /= sfactor;
00102   sfactor= sf;
00103   pixel  = sf*PIXEL;
00104   thicken= (sf>>1)*PIXEL;
00105   ox  *= sfactor; oy  *= sfactor;
00106   cx1 *= sfactor; cy1 *= sfactor;
00107   cx2 *= sfactor; cy2 *= sfactor;
00108 }
00109 
00110 /******************************************************************************
00111 * Clipping
00112 ******************************************************************************/
00113 
00114 void
00115 renderer_rep::get_clipping (SI &x1, SI &y1, SI &x2, SI &y2) {
00116   x1= cx1- ox; y1= cy1- oy;
00117   x2= cx2- ox; y2= cy2- oy;
00118 }
00119 
00120 void
00121 renderer_rep::set_clipping (SI x1, SI y1, SI x2, SI y2, bool restore) {
00122   (void) restore;
00123   outer_round (x1, y1, x2, y2);
00124   cx1= x1+ ox; cy1= y1+ oy;
00125   cx2= x2+ ox; cy2= y2+ oy;
00126 }
00127 
00128 void
00129 renderer_rep::extra_clipping (SI x1, SI y1, SI x2, SI y2) {
00130   SI ox1, oy1, ox2, oy2;
00131   get_clipping (ox1, oy1, ox2, oy2);
00132   x1= max (x1, ox1); y1= max (y1, oy1);
00133   x2= max (x1, min (x2, ox2)); y2= max (y1, min (y2, oy2));
00134   set_clipping (x1, y1, x2, y2);
00135 }
00136 
00137 void
00138 renderer_rep::clip (SI x1, SI y1, SI x2, SI y2) {
00139   rectangle r (cx1, cy1, cx2, cy2);
00140   clip_stack= rectangles (r, clip_stack);
00141   set_clipping (x1, y1, x2, y2);
00142 }
00143 
00144 void
00145 renderer_rep::unclip () {
00146   rectangle r (clip_stack->item);
00147   set_clipping (r->x1- ox, r->y1- oy, r->x2- ox, r->y2- oy);
00148   clip_stack= clip_stack->next;
00149 }
00150 
00151 bool
00152 renderer_rep::is_visible (SI x1, SI y1, SI x2, SI y2) {
00153   return
00154     (x2 >= (cx1- ox)) && (y2 >= (cy1- oy)) &&
00155     (x1 <  (cx2- ox)) && (y1 <  (cy2- oy));
00156 }
00157 
00158 #define RND(x) (((x)>=0)?(((x)/pixel)*pixel):((((x)-pixel+1)/pixel)*pixel))
00159 
00160 void
00161 renderer_rep::round (SI& x, SI& y) {
00162   x= RND (x+ ox)- ox;
00163   y= RND (y+ oy)- oy;
00164 }
00165 
00166 void
00167 renderer_rep::inner_round (SI& x1, SI& y1, SI& x2, SI& y2) {
00168   x1= RND (x1+ox+pixel-1) - ox;
00169   y1= RND (y1+oy+pixel-1) - oy;
00170   x2= RND (x2+ox) - ox;
00171   y2= RND (y2+oy) - oy;
00172 }
00173 
00174 void
00175 renderer_rep::outer_round (SI& x1, SI& y1, SI& x2, SI& y2) {
00176   x1= RND (x1+ox) - ox;
00177   y1= RND (y1+oy) - oy;
00178   x2= RND (x2+ox+pixel-1) - ox;
00179   y2= RND (y2+oy+pixel-1) - oy;
00180 }
00181 
00182 #undef RND
00183 
00184 #define RND(x) (((x)>=0)?(((x)/PIXEL)*PIXEL):((((x)-PIXEL+1)/PIXEL)*PIXEL))
00185 
00186 void
00187 abs_round (SI& l) {
00188   l= RND (l);
00189 }
00190 
00191 void
00192 abs_round (SI& x, SI& y) {
00193   x= RND (x);
00194   y= RND (y);
00195 }
00196 
00197 void
00198 abs_inner_round (SI& x1, SI& y1, SI& x2, SI& y2) {
00199   x1= RND (x1+PIXEL-1);
00200   y1= RND (y1+PIXEL-1);
00201   x2= RND (x2);
00202   y2= RND (y2);
00203 }
00204 
00205 void
00206 abs_outer_round (SI& x1, SI& y1, SI& x2, SI& y2) {
00207   x1= RND (x1);
00208   y1= RND (y1);
00209   x2= RND (x2+PIXEL-1);
00210   y2= RND (y2+PIXEL-1);
00211 }
00212 
00213 /******************************************************************************
00214 * Default property selection and rendering routines
00215 ******************************************************************************/
00216 
00217 void
00218 renderer_rep::triangle (SI x1, SI y1, SI x2, SI y2, SI x3, SI y3) {
00219   array<SI> x (3), y (3);
00220   x[0]= x1; y[0]= y1;
00221   x[1]= x2; y[1]= y2;
00222   x[2]= x3; y[2]= y3;
00223   polygon (x, y);
00224 }
00225 
00226 void
00227 renderer_rep::set_background_pattern (tree pat, int alpha) {
00228   pattern= pat;
00229   pattern_alpha= alpha;
00230   if (pattern == "");
00231   else if (is_atomic (pattern))
00232     set_background (named_color (pat->label, alpha));
00233   else if (is_func (pattern, PATTERN, 4))
00234     set_background (named_color (as_string (pattern[3]), alpha));
00235 }
00236 
00237 tree
00238 renderer_rep::get_background_pattern (int& alpha) {
00239   alpha= pattern_alpha;
00240   if (is_atomic (pattern) || is_func (pattern, PATTERN, 4))
00241     return pattern;
00242   else {
00243     tree s= get_named_color (get_background ());
00244     if (is_func (pattern, PATTERN, 3))
00245       return pattern * tree (PATTERN, s);
00246     else return s;
00247   }
00248 }
00249 
00250 bool is_percentage (tree t, string s= "%");
00251 double as_percentage (tree t);
00252 
00253 void
00254 renderer_rep::clear_pattern (SI x1, SI y1, SI x2, SI y2) {
00255   if (pattern == "");
00256   else if (is_atomic (pattern))
00257     clear (x1, y1, x2, y2);
00258   else if (is_func (pattern, PATTERN)) {
00259     outer_round (x1, y1, x2, y2);
00260     //cout << "A: " << x1 << ", " << y1 << ", " << x2 << ", " << y2 << "\n";
00261     //cout << "A: " << x/pixel1 << ", " << y1 << ", " << x2 << ", " << y2 << "\n";
00262     SI cx1, cy1, cx2, cy2;
00263     get_clipping (cx1, cy1, cx2, cy2);
00264     extra_clipping (x1, y1, x2, y2);
00265 
00266     url u= as_string (pattern[0]);
00267     int imw_pt, imh_pt;
00268     image_size (u, imw_pt, imh_pt);
00269     double pt= ((double) 600*PIXEL) / 72.0;
00270     SI imw= (SI) (((double) imw_pt) * pt);
00271     SI imh= (SI) (((double) imh_pt) * pt);
00272 
00273     SI w= x2 - x1, h= y2 - y1;
00274     if (pattern[1] == "") w= imw;
00275     else if (is_int (pattern[1])) w= as_int (pattern[1]);
00276     else if (is_percentage (pattern[1]))
00277       w= (SI) (as_percentage (pattern[1]) * ((double) w));
00278     else if (is_percentage (pattern[1], "@"))
00279       w= (SI) (as_percentage (pattern[1]) * ((double) h));
00280     if (pattern[1] == "") h= imh;
00281     else if (is_int (pattern[2])) h= as_int (pattern[2]);
00282     else if (is_percentage (pattern[2]))
00283       h= (SI) (as_percentage (pattern[2]) * ((double) h));
00284     else if (is_percentage (pattern[2], "@"))
00285       h= (SI) (as_percentage (pattern[2]) * ((double) w));
00286     w= ((w + pixel - 1) / pixel) * pixel;
00287     h= ((h + pixel - 1) / pixel) * pixel;
00288 
00289     SI sx= 0; //is_percentage (pattern[1])? 0: ox;
00290     SI sy= 0; //is_percentage (pattern[2])? 0: oy;
00291     for (int i= ((x1+sx)/w) - 1; i <= ((x2+sx)/w) + 1; i++)
00292       for (int j= ((y1+sy)/h) - 1; j <= ((y2+sy)/h) + 1; j++) {
00293        SI X1= i*w     - sx, Y1= j*h     - sy;
00294        SI X2= (i+1)*w - sx, Y2= (j+1)*h - sy;
00295        if (X1 < x2 && X2 > x1 && Y1 < y2 && Y2 > y1)
00296          image (u, w, h, X1, Y1, 0.0, 0.0, 1.0, 1.0, pattern_alpha);
00297       }
00298     set_clipping (cx1, cy1, cx2, cy2, true);
00299   }
00300   else clear (x1, y1, x2, y2);
00301 }
00302 
00303 #undef RND
00304 
00305 /******************************************************************************
00306 * Drawing selections using alpha transparency
00307 ******************************************************************************/
00308 
00309 void
00310 renderer_rep::draw_rectangles (rectangles rs) {
00311   rectangles it= rs;
00312   while (!is_nil (it)) {
00313     fill (it->item->x1, it->item->y1, it->item->x2, it->item->y2);
00314     it= it->next;
00315   }
00316 }
00317 
00318 void
00319 renderer_rep::draw_selection (rectangles rs) {
00320   color fg= get_color ();
00321   int r, g, b, a;
00322   get_rgb_color (fg, r, g, b, a);
00323   color pfg= rgb_color (r, g, b, (a + 1) / 16);
00324   rectangles inn= ::thicken (rs, -pixel, -pixel);
00325   rectangles out= ::simplify (::correct (rs - inn));
00326   set_color (pfg);
00327   draw_rectangles (::simplify (inn));
00328   set_color (fg);
00329   draw_rectangles (out);
00330 }