Various fixes for various compilers...
[wxWidgets.git] / src / html / m_image.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mod_image.cpp
3 // Purpose: wxHtml module for displaying images
4 // Author: Vaclav Slavik
5 // RCS-ID: $Id$
6 // Copyright: (c) 1999 Vaclav Slavik, Joel Lucsy
7 // Licence: wxWindows Licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation
12 #endif
13
14 #include "wx/wxprec.h"
15
16 #include "wx/defs.h"
17 #if wxUSE_HTML
18
19 #ifdef __BORDLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WXPRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/html/forcelnk.h"
28 #include "wx/html/m_templ.h"
29
30
31 #include "wx/image.h"
32 #include "wx/dynarray.h"
33
34 #include <math.h>
35 #include <float.h>
36
37 FORCE_LINK_ME(mod_image)
38
39
40
41
42 WX_DECLARE_OBJARRAY(int, CoordArray);
43 #include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
44 WX_DEFINE_OBJARRAY(CoordArray);
45
46
47 //--------------------------------------------------------------------------------
48 // wxHtmlImageMapAreaCell
49 // 0-width, 0-height cell that represents single area in imagemap
50 // (it's GetLink is called from wxHtmlImageCell's)
51 //--------------------------------------------------------------------------------
52
53 class wxHtmlImageMapAreaCell : public wxHtmlCell
54 {
55 public:
56 enum celltype { CIRCLE, RECT, POLY };
57 protected:
58 CoordArray coords;
59 celltype type;
60 int radius;
61 public:
62 wxHtmlImageMapAreaCell( celltype t, wxString &coords );
63 virtual wxString GetLink( int x = 0, int y = 0 ) const;
64 };
65
66
67
68
69
70 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t, wxString &incoords )
71 {
72 int i;
73 wxString x = incoords, y;
74
75 type = t;
76 while ((i = x.Find( ',' )) != -1) {
77 coords.Add( wxAtoi( x.Left( i ).c_str() ) );
78 x = x.Mid( i + 1 );
79 }
80 coords.Add( wxAtoi( x.c_str() ) );
81 }
82
83 wxString wxHtmlImageMapAreaCell::GetLink( int x, int y ) const
84 {
85 switch (type) {
86 case RECT:
87 {
88 int l, t, r, b;
89
90 l = coords[ 0 ];
91 t = coords[ 1 ];
92 r = coords[ 2 ];
93 b = coords[ 3 ];
94 if (x >= l && x <= r && y >= t && y <= b) {
95 return m_Link;
96 }
97 break;
98 }
99 case CIRCLE:
100 {
101 int l, t, r;
102 double d;
103
104 l = coords[ 0 ];
105 t = coords[ 1 ];
106 r = coords[ 2 ];
107 d = sqrt( (double) (((x - l) * (x - l)) + ((y - t) * (y - t))) );
108 if (d < (double)r) {
109 return m_Link;
110 }
111 }
112 break;
113 case POLY:
114 {
115 if (coords.GetCount() >= 6) {
116 int intersects = 0;
117 int wherex = x;
118 int wherey = y;
119 int totalv = coords.GetCount() / 2;
120 int totalc = totalv * 2;
121 int xval = coords[totalc - 2];
122 int yval = coords[totalc - 1];
123 int end = totalc;
124 int pointer = 1;
125
126 if ((yval >= wherey) != (coords[pointer] >= wherey)) {
127 if ((xval >= wherex) == (coords[0] >= wherex)) {
128 intersects += (xval >= wherex) ? 1 : 0;
129 } else {
130 intersects += ((xval - (yval - wherey) *
131 (coords[0] - xval) /
132 (coords[pointer] - yval)) >= wherex) ? 1 : 0;
133 }
134 }
135
136 while (pointer < end) {
137 yval = coords[pointer];
138 pointer += 2;
139 if (yval >= wherey) {
140 while ((pointer < end) && (coords[pointer] >= wherey)) {
141 pointer += 2;
142 }
143 if (pointer >= end) {
144 break;
145 }
146 if ((coords[pointer - 3] >= wherex) ==
147 (coords[pointer - 1] >= wherex)) {
148 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
149 } else {
150 intersects +=
151 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
152 (coords[pointer - 1] - coords[pointer - 3]) /
153 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
154 }
155 } else {
156 while ((pointer < end) && (coords[pointer] < wherey)) {
157 pointer += 2;
158 }
159 if (pointer >= end) {
160 break;
161 }
162 if ((coords[pointer - 3] >= wherex) ==
163 (coords[pointer - 1] >= wherex)) {
164 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
165 } else {
166 intersects +=
167 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
168 (coords[pointer - 1] - coords[pointer - 3]) /
169 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
170 }
171 }
172 }
173 if ((intersects & 1) != 0) {
174 return m_Link;
175 }
176 }
177 }
178 break;
179 }
180 if (m_Next) {
181 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
182 return a->GetLink( x, y );
183 }
184 return wxEmptyString;
185 }
186
187
188
189
190
191
192
193
194 //--------------------------------------------------------------------------------
195 // wxHtmlImageMapCell
196 // 0-width, 0-height cell that represents map from imagemaps
197 // it is always placed before wxHtmlImageMapAreaCells
198 // It responds to Find(wxHTML_COND_ISIMAGEMAP)
199 //--------------------------------------------------------------------------------
200
201
202 class wxHtmlImageMapCell : public wxHtmlCell
203 {
204 public:
205 wxHtmlImageMapCell( wxString &name );
206 protected:
207 wxString m_Name;
208 public:
209 virtual wxString GetLink( int x = 0, int y = 0 ) const;
210 virtual const wxHtmlCell *Find( int cond, const void *param ) const;
211 };
212
213
214 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString &name )
215 {
216 m_Name = name ;
217 }
218
219 wxString wxHtmlImageMapCell::GetLink( int x, int y ) const
220 {
221 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
222 if (a)
223 return a->GetLink( x, y );
224 return wxHtmlCell::GetLink( x, y );
225 }
226
227 const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const
228 {
229 if (cond == wxHTML_COND_ISIMAGEMAP) {
230 if (m_Name == *((wxString*)(param)))
231 return this;
232 }
233 return wxHtmlCell::Find(cond, param);
234 }
235
236
237
238
239
240 //--------------------------------------------------------------------------------
241 // wxHtmlImageCell
242 // Image/bitmap
243 //--------------------------------------------------------------------------------
244
245 class wxHtmlImageCell : public wxHtmlCell
246 {
247 public:
248 wxBitmap *m_Image;
249 wxHtmlImageMapCell *m_ImageMap;
250 wxString m_MapName;
251
252 wxHtmlImageCell(wxFSFile *input, int w = -1, int h = -1, int align = wxHTML_ALIGN_BOTTOM, wxString mapname = wxEmptyString);
253 ~wxHtmlImageCell() {if (m_Image) delete m_Image; }
254 void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2);
255 virtual wxString GetLink( int x = 0, int y = 0 ) const;
256 };
257
258
259
260
261 //--------------------------------------------------------------------------------
262 // wxHtmlImageCell
263 //--------------------------------------------------------------------------------
264
265 wxHtmlImageCell::wxHtmlImageCell(wxFSFile *input, int w, int h, int align, wxString mapname) : wxHtmlCell()
266 {
267 wxImage *img;
268 int ww, hh;
269 wxInputStream *s = input -> GetStream();
270
271 img = new wxImage(*s, wxBITMAP_TYPE_ANY);
272
273 m_Image = NULL;
274 if (img && (img -> Ok())) {
275 ww = img -> GetWidth();
276 hh = img -> GetHeight();
277 if (w != -1) m_Width = w; else m_Width = ww;
278 if (h != -1) m_Height = h; else m_Height = hh;
279 if ((m_Width != ww) || (m_Height != hh)) {
280 wxImage img2 = img -> Scale(m_Width, m_Height);
281 m_Image = new wxBitmap(img2.ConvertToBitmap());
282 } else
283 m_Image = new wxBitmap(img -> ConvertToBitmap());
284 delete img;
285 }
286 switch (align) {
287 case wxHTML_ALIGN_TOP :
288 m_Descent = m_Height;
289 break;
290 case wxHTML_ALIGN_CENTER :
291 m_Descent = m_Height / 2;
292 break;
293 case wxHTML_ALIGN_BOTTOM :
294 default :
295 m_Descent = 0;
296 break;
297 }
298
299 m_ImageMap = NULL;
300 m_MapName = mapname;
301 SetCanLiveOnPagebreak(FALSE);
302 }
303
304
305
306 void wxHtmlImageCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
307 {
308 if (m_Image)
309 dc.DrawBitmap(*m_Image, x + m_PosX, y + m_PosY, TRUE);
310 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
311 }
312
313 wxString wxHtmlImageCell::GetLink( int x, int y ) const
314 {
315 if (m_MapName.IsEmpty())
316 return wxHtmlCell::GetLink( x, y );
317 if (!m_ImageMap) {
318 wxHtmlContainerCell *p, *op;
319 op = p = GetParent();
320 while (p) {
321 op = p;
322 p = p->GetParent();
323 }
324 p = op;
325 wxHtmlCell *cell = (wxHtmlCell*)p->Find( wxHTML_COND_ISIMAGEMAP, (const void*)(&m_MapName));
326 if (!cell) {
327 ((wxString&)m_MapName).Clear();
328 return wxHtmlCell::GetLink( x, y );
329 }
330 { // dirty hack, ask Joel why he fills m_ImageMap in this place
331 // THE problem is that we're in const method and we can't modify m_ImageMap
332 wxHtmlImageMapCell **cx = (wxHtmlImageMapCell**)(&m_ImageMap);
333 *cx = (wxHtmlImageMapCell*)cell;
334 }
335 }
336 return m_ImageMap->GetLink( x, y );
337 }
338
339
340
341 //--------------------------------------------------------------------------------
342 // tag handler
343 //--------------------------------------------------------------------------------
344
345 TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA")
346
347 TAG_HANDLER_PROC(tag)
348 {
349 if (tag.GetName() == "IMG") {
350 if (tag.HasParam("SRC")) {
351 int w = -1, h = -1;
352 int al;
353 wxFSFile *str;
354 wxString tmp = tag.GetParam("SRC");
355 wxString mn = wxEmptyString;
356
357 str = m_WParser -> GetFS() -> OpenFile(tmp);
358 if (tag.HasParam(wxT("WIDTH"))) tag.ScanParam(wxT("WIDTH"), wxT("%i"), &w);
359 if (tag.HasParam(wxT("HEIGHT"))) tag.ScanParam(wxT("HEIGHT"), wxT("%i"), &h);
360 al = wxHTML_ALIGN_BOTTOM;
361 if (tag.HasParam("ALIGN")) {
362 wxString alstr = tag.GetParam("ALIGN");
363 alstr.MakeUpper(); // for the case alignment was in ".."
364 if (alstr == "TEXTTOP") al = wxHTML_ALIGN_TOP;
365 else if ((alstr == "CENTER") || (alstr == "ABSCENTER")) al = wxHTML_ALIGN_CENTER;
366 }
367 if (tag.HasParam("USEMAP")) {
368 mn = tag.GetParam( "USEMAP" );
369 if (mn[ (unsigned int) 0 ] == '#') {
370 mn = mn.Mid( 1 );
371 }
372 }
373 wxHtmlImageCell *cel = NULL;
374 if (str) {
375 cel = new wxHtmlImageCell(str, w, h, al, mn);
376 cel -> SetLink(m_WParser -> GetLink());
377 m_WParser -> GetContainer() -> InsertCell(cel);
378 delete str;
379 }
380 }
381 }
382 if (tag.GetName() == "MAP") {
383 m_WParser->CloseContainer();
384 m_WParser->OpenContainer();
385 if (tag.HasParam("NAME")) {
386 wxString tmp = tag.GetParam("NAME");
387 wxHtmlImageMapCell *cel = new wxHtmlImageMapCell( tmp );
388 m_WParser->GetContainer()->InsertCell( cel );
389 }
390 ParseInner( tag );
391 m_WParser->CloseContainer();
392 m_WParser->OpenContainer();
393 }
394 if (tag.GetName() == "AREA") {
395 if (tag.HasParam("SHAPE")) {
396 wxString tmp = tag.GetParam("SHAPE");
397 wxString coords;
398 tmp.MakeUpper();
399 wxHtmlImageMapAreaCell *cel = NULL;
400 if (tag.HasParam("COORDS")) {
401 coords = tag.GetParam("COORDS");
402 }
403 if (tmp == "POLY") {
404 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY, coords );
405 } else if (tmp == "CIRCLE") {
406 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE, coords );
407 } else if (tmp == "RECT") {
408 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT, coords );
409 }
410 if (cel != NULL && tag.HasParam("HREF")) {
411 wxString tmp = tag.GetParam("HREF");
412 cel->SetLink( tmp );
413 }
414 if (cel != NULL) m_WParser->GetContainer()->InsertCell( cel );
415 }
416 }
417
418 return FALSE;
419 }
420
421 TAG_HANDLER_END(IMG)
422
423
424
425 TAGS_MODULE_BEGIN(Image)
426
427 TAGS_MODULE_ADD(IMG)
428
429 TAGS_MODULE_END(Image)
430
431
432 #endif