shapedraw.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2001  The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 #include "shapedraw.h"
00030 #include "vgafile.h"
00031 #include "ibuf8.h"
00032 #include "u7drag.h"
00033 
00034 using std::cout;
00035 using std::endl;
00036 
00037 /*
00038  *  Blit onto screen.
00039  */
00040 
00041 void Shape_draw::show
00042   (
00043   GdkDrawable *drawable,
00044   int x, int y, int w, int h  // Area to blit.
00045   )
00046   {
00047   int stride = iwin->get_line_width();
00048   gdk_draw_indexed_image(drawable, drawgc, x, y, w, h,
00049       GDK_RGB_DITHER_NORMAL,
00050       iwin->get_bits() + y*stride + x, 
00051       stride, palette);
00052   }
00053 
00054 /*
00055  *  Draw one shape at a particular place.
00056  */
00057 
00058 void Shape_draw::draw_shape
00059   (
00060   Shape_frame *shape,
00061   int x, int y
00062   )
00063   {
00064   shape->paint(iwin, x + shape->get_xleft(), y + shape->get_yabove());
00065   }
00066 
00067 /*
00068  *  Draw one shape at a particular place.
00069  */
00070 
00071 void Shape_draw::draw_shape
00072   (
00073   int shapenum, int framenum,
00074   int x, int y
00075   )
00076   {
00077   if (shapenum < 0 || shapenum >= ifile->get_num_shapes())
00078     return;
00079   Shape_frame *shape = ifile->get_shape(shapenum, framenum);
00080   if (shape)
00081     draw_shape(shape, x, y);
00082   }
00083 
00084 /*
00085  *  Draw one shape's outline at a particular place.
00086  */
00087 
00088 void Shape_draw::draw_shape_outline
00089   (
00090   int shapenum, int framenum,
00091   int x, int y,
00092   unsigned char color   // Color index for outline.
00093   )
00094   {
00095   if (shapenum < 0 || shapenum >= ifile->get_num_shapes())
00096     return;
00097   Shape_frame *shape = ifile->get_shape(shapenum, framenum);
00098   if (shape)
00099     {
00100     if (shape->is_rle())
00101       shape->paint_rle_outline(iwin, x + shape->get_xleft(), 
00102           y + shape->get_yabove(), color);
00103     else
00104       {
00105       int w = shape->get_width(), h = shape->get_height();
00106       iwin->fill_line8(color, w, x, y);
00107       iwin->fill_line8(color, w, x, y + h - 1);
00108       iwin->fill8(color, 1, h, x, y);
00109       iwin->fill8(color, 1, h, x + w - 1, y);
00110       }
00111     }
00112   }
00113 
00114 /*
00115  *  Draw a shape centered in the drawing area.
00116  */
00117 
00118 void Shape_draw::draw_shape_centered
00119   (
00120   int shapenum,     // -1 to not draw shape.
00121   int framenum
00122   )
00123   {
00124   iwin->fill8(255);   // Background (transparent) color.
00125   if (shapenum < 0 || shapenum >= ifile->get_num_shapes())
00126     return;
00127   Shape_frame *shape = ifile->get_shape(shapenum, framenum);
00128   if (!shape)
00129     return;
00130           // Get drawing area dimensions.
00131   gint winw = draw->allocation.width, winh = draw->allocation.height;
00132   draw_shape(shape, (winw - shape->get_width())/2,
00133         (winh - shape->get_height())/2);
00134   }
00135 
00136 /*
00137  *  Create.
00138  */
00139 
00140 Shape_draw::Shape_draw
00141   (
00142   Vga_file *i,      // Where they're kept.
00143   unsigned char *palbuf,    // Palette, 3*256 bytes (rgb triples).
00144   GtkWidget *drw      // Drawing area to use.
00145   ) : ifile(i),
00146       iwin(0), palette(0), draw(drw), drawgc(0),
00147       drop_callback(0), drop_user_data(0), dragging(false)
00148   {
00149   guint32 colors[256];
00150   for (int i = 0; i < 256; i++)
00151     colors[i] = (palbuf[3*i]<<16)*4 + (palbuf[3*i+1]<<8)*4 + 
00152               palbuf[3*i+2]*4;
00153   palette = gdk_rgb_cmap_new(colors, 256);
00154   }
00155 
00156 /*
00157  *  Delete.
00158  */
00159 
00160 Shape_draw::~Shape_draw
00161   (
00162   )
00163   {
00164   gdk_rgb_cmap_free(palette);
00165   delete iwin;
00166   }
00167 
00168 /*
00169  *  Default render.
00170  */
00171 
00172 void Shape_draw::render
00173   (
00174   )
00175   {
00176   }
00177 
00178 /*
00179  *  Set background color and repaint.
00180  */
00181 
00182 void Shape_draw::set_background_color
00183   (
00184   guint32 c
00185   )
00186   {
00187   palette->colors[255] = c;
00188   render();
00189   show();
00190   }
00191 
00192 /*
00193  *  Configure the viewing window.
00194  */
00195 
00196 void Shape_draw::configure
00197   (
00198   )
00199   {
00200   if (!draw->window)
00201     return;     // Not ready yet.
00202   if (!iwin)      // First time?
00203     {
00204     drawgc = gdk_gc_new(draw->window);
00205           // Foreground = yellow.
00206     gdk_rgb_gc_set_foreground(drawgc, (255<<16) + (255<<8));
00207     iwin = new Image_buffer8(
00208       draw->allocation.width, draw->allocation.height);
00209     }
00210   else if (iwin->get_width() != draw->allocation.width ||
00211      iwin->get_height() != draw->allocation.height)
00212     {
00213     delete iwin;
00214     iwin = new Image_buffer8(
00215       draw->allocation.width, draw->allocation.height);
00216     }
00217   }
00218 
00219 /*
00220  *  Shape was dropped.
00221  */
00222 
00223 void Shape_draw::drag_data_received
00224   (
00225   GtkWidget *widget,
00226   GdkDragContext *context,
00227   gint x,
00228   gint y,
00229   GtkSelectionData *seldata,
00230   guint info,
00231   guint time,
00232   gpointer udata      // Should point to Shape_draw.
00233   )
00234   {
00235   Shape_draw *draw = (Shape_draw *) udata;
00236   cout << "drag_data_received" << endl;
00237   if (draw->drop_callback &&
00238       seldata->type == gdk_atom_intern(U7_TARGET_SHAPEID_NAME, 0) &&
00239       seldata->format == 8 && seldata->length > 0)
00240     {
00241     int file, shape, frame;
00242     Get_u7_shapeid(seldata->data, file, shape, frame);
00243     (*draw->drop_callback)(file, shape, frame,
00244               draw->drop_user_data);
00245     }
00246   }
00247 
00248 /*
00249  *  Set to accept drops from drag-n-drop of a shape.
00250  */
00251 
00252 void Shape_draw::enable_drop
00253   (
00254   Drop_callback callback,   // Call this when shape dropped.
00255   void *udata     // Passed to callback.
00256   )
00257   {
00258   gtk_widget_realize(draw);//???????
00259 #ifndef WIN32
00260   drop_callback = callback;
00261   drop_user_data = udata;
00262   GtkTargetEntry tents[1];
00263   tents[0].target = U7_TARGET_SHAPEID_NAME;
00264   tents[0].flags = 0;
00265   tents[0].info = U7_TARGET_SHAPEID;
00266   gtk_drag_dest_set(draw, GTK_DEST_DEFAULT_ALL, tents, 1,
00267       (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE));
00268 
00269   gtk_signal_connect(GTK_OBJECT(draw), "drag_data_received",
00270         GTK_SIGNAL_FUNC(drag_data_received), this);
00271 #endif
00272   }
00273 
00274 /*
00275  *  Set an icon for dragging FROM this area.
00276  */
00277 
00278 void Shape_draw::set_drag_icon
00279   (
00280   GdkDragContext *context,
00281   Shape_frame *shape    // Shape to use for the icon.
00282   )
00283   {
00284   int w = shape->get_width(), h = shape->get_height(),
00285     xright = shape->get_xright(), ybelow = shape->get_ybelow();
00286   Image_buffer8 tbuf(w, h); // Create buffer to render to.
00287   tbuf.fill8(0xff);   // Fill with 'transparent' pixel.
00288   unsigned char *tbits = tbuf.get_bits();
00289   shape->paint(&tbuf, w - 1 - xright, h - 1 - ybelow);
00290           // Put shape on a pixmap.
00291   GdkPixmap *pixmap = gdk_pixmap_new(draw->window, w, h, -1);
00292   gdk_draw_indexed_image(pixmap, drawgc, 0, 0, w, h,
00293       GDK_RGB_DITHER_NORMAL, tbits,
00294       tbuf.get_line_width(), palette);
00295   int mask_stride = (w + 7)/8;  // Round up to nearest byte.
00296   char *mdata = new char[mask_stride*h];
00297   for (int y = 0; y < h; y++) // Do each row.
00298           // Do each byte.
00299     for (int b = 0; b < mask_stride; b++)
00300       {
00301       char bits = 0;
00302       unsigned char *vals = tbits + y*w + b*8;
00303       for (int i = 0; i < 8; i++)
00304         if (vals[i] != 0xff)
00305           bits |= (1<<i);
00306       mdata[y*mask_stride + b] = bits;
00307       }
00308   GdkBitmap *mask = gdk_bitmap_create_from_data(draw->window,
00309               mdata, w, h);
00310   delete mdata;
00311           // This will be the shape dragged.
00312   gtk_drag_set_icon_pixmap(context,
00313       gdk_window_get_colormap(draw->window), pixmap, mask,
00314           w - 2 - xright, h - 2 - ybelow);
00315   gdk_pixmap_unref(pixmap);
00316   gdk_bitmap_unref(mask);
00317   }
00318 
00319 /*
00320  *  Start dragging from here.
00321  *
00322  *  Note: Sets 'dragging', which is only cleared by 'mouse_up()'.
00323  */
00324 
00325 void Shape_draw::start_drag
00326   (
00327   char *target,     // Target (ie, U7_TARGET_SHAPEID_NAME).
00328   int id,       // ID (ie, U7_TARGET_SHAPEID).
00329   GdkEvent *event     // Event that started this.
00330   )
00331   {
00332   if (dragging)
00333     return;
00334   dragging = true;
00335   GtkTargetEntry tents[1];// Set up for dragging.
00336   tents[0].target = target;
00337   tents[0].flags = 0;
00338   tents[0].info = id;
00339   GtkTargetList *tlist = gtk_target_list_new(&tents[0], 1);
00340           // ??+++ Do we need to free tlist?
00341   gtk_drag_begin(draw, tlist,
00342       (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE),
00343       1, event);
00344   }

Generated on Mon Jul 9 14:42:48 2007 for ExultEngine by  doxygen 1.5.1