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