]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_image.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxHtml module for displaying images 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik, Joel Lucsy 
   7 // Licence:     wxWindows Licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation 
  14 #include "wx/wxprec.h" 
  17 #if wxUSE_HTML && wxUSE_STREAMS 
  25     #include "wx/scrolwin.h" 
  27     #include "wx/dcmemory.h" 
  30 #include "wx/html/forcelnk.h" 
  31 #include "wx/html/m_templ.h" 
  32 #include "wx/html/htmlwin.h" 
  35 #include "wx/gifdecod.h" 
  36 #include "wx/dynarray.h" 
  38 #include "wx/artprov.h" 
  43 FORCE_LINK_ME(m_image
) 
  48 WX_DECLARE_OBJARRAY(int, CoordArray
); 
  49 #include "wx/arrimpl.cpp" // this is a magic incantation which must be done! 
  50 WX_DEFINE_OBJARRAY(CoordArray
); 
  53 // --------------------------------------------------------------------------- 
  54 // wxHtmlImageMapAreaCell 
  55 //                  0-width, 0-height cell that represents single area in 
  56 //                  imagemap (it's GetLink is called from wxHtmlImageCell's) 
  57 // --------------------------------------------------------------------------- 
  59 class wxHtmlImageMapAreaCell 
: public wxHtmlCell
 
  62         enum celltype 
{ CIRCLE
, RECT
, POLY 
}; 
  68         wxHtmlImageMapAreaCell( celltype t
, wxString 
&coords
, double pixel_scale 
= 1.0); 
  69         virtual wxHtmlLinkInfo 
*GetLink( int x 
= 0, int y 
= 0 ) const; 
  70         void Draw(wxDC
& WXUNUSED(dc
), 
  71                   int WXUNUSED(x
), int WXUNUSED(y
), 
  72                   int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
  73                   wxHtmlRenderingInfo
& WXUNUSED(info
)) {} 
  80 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t
, wxString 
&incoords
, double pixel_scale 
) 
  83     wxString x 
= incoords
, y
; 
  86     while ((i 
= x
.Find( ',' )) != -1) 
  88         coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.Left( i 
).c_str())) ); 
  91     coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.c_str())) ); 
  94 wxHtmlLinkInfo 
*wxHtmlImageMapAreaCell::GetLink( int x
, int y 
) const 
 106                 if (x 
>= l 
&& x 
<= r 
&& y 
>= t 
&& y 
<= b
) 
 120                 d 
= sqrt( (double) (((x 
- l
) * (x 
- l
)) + ((y 
- t
) * (y 
- t
))) ); 
 129                 if (coords
.GetCount() >= 6) 
 134                     int totalv 
= coords
.GetCount() / 2; 
 135                     int totalc 
= totalv 
* 2; 
 136                     int xval 
= coords
[totalc 
- 2]; 
 137                     int yval 
= coords
[totalc 
- 1]; 
 141                     if ((yval 
>= wherey
) != (coords
[pointer
] >= wherey
)) 
 143                         if ((xval 
>= wherex
) == (coords
[0] >= wherex
)) 
 145                             intersects 
+= (xval 
>= wherex
) ? 1 : 0; 
 149                             intersects 
+= ((xval 
- (yval 
- wherey
) * 
 151                                             (coords
[pointer
] - yval
)) >= wherex
) ? 1 : 0; 
 155                     while (pointer 
< end
) 
 157                         yval 
= coords
[pointer
]; 
 161                             while ((pointer 
< end
) && (coords
[pointer
] >= wherey
)) 
 169                             if ((coords
[pointer 
- 3] >= wherex
) == 
 170                                     (coords
[pointer 
- 1] >= wherex
)) { 
 171                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 176                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 177                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 178                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 183                             while ((pointer 
< end
) && (coords
[pointer
] < wherey
)) 
 191                             if ((coords
[pointer 
- 3] >= wherex
) == 
 192                                     (coords
[pointer 
- 1] >= wherex
)) 
 194                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 199                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 200                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 201                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 205                     if ((intersects 
& 1) != 0) 
 216         wxHtmlImageMapAreaCell  
*a 
= (wxHtmlImageMapAreaCell
*)m_Next
; 
 217         return a
->GetLink( x
, y 
); 
 229 //-------------------------------------------------------------------------------- 
 230 // wxHtmlImageMapCell 
 231 //                  0-width, 0-height cell that represents map from imagemaps 
 232 //                  it is always placed before wxHtmlImageMapAreaCells 
 233 //                  It responds to Find(wxHTML_COND_ISIMAGEMAP) 
 234 //-------------------------------------------------------------------------------- 
 237 class wxHtmlImageMapCell 
: public wxHtmlCell
 
 240         wxHtmlImageMapCell( wxString 
&name 
); 
 244         virtual wxHtmlLinkInfo 
*GetLink( int x 
= 0, int y 
= 0 ) const; 
 245         virtual const wxHtmlCell 
*Find( int cond
, const void *param 
) const; 
 246         void Draw(wxDC
& WXUNUSED(dc
), 
 247                   int WXUNUSED(x
), int WXUNUSED(y
), 
 248                   int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
 249                   wxHtmlRenderingInfo
& WXUNUSED(info
)) {} 
 253 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString 
&name 
) 
 258 wxHtmlLinkInfo 
