campo-sirio/xi/xibitmap.c

285 lines
7.0 KiB
C
Raw Normal View History

/*******************************************************************************
* Copyright 1991-1996 by ORCA Software, Inc. *
* *
* All rights reserved. May not be reproduced or distributed, in printed or *
* electronic form, without permission of ORCA Software, Inc. May not be *
* distributed as object code, separately or linked with other object modules, *
* without permission. *
*******************************************************************************/
#define XI_INTERNAL
#define XI_R3_COMPAT
#include "xi.h"
#include "xiutils.h"
#if XIWS != XIWS_MAC && XIWS != XIWS_XM && XIWS != XIWS_WXGTK
#include <io.h>
#endif
#if XIWS == XIWS_XM || XIWS == XIWS_WXGTK
#include <unistd.h>
#endif
XI_BITMAP *
xi_bitmap_create( char *filename, XI_BITMAP_MODE mode )
{
XI_BITMAP *bitmap;
bitmap = XinMemoryZeroAlloc( sizeof( XI_BITMAP ) );
if ( filename != NULL )
{
#if XIWS != XIWS_MAC
if ( access( filename, 0 ) != -1 )
#endif
bitmap->xin_bitmap = XinBitmapRead( filename );
if ( bitmap->xin_bitmap == NULL )
{
XinMemoryFree( bitmap );
return NULL;
}
}
bitmap->mode = mode;
bitmap->ref_count = 1;
return bitmap;
}
XI_BITMAP *
xi_bitmap_create_res( short id, XI_BITMAP_MODE mode )
{
XI_BITMAP *bitmap;
bitmap = XinMemoryZeroAlloc( sizeof( XI_BITMAP ) );
if ( id != 0 )
{
bitmap->xin_bitmap = XinBitmapReadRes( id );
if ( bitmap->xin_bitmap == NULL )
{
XinMemoryFree( bitmap );
return NULL;
}
}
bitmap->mode = mode;
bitmap->ref_count = 1;
return bitmap;
}
XI_BITMAP *
xi_bitmap_copy( XI_BITMAP * bitmap )
{
if ( bitmap != NULL )
bitmap->ref_count++;
return bitmap;
}
void
xi_bitmap_destroy( XI_BITMAP * bitmap )
{
if ( bitmap != NULL && --bitmap->ref_count == 0 )
{
if ( bitmap->xin_bitmap != NULL )
XinBitmapDestroy( bitmap->xin_bitmap );
XinMemoryFree( bitmap );
}
}
static void
normal_bitmap( XI_BITMAP * bitmap, XinWindow win, XinRect * rct )
{
short width,
height;
int x,
y;
XinRect src;
XinRect dest;
int full_width,
full_height;
XinBrush brush;
if ( bitmap->xin_bitmap == NULL )
width = height = 0;
else
XinBitmapSizeGet( bitmap->xin_bitmap, &width, &height );
full_width = rct->right - rct->left;
full_height = rct->bottom - rct->top;
if ( bitmap->hcenter )
{
if ( width > full_width )
x = 0;
else
x = ( full_width - width ) / 2;
}
else
x = bitmap->x_offset;
if ( bitmap->vcenter )
{
if ( height > full_height )
y = 0;
else
y = ( full_height - height ) / 2;
}
else
y = bitmap->y_offset;
if ( x + width > full_width )
width = full_width - x;
if ( y + height > full_height )
height = full_height - y;
if ( bitmap->xin_bitmap != 0 )
{
dest.top = rct->top + y;
dest.left = rct->left + x;
dest.bottom = dest.top + height;
dest.right = dest.left + width;
src.top = src.left = 0;
src.right = width;
src.bottom = height;
XinWindowBitmapDraw( win, bitmap->xin_bitmap, &dest, &src );
}
/* Draw background color around bitmap */
XinWindowPenSet( win, &hollow_cpen );
brush.pattern = XinBrushSolid;
brush.fore_color = bitmap->background;
XinWindowBrushSet( win, &brush );
if ( y > 0 )
{ /* Draw top rectangle */
dest.top = rct->top;
dest.left = rct->left;
dest.bottom = rct->top + y;
dest.right = rct->right;
xi_draw_rect( win, &dest );
}
if ( x > 0 )
{ /* Draw left rectangle */
dest.top = rct->top + y;
dest.left = rct->left;
dest.bottom = dest.top + height;
dest.right = rct->left + x;
xi_draw_rect( win, &dest );
}
if ( x + width < full_width )
{ /* Draw right rectangle */
dest.top = rct->top + y;
dest.left = rct->left + x + width;
dest.bottom = dest.top + height;
dest.right = rct->right;
xi_draw_rect( win, &dest );
}
if ( y + height < full_height )
{ /* Draw bottom rectangle */
dest.top = rct->top + y + height;
dest.left = rct->left;
dest.bottom = rct->bottom;
dest.right = rct->right;
xi_draw_rect( win, &dest );
}
}
static void
resize_bitmap( XI_BITMAP * bitmap, XinWindow win, XinRect * rct )
{
short width,
height;
XinRect src;
XinBitmapSizeGet( bitmap->xin_bitmap, &width, &height );
src.top = src.left = 0;
src.right = width;
src.bottom = height;
XinWindowBitmapDraw( win, bitmap->xin_bitmap, rct, &src );
}
static void
tile_bitmap( XI_BITMAP * bitmap, XinWindow win, XinRect * rct, XinRect * clip_rct, BOOLEAN on_update )
{
short width,
height;
XinRect src;
XinRect dest;
int full_width,
full_height;
int x,
y;
XinBitmapSizeGet( bitmap->xin_bitmap, &width, &height );
full_width = rct->right - rct->left;
full_height = rct->bottom - rct->top;
src.top = 0;
src.left = 0;
src.bottom = height;
for ( y = 0; y < full_height; y += height )
{
dest.top = rct->top + y;
if ( clip_rct != NULL )
{
if ( dest.top > clip_rct->bottom )
break;
if ( dest.top + height < clip_rct->top )
continue;
}
if ( y + height > full_height )
src.bottom = full_height - y;
src.right = width;
for ( x = 0; x < full_width; x += width )
{
if ( x + width > full_width )
src.right = full_width - x;
dest.left = rct->left + x;
dest.right = dest.left + src.right;
dest.bottom = dest.top + src.bottom;
if ( clip_rct != NULL )
{
if ( dest.left > clip_rct->right )
break;
if ( dest.right < clip_rct->left )
continue;
}
if ( !on_update || XinWindowPaintNeeds( win, &dest ) )
XinWindowBitmapDraw( win, bitmap->xin_bitmap, &dest, &src );
}
}
}
void
xi_bitmap_draw( XI_BITMAP * bitmap, XinWindow win, XinRect * rct,
XinRect * clip_rct, BOOLEAN in_paint_event )
{
XI_BITMAP_MODE mode;
if ( bitmap == NULL )
return;
if ( bitmap->xin_bitmap == NULL )
mode = XI_BITMAP_NORMAL;
else
mode = bitmap->mode;
XinWindowClipSet( win, clip_rct );
switch ( mode )
{
case XI_BITMAP_NORMAL:
normal_bitmap( bitmap, win, rct );
break;
case XI_BITMAP_RESIZE:
resize_bitmap( bitmap, win, rct );
break;
case XI_BITMAP_TILE:
tile_bitmap( bitmap, win, rct, clip_rct, in_paint_event );
break;
}
}
void
xi_bitmap_size_get( XI_BITMAP * bitmap, short *width, short *height )
{
if ( bitmap != NULL && bitmap->xin_bitmap != NULL )
XinBitmapSizeGet( bitmap->xin_bitmap, width, height );
}
BOOLEAN
xi_bitmap_draw_all_on_resize( XI_BITMAP * bitmap )
{
if ( bitmap == NULL || bitmap->xin_bitmap == NULL )
return FALSE;
return ( ( bitmap->mode == XI_BITMAP_NORMAL && ( bitmap->vcenter || bitmap->hcenter ) )
|| bitmap->mode == XI_BITMAP_RESIZE );
}