Subversion Repositories wimsdev

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
20 reyssat 1
// 2D Graphics Package
2
// Drawing routines for DynLayer
3
// Copyright (C) 2000-2001 Dan Steinman, Guoyi Chao, Rob Breeds
4
 
5
// Guoyi Chao: drawing routines for line, circle, ellipse
6
// Dan Steinman: DynAPI2 support, object wrappers, VML support, improved routines for line, rect, and fills()
7
// Rob Breeds: improve performance on ellipse and circle algorithms, and added line thicknesses support
8
 
9
// Distributed under the terms of the GNU Library General Public License
10
 
11
function Graphics(dlyr) {
12
        this._dlyr = dlyr;
13
        this._s = "yellow";
14
        this._w = 1;
15
        this._f = "white";
16
}
17
Graphics.prototype.setStrokeColor = function(v) {this._s = v};
18
Graphics.prototype.setStrokeWeight = function(v) {this._w = v};
19
Graphics.prototype.setFillColor = function(v) {this._f = v};
20
Graphics.prototype.drawPixel = function(x,y) {
21
        drawPixel(x,y,this._s,this._w,this);
22
};
23
Graphics.prototype.drawLine = function(x1,y1,x2,y2) {
24
        var shape;
25
        if (Graphics.useVML) {
26
                shape = new VML_Line(x1,y1,x2,y2,this._w,this._s);
27
                this._dlyr.elm.appendChild(shape.elm);
28
        }
29
        else {
30
                shape = new Line(x1,y1,x2,y2,this._w,this._s);
31
                this._dlyr.addChild(shape);
32
        }
33
        return shape;
34
};
35
Graphics.prototype.drawCircle = function(x,y,radius) {
36
        var shape;
37
        if (Graphics.useVML) {
38
                // bug in IE, always fills anyway
39
                shape = new VML_Oval(x,y,2*radius,2*radius,this._w,this._s, dynapi.ua.ie5?this._dlyr.bgColor:false);
40
                this._dlyr.elm.appendChild(shape.elm);
41
        }
42
        else {
43
                shape = new Circle(x,y,radius,this._w,this._s);
44
                this._dlyr.addChild(shape);
45
        }
46
        return shape;
47
};
48
Graphics.prototype.fillCircle = function(x,y,r) {
49
        fillCircle(x+r,y+r,r,this.color,this._dlyr);
50
};
51
Graphics.prototype.drawOval = function(x,y,w,h) {
52
        drawEllipse(x+w/2,y+h/2,w,h,this.color,false,this.thickness,this._dlyr);
53
};
54
Graphics.prototype.fillEllipse = function(x,y,w,h) {
55
        drawEllipse(x+w/2,y+h/2,w,h,this.color,true,this.thickness,this._dlyr);
56
};
57
Graphics.prototype.drawRect = function(x,y,w,h) {
58
        drawRect(x,y,w,h,this.color,this.thickness,this._dlyr);
59
};
60
Graphics.prototype.fillRect = function(x,y,w,h) {
61
        fillRect(x,y,w,h,this.color,this._dlyr);
62
};
63
Graphics.prototype.clear = function() {
64
        this.deleteAllChildren();
65
        this.setHTML('');
66
};
67
 
68
Graphics.useVML = false;
69
if (dynapi.ua.ie && dynapi.ua.v>=5) {  // include active-x component for IE5+
70
        Graphics.useVML = true;
71
        var str = '<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>'+
72
                '<object id="VMLRender" codebase="vgx.dll" classid="CLSID:10072CEC-8CC1-11D1-986E-00A0C955B42E"></object>'+
73
                '<style>'+
74
                '<!--'+
75
                'v\\:* { behavior: url(#VMLRender); }'+
76
                '-->'+
77
                '</style>';
78
 
79
        if (dynapi.loaded) {
80
                dynapi.frame.document.body.appendChild('beforeEnd',str);
81
        }
82
        else {
83
                document.write(str);
84
        }
85
}
86
 
87
// Drawing Routines
88
 
89
function Pixel(x,y,color,t) {   // not really needed
90
        this.DynLayer = DynLayer;
91
        this.DynLayer();
92
        this.setLocation(x,y);
93
        this.setSize(t||1,t||1);
94
        this.setBgColor(color||"black");
95
}
96
Pixel.prototype = new DynLayer();
97
 
98
function drawPixel(x,y,color,t,lyr) {
99
        lyr.addChild( new DynLayer('',Math.round(x),Math.round(y),t,t,color) )
100
}
101
 
102
function Shape() {
103
        this.DynLayer = DynLayer;
104
        this.DynLayer();
105
 
106
        this.setStrokeColor("black");
107
        this.setStrokeWeight(1);
108
}
109
Shape.prototype = new DynLayer();
110
Shape.prototype.setStrokeColor = function(v) {this._s = v};
111
Shape.prototype.setStrokeWeight = function(v) {this._w = v};
112
 
113
function Line(x1,y1,x2,y2,w,s) {
114
        this.Shape = Shape;
115
        this.Shape();
116
        this.setStrokeWeight(w);
117
        this.setStrokeColor(s);
118
 
119
        var dx = Math.min(x1,x2);
120
        var dy = Math.min(y1,y2);
121
        var width = Math.abs(x2-x1);
122
        var height = Math.abs(y2-y1);
123
        this.setLocation(dx, dy);
124
 
125
        if(x1==x2||y1==y2) {  // straight line
126
                this.setBgColor(s);
127
                if(x1==x2) this.setSize(w,height); // vertical
128
                else this.setSize(width,w);  //horizontal
129
        }
130
        else {  // diagonal
131
                this.setSize(width,height);
132
                var nx1 = x1-dx;
133
                var ny1 = y1-dy;
134
                var nx2 = x2-dx;
135
                var ny2 = y2-dy;
136
                drawLine(nx1,ny1,nx2,ny2,s,w,this);
137
        }
138
}
139
Line.prototype = new Shape();
140
 
141
function VMLElement() {
142
        this.elm = null
143
};
144
VMLElement.prototype.createShape = function(type) {
145
        this.elm = document.createElement('v:'+type);
146
}
147
VMLElement.prototype.setLocation = function() {};
148
 
149
function VML_Line(x1,y1,x2,y2,w,s) {
150
        this.VMLElement = VMLElement;
151
        this.VMLElement();
152
 
153
        this.createShape("line");
154
        this.elm.from = x1+'px ,'+y1+'px';
155
        this.elm.to = x2+'px ,'+y2+'px';
156
        this.elm.strokeColor = s;
157
        this.elm.innerHTML = '<v:stroke weight="'+w+'px">';    
158
 
159
        //this.elm.innerHTML = '<v:stroke weight="'+this.thickness+'px" color="'+this.color+'">';
160
        //"<v:line id='line" + nnode + "' from=" + x1 + "," + y1 +"' to='" + x2 + "," + y2 +"'><v:stroke weight='2px' color='black'/></v:line>";
161
};
162
VML_Line.prototype = new VMLElement();
163
 
164
function VML_Oval(x,y,width,height,w,s,fc) {
165
        this.VMLElement = VMLElement;
166
        this.VMLElement();
167
 
168
        this.elm = document.createElement('v:oval');
169
        this.elm.style.position = "absolute";
170
        this.elm.style.left = x+"px";
171
        this.elm.style.top = y+"px";
172
        this.elm.style.width = width+"px";
173
        this.elm.style.height = height+"px";
174
 
175
        this.elm.strokeColor = s;
176
 
177
        if (fc) {
178
                this.elm.fillColor = fc;
179
                this.elm.fill = true;
180
        }
181
        else this.elm.fill = false;
182
 
183
        this.elm.innerHTML = '<v:stroke weight="'+w+'px">';
184
};
185
VML_Oval.prototype = new VMLElement();
186
 
187
function drawLine(x1,y1,x2,y2,color,t,lyr) {
188
        var flag = (Math.abs(y2-y1) > Math.abs(x2-x1))
189
        var dx,dy,x,y,e,xstep,ystep
190
        if (flag) dx=Math.abs(y2-y1),dy=Math.abs(x2-x1),x=y1,y=x1
191
        else dx=Math.abs(x2-x1),dy=Math.abs(y2-y1),x=x1,y=y1
192
        xstep=x1>x2?-1:1
193
        ystep=y1>y2?-1:1
194
        if(x1==x2||y1==y2) {
195
                if(x1==x2) {
196
                        var ny1 = Math.min(y1,y2)
197
                        var ny2 = Math.max(y1,y2)
198
                        lyr.addChild( new DynLayer('',x1,ny1,t,(ny2-ny1)*t,color) )
199
                        return
200
                }
201
                else {
202
                        var nx1 = Math.min(x1,x2)
203
                        var nx2 = Math.max(x1,x2)
204
                        lyr.addChild( new DynLayer('',nx1,y1,(nx2-nx1)*t,t,color) )
205
                        return
206
                }
207
        }
208
        // Bresenham Method Begin
209
        var e=-dx
210
        for(var count=0;count<=dx;count++) {
211
                if (flag) drawPixel(y,x,color,t,lyr)
212
                else drawPixel(x,y,color,t,lyr)
213
                if (flag) x+=ystep
214
                else x+=xstep
215
                e+=dy<<1
216
                if(e>=0) {
217
                        if(flag) y+=xstep
218
                        else y+=ystep
219
                        e-=dx<<1
220
                }
221
        }
222
        return
223
}
224
 
225
function Circle(x,y,radius,w,s) {
226
        this.Shape = Shape;
227
        this.Shape();
228
        this.setStrokeWeight(w);
229
        this.setStrokeColor(s);
230
 
231
        this.setLocation(x,y);
232
        this.setSize(2*radius, 2*radius);
233
 
234
        drawCircle(0+radius,0+radius,radius-1,this._s,this._w,this);
235
}
236
Circle.prototype = new Shape();
237
 
238
function drawCircle(centerX,centerY,radius,color,t,lyr) {
239
        var x = centerX;
240
        var y = centerY;
241
        var cx = 0
242
        var cy = radius
243
        var df = 1 - radius
244
        var d_e = 3
245
        var d_se = -(radius<<1) + 5
246
        do {
247
                drawPixel(x+cx, y+cy, color,t,lyr)
248
                if (cx) drawPixel(x-cx, y+cy, color,t,lyr)
249
      if (cy)   drawPixel(x+cx, y-cy, color,t,lyr)
250
      if ((cx) && (cy)) drawPixel(x-cx, y-cy, color,t,lyr)
251
      if (cx != cy) {
252
                        drawPixel(x+cy, y+cx, color,t,lyr)
253
                        if (cx) drawPixel(x+cy, y-cx, color,t,lyr)
254
                        if (cy) drawPixel(x-cy, y+cx, color,t,lyr)
255
                        if (cx && cy) drawPixel(x-cy, y-cx, color,t,lyr)
256
      }
257
      if (df < 0)  {
258
                        df += d_e
259
                        d_e += 2
260
                        d_se += 2
261
      }
262
      else {
263
                        df += d_se
264
                        d_e += 2
265
                        d_se += 4
266
                        cy--
267
                }
268
                cx++
269
   } while (cx <= cy)
270
}
271
 
272
function fillCircle(x,y,radius,color,lyr) {
273
        var cx = 0
274
        var cy = radius
275
        var df = 1 - radius
276
        var d_e = 3
277
        var d_se = -(radius<<1) + 5
278
        do {
279
                fillRect(x-cy, y-cx, cy<<1, cx<<1, color,lyr)
280
            if (df < 0)  {
281
                        df += d_e
282
                        d_e += 2
283
                        d_se += 2
284
                }
285
                else {
286
                        if (cx != cy) fillRect(x-cx, y-cy, cx<<1, cy<<1, color,lyr)
287
                        df += d_se
288
                        d_e += 2
289
                        d_se += 4
290
                        cy--
291
                }
292
                cx++
293
        } while (cx <= cy)
294
}
295
 
296
function drawEllipse(cx,cy,rx,ry,color,filled,t,lyr) {
297
        var x,y,a2,b2, S, T
298
        a2 = rx*rx
299
        b2 = ry*ry
300
        x = 0
301
        y = ry
302
        S = a2*(1-2*ry) + 2*b2
303
        T = b2 - 2*a2*(2*ry-1)
304
        symmPaint(cx,cy,x,y,color,filled,t,lyr)
305
        do {
306
                if (S<0) {
307
                        S += 2*b2*(2*x+3)
308
                        T += 4*b2*(x+1)
309
                        x++
310
                } else if (T<0) {
311
                        S += 2*b2*(2*x+3) - 4*a2*(y-1)
312
                        T += 4*b2*(x+1) - 2*a2*(2*y-3)
313
                        x++
314
                        y--
315
                } else {
316
                        S -= 4*a2*(y-1)
317
                        T -= 2*a2*(2*y-3)
318
                        y--
319
                }
320
                symmPaint(cx,cy,x,y,color,filled,t,lyr)
321
        } while (y>0)
322
}
323
 
324
//Bresenham's algorithm for ellipses
325
function symmPaint(cx,cy, x, y, color, filled, t, lyr){
326
        if (filled) {
327
                fillRect ( cx-x, cy-y, x<<1, y<<1, color, lyr )
328
        } else {
329
                drawPixel ( cx-x, cy-y, color, t,lyr )
330
                drawPixel ( cx+x, cy-y, color, t,lyr )
331
                drawPixel ( cx-x, cy+y, color, t,lyr )
332
                drawPixel ( cx+x, cy+y, color, t,lyr )
333
        }
334
}
335
 
336
function drawRect(x,y,w,h,color,t,lyr) {
337
        lyr.addChild( new DynLayer('',x,y,w,t,color) )
338
        lyr.addChild( new DynLayer('',x,y,t,h,color) )
339
        lyr.addChild( new DynLayer('',x+w-t,y,t,h,color) )
340
        lyr.addChild( new DynLayer('',x,y+h-t,w,t,color) )
341
}
342
 
343
function fillRect(x,y,w,h,color,lyr) {
344
        lyr.addChild( new DynLayer('',x,y,w,h,color) )
345
}