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