wxHTML src code indentation now conforms (more) to wxWin coding style
[wxWidgets.git] / src / html / m_image.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: m_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 && wxUSE_STREAMS
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(m_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, double pixel_scale = 1.0);
63 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
64 };
65
66
67
68
69
70 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t, wxString &incoords, double pixel_scale )
71 {
72 int i;
73 wxString x = incoords, y;
74
75 type = t;
76 while ((i = x.Find( ',' )) != -1)
77 {
78 coords.Add( (int)(pixel_scale * (double)wxAtoi( x.Left( i ).c_str())) );
79 x = x.Mid( i + 1 );
80 }
81 coords.Add( (int)(pixel_scale * (double)wxAtoi( x.c_str())) );
82 }
83
84 wxHtmlLinkInfo *wxHtmlImageMapAreaCell::GetLink( int x, int y ) const
85 {
86 switch (type)
87 {
88 case RECT:
89 {
90 int l, t, r, b;
91
92 l = coords[ 0 ];
93 t = coords[ 1 ];
94 r = coords[ 2 ];
95 b = coords[ 3 ];
96 if (x >= l && x <= r && y >= t && y <= b)
97 {
98 return m_Link;
99 }
100 break;
101 }
102 case CIRCLE:
103 {
104 int l, t, r;
105 double d;
106
107 l = coords[ 0 ];
108 t = coords[ 1 ];
109 r = coords[ 2 ];
110 d = sqrt( (double) (((x - l) * (x - l)) + ((y - t) * (y - t))) );
111 if (d < (double)r)
112 {
113 return m_Link;
114 }
115 }
116 break;
117 case POLY:
118 {
119 if (coords.GetCount() >= 6)
120 {
121 int intersects = 0;
122 int wherex = x;
123 int wherey = y;
124 int totalv = coords.GetCount() / 2;
125 int totalc = totalv * 2;
126 int xval = coords[totalc - 2];
127 int yval = coords[totalc - 1];
128 int end = totalc;
129 int pointer = 1;
130
131 if ((yval >= wherey) != (coords[pointer] >= wherey))
132 {
133 if ((xval >= wherex) == (coords[0] >= wherex))
134 {
135 intersects += (xval >= wherex) ? 1 : 0;
136 }
137 else
138 {
139 intersects += ((xval - (yval - wherey) *
140 (coords[0] - xval) /
141 (coords[pointer] - yval)) >= wherex) ? 1 : 0;
142 }
143 }
144
145 while (pointer < end)
146 {
147 yval = coords[pointer];
148 pointer += 2;
149 if (yval >= wherey)
150 {
151 while ((pointer < end) && (coords[pointer] >= wherey))
152 {
153 pointer += 2;
154 }
155 if (pointer >= end)
156 {
157 break;
158 }
159 if ((coords[pointer - 3] >= wherex) ==
160 (coords[pointer - 1] >= wherex)) {
161 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
162 }
163 else
164 {
165 intersects +=
166 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
167 (coords[pointer - 1] - coords[pointer - 3]) /
168 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
169 }
170 }
171 else
172 {
173 while ((pointer < end) && (coords[pointer] < wherey))
174 {
175 pointer += 2;
176 }
177 if (pointer >= end)
178 {
179 break;
180 }
181 if ((coords[pointer - 3] >= wherex) ==
182 (coords[pointer - 1] >= wherex))
183 {
184 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
185 }
186 else
187 {
188 intersects +=
189 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
190 (coords[pointer - 1] - coords[pointer - 3]) /
191 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
192 }
193 }
194 }
195 if ((intersects & 1) != 0)
196 {
197 return m_Link;
198 }
199 }
200 }
201 break;
202 }
203
204 if (m_Next)
205 {
206 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
207 return a->GetLink( x, y );
208 }
209 return NULL;
210 }
211
212
213
214
215
216
217
218
219 //--------------------------------------------------------------------------------
220 // wxHtmlImageMapCell
221 // 0-width, 0-height cell that represents map from imagemaps
222 // it is always placed before wxHtmlImageMapAreaCells
223 // It responds to Find(wxHTML_COND_ISIMAGEMAP)
224 //--------------------------------------------------------------------------------
225
226
227 class wxHtmlImageMapCell : public wxHtmlCell
228 {
229 public:
230 wxHtmlImageMapCell( wxString &name );
231 protected:
232 wxString m_Name;
233 public:
234 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
235 virtual const wxHtmlCell *Find( int cond, const void *param ) const;
236 };
237
238
239 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString &name )
240 {
241 m_Name = name ;
242 }
243
244 wxHtmlLinkInfo *wxHtmlImageMapCell::GetLink( int x, int y ) const
245 {
246 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
247 if (a)
248 return a->GetLink( x, y );
249 return wxHtmlCell::GetLink( x, y );
250 }
251
252 const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const
253 {
254 if (cond == wxHTML_COND_ISIMAGEMAP)
255 {
256 if (m_Name == *((wxString*)(param)))
257 return this;
258 }
259 return wxHtmlCell::Find(cond, param);
260 }
261
262
263
264
265
266 //--------------------------------------------------------------------------------
267 // wxHtmlImageCell
268 // Image/bitmap
269 //--------------------------------------------------------------------------------
270
271 class wxHtmlImageCell : public wxHtmlCell
272 {
273 public:
274 wxBitmap *m_Image;
275 wxHtmlImageMapCell *m_ImageMap;
276 wxString m_MapName;
277
278 wxHtmlImageCell(wxFSFile *input, int w = -1, int h = -1, double scale = 1.0, int align = wxHTML_ALIGN_BOTTOM, wxString mapname = wxEmptyString);
279 ~wxHtmlImageCell() {if (m_Image) delete m_Image; }
280 void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2);
281 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
282 };
283
284
285
286
287 //--------------------------------------------------------------------------------
288 // wxHtmlImageCell
289 //--------------------------------------------------------------------------------
290
291 wxHtmlImageCell::wxHtmlImageCell(wxFSFile *input, int w, int h, double scale, int align, wxString mapname) : wxHtmlCell()
292 {
293 wxImage *img;
294 int ww, hh;
295 wxInputStream *s = input->GetStream();
296
297 img = new wxImage(*s, wxBITMAP_TYPE_ANY);
298
299 m_Image = NULL;
300 if (img && (img->Ok()))
301 {
302 ww = img->GetWidth();
303 hh = img->GetHeight();
304 if (w != -1) m_Width = w; else m_Width = ww;
305 if (h != -1) m_Height = h; else m_Height = hh;
306
307 m_Width = (int)(scale * (double)m_Width);
308 m_Height = (int)(scale * (double)m_Height);
309
310 if ((m_Width != ww) || (m_Height != hh))
311 {
312 wxImage img2 = img->Scale(m_Width, m_Height);
313 m_Image = new wxBitmap(img2.ConvertToBitmap());
314 }
315 else
316 m_Image = new wxBitmap(img->ConvertToBitmap());
317 delete img;
318 }
319 switch (align)
320 {
321 case wxHTML_ALIGN_TOP :
322 m_Descent = m_Height;
323 break;
324 case wxHTML_ALIGN_CENTER :
325 m_Descent = m_Height / 2;
326 break;
327 case wxHTML_ALIGN_BOTTOM :
328 default :
329 m_Descent = 0;
330 break;
331 }
332
333 m_ImageMap = NULL;
334 m_MapName = mapname;
335 SetCanLiveOnPagebreak(FALSE);
336 }
337
338
339
340 void wxHtmlImageCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2)
341 {
342 if (m_Image)
343 // dc.DrawBitmap(*m_Image, x + m_PosX, y + m_PosY, (m_Image->GetMask() != (wxMask*) 0));
344 dc.DrawBitmap(*m_Image, x + m_PosX, y + m_PosY, TRUE);
345 wxHtmlCell::Draw(dc, x, y, view_y1, view_y2);
346 }
347
348 wxHtmlLinkInfo *wxHtmlImageCell::GetLink( int x, int y ) const
349 {
350 if (m_MapName.IsEmpty())
351 return wxHtmlCell::GetLink( x, y );
352 if (!m_ImageMap)
353 {
354 wxHtmlContainerCell *p, *op;
355 op = p = GetParent();
356 while (p)
357 {
358 op = p;
359 p = p->GetParent();
360 }
361 p = op;
362 wxHtmlCell *cell = (wxHtmlCell*)p->Find( wxHTML_COND_ISIMAGEMAP, (const void*)(&m_MapName));
363 if (!cell)
364 {
365 ((wxString&)m_MapName).Clear();
366 return wxHtmlCell::GetLink( x, y );
367 }
368 { // dirty hack, ask Joel why he fills m_ImageMap in this place
369 // THE problem is that we're in const method and we can't modify m_ImageMap
370 wxHtmlImageMapCell **cx = (wxHtmlImageMapCell**)(&m_ImageMap);
371 *cx = (wxHtmlImageMapCell*)cell;
372 }
373 }
374 return m_ImageMap->GetLink( x, y );
375 }
376
377
378
379 //--------------------------------------------------------------------------------
380 // tag handler
381 //--------------------------------------------------------------------------------
382
383 TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA")
384
385 TAG_HANDLER_PROC(tag)
386 {
387 if (tag.GetName() == wxT("IMG"))
388 {
389 if (tag.HasParam(wxT("SRC")))
390 {
391 int w = -1, h = -1;
392 int al;
393 wxFSFile *str;
394 wxString tmp = tag.GetParam(wxT("SRC"));
395 wxString mn = wxEmptyString;
396
397 str = m_WParser->GetFS()->OpenFile(tmp);
398 if (tag.HasParam(wxT("WIDTH"))) tag.ScanParam(wxT("WIDTH"), wxT("%i"), &w);
399 if (tag.HasParam(wxT("HEIGHT"))) tag.ScanParam(wxT("HEIGHT"), wxT("%i"), &h);
400 al = wxHTML_ALIGN_BOTTOM;
401 if (tag.HasParam(wxT("ALIGN")))
402 {
403 wxString alstr = tag.GetParam(wxT("ALIGN"));
404 alstr.MakeUpper(); // for the case alignment was in ".."
405 if (alstr == wxT("TEXTTOP")) al = wxHTML_ALIGN_TOP;
406 else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER"))) al = wxHTML_ALIGN_CENTER;
407 }
408 if (tag.HasParam(wxT("USEMAP")))
409 {
410 mn = tag.GetParam( wxT("USEMAP") );
411 if (mn[ (unsigned int) 0 ] == wxT('#'))
412 {
413 mn = mn.Mid( 1 );
414 }
415 }
416 wxHtmlImageCell *cel = NULL;
417 if (str)
418 {
419 cel = new wxHtmlImageCell(str, w, h, m_WParser->GetPixelScale(), al, mn);
420 cel->SetLink(m_WParser->GetLink());
421 m_WParser->GetContainer()->InsertCell(cel);
422 delete str;
423 }
424 }
425 }
426 if (tag.GetName() == wxT("MAP"))
427 {
428 m_WParser->CloseContainer();
429 m_WParser->OpenContainer();
430 if (tag.HasParam(wxT("NAME")))
431 {
432 wxString tmp = tag.GetParam(wxT("NAME"));
433 wxHtmlImageMapCell *cel = new wxHtmlImageMapCell( tmp );
434 m_WParser->GetContainer()->InsertCell( cel );
435 }
436 ParseInner( tag );
437 m_WParser->CloseContainer();
438 m_WParser->OpenContainer();
439 }
440 if (tag.GetName() == wxT("AREA"))
441 {
442 if (tag.HasParam(wxT("SHAPE")))
443 {
444 wxString tmp = tag.GetParam(wxT("SHAPE"));
445 wxString coords = wxEmptyString;
446 tmp.MakeUpper();
447 wxHtmlImageMapAreaCell *cel = NULL;
448 if (tag.HasParam(wxT("COORDS")))
449 {
450 coords = tag.GetParam(wxT("COORDS"));
451 }
452 if (tmp == wxT("POLY"))
453 {
454 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY, coords, m_WParser->GetPixelScale() );
455 }
456 else if (tmp == wxT("CIRCLE"))
457 {
458 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE, coords, m_WParser->GetPixelScale() );
459 }
460 else if (tmp == wxT("RECT"))
461 {
462 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT, coords, m_WParser->GetPixelScale() );
463 }
464 if (cel != NULL && tag.HasParam(wxT("HREF")))
465 {
466 wxString tmp = tag.GetParam(wxT("HREF"));
467 wxString target = wxEmptyString;
468 if (tag.HasParam(wxT("TARGET"))) target = tag.GetParam(wxT("TARGET"));
469 cel->SetLink( wxHtmlLinkInfo(tmp, target));
470 }
471 if (cel != NULL) m_WParser->GetContainer()->InsertCell( cel );
472 }
473 }
474
475 return FALSE;
476 }
477
478 TAG_HANDLER_END(IMG)
479
480
481
482 TAGS_MODULE_BEGIN(Image)
483
484 TAGS_MODULE_ADD(IMG)
485
486 TAGS_MODULE_END(Image)
487
488
489 #endif