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