/*
* Copyright (C) 1999, 2008 Philippe Banwarth
* email: bwt@altern.org
* smail: Philippe Banwarth, 8 sente du milieu des Gaudins, 95150 Taverny, France.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include "gcompris/gcompris.h"
#include
#include
/* Added by Florian Ernst for lines 193 and 194 */
//#include
/* End of added section */
#include "gtans.h"
#include "gtans_interface.h"
#include "gtans_support.h"
void taninitstart(void);
/* GCompris */
static void start_board (GcomprisBoard *agcomprisBoard);
static void pause_board (gboolean pause);
static void end_board (void);
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
static gint actual_figure = -2;
/* Description of this plugin */
static BoardPlugin menu_bp =
{
NULL,
NULL,
"GTans",
"Tangram",
"Bruno Coudoin ",
NULL,
NULL,
NULL,
NULL,
start_board,
pause_board,
end_board,
is_our_board,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
GET_BPLUGIN_INFO(gtans)
static GcomprisBoard *gcomprisBoard = NULL;
static GooCanvasItem *boardRootItem = NULL;
static gboolean board_paused = FALSE;
static void start_board (GcomprisBoard *agcomprisBoard)
{
if(agcomprisBoard!=NULL)
{
gcomprisBoard=agcomprisBoard;
gcomprisBoard->level = 1;
gcomprisBoard->maxlevel = 1;
gc_bar_set(0);
gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas),
"tangram/gtans_bg.svgz");
selectedgrande = FALSE;
taninitstart();
}
}
static void end_board (void)
{
goo_canvas_item_remove(boardRootItem);
boardRootItem = NULL;
widgetpetite = NULL;
widgetgrande = NULL;
pixmapgrande1=NULL;
pixmapgrande2=NULL;
pixmappetite=NULL;
pixmappiece1=NULL;
pixmappiece2=NULL;
pixmapfond=NULL;
colselwin=NULL;
filselwin=NULL;
selectedgrande = FALSE;
}
static gboolean
is_our_board (GcomprisBoard *gcomprisBoard)
{
if (gcomprisBoard)
{
if(g_ascii_strcasecmp(gcomprisBoard->type, "tangram")==0)
{
/* Set the plugin entry */
gcomprisBoard->plugin=&menu_bp;
return TRUE;
}
}
return FALSE;
}
static void pause_board (gboolean pause)
{
if(gcomprisBoard==NULL)
return;
board_paused = pause;
if ((!pause) && figpetite.reussi) {
gtk_widget_show(widgetgrande);
gtk_widget_show(widgetpetite);
actual_figure++;
tansetnewfigurepart1(actual_figure);
tansetnewfigurepart2();
} else {
if (pause) {
gtk_widget_hide(widgetgrande);
gtk_widget_hide(widgetpetite);
} else {
gtk_widget_show(widgetgrande);
gtk_widget_show(widgetpetite);
}
}
}
void change_figure(gboolean next){
if (next)
tansetnewfigurepart1((actual_figure+1)%figtabsize);
else
tansetnewfigurepart1((actual_figure + figtabsize -1)%figtabsize);
tansetnewfigurepart2();
}
/********************************/
GtkWidget *mainwindow;
GtkWidget *widgetgrande; /* widget de la grande drawarea */
GtkWidget *widgetpetite; /* widget de la petite drawarea */
GtkStatusbar *widgetstat; /* widget de la statusbar */
GtkSpinButton *spinner=NULL;
gint statconid; /* context id de la statusbar */
GdkRectangle selbackrect; /* rectangle a redessiner pour effacer la piece selected */
GdkPixmap *pixmapgrande1=NULL,*pixmapgrande2;
GdkPixmap *pixmappetite=NULL;
GdkPixmap *pixmappiece1=NULL,*pixmappiece2=NULL,*pixmapfond=NULL;
GtkWidget *colselwin=NULL,*filselwin=NULL;
/* les polygones doivent etre clockwise */
tanpiecedef piecesdef[]={
{2.0/3,2.0/3, 4,{{1,0,6*HT},{1,0,0},{0,1,2*HT},{0,1,0}}, 3,{{0,0},{2,0},{0,2},{0,0}}},
{CL/3,CL/3, 2,{{CC,CC,5*HT},{CC,CC,3*HT},{0,0,0},{0,0,0}}, 3,{{0,0},{CL,0},{0,CL},{0,0}}},
{0.5,0.5, 2,{{0,0,0},{1,1,4*HT},{0,0,0},{0,0,0}}, 4,{{0,0},{1,0},{1,1},{0,1}}},
{CC/2,(CC+CL)/2,2,{{0,CC,1*HT},{CC,CL,5*HT},{0,0,0},{0,0,0}},4,{{0,CC},{CC,0},{CC,CL},{0,CC+CL}}},
{1.0/3,1.0/3, 1,{{0,0,0},{0,0,0},{0,0,0},{0,0,0}}, 3,{{0,0},{1,0},{0,1},{0,0}}}
};
tanfigure figuredebut={
0.125,1,TOUR/64,FALSE,
{{0,0,0.8,0.8,0},
{0,0,3.3,0.8,0},
{1,0,1.5,1.5,HT*4},
{2,0,6,0.6,0},
{3,0,6,1.6,HT*2},
{4,0,3.6,1.8,HT*7},
{4,0,4.1,1.3,HT*1}}
};
tanfigure *figtab=NULL;
int figtabsize; /* ==0 : pas de figure */
char *figfilename=NULL;
int figactualnr; /* nr de la figure dans le figtab (-1=figuredebut, -2=figpetite) */
tantinytri tinytabpe[TINYNBR],tinytabgr[TINYNBR];
tanfigure figgrande,figpetite;
int selectedgrande=FALSE;
int xact,yact,xoth,yoth,xold,yold;
int actiongrande=AN_none;
int selpossible=TRUE;
int rotact,rotnew,rotold;
int rotstepnbr=TOUR/32; /* nb. de pas de rotation affiches */
int initcbgr=FALSE,initcbpe=FALSE; /* init cb deja appellee ? */
GdkGC *invertgc;
int invx2,invy2;
GdkGC *tabgc[GCNBR];
GdkColor colortab[GCNBR];
GdkPixmap *dumtabpxpx[3],**tabpxpx=dumtabpxpx-PXSTART;
char *dumtabpxnam[3],**tabpxnam=dumtabpxnam-PXSTART;
gboolean helpoutset=FALSE;
gboolean helptanset=PIECENBR;
int accuracy; /* precision de reconaissance */
gboolean editmode;
#define FLPNTMAX PIECENBR*(PNTNBRMAX+1)*2
static gboolean dumtabpxpixmode[3],*tabpxpixmode=dumtabpxpixmode-PXSTART; /* mode VOULU */
static gboolean tabcolalloc[GCNBR]; /* couleur allouee ? */
static gchar *userconf=NULL; /* nom complet du fichier de config local */
static tanflfig flfigpetite;
static tanfpnt fpntspetite[FLPNTMAX];
static double dxout,dyout,dxpetite,dypetite;
static double selposxnc,selposync; /* position de la piece actuelle non limitee */
/********************************/
/* change la valeur max du spinbutton (si il existe) */
void tanspinsetvalmax (int val){
GtkAdjustment *adj;
if (spinner!=NULL){
adj = gtk_spin_button_get_adjustment(spinner);
adj->upper = (gfloat)val;
gtk_adjustment_changed(adj);
if (gtk_spin_button_get_value_as_int(spinner)){
gtk_spin_button_set_value(spinner, 0);
}
else{
tansetnewfigurepart1(0);
tansetnewfigurepart2();
}
} else
{
tansetnewfigurepart1(0);
tansetnewfigurepart2();
}
}
/********************************/
void tanallocname (char **pnt, char *name){
if (*pnt!=name){
if (*pnt!=NULL)
g_free(*pnt);
*pnt=(char *)g_malloc(strlen(name)+1);
strcpy(*pnt,name);
}
}
/********************************/
/* maintien les pieces dans les limites */
void tanclampgrandefig (void){
tanpiecepos *piecepos;
int i;
double dumzoom;
dumzoom = 1.0/figgrande.zoom;
piecepos = figgrande.piecepos;
for (i = 0; iposx = CLAMP(piecepos->posx, 0.0, dumzoom);
piecepos->posy = CLAMP(piecepos->posy, 0.0, dumzoom);
piecepos++;
}
return;
}
/********************************/
/* renvoi la direction d'un segment */
int tanangle (double dx, double dy){
int ret;
ret = (int)(atan2(dy,dx)/PASTOUR);
ret = (ret+TOUR)%TOUR;
return (ret);
}
/********************************/
gboolean tantinytabcompare (tantinytri *tinys1, tantinytri *tinys2, int accuracy){
gboolean libre[TINYNBR];
int i,j,jmin;
double dist,mindist,mindistmax,xi,yi;
int drot,drotmax,roti;
double flaccur;
switch (accuracy){
case 0 :
flaccur = 1.0;
drotmax = (int)(TOUR/64)+1;
break;
case 2 :
flaccur = 4.0;
drotmax = (int)(TOUR/32)+1;
break;
default :
flaccur = 2.0;
drotmax = (int)(TOUR/64)+1;
}
/* drotmax=figpetite.drotmax; */
mindistmax=pow(figpetite.distmax*0.10*flaccur,2);
for (i=0; iTOUR/2 )
drot = TOUR-drot;
if ( distmindistmax )
return FALSE;
}
return TRUE;
}
/********************************/
void tansmall2tiny (tansmalltri *small, tantinytri *tiny1, tantinytri *tiny2){
double cosrot,sinrot;
int rot;
rot=small->rot;
cosrot=cos(rot*PASTOUR);
sinrot=sin(rot*PASTOUR);
tiny1->rot=(rot+HT*3)%TOUR;
tiny1->posx=small->posx+0.5*cosrot +0.16666666*sinrot;
tiny1->posy=small->posy+0.16666666*cosrot-0.5*sinrot;
tiny2->rot=(rot+HT*5)%TOUR;
tiny2->posx=small->posx+0.16666666*cosrot+0.5*sinrot;
tiny2->posy=small->posy+0.5*cosrot -0.16666666*sinrot;
}
/********************************/
void tanmaketinytabnotr (tanfigure *figure, tantinytri *tinys){
int i,j;
tansmalltri dusmall,*small=&dusmall;
tanpiecepos *piecepos;
tanpiecedef *piecedat;
double ly,lx2,cosrot,sinrot;
int rot,rottri;
piecepos=figure->piecepos;
for (j=0; jtype];
rot=piecepos->rot;
cosrot=cos(rot*PASTOUR);
sinrot=sin(rot*PASTOUR);
for (i=0; itrinbr; i++){
lx2=piecedat->tri[i].posx-piecedat->handlex;
ly=piecedat->tri[i].posy-piecedat->handley;
rottri=piecedat->tri[i].rot;
if (piecepos->flipped){
lx2=-lx2;
rottri=TOUR+6*HT-rottri;
}
small->posx=piecepos->posx+lx2*cosrot+ly*sinrot;
small->posy=piecepos->posy+ly*cosrot-lx2*sinrot;
small->rot=(rottri+rot)%TOUR;
tansmall2tiny(small,tinys,tinys+1);
tinys+=2;
}
piecepos++;
}
}
/********************************/
void tantranstinytab (tantinytri *tinys){
int i;
double moyx=0,moyy=0;
for (i=0; iposx;
moyy+=tinys->posy;
tinys++;
}
moyx/=TINYNBR;
moyy/=TINYNBR;
for (i=0; iposx-=moyx;
tinys->posy-=moyy;
}
}
/********************************/
/* termine la rotation (lorsque le mouse button est relache) */
/* est appele par redrawgrande et on_buttonpress au cas ou le signal a ete masque par*/
/* l'appui sur un bouton */
void tanreleaseifrot (void){
if (actiongrande==AN_rot){
gdk_draw_line (widgetgrande->window,
invertgc,
xact,yact,invx2,invy2);
figgrande.piecepos[PIECENBR-1].rot=(rotnew+TOUR*5)%TOUR;
}
actiongrande = AN_none;
return;
}
/********************************/
/* calcule une serie de GdkPoint correspondant au polygone de la piece */
/* + un point correspondand au centre de la piece */
int tanplacepiece (tanpiecepos *piecepos, GdkPoint *pnts, double zoom){
int i;
tanpiecedef *piecedat;
double lx,ly,lx2,cosrot,sinrot;
int rot;
piecedat=&piecesdef[piecepos->type];
rot=piecepos->rot;
cosrot=cos(rot*PASTOUR);
sinrot=sin(rot*PASTOUR);
for(i=0; ipntnbr; i++){
lx2=piecedat->pnt[i].posx-piecedat->handlex;
ly=piecedat->pnt[i].posy-piecedat->handley;
if (piecepos->flipped)
lx2=-lx2;
lx=(piecepos->posx+lx2*cosrot+ly*sinrot)*zoom;
ly=(piecepos->posy+ly*cosrot-lx2*sinrot)*zoom;
pnts->x=(gint16)(lx+ARON);
pnts->y=(gint16)(ly+ARON);
pnts++;
}
pnts->x=(gint16)(piecepos->posx*zoom+ARON);
pnts->y=(gint16)(piecepos->posy*zoom+ARON);
return(piecedat->pntnbr);
}
/********************************/
/* calcule une serie de point en flottant correspondant au polygone de la piece */
/* pas de point central */
/* copie le premier points derriere le dernier */
/* le polygone retourne est clockwise (si la def l'est) */
int tanplacepiecefloat (tanpiecepos *piecepos, tanfpnt *fpnts, double zoom){
int i;
tanpiecedef *piecedat;
double lx,ly,lx2,cosrot,sinrot;
int rot;
int nbr;
piecedat=&piecesdef[piecepos->type];
nbr=piecedat->pntnbr;
rot=piecepos->rot;
cosrot=cos(rot*PASTOUR);
sinrot=sin(rot*PASTOUR);
for(i=0; ipnt[i].posx-piecedat->handlex;
ly=piecedat->pnt[i].posy-piecedat->handley;
if (piecepos->flipped)
lx2=-lx2;
lx=(piecepos->posx+lx2*cosrot+ly*sinrot)*zoom;
ly=(piecepos->posy+ly*cosrot-lx2*sinrot)*zoom;
fpnts->posx=lx;
fpnts++->posy=ly;
}
fpnts -=nbr;
if (piecepos->flipped){
tanfpnt dumfpnt;
for (i = 0; iposx-segment->posx;
*pdy=point->posy-segment->posy;
seglencar=segdx*segdx+segdy*segdy;
if ( (scal=(*pdx*segdx)+(*pdy*segdy))<0 || (dum=scal/seglencar)>1 )
return (1000000.0);
*pdx-=segdx*dum;
*pdy-=segdy*dum;
return (*pdx*(*pdx)+*pdy*(*pdy));
}
/********************************/
double tandistcar (tanfpnt *pnt1, tanfpnt *pnt2){
double dx,dy;
dx=(pnt1->posx-pnt2->posx);
dy=(pnt1->posy-pnt2->posy);
return (dx*dx+dy*dy);
}
/********************************/
void tancolle (tanfigure *figure, double seuil){
tanpiecepos *piecepos;
tanfpnt pnts1[PNTNBRMAX+1],pnts2[PNTNBRMAX+1];
int pntnbr1,pntnbr2;
int i,j,k,l;
int nbrcommun;
double dx,dy,dx2,dy2,dxtot,dytot;
seuil*=seuil;
piecepos=figure->piecepos;
for (i=0; iseuil && (dx2*dx2+dy2*dy2)>seuil ){
if ( tandistcarsegpnt(&pnts1[k],&pnts2[l],&dx,&dy)seuil && (dx2*dx2+dy2*dy2)>seuil ){
if ( tandistcarsegpnt(pnts1+k*2,pnts2+l*2,&dx,&dy)ixmax)
ixmax=ix;
if (iyiymax)
iymax=iy;
}
update_rect.x=ixmin;
update_rect.y=iymin;
update_rect.width=ixmax-ixmin+1;
update_rect.height=iymax-iymin+1;
switch (remplis){
case TAN_PETITEHLP:
gc=tabgc[GCPETITEHLP];
break;
case TAN_PIECENOR:
gc=tabgc[GCPIECENOR];
gdk_gc_set_ts_origin (gc,pnt[pntnbr].x,pnt[pntnbr].y);
break;
case TAN_PIECEHI:
gc=tabgc[GCPIECEHI];
gdk_gc_set_ts_origin (gc,pnt[pntnbr].x,pnt[pntnbr].y);
break;
default:
gc=widget->style->white_gc;
break;
}
gdk_draw_polygon (pixmap,
gc,
TRUE,
pnt,
pntnbr);
if ( remplis==TAN_PIECENOR || remplis==TAN_PIECEHI ){
pnt[pntnbr]=pnt[0]; /* ecrase le point du centre */
for (i=0; iflipped)
gris=-gris;
gris=gris+0.5;
gdk_draw_line (pixmap,
tabgc[(int)(gris*(GRISNBR))],
pnt[i].x,pnt[i].y,pnt[i+1].x,pnt[i+1].y);
}
}
return(update_rect);
}
/********************************/
void tandrawfigure (GtkWidget *widget,GdkPixmap *pixmap,
tanfigure *figure,int exclue, tanremplis remplis){
double zoom;
int i;
tanpiecepos *piecepos;
zoom=widget->allocation.width*figure->zoom;
piecepos=figure->piecepos;
for (i=0; iallocation.width*figgrande.zoom;
dx=dxout;
dy=dyout;
}
else{
zoom = widgetpetite->allocation.width*figpetite.zoom;
dx=dxpetite;
dy=dypetite;
}
flpiecenbr = flfig->flpiecenbr;
for (i = 0; iflpieces[i].flpnts;
flpntnbr = flfig->flpieces[i].flpntnbr;
polytype = flfig->flpieces[i].polytype;
for (j = 0; jallocation.width,
widgetgrande->allocation.height);
if ( helpoutset && figtabsize )
tandrawfloat(pixmap, TRUE);
}
/********************************/
void taninitselect(int selected, gboolean force){
int i;
tanpiecepos dum;
if ( force ||
selected != PIECENBR-1 ||
!selectedgrande ){
tandrawbgndgr(pixmapgrande2);
tandrawfigure(widgetgrande,pixmapgrande2,&figgrande,
selected,TAN_PIECENOR);
selbackrect.x=0;
selbackrect.y=0;
selbackrect.width=widgetgrande->allocation.width;
selbackrect.height=widgetgrande->allocation.height;
dum=figgrande.piecepos[selected];
for (i=selected; iallocation.width*figgrande.zoom;
selposxnc += dx/zoom;
selposync += dy/zoom;
selpiece->posx = CLAMP(selposxnc, 0, 1.0/figgrande.zoom);
selpiece->posy = CLAMP(selposync, 0, 1.0/figgrande.zoom);
dumrot=selpiece->rot;
rotnew=selpiece->rot-=drot;
gdk_draw_pixmap(pixmapgrande1,
widgetgrande->style->fg_gc[GTK_WIDGET_STATE (widgetgrande)],
pixmapgrande2,
selbackrect.x,selbackrect.y,
selbackrect.x,selbackrect.y,
selbackrect.width,selbackrect.height);
selbk2=tandrawpiece(widgetgrande,pixmapgrande1,
selpiece,
zoom,
TAN_PIECEHI);
gtk_widget_draw (widgetgrande, &selbackrect);
gtk_widget_draw (widgetgrande, &selbk2);
selbackrect=selbk2;
selpiece->rot=dumrot;
}
/********************************/
void tanredrawgrande (void){
GdkRectangle rect={0,0,0,0};
GtkWidget *widget=NULL;
tanreleaseifrot();
if (selectedgrande){
taninitselect(PIECENBR-1, TRUE);
tandrawselect(0,0,0);
}
else{
widget=widgetgrande;
tandrawbgndgr(pixmapgrande1);
tandrawfigure(widget, pixmapgrande1, &figgrande, PIECENBR+1, TAN_PIECENOR);
rect.width=widget->allocation.width;
rect.height=widget->allocation.height;
gtk_widget_draw (widget, &rect);
}
}
/********************************/
void tanclearreussinr (int fignr){
if ( fignr>= 0 && fignrreussi = FALSE;
}
/********************************/
void tansetreussiactual (void){
figpetite.reussi = TRUE;
if ( figactualnr>= 0 && figactualnrreussi = TRUE;
}
/********************************/
void tanredrawpetite (void){
GdkRectangle rect={0,0,0,0};
int wid,hei;
/* in case we are called before widget configured */
if (!widgetpetite)
return;
wid = widgetpetite->allocation.width;
hei = widgetpetite->allocation.height;
gdk_draw_rectangle (pixmappetite,
figpetite.reussi ? tabgc[GCPETITECHK] : tabgc[GCPETITEBG],
TRUE,
0, 0, wid, hei);
if (!figtabsize)
return;
tandrawfloat (pixmappetite, FALSE);
if (helptansetallocation.width*figpetite.zoom,
TAN_PETITEHLP);
/* tandrawfigure(widget, pixmappetite, &figpetite, PIECENBR+1, TAN_PETITEFG); */
rect.width=wid;
rect.height=hei;
gtk_widget_draw (widgetpetite, &rect);
}
/********************************/
void tanunselect (void){
if (selectedgrande){
selectedgrande=FALSE;
tanredrawgrande();
}
}
/********************************/
gdouble tanreadfloat(FILE *fhd, int *lres)
{
gdouble pouet;
char buf[100];
pouet = 1;
if (*lres==1){
*lres = fscanf(fhd, "%99s",buf);
pouet=g_strtod(buf,NULL);
}
return pouet;
}
/********************************/
#define SPESC if (lres==1) lres = fscanf
gboolean tanloadfigtab (char *name){
FILE *hand=NULL;
int i,j;
gboolean succes;
int newfigtabsize;
tanfigure *newfigtab=NULL,*figs;
int lres;
lres=0;
if ( (hand = g_fopen(name, "r"))!=NULL &&
fscanf(hand, "gTans v1.0 %d \n", &newfigtabsize)==1 &&
(newfigtab = (tanfigure *)g_malloc(sizeof(tanfigure)*newfigtabsize))!=NULL ){
lres=1;
figs = newfigtab;
for (i = 0; izoom = tanreadfloat(hand, &lres);
figs->distmax = tanreadfloat(hand, &lres);
SPESC(hand,"%d \n", &figs->drotmax);
/*fscanf(hand,"%le %le %d \n",&figs->zoom,&figs->distmax,&figs->drotmax);*/
for (j=0; jpiecepos[j].type);
SPESC(hand,"%d", &figs->piecepos[j].flipped);
figs->piecepos[j].posx = tanreadfloat(hand, &lres);
figs->piecepos[j].posy = tanreadfloat(hand, &lres);
SPESC(hand,"%d \n", &figs->piecepos[j].rot);
/*fscanf(hand,"%d %d %le %le %d \n",&figs->piecepos[j].type,&figs->piecepos[j].flipped,
&figs->piecepos[j].posx,&figs->piecepos[j].posy,&figs->piecepos[j].rot);*/
}
figs++;
}
} else
g_warning("Opening file %s fails",name);
if (hand!=NULL)
fclose(hand);
succes=FALSE;
if (lres==1){
succes=TRUE;
if(figtab!=NULL)
g_free(figtab);
figtab=newfigtab;
figtabsize=newfigtabsize;
actual_figure = 0;
tansetnewfigurepart1(actual_figure);
tansetnewfigurepart2();
//tanspinsetvalmax(figtabsize-1);
}
if (succes || figfilename==NULL)
tanallocname(&figfilename, name);
return(succes);
}
/********************************/
/* charge un pixmap, si necessaire desalloue et/ou (re)alloue la couleur */
gboolean tansetpixmapmode(GtkWidget *widget, char *aname, int gcnbr){
GdkPixmap *pixmap;
GdkGC *gc;
char *pname;
gboolean ret;
pixmap=tabpxpx[gcnbr];
pname=tabpxnam[gcnbr];
gc=tabgc[gcnbr];
if (tabcolalloc[gcnbr]){
gdk_colormap_free_colors (gdk_colormap_get_system(), &colortab[gcnbr], 1);
tabcolalloc[gcnbr] = FALSE;
}
if (pixmap!=NULL)
gdk_pixmap_unref(pixmap);
ret=FALSE;
if ( (pixmap=gdk_pixmap_create_from_xpm (widget->window, NULL, NULL, aname))!=NULL ){
tanallocname(&pname,aname);
gdk_gc_set_fill (gc, GDK_TILED);
gdk_gc_set_tile (gc, pixmap);
ret=TRUE;
}
if (pname==NULL)
tanallocname(&pname,"LoadPixmapFailed");
tabpxpx[gcnbr] = pixmap;
tabpxnam[gcnbr] = pname;
tabpxpixmode[gcnbr] = ret;
if (!ret)
tansetcolormode(&colortab[gcnbr],gcnbr);
return (ret);
}
/********************************/
/* passe en mode color, decharge le pixmap (mais pas le nom) */
void tansetcolormode(GdkColor *acolor, int gcnbr){
GdkPixmap *pixmap;
GdkGC *gc;
GdkColor *pcolor;
GdkColormap *syscmap;
gc = tabgc[gcnbr];
pcolor = &colortab[gcnbr];
syscmap = gdk_colormap_get_system();
if (tabcolalloc[gcnbr])
gdk_colormap_free_colors (syscmap, pcolor, 1);
if ( gcnbr>=PXSTART && gcnbrred = acolor->red;
pcolor->green = acolor->green;
pcolor->blue = acolor->blue;
tabcolalloc[gcnbr] = gdk_colormap_alloc_color (syscmap, pcolor, FALSE, TRUE);
gdk_gc_set_fill (gc, GDK_SOLID);
gdk_gc_set_foreground (gc, pcolor);
}
/********************************/
/* config par defaut */
void tansetdefconfig (void){
int i;
guint backgroung_color_red = 0xe8<<8;
guint backgroung_color_green = 0xe7<<8;
guint backgroung_color_blue = 0xe2<<8;
for (i = PXSTART; ipackage_data_dir,
"/tangram/default.figures", NULL);
tanallocname(&figfilename, deffigfile);
g_free(deffigfile);
accuracy = 1;
rotstepnbr = TOUR/32;
figgrande.zoom = 0.125;
return;
}
/********************************/
/* supprime 2 points successifs identiques (en principe inutile) */
gboolean tanremsame(tanflfig *flfig, tanpoly *polys, int *pntsuiv, tanfpnt *fpnts, double seuil){
int i,k;
gboolean trouve, ret;
int polynbr;
int act;
int suiv;
polynbr = flfig->flpiecenbr;
ret = FALSE;
trouve = TRUE;
while (trouve){
trouve = FALSE;
for (i = 0; iflpiecenbr;
ret = FALSE;
trouve = TRUE;
while ( trouve && flptnewseuil &&
tandistcar(&segment[1], &fpnts[act2])>seuil &&
tandistcarsegpnt(segment, &fpnts[act2], &dx, &dy)flpiecenbr = polynbr;
return (ret);
}
/* "tasse" les fpnt et recree la floatfig */
/* copie les point de ref dans cop */
/* en sortie les 2 sont identiques mais la floatfig pointe sur cop */
int tantasse(tanflfig *flfig,
tanpoly *polys,
int *pntsuiv,
tanfpnt *fpntsref,
tanfpnt *fpntscop){
int i, j;
int act, pntnbr;
tanfpnt *fpnts;
fpnts=fpntscop;
for (i = 0; iflpiecenbr; i++){
pntnbr = polys[i].pntnbr;
flfig->flpieces[i].flpntnbr = pntnbr;
flfig->flpieces[i].flpnts = fpnts;
flfig->flpieces[i].polytype = polys[i].polytype;
act = polys[i].firstpnt;
for (j = 0; jflpiecenbr; i++){
pntnbr = polys[i].pntnbr;
polys[i].firstpnt = act;
for (j = 0; jflpiecenbr;
ret = FALSE;
trouve = TRUE;
while (trouve){
trouve = FALSE;
for (i = 0; iflpiecenbr;
ret = FALSE;
trouve = TRUE;
while (trouve){
trouve = FALSE;
for (i = 0; iflpiecenbr;
ret = FALSE;
trouve = TRUE;
while (trouve){
trouve = FALSE;
for (i = 0; iflpiecenbr = polynbr;
return (ret);
}
/* detecte les poly "inclus" */
/* probleme potentiel : pourrait ne pas detecter une inclusion
car on n'ajoute pas de points pour les 'auto-corespondance' */
gboolean taninclus(tanflfig *flfig, tanpoly *polys, int *pntsuiv, tanfpnt *fpnts, double seuil){
int i,k,l,m,n;
gboolean trouve, ret;
int polynbr;
int act1,act2;
int suiv1,suiv2;
int pntnbr;
tanpoly dumpoly;
double dumposxmin;
int dumpntposxmin = 0;
polynbr = flfig->flpiecenbr;
trouve = ret = FALSE;
for (i = 0; im+1; n--)
polys[n] = polys[n-2];
dumpoly.pntnbr -= l-k+1;
dumpoly.firstpnt = act1;
if (dumpoly.polytype!=TAN_POLYON)
dumpoly.polytype = TAN_POLYBACK;
else
dumpoly.polytype = TAN_POLYON;
polys[m] = dumpoly;
polys[m+1].pntnbr = l-k-1;
polys[m+1].firstpnt = act2;
polys[m+1].polytype = TAN_POLYON;
polynbr += 2;
trouve = ret = TRUE;
}
act2 = suiv2;
}
act1 = suiv1;
}
}
flfig->flpiecenbr = polynbr;
return (ret);
}
/* change de petite figure */
/* pas d'acces gtk */
void tansetnewfigurepart1(int nrfig){
tanfigure *figure;
int i,j;
double xmin=10000,xmax=-10000,ymin=10000,ymax=-10000;
tanpiecepos *piecepos;
tanflfig *flfig=&flfigpetite;
int flpiecenbr,flpntnbr;
tanfpnt *fpnts;
tanfpnt dumfpnts[FLPNTMAX];
tanpoly polys[PIECENBR];
int polypntact,polypntnbr;
int pntsuivants[FLPNTMAX];
double seuil=0.00000000001;
int pntnew;
if ( nrfig>=0 && figtabsize ){
nrfig %= figtabsize;
actual_figure = nrfig;
figure = figtab+nrfig;
} else {
if (nrfig==-1)
figure = &figuredebut;
else
figure = &figpetite;
nrfig = -1;
}
figactualnr = nrfig;
helptanset=PIECENBR;
figpetite=*figure;
tancolle(&figpetite,0.02);
tanmaketinytabnotr(&figpetite,tinytabpe);
tantranstinytab(tinytabpe);
/* la floatfig et preparation de la concatenation */
flfig->flpiecenbr = PIECENBR;
flfig->figure = figure;
fpnts = dumfpnts;
polypntact = 0;
for (i = 0; ipiecepos[i].type].pntnbr;
polys[i].pntnbr = polypntnbr;
polys[i].firstpnt = polypntact;
polys[i].polytype = TAN_POLYNORMAL;
for (j = 0; jpiecepos[i], fpnts,1);
fpnts += polypntnbr+1;
}
tanconcat(flfig, polys, pntsuivants, dumfpnts, seuil);
tanconseq(flfig, polys, pntsuivants, dumfpnts, seuil);
pntnew = tantasse(flfig, polys, pntsuivants, dumfpnts, fpntspetite);
tanajoute(flfig, polys, pntsuivants, dumfpnts, seuil, pntnew);
tanconcat(flfig, polys, pntsuivants, dumfpnts, seuil);
tanconseq(flfig, polys, pntsuivants, dumfpnts, seuil);
if (taninclus(flfig, polys, pntsuivants, dumfpnts, seuil))
taninclus(flfig, polys, pntsuivants, dumfpnts, seuil);
tanalign(flfig, polys, pntsuivants, dumfpnts);
tanremsame(flfig, polys, pntsuivants, dumfpnts, seuil);
pntnew = tantasse(flfig, polys, pntsuivants, dumfpnts, fpntspetite);
tanajoute(flfig, polys, pntsuivants, dumfpnts, seuil, pntnew);
tanconcat(flfig, polys, pntsuivants, dumfpnts, seuil);
tanconseq(flfig, polys, pntsuivants, dumfpnts, seuil);
if (taninclus(flfig, polys, pntsuivants, dumfpnts, seuil))
taninclus(flfig, polys, pntsuivants, dumfpnts, seuil);
tanalign(flfig, polys, pntsuivants, dumfpnts);
tanremsame(flfig, polys, pntsuivants, dumfpnts, seuil);
tantasse(flfig, polys, pntsuivants, dumfpnts, fpntspetite);
/* calcul du centrage */
flpiecenbr = flfig->flpiecenbr;
for (i = 0; iflpieces[i].flpnts;
flpntnbr = flfig->flpieces[i].flpntnbr;
for (j = 0; jxmax)
xmax=fpnts[j].posx;
if (fpnts[j].posy>ymax)
ymax=fpnts[j].posy;
if (fpnts[j].posx(ymax-ymin) ? (xmax-xmin) : (ymax-ymin) )+0.25);
dxpetite = 0.5*(xmax+xmin)-(0.5/figpetite.zoom);
dypetite = 0.5*(ymax+ymin)-(0.5/figpetite.zoom);
dxout = 0.5*(xmax+xmin)-(0.5/figgrande.zoom); /* cf tanrecentreout pour correction */
dyout = 0.5*(ymax+ymin)-(0.5/figgrande.zoom);
/* centrage des pieces petite */
piecepos=figpetite.piecepos;
for (i=0; iposx-=dxpetite;
piecepos->posy-=dypetite;
piecepos++;
}
}
/********************************/
/* corrige dxout et dyout pour les changement de zoom de figgrande */
void tanrecentreout(double oldzoom, double newzoom){
tanpiecepos *piecepos;
int i;
double correction;
correction = 0.5*(1/oldzoom-1/newzoom);
dxout += correction;
dyout += correction;
piecepos = figgrande.piecepos;
for (i = 0; iposx -= correction;
piecepos->posy -= correction;
piecepos++;
}
return;
}
/********************************/
/* change de petite figure */
void tansetnewfigurepart2(void){
if (selectedgrande){
helpoutset=FALSE;
tanunselect();
}
else if (helpoutset){ /* pour eviter 2 appels successif a tanredrawgrande */
helpoutset=FALSE;
tanredrawgrande();
}
tanredrawpetite();
selpossible=TRUE;
}
/********************************/
void spesavefig (void){
FILE *hand;
int j;
tanfigure *fig=NULL; /*juste pour eviter un warning*/
if ( (hand=g_fopen("pouet.fig", "w"))!=NULL){
fprintf(hand, "gTans v1.0 %d \n",figtabsize);
fig=&figgrande;
fprintf(hand,"%e %e %d \n",1.0,fig->distmax,fig->drotmax);
for (j=0; jpiecepos[j].type,fig->piecepos[j].flipped,
fig->piecepos[j].posx,fig->piecepos[j].posy,fig->piecepos[j].rot);
}
if (hand!=NULL){
fclose(hand);
figpetite=*fig;
figpetite.zoom=1;
tansetnewfigurepart1(-2);
tansetnewfigurepart2();
}
}
/********************************/
void taninitstart(void){
int i;
for (i = PXSTART; icanvas),
NULL);
create_mainwindow(boardRootItem);
tanloadfigtab(figfilename);
}
/********************************/
void tanend(void){
int i;
GdkColormap *syscmap;
syscmap = gdk_colormap_get_system();
if (userconf!=NULL)
g_free(userconf);
if (figfilename!=NULL)
g_free(figfilename);
if (figtab!=NULL)
g_free(figtab);
if (pixmappetite!=NULL)
gdk_pixmap_unref(pixmappetite);
if (pixmapgrande1!=NULL)
gdk_pixmap_unref(pixmapgrande1);
if (pixmapgrande2!=NULL)
gdk_pixmap_unref(pixmapgrande2);
if (pixmappiece1!=NULL)
gdk_pixmap_unref(pixmappiece1);
if (pixmappiece2!=NULL)
gdk_pixmap_unref(pixmappiece2);
if (pixmapfond!=NULL)
gdk_pixmap_unref(pixmapfond);
for (i=PXSTART; iwindow);
if (tabpxpixmode[i])
tansetpixmapmode(widgetgrande,tabpxnam[i],i);
else
tansetcolormode(&colortab[i],i);
}
for (i=0; ired = color->green = color->blue = (gushort)(65535.0/(GRISNBR-1)*i);
tabgc[i] = gdk_gc_new(widgetgrande->window);
tansetcolormode(color,i);
}
invertgc=gdk_gc_new(widgetgrande->window);
gdk_gc_set_function(invertgc,GDK_INVERT);
tabgc[GCPIECEHLP]=gdk_gc_new(widgetgrande->window);
tansetcolormode(&colortab[GCPIECEHLP],GCPIECEHLP);
/* les line attribute sont dans le callback */
if (initcbpe)
taninitcbcommun();
}
/********************************/
void taninitcbpe(void){
initcbpe=TRUE; /* pour ne pas initialiser 2 fois (c'est pas propre, mais bon) */
tabgc[GCPETITEFG]=gdk_gc_new(widgetpetite->window);
tansetcolormode(&colortab[GCPETITEFG],GCPETITEFG);
tabgc[GCPETITEBG]=gdk_gc_new(widgetpetite->window);
tansetcolormode(&colortab[GCPETITEBG],GCPETITEBG);
tabgc[GCPETITEHLP]=gdk_gc_new(widgetpetite->window);
tansetcolormode(&colortab[GCPETITEHLP],GCPETITEHLP);
tabgc[GCPETITECHK]=gdk_gc_new(widgetpetite->window);
tansetcolormode(&colortab[GCPETITECHK],GCPETITECHK);
if (initcbgr)
taninitcbcommun();
}
/********************************/
/* determine si le point x,y est dans la piece */
gboolean tanpntisinpiece(int x, int y, tanpiecepos *piecepos){
int i;
gboolean in;
GdkPoint pnt[PNTNBRMAX+2];
int nbrpnt;
nbrpnt=tanplacepiece(piecepos,pnt,widgetgrande->allocation.width*figgrande.zoom);
pnt[nbrpnt]=pnt[0];
in=TRUE;
if (piecepos->flipped){
for (i=0; (i0 )
in=FALSE;
}
return (in);
}
/********************************/
/* determine dans quelle piece se trouve le point (-1=aucune) */
int tanwichisselect(int x, int y){
int i;
gboolean trouve;
trouve=FALSE;
for (i=PIECENBR-1; i>=0 && !trouve; i--)
trouve=tanpntisinpiece(x,y,figgrande.piecepos+i);
if (trouve)
i++;
return (i);
}