*wxHtmlImageMapCell::GetLink( int x
, int y 
) const 
 260     wxHtmlImageMapAreaCell  
*a 
= (wxHtmlImageMapAreaCell
*)m_Next
; 
 262         return a
->GetLink( x
, y 
); 
 263     return wxHtmlCell::GetLink( x
, y 
); 
 266 const wxHtmlCell 
*wxHtmlImageMapCell::Find( int cond
, const void *param 
) const 
 268     if (cond 
== wxHTML_COND_ISIMAGEMAP
) 
 270         if (m_Name 
== *((wxString
*)(param
))) 
 273     return wxHtmlCell::Find(cond
, param
); 
 280 //-------------------------------------------------------------------------------- 
 283 //-------------------------------------------------------------------------------- 
 285 class wxHtmlImageCell 
: public wxHtmlCell
 
 288     wxHtmlImageCell(wxWindow 
*window
, 
 289                     wxFSFile 
*input
, int w 
= -1, int h 
= -1, 
 290                     double scale 
= 1.0, int align 
= wxHTML_ALIGN_BOTTOM
, 
 291                     const wxString
& mapname 
= wxEmptyString
); 
 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; 
 297     void SetImage(const wxImage
& img
); 
 298 #if wxUSE_GIF && wxUSE_TIMER 
 299     void AdvanceAnimation(wxTimer 
*timer
); 
 300     virtual void Layout(int w
); 
 307     wxScrolledWindow   
*m_window
; 
 308 #if wxUSE_GIF && wxUSE_TIMER 
 309     wxGIFDecoder       
*m_gifDecoder
; 
 311     int                 m_physX
, m_physY
; 
 314     wxHtmlImageMapCell 
*m_imageMap
; 
 317     DECLARE_NO_COPY_CLASS(wxHtmlImageCell
) 
 320 #if wxUSE_GIF && wxUSE_TIMER 
 321 class wxGIFTimer 
: public wxTimer
 
 324         wxGIFTimer(wxHtmlImageCell 
*cell
) : m_cell(cell
) {} 
 325         virtual void Notify() 
 327             m_cell
->AdvanceAnimation(this); 
 331         wxHtmlImageCell 
*m_cell
; 
 333     DECLARE_NO_COPY_CLASS(wxGIFTimer
) 
 338 //---------------------------------------------------------------------------- 
 340 //---------------------------------------------------------------------------- 
 343 wxHtmlImageCell::wxHtmlImageCell(wxWindow 
*window
, wxFSFile 
*input
, 
 344                                  int w
, int h
, double scale
, int align
, 
 345                                  const wxString
& mapname
) : wxHtmlCell() 
 347     m_window 
= window 
? wxStaticCast(window
, wxScrolledWindow
) : NULL
; 
 355     SetCanLiveOnPagebreak(FALSE
); 
 356 #if wxUSE_GIF && wxUSE_TIMER 
 359     m_physX 
= m_physY 
= -1; 
 362     if ( m_bmpW 
&& m_bmpH 
) 
 366             wxInputStream 
*s 
= input
->GetStream(); 
 372 #if wxUSE_GIF && wxUSE_TIMER 
 373                 if ( (input
->GetLocation().Matches(wxT("*.gif")) || 
 374                       input
->GetLocation().Matches(wxT("*.GIF"))) && m_window 
) 
 376                     m_gifDecoder 
= new wxGIFDecoder(s
, TRUE
); 
 377                     if ( m_gifDecoder
->ReadGIF() == wxGIF_OK 
) 
 380                         if ( m_gifDecoder
->ConvertToImage(&img
) ) 
 385                         if ( m_gifDecoder
->IsAnimation() ) 
 387                             m_gifTimer 
= new wxGIFTimer(this); 
 388                             m_gifTimer
->Start(m_gifDecoder
->GetDelay(), TRUE
); 
 392                             wxDELETE(m_gifDecoder
); 
 397                         wxDELETE(m_gifDecoder
); 
 402 #endif // wxUSE_GIF && wxUSE_TIMER 
 404                     wxImage 
