⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cimg.c

📁 GSview 4.6 PostScript previewer。Ghostscript在MS-Windows, OS/2 and Unix下的图形化接口
💻 C
📖 第 1 页 / 共 2 页
字号:
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);
#ifdef DISPLAY_DEBUG
    gs_addmessf("display_close(0x%x, 0x%x)\n", handle, device);
#endif
    img->open = FALSE;
    img->opening = FALSE;

    img->handle = handle;
    img->device = device;

    img->width = img->height = img->raster = 0;
    img->format = 0;
    img->image = NULL;

    if (img->tile)
	free(img->tile);
    img->tile = NULL;
    img->tile_width = 0;
    img->tile_height = 0;
    img->tile_dirty = 0;
    img->tile_verydirty_threshold = 0;
    img->tile_threshold = 0;
    img->tile_columns = 0;
    img->tile_rows = 0;
    img->tile_time = 0;
    img->tile_interval = 0;

    image_unlock(img);

    view_post_message(view, WM_GSDEVICE, 0);
    return 0;
}

/* Device is about to be resized. */
/* Resize will only occur if this function returns 0. */
static int display_presize(void *handle, void *device, int width, int height, 
	int raster, unsigned int format)
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);
#ifdef DISPLAY_DEBUG
    gs_addmessf("display_presize(0x%x, 0x%x, width=%d height=%d raster=%d\
 format=%d)\n", 
       handle, device, width, height, raster, format);
#endif
    if (!img->opening)
	image_lock(img);

    /* check if we understand format */
    if (image_presize(img, width, height, raster, format))
	return_error(DISPLAY_ERROR);

    if (img->tile)
	free(img->tile);
    img->tile = NULL;

    return 0;
}
   
/* Device has been resized. */
/* New pointer to raster returned in pimage */
static int display_size(void *handle, void *device, int width, int height, 
	int raster, unsigned int format, unsigned char *pimage)
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);
    int len;
#ifdef DISPLAY_DEBUG
    gs_addmessf("display_size(0x%x, 0x%x, width=%d height=%d raster=%d\
 format=%d image=0x%x)\n", 
       handle, device, width, height, raster, format, pimage);
#endif
    img->width = width;
    img->height = height;
    img->raster = raster;
    img->format = format;
    img->image = pimage;
    if (image_size(img))
	img->open = FALSE;
    else {
	if (img->opening)
	    img->open = TRUE;
	img->opening = FALSE;
    }

    img->tile_width = 64;
    img->tile_height = 64;
    img->tile_dirty = 0;
    img->tile_verydirty_threshold = 256;
    if (img->tile) {
	free(img->tile);
	img->tile = NULL;
    }
    img->tile_columns = (img->width + img->tile_width - 1) / img->tile_width;
    img->tile_rows = (img->height + img->tile_height - 1) / img->tile_height;
    len = img->tile_rows * img->tile_columns * sizeof(img->tile[0]);
    img->tile = (int *)malloc(len);
    if (img->tile)
	memset(img->tile, 0, len);
    img->tile_threshold = max(4, img->tile_columns/2);
    img->tile_time = 0;
    img->tile_interval = 100;	/* start at 100ms */

    image_unlock(img);
    view_post_message(view, WM_GSSIZE, 0);
    return 0;
}
   
/* flushpage */
static int display_sync(void *handle, void *device)
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);
#ifdef DISPLAY_DEBUG
    gs_addmessf("display_sync(0x%x, 0x%x)\n", handle, device);
#endif
    if (img->ignore_sync) {
	/* ignore this sync, but not the next */
	img->ignore_sync = FALSE;
	return 0;
    }
    image_sync(img);
    view_post_message(view, WM_GSSYNC, 0);
    return 0;
}

/* showpage */
/* If you want to pause on showpage, then don't return immediately */
static int display_page(void *handle, void *device, int copies, int flush)
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);

#ifdef DISPLAY_DEBUG
    gs_addmessf("display_page(0x%x, 0x%x, copies=%d flush=%d)\n", 
	handle, device, copies, flush);
#endif
    img->ignore_sync = FALSE;
    image_sync(img);
    view_page_callback(view);

    return 0;
}

/* 
 * This keeps track of how much of the page is currently
 * dirty by segmenting the page into tiles and keeping
 * track of which tiles are dirty.
 * When more than img->tile_threshold tiles are dirty,
 * or a single tile has been dirtied many times,
 * a refresh of those tiles is requested.
 * The first part of this code must be fast because it is
 * called frequently.
 *
 * The current code causes the redraw to occur in chunks.
 * Perhaps a LRU method would be better so that it progressively
 * draws those tiles which are no longer being dirtied.
 */

