00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "gmag-graphical-server.h"
00025
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <popt.h>
00029 #ifdef HAVE_COLORBLIND
00030 #include <colorblind.h>
00031 #endif
00032 #include <gdk/gdkwindow.h>
00033 #include <gtk/gtk.h>
00034 #ifdef USE_GDKPIXBUF_RENDER_TO_DRAWABLE
00035 #include <gdk/gdkpixbuf.h>
00036 #else
00037 #include <gdk/gdk.h>
00038 #endif
00039 #include <gdk/gdkx.h>
00040 #include <gdk/gdkrgb.h>
00041 #include <libbonobo.h>
00042 #include <math.h>
00043
00044 #undef ZOOM_REGION_DEBUG
00045
00046 #include "zoom-region.h"
00047 #include "zoom-region-private.h"
00048 #include "magnifier.h"
00049 #include "magnifier-private.h"
00050
00051 #define DEBUG_CLIENT_CALLS
00052
00053 #ifdef DEBUG_CLIENT_CALLS
00054 static gboolean client_debug = FALSE;
00055 #define DBG(a) if (client_debug) { (a); }
00056 #else
00057 #define DBG(a)
00058 #endif
00059
00060 static GObjectClass *parent_class = NULL;
00061
00062 enum {
00063 ZOOM_REGION_MANAGED_PROP,
00064 ZOOM_REGION_POLL_MOUSE_PROP,
00065 ZOOM_REGION_DRAW_CURSOR_PROP,
00066 ZOOM_REGION_SMOOTHSCROLL_PROP,
00067 ZOOM_REGION_COLORBLIND_PROP,
00068 ZOOM_REGION_INVERT_PROP,
00069 ZOOM_REGION_SMOOTHING_PROP,
00070 ZOOM_REGION_CONTRASTR_PROP,
00071 ZOOM_REGION_CONTRASTG_PROP,
00072 ZOOM_REGION_CONTRASTB_PROP,
00073 ZOOM_REGION_BRIGHTR_PROP,
00074 ZOOM_REGION_BRIGHTG_PROP,
00075 ZOOM_REGION_BRIGHTB_PROP,
00076 ZOOM_REGION_XSCALE_PROP,
00077 ZOOM_REGION_YSCALE_PROP,
00078 ZOOM_REGION_BORDERSIZE_PROP,
00079 ZOOM_REGION_BORDERSIZETOP_PROP,
00080 ZOOM_REGION_BORDERSIZELEFT_PROP,
00081 ZOOM_REGION_BORDERSIZERIGHT_PROP,
00082 ZOOM_REGION_BORDERSIZEBOTTOM_PROP,
00083 ZOOM_REGION_BORDERCOLOR_PROP,
00084 ZOOM_REGION_XALIGN_PROP,
00085 ZOOM_REGION_YALIGN_PROP,
00086 ZOOM_REGION_VIEWPORT_PROP,
00087 ZOOM_REGION_TESTPATTERN_PROP,
00088 ZOOM_REGION_TIMING_TEST_PROP,
00089 ZOOM_REGION_TIMING_OUTPUT_PROP,
00090 ZOOM_REGION_TIMING_PAN_RATE_PROP,
00091 ZOOM_REGION_EXIT_MAGNIFIER
00092 } PropIdx;
00093
00094 #ifdef DEBUG_CLIENT_CALLS
00095 gchar* prop_names[ZOOM_REGION_EXIT_MAGNIFIER + 1] =
00096 {
00097 "MANAGED",
00098 "POLLMOUSE",
00099 "DRAWCURSOR",
00100 "SMOOTHSCROLL",
00101 "COLORBLIND",
00102 "INVERT",
00103 "SMOOTHING",
00104 "CONTRASTR",
00105 "CONTRASTG",
00106 "CONTRASTB",
00107 "BRIGHTR",
00108 "BRIGHTG",
00109 "BRIGHTB",
00110 "XSCALE",
00111 "YSCALE",
00112 "BORDERSIZE",
00113 "BORDERSIZETOP",
00114 "BORDERSIZELEFT",
00115 "BORDERSIZERIGHT",
00116 "BORDERSIZEBOTTOM",
00117 "BORDERCOLOR",
00118 "XALIGN",
00119 "YALIGN",
00120 "VIEWPORT",
00121 "TESTPATTERN",
00122 "TIMING_TEST",
00123 "TIMING_OUTPUT",
00124 "TIMING_PAN_RATE",
00125 "EXIT_MAGNIFIER"
00126 };
00127 #endif
00128
00129 typedef enum {
00130 ZOOM_REGION_ERROR_NONE,
00131 ZOOM_REGION_ERROR_NO_TARGET_DRAWABLE,
00132 ZOOM_REGION_ERROR_TOO_BIG
00133 } ZoomRegionPixmapCreationError;
00134
00135 #ifdef HAVE_COLORBLIND
00136 static COLORBLIND_RUNTIME *cbr = NULL;
00137 static COLORBLIND_XCOLOR *color = NULL;
00138 #endif
00139
00140
00141 static float timing_scale_max = 0;
00142 static float timing_idle_max = 0;
00143 static float timing_frame_max = 0;
00144 static float cps_max = 0;
00145 static float nrr_max = 0;
00146 static float update_nrr_max = 0;
00147 static gboolean reset_timing = FALSE;
00148 static gboolean timing_test = FALSE;
00149
00150 static guint pending_idle_handler = 0;
00151 static gboolean processing_updates = FALSE;
00152 static gboolean timing_start = FALSE;
00153
00154 static gboolean can_coalesce = TRUE ;
00155
00156 #define CLAMP_B_C(v) (t = (v), CLAMP (t, -1, 1));
00157
00158 static void zoom_region_sync (ZoomRegion *region);
00159 static void zoom_region_finalize (GObject *object);
00160 static void zoom_region_update (ZoomRegion *zoom_region,
00161 const GdkRectangle rect);
00162 static void zoom_region_queue_update (ZoomRegion *zoom_region,
00163 const GdkRectangle rect);
00164
00165 static int zoom_region_process_updates (gpointer data);
00166 static void zoom_region_paint (ZoomRegion *zoom_region, GdkRectangle *rect);
00167 static void zoom_region_paint_pixmap (ZoomRegion *zoom_region, GdkRectangle *rect);
00168 static int zoom_region_update_pointer_timeout (gpointer data);
00169 static GdkRectangle zoom_region_rect_from_bounds (ZoomRegion *zoom_region,
00170 const GNOME_Magnifier_RectBounds *bounds);
00171 static ZoomRegionPixmapCreationError zoom_region_create_pixmap (ZoomRegion *zoom_region);
00172 static GdkRectangle zoom_region_update_pixmap (ZoomRegion *zoom_region, const GdkRectangle update_rect, GdkRectangle *paint_rect);
00173 static void zoom_region_get_move_x_y (ZoomRegion *zoom_region, long *x, long *y);
00174 static void zoom_region_recompute_exposed_bounds (ZoomRegion *zoom_region);
00175 static void zoom_region_update_current (ZoomRegion *zoom_region);
00176
00177 void
00178 reset_timing_stats()
00179 {
00180 timing_scale_max = 0;
00181 timing_idle_max = 0;
00182 timing_frame_max = 0;
00183 cps_max = 0;
00184 nrr_max = 0;
00185 update_nrr_max = 0;
00186 mag_timing.num_scale_samples = 0;
00187 mag_timing.num_idle_samples = 0;
00188 mag_timing.num_frame_samples = 0;
00189 mag_timing.num_line_samples = 0;
00190 mag_timing.scale_total = 0;
00191 mag_timing.idle_total = 0;
00192 mag_timing.frame_total = 0;
00193 mag_timing.update_pixels_total = 0;
00194 mag_timing.update_pixels_total = 0;
00195 mag_timing.dx_total = 0;
00196 mag_timing.dy_total = 0;
00197 mag_timing.last_frame_val = 0;
00198 mag_timing.last_dy = 0;
00199 g_timer_start (mag_timing.process);
00200 }
00201
00204 #undef DEBUG
00205 #ifdef DEBUG
00206 #define DEBUG_RECT(a, b) _debug_announce_rect (a, b)
00207 #else
00208 #define DEBUG_RECT(a, b)
00209 #endif
00210 static void
00211 _debug_announce_rect (char *msg, GdkRectangle rect)
00212 {
00213 fprintf (stderr, "%s: (%d,%d - %d,%d)\n",
00214 msg, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
00215 }
00216
00217 static gboolean
00218 _diff_pixbufs (const GdkPixbuf *a, const GdkPixbuf *b)
00219 {
00220 long i, j;
00221 int bits_per_byte = 8;
00222 guchar *pa = gdk_pixbuf_get_pixels (a);
00223 guchar *pb = gdk_pixbuf_get_pixels (b);
00224 guchar *cpa, *cpb;
00225 long rsa = gdk_pixbuf_get_rowstride (a);
00226 long rsb = gdk_pixbuf_get_rowstride (b);
00227 long rowbytes = gdk_pixbuf_get_width (a) *
00228 gdk_pixbuf_get_bits_per_sample (a) *
00229 gdk_pixbuf_get_n_channels (a)/ bits_per_byte;
00230 long n_rows = gdk_pixbuf_get_height (a);
00231
00232 if (gdk_pixbuf_get_height (b) != n_rows)
00233 return TRUE;
00234 if (gdk_pixbuf_get_width (b) != gdk_pixbuf_get_width (a))
00235 return TRUE;
00236 for (j = 0; j < n_rows; ++j)
00237 {
00238 cpa = pa + j * rsa;
00239 cpb = pb + j * rsb;
00240 for (i = 0; i < rowbytes; ++i)
00241 {
00242 if (*cpa != *cpb)
00243 {
00244 return TRUE;
00245 }
00246 cpa++;
00247 cpb++;
00248 }
00249 }
00250 return FALSE;
00251 }
00252
00255 #ifdef BROKEN_COALESCE_STUFF_GETS_FIXED
00256
00265 static gboolean
00266 _combine_rects (GdkRectangle *a, GdkRectangle *b)
00267 {
00268 gboolean can_combine = FALSE;
00269 if ((a->x == b->x) && (a->x + a->width == b->x + b->width))
00270 {
00271 can_combine = TRUE;
00272 }
00273 else if ((a->y == b->y) && (a->y + a->height == b->y + b->height))
00274 {
00275 can_combine = TRUE;
00276 }
00277 if (can_combine)
00278 {
00279 GdkRectangle c;
00280
00281 if (gdk_rectangle_intersect (a, b, &c))
00282 {
00283 gdk_rectangle_union (a, b, &c);
00284 *a = c;
00285 can_combine = TRUE;
00286 }
00287 else
00288 {
00289 can_combine = FALSE;
00290 }
00291 }
00292 return can_combine;
00293 }
00294
00308 static gboolean
00309 _refactor_rects (GdkRectangle *p, GdkRectangle *n)
00310 {
00311 gboolean refactored = FALSE;
00312 GdkRectangle *a, *b;
00313 if (p->x == n->x)
00314 {
00315 if (p->width < n->width)
00316 {
00317 a = p;
00318 b = n;
00319 }
00320 else
00321 {
00322 a = n;
00323 b = p;
00324 }
00325 if (a->y == b->y + b->height)
00326 {
00327 a->y -= b->height;
00328 a->height += b->height;
00329 b->x += a->width;
00330 b->width -= a->width;
00331 refactored = TRUE;
00332 }
00333 else if (a->y + a->height == b->y)
00334 {
00335 a->height += b->height;
00336 b->x += a->width;
00337 b->width -= a->width;
00338 refactored = TRUE;
00339 }
00340 if (refactored) fprintf (stderr, "REFACTOR 1\n");
00341 }
00342 else if (p->y == n->y)
00343 {
00344 if (p->height < n->height)
00345 {
00346 a = p;
00347 b = n;
00348 }
00349 else
00350 {
00351 a = n;
00352 b = p;
00353 }
00354 if (a->x == b->x + b->width)
00355 {
00356 a->x -= b->width;
00357 a->width += b->width;
00358 b->y += a->height;
00359 b->height -= a->height;
00360 refactored = TRUE;
00361 }
00362 else if (a->x + a->width == b->x)
00363 {
00364 a->width += b->width;
00365 b->y += a->height;
00366 b->height -= a->height;
00367 refactored = TRUE;
00368 }
00369 if (refactored) fprintf (stderr, "REFACTOR 2\n");
00370 }
00371 else if (p->x + p->width == n->x + n->width)
00372 {
00373 if (p->width < n->width)
00374 {
00375 a = p;
00376 b = n;
00377 }
00378 else
00379 {
00380 a = n;
00381 b = p;
00382 }
00383 if (a->y == b->y + b->height)
00384 {
00385 a->y -= b->height;
00386 a->height += b->height;
00387 b->width -= a->width;
00388 refactored = TRUE;
00389 }
00390 else if (a->y + a->height == b->y)
00391 {
00392 a->height += b->height;
00393 b->width -= a->width;
00394 refactored = TRUE;
00395 }
00396 if (refactored) fprintf (stderr, "REFACTOR 3\n");
00397 }
00398 else if (p->y + p->height == n->y + n->height)
00399 {
00400 if (p->height < n->height)
00401 {
00402 a = p;
00403 b = n;
00404 }
00405 else
00406 {
00407 a = n;
00408 b = p;
00409 }
00410 if (a->x == b->x + b->width)
00411 {
00412 a->x -= b->width;
00413 a->width += b->width;
00414 b->height -= a->height;
00415 refactored = TRUE;
00416 }
00417 else if (a->x + a->width == b->x)
00418 {
00419 a->width += b->width;
00420 b->height -= a->height;
00421 refactored = TRUE;
00422 }
00423 if (refactored) fprintf (stderr, "REFACTOR 4\n");
00424 }
00425 return refactored;
00426 }
00427
00428 static GList*
00429 _combine_update_rects (GList *q, int lookahead_n)
00430 {
00431 int i = 0;
00432 GdkRectangle *a = q->data;
00433 GList *p = q;
00434 while (i < lookahead_n && p && p->next)
00435 {
00436 if (_combine_rects (a, q->next->data))
00437 {
00438 q = g_list_delete_link (q, p->next);
00439 }
00440 else
00441 {
00442 p = p->next;
00443 ++i;
00444 }
00445 }
00446 return q;
00447 }
00448 #endif
00449
00450
00451
00452 #define _is_horizontal_rect(r) ((r)->width > (r)->height)
00453 #define _is_vertical_rect(r) ((r)->height > (r)->width)
00454
00461 static GList *
00462 _coalesce_update_rects (GList *q, int min_coalesce_length)
00463 {
00464 GdkRectangle *v = NULL, *h = NULL;
00465 GList *compact_queue = NULL;
00466
00467 if (g_list_length (q) < min_coalesce_length)
00468 return g_list_copy (q);
00469 while (q)
00470 {
00471 if (_is_vertical_rect ((GdkRectangle *) (q->data)))
00472 {
00473 if (v) gdk_rectangle_union (v, q->data, v);
00474 else
00475 {
00476 v = g_new0 (GdkRectangle, 1);
00477 *v = *(GdkRectangle *)q->data;
00478 }
00479 }
00480 else if (_is_horizontal_rect ((GdkRectangle *) (q->data)))
00481 {
00482 if (h) gdk_rectangle_union (h, q->data, h);
00483 else
00484 {
00485 h = g_new0 (GdkRectangle, 1);
00486 *h = *(GdkRectangle *)q->data;
00487 }
00488 }
00489 else
00490 compact_queue = g_list_prepend (compact_queue, q->data);
00491 q = q->next;
00492 };
00493 if (v)
00494 compact_queue = g_list_prepend (compact_queue, v);
00495 if (h)
00496 compact_queue = g_list_prepend (compact_queue, h);
00497
00498
00499 return compact_queue;
00500 }
00501
00502 #ifdef BROKEN_COALESCE_STUFF_GETS_FIXED
00503 static GList *
00504 _smartbutbroken_coalesce_update_rects (GList *q, int lookahead_n)
00505 {
00506 int i = 0, len;
00507 fprintf (stderr, "starting queue length = %d\n", g_list_length (q));
00508 do {
00509 GdkRectangle *a;
00510 len = g_list_length (q);
00511 q = _combine_update_rects (q, lookahead_n);
00512 a = q->data;
00513 while (i < lookahead_n && q && q->next)
00514 {
00515 if (_refactor_rects (a, q->next->data))
00516 break;
00517 else
00518 ++i;
00519 }
00520 q = _combine_update_rects (q, lookahead_n);
00521 } while (g_list_length (q) < len);
00522 fprintf (stderr, "ending queue length = %d\n", g_list_length (q));
00523 return q;
00524 }
00525 #endif
00526
00530 static GdkRectangle
00531 _rectangle_clip_to_rectangle (GdkRectangle area,
00532 GdkRectangle clip_rect)
00533 {
00534 GdkRectangle clipped;
00535 clipped.x = MAX (area.x, clip_rect.x);
00536 clipped.y = MAX (area.y, clip_rect.y);
00537 clipped.width = MIN ((area.x + area.width), (clip_rect.x + clip_rect.width)) - clipped.x;
00538 clipped.height = MIN ((area.y + area.height), (clip_rect.y + clip_rect.height)) - clipped.y;
00539 return clipped;
00540 }
00541
00542 static GdkRectangle
00543 _rectangle_clip_to_bounds (GdkRectangle area,
00544 GNOME_Magnifier_RectBounds *clip_bounds)
00545 {
00546 area.x = MAX (area.x, clip_bounds->x1);
00547 area.x = MIN (area.x, clip_bounds->x2);
00548 area.width = MIN (area.width, clip_bounds->x2 - area.x);
00549 area.y = MAX (area.y, clip_bounds->y1);
00550 area.y = MIN (area.y, clip_bounds->y2);
00551 area.height = MIN (area.height, clip_bounds->y2 - area.y);
00552 return area;
00553 }
00554
00555 static GdkRectangle
00556 zoom_region_clip_to_source (ZoomRegion *zoom_region,
00557 GdkRectangle area)
00558 {
00559 GNOME_Magnifier_RectBounds *source_rect_ptr;
00560 if (zoom_region && zoom_region->priv && zoom_region->priv->parent)
00561 {
00562 source_rect_ptr = &((Magnifier *)zoom_region->priv->parent)->source_bounds;
00563 DEBUG_RECT ("clipping to source bounds", zoom_region_rect_from_bounds (zoom_region, source_rect_ptr));
00564 return _rectangle_clip_to_bounds (area, source_rect_ptr);
00565 }
00566 return area;
00567 }
00568
00569 static GdkRectangle
00570 zoom_region_clip_to_exposed_target (ZoomRegion *zoom_region,
00571 GdkRectangle area)
00572 {
00573 GNOME_Magnifier_RectBounds onscreen_target, *source_area;
00574 source_area = &zoom_region->priv->source_area;
00575
00576 onscreen_target.x1 = MAX (floor (zoom_region->priv->exposed_bounds.x1
00577 / zoom_region->xscale),
00578 source_area->x1);
00579 onscreen_target.y1 = MAX (floor (zoom_region->priv->exposed_bounds.y1
00580 / zoom_region->yscale),
00581 source_area->y1);
00582 onscreen_target.x2 = MIN (ceil (zoom_region->priv->exposed_bounds.x2
00583 / zoom_region->xscale),
00584 source_area->x2);
00585 onscreen_target.y2 = MIN (ceil (zoom_region->priv->exposed_bounds.y2
00586 / zoom_region->yscale),
00587 source_area->y2);
00588
00589 return _rectangle_clip_to_bounds (area, &onscreen_target);
00590 }
00591
00592 static GdkRectangle
00593 zoom_region_clip_to_scaled_pixmap (ZoomRegion *zoom_region,
00594 GdkRectangle area)
00595 {
00596 GdkRectangle pixmap_area = {0, 0, 0, 0};
00597 if (zoom_region->priv && zoom_region->priv->pixmap)
00598 {
00599 gdk_drawable_get_size (zoom_region->priv->pixmap, &pixmap_area.width, &pixmap_area.height);
00600 return _rectangle_clip_to_rectangle (area, pixmap_area);
00601 }
00602 else
00603 return area;
00604 }
00605
00606 static GdkRectangle
00607 zoom_region_clip_to_window (ZoomRegion *zoom_region,
00608 GdkRectangle area)
00609 {
00610 GdkRectangle window_rect;
00611
00612
00613
00614 return area;
00615
00616 if (zoom_region->priv->w->window)
00617 gdk_drawable_get_size (GDK_DRAWABLE (zoom_region->priv->w->window),
00618 &window_rect.x,
00619 &window_rect.y);
00620 else
00621 {
00622 window_rect.x = 0;
00623 window_rect.y = 0;
00624 }
00625 return _rectangle_clip_to_rectangle (area, window_rect);
00626 }
00627
00628 static GdkRectangle
00629 zoom_region_source_rect_from_view_bounds (ZoomRegion *zoom_region,
00630 const GNOME_Magnifier_RectBounds *view_bounds)
00631 {
00632 GdkRectangle source_rect;
00633 source_rect.x = floor ((view_bounds->x1 + zoom_region->priv->exposed_bounds.x1)
00634 / zoom_region->xscale);
00635 source_rect.y = floor ((view_bounds->y1 + zoom_region->priv->exposed_bounds.y1)
00636 / zoom_region->yscale);
00637 source_rect.width = ceil ((view_bounds->x2 - view_bounds->x1) / zoom_region->xscale) + 1;
00638 source_rect.height = ceil ((view_bounds->y2 - view_bounds->y1) / zoom_region->yscale) + 1;
00639 return source_rect;
00640 }
00641
00642 static GdkRectangle
00643 zoom_region_view_rect_from_source_rect (ZoomRegion *zoom_region,
00644 const GdkRectangle source_rect)
00645 {
00646 GdkRectangle view_rect;
00647 view_rect.x = source_rect.x * zoom_region->xscale - zoom_region->priv->exposed_bounds.x1;
00648 view_rect.y = source_rect.y * zoom_region->yscale - zoom_region->priv->exposed_bounds.y1;
00649 view_rect.width = source_rect.width * zoom_region->xscale;
00650 view_rect.height = source_rect.height * zoom_region->yscale;
00651 DEBUG_RECT ("source", source_rect);
00652 DEBUG_RECT ("converted to view-rect", view_rect);
00653 return view_rect;
00654 }
00655
00656 static GdkRectangle
00657 zoom_region_source_rect_from_view_rect (ZoomRegion *zoom_region,
00658 const GdkRectangle view_rect)
00659 {
00660 GdkRectangle source_rect;
00661 source_rect.x = floor ((view_rect.x + zoom_region->priv->exposed_bounds.x1)
00662 / zoom_region->xscale);
00663 source_rect.y = floor ((view_rect.y + zoom_region->priv->exposed_bounds.y1)
00664 / zoom_region->yscale);
00665 source_rect.width = ceil (view_rect.width / zoom_region->xscale) + 1;
00666 source_rect.height = ceil (view_rect.height / zoom_region->yscale) + 1;
00667 return source_rect;
00668 }
00669
00670 static GdkRectangle
00671 zoom_region_rect_from_bounds (ZoomRegion *zoom_region,
00672 const GNOME_Magnifier_RectBounds *bounds)
00673 {
00674 GdkRectangle rect;
00675 rect.x = bounds->x1;
00676 rect.y = bounds->y1;
00677 rect.width = bounds->x2 - bounds->x1;
00678 rect.height = bounds->y2 - bounds->y1;
00679 return rect;
00680 }
00681
00684 static CORBA_boolean
00685 zoom_region_update_scale (ZoomRegion *zoom_region, gdouble x, gdouble y)
00686 {
00687 gdouble x_old = zoom_region->xscale;
00688 gdouble y_old = zoom_region->yscale;
00689 long x_move, y_move;
00690
00691 zoom_region->xscale = x;
00692 zoom_region->yscale = y;
00693
00694 if (zoom_region->priv->scaled_pixbuf)
00695 g_object_unref (zoom_region->priv->scaled_pixbuf);
00696 zoom_region->priv->scaled_pixbuf =
00697 gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, (zoom_region->priv->source_area.x2 - zoom_region->priv->source_area.x1) * zoom_region->xscale + 1, (zoom_region->priv->source_area.y2 - zoom_region->priv->source_area.y1) * zoom_region->yscale + 1);
00698
00699 if (zoom_region->priv->pixmap)
00700 g_object_unref (zoom_region->priv->pixmap);
00701
00702 if (zoom_region_create_pixmap (zoom_region) ==
00703 ZOOM_REGION_ERROR_TOO_BIG) {
00704 zoom_region->xscale = x_old;
00705 zoom_region->yscale = y_old;
00706 zoom_region_create_pixmap (zoom_region);
00707 g_object_unref (zoom_region->priv->scaled_pixbuf);
00708
00709
00710
00711 zoom_region->priv->scaled_pixbuf = gdk_pixbuf_new (
00712 GDK_COLORSPACE_RGB, FALSE, 8, (zoom_region->priv->source_area.x2 - zoom_region->priv->source_area.x1) * zoom_region->xscale + 1, (zoom_region->priv->source_area.y2 - zoom_region->priv->source_area.y1) * zoom_region->yscale + 1);
00713
00714 return CORBA_FALSE;
00715 }
00716
00717 zoom_region_get_move_x_y (zoom_region, &x_move, &y_move);
00718 zoom_region->priv->exposed_bounds.x1 = x_move * zoom_region->xscale;
00719 zoom_region->priv->exposed_bounds.y1 = y_move * zoom_region->yscale;
00720 zoom_region_recompute_exposed_bounds (zoom_region);
00721 zoom_region_update_current (zoom_region);
00722
00723 return CORBA_TRUE;
00724 }
00725
00726 static void
00727 zoom_region_queue_update (ZoomRegion *zoom_region,
00728 const GdkRectangle update_rect)
00729 {
00730 GdkRectangle *rect =
00731 g_new0 (GdkRectangle, 1);
00732 *rect = update_rect;
00733
00734 #ifdef ZOOM_REGION_DEBUG
00735 g_assert (zoom_region->alive);
00736 #endif
00737 DEBUG_RECT ("queueing update", *rect);
00738
00739 zoom_region->priv->q =
00740 g_list_prepend (zoom_region->priv->q, rect);
00741 if (zoom_region->priv && zoom_region->priv->update_handler_id == 0)
00742 zoom_region->priv->update_handler_id =
00743 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
00744 zoom_region_process_updates,
00745 zoom_region,
00746 NULL);
00747 }
00748
00749 static void
00750 zoom_region_update_current (ZoomRegion *zoom_region)
00751 {
00752 #ifdef ZOOM_REGION_DEBUG
00753 g_assert (zoom_region->alive);
00754 #endif
00755 if (zoom_region->priv)
00756 {
00757 gboolean pixmap_valid = GDK_IS_DRAWABLE (zoom_region->priv->pixmap);
00758 if (!pixmap_valid)
00759 pixmap_valid = (zoom_region_create_pixmap (zoom_region) == ZOOM_REGION_ERROR_NONE);
00760 if (pixmap_valid)
00761 zoom_region_update (zoom_region,
00762 zoom_region_source_rect_from_view_bounds (
00763 zoom_region,
00764 &zoom_region->viewport));
00765 }
00766 }
00767
00768 static GdkRectangle
00769 zoom_region_cursor_rect (ZoomRegion *zoom_region)
00770 {
00771 GdkRectangle rect = {0, 0, 0, 0};
00772 Magnifier *magnifier = zoom_region->priv->parent;
00773 GdkDrawable *cursor = NULL;
00774 if (magnifier)
00775 cursor = magnifier_get_cursor (magnifier);
00776 if (cursor)
00777 {
00778 rect.x = zoom_region->priv->last_cursor_pos.x;
00779 rect.y = zoom_region->priv->last_cursor_pos.y;
00780 rect = zoom_region_view_rect_from_source_rect (zoom_region, rect);
00781 rect.x -= magnifier->cursor_hotspot.x;
00782 rect.y -= magnifier->cursor_hotspot.y;
00783 gdk_drawable_get_size (cursor, &rect.width, &rect.height);
00784 }
00785 return rect;
00786 }
00787
00788 static void
00789 zoom_region_unpaint_crosswire_cursor (ZoomRegion *zoom_region,
00790 GdkRectangle *clip_rect)
00791 {
00792 Magnifier *magnifier = zoom_region->priv->parent;
00793 GdkRectangle vline_rect, hline_rect;
00794 GdkPoint cursor_pos;
00795
00796 #ifdef ZOOM_REGION_DEBUG
00797 g_assert (zoom_region->alive);
00798 #endif
00799 if (!magnifier || magnifier->crosswire_size <= 0) return;
00800
00801 cursor_pos = zoom_region->priv->last_drawn_crosswire_pos;
00802 vline_rect.x = cursor_pos.x - magnifier->crosswire_size/2;
00803 vline_rect.y = clip_rect ? clip_rect->y : 0;
00804 vline_rect.width = MAX (magnifier->crosswire_size, 1);
00805 vline_rect.height = clip_rect ? clip_rect->height : 4096;
00806 hline_rect.x = clip_rect ? clip_rect->x : 0;
00807 hline_rect.y = cursor_pos.y - magnifier->crosswire_size/2;
00808 hline_rect.width = clip_rect ? clip_rect->width : 4096;
00809 hline_rect.height = MAX (magnifier->crosswire_size, 1);
00810
00811 zoom_region_paint_pixmap (zoom_region, &vline_rect);
00812 zoom_region_paint_pixmap (zoom_region, &hline_rect);
00813 }
00814
00815 static void
00816 zoom_region_paint_crosswire_cursor (ZoomRegion *zoom_region, GdkRectangle *clip_rect)
00817 {
00818 Magnifier *magnifier = zoom_region->priv->parent;
00819 static GdkColormap *cmap;
00820 static GdkColor last_color;
00821 static gboolean last_color_init = FALSE;
00822 GdkGCValues values;
00823 GdkRectangle rect;
00824 GdkDrawable *cursor;
00825 GdkColor color = {0, 0, 0, 0};
00826 int x_start = 0, y_start = 0, x_end = 4096, y_end = 4096;
00827 int x_left_clip = 0, x_right_clip = 0, y_top_clip = 0, y_bottom_clip = 0;
00828 int csize = 0;
00829
00830 #ifdef ZOOM_REGION_DEBUG
00831 g_assert (zoom_region->alive);
00832 #endif
00833 if (!(magnifier &&
00834 zoom_region->priv->w->window &&
00835 GDK_IS_DRAWABLE (zoom_region->priv->w->window) &&
00836 magnifier->crosswire_size > 0)) return;
00837
00838 if (zoom_region->priv->crosswire_gc == NULL)
00839 {
00840 zoom_region->priv->crosswire_gc = gdk_gc_new (zoom_region->priv->w->window);
00841 cmap = gdk_gc_get_colormap(zoom_region->priv->crosswire_gc);
00842 last_color_init = FALSE;
00843 }
00844
00845 if (magnifier->crosswire_color == 0)
00846 {
00847 color.red = 0xFFFF;
00848 color.blue = 0xFFFF;
00849 color.green = 0xFFFF;
00850 values.function = GDK_INVERT;
00851 }
00852 else
00853 {
00854 color.red = (magnifier->crosswire_color & 0xFF0000) >> 8;
00855 color.green = (magnifier->crosswire_color & 0xFF00);
00856 color.blue = (magnifier->crosswire_color & 0xFF) << 8;
00857 values.function = GDK_COPY;
00858 }
00859
00860 values.foreground = color;
00861
00862
00863 if (!last_color_init || color.red != last_color.red ||
00864 color.blue != last_color.blue || color.green != last_color.green)
00865 {
00866 if (cmap)
00867 {
00868 gdk_rgb_find_color (cmap, &(values.foreground));
00869 gdk_gc_set_values(zoom_region->priv->crosswire_gc, &values, GDK_GC_FUNCTION | GDK_GC_FOREGROUND);
00870 }
00871 else
00872 {
00873 gdk_gc_set_values(zoom_region->priv->crosswire_gc, &values, GDK_GC_FUNCTION);
00874 }
00875
00876 last_color.red = color.red;
00877 last_color.blue = color.blue;
00878 last_color.green = color.green;
00879 last_color_init = TRUE;
00880 }
00881
00882 rect.x = zoom_region->priv->last_cursor_pos.x;
00883 rect.y = zoom_region->priv->last_cursor_pos.y;
00884 rect.width = 0;
00885 rect.height = 0;
00886 rect = zoom_region_view_rect_from_source_rect (zoom_region, rect);
00887 if (clip_rect) gdk_gc_set_clip_rectangle (zoom_region->priv->crosswire_gc, clip_rect);
00888 else gdk_gc_set_clip_rectangle (zoom_region->priv->crosswire_gc, NULL);
00889
00890 if ((cursor = magnifier_get_cursor (magnifier))) {
00891 gdk_drawable_get_size (cursor, &csize, &csize);
00892 }
00893
00894 if (magnifier->crosswire_length) {
00895 if (magnifier->crosswire_clip) {
00896 x_start = rect.x - magnifier->cursor_hotspot.x -
00897 magnifier->crosswire_length;
00898 x_end = rect.x +
00899 (csize - magnifier->cursor_hotspot.x) +
00900 magnifier->crosswire_length;
00901 y_start = rect.y - magnifier->cursor_hotspot.y -
00902 magnifier->crosswire_length;
00903 y_end = rect.y +
00904 (csize - magnifier->cursor_hotspot.y) +
00905 magnifier->crosswire_length;
00906 } else {
00907 x_start = rect.x - magnifier->crosswire_length;
00908 x_end = rect.x + magnifier->crosswire_length;
00909 y_start = rect.y - magnifier->crosswire_length;
00910 y_end = rect.y + magnifier->crosswire_length;
00911 }
00912 }
00913
00914 if (magnifier->crosswire_clip)
00915 {
00916 y_top_clip = rect.y - magnifier->cursor_hotspot.y -
00917 magnifier->crosswire_size;
00918 y_bottom_clip = rect.y +
00919 (csize - magnifier->cursor_hotspot.y) +
00920 magnifier->crosswire_size;
00921 x_left_clip = rect.x - magnifier->cursor_hotspot.x -
00922 magnifier->crosswire_size;
00923 x_right_clip = rect.x +
00924 (csize - magnifier->cursor_hotspot.x) +
00925 magnifier->crosswire_size;
00926
00927 }
00928 if (magnifier->crosswire_size == 1) {
00929 if (magnifier->crosswire_clip) {
00930 gdk_draw_line (zoom_region->priv->w->window,
00931 zoom_region->priv->crosswire_gc,
00932 rect.x, y_top_clip, rect.x,
00933 y_bottom_clip);
00934 gdk_draw_line (zoom_region->priv->w->window,
00935 zoom_region->priv->crosswire_gc,
00936 x_left_clip, rect.y, x_right_clip,
00937 rect.y);
00938 }
00939 gdk_draw_line (zoom_region->priv->w->window,
00940 zoom_region->priv->crosswire_gc,
00941 rect.x, y_start, rect.x, y_end);
00942 gdk_draw_line (zoom_region->priv->w->window,
00943 zoom_region->priv->crosswire_gc,
00944 x_start, rect.y, x_end, rect.y);
00945 }
00946 else {
00947 if (magnifier->crosswire_clip ) {
00948 gdk_draw_rectangle (
00949 zoom_region->priv->w->window,
00950 zoom_region->priv->crosswire_gc, TRUE,
00951 rect.x - magnifier->crosswire_size / 2,
00952 y_top_clip, magnifier->crosswire_size,
00953 y_bottom_clip - y_top_clip);
00954 gdk_draw_rectangle (
00955 zoom_region->priv->w->window,
00956 zoom_region->priv->crosswire_gc, TRUE,
00957 x_left_clip,
00958 rect.y - magnifier->crosswire_size / 2,
00959 x_right_clip - x_left_clip,
00960 magnifier->crosswire_size);
00961 }
00962 gdk_draw_rectangle (
00963 zoom_region->priv->w->window,
00964 zoom_region->priv->crosswire_gc, TRUE,
00965 rect.x - magnifier->crosswire_size / 2, y_start,
00966 magnifier->crosswire_size, y_end - y_start);
00967 gdk_draw_rectangle (
00968 zoom_region->priv->w->window,
00969 zoom_region->priv->crosswire_gc, TRUE,
00970 x_start, rect.y - magnifier->crosswire_size / 2,
00971 x_end - x_start, magnifier->crosswire_size);
00972 }
00973 }
00974
00975 static void
00976 zoom_region_unpaint_cursor (ZoomRegion *zoom_region, GdkRectangle *clip_rect)
00977 {
00978 #ifdef ZOOM_REGION_DEBUG
00979 g_assert (zoom_region->alive);
00980 #endif
00981 zoom_region_paint_pixmap (zoom_region,
00982 &zoom_region->priv->cursor_backing_rect);
00983 }
00984
00985
00986 static void
00987 zoom_region_paint_cursor (ZoomRegion *zoom_region,
00988 GdkRectangle *clip_rect)
00989 {
00990 GdkGCValues values;
00991 GdkRectangle rect, intersct;
00992 GdkRectangle fullscreen;
00993 Magnifier *magnifier = zoom_region->priv->parent;
00994 rect = zoom_region_cursor_rect (zoom_region);
00995 #ifdef ZOOM_REGION_DEBUG
00996 g_assert (zoom_region->alive);
00997 #endif
00998 if (!zoom_region->draw_cursor)
00999 return;
01000
01001 if (clip_rect == NULL)
01002 {
01003 fullscreen = zoom_region_rect_from_bounds (zoom_region,
01004 &zoom_region->viewport);
01005 clip_rect = &fullscreen;
01006 }
01007
01008 zoom_region->priv->last_drawn_crosswire_pos.x = rect.x + magnifier->cursor_hotspot.x;
01009 zoom_region->priv->last_drawn_crosswire_pos.y = rect.y + magnifier->cursor_hotspot.y;
01010
01011 if (gdk_rectangle_intersect (clip_rect, &rect, &intersct))
01012 {
01013 int width = 0, height = 0;
01014
01015 GdkDrawable *cursor = magnifier_get_cursor (magnifier);
01016 if (!cursor)
01017 return;
01018 else if (!GDK_IS_DRAWABLE (cursor)) g_message ("cursor isn't DRAWABLE!");
01019 zoom_region->priv->cursor_backing_rect = rect;
01020 if (zoom_region->priv->cursor_backing_pixels) {
01021 gdk_drawable_get_size (zoom_region->priv->cursor_backing_pixels,
01022 &width, &height);
01023 }
01024 if (rect.width != width || rect.height != height)
01025 {
01026 if (zoom_region->priv->cursor_backing_pixels) {
01027 g_object_unref (zoom_region->priv->cursor_backing_pixels);
01028 }
01029 zoom_region->priv->cursor_backing_pixels =
01030 gdk_pixmap_new (zoom_region->priv->w->window,
01031 rect.width,
01032 rect.height,
01033 -1);
01034 }
01035 if (zoom_region->priv->w->window != NULL)
01036 {
01037 if (zoom_region->priv->default_gc == NULL)
01038 zoom_region->priv->default_gc = gdk_gc_new(zoom_region->priv->w->window);
01039 gdk_draw_drawable (zoom_region->priv->cursor_backing_pixels,
01040 zoom_region->priv->default_gc,
01041 zoom_region->priv->w->window,
01042 rect.x,
01043 rect.y,
01044 0, 0,
01045 rect.width,
01046 rect.height);
01047 }
01048 DEBUG_RECT ("painting", rect);
01049 if (cursor && zoom_region->priv->w && GDK_IS_DRAWABLE (zoom_region->priv->w->window))
01050 {
01051 if (zoom_region->priv->paint_cursor_gc == NULL)
01052 zoom_region->priv->paint_cursor_gc = gdk_gc_new (zoom_region->priv->w->window);
01053
01054 gdk_gc_set_clip_rectangle (zoom_region->priv->paint_cursor_gc, clip_rect);
01055 values.clip_x_origin = rect.x;
01056 values.clip_y_origin = rect.y;
01057 values.clip_mask = magnifier->priv->cursor_mask;
01058 gdk_gc_set_values(zoom_region->priv->paint_cursor_gc, &values, GDK_GC_CLIP_X_ORIGIN |
01059 GDK_GC_CLIP_Y_ORIGIN | GDK_GC_CLIP_MASK);
01060
01061 gdk_draw_rectangle (zoom_region->priv->w->window,
01062 zoom_region->priv->paint_cursor_gc,
01063 TRUE,
01064 rect.x, rect.y, rect.width, rect.height);
01065
01066 gdk_draw_drawable (zoom_region->priv->w->window,
01067 zoom_region->priv->paint_cursor_gc,
01068 cursor,
01069 0, 0,
01070 rect.x,
01071 rect.y,
01072 rect.width,
01073 rect.height);
01074 }
01075 }
01076 }
01077
01082 static void
01083 zoom_region_coalesce_updates (ZoomRegion *zoom_region)
01084 {
01085
01086 GList *q;
01087 int lookahead_n = 4;
01088 int max_qlen = 50;
01089
01090 if (zoom_region->priv && zoom_region->priv->q && g_list_length (zoom_region->priv->q) > max_qlen)
01091 {
01092 g_list_free (zoom_region->priv->q);
01093 zoom_region->priv->q = NULL;
01094
01095 zoom_region_queue_update (zoom_region, zoom_region_rect_from_bounds
01096 (zoom_region, &zoom_region->priv->source_area));
01097 }
01098 else
01099
01100 if (zoom_region->priv && zoom_region->priv->q &&
01101 (g_list_length (zoom_region->priv->q) > 1) && can_coalesce)
01102 {
01103 q = g_list_reverse (g_list_copy (zoom_region->priv->q));
01104 if (q)
01105 {
01106 GList *coalesce_copy;
01107 if (zoom_region->coalesce_func)
01108 {
01109 GList *new;
01110 coalesce_copy = (*zoom_region->coalesce_func) (q, lookahead_n);
01111 new = g_list_reverse (coalesce_copy);
01112 g_list_free (zoom_region->priv->q);
01113 zoom_region->priv->q = new;
01114 }
01115 g_list_free (q);
01116 }
01117 }
01118 }
01119
01120
01121 static void
01122 zoom_region_paint_border (ZoomRegion *zoom_region)
01123 {
01124 GdkColor color;
01125
01126 #ifdef ZOOM_REGION_DEBUG
01127 g_assert (zoom_region->alive);
01128 #endif
01129 if ((zoom_region->border_size_left > 0 ||
01130 zoom_region->border_size_top > 0 ||
01131 zoom_region->border_size_right > 0 ||
01132 zoom_region->border_size_bottom > 0) &&
01133 (zoom_region->priv->border->window)) {
01134 color.red = (((zoom_region->border_color & 0xFF0000) >> 16) *
01135 65535) / 255;
01136 color.green = (((zoom_region->border_color & 0xFF00) >> 8) *
01137 65535) / 255;
01138 color.blue = ((zoom_region->border_color & 0xFF) * 65535) /
01139 255;
01140
01141 #ifdef DEBUG_BORDER
01142 fprintf (stderr, "border color triple RGB=%d|%d|%d\n",
01143 color.red, color.green, color.blue);
01144 #endif
01145
01146 gtk_widget_modify_bg (zoom_region->priv->border,
01147 GTK_STATE_NORMAL, &color);
01148 }
01149 }
01150
01151 static void
01152 zoom_region_paint_pixmap (ZoomRegion *zoom_region,
01153 GdkRectangle *area)
01154 {
01155 #ifdef ZOOM_REGION_DEBUG
01156 g_assert (zoom_region->alive);
01157 #endif
01158 g_assert (zoom_region->priv);
01159 g_assert (zoom_region->priv->w);
01160
01161 if (!GDK_IS_DRAWABLE (zoom_region->priv->w->window)) return;
01162 if (zoom_region->priv->default_gc == NULL)
01163 zoom_region->priv->default_gc = gdk_gc_new (zoom_region->priv->w->window);
01164
01165 if (zoom_region->priv->pixmap && GDK_IS_DRAWABLE (zoom_region->priv->w->window))
01166 {
01167 gdk_draw_drawable (zoom_region->priv->w->window,
01168 zoom_region->priv->default_gc,
01169 zoom_region->priv->pixmap,
01170 area->x + zoom_region->priv->exposed_bounds.x1 - zoom_region->priv->source_area.x1 * zoom_region->xscale,
01171 area->y + zoom_region->priv->exposed_bounds.y1 - zoom_region->priv->source_area.y1 * zoom_region->yscale,
01172 area->x,
01173 area->y,
01174 area->width,
01175 area->height);
01176 }
01177 }
01178
01182 static void
01183 zoom_region_paint (ZoomRegion *zoom_region,
01184 GdkRectangle *area)
01185 {
01186 GdkRectangle paint_area;
01187
01188 #ifdef ZOOM_REGION_DEBUG
01189 g_assert (zoom_region->alive);
01190 #endif
01191 DEBUG_RECT ("painting (clipped)", *area);
01192 paint_area = zoom_region_clip_to_window (zoom_region, *area);
01193 zoom_region_paint_pixmap (zoom_region, &paint_area);
01194 zoom_region_paint_cursor (zoom_region, &paint_area);
01195 zoom_region_paint_crosswire_cursor (zoom_region, &paint_area);
01196 }
01197
01198 static ZoomRegionPixmapCreationError
01199 zoom_region_create_pixmap (ZoomRegion *zoom_region)
01200 {
01201 #ifdef ZOOM_REGION_DEBUG
01202 g_assert (zoom_region->alive);
01203 #endif
01204 if (zoom_region->priv->w && GDK_IS_DRAWABLE (zoom_region->priv->w->window))
01205 {
01206 long width = (zoom_region->priv->source_area.x2 -
01207 zoom_region->priv->source_area.x1) * zoom_region->xscale;
01208 long height = (zoom_region->priv->source_area.y2 -
01209 zoom_region->priv->source_area.y1) * zoom_region->yscale;
01210 zoom_region->priv->pixmap =
01211 gdk_pixmap_new (
01212 zoom_region->priv->w->window,
01213 width,
01214 height,
01215 gdk_drawable_get_depth (
01216 zoom_region->priv->w->window));
01217
01218 if (gmag_gs_error_check ()) {
01219 zoom_region->priv->pixmap = NULL;
01220 return ZOOM_REGION_ERROR_TOO_BIG;
01221 }
01222
01223 DEBUG_RECT("viewport", zoom_region_source_rect_from_view_bounds
01224 (zoom_region, &zoom_region->viewport));
01225 DEBUG_RECT("source", zoom_region_rect_from_bounds
01226 (zoom_region, &((Magnifier*)zoom_region->priv->parent)->source_bounds));
01227
01228 return ZOOM_REGION_ERROR_NONE;
01229 }
01230
01231 return ZOOM_REGION_ERROR_NO_TARGET_DRAWABLE;
01232 }
01233
01234 static void
01235 zoom_region_expose_handler (GtkWindow * w,
01236 GdkEventExpose *event,
01237 gpointer data)
01238 {
01239 ZoomRegion *zoom_region = data;
01240 DEBUG_RECT ("expose", event->area);
01241
01242 #ifdef ZOOM_REGION_DEBUG
01243 g_assert (zoom_region->alive);
01244 #endif
01245 if (zoom_region->priv->pixmap == NULL)
01246 {
01247 ZoomRegionPixmapCreationError ret;
01248
01249 while ((ret = zoom_region_create_pixmap (zoom_region)) ==
01250 ZOOM_REGION_ERROR_TOO_BIG) {
01251 zoom_region->xscale -= 1.0;
01252 zoom_region->yscale -= 1.0;
01253 zoom_region->priv->pixmap = NULL;
01254 g_warning ("Scale factor too big to fit in memory; shrinking.");
01255 }
01256 if (ret == ZOOM_REGION_ERROR_NO_TARGET_DRAWABLE)
01257 g_warning ("create-pixmap: no target drawable");
01258 else
01259 zoom_region_update_pixmap (zoom_region, event->area,
01260 NULL);
01261 }
01262 zoom_region_paint (zoom_region, &event->area);
01263 }
01264
01265 static void
01266 zoom_region_update_cursor (ZoomRegion *zoom_region, int dx, int dy,
01267 GdkRectangle *clip_rect)
01268 {
01269 #ifdef ZOOM_REGION_DEBUG
01270 g_assert (zoom_region->alive);
01271 #endif
01272 zoom_region_unpaint_crosswire_cursor (zoom_region, clip_rect);
01273 zoom_region_unpaint_cursor (zoom_region, clip_rect);
01274 zoom_region->priv->cursor_backing_rect.x += dx;
01275 zoom_region->priv->cursor_backing_rect.y += dy;
01276 zoom_region->priv->last_drawn_crosswire_pos.x += dx;
01277 zoom_region->priv->last_drawn_crosswire_pos.y += dy;
01278 zoom_region_paint_cursor (zoom_region, clip_rect);
01279 zoom_region_paint_crosswire_cursor (zoom_region, clip_rect);
01280 if (GTK_IS_WIDGET (zoom_region->priv->w) &&
01281 GDK_IS_WINDOW (zoom_region->priv->w->window))
01282 gdk_display_sync (gdk_drawable_get_display (
01283 zoom_region->priv->w->window));
01284 }
01285
01286 static gboolean
01287 zoom_region_calculate_scroll_rects (ZoomRegion *zoom_region,
01288 int dx, int dy,
01289 GdkRectangle *scroll_rect,
01290 GdkRectangle *expose_rect_h,
01291 GdkRectangle *expose_rect_v)
01292 {
01293 GdkWindow *window = NULL;
01294 GdkRectangle rect = {0, 0, 0, 0};
01295 gboolean retval = TRUE;
01296
01297 #ifdef ZOOM_REGION_DEBUG
01298 g_assert (zoom_region->alive);
01299 #endif
01300 rect.x = 0;
01301 rect.y = 0;
01302 if (zoom_region && zoom_region->priv->w &&
01303 zoom_region->priv->w->window)
01304 window = zoom_region->priv->w->window;
01305 else
01306 retval = FALSE;
01307 if (!window)
01308 retval = FALSE;
01309
01310 if (window != NULL)
01311 gdk_drawable_get_size (GDK_DRAWABLE (window),
01312 &rect.width,
01313 &rect.height);
01314
01315 if ((ABS (dx) >= rect.width) || (ABS (dy) >= rect.height)) {
01316 *scroll_rect = rect;
01317 DBG(fprintf (stderr, "deltas too big to scroll\n"));
01318 retval = FALSE;
01319 }
01320 else {
01321 scroll_rect->x = MAX (0, dx);
01322 scroll_rect->y = MAX (0, dy);
01323 scroll_rect->width = MIN (rect.width + dx, rect.width - dx);
01324 scroll_rect->height = MIN (rect.height + dy, rect.height - dy);
01325 }
01326
01327 expose_rect_h->x = 0;
01328 expose_rect_h->y = (scroll_rect->y == 0) ? scroll_rect->height : 0;
01329 expose_rect_h->width = rect.width;
01330 expose_rect_h->height = rect.height - scroll_rect->height;
01331
01332 expose_rect_v->x = (scroll_rect->x == 0) ? scroll_rect->width : 0;
01333 expose_rect_v->y = scroll_rect->y;
01334 expose_rect_v->width = rect.width - scroll_rect->width;
01335 expose_rect_v->height = scroll_rect->height;
01336
01337 return retval;
01338 }
01339
01340 static void
01341 zoom_region_scroll_fast (ZoomRegion *zoom_region, int dx, int dy,
01342 GdkRectangle *scroll_rect,
01343 GdkRectangle *expose_rect_h,
01344 GdkRectangle *expose_rect_v)
01345 {
01346 GdkWindow *window;
01347
01348 #ifdef ZOOM_REGION_DEBUG
01349 g_assert (zoom_region->alive);
01350 #endif
01351 if (zoom_region->priv->w && zoom_region->priv->w->window)
01352 window = zoom_region->priv->w->window;
01353 else {
01354 processing_updates = FALSE;
01355 return;
01356 }
01357 zoom_region_unpaint_crosswire_cursor (zoom_region, scroll_rect);
01358 zoom_region_unpaint_cursor (zoom_region, scroll_rect);
01359 gdk_window_scroll (window, dx, dy);
01360 zoom_region_paint_cursor (zoom_region, scroll_rect);
01361 zoom_region_paint_crosswire_cursor (zoom_region, scroll_rect);
01362 gdk_window_process_updates (window, FALSE);
01363
01364 if (zoom_region->smooth_scroll_policy >
01365 GNOME_Magnifier_ZoomRegion_SCROLL_FASTEST)
01366 gdk_display_sync (gdk_drawable_get_display (window));
01367 }
01368
01369 static void
01370 zoom_region_scroll_smooth (ZoomRegion *zoom_region, int dx, int dy,
01371 GdkRectangle *scroll_rect,
01372 GdkRectangle *expose_rect_h,
01373 GdkRectangle *expose_rect_v)
01374 {
01375 GdkWindow *window = NULL;
01376 GdkRectangle window_rect;
01377
01378 #ifdef ZOOM_REGION_DEBUG
01379 g_assert (zoom_region->alive);
01380 #endif
01381 if (zoom_region->priv->w && GDK_IS_DRAWABLE (zoom_region->priv->w->window))
01382 window = zoom_region->priv->w->window;
01383 else
01384 return;
01385 window_rect.x = 0;
01386 window_rect.y = 0;
01387 gdk_drawable_get_size (GDK_DRAWABLE (window),
01388 &window_rect.width, &window_rect.height);
01389 gdk_window_begin_paint_rect (window, &window_rect);
01390 gdk_window_invalidate_rect (window, &window_rect, FALSE);
01391 gdk_window_process_updates (window, FALSE);
01392 gdk_window_end_paint (window);
01393 }
01394
01395 static void
01396 zoom_region_scroll (ZoomRegion *zoom_region, int dx, int dy)
01397 {
01398 GdkRectangle scroll_rect, expose_rect_h, expose_rect_v;
01399 gboolean can_scroll;
01400
01401 #ifdef ZOOM_REGION_DEBUG
01402 g_assert (zoom_region->alive);
01403 #endif
01404 if (timing_test) {
01405 mag_timing.num_line_samples++;
01406 mag_timing.dx = abs(dx);
01407 mag_timing.dy = abs(dy);
01408 mag_timing.dx_total += mag_timing.dx;
01409 mag_timing.dy_total += mag_timing.dy;
01410 if (zoom_region->timing_output) {
01411 fprintf(stderr, " Panning Increment (x) = %d (avg. %f) lines/frame\n",
01412 mag_timing.dx, (float)mag_timing.dx_total / (float)mag_timing.num_line_samples);
01413 fprintf(stderr, " Panning Increment (y) = %d (avg. %f) lines/frame\n",
01414 mag_timing.dy, (float)mag_timing.dy_total / (float)mag_timing.num_line_samples);
01415 }
01416 }
01417
01418
01419
01420
01421
01422 processing_updates = TRUE;
01423
01424 can_scroll = zoom_region_calculate_scroll_rects (zoom_region, dx, dy,
01425 &scroll_rect,
01426 &expose_rect_h,
01427 &expose_rect_v);
01428
01429 if (can_scroll) {
01430 zoom_region_update_pixmap (zoom_region, zoom_region_source_rect_from_view_rect (zoom_region, expose_rect_h), NULL);
01431 zoom_region_update_pixmap (zoom_region, zoom_region_source_rect_from_view_rect (zoom_region, expose_rect_v), NULL);
01432
01433 if (zoom_region->smooth_scroll_policy > GNOME_Magnifier_ZoomRegion_SCROLL_FAST) {
01434 zoom_region_scroll_smooth (zoom_region, dx, dy,
01435 &scroll_rect,
01436 &expose_rect_h,
01437 &expose_rect_v);
01438 } else {
01439 zoom_region_scroll_fast (zoom_region, dx, dy,
01440 &scroll_rect,
01441 &expose_rect_h,
01442 &expose_rect_v);
01443 }
01444 } else {
01445 zoom_region_queue_update (zoom_region, zoom_region_source_rect_from_view_rect (zoom_region, scroll_rect));
01446 }
01447 }
01448
01449 static void
01450 zoom_region_recompute_exposed_bounds (ZoomRegion *zoom_region)
01451 {
01452 zoom_region->priv->exposed_bounds.x2 = zoom_region->priv->exposed_bounds.x1
01453 + (zoom_region->viewport.x2 - zoom_region->viewport.x1);
01454 zoom_region->priv->exposed_bounds.y2 = zoom_region->priv->exposed_bounds.y1
01455 + (zoom_region->viewport.y2 - zoom_region->viewport.y1);
01456 }
01457
01458 static void
01459 zoom_region_set_cursor_pos (ZoomRegion *zoom_region, int x, int y)
01460 {
01461 if (zoom_region->priv)
01462 {
01463 zoom_region->priv->last_cursor_pos.x = x;
01464 zoom_region->priv->last_cursor_pos.y = y;
01465 }
01466 }
01467
01468 static gboolean
01469 zoom_region_update_pointer (ZoomRegion *zoom_region, gboolean draw_cursor)
01470 {
01471 Magnifier *magnifier;
01472 gint mouse_x_return, mouse_y_return;
01473 guint mask_return;
01474
01475 #ifdef ZOOM_REGION_DEBUG
01476 g_assert (zoom_region->alive);
01477 #endif
01478 if (!zoom_region->priv || !zoom_region->priv->parent
01479 || !zoom_region->poll_mouse)
01480 return FALSE;
01481
01482 magnifier = zoom_region->priv->parent;
01483
01484
01485 if (magnifier && magnifier->priv && magnifier_get_root (magnifier))
01486 {
01487 gdk_window_get_pointer (
01488 magnifier_get_root (magnifier),
01489 &mouse_x_return,
01490 &mouse_y_return,
01491 &mask_return);
01492
01493 if (zoom_region->priv->last_cursor_pos.x != mouse_x_return
01494 || zoom_region->priv->last_cursor_pos.y != mouse_y_return)
01495 {
01496 zoom_region_set_cursor_pos (zoom_region,
01497 mouse_x_return,
01498 mouse_y_return);
01499 if (draw_cursor)
01500 zoom_region_update_cursor (zoom_region, 0, 0,
01501 NULL);
01502
01503 return TRUE;
01504 }
01505 }
01506 return FALSE;
01507 }
01508
01509 static int
01510 zoom_region_update_pointer_idle (gpointer data)
01511 {
01512 ZoomRegion *zoom_region = (ZoomRegion *) data;
01513
01514 if (zoom_region_update_pointer (zoom_region, TRUE))
01515 return TRUE;
01516 else {
01517 if (zoom_region->priv)
01518 zoom_region->priv->update_pointer_id =
01519 g_timeout_add_full (G_PRIORITY_DEFAULT,
01520 100,
01521 zoom_region_update_pointer_timeout,
01522 zoom_region,
01523 NULL);
01524 return FALSE;
01525 }
01526 }
01527
01528 static int
01529 zoom_region_update_pointer_timeout (gpointer data)
01530 {
01531 ZoomRegion *zoom_region = data;
01532
01533 if (zoom_region->priv && zoom_region_update_pointer (zoom_region,
01534 TRUE)) {
01535 zoom_region->priv->update_pointer_id =
01536 g_idle_add_full (G_PRIORITY_HIGH_IDLE,
01537 zoom_region_update_pointer_idle,
01538 data,
01539 NULL);
01540 return FALSE;
01541 } else
01542 return TRUE;
01543 }
01544
01545 static void
01546 zoom_region_moveto (ZoomRegion *zoom_region,
01547 const long x, const long y)
01548 {
01549 long dx = x * zoom_region->xscale - zoom_region->priv->exposed_bounds.x1;
01550 long dy = y * zoom_region->yscale - zoom_region->priv->exposed_bounds.y1;
01551 #ifdef ZOOM_REGION_DEBUG
01552 g_assert (zoom_region->alive);
01553 #endif
01554
01555
01556 mag_timing.dx = 0;
01557 mag_timing.dy = 0;
01558
01559 if ((dx != 0) || (dy != 0)) {
01560 zoom_region_update_pointer (zoom_region, FALSE);
01561 zoom_region->priv->exposed_bounds.x1 = x * zoom_region->xscale;
01562 zoom_region->priv->exposed_bounds.y1 = y * zoom_region->yscale;
01563 zoom_region_recompute_exposed_bounds (zoom_region);
01564 zoom_region_scroll (zoom_region,
01565 -dx, -dy);
01566 }
01567 }
01568
01569
01570
01571
01572 static void
01573 zoom_region_process_pixbuf (ZoomRegion *zoom_region, GdkPixbuf *pixbuf)
01574 {
01575 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
01576 int i, j, t;
01577 int w = gdk_pixbuf_get_width (pixbuf);
01578 int h = gdk_pixbuf_get_height (pixbuf);
01579 int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
01580 guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
01581 guchar *pixels_row;
01582
01583 gboolean manipulate_contrast = FALSE;
01584 gboolean manipulate_brightness = FALSE;
01585 gboolean color_blind_filter = FALSE;
01586
01587 if (zoom_region->contrast_r != 0 || zoom_region->contrast_g != 0 ||
01588 zoom_region->contrast_b != 0) {
01589 manipulate_contrast = TRUE;
01590 }
01591
01592 if (zoom_region->bright_r != 0 || zoom_region->bright_g != 0 ||
01593 zoom_region->bright_b != 0) {
01594 manipulate_brightness = TRUE;
01595 }
01596
01597 #ifdef HAVE_COLORBLIND
01598 if (zoom_region->color_blind_filter !=
01599 GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_NO_FILTER) {
01600 color_blind_filter = TRUE;
01601 }
01602 #endif
01603
01604 if (!manipulate_contrast && !zoom_region->invert &&
01605 !manipulate_brightness && !color_blind_filter)
01606 return;
01607
01608 #define CLAMP_UCHAR(v) (t = (v), CLAMP (t, 0, 255))
01609 #define CLAMP_LOW_MID(v) (t = (v), CLAMP (t, 0, 127))
01610 #define CLAMP_MID_HIGH(v) (t = (v), CLAMP (t, 127, 255))
01611
01612 for (j = 0; j < h; ++j) {
01613 pixels_row = pixels;
01614 for (i = 0; i < w; ++i) {
01615 if (manipulate_contrast) {
01616
01617 if (pixels_row[0] <= 127)
01618 pixels_row[0] = CLAMP_LOW_MID (pixels_row[0] - zoom_region->contrast_r * 127);
01619 else
01620 pixels_row[0] = CLAMP_MID_HIGH (pixels_row[0] + zoom_region->contrast_r * 127);
01621
01622
01623 if (pixels_row[1] <= 127)
01624 pixels_row[1] = CLAMP_LOW_MID (pixels_row[1] - zoom_region->contrast_g * 127);
01625 else
01626 pixels_row[1] = CLAMP_MID_HIGH (pixels_row[1] + zoom_region->contrast_g * 127);
01627
01628
01629 if (pixels_row[2] <= 127)
01630 pixels_row[2] = CLAMP_LOW_MID (pixels_row[2] - zoom_region->contrast_b * 127);
01631 else
01632 pixels_row[2] = CLAMP_MID_HIGH (pixels_row[2] + zoom_region->contrast_b * 127);
01633 }
01634
01635 if (manipulate_brightness) {
01636
01637 pixels_row[0] = CLAMP_UCHAR (pixels_row[0] + zoom_region->bright_r * 255);
01638
01639
01640 pixels_row[1] = CLAMP_UCHAR (pixels_row[1] + zoom_region->bright_g * 255);
01641
01642
01643 pixels_row[2] = CLAMP_UCHAR (pixels_row[2] + zoom_region->bright_b * 255);
01644 }
01645
01646 if (zoom_region->invert) {
01647 pixels_row[0] = ~(pixels_row[0]);
01648 pixels_row[1] = ~(pixels_row[1]);
01649 pixels_row[2] = ~(pixels_row[2]);
01650 }
01651
01652 #ifdef HAVE_COLORBLIND
01653 if (color_blind_filter) {
01654 color->red = pixels_row[0];
01655 color->green = pixels_row[1];
01656 color->blue = pixels_row[2];
01657 if (colorblind_filter (cbr, color)) {
01658 pixels_row[0] = color->red;
01659 pixels_row[1] = color->green;
01660 pixels_row[2] = color->blue;
01661 }
01662 }
01663 #endif
01664
01665 pixels_row += n_channels;
01666 }
01667 pixels += rowstride;
01668 }
01669
01670 }
01671
01672 static void
01673 zoom_region_post_process_pixbuf (ZoomRegion *zoom_region,
01674 GdkPixbuf *subimage,
01675 GdkPixbuf *scaled_image)
01676 {
01677
01687 }
01688
01689 static GdkPixbuf *
01690 zoom_region_get_source_subwindow (ZoomRegion *zoom_region,
01691 const GdkRectangle bounds)
01692 {
01693 int i, j, width, height;
01694 Magnifier *magnifier = zoom_region->priv->parent;
01695 GdkPixbuf *subimage = NULL;
01696
01697 #ifdef ZOOM_REGION_DEBUG
01698 g_assert (zoom_region->alive);
01699 #endif
01700 width = gdk_screen_get_width (
01701 gdk_display_get_screen (magnifier->source_display,
01702 magnifier->source_screen_num));
01703 height = gdk_screen_get_height (
01704 gdk_display_get_screen (magnifier->source_display,
01705 magnifier->source_screen_num));
01706
01707 if ((bounds.width <= 0) || (bounds.height <= 0))
01708 {
01709 return NULL;
01710 }
01711
01712 if (!zoom_region->priv->source_drawable)
01713 {
01714
01715 if (zoom_region->priv->test) {
01716 GdkImage *test_image = NULL;
01717
01718 test_image = gdk_image_new (GDK_IMAGE_FASTEST,
01719 gdk_visual_get_system (),
01720 width,
01721 height);
01722
01723 for (i = 0; i < width; ++i)
01724 for (j = 0; j < height; ++j)
01725 gdk_image_put_pixel (test_image, i, j, i*j);
01726
01727 zoom_region->priv->source_drawable = gdk_pixmap_new (zoom_region->priv->w->window, width, height, -1);
01728
01729 if (zoom_region->priv->default_gc == NULL)
01730 zoom_region->priv->default_gc = gdk_gc_new(zoom_region->priv->w->window);
01731
01732 gdk_draw_image (zoom_region->priv->source_drawable,
01733 zoom_region->priv->default_gc,
01734 test_image,
01735 0, 0,
01736 0, 0,
01737 width, height);
01738 }
01739 else
01740 {
01741 if (magnifier->priv->source_drawable) {
01742 zoom_region->priv->source_drawable =
01743 magnifier->priv->source_drawable;
01744 } else
01745 zoom_region->priv->source_drawable = gdk_screen_get_root_window (gdk_display_get_screen (magnifier->source_display, magnifier->source_screen_num));
01746 }
01747 if (zoom_region->cache_source)
01748 {
01749 zoom_region->priv->source_pixbuf_cache =
01750 gdk_pixbuf_new (GDK_COLORSPACE_RGB,
01751 FALSE,
01752 8,
01753 width, height);
01754 }
01755 }
01756 DEBUG_RECT ("getting subimage from ", bounds);
01757
01758 subimage = gdk_pixbuf_get_from_drawable (NULL, zoom_region->priv->source_drawable,
01759 gdk_colormap_get_system (),
01760 bounds.x,
01761 bounds.y,
01762 0,
01763 0,
01764 bounds.width,
01765 bounds.height);
01766
01767
01768
01769 if (!subimage)
01770 _debug_announce_rect ("update of invalid subregion!\n", bounds);
01771
01772
01773 if (zoom_region->cache_source && subimage) {
01774 GdkPixbuf *cache_subpixbuf =
01775 gdk_pixbuf_new_subpixbuf (zoom_region->priv->source_pixbuf_cache,
01776 bounds.x, bounds.y, bounds.width, bounds.height);
01777 if (_diff_pixbufs (subimage, cache_subpixbuf)) {
01778 gdk_pixbuf_copy_area (subimage, 0, 0, bounds.width, bounds.height,
01779 zoom_region->priv->source_pixbuf_cache,
01780 bounds.x, bounds.y);
01781 }
01782 else
01783 {
01784 if (subimage)
01785 g_object_unref (subimage);
01786 subimage = NULL;
01787 }
01788 g_object_unref (cache_subpixbuf);
01789 }
01790 return subimage;
01791 }
01792
01793 static GdkRectangle
01794 zoom_region_update_pixmap (ZoomRegion *zoom_region,
01795 const GdkRectangle update_rect,
01796 GdkRectangle *p_rect)
01797 {
01798 GdkPixbuf *subimage;
01799 GdkRectangle source_rect;
01800
01801 #ifdef ZOOM_REGION_DEBUG
01802 g_assert (zoom_region->alive);
01803 #endif
01804 DEBUG_RECT ("unclipped update rect", update_rect);
01805 source_rect = zoom_region_clip_to_source (zoom_region, update_rect);
01806 DEBUG_RECT ("clipped to source", source_rect);
01807 source_rect = zoom_region_clip_to_exposed_target (zoom_region, source_rect);
01808 DEBUG_RECT ("update rect clipped to exposed target", source_rect);
01809
01810 subimage = zoom_region_get_source_subwindow (zoom_region, source_rect);
01811
01812 if (subimage)
01813 {
01814 GdkRectangle paint_rect;
01815 g_timer_start (mag_timing.scale);
01816 DEBUG_RECT ("source rect", source_rect);
01817 paint_rect = zoom_region_view_rect_from_source_rect (zoom_region, source_rect);
01818 if (p_rect) {
01819 *p_rect = paint_rect;
01820 }
01821
01822 DEBUG_RECT ("paint rect", paint_rect);
01823
01824 zoom_region_process_pixbuf (zoom_region, subimage);
01825
01830 gdk_pixbuf_scale (subimage,
01831 zoom_region->priv->scaled_pixbuf,
01832 0,
01833 0,
01834 paint_rect.width,
01835 paint_rect.height,
01836 0,
01837 0,
01838 zoom_region->xscale,
01839 zoom_region->yscale,
01840 zoom_region->priv->gdk_interp_type);
01841
01842 zoom_region_post_process_pixbuf (zoom_region, subimage,
01843 zoom_region->priv->scaled_pixbuf);
01844 if (zoom_region->priv->default_gc == NULL)
01845 zoom_region->priv->default_gc = gdk_gc_new(zoom_region->priv->w->window);
01846
01847 #ifndef USE_GDK_PIXBUF_RENDER_TO_DRAWABLE
01848 if (GDK_IS_DRAWABLE (zoom_region->priv->pixmap))
01849 gdk_draw_pixbuf (zoom_region->priv->pixmap,
01850 zoom_region->priv->default_gc,
01851 zoom_region->priv->scaled_pixbuf,
01852 0,
01853 0,
01854 paint_rect.x + zoom_region->priv->exposed_bounds.x1 - zoom_region->priv->source_area.x1 * zoom_region->xscale,
01855 paint_rect.y + zoom_region->priv->exposed_bounds.y1 - zoom_region->priv->source_area.y1 * zoom_region->yscale,
01856 paint_rect.width,
01857 paint_rect.height,
01858 GDK_RGB_DITHER_NONE,
01859 0,
01860 0);
01861 else
01862 g_warning ("updating non-drawable pixmap: region %p", zoom_region);
01863 #else
01864 gdk_pixbuf_render_to_drawable (zoom_region->priv->scaled_pixbuf,
01865 zoom_region->priv->pixmap,
01866 zoom_region->priv->default_gc,
01867 0,
01868 0,
01869 paint_rect.x + zoom_region->priv->exposed_bounds.x1,
01870 paint_rect.y + zoom_region->priv->exposed_bounds.y1,
01871 paint_rect.width,
01872 paint_rect.height,
01873 GDK_RGB_DITHER_NONE,
01874 0,
01875 0);
01876 #endif
01877 if (gmag_gs_error_check ())
01878 g_warning ("Could not render scaled image to drawable; out of memory!\n");
01879 g_object_unref (subimage);
01880
01881 g_timer_stop (mag_timing.scale);
01882 }
01883 return source_rect;
01884 }
01885
01892 static void
01893 zoom_region_update (ZoomRegion *zoom_region,
01894 const GdkRectangle update_rect)
01895 {
01896 GdkRectangle paint_rect = {0, 0, 0, 0};
01897 if (zoom_region->priv->w && zoom_region->priv->w->window) {
01898 GdkRectangle source_rect = zoom_region_update_pixmap (zoom_region, update_rect, &paint_rect);
01899 if (paint_rect.x != 0 || paint_rect.y != 0 ||
01900 paint_rect.width != 0 || paint_rect.height != 0) {
01901 gdk_window_begin_paint_rect (
01902 zoom_region->priv->w->window, &paint_rect);
01903 zoom_region_paint (zoom_region, &paint_rect);
01904 gdk_window_end_paint (zoom_region->priv->w->window);
01905 }
01906 if (timing_test) {
01907 mag_timing.num_scale_samples++;
01908
01909 gulong microseconds;
01910
01911 mag_timing.scale_val =
01912 g_timer_elapsed (mag_timing.scale,
01913 µseconds);
01914 mag_timing.scale_total += mag_timing.scale_val;
01915
01916 if (mag_timing.scale_val != 0 && (timing_scale_max == 0 ||
01917 (1.0/(float)mag_timing.scale_val) > (1.0/(float)timing_scale_max)))
01918 timing_scale_max = mag_timing.scale_val;
01919 if ((source_rect.height * source_rect.width / mag_timing.scale_val) > update_nrr_max)
01920 update_nrr_max = source_rect.height * source_rect.width / mag_timing.scale_val;
01921
01922 mag_timing.update_pixels_total += source_rect.height * source_rect.width;
01923
01924 if (zoom_region->timing_output) {
01925 fprintf(stderr, " Update Duration = %f (avg. %f) (max. %f) (tot. %f) seconds\n",
01926 mag_timing.scale_val, (mag_timing.scale_total /
01927 mag_timing.num_scale_samples), timing_scale_max, mag_timing.scale_total);
01928 fprintf(stderr, " Update Pixels = %ld (avg. %ld) pixels/frame\n",
01929 (long) source_rect.height * source_rect.width,
01930 mag_timing.update_pixels_total / mag_timing.num_scale_samples);
01931 fprintf(stderr, " Update Rate = (avg. %f) (max. %f) updates/second\n",
01932 1.0/(mag_timing.scale_total / mag_timing.num_scale_samples), 1.0/(float)timing_scale_max);
01933 fprintf(stderr, " Net Update Rate = (avg. %f) (max. %f) Mpex/second\n",
01934 ((float)mag_timing.update_pixels_total / (float)mag_timing.scale_total) / 1000000.0,
01935 update_nrr_max / 1000000.0);
01936 }
01937 }
01938 } else {
01939 fprintf (stderr, "update on uninitialized zoom region!\n");
01940 }
01941 }
01942
01943 static void
01944 zoom_region_init_window (ZoomRegion *zoom_region)
01945 {
01946 GtkFixed *parent;
01947 GtkWidget *zoomer, *border;
01948 DBG(fprintf (stderr, "window not yet created...\n"));
01949 parent = GTK_FIXED (
01950 ((Magnifier *)zoom_region->priv->parent)->priv->canvas);
01951 zoomer = gtk_drawing_area_new ();
01952 border = gtk_drawing_area_new ();
01953 zoom_region->priv->border = border;
01954 zoom_region->priv->w = zoomer;
01955
01956 #ifdef ZOOM_REGION_DEBUG
01957 g_assert (zoom_region->alive);
01958 #endif
01959 gtk_widget_set_size_request (GTK_WIDGET (border),
01960 zoom_region->viewport.x2 -
01961 zoom_region->viewport.x1,
01962 zoom_region->viewport.y2 -
01963 zoom_region->viewport.y1);
01964 gtk_widget_set_size_request (GTK_WIDGET (zoomer),
01965 zoom_region->viewport.x2 -
01966 zoom_region->viewport.x1 -
01967 (zoom_region->border_size_right +
01968 zoom_region->border_size_left),
01969 zoom_region->viewport.y2 -
01970 zoom_region->viewport.y1 -
01971 (zoom_region->border_size_bottom +
01972 zoom_region->border_size_top));
01973 gtk_fixed_put (parent, border,
01974 zoom_region->viewport.x1,
01975 zoom_region->viewport.y1);
01976 gtk_fixed_put (parent, zoomer,
01977 zoom_region->viewport.x1 +
01978 zoom_region->border_size_left,
01979 zoom_region->viewport.y1 +
01980 zoom_region->border_size_top);
01981 gtk_widget_show (GTK_WIDGET (border));
01982 gtk_widget_show (GTK_WIDGET (zoomer));
01983 gtk_widget_show (GTK_WIDGET (parent));
01984 zoom_region->priv->expose_handler_id =
01985 g_signal_connect (G_OBJECT (zoom_region->priv->w),
01986 "expose_event",
01987 G_CALLBACK (zoom_region_expose_handler),
01988 zoom_region);
01989 DBG(fprintf (stderr, "New window created\n"));
01990 }
01991
01992 static int
01993 zoom_region_process_updates (gpointer data)
01994 {
01995 ZoomRegion *zoom_region = (ZoomRegion *) data;
01996
01997
01998 zoom_region_coalesce_updates (zoom_region);
01999
02000 if (zoom_region->priv->q != NULL) {
02001 GList *last = g_list_last (zoom_region->priv->q);
02002 #ifdef ZOOM_REGION_DEBUG
02003 fprintf (stderr, "qlen=%d\n", g_list_length (zoom_region->priv->q));
02004 #endif
02005 if (last) {
02006 zoom_region->priv->q = g_list_remove_link (zoom_region->priv->q,
02007 last);
02008 zoom_region_update (zoom_region,
02009 * (GdkRectangle *) last->data);
02010 g_list_free (last);
02011 #ifdef DEBUG
02012 fputs (".\n", stderr);
02013 #endif
02014 }
02015 return TRUE;
02016 }
02017 else
02018 {
02019 if (zoom_region->priv)
02020 zoom_region->priv->update_handler_id = 0;
02021 return FALSE;
02022 }
02023 }
02024
02025 void
02026 timing_report(ZoomRegion *zoom_region)
02027 {
02028 float frame_avg;
02029 float x_scroll_incr, y_scroll_incr;
02030 int width, height, x, y;
02031
02032 if (timing_test) {
02033 width = (zoom_region->viewport.x2 -
02034 zoom_region->viewport.x1) / zoom_region->xscale;
02035 height = (zoom_region->viewport.y2 -
02036 zoom_region->viewport.y1) / zoom_region->yscale;
02037
02038 frame_avg = mag_timing.frame_total / mag_timing.num_frame_samples;
02039
02040 x_scroll_incr = (float)mag_timing.dx_total / (float)mag_timing.num_line_samples;
02041 y_scroll_incr = (float)mag_timing.dy_total / (float)mag_timing.num_line_samples;
02042
02043 gdk_drawable_get_size (GDK_DRAWABLE (zoom_region->priv->w->window),
02044 &x, &y);
02045
02046 fprintf(stderr, " Frames Processed = %ld\n",
02047 mag_timing.num_frame_samples + 1);
02048 fprintf(stderr, " Width/Height/Depth = %d/%d/%d\n", x, y,
02049 gdk_drawable_get_depth (zoom_region->priv->w->window));
02050 fprintf(stderr, " Zoom Factor (x/y) = %f/%f\n", zoom_region->xscale,
02051 zoom_region->yscale);
02052 if (mag_timing.num_scale_samples != 0) {
02053 fprintf(stderr, " Update Duration = (avg. %f) (max. %f) (tot. %f) seconds\n",
02054 (mag_timing.scale_total / mag_timing.num_scale_samples), timing_scale_max, mag_timing.scale_total);
02055 fprintf(stderr, " Update Pixels = (avg. %ld) pixels/frame\n",
02056 mag_timing.update_pixels_total / mag_timing.num_scale_samples);
02057 fprintf(stderr, " Update Rate = (avg. %f) (max. %f) updates/second\n",
02058 1.0/((float)mag_timing.scale_total / (float)mag_timing.num_scale_samples),
02059 1.0/(float)timing_scale_max);
02060 fprintf(stderr, " Net Update Rate = (avg. %f) (max. %f) Mpex/second\n",
02061 ((float)mag_timing.update_pixels_total / (float)mag_timing.scale_total) / 1000000.0,
02062 update_nrr_max / 1000000.0);
02063 }
02064 fprintf(stderr, " Pan Latency = (avg. %f) (max. %f) seconds\n",
02065 (mag_timing.idle_total / mag_timing.num_idle_samples), timing_idle_max);
02066 fprintf(stderr, " Total Frame Duration = (avg. %f) (max. %f) (tot. %f) seconds\n",
02067 frame_avg, timing_frame_max, mag_timing.frame_total);
02068 fprintf(stderr, " Frame Rate = (avg. %f) (max. %f) frames/second\n",
02069 1.0 / (mag_timing.frame_total / mag_timing.num_frame_samples), cps_max);
02070 fprintf(stderr, " Scroll Delta (x) = (avg. %f) (tot. %d) lines\n",
02071 x_scroll_incr, mag_timing.dx_total);
02072 fprintf(stderr, " Scroll Delta (y) = (avg. %f) (tot. %d) lines\n",
02073 y_scroll_incr, mag_timing.dy_total);
02074 fprintf(stderr, " Scroll Rate (x) = (avg. %f) lines/second\n",
02075 x_scroll_incr / frame_avg);
02076 fprintf(stderr, " Scroll Rate (y) = (avg. %f) lines/second\n",
02077 y_scroll_incr / frame_avg);
02078
02079 fprintf(stderr, " Net Render Rate = (avg. %f) (max. %f) Mpex/second\n\n",
02080 (height * width *
02081 ((float)mag_timing.num_frame_samples / (float)mag_timing.frame_total)) / 1000000.0,
02082 nrr_max / 1000000.0);
02083 }
02084 }
02085
02086 static void
02087 zoom_region_time_frame(ZoomRegion *zoom_region, Magnifier *magnifier)
02088 {
02089 float frame_avg;
02090 float x_scroll_incr, y_scroll_incr;
02091 int width = magnifier->target_bounds.x2 - magnifier->target_bounds.x1;
02092 int height = magnifier->target_bounds.y2 - magnifier->target_bounds.y1;
02093
02094 mag_timing.num_frame_samples++;
02095 g_timer_stop (mag_timing.frame);
02096
02097 gulong microseconds;
02098
02099 mag_timing.frame_val = g_timer_elapsed (mag_timing.frame,
02100 µseconds);
02101
02102 mag_timing.frame_total += mag_timing.frame_val;
02103 if (mag_timing.frame_val > timing_frame_max)
02104 timing_frame_max = mag_timing.frame_val;
02105 if (mag_timing.frame_val != 0 && 1.0/mag_timing.frame_val > cps_max)
02106 cps_max = 1.0/mag_timing.frame_val;
02107
02108 frame_avg = mag_timing.frame_total / mag_timing.num_frame_samples;
02109
02110 x_scroll_incr = (float)mag_timing.dx_total / (float)mag_timing.num_line_samples;
02111 y_scroll_incr = (float)mag_timing.dy_total / (float)mag_timing.num_line_samples;
02112
02113 if ((height * width / mag_timing.frame_val) > nrr_max)
02114 nrr_max = height * width / mag_timing.frame_val;
02115
02116 if (zoom_region->timing_output) {
02117 fprintf(stderr, " Total Frame Duration = %f (avg. %f) (max. %f) (tot. %f) seconds\n",
02118 mag_timing.frame_val, frame_avg, timing_frame_max, mag_timing.frame_total);
02119 fprintf(stderr, " Frame Rate = (avg. %f) (max. %f) frames/second\n",
02120 1.0 /frame_avg, cps_max);
02121 fprintf(stderr, " Scroll Delta (x) = (avg. %f) (tot. %d) lines\n",
02122 x_scroll_incr, mag_timing.dx_total);
02123 fprintf(stderr, " Scroll Delta (y) = (avg. %f) (tot. %d) lines\n",
02124 y_scroll_incr, mag_timing.dy_total);
02125 fprintf(stderr, " Scroll Rate (x) = (avg. %f) lines/second\n",
02126 x_scroll_incr / frame_avg);
02127 fprintf(stderr, " Scroll Rate (y) = (avg. %f) lines/second\n",
02128 y_scroll_incr / frame_avg);
02129
02130 fprintf(stderr, " Net Render Rate = (avg. %f) (max. %f) Mpex/second\n",
02131 (height * width *
02132 ((float)mag_timing.num_frame_samples / (float)mag_timing.frame_total)) / 1000000.0,
02133 nrr_max / 1000000.0);
02134 }
02135
02136 mag_timing.last_frame_val = mag_timing.frame_val;
02137 mag_timing.last_dy = mag_timing.dy;
02138
02139 if (reset_timing) {
02140 fprintf(stderr, "\n### Updates summary:\n\n");
02141 timing_report (zoom_region);
02142 fprintf(stderr, "\n### Updates finished, starting panning test\n");
02143 reset_timing_stats();
02144 reset_timing = FALSE;
02145 }
02146 }
02147
02148 static void
02149 zoom_region_sync (ZoomRegion *zoom_region)
02150 {
02151 while (zoom_region->priv->q)
02152 zoom_region_process_updates (zoom_region);
02153 }
02154
02155 static gboolean
02156 gdk_timing_idle (gpointer data)
02157 {
02158 ZoomRegion *zoom_region = data;
02159
02160
02161 processing_updates = FALSE;
02162 g_timer_stop (mag_timing.idle);
02163
02164 if (timing_test) {
02165 mag_timing.num_idle_samples++;
02166
02167 gulong microseconds;
02168
02169 mag_timing.idle_val = g_timer_elapsed (mag_timing.idle,
02170 µseconds);
02171 mag_timing.idle_total += mag_timing.idle_val;
02172
02173 if (mag_timing.idle_val > timing_idle_max)
02174 timing_idle_max = mag_timing.idle_val;
02175
02176 if (zoom_region->timing_output) {
02177 fprintf(stderr, " Pan Latency = %f (avg. %f) (max. %f) seconds\n",
02178 mag_timing.idle_val, (mag_timing.idle_total /
02179 mag_timing.num_idle_samples), timing_idle_max);
02180 }
02181 }
02182
02183 return FALSE;
02184 }
02185
02186 static void
02187 zoom_region_get_move_x_y (ZoomRegion *zoom_region, long *x, long *y)
02188 {
02189 long width, height;
02190
02191 width = (zoom_region->viewport.x2 - zoom_region->viewport.x1) /
02192 zoom_region->xscale;
02193 height = (zoom_region->viewport.y2 - zoom_region->viewport.y1) /
02194 zoom_region->yscale;
02195
02196 switch (zoom_region->x_align_policy) {
02197 case GNOME_Magnifier_ZoomRegion_ALIGN_MAX:
02198 *x = zoom_region->roi.x2 - width;
02199 break;
02200 case GNOME_Magnifier_ZoomRegion_ALIGN_MIN:
02201 *x = zoom_region->roi.x1;
02202 break;
02203 case GNOME_Magnifier_ZoomRegion_ALIGN_CENTER:
02204 default:
02205 *x = ((zoom_region->roi.x1 + zoom_region->roi.x2) - width ) /
02206 2;
02207 }
02208
02209 switch (zoom_region->y_align_policy) {
02210 case GNOME_Magnifier_ZoomRegion_ALIGN_MAX:
02211 *y = zoom_region->roi.y2 - height;
02212 break;
02213 case GNOME_Magnifier_ZoomRegion_ALIGN_MIN:
02214 *y = zoom_region->roi.y1;
02215 break;
02216 case GNOME_Magnifier_ZoomRegion_ALIGN_CENTER:
02217 default:
02218 *y = ((zoom_region->roi.y1 + zoom_region->roi.y2) - height ) /
02219 2;
02220 }
02221 }
02222
02223 static void
02224 zoom_region_align (ZoomRegion *zoom_region)
02225 {
02226 Magnifier *magnifier = zoom_region->priv->parent;
02227 long x = 0, y = 0;
02228
02229 if (timing_start)
02230 zoom_region_time_frame(zoom_region, magnifier);
02231
02232 if (timing_test) {
02233 g_timer_start (mag_timing.frame);
02234
02235 if (zoom_region->timing_output) {
02236 gint x, y;
02237
02238 gdk_drawable_get_size (GDK_DRAWABLE (zoom_region->priv->w->window),
02239 &x, &y);
02240
02241 fprintf(stderr, "\nTiming Information - ROI = (%d, %d) (%d, %d):\n",
02242 zoom_region->roi.x1, zoom_region->roi.y1, zoom_region->roi.x2,
02243 zoom_region->roi.y2);
02244 fprintf(stderr, " Frame Number = %ld\n",
02245 mag_timing.num_frame_samples + 1);
02246 fprintf(stderr, " Width/Height/Depth = %d/%d/%d\n", x, y,
02247 gdk_drawable_get_depth (zoom_region->priv->w->window));
02248 }
02249
02250
02251
02252
02253
02254 if (!timing_start)
02255 g_timer_start (mag_timing.process);
02256
02257 timing_start = TRUE;
02258 }
02259
02260 g_timer_start (mag_timing.idle);
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279 g_idle_add_full (GDK_PRIORITY_REDRAW + 1,
02280 gdk_timing_idle, zoom_region, NULL);
02281
02282 zoom_region_get_move_x_y (zoom_region, &x, &y);
02283
02284 zoom_region_moveto (zoom_region, x, y);
02285 }
02286
02287 static void
02288 zoom_region_set_viewport (ZoomRegion *zoom_region,
02289 const GNOME_Magnifier_RectBounds *viewport)
02290 {
02291 #ifdef ZOOM_REGION_DEBUG
02292 g_assert (zoom_region->alive);
02293 #endif
02294 if (zoom_region->viewport.x1 == viewport->x1 &&
02295 zoom_region->viewport.y1 == viewport->y1 &&
02296 zoom_region->viewport.x2 == viewport->x2 &&
02297 zoom_region->viewport.y2 == viewport->y2) {
02298 return;
02299 }
02300 zoom_region->viewport = *viewport;
02301 #ifdef DEBUG
02302 fprintf (stderr, "Setting viewport %d,%d - %d,%d\n",
02303 (int) viewport->x1, (int) viewport->y1,
02304 (int) viewport->x2, (int) viewport->y2);
02305 #endif
02306 zoom_region_align (zoom_region);
02307 if (!zoom_region->priv->w) {
02308 zoom_region_init_window (zoom_region);
02309 } else {
02310 CORBA_any *any;
02311 CORBA_Environment ev;
02312 Bonobo_PropertyBag properties;
02313 Magnifier *magnifier = (Magnifier *) zoom_region->priv->parent;
02314 GtkFixed *fixed = GTK_FIXED (magnifier->priv->canvas);
02315 gtk_fixed_move (fixed,
02316 zoom_region->priv->border,
02317 zoom_region->viewport.x1,
02318 zoom_region->viewport.y1);
02319 gtk_fixed_move (fixed,
02320 zoom_region->priv->w,
02321 zoom_region->viewport.x1 +
02322 zoom_region->border_size_left,
02323 zoom_region->viewport.y1 +
02324 zoom_region->border_size_top);
02325 gtk_widget_set_size_request (
02326 GTK_WIDGET (zoom_region->priv->border),
02327 zoom_region->viewport.x2 - zoom_region->viewport.x1,
02328 zoom_region->viewport.y2 - zoom_region->viewport.y1);
02329 gtk_widget_set_size_request (GTK_WIDGET (zoom_region->priv->w),
02330 zoom_region->viewport.x2 -
02331 zoom_region->viewport.x1 -
02332 (zoom_region->border_size_right +
02333 zoom_region->border_size_left),
02334 zoom_region->viewport.y2 -
02335 zoom_region->viewport.y1 -
02336 (zoom_region->border_size_bottom +
02337 zoom_region->border_size_top));
02338 CORBA_exception_init (&ev);
02339 properties =
02340 GNOME_Magnifier_Magnifier_getProperties(
02341 BONOBO_OBJREF (
02342 (Magnifier *) zoom_region->priv->parent), &ev);
02343 if (!BONOBO_EX (&ev))
02344 any = Bonobo_PropertyBag_getValue (
02345 properties, "source-display-bounds", &ev);
02346 if (!BONOBO_EX (&ev))
02347 zoom_region->priv->source_area =
02348 *((GNOME_Magnifier_RectBounds *) any->_value);
02349 if (zoom_region->priv->pixmap)
02350 g_object_unref (zoom_region->priv->pixmap);
02351 zoom_region_create_pixmap (zoom_region);
02352 if (zoom_region->priv->scaled_pixbuf)
02353 g_object_unref (zoom_region->priv->scaled_pixbuf);
02354
02355 zoom_region->priv->scaled_pixbuf =
02356 gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
02357 (zoom_region->priv->source_area.x2 -
02358 zoom_region->priv->source_area.x1) * zoom_region->xscale + 1,
02359 (zoom_region->priv->source_area.y2 -
02360 zoom_region->priv->source_area.y1) * zoom_region->yscale + 1);
02361 }
02362 zoom_region_queue_update (zoom_region,
02363 zoom_region_source_rect_from_view_bounds (
02364 zoom_region, &zoom_region->viewport));
02365 }
02366
02367 static void
02368 zoom_region_get_property (BonoboPropertyBag *bag,
02369 BonoboArg *arg,
02370 guint arg_id,
02371 CORBA_Environment *ev,
02372 gpointer user_data)
02373 {
02374 ZoomRegion *zoom_region = user_data;
02375
02376 #ifdef ZOOM_REGION_DEBUG
02377 g_assert (zoom_region->alive);
02378 #endif
02379 DBG (fprintf (stderr, "Get zoom-region property: %s\n", prop_names[arg_id]));
02380
02381 switch (arg_id) {
02382 case ZOOM_REGION_MANAGED_PROP:
02383 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->is_managed);
02384 break;
02385 case ZOOM_REGION_POLL_MOUSE_PROP:
02386 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->poll_mouse);
02387 break;
02388 case ZOOM_REGION_DRAW_CURSOR_PROP:
02389 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->draw_cursor);
02390 break;
02391 case ZOOM_REGION_INVERT_PROP:
02392 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->invert);
02393 break;
02394 case ZOOM_REGION_SMOOTHSCROLL_PROP:
02395 BONOBO_ARG_SET_SHORT (arg, zoom_region->smooth_scroll_policy);
02396 break;
02397 case ZOOM_REGION_COLORBLIND_PROP:
02398 BONOBO_ARG_SET_SHORT (arg, zoom_region->color_blind_filter);
02399 break;
02400 case ZOOM_REGION_TESTPATTERN_PROP:
02401 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->priv->test);
02402 break;
02403 case ZOOM_REGION_SMOOTHING_PROP:
02404 BONOBO_ARG_SET_STRING (arg, zoom_region->smoothing);
02405 break;
02406 case ZOOM_REGION_CONTRASTR_PROP:
02407 BONOBO_ARG_SET_FLOAT (arg, zoom_region->contrast_r);
02408 break;
02409 case ZOOM_REGION_CONTRASTG_PROP:
02410 BONOBO_ARG_SET_FLOAT (arg, zoom_region->contrast_g);
02411 break;
02412 case ZOOM_REGION_CONTRASTB_PROP:
02413 BONOBO_ARG_SET_FLOAT (arg, zoom_region->contrast_b);
02414 break;
02415 case ZOOM_REGION_BRIGHTR_PROP:
02416 BONOBO_ARG_SET_FLOAT (arg, zoom_region->bright_r);
02417 break;
02418 case ZOOM_REGION_BRIGHTG_PROP:
02419 BONOBO_ARG_SET_FLOAT (arg, zoom_region->bright_g);
02420 break;
02421 case ZOOM_REGION_BRIGHTB_PROP:
02422 BONOBO_ARG_SET_FLOAT (arg, zoom_region->bright_b);
02423 break;
02424 case ZOOM_REGION_XSCALE_PROP:
02425 BONOBO_ARG_SET_FLOAT (arg, zoom_region->xscale);
02426 break;
02427 case ZOOM_REGION_YSCALE_PROP:
02428 BONOBO_ARG_SET_FLOAT (arg, zoom_region->yscale);
02429 break;
02430 case ZOOM_REGION_BORDERSIZE_PROP:
02431 BONOBO_ARG_SET_LONG (
02432 arg, (zoom_region->border_size_top +
02433 zoom_region->border_size_left +
02434 zoom_region->border_size_right +
02435 zoom_region->border_size_bottom) / 4);
02436 break;
02437 case ZOOM_REGION_BORDERSIZETOP_PROP:
02438 BONOBO_ARG_SET_LONG (arg, zoom_region->border_size_top);
02439 break;
02440 case ZOOM_REGION_BORDERSIZELEFT_PROP:
02441 BONOBO_ARG_SET_LONG (arg, zoom_region->border_size_left);
02442 break;
02443 case ZOOM_REGION_BORDERSIZERIGHT_PROP:
02444 BONOBO_ARG_SET_LONG (arg, zoom_region->border_size_right);
02445 break;
02446 case ZOOM_REGION_BORDERSIZEBOTTOM_PROP:
02447 BONOBO_ARG_SET_LONG (arg, zoom_region->border_size_bottom);
02448 break;
02449 case ZOOM_REGION_XALIGN_PROP:
02450
02451 BONOBO_ARG_SET_INT (arg, zoom_region->x_align_policy);
02452 break;
02453 case ZOOM_REGION_YALIGN_PROP:
02454 BONOBO_ARG_SET_INT (arg, zoom_region->y_align_policy);
02455 break;
02456 case ZOOM_REGION_BORDERCOLOR_PROP:
02457 BONOBO_ARG_SET_LONG (arg,
02458 zoom_region->border_color);
02459 break;
02460 case ZOOM_REGION_VIEWPORT_PROP:
02461 BONOBO_ARG_SET_GENERAL (arg, zoom_region->viewport,
02462 TC_GNOME_Magnifier_RectBounds,
02463 GNOME_Magnifier_RectBounds,
02464 NULL);
02465 break;
02466 case ZOOM_REGION_TIMING_TEST_PROP:
02467 BONOBO_ARG_SET_INT (arg, zoom_region->timing_iterations);
02468 break;
02469 case ZOOM_REGION_TIMING_OUTPUT_PROP:
02470 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->timing_output);
02471 break;
02472 case ZOOM_REGION_TIMING_PAN_RATE_PROP:
02473 BONOBO_ARG_SET_INT (arg, zoom_region->timing_pan_rate);
02474 break;
02475 case ZOOM_REGION_EXIT_MAGNIFIER:
02476 BONOBO_ARG_SET_BOOLEAN (arg, zoom_region->exit_magnifier);
02477 break;
02478 default:
02479 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
02480 };
02481 }
02482
02483 static void
02484 zoom_region_update_borders (ZoomRegion *zoom_region)
02485 {
02486 gtk_widget_set_size_request (GTK_WIDGET (zoom_region->priv->border),
02487 zoom_region->viewport.x2 -
02488 zoom_region->viewport.x1,
02489 zoom_region->viewport.y2 -
02490 zoom_region->viewport.y1);
02491 gtk_widget_set_size_request (GTK_WIDGET (zoom_region->priv->w),
02492 zoom_region->viewport.x2 -
02493 zoom_region->viewport.x1 -
02494 (zoom_region->border_size_right +
02495 zoom_region->border_size_left),
02496 zoom_region->viewport.y2 -
02497 zoom_region->viewport.y1 -
02498 (zoom_region->border_size_bottom +
02499 zoom_region->border_size_top));
02500 gtk_fixed_move (GTK_FIXED (((Magnifier *)zoom_region->priv->parent)->priv->canvas), zoom_region->priv->border, zoom_region->viewport.x1, zoom_region->viewport.y1);
02501 gtk_fixed_move (GTK_FIXED (((Magnifier *)zoom_region->priv->parent)->priv->canvas), zoom_region->priv->w, zoom_region->viewport.x1 + zoom_region->border_size_left, zoom_region->viewport.y1 + zoom_region->border_size_top);
02502 }
02503
02504 static void
02505 zoom_region_set_property (BonoboPropertyBag *bag,
02506 BonoboArg *arg,
02507 guint arg_id,
02508 CORBA_Environment *ev,
02509 gpointer user_data)
02510 {
02511 ZoomRegion *zoom_region = user_data;
02512 GNOME_Magnifier_RectBounds bounds;
02513 gfloat t;
02514
02515 #ifdef ZOOM_REGION_DEBUG
02516 g_assert (zoom_region->alive);
02517 #endif
02518 DBG (fprintf (stderr, "Set zoom-region property: %s\n", prop_names[arg_id]));
02519
02520 switch (arg_id) {
02521 case ZOOM_REGION_MANAGED_PROP:
02522 zoom_region->is_managed = BONOBO_ARG_GET_BOOLEAN (arg);
02523 break;
02524 case ZOOM_REGION_POLL_MOUSE_PROP:
02525 zoom_region->poll_mouse = BONOBO_ARG_GET_BOOLEAN (arg);
02526 if (zoom_region->poll_mouse)
02527 {
02528 g_message ("Adding polling timer");
02529 zoom_region->priv->update_pointer_id =
02530 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
02531 200,
02532 zoom_region_update_pointer_timeout,
02533 zoom_region,
02534 NULL);
02535 }
02536 else if (zoom_region->priv->update_pointer_id)
02537 {
02538 g_message ("Removing polling timer");
02539 g_source_remove (zoom_region->priv->update_pointer_id);
02540 zoom_region->priv->update_pointer_id = 0;
02541 }
02542 break;
02543 case ZOOM_REGION_DRAW_CURSOR_PROP:
02544 zoom_region->draw_cursor = BONOBO_ARG_GET_BOOLEAN (arg);
02545 if (!zoom_region->draw_cursor)
02546 zoom_region_unpaint_cursor (zoom_region, NULL);
02547 break;
02548 case ZOOM_REGION_INVERT_PROP:
02549 zoom_region->invert = BONOBO_ARG_GET_BOOLEAN (arg);
02550 zoom_region_update_current (zoom_region);
02551 break;
02552 case ZOOM_REGION_SMOOTHSCROLL_PROP:
02553 zoom_region->smooth_scroll_policy = BONOBO_ARG_GET_SHORT (arg);
02554 break;
02555 case ZOOM_REGION_COLORBLIND_PROP:
02556 zoom_region->color_blind_filter = BONOBO_ARG_GET_SHORT (arg);
02557
02558 switch (zoom_region->color_blind_filter) {
02559 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_NO_FILTER:
02560 break;
02561 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_SATURATE_RED:
02562 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_saturate_red);
02563 break;
02564 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_SATURATE_GREEN:
02565 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_saturate_green);
02566 break;
02567 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_SATURATE_BLUE:
02568 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_saturate_blue);
02569 break;
02570 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_RED:
02571 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_dessaturate_red);
02572 break;
02573 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_GREEN:
02574 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_dessaturate_green);
02575 break;
02576 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE_BLUE:
02577 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_dessaturate_blue);
02578 break;
02579 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_HUE_SHIFT_POSITIVE:
02580 colorblind_set_filter_type (cbr, colorblind_filter_t_hue_shift_positive);
02581 break;
02582 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_HUE_SHIFT_NEGATIVE:
02583 colorblind_set_filter_type (cbr, colorblind_filter_t_hue_shift_negative);
02584 break;
02585 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_SATURATE:
02586 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_saturate);
02587 break;
02588 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_SELECTIVE_DESSATURATE:
02589 colorblind_set_filter_type (cbr, colorblind_filter_t_selective_dessaturate);
02590 break;
02591 case GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_MONOCHRONE_OTHERS:
02592 colorblind_set_filter_type (cbr, colorblind_filter_t_monochrome_others);
02593 break;
02594 }
02595
02596 zoom_region_update_current (zoom_region);
02597 break;
02598 case ZOOM_REGION_SMOOTHING_PROP:
02599 zoom_region->smoothing = BONOBO_ARG_GET_STRING (arg);
02600 if (!strncmp (zoom_region->smoothing, "bilinear", 8))
02601 zoom_region->priv->gdk_interp_type = GDK_INTERP_BILINEAR;
02602 else
02603 zoom_region->priv->gdk_interp_type = GDK_INTERP_NEAREST;
02604 zoom_region_update_current (zoom_region);
02605 break;
02606 case ZOOM_REGION_TESTPATTERN_PROP:
02607 zoom_region->priv->test = BONOBO_ARG_GET_BOOLEAN (arg);
02608 if (zoom_region->priv->source_drawable) {
02609 g_object_unref (zoom_region->priv->source_drawable);
02610 zoom_region->priv->source_drawable = NULL;
02611 }
02612 zoom_region_update_current (zoom_region);
02613 break;
02614 case ZOOM_REGION_CONTRASTR_PROP:
02615 zoom_region->contrast_r =
02616 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02617 zoom_region_update_current (zoom_region);
02618 break;
02619 case ZOOM_REGION_CONTRASTG_PROP:
02620 zoom_region->contrast_g =
02621 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02622 zoom_region_update_current (zoom_region);
02623 break;
02624 case ZOOM_REGION_CONTRASTB_PROP:
02625 zoom_region->contrast_b =
02626 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02627 zoom_region_update_current (zoom_region);
02628 break;
02629 case ZOOM_REGION_BRIGHTR_PROP:
02630 zoom_region->bright_r =
02631 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02632 zoom_region_update_current (zoom_region);
02633 break;
02634 case ZOOM_REGION_BRIGHTG_PROP:
02635 zoom_region->bright_g =
02636 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02637 zoom_region_update_current (zoom_region);
02638 break;
02639 case ZOOM_REGION_BRIGHTB_PROP:
02640 zoom_region->bright_b =
02641 CLAMP_B_C (BONOBO_ARG_GET_FLOAT (arg));
02642 zoom_region_update_current (zoom_region);
02643 break;
02644 case ZOOM_REGION_XSCALE_PROP:
02645 (void) zoom_region_update_scale (zoom_region,
02646 BONOBO_ARG_GET_FLOAT (arg),
02647 zoom_region->yscale);
02648 break;
02649 case ZOOM_REGION_YSCALE_PROP:
02650 (void) zoom_region_update_scale (zoom_region,
02651 zoom_region->xscale,
02652 BONOBO_ARG_GET_FLOAT (arg));
02653
02654 break;
02655 case ZOOM_REGION_BORDERSIZE_PROP:
02656 zoom_region->border_size_left =
02657 zoom_region->border_size_top =
02658 zoom_region->border_size_right =
02659 zoom_region->border_size_bottom =
02660 BONOBO_ARG_GET_LONG (arg);
02661 zoom_region_update_borders (zoom_region);
02662 break;
02663 case ZOOM_REGION_BORDERSIZELEFT_PROP:
02664 zoom_region->border_size_left = BONOBO_ARG_GET_LONG (arg);
02665 zoom_region_update_borders (zoom_region);
02666 break;
02667 case ZOOM_REGION_BORDERSIZETOP_PROP:
02668 zoom_region->border_size_top = BONOBO_ARG_GET_LONG (arg);
02669 zoom_region_update_borders (zoom_region);
02670 break;
02671 case ZOOM_REGION_BORDERSIZERIGHT_PROP:
02672 zoom_region->border_size_right = BONOBO_ARG_GET_LONG (arg);
02673 zoom_region_update_borders (zoom_region);
02674 break;
02675 case ZOOM_REGION_BORDERSIZEBOTTOM_PROP:
02676 zoom_region->border_size_bottom = BONOBO_ARG_GET_LONG (arg);
02677 zoom_region_update_borders (zoom_region);
02678 break;
02679 case ZOOM_REGION_BORDERCOLOR_PROP:
02680 zoom_region->border_color =
02681 BONOBO_ARG_GET_LONG (arg);
02682 zoom_region_paint_border (zoom_region);
02683 break;
02684 case ZOOM_REGION_XALIGN_PROP:
02685 zoom_region->x_align_policy = BONOBO_ARG_GET_INT (arg);
02686 zoom_region_align (zoom_region);
02687 break;
02688 case ZOOM_REGION_YALIGN_PROP:
02689
02690 zoom_region->y_align_policy = BONOBO_ARG_GET_INT (arg);
02691 zoom_region_align (zoom_region);
02692 break;
02693 case ZOOM_REGION_VIEWPORT_PROP:
02694 bounds = BONOBO_ARG_GET_GENERAL (arg,
02695 TC_GNOME_Magnifier_RectBounds,
02696 GNOME_Magnifier_RectBounds,
02697 NULL);
02698 zoom_region_set_viewport (zoom_region, &bounds);
02699 break;
02700 case ZOOM_REGION_TIMING_TEST_PROP:
02701 zoom_region->timing_iterations = BONOBO_ARG_GET_INT (arg);
02702 timing_test = TRUE;
02703 break;
02704 case ZOOM_REGION_TIMING_OUTPUT_PROP:
02705 zoom_region->timing_output = BONOBO_ARG_GET_BOOLEAN (arg);
02706 break;
02707 case ZOOM_REGION_TIMING_PAN_RATE_PROP:
02708 zoom_region->timing_pan_rate = BONOBO_ARG_GET_INT (arg);
02709 timing_test = TRUE;
02710 break;
02711 case ZOOM_REGION_EXIT_MAGNIFIER:
02712 zoom_region->exit_magnifier = BONOBO_ARG_GET_BOOLEAN (arg);
02713 break;
02714 default:
02715 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
02716 };
02717 }
02718
02719 static int
02720 zoom_region_process_pending (gpointer data)
02721 {
02722 ZoomRegion *zoom_region = (ZoomRegion *) data;
02723
02724 #ifdef ZOOM_REGION_DEBUG
02725 g_assert (zoom_region->alive);
02726 #endif
02727 zoom_region_align (zoom_region);
02728 return FALSE;
02729 }
02730
02731 static int
02732 zoom_region_pan_test (gpointer data)
02733 {
02734 ZoomRegion *zoom_region = (ZoomRegion *) data;
02735 Magnifier *magnifier = zoom_region->priv->parent;
02736 GNOME_Magnifier_ZoomRegionList *zoom_regions;
02737 GNOME_Magnifier_RectBounds roi;
02738 CORBA_Environment ev;
02739 static int counter = 0;
02740 static gboolean finished_update = !TRUE;
02741 static float last_pixels_at_speed = -1;
02742 float pixels_at_speed;
02743 float total_time;
02744 int screen_height, height;
02745 int pixel_position;
02746 int pixel_direction;
02747
02748 screen_height = gdk_screen_get_height (
02749 gdk_display_get_screen (magnifier->source_display,
02750 magnifier->source_screen_num));
02751
02752 height = (zoom_region->viewport.y2 -
02753 zoom_region->viewport.y1) / zoom_region->yscale;
02754
02755 roi.x1 = zoom_region->roi.x1;
02756 roi.x2 = zoom_region->roi.x2;
02757
02758 g_timer_stop (mag_timing.process);
02759
02760 gulong microseconds;
02761
02762 total_time = g_timer_elapsed (mag_timing.process, µseconds);
02763
02764 if (mag_timing.frame_total != 0.0)
02765 pixels_at_speed = total_time * zoom_region->timing_pan_rate;
02766 else
02767 pixels_at_speed = 0.0;
02768
02769
02770 if ((int)(last_pixels_at_speed) == (int)(pixels_at_speed))
02771 return TRUE;
02772
02773 pixel_position = (int)(pixels_at_speed) % (screen_height - height);
02774 counter = (int)(pixels_at_speed) / (screen_height - height);
02775 pixel_direction = counter % 2;
02776
02777 if (!finished_update) {
02778 if ((int)(pixels_at_speed) > (zoom_region->roi.y1 + height))
02779 roi.y1 = zoom_region->roi.y1 + height;
02780 else
02781 roi.y1 = (int)(pixels_at_speed);
02782
02783 if (roi.y1 >= screen_height - height) {
02784 roi.y1 = screen_height - height;
02785 }
02786 } else {
02787 if (pixel_direction == 0)
02788 roi.y1 = screen_height - height - pixel_position;
02789 else
02790 roi.y1 = pixel_position;
02791 }
02792
02793 roi.y2 = roi.y1 + height;
02794 magnifier->priv->cursor_x = (roi.x2 + roi.x1) / 2;
02795 magnifier->priv->cursor_y = (roi.y2 + roi.y1) / 2;
02796
02797
02798 if (counter > zoom_region->timing_iterations - 1)
02799 zoom_region->exit_magnifier = TRUE;
02800
02801 zoom_regions = GNOME_Magnifier_Magnifier_getZoomRegions (
02802 BONOBO_OBJREF (magnifier), &ev);
02803
02804 if (zoom_regions && (zoom_regions->_length > 0)) {
02805 GNOME_Magnifier_ZoomRegion_setROI (
02806 zoom_regions->_buffer[0], &roi, &ev);
02807 }
02808
02809 if (!finished_update) {
02810 zoom_region_process_updates(zoom_region);
02811 if (roi.y1 == screen_height - height) {
02812 finished_update = TRUE;
02813 reset_timing = TRUE;
02814 }
02815 }
02816
02817 last_pixels_at_speed = pixels_at_speed;
02818
02819 return FALSE;
02820 }
02821
02822 static void
02823 impl_zoom_region_set_pointer_pos (PortableServer_Servant servant,
02824 const CORBA_long mouse_x,
02825 const CORBA_long mouse_y,
02826 CORBA_Environment *ev)
02827 {
02828 ZoomRegion *zoom_region =
02829 ZOOM_REGION (bonobo_object_from_servant (servant));
02830 GdkRectangle paint_area, *clip = NULL;
02831
02832 #ifdef ZOOM_REGION_DEBUG
02833 g_assert (zoom_region->alive);
02834 #endif
02835 DBG (fprintf (stderr, "Set Pointer: \t%ld,%ld\n",
02836 (long) mouse_x, (long) mouse_y));
02837
02838 fprintf (stderr, "Set Pointer: \t%ld,%ld\n",
02839 (long) mouse_x, (long) mouse_y);
02840
02841 zoom_region_set_cursor_pos (zoom_region, (int) mouse_x, (int) mouse_y);
02842
02843 if (GTK_IS_WIDGET (zoom_region->priv->w) &&
02844 GDK_IS_DRAWABLE (zoom_region->priv->w->window))
02845 {
02846 gdk_drawable_get_size (
02847 GDK_DRAWABLE (
02848 zoom_region->priv->w->window),
02849 &paint_area.width, &paint_area.height);
02850 paint_area.x = 0;
02851 paint_area.y = 0;
02852 clip = &paint_area;
02853 paint_area = zoom_region_clip_to_source (
02854 zoom_region, paint_area);
02855 }
02856
02857
02858
02859
02860
02861 }
02862
02863 static void
02864 impl_zoom_region_set_contrast (PortableServer_Servant servant,
02865 const CORBA_float R,
02866 const CORBA_float G,
02867 const CORBA_float B,
02868 CORBA_Environment *ev)
02869 {
02870 ZoomRegion *zoom_region =
02871 ZOOM_REGION (bonobo_object_from_servant (servant));
02872 gfloat t;
02873
02874 #ifdef ZOOM_REGION_DEBUG
02875 g_assert (zoom_region->alive);
02876 #endif
02877 DBG (fprintf (stderr, "Set contrast: \t%f,%f %f\n", R, G, B));
02878
02879
02880 if (zoom_region->contrast_r == R &&
02881 zoom_region->contrast_g == G &&
02882 zoom_region->contrast_b == B)
02883 return;
02884
02885 zoom_region->contrast_r = CLAMP_B_C (R);
02886 zoom_region->contrast_g = CLAMP_B_C (G);
02887 zoom_region->contrast_b = CLAMP_B_C (B);
02888
02889 zoom_region_update_current (zoom_region);
02890 }
02891
02892 static void
02893 impl_zoom_region_get_contrast (PortableServer_Servant servant,
02894 CORBA_float *R,
02895 CORBA_float *G,
02896 CORBA_float *B,
02897 CORBA_Environment *ev)
02898 {
02899 ZoomRegion *zoom_region =
02900 ZOOM_REGION (bonobo_object_from_servant (servant));
02901
02902 #ifdef ZOOM_REGION_DEBUG
02903 g_assert (zoom_region->alive);
02904 #endif
02905
02906 *R = zoom_region->contrast_r;
02907 *G = zoom_region->contrast_g;
02908 *B = zoom_region->contrast_b;
02909 }
02910
02911 static void
02912 impl_zoom_region_set_brightness (PortableServer_Servant servant,
02913 const CORBA_float R,
02914 const CORBA_float G,
02915 const CORBA_float B,
02916 CORBA_Environment *ev)
02917 {
02918 ZoomRegion *zoom_region =
02919 ZOOM_REGION (bonobo_object_from_servant (servant));
02920 gfloat t;
02921
02922 #ifdef ZOOM_REGION_DEBUG
02923 g_assert (zoom_region->alive);
02924 #endif
02925 DBG (fprintf (stderr, "Set brightness: \t%f,%f %f\n", R, G, B));
02926
02927
02928 if (zoom_region->bright_r == R &&
02929 zoom_region->bright_g == G &&
02930 zoom_region->bright_b == B)
02931 return;
02932
02933 zoom_region->bright_r = CLAMP_B_C (R);
02934 zoom_region->bright_g = CLAMP_B_C (G);
02935 zoom_region->bright_b = CLAMP_B_C (B);
02936
02937 zoom_region_update_current (zoom_region);
02938 }
02939
02940 static void
02941 impl_zoom_region_get_brightness (PortableServer_Servant servant,
02942 CORBA_float *R,
02943 CORBA_float *G,
02944 CORBA_float *B,
02945 CORBA_Environment *ev)
02946 {
02947 ZoomRegion *zoom_region =
02948 ZOOM_REGION (bonobo_object_from_servant (servant));
02949
02950 #ifdef ZOOM_REGION_DEBUG
02951 g_assert (zoom_region->alive);
02952 #endif
02953
02954 *R = zoom_region->bright_r;
02955 *G = zoom_region->bright_g;
02956 *B = zoom_region->bright_b;
02957 }
02958
02959 static void
02960 impl_zoom_region_set_roi (PortableServer_Servant servant,
02961 const GNOME_Magnifier_RectBounds *bounds,
02962 CORBA_Environment *ev)
02963 {
02964 ZoomRegion *zoom_region =
02965 ZOOM_REGION (bonobo_object_from_servant (servant));
02966
02967 #ifdef ZOOM_REGION_DEBUG
02968 g_assert (zoom_region->alive);
02969 #endif
02970 DBG (fprintf (stderr, "Set ROI: \t%d,%d %d,%d\n",
02971 bounds->x1, bounds->y1, bounds->x2, bounds->y2));
02972
02973 if ((zoom_region->roi.x1 == bounds->x1) &&
02974 (zoom_region->roi.x2 == bounds->x2) &&
02975 (zoom_region->roi.y1 == bounds->y1) &&
02976 (zoom_region->roi.y2 == bounds->y2)) {
02977 return;
02978 }
02979
02980
02981 if (!bounds || (bounds->x2 <= bounds->x1)
02982 || (bounds->y2 < bounds->y1) ||
02983 ((bounds->x1 + bounds->x2)/2 < 0) ||
02984 ((bounds->y1 + bounds->y2)/2 < 0))
02985 {
02986 g_warning ("Bad bounds request (%d,%d to %d,%d), ignoring.\n",
02987 bounds->x1, bounds->y1, bounds->x2, bounds->y2);
02988 return;
02989 }
02990
02991 zoom_region->roi = *bounds;
02992
02993 if (zoom_region->timing_pan_rate > 0) {
02994
02995 g_idle_add_full (GDK_PRIORITY_REDRAW + 3,
02996 zoom_region_pan_test, zoom_region, NULL);
02997 }
02998
02999 if (zoom_region->exit_magnifier) {
03000 if (timing_test) {
03001 fprintf(stderr, "\n### Timing Summary:\n\n");
03002 if (zoom_region->timing_pan_rate)
03003 fprintf(stderr, " Pan Rate = %d\n", zoom_region->timing_pan_rate);
03004 timing_report(zoom_region);
03005 }
03006 exit(0);
03007 }
03008
03009
03010
03011
03012
03013 if (processing_updates) {
03014
03015 if (pending_idle_handler != 0) {
03016 g_source_remove(pending_idle_handler);
03017 pending_idle_handler = 0;
03018 }
03019
03020
03021
03022 pending_idle_handler = g_idle_add_full (GDK_PRIORITY_REDRAW + 2,
03023 zoom_region_process_pending, zoom_region, NULL);
03024
03025 if (zoom_region->timing_output) {
03026 fprintf(stderr,
03027 "\n [Last update not finished, pending - ROI=(%d, %d) (%d, %d)]\n\n",
03028 zoom_region->roi.x1, zoom_region->roi.y1, zoom_region->roi.x2,
03029 zoom_region->roi.y2);
03030 }
03031 } else {
03032 zoom_region_align (zoom_region);
03033 }
03034 }
03035
03036 static CORBA_boolean
03037 impl_zoom_region_set_mag_factor (PortableServer_Servant servant,
03038 const CORBA_float mag_factor_x,
03039 const CORBA_float mag_factor_y,
03040 CORBA_Environment *ev)
03041 {
03042 ZoomRegion *zoom_region =
03043 ZOOM_REGION (bonobo_object_from_servant (servant));
03044
03045 #ifdef ZOOM_REGION_DEBUG
03046 g_assert (zoom_region->alive);
03047 #endif
03048 CORBA_any *any;
03049 CORBA_boolean retval = CORBA_TRUE;
03050
03051 if ((zoom_region->xscale == mag_factor_x) &&
03052 (zoom_region->yscale == mag_factor_y)) {
03053 return retval;
03054 }
03055
03056
03057 Bonobo_PropertyBag properties =
03058 GNOME_Magnifier_Magnifier_getProperties(
03059 BONOBO_OBJREF (
03060 (Magnifier *) zoom_region->priv->parent), ev);
03061 any = Bonobo_PropertyBag_getValue (
03062 properties, "source-display-bounds", ev);
03063 if (!BONOBO_EX (ev))
03064 zoom_region->priv->source_area =
03065 *((GNOME_Magnifier_RectBounds *) any->_value);
03066 else
03067 retval = CORBA_FALSE;
03068
03069 retval = zoom_region_update_scale (zoom_region,
03070 mag_factor_x, mag_factor_y);
03071 zoom_region_sync (zoom_region);
03072
03073 bonobo_object_release_unref (properties, NULL);
03074 return retval;
03075 }
03076
03077 static void
03078 impl_zoom_region_get_mag_factor (PortableServer_Servant servant,
03079 CORBA_float *mag_factor_x,
03080 CORBA_float *mag_factor_y,
03081 CORBA_Environment *ev)
03082 {
03083 ZoomRegion *zoom_region =
03084 ZOOM_REGION (bonobo_object_from_servant (servant));
03085
03086 #ifdef ZOOM_REGION_DEBUG
03087 g_assert (zoom_region->alive);
03088 #endif
03089 *mag_factor_x = zoom_region->xscale;
03090 *mag_factor_y = zoom_region->yscale;
03091 }
03092
03093 static Bonobo_PropertyBag
03094 impl_zoom_region_get_properties (PortableServer_Servant servant,
03095 CORBA_Environment *ev)
03096 {
03097 ZoomRegion *zoom_region =
03098 ZOOM_REGION (bonobo_object_from_servant (servant));
03099
03100 #ifdef ZOOM_REGION_DEBUG
03101 g_assert (zoom_region->alive);
03102 #endif
03103 return bonobo_object_dup_ref (
03104 BONOBO_OBJREF (zoom_region->properties), ev);
03105 }
03106
03107 static void
03108 impl_zoom_region_update_pointer (PortableServer_Servant servant,
03109 CORBA_Environment *ev)
03110 {
03111 ZoomRegion *zoom_region =
03112 ZOOM_REGION (bonobo_object_from_servant (servant));
03113
03114 #ifdef ZOOM_REGION_DEBUG
03115 g_assert (zoom_region->alive);
03116 #endif
03117
03118 zoom_region_update_cursor (zoom_region, 0, 0, NULL);
03119 }
03120
03121 static void
03122 impl_zoom_region_mark_dirty (PortableServer_Servant servant,
03123 const GNOME_Magnifier_RectBounds *roi_dirty,
03124 CORBA_Environment *ev)
03125 {
03126 ZoomRegion *zoom_region =
03127 ZOOM_REGION (bonobo_object_from_servant (servant));
03128
03129 #ifdef ZOOM_REGION_DEBUG
03130 g_assert (zoom_region->alive);
03131 #endif
03132 DEBUG_RECT ("mark dirty", zoom_region_rect_from_bounds (
03133 zoom_region, roi_dirty) );
03134
03135 zoom_region_update_pointer (zoom_region, TRUE);
03136
03137 zoom_region_queue_update (zoom_region,
03138 zoom_region_clip_to_source (zoom_region,
03139 zoom_region_rect_from_bounds (zoom_region, roi_dirty)));
03140 }
03141
03142 static GNOME_Magnifier_RectBounds
03143 impl_zoom_region_get_roi (PortableServer_Servant servant,
03144 CORBA_Environment *ev)
03145 {
03146 ZoomRegion *zoom_region =
03147 ZOOM_REGION (bonobo_object_from_servant (servant));
03148
03149 #ifdef ZOOM_REGION_DEBUG
03150 g_assert (zoom_region->alive);
03151 #endif
03152 return zoom_region->roi;
03153 }
03154
03155 static void
03156 impl_zoom_region_move_resize (PortableServer_Servant servant,
03157 const GNOME_Magnifier_RectBounds *viewport_bounds,
03158 CORBA_Environment *ev)
03159 {
03160 ZoomRegion *zoom_region =
03161 ZOOM_REGION (bonobo_object_from_servant (servant));
03162
03163 #ifdef ZOOM_REGION_DEBUG
03164 g_assert (zoom_region->alive);
03165 #endif
03166 zoom_region_set_viewport (zoom_region, viewport_bounds);
03167 }
03168
03169
03170 static void
03171 zoom_region_do_dispose (ZoomRegion *zoom_region)
03172 {
03173 DBG(g_message ("disposing region %p", zoom_region));
03174 if (zoom_region->priv && zoom_region->priv->expose_handler_id &&
03175 GTK_IS_WIDGET (zoom_region->priv->w)) {
03176 g_signal_handler_disconnect (
03177 zoom_region->priv->w,
03178 zoom_region->priv->expose_handler_id);
03179 zoom_region->priv->expose_handler_id = 0;
03180 }
03181 if (zoom_region->priv && zoom_region->priv->update_pointer_id)
03182 g_source_remove (zoom_region->priv->update_pointer_id);
03183 if (zoom_region->priv && zoom_region->priv->update_handler_id)
03184 g_source_remove (zoom_region->priv->update_handler_id);
03185 g_idle_remove_by_data (zoom_region);
03186
03187 #ifdef ZOOM_REGION_DEBUG
03188 zoom_region->alive = FALSE;
03189 #endif
03190 }
03191
03192 static void
03193 impl_zoom_region_dispose (PortableServer_Servant servant,
03194 CORBA_Environment *ev)
03195 {
03196 ZoomRegion *zoom_region =
03197 ZOOM_REGION (bonobo_object_from_servant (servant));
03198 zoom_region_do_dispose (zoom_region);
03199 }
03200
03201
03202
03203 static void
03204 zoom_region_dispose (GObject *object)
03205 {
03206 ZoomRegion *zoom_region = ZOOM_REGION (object);
03207
03208 zoom_region_do_dispose (zoom_region);
03209
03210 BONOBO_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
03211 }
03212
03213 static void
03214 zoom_region_class_init (ZoomRegionClass *klass)
03215 {
03216 GObjectClass * object_class = (GObjectClass *) klass;
03217 POA_GNOME_Magnifier_ZoomRegion__epv *epv = &klass->epv;
03218 parent_class = g_type_class_peek (BONOBO_TYPE_OBJECT);
03219
03220 object_class->dispose = zoom_region_dispose;
03221 object_class->finalize = zoom_region_finalize;
03222
03223 epv->setMagFactor = impl_zoom_region_set_mag_factor;
03224 epv->getMagFactor = impl_zoom_region_get_mag_factor;
03225 epv->getProperties = impl_zoom_region_get_properties;
03226 epv->setROI = impl_zoom_region_set_roi;
03227 epv->setPointerPos = impl_zoom_region_set_pointer_pos;
03228 epv->updatePointer = impl_zoom_region_update_pointer;
03229 epv->markDirty = impl_zoom_region_mark_dirty;
03230 epv->getROI = impl_zoom_region_get_roi;
03231 epv->moveResize = impl_zoom_region_move_resize;
03232 epv->dispose = impl_zoom_region_dispose;
03233 epv->setContrast = impl_zoom_region_set_contrast;
03234 epv->getContrast = impl_zoom_region_get_contrast;
03235 epv->setBrightness = impl_zoom_region_set_brightness;
03236 epv->getBrightness = impl_zoom_region_get_brightness;
03237
03238 reset_timing_stats();
03239 #ifdef DEBUG_CLIENT_CALLS
03240 client_debug = (g_getenv ("MAG_CLIENT_DEBUG") != NULL);
03241 #endif
03242 }
03243
03244 static void
03245 zoom_region_properties_init (ZoomRegion *zoom_region)
03246 {
03247 BonoboArg *def;
03248
03249 zoom_region->properties =
03250 bonobo_property_bag_new_closure (
03251 g_cclosure_new_object (
03252 G_CALLBACK (zoom_region_get_property),
03253 G_OBJECT (zoom_region)),
03254 g_cclosure_new_object (
03255 G_CALLBACK (zoom_region_set_property),
03256 G_OBJECT (zoom_region)));
03257
03258 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03259 BONOBO_ARG_SET_BOOLEAN (def, TRUE);
03260
03261 bonobo_property_bag_add (zoom_region->properties,
03262 "is-managed",
03263 ZOOM_REGION_MANAGED_PROP,
03264 BONOBO_ARG_BOOLEAN,
03265 def,
03266 "If false, zoom region does not auto-update, but is drawn into directly by the client",
03267 Bonobo_PROPERTY_READABLE |
03268 Bonobo_PROPERTY_WRITEABLE);
03269
03270 bonobo_arg_release (def);
03271 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03272 BONOBO_ARG_SET_BOOLEAN (def, TRUE);
03273
03274 bonobo_property_bag_add (zoom_region->properties,
03275 "poll-mouse",
03276 ZOOM_REGION_POLL_MOUSE_PROP,
03277 BONOBO_ARG_BOOLEAN,
03278 NULL,
03279 "If false, zoom region does not poll for pointer location, but is (exclusively) given it by the client",
03280 Bonobo_PROPERTY_READABLE |
03281 Bonobo_PROPERTY_WRITEABLE);
03282
03283 bonobo_arg_release (def);
03284 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03285 BONOBO_ARG_SET_BOOLEAN (def, TRUE);
03286
03287 bonobo_property_bag_add (zoom_region->properties,
03288 "draw-cursor",
03289 ZOOM_REGION_DRAW_CURSOR_PROP,
03290 BONOBO_ARG_BOOLEAN,
03291 NULL,
03292 "If false, zoom region does not draw the cursor.",
03293 Bonobo_PROPERTY_READABLE |
03294 Bonobo_PROPERTY_WRITEABLE);
03295
03296 bonobo_arg_release (def);
03297 def = bonobo_arg_new (BONOBO_ARG_SHORT);
03298 BONOBO_ARG_SET_SHORT (def, GNOME_Magnifier_ZoomRegion_SCROLL_FASTEST);
03299
03300 bonobo_property_bag_add (zoom_region->properties,
03301 "smooth-scroll-policy",
03302 ZOOM_REGION_SMOOTHSCROLL_PROP,
03303 BONOBO_ARG_SHORT,
03304 def,
03305 "scrolling policy, slower versus faster",
03306 Bonobo_PROPERTY_READABLE |
03307 Bonobo_PROPERTY_WRITEABLE);
03308
03309 bonobo_arg_release (def);
03310 def = bonobo_arg_new (BONOBO_ARG_SHORT);
03311 BONOBO_ARG_SET_SHORT (
03312 def,
03313 GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_NO_FILTER);
03314
03315 bonobo_property_bag_add (zoom_region->properties,
03316 "color-blind-filter",
03317 ZOOM_REGION_COLORBLIND_PROP,
03318 BONOBO_ARG_SHORT,
03319 def,
03320 "color blind filter to apply in an image",
03321 Bonobo_PROPERTY_READABLE |
03322 Bonobo_PROPERTY_WRITEABLE);
03323
03324 bonobo_arg_release (def);
03325 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03326 BONOBO_ARG_SET_BOOLEAN (def, FALSE);
03327
03328 bonobo_property_bag_add (zoom_region->properties,
03329 "use-test-pattern",
03330 ZOOM_REGION_TESTPATTERN_PROP,
03331 BONOBO_ARG_BOOLEAN,
03332 def,
03333 "use test pattern for source",
03334 Bonobo_PROPERTY_READABLE |
03335 Bonobo_PROPERTY_WRITEABLE);
03336
03337 bonobo_arg_release (def);
03338 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03339 BONOBO_ARG_SET_BOOLEAN (def, TRUE);
03340
03341 bonobo_property_bag_add (zoom_region->properties,
03342 "inverse-video",
03343 ZOOM_REGION_INVERT_PROP,
03344 BONOBO_ARG_BOOLEAN,
03345 def,
03346 "inverse video display",
03347 Bonobo_PROPERTY_READABLE |
03348 Bonobo_PROPERTY_WRITEABLE);
03349
03350 bonobo_arg_release (def);
03351
03352 bonobo_property_bag_add (zoom_region->properties,
03353 "smoothing-type",
03354 ZOOM_REGION_SMOOTHING_PROP,
03355 BONOBO_ARG_STRING,
03356 NULL,
03357 "image smoothing algorithm used",
03358 Bonobo_PROPERTY_READABLE |
03359 Bonobo_PROPERTY_WRITEABLE);
03360
03361 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03362 BONOBO_ARG_SET_FLOAT (def, 0.0);
03363
03364 bonobo_property_bag_add (zoom_region->properties,
03365 "red-contrast",
03366 ZOOM_REGION_CONTRASTR_PROP,
03367 BONOBO_ARG_FLOAT,
03368 def,
03369 "red image contrast ratio",
03370 Bonobo_PROPERTY_READABLE |
03371 Bonobo_PROPERTY_WRITEABLE);
03372 bonobo_arg_release (def);
03373
03374 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03375 BONOBO_ARG_SET_FLOAT (def, 0.0);
03376
03377 bonobo_property_bag_add (zoom_region->properties,
03378 "green-contrast",
03379 ZOOM_REGION_CONTRASTG_PROP,
03380 BONOBO_ARG_FLOAT,
03381 def,
03382 "green image contrast ratio",
03383 Bonobo_PROPERTY_READABLE |
03384 Bonobo_PROPERTY_WRITEABLE);
03385 bonobo_arg_release (def);
03386
03387 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03388 BONOBO_ARG_SET_FLOAT (def, 0.0);
03389
03390 bonobo_property_bag_add (zoom_region->properties,
03391 "blue-contrast",
03392 ZOOM_REGION_CONTRASTB_PROP,
03393 BONOBO_ARG_FLOAT,
03394 def,
03395 "blue image contrast ratio",
03396 Bonobo_PROPERTY_READABLE |
03397 Bonobo_PROPERTY_WRITEABLE);
03398 bonobo_arg_release (def);
03399
03400 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03401 BONOBO_ARG_SET_FLOAT (def, 0.0);
03402
03403 bonobo_property_bag_add (zoom_region->properties,
03404 "red-brightness",
03405 ZOOM_REGION_BRIGHTR_PROP,
03406 BONOBO_ARG_FLOAT,
03407 def,
03408 "red image brightness ratio",
03409 Bonobo_PROPERTY_READABLE |
03410 Bonobo_PROPERTY_WRITEABLE);
03411 bonobo_arg_release (def);
03412
03413 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03414 BONOBO_ARG_SET_FLOAT (def, 0.0);
03415
03416 bonobo_property_bag_add (zoom_region->properties,
03417 "green-brightness",
03418 ZOOM_REGION_BRIGHTG_PROP,
03419 BONOBO_ARG_FLOAT,
03420 def,
03421 "green image brightness ratio",
03422 Bonobo_PROPERTY_READABLE |
03423 Bonobo_PROPERTY_WRITEABLE);
03424 bonobo_arg_release (def);
03425
03426 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03427 BONOBO_ARG_SET_FLOAT (def, 0.0);
03428
03429 bonobo_property_bag_add (zoom_region->properties,
03430 "blue-brightness",
03431 ZOOM_REGION_BRIGHTB_PROP,
03432 BONOBO_ARG_FLOAT,
03433 def,
03434 "blue image brightness ratio",
03435 Bonobo_PROPERTY_READABLE |
03436 Bonobo_PROPERTY_WRITEABLE);
03437 bonobo_arg_release (def);
03438
03439 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03440 BONOBO_ARG_SET_FLOAT (def, 2.0);
03441
03442 bonobo_property_bag_add (zoom_region->properties,
03443 "mag-factor-x",
03444 ZOOM_REGION_XSCALE_PROP,
03445 BONOBO_ARG_FLOAT,
03446 def,
03447 "x scale factor",
03448 Bonobo_PROPERTY_READABLE |
03449 Bonobo_PROPERTY_WRITEABLE);
03450
03451 bonobo_arg_release (def);
03452 def = bonobo_arg_new (BONOBO_ARG_FLOAT);
03453 BONOBO_ARG_SET_FLOAT (def, 2.0);
03454
03455 bonobo_property_bag_add (zoom_region->properties,
03456 "mag-factor-y",
03457 ZOOM_REGION_YSCALE_PROP,
03458 BONOBO_ARG_FLOAT,
03459 def,
03460 "y scale factor",
03461 Bonobo_PROPERTY_READABLE |
03462 Bonobo_PROPERTY_WRITEABLE);
03463
03464 bonobo_arg_release (def);
03465 def = bonobo_arg_new (BONOBO_ARG_LONG);
03466 BONOBO_ARG_SET_LONG (def, 0);
03467
03468 bonobo_property_bag_add (zoom_region->properties,
03469 "border-size",
03470 ZOOM_REGION_BORDERSIZE_PROP,
03471 BONOBO_ARG_LONG,
03472 def,
03473 "size of zoom-region borders, in pixels",
03474 Bonobo_PROPERTY_READABLE |
03475 Bonobo_PROPERTY_WRITEABLE);
03476
03477 bonobo_arg_release (def);
03478 def = bonobo_arg_new (BONOBO_ARG_LONG);
03479 BONOBO_ARG_SET_LONG (def, 0);
03480
03481 bonobo_property_bag_add (zoom_region->properties,
03482 "border-size-left",
03483 ZOOM_REGION_BORDERSIZELEFT_PROP,
03484 BONOBO_ARG_LONG,
03485 def,
03486 "size of left zoom-region border, in pixels",
03487 Bonobo_PROPERTY_READABLE |
03488 Bonobo_PROPERTY_WRITEABLE);
03489
03490 bonobo_arg_release (def);
03491 def = bonobo_arg_new (BONOBO_ARG_LONG);
03492 BONOBO_ARG_SET_LONG (def, 0);
03493
03494 bonobo_property_bag_add (zoom_region->properties,
03495 "border-size-top",
03496 ZOOM_REGION_BORDERSIZETOP_PROP,
03497 BONOBO_ARG_LONG,
03498 def,
03499 "size of top zoom-region border, in pixels",
03500 Bonobo_PROPERTY_READABLE |
03501 Bonobo_PROPERTY_WRITEABLE);
03502
03503 bonobo_arg_release (def);
03504 def = bonobo_arg_new (BONOBO_ARG_LONG);
03505 BONOBO_ARG_SET_LONG (def, 0);
03506
03507 bonobo_property_bag_add (zoom_region->properties,
03508 "border-size-right",
03509 ZOOM_REGION_BORDERSIZERIGHT_PROP,
03510 BONOBO_ARG_LONG,
03511 def,
03512 "size of right zoom-region border, in pixels",
03513 Bonobo_PROPERTY_READABLE |
03514 Bonobo_PROPERTY_WRITEABLE);
03515
03516 bonobo_arg_release (def);
03517 def = bonobo_arg_new (BONOBO_ARG_LONG);
03518 BONOBO_ARG_SET_LONG (def, 0);
03519
03520 bonobo_property_bag_add (zoom_region->properties,
03521 "border-size-bottom",
03522 ZOOM_REGION_BORDERSIZEBOTTOM_PROP,
03523 BONOBO_ARG_LONG,
03524 def,
03525 "size of bottom zoom-region border, in "
03526 "pixels",
03527 Bonobo_PROPERTY_READABLE |
03528 Bonobo_PROPERTY_WRITEABLE);
03529
03530 bonobo_arg_release (def);
03531 def = bonobo_arg_new (BONOBO_ARG_LONG);
03532 BONOBO_ARG_SET_LONG (def, 0x00000000);
03533
03534 bonobo_property_bag_add (zoom_region->properties,
03535 "border-color",
03536 ZOOM_REGION_BORDERCOLOR_PROP,
03537 BONOBO_ARG_LONG,
03538 def,
03539 "border color, as RGBA32",
03540 Bonobo_PROPERTY_READABLE |
03541 Bonobo_PROPERTY_WRITEABLE);
03542
03543 bonobo_arg_release (def);
03544 def = bonobo_arg_new (BONOBO_ARG_INT);
03545 BONOBO_ARG_SET_INT (def, 0);
03546
03547 bonobo_property_bag_add (zoom_region->properties,
03548 "x-alignment",
03549 ZOOM_REGION_XALIGN_PROP,
03550 BONOBO_ARG_INT,
03551 def,
03552 "x-alignment policy for this region",
03553 Bonobo_PROPERTY_READABLE |
03554 Bonobo_PROPERTY_WRITEABLE);
03555
03556 bonobo_arg_release (def);
03557 def = bonobo_arg_new (BONOBO_ARG_INT);
03558 BONOBO_ARG_SET_INT (def, 0);
03559
03560 bonobo_property_bag_add (zoom_region->properties,
03561 "y-alignment",
03562 ZOOM_REGION_YALIGN_PROP,
03563 BONOBO_ARG_INT,
03564 def,
03565 "y-alignment policy for this region",
03566 Bonobo_PROPERTY_READABLE |
03567 Bonobo_PROPERTY_WRITEABLE);
03568 bonobo_arg_release (def);
03569
03570 bonobo_property_bag_add (zoom_region->properties,
03571 "viewport",
03572 ZOOM_REGION_VIEWPORT_PROP,
03573 TC_GNOME_Magnifier_RectBounds,
03574 NULL,
03575 "viewport bounding box",
03576 Bonobo_PROPERTY_READABLE |
03577 Bonobo_PROPERTY_WRITEABLE);
03578
03579 def = bonobo_arg_new (BONOBO_ARG_INT);
03580 BONOBO_ARG_SET_INT (def, 0);
03581
03582 bonobo_property_bag_add (zoom_region->properties,
03583 "timing-iterations",
03584 ZOOM_REGION_TIMING_TEST_PROP,
03585 BONOBO_ARG_INT,
03586 def,
03587 "timing iterations",
03588 Bonobo_PROPERTY_READABLE |
03589 Bonobo_PROPERTY_WRITEABLE);
03590 bonobo_arg_release (def);
03591
03592 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03593 BONOBO_ARG_SET_BOOLEAN (def, FALSE);
03594
03595 bonobo_property_bag_add (zoom_region->properties,
03596 "timing-output",
03597 ZOOM_REGION_TIMING_OUTPUT_PROP,
03598 BONOBO_ARG_BOOLEAN,
03599 def,
03600 "timing output",
03601 Bonobo_PROPERTY_READABLE |
03602 Bonobo_PROPERTY_WRITEABLE);
03603
03604 bonobo_arg_release (def);
03605
03606 def = bonobo_arg_new (BONOBO_ARG_INT);
03607 BONOBO_ARG_SET_INT (def, 0);
03608
03609 bonobo_property_bag_add (zoom_region->properties,
03610 "timing-pan-rate",
03611 ZOOM_REGION_TIMING_PAN_RATE_PROP,
03612 BONOBO_ARG_INT,
03613 def,
03614 "timing pan rate",
03615 Bonobo_PROPERTY_READABLE |
03616 Bonobo_PROPERTY_WRITEABLE);
03617 bonobo_arg_release (def);
03618
03619 def = bonobo_arg_new (BONOBO_ARG_BOOLEAN);
03620 BONOBO_ARG_SET_BOOLEAN (def, FALSE);
03621
03622 bonobo_property_bag_add (zoom_region->properties,
03623 "exit-magnifier",
03624 ZOOM_REGION_EXIT_MAGNIFIER,
03625 BONOBO_ARG_BOOLEAN,
03626 def,
03627 "timing output",
03628 Bonobo_PROPERTY_READABLE |
03629 Bonobo_PROPERTY_WRITEABLE);
03630
03631 bonobo_arg_release (def);
03632
03633 }
03634
03635 static void
03636 zoom_region_private_init (ZoomRegionPrivate *priv)
03637 {
03638 GdkRectangle rect = {0, 0, 0, 0};
03639 GNOME_Magnifier_RectBounds rectbounds = {0, 0, 0, 0};
03640 priv->parent = NULL;
03641 priv->w = NULL;
03642 priv->default_gc = NULL;
03643 priv->paint_cursor_gc = NULL;
03644 priv->crosswire_gc = NULL;
03645 priv->q = NULL;
03646 priv->scaled_pixbuf = NULL;
03647 priv->source_pixbuf_cache = NULL;
03648 priv->source_drawable = NULL;
03649 priv->pixmap = NULL;
03650 priv->cursor_backing_rect = rect;
03651 priv->cursor_backing_pixels = NULL;
03652 priv->gdk_interp_type = GDK_INTERP_NEAREST;
03653 priv->expose_handler_id = 0;
03654 priv->test = FALSE;
03655 priv->last_cursor_pos.x = 0;
03656 priv->last_cursor_pos.y = 0;
03657 priv->last_drawn_crosswire_pos.x = 0;
03658 priv->last_drawn_crosswire_pos.y = 0;
03659 priv->exposed_bounds = rectbounds;
03660 priv->source_area = rectbounds;
03661 priv->update_pointer_id = 0;
03662 priv->update_handler_id = 0;
03663 }
03664
03665
03666
03667 static void
03668 zoom_region_init (ZoomRegion *zoom_region)
03669 {
03670 DBG(g_message ("initializing region %p", zoom_region));
03671
03672 #ifdef HAVE_COLORBLIND
03673 cbr = colorblind_create();
03674 color = malloc (sizeof (COLORBLIND_XCOLOR));
03675 #endif
03676
03677 zoom_region_properties_init (zoom_region);
03678 zoom_region->draw_cursor = TRUE;
03679 zoom_region->smooth_scroll_policy =
03680 GNOME_Magnifier_ZoomRegion_SCROLL_SMOOTH;
03681 zoom_region->color_blind_filter =
03682 GNOME_Magnifier_ZoomRegion_COLORBLIND_FILTER_T_NO_FILTER;
03683 zoom_region->contrast_r = 0.0;
03684 zoom_region->contrast_g = 0.0;
03685 zoom_region->contrast_b = 0.0;
03686 zoom_region->bright_r = 0.0;
03687 zoom_region->bright_g = 0.0;
03688 zoom_region->bright_b = 0.0;
03689 zoom_region->invert = FALSE;
03690 zoom_region->cache_source = FALSE;
03691 zoom_region->border_size_left = 0;
03692 zoom_region->border_size_top = 0;
03693 zoom_region->border_size_right = 0;
03694 zoom_region->border_size_bottom = 0;
03695 zoom_region->border_color = 0;
03696 zoom_region->roi.x1 = 0;
03697 zoom_region->roi.x1 = 0;
03698 zoom_region->roi.x2 = 1;
03699 zoom_region->roi.x2 = 1;
03700 zoom_region->x_align_policy = GNOME_Magnifier_ZoomRegion_ALIGN_CENTER;
03701 zoom_region->y_align_policy = GNOME_Magnifier_ZoomRegion_ALIGN_CENTER;
03702 zoom_region->coalesce_func = _coalesce_update_rects;
03703 zoom_region->poll_mouse = TRUE;
03704 zoom_region->priv = g_malloc (sizeof (ZoomRegionPrivate));
03705 zoom_region_private_init (zoom_region->priv);
03706 bonobo_object_add_interface (BONOBO_OBJECT (zoom_region),
03707 BONOBO_OBJECT (zoom_region->properties));
03708 zoom_region->timing_output = FALSE;
03709 #ifdef ZOOM_REGION_DEBUG
03710 zoom_region->alive = TRUE;
03711 #endif
03712 zoom_region->priv->update_pointer_id =
03713 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE,
03714 200,
03715 zoom_region_update_pointer_timeout,
03716 zoom_region,
03717 NULL);
03718 }
03719
03720 ZoomRegion *
03721 zoom_region_new (void)
03722 {
03723 return g_object_new (zoom_region_get_type(), NULL);
03724 }
03725
03726
03727 static void
03728 zoom_region_finalize (GObject *region)
03729 {
03730 ZoomRegion *zoom_region = (ZoomRegion *) region;
03731
03732 DBG(g_message ("finalizing region %p", zoom_region));
03733
03734 if (zoom_region->priv && zoom_region->priv->q)
03735 {
03736 g_list_free (zoom_region->priv->q);
03737 zoom_region->priv->q = NULL;
03738 }
03739 if (GTK_IS_WIDGET (zoom_region->priv->w))
03740 gtk_container_remove (GTK_CONTAINER (((Magnifier *) zoom_region->priv->parent)->priv->canvas), GTK_WIDGET (zoom_region->priv->w));
03741 if (GTK_IS_WIDGET (zoom_region->priv->border))
03742 gtk_container_remove (GTK_CONTAINER (((Magnifier *) zoom_region->priv->parent)->priv->canvas), GTK_WIDGET (zoom_region->priv->border));
03743 if (zoom_region->priv->source_pixbuf_cache)
03744 g_object_unref (zoom_region->priv->source_pixbuf_cache);
03745 if (zoom_region->priv->scaled_pixbuf)
03746 g_object_unref (zoom_region->priv->scaled_pixbuf);
03747 if (zoom_region->priv->pixmap)
03748 g_object_unref (zoom_region->priv->pixmap);
03749 zoom_region->priv->pixmap = NULL;
03750 zoom_region->priv->parent = NULL;
03751 if (zoom_region->priv->cursor_backing_pixels)
03752 g_object_unref (zoom_region->priv->cursor_backing_pixels);
03753 g_free (zoom_region->priv);
03754 zoom_region->priv = NULL;
03755
03756 #ifdef HAVE_COLORBLIND
03757 free(cbr);
03758 free(color);
03759 #endif
03760
03761 #ifdef ZOOM_REGION_DEBUG
03762 zoom_region->alive = FALSE;
03763 #endif
03764 BONOBO_CALL_PARENT (G_OBJECT_CLASS, finalize, (region));
03765 }
03766
03767 BONOBO_TYPE_FUNC_FULL (ZoomRegion,
03768 GNOME_Magnifier_ZoomRegion,
03769 BONOBO_TYPE_OBJECT,
03770 zoom_region);