image(*s
, wxBITMAP_TYPE_ANY
); 
 410         else // input==NULL, use "broken image" bitmap 
 412             if ( m_bmpW 
== -1 && m_bmpH 
== -1 ) 
 420                 if ( m_bmpW 
== -1 ) m_bmpW 
= 31; 
 421                 if ( m_bmpH 
== -1 ) m_bmpH 
= 33; 
 424                 new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE
)); 
 427     //else: ignore the 0-sized images used sometimes on the Web pages 
 429     m_Width 
= (int)(scale 
* (double)m_bmpW
); 
 430     m_Height 
= (int)(scale 
* (double)m_bmpH
); 
 434         case wxHTML_ALIGN_TOP 
: 
 435             m_Descent 
= m_Height
; 
 437         case wxHTML_ALIGN_CENTER 
: 
 438             m_Descent 
= m_Height 
/ 2; 
 440         case wxHTML_ALIGN_BOTTOM 
: 
 447 void wxHtmlImageCell::SetImage(const wxImage
& img
) 
 455         hh 
= img
.GetHeight(); 
 462         if ((m_bmpW 
!= ww
) || (m_bmpH 
!= hh
)) 
 464             wxImage img2 
= img
.Scale(m_bmpW
, m_bmpH
); 
 465             m_bitmap 
= new wxBitmap(img2
); 
 468             m_bitmap 
= new wxBitmap(img
); 
 472 #if wxUSE_GIF && wxUSE_TIMER 
 473 void wxHtmlImageCell::AdvanceAnimation(wxTimer 
*timer
) 
 477     m_gifDecoder
->GoNextFrame(TRUE
); 
 481         m_physX 
= m_physY 
= 0; 
 482         for (wxHtmlCell 
*cell 
= this; cell
; cell 
= cell
->GetParent()) 
 484             m_physX 
+= cell
->GetPosX(); 
 485             m_physY 
+= cell
->GetPosY(); 
 490     m_window
->CalcScrolledPosition(m_physX
, m_physY
, &x
, &y
); 
 491     wxRect 
rect(x
, y
, m_Width
, m_Height
); 
 493     if ( m_window
->GetClientRect().Intersects(rect
) && 
 494          m_gifDecoder
->ConvertToImage(&img
) ) 
 496         if ( (int)m_gifDecoder
->GetWidth() != m_Width 
|| 
 497              (int)m_gifDecoder
->GetHeight() != m_Height 
|| 
 498              m_gifDecoder
->GetLeft() != 0 || m_gifDecoder
->GetTop() != 0 ) 
 502             dc
.SelectObject(*m_bitmap
); 
 503             dc
.DrawBitmap(bmp
, m_gifDecoder
->GetLeft(), m_gifDecoder
->GetTop()); 
 507         m_window
->Refresh(img
.HasMask(), &rect
); 
 510     timer
->Start(m_gifDecoder
->GetDelay(), TRUE
); 
 513 void wxHtmlImageCell::Layout(int w
) 
 515     wxHtmlCell::Layout(w
); 
 516     m_physX 
= m_physY 
= -1; 
 521 wxHtmlImageCell::~wxHtmlImageCell() 
 524 #if wxUSE_GIF && wxUSE_TIMER 
 531 void wxHtmlImageCell::Draw(wxDC
& dc
, int x
, int y
, 
 532                            int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
 533                            wxHtmlRenderingInfo
& WXUNUSED(info
)) 
 537         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 538         dc
.SetPen(*wxBLACK_PEN
); 
 539         dc
.DrawRectangle(x 
+ m_PosX
, y 
+ m_PosY
, m_Width
, m_Height
); 
 545         dc
.GetUserScale(&us_x
, &us_y
); 
 546         dc
.SetUserScale(us_x 
* m_scale
, us_y 
* m_scale
); 
 548         dc
.DrawBitmap(*m_bitmap
, (int) ((x 
+ m_PosX
) / m_scale
), 
 549                                  (int) ((y 
+ m_PosY
) / m_scale
), TRUE
); 
 550         dc
.SetUserScale(us_x
, us_y
); 
 554 wxHtmlLinkInfo 
*wxHtmlImageCell::GetLink( int x
, int y 
) const 
 556     if (m_mapName
.IsEmpty()) 
 557         return wxHtmlCell::GetLink( x
, y 
); 
 560         wxHtmlContainerCell 
*p
, *op
; 
 561         op 
= p 
= GetParent(); 
 568         wxHtmlCell 