void
image_draw_tile(IMAGE *img, int tx1, int ty1, int tx2, int ty2)
{
    int param;
    tx1 = min(max(0, tx1), 255);
    ty1 = min(max(0, ty1), 255);
    tx2 = min(max(0, tx2), 255);
    ty2 = min(max(0, ty2), 255);
    param = (tx1<<24) + (ty1<<16) + (tx2<<8) + ty2;
    view_post_message((VIEW *)(img->handle), WM_GSTILE, param);
}


void
image_tile_update(IMAGE *img, int ux, int uy, int uw, int uh)
{
    int tx, ty;
    int tx1, ty1, tx2, ty2;
    int columns = img->tile_columns;
    int rows = img->tile_rows;
    int dirty = 0;
    int very_dirty = 0;
    if (!img->tile)
	return;
    if ((img->width==0) || (img->height ==0) || 
	(img->tile_width == 0) || (img->tile_height ==0))
	return;

    /* Mark tiles as dirty */
    tx1 = ux / img->tile_width;		/* lower left */
    ty1 = uy / img->tile_height;
    tx2 = (ux+uw-1) / img->tile_width;	/* upper right */
    ty2 = (uy+uh-1) / img->tile_height;

    /* Sanity check on tile index */
    if ((tx2 >= img->tile_columns) || (tx1 > tx2) || (tx1 < 0) ||
        (ty2 >= img->tile_rows) || (ty1 > ty2) || (ty1 < 0))
	return;
    /* Mark dirty tiles */
    for (ty=ty1; ty<=ty2; ty++) {
	for (tx=tx1; tx<=tx2; tx++) {
	    /* is tile newly dirtied? */
	    if (!img->tile[ty*columns + tx])
		img->tile_dirty++;		/* newly dirtied tile */
	    /* mark tile as dirty, and note if it is very dirty */
	    dirty = ++(img->tile[ty*columns + tx]);
	    if (dirty > img->tile_verydirty_threshold)
		very_dirty = 1;
	}
    }
    /* code above here must be fast */

    if (very_dirty || (img->tile_dirty > img->tile_threshold)) {
	/* Make sure we do this no more than 10 times per second */
	/* to avoid swamping the window queue */
	if (image_update_time(img) != 0) {
	    /* too soon */
	    return;
	}

	/* work out rectangle enclosing dirty tiles */
	tx1 = columns;
	tx2 = 0;
	ty1 = rows;
	ty2 = 0;
	dirty = 0;
	for (ty=0; ty<rows; ty++) {
	    for (tx=0; tx<columns; tx++) {
		if (img->tile[ty * columns + tx]) {
		    dirty++;
		    if (tx < tx1)
			tx1 = tx;
		    if (tx > tx2)
			tx2 = tx;
		    if (ty < ty1)
			ty1 = ty;
		    if (ty > ty2)
			ty2 = ty;
		}
		else {
		}
	    }
	}
	if (img->ignore_sync) {
	    img->ignore_sync = FALSE;
	    image_sync(img);
	}
	else if ((tx2 >= tx1) && (ty2 >= ty1)) {
	    /* redraw it */
	    int tx3;
	    if (dirty * 10 < (tx2 - tx1 + 1) * (ty2 - ty1 + 1)) {
		/* draw individual tiles */
		/* but merge horizontally adjacent tiles together */
		for (ty=ty1; ty<=ty2; ty++) {
		    for (tx=tx1; tx<=tx2; tx++) {
			if (img->tile[ty*columns + tx]) {
			    /* look for adjacent tiles */
			    for (tx3 = tx+1; tx3 <= tx2; tx3++) {
				if (!img->tile[ty*columns + tx3])
				    break;
			    }
			    tx3--;
			    image_draw_tile(img, tx, ty, tx3, ty);
			}
		    }
		}
	    }
	    else {
		image_draw_tile(img, tx1, ty1, tx2, ty2);
	    }
		
	}
	memset(img->tile, 0, sizeof(img->tile[0]) * rows * columns);
	img->tile_dirty = 0;	/* all tiles will be cleaned */
    }
}

/* Poll the caller for cooperative multitasking. */
/* If this function is NULL, polling is not needed */
static int display_update(void *handle, void *device, 
    int x, int y, int w, int h)
{
    VIEW *view = (VIEW *)handle;
    IMAGE *img = view_get_image(view);
    image_tile_update(img, x, y, w, h);

    if (img->lock_count != 0)
	return 0; /* prevent update during image resize on single thread */
    return view_poll((VIEW *)handle);
}


display_callback gsdisplay = { 
    sizeof(display_callback),
    DISPLAY_VERSION_MAJOR,
    DISPLAY_VERSION_MINOR,
    display_open,
    display_preclose,
    display_close,
    display_presize,
    display_size,
    display_sync,
    display_page,
    display_update,
#ifdef OS2
    display_memalloc,
    display_memfree
#else
    NULL,	/* memalloc */
    NULL	/* memfree */
#endif
};


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -