1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/html/m_image.cpp
3 // Purpose:     wxHtml module for displaying images
4 // Author:      Vaclav Slavik
5 // RCS-ID:      $Id: m_image.cpp 52997 2008-04-03 18:55:46Z VS $
6 // Copyright:   (c) 1999 Vaclav Slavik, Joel Lucsy
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 #include "wx/wxprec.h"
11 
12 #ifdef __BORLANDC__
13     #pragma hdrstop
14 #endif
15 
16 #if wxUSE_HTML && wxUSE_STREAMS
17 
18 #ifndef WXPRECOMP
19     #include "wx/dynarray.h"
20     #include "wx/dc.h"
21     #include "wx/scrolwin.h"
22     #include "wx/timer.h"
23     #include "wx/dcmemory.h"
24     #include "wx/log.h"
25     #include "wx/math.h"
26     #include "wx/image.h"
27 #endif
28 
29 #include "wx/html/forcelnk.h"
30 #include "wx/html/m_templ.h"
31 #include "wx/html/htmlwin.h"
32 
33 #include "wx/gifdecod.h"
34 #include "wx/artprov.h"
35 
36 #include <float.h>
37 
38 FORCE_LINK_ME(m_image)
39 
40 
41 
42 
43 WX_DECLARE_OBJARRAY(int, CoordArray);
44 #include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
45 WX_DEFINE_OBJARRAY(CoordArray)
46 
47 
48 // ---------------------------------------------------------------------------
49 // wxHtmlImageMapAreaCell
50 //                  0-width, 0-height cell that represents single area in
51 //                  imagemap (it's GetLink is called from wxHtmlImageCell's)
52 // ---------------------------------------------------------------------------
53 
54 class wxHtmlImageMapAreaCell : public wxHtmlCell
55 {
56     public:
57         enum celltype { CIRCLE, RECT, POLY };
58     protected:
59         CoordArray coords;
60         celltype type;
61         int radius;
62     public:
63         wxHtmlImageMapAreaCell( celltype t, wxString &coords, double pixel_scale = 1.0);
64         virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
Draw(wxDC & WXUNUSED (dc),int WXUNUSED (x),int WXUNUSED (y),int WXUNUSED (view_y1),int WXUNUSED (view_y2),wxHtmlRenderingInfo & WXUNUSED (info))65         void Draw(wxDC& WXUNUSED(dc),
66                   int WXUNUSED(x), int WXUNUSED(y),
67                   int WXUNUSED(view_y1), int WXUNUSED(view_y2),
68                   wxHtmlRenderingInfo& WXUNUSED(info)) {}
69 
70 
71     DECLARE_NO_COPY_CLASS(wxHtmlImageMapAreaCell)
72 };
73 
74 
75 
76 
77 
wxHtmlImageMapAreaCell(wxHtmlImageMapAreaCell::celltype t,wxString & incoords,double pixel_scale)78 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t, wxString &incoords, double pixel_scale )
79 {
80     int i;
81     wxString x = incoords, y;
82 
83     type = t;
84     while ((i = x.Find( ',' )) != wxNOT_FOUND)
85     {
86         coords.Add( (int)(pixel_scale * (double)wxAtoi( x.Left( i ).c_str())) );
87         x = x.Mid( i + 1 );
88     }
89     coords.Add( (int)(pixel_scale * (double)wxAtoi( x.c_str())) );
90 }
91 
GetLink(int x,int y) const92 wxHtmlLinkInfo *wxHtmlImageMapAreaCell::GetLink( int x, int y ) const
93 {
94     switch (type)
95     {
96         case RECT:
97             {
98                 int l, t, r, b;
99 
100                 l = coords[ 0 ];
101                 t = coords[ 1 ];
102                 r = coords[ 2 ];
103                 b = coords[ 3 ];
104                 if (x >= l && x <= r && y >= t && y <= b)
105                 {
106                     return m_Link;
107                 }
108                 break;
109             }
110         case CIRCLE:
111             {
112                 int l, t, r;
113                 double  d;
114 
115                 l = coords[ 0 ];
116                 t = coords[ 1 ];
117                 r = coords[ 2 ];
118                 d = sqrt( (double) (((x - l) * (x - l)) + ((y - t) * (y - t))) );
119                 if (d < (double)r)
120                 {
121                     return m_Link;
122                 }
123             }
124             break;
125         case POLY:
126             {
127                 if (coords.GetCount() >= 6)
128                 {
129                     int intersects = 0;
130                     int wherex = x;
131                     int wherey = y;
132                     int totalv = coords.GetCount() / 2;
133                     int totalc = totalv * 2;
134                     int xval = coords[totalc - 2];
135                     int yval = coords[totalc - 1];
136                     int end = totalc;
137                     int pointer = 1;
138 
139                     if ((yval >= wherey) != (coords[pointer] >= wherey))
140                     {
141                         if ((xval >= wherex) == (coords[0] >= wherex))
142                         {
143                             intersects += (xval >= wherex) ? 1 : 0;
144                         }
145                         else
146                         {
147                             intersects += ((xval - (yval - wherey) *
148                                             (coords[0] - xval) /
149                                             (coords[pointer] - yval)) >= wherex) ? 1 : 0;
150                         }
151                     }
152 
153                     while (pointer < end)
154                     {
155                         yval = coords[pointer];
156                         pointer += 2;
157                         if (yval >= wherey)
158                         {
159                             while ((pointer < end) && (coords[pointer] >= wherey))
160                             {
161                                 pointer += 2;
162                             }
163                             if (pointer >= end)
164                             {
165                                 break;
166                             }
167                             if ((coords[pointer - 3] >= wherex) ==
168                                     (coords[pointer - 1] >= wherex)) {
169                                 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
170                             }
171                             else
172                             {
173                                 intersects +=
174                                     ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
175                                       (coords[pointer - 1] - coords[pointer - 3]) /
176                                       (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
177                             }
178                         }
179                         else
180                         {
181                             while ((pointer < end) && (coords[pointer] < wherey))
182                             {
183                                 pointer += 2;
184                             }
185                             if (pointer >= end)
186                             {
187                                 break;
188                             }
189                             if ((coords[pointer - 3] >= wherex) ==
190                                     (coords[pointer - 1] >= wherex))
191                             {
192                                 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
193                             }
194                             else
195                             {
196                                 intersects +=
197                                     ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
198                                       (coords[pointer - 1] - coords[pointer - 3]) /
199                                       (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
200                             }
201                         }
202                     }
203                     if ((intersects & 1) != 0)
204                     {
205                         return m_Link;
206                     }
207                 }
208             }
209             break;
210     }
211 
212     if (m_Next)
213     {
214         wxHtmlImageMapAreaCell  *a = (wxHtmlImageMapAreaCell*)m_Next;
215         return a->GetLink( x, y );
216     }
217     return NULL;
218 }
219 
220 
221 
222 
223 
224 
225 
226 
227 //--------------------------------------------------------------------------------
228 // wxHtmlImageMapCell
229 //                  0-width, 0-height cell that represents map from imagemaps
230 //                  it is always placed before wxHtmlImageMapAreaCells
231 //                  It responds to Find(wxHTML_COND_ISIMAGEMAP)
232 //--------------------------------------------------------------------------------
233 
234 
235 class wxHtmlImageMapCell : public wxHtmlCell
236 {
237     public:
238         wxHtmlImageMapCell( wxString &name );
239     protected:
240         wxString m_Name;
241     public:
242         virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
243         virtual const wxHtmlCell *Find( int cond, const void *param ) const;
Draw(wxDC & WXUNUSED (dc),int WXUNUSED (x),int WXUNUSED (y),int WXUNUSED (view_y1),int WXUNUSED (view_y2),wxHtmlRenderingInfo & WXUNUSED (info))244         void Draw(wxDC& WXUNUSED(dc),
245                   int WXUNUSED(x), int WXUNUSED(y),
246                   int WXUNUSED(view_y1), int WXUNUSED(view_y2),
247                   wxHtmlRenderingInfo& WXUNUSED(info)) {}
248 
249     DECLARE_NO_COPY_CLASS(wxHtmlImageMapCell)
250 };
251 
252 
wxHtmlImageMapCell(wxString & name)253 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString &name )
254 {
255     m_Name = name ;
256 }
257 
GetLink(int x,int y) const258 wxHtmlLinkInfo *wxHtmlImageMapCell::GetLink( int x, int y ) const
259 {
260     wxHtmlImageMapAreaCell  *a = (wxHtmlImageMapAreaCell*)m_Next;
261     if (a)
262         return a->GetLink( x, y );
263     return wxHtmlCell::GetLink( x, y );
264 }
265 
Find(int cond,const void * param) const266 const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const
267 {
268     if (cond == wxHTML_COND_ISIMAGEMAP)
269     {
270         if (m_Name == *((wxString*)(param)))
271             return this;
272     }
273     return wxHtmlCell::Find(cond, param);
274 }
275 
276 
277 
278 
279 
280 //--------------------------------------------------------------------------------
281 // wxHtmlImageCell
282 //                  Image/bitmap
283 //--------------------------------------------------------------------------------
284 
285 class wxHtmlImageCell : public wxHtmlCell
286 {
287 public:
288     wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
289                     wxFSFile *input, int w = wxDefaultCoord, int h = wxDefaultCoord,
290                     double scale = 1.0, int align = wxHTML_ALIGN_BOTTOM,
291                     const wxString& mapname = wxEmptyString);
292     virtual ~wxHtmlImageCell();
293     void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2,
294               wxHtmlRenderingInfo& info);
295     virtual wxHtmlLinkInfo *GetLink(int x = 0, int y = 0) const;
296 
297     void SetImage(const wxImage& img);
298 #if wxUSE_GIF && wxUSE_TIMER
299     void AdvanceAnimation(wxTimer *timer);
300     virtual void Layout(int w);
301 #endif
302 
303 private:
304     wxBitmap           *m_bitmap;
305     int                 m_bmpW, m_bmpH;
306     bool                m_showFrame:1;
307     wxHtmlWindowInterface *m_windowIface;
308 #if wxUSE_GIF && wxUSE_TIMER
309     wxGIFDecoder       *m_gifDecoder;
310     wxTimer            *m_gifTimer;
311     int                 m_physX, m_physY;
312     size_t              m_nCurrFrame;
313 #endif
314     double              m_scale;
315     wxHtmlImageMapCell *m_imageMap;
316     wxString            m_mapName;
317 
318     DECLARE_NO_COPY_CLASS(wxHtmlImageCell)
319 };
320 
321 #if wxUSE_GIF && wxUSE_TIMER
322 class wxGIFTimer : public wxTimer
323 {
324     public:
wxGIFTimer(wxHtmlImageCell * cell)325         wxGIFTimer(wxHtmlImageCell *cell) : m_cell(cell) {}
Notify()326         virtual void Notify()
327         {
328             m_cell->AdvanceAnimation(this);
329         }
330 
331     private:
332         wxHtmlImageCell *m_cell;
333 
334     DECLARE_NO_COPY_CLASS(wxGIFTimer)
335 };
336 #endif
337 
338 
339 //----------------------------------------------------------------------------
340 // wxHtmlImageCell
341 //----------------------------------------------------------------------------
342 
343 
wxHtmlImageCell(wxHtmlWindowInterface * windowIface,wxFSFile * input,int w,int h,double scale,int align,const wxString & mapname)344 wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
345                                  wxFSFile *input,
346                                  int w, int h, double scale, int align,
347                                  const wxString& mapname) : wxHtmlCell()
348 {
349     m_windowIface = windowIface;
350     m_scale = scale;
351     m_showFrame = false;
352     m_bitmap = NULL;
353     m_bmpW = w;
354     m_bmpH = h;
355     m_imageMap = NULL;
356     m_mapName = mapname;
357     SetCanLiveOnPagebreak(false);
358 #if wxUSE_GIF && wxUSE_TIMER
359     m_gifDecoder = NULL;
360     m_gifTimer = NULL;
361     m_physX = m_physY = wxDefaultCoord;
362     m_nCurrFrame = 0;
363 #endif
364 
365     if ( m_bmpW && m_bmpH )
366     {
367         if ( input )
368         {
369             wxInputStream *s = input->GetStream();
370 
371             if ( s )
372             {
373 #if wxUSE_GIF && wxUSE_TIMER
374                 bool readImg = true;
375                 if ( m_windowIface &&
376                      (input->GetLocation().Matches(wxT("*.gif")) ||
377                       input->GetLocation().Matches(wxT("*.GIF"))) )
378                 {
379                     m_gifDecoder = new wxGIFDecoder();
380                     if ( m_gifDecoder->LoadGIF(*s) == wxGIF_OK )
381                     {
382                         wxImage img;
383                         if ( m_gifDecoder->ConvertToImage(0, &img) )
384                             SetImage(img);
385 
386                         readImg = false;
387 
388                         if ( m_gifDecoder->IsAnimation() )
389                         {
390                             m_gifTimer = new wxGIFTimer(this);
391                             long delay = m_gifDecoder->GetDelay(0);
392                             if ( delay == 0 )
393                                 delay = 1;
394                             m_gifTimer->Start(delay, true);
395                         }
396                         else
397                         {
398                             wxDELETE(m_gifDecoder);
399                         }
400                     }
401                     else
402                     {
403                         wxDELETE(m_gifDecoder);
404                     }
405                 }
406 
407                 if ( readImg )
408 #endif // wxUSE_GIF && wxUSE_TIMER
409                 {
410                     wxImage image(*s, wxBITMAP_TYPE_ANY);
411                     if ( image.Ok() )
412                         SetImage(image);
413                 }
414             }
415         }
416         else // input==NULL, use "broken image" bitmap
417         {
418             if ( m_bmpW == wxDefaultCoord && m_bmpH == wxDefaultCoord )
419             {
420                 m_bmpW = 29;
421                 m_bmpH = 31;
422             }
423             else
424             {
425                 m_showFrame = true;
426                 if ( m_bmpW == wxDefaultCoord ) m_bmpW = 31;
427                 if ( m_bmpH == wxDefaultCoord ) m_bmpH = 33;
428             }
429             m_bitmap =
430                 new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
431         }
432     }
433     //else: ignore the 0-sized images used sometimes on the Web pages
434 
435     m_Width = (int)(scale * (double)m_bmpW);
436     m_Height = (int)(scale * (double)m_bmpH);
437 
438     switch (align)
439     {
440         case wxHTML_ALIGN_TOP :
441             m_Descent = m_Height;
442             break;
443         case wxHTML_ALIGN_CENTER :
444             m_Descent = m_Height / 2;
445             break;
446         case wxHTML_ALIGN_BOTTOM :
447         default :
448             m_Descent = 0;
449             break;
450     }
451  }
452 
SetImage(const wxImage & img)453 void wxHtmlImageCell::SetImage(const wxImage& img)
454 {
455 #if !defined(__WXMSW__) || wxUSE_WXDIB
456     if ( img.Ok() )
457     {
458         delete m_bitmap;
459 
460         int ww, hh;
461         ww = img.GetWidth();
462         hh = img.GetHeight();
463 
464         if ( m_bmpW == wxDefaultCoord )
465             m_bmpW = ww;
466         if ( m_bmpH == wxDefaultCoord )
467             m_bmpH = hh;
468 
469         // Only scale the bitmap at the rendering stage,
470         // so we don't lose quality twice
471 /*
472         if ((m_bmpW != ww) || (m_bmpH != hh))
473         {
474             wxImage img2 = img.Scale(m_bmpW, m_bmpH);
475             m_bitmap = new wxBitmap(img2);
476         }
477         else
478 */
479             m_bitmap = new wxBitmap(img);
480     }
481 #endif
482 }
483 
484 #if wxUSE_GIF && wxUSE_TIMER
AdvanceAnimation(wxTimer * timer)485 void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer)
486 {
487     wxImage img;
488 
489     // advance current frame
490     m_nCurrFrame++;
491     if (m_nCurrFrame == m_gifDecoder->GetFrameCount())
492         m_nCurrFrame = 0;
493 
494     if ( m_physX == wxDefaultCoord )
495     {
496         m_physX = m_physY = 0;
497         for (wxHtmlCell *cell = this; cell; cell = cell->GetParent())
498         {
499             m_physX += cell->GetPosX();
500             m_physY += cell->GetPosY();
501         }
502     }
503 
504     wxWindow *win = m_windowIface->GetHTMLWindow();
505     wxPoint pos =
506         m_windowIface->HTMLCoordsToWindow(this, wxPoint(m_physX, m_physY));
507     wxRect rect(pos, wxSize(m_Width, m_Height));
508 
509     if ( win->GetClientRect().Intersects(rect) &&
510          m_gifDecoder->ConvertToImage(m_nCurrFrame, &img) )
511     {
512 #if !defined(__WXMSW__) || wxUSE_WXDIB
513         if ( m_gifDecoder->GetFrameSize(m_nCurrFrame) != wxSize(m_Width, m_Height) ||
514              m_gifDecoder->GetFramePosition(m_nCurrFrame) != wxPoint(0, 0) )
515         {
516             wxBitmap bmp(img);
517             wxMemoryDC dc;
518             dc.SelectObject(*m_bitmap);
519             dc.DrawBitmap(bmp, m_gifDecoder->GetFramePosition(m_nCurrFrame),
520                           true /* use mask */);
521         }
522         else
523 #endif
524             SetImage(img);
525         win->Refresh(img.HasMask(), &rect);
526     }
527 
528     long delay = m_gifDecoder->GetDelay(m_nCurrFrame);
529     if ( delay == 0 )
530         delay = 1;
531     timer->Start(delay, true);
532 }
533 
Layout(int w)534 void wxHtmlImageCell::Layout(int w)
535 {
536     wxHtmlCell::Layout(w);
537     m_physX = m_physY = wxDefaultCoord;
538 }
539 
540 #endif
541 
~wxHtmlImageCell()542 wxHtmlImageCell::~wxHtmlImageCell()
543 {
544     delete m_bitmap;
545 #if wxUSE_GIF && wxUSE_TIMER
546     delete m_gifTimer;
547     delete m_gifDecoder;
548 #endif
549 }
550 
551 
Draw(wxDC & dc,int x,int y,int WXUNUSED (view_y1),int WXUNUSED (view_y2),wxHtmlRenderingInfo & WXUNUSED (info))552 void wxHtmlImageCell::Draw(wxDC& dc, int x, int y,
553                            int WXUNUSED(view_y1), int WXUNUSED(view_y2),
554                            wxHtmlRenderingInfo& WXUNUSED(info))
555 {
556     if ( m_showFrame )
557     {
558         dc.SetBrush(*wxTRANSPARENT_BRUSH);
559         dc.SetPen(*wxBLACK_PEN);
560         dc.DrawRectangle(x + m_PosX, y + m_PosY, m_Width, m_Height);
561         x++, y++;
562     }
563     if ( m_bitmap )
564     {
565         // We add in the scaling from the desired bitmap width
566         // and height, so we only do the scaling once.
567         double imageScaleX = 1.0;
568         double imageScaleY = 1.0;
569         if (m_bmpW != m_bitmap->GetWidth())
570             imageScaleX = (double) m_bmpW / (double) m_bitmap->GetWidth();
571         if (m_bmpH != m_bitmap->GetHeight())
572             imageScaleY = (double) m_bmpH / (double) m_bitmap->GetHeight();
573 
574         double us_x, us_y;
575         dc.GetUserScale(&us_x, &us_y);
576         dc.SetUserScale(us_x * m_scale * imageScaleX, us_y * m_scale * imageScaleY);
577 
578         dc.DrawBitmap(*m_bitmap, (int) ((x + m_PosX) / (m_scale*imageScaleX)),
579                                  (int) ((y + m_PosY) / (m_scale*imageScaleY)), true);
580         dc.SetUserScale(us_x, us_y);
581     }
582 }
583 
GetLink(int x,int y) const584 wxHtmlLinkInfo *wxHtmlImageCell::GetLink( int x, int y ) const
585 {
586     if (m_mapName.empty())
587         return wxHtmlCell::GetLink( x, y );
588     if (!m_imageMap)
589     {
590         wxHtmlContainerCell *p, *op;
591         op = p = GetParent();
592         while (p)
593         {
594             op = p;
595             p = p->GetParent();
596         }
597         p = op;
598         wxHtmlCell *cell = (wxHtmlCell*)p->Find(wxHTML_COND_ISIMAGEMAP,
599                                                 (const void*)(&m_mapName));
600         if (!cell)
601         {
602             ((wxString&)m_mapName).Clear();
603             return wxHtmlCell::GetLink( x, y );
604         }
605         {   // dirty hack, ask Joel why he fills m_ImageMap in this place
606             // THE problem is that we're in const method and we can't modify m_ImageMap
607             wxHtmlImageMapCell **cx = (wxHtmlImageMapCell**)(&m_imageMap);
608             *cx = (wxHtmlImageMapCell*)cell;
609         }
610     }
611     return m_imageMap->GetLink(x, y);
612 }
613 
614 
615 
616 //--------------------------------------------------------------------------------
617 // tag handler
618 //--------------------------------------------------------------------------------
619 
620 TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA")
TAG_HANDLER_CONSTR(IMG)621     TAG_HANDLER_CONSTR(IMG) { }
622 
TAG_HANDLER_PROC(tag)623     TAG_HANDLER_PROC(tag)
624     {
625         if (tag.GetName() == wxT("IMG"))
626         {
627             if (tag.HasParam(wxT("SRC")))
628             {
629                 int w = wxDefaultCoord, h = wxDefaultCoord;
630                 int al;
631                 wxFSFile *str;
632                 wxString tmp = tag.GetParam(wxT("SRC"));
633                 wxString mn = wxEmptyString;
634 
635                 str = m_WParser->OpenURL(wxHTML_URL_IMAGE, tmp);
636 
637                 if (tag.HasParam(wxT("WIDTH")))
638                     tag.GetParamAsInt(wxT("WIDTH"), &w);
639                 if (tag.HasParam(wxT("HEIGHT")))
640                     tag.GetParamAsInt(wxT("HEIGHT"), &h);
641                 al = wxHTML_ALIGN_BOTTOM;
642                 if (tag.HasParam(wxT("ALIGN")))
643                 {
644                     wxString alstr = tag.GetParam(wxT("ALIGN"));
645                     alstr.MakeUpper();  // for the case alignment was in ".."
646                     if (alstr == wxT("TEXTTOP"))
647                         al = wxHTML_ALIGN_TOP;
648                     else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
649                         al = wxHTML_ALIGN_CENTER;
650                 }
651                 if (tag.HasParam(wxT("USEMAP")))
652                 {
653                     mn = tag.GetParam( wxT("USEMAP") );
654                     if (mn.GetChar(0) == wxT('#'))
655                     {
656                         mn = mn.Mid( 1 );
657                     }
658                 }
659                 wxHtmlImageCell *cel = new wxHtmlImageCell(
660                                           m_WParser->GetWindowInterface(),
661                                           str, w, h,
662                                           m_WParser->GetPixelScale(),
663                                           al, mn);
664                 m_WParser->ApplyStateToCell(cel);
665                 cel->SetId(tag.GetParam(wxT("id"))); // may be empty
666                 m_WParser->GetContainer()->InsertCell(cel);
667                 if (str)
668                     delete str;
669             }
670         }
671         if (tag.GetName() == wxT("MAP"))
672         {
673             m_WParser->CloseContainer();
674             m_WParser->OpenContainer();
675             if (tag.HasParam(wxT("NAME")))
676             {
677                 wxString tmp = tag.GetParam(wxT("NAME"));
678                 wxHtmlImageMapCell *cel = new wxHtmlImageMapCell( tmp );
679                 m_WParser->GetContainer()->InsertCell( cel );
680             }
681             ParseInner( tag );
682             m_WParser->CloseContainer();
683             m_WParser->OpenContainer();
684         }
685         if (tag.GetName() == wxT("AREA"))
686         {
687             if (tag.HasParam(wxT("SHAPE")))
688             {
689                 wxString tmp = tag.GetParam(wxT("SHAPE"));
690                 wxString coords = wxEmptyString;
691                 tmp.MakeUpper();
692                 wxHtmlImageMapAreaCell *cel = NULL;
693                 if (tag.HasParam(wxT("COORDS")))
694                 {
695                     coords = tag.GetParam(wxT("COORDS"));
696                 }
697                 if (tmp == wxT("POLY"))
698                 {
699                     cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY, coords, m_WParser->GetPixelScale() );
700                 }
701                 else if (tmp == wxT("CIRCLE"))
702                 {
703                     cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE, coords, m_WParser->GetPixelScale() );
704                 }
705                 else if (tmp == wxT("RECT"))
706                 {
707                     cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT, coords, m_WParser->GetPixelScale() );
708                 }
709                 if (cel != NULL && tag.HasParam(wxT("HREF")))
710                 {
711                     wxString target;
712                     if (tag.HasParam(wxT("TARGET")))
713                         target = tag.GetParam(wxT("TARGET"));
714                     cel->SetLink(wxHtmlLinkInfo(tag.GetParam(wxT("HREF")), target));
715                 }
716                 if (cel != NULL)
717                     m_WParser->GetContainer()->InsertCell( cel );
718             }
719         }
720 
721         return false;
722     }
723 
724 TAG_HANDLER_END(IMG)
725 
726 
727 
728 TAGS_MODULE_BEGIN(Image)
729 
730     TAGS_MODULE_ADD(IMG)
731 
732 TAGS_MODULE_END(Image)
733 
734 
735 #endif
736