*cell 
= (wxHtmlCell
*)p
->Find(wxHTML_COND_ISIMAGEMAP
, 
 569                                                 (const void*)(&m_mapName
)); 
 572             ((wxString
&)m_mapName
).Clear(); 
 573             return wxHtmlCell::GetLink( x
, y 
); 
 575         {   // dirty hack, ask Joel why he fills m_ImageMap in this place 
 576             // THE problem is that we're in const method and we can't modify m_ImageMap 
 577             wxHtmlImageMapCell 
**cx 
= (wxHtmlImageMapCell
**)(&m_imageMap
); 
 578             *cx 
= (wxHtmlImageMapCell
*)cell
; 
 581     return m_imageMap
->GetLink(x
, y
); 
 586 //-------------------------------------------------------------------------------- 
 588 //-------------------------------------------------------------------------------- 
 590 TAG_HANDLER_BEGIN(IMG
, "IMG,MAP,AREA") 
 592     TAG_HANDLER_PROC(tag
) 
 594         if (tag
.GetName() == wxT("IMG")) 
 596             if (tag
.HasParam(wxT("SRC"))) 
 601                 wxString tmp 
= tag
.GetParam(wxT("SRC")); 
 602                 wxString mn 
= wxEmptyString
; 
 604                 str 
= m_WParser
->OpenURL(wxHTML_URL_IMAGE
, tmp
); 
 606                 if (tag
.HasParam(wxT("WIDTH"))) 
 607                     tag
.GetParamAsInt(wxT("WIDTH"), &w
); 
 608                 if (tag
.HasParam(wxT("HEIGHT"))) 
 609                     tag
.GetParamAsInt(wxT("HEIGHT"), &h
); 
 610                 al 
= wxHTML_ALIGN_BOTTOM
; 
 611                 if (tag
.HasParam(wxT("ALIGN"))) 
 613                     wxString alstr 
= tag
.GetParam(wxT("ALIGN")); 
 614                     alstr
.MakeUpper();  // for the case alignment was in ".." 
 615                     if (alstr 
== wxT("TEXTTOP")) 
 616                         al 
= wxHTML_ALIGN_TOP
; 
 617                     else if ((alstr 
== wxT("CENTER")) || (alstr 
== wxT("ABSCENTER"))) 
 618                         al 
= wxHTML_ALIGN_CENTER
; 
 620                 if (tag
.HasParam(wxT("USEMAP"))) 
 622                     mn 
= tag
.GetParam( wxT("USEMAP") ); 
 623                     if (mn
.GetChar(0) == wxT('#')) 
 628                 wxHtmlImageCell 
*cel 
= new wxHtmlImageCell( 
 629                                           m_WParser
->GetWindow(), 
 631                                           m_WParser
->GetPixelScale(), 
 633                 cel
->SetLink(m_WParser
->GetLink()); 
 634                 cel
->SetId(tag
.GetParam(wxT("id"))); // may be empty 
 635                 m_WParser
->GetContainer()->InsertCell(cel
); 
 640         if (tag
.GetName() == wxT("MAP")) 
 642             m_WParser
->CloseContainer(); 
 643             m_WParser
->OpenContainer(); 
 644             if (tag
.HasParam(wxT("NAME"))) 
 646                 wxString tmp 
= tag
.GetParam(wxT("NAME")); 
 647                 wxHtmlImageMapCell 
*cel 
= new wxHtmlImageMapCell( tmp 
); 
 648                 m_WParser
->GetContainer()->InsertCell( cel 
); 
 651             m_WParser
->CloseContainer(); 
 652             m_WParser
->OpenContainer(); 
 654         if (tag
.GetName() == wxT("AREA")) 
 656             if (tag
.HasParam(wxT("SHAPE"))) 
 658                 wxString tmp 
= tag
.GetParam(wxT("SHAPE")); 
 659                 wxString coords 
= wxEmptyString
; 
 661                 wxHtmlImageMapAreaCell 
*cel 
= NULL
; 
 662                 if (tag
.HasParam(wxT("COORDS"))) 
 664                     coords 
= tag
.GetParam(wxT("COORDS")); 
 666                 if (tmp 
== wxT("POLY")) 
 668                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY
, coords
, m_WParser
->GetPixelScale() ); 
 670                 else if (tmp 
== wxT("CIRCLE")) 
 672                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE
, coords
, m_WParser
->GetPixelScale() ); 
 674                 else if (tmp 
== wxT("RECT")) 
 676                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT
, coords
, m_WParser
->GetPixelScale() ); 
 678                 if (cel 
!= NULL 
&& tag
.HasParam(wxT("HREF"))) 
 680                     wxString tmp 
= tag
.GetParam(wxT("HREF")); 
 681                     wxString target 
= wxEmptyString
; 
 682                     if (tag
.HasParam(wxT("TARGET"))) target 
= tag
.GetParam(wxT("TARGET")); 
 683                     cel
->SetLink( wxHtmlLinkInfo(tmp
, target
)); 
 685                 if (cel 
!= NULL
) m_WParser
->GetContainer()->InsertCell( cel 
); 
 696 TAGS_MODULE_BEGIN(Image
) 
 700 TAGS_MODULE_END(Image
)