]>
git.saurik.com Git - wxWidgets.git/blob - src/html/m_image.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/html/m_image.cpp 
   3 // Purpose:     wxHtml module for displaying images 
   4 // Author:      Vaclav Slavik 
   6 // Copyright:   (c) 1999 Vaclav Slavik, Joel Lucsy 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #include "wx/wxprec.h" 
  16 #if wxUSE_HTML && wxUSE_STREAMS 
  19     #include "wx/dynarray.h" 
  21     #include "wx/scrolwin.h" 
  23     #include "wx/dcmemory.h" 
  29 #include "wx/html/forcelnk.h" 
  30 #include "wx/html/m_templ.h" 
  31 #include "wx/html/htmlwin.h" 
  33 #include "wx/gifdecod.h" 
  34 #include "wx/artprov.h" 
  38 FORCE_LINK_ME(m_image
) 
  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
) 
  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 // --------------------------------------------------------------------------- 
  54 class wxHtmlImageMapAreaCell 
: public wxHtmlCell
 
  57         enum celltype 
{ CIRCLE
, RECT
, POLY 
}; 
  63         wxHtmlImageMapAreaCell( celltype t
, wxString 
&coords
, double pixel_scale 
= 1.0); 
  64         virtual wxHtmlLinkInfo 
*GetLink( int x 
= 0, int y 
= 0 ) const; 
  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
)) {} 
  71     DECLARE_NO_COPY_CLASS(wxHtmlImageMapAreaCell
) 
  78 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t
, wxString 
&incoords
, double pixel_scale 
) 
  81     wxString x 
= incoords
, y
; 
  84     while ((i 
= x
.Find( ',' )) != wxNOT_FOUND
) 
  86         coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.Left( i 
).c_str())) ); 
  89     coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.c_str())) ); 
  92 wxHtmlLinkInfo 
*wxHtmlImageMapAreaCell::GetLink( int x
, int y 
) const 
 104                 if (x 
>= l 
&& x 
<= r 
&& y 
>= t 
&& y 
<= b
) 
 118                 d 
= sqrt( (double) (((x 
- l
) * (x 
- l
)) + ((y 
- t
) * (y 
- t
))) ); 
 127                 if (coords
.GetCount() >= 6) 
 132                     int totalv 
= coords
.GetCount() / 2; 
 133                     int totalc 
= totalv 
* 2; 
 134                     int xval 
= coords
[totalc 
- 2]; 
 135                     int yval 
= coords
[totalc 
- 1]; 
 139                     if ((yval 
>= wherey
) != (coords
[pointer
] >= wherey
)) 
 141                         if ((xval 
>= wherex
) == (coords
[0] >= wherex
)) 
 143                             intersects 
+= (xval 
>= wherex
) ? 1 : 0; 
 147                             intersects 
+= ((xval 
- (yval 
- wherey
) * 
 149                                             (coords
[pointer
] - yval
)) >= wherex
) ? 1 : 0; 
 153                     while (pointer 
< end
) 
 155                         yval 
= coords
[pointer
]; 
 159                             while ((pointer 
< end
) && (coords
[pointer
] >= wherey
)) 
 167                             if ((coords
[pointer 
- 3] >= wherex
) == 
 168                                     (coords
[pointer 
- 1] >= wherex
)) { 
 169                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 174                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 175                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 176                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 181                             while ((pointer 
< end
) && (coords
[pointer
] < wherey
)) 
 189                             if ((coords
[pointer 
- 3] >= wherex
) == 
 190                                     (coords
[pointer 
- 1] >= wherex
)) 
 192                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 197                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 198                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 199                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 203                     if ((intersects 
& 1) != 0) 
 214         wxHtmlImageMapAreaCell  
*a 
= (wxHtmlImageMapAreaCell
*)m_Next
; 
 215         return a
->GetLink( x
, y 
); 
 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 //-------------------------------------------------------------------------------- 
 235 class wxHtmlImageMapCell 
: public wxHtmlCell
 
 238         wxHtmlImageMapCell( wxString 
&name 
); 
 242         virtual wxHtmlLinkInfo 
*GetLink( int x 
= 0, int y 
= 0 ) const; 
 243         virtual const wxHtmlCell 
*Find( int cond
, const void *param 
) const; 
 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
)) {} 
 249     DECLARE_NO_COPY_CLASS(wxHtmlImageMapCell
) 
 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(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; 
 297     void SetImage(const wxImage
& img
); 
 298 #if wxUSE_GIF && wxUSE_TIMER 
 299     void AdvanceAnimation(wxTimer 
*timer
); 
 300     virtual void Layout(int w
); 
 307     wxHtmlWindowInterface 
*m_windowIface
; 
 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(wxHtmlWindowInterface 
*windowIface
, 
 345                                  int w
, int h
, double scale
, int align
, 
 346                                  const wxString
& mapname
) : wxHtmlCell() 
 348     m_windowIface 
= windowIface
; 
 356     SetCanLiveOnPagebreak(false); 
 357 #if wxUSE_GIF && wxUSE_TIMER 
 360     m_physX 
= m_physY 
= wxDefaultCoord
; 
 363     if ( m_bmpW 
&& m_bmpH 
) 
 367             wxInputStream 
*s 
= input
->GetStream(); 
 371 #if wxUSE_GIF && wxUSE_TIMER 
 373                 if ( m_windowIface 
&& 
 374                      (input
->GetLocation().Matches(wxT("*.gif")) || 
 375                       input
->GetLocation().Matches(wxT("*.GIF"))) ) 
 377                     m_gifDecoder 
= new wxGIFDecoder(s
, true); 
 378                     if ( m_gifDecoder
->ReadGIF() == wxGIF_OK 
) 
 381                         if ( m_gifDecoder
->ConvertToImage(&img
) ) 
 386                         if ( m_gifDecoder
->IsAnimation() ) 
 388                             m_gifTimer 
= new wxGIFTimer(this); 
 389                             m_gifTimer
->Start(m_gifDecoder
->GetDelay(), true); 
 393                             wxDELETE(m_gifDecoder
); 
 398                         wxDELETE(m_gifDecoder
); 
 403 #endif // wxUSE_GIF && wxUSE_TIMER 
 405                     wxImage 
image(*s
, wxBITMAP_TYPE_ANY
); 
 411         else // input==NULL, use "broken image" bitmap 
 413             if ( m_bmpW 
== wxDefaultCoord 
&& m_bmpH 
== wxDefaultCoord 
) 
 421                 if ( m_bmpW 
== wxDefaultCoord 
) m_bmpW 
= 31; 
 422                 if ( m_bmpH 
== wxDefaultCoord 
) m_bmpH 
= 33; 
 425                 new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE
)); 
 428     //else: ignore the 0-sized images used sometimes on the Web pages 
 430     m_Width 
= (int)(scale 
* (double)m_bmpW
); 
 431     m_Height 
= (int)(scale 
* (double)m_bmpH
); 
 435         case wxHTML_ALIGN_TOP 
: 
 436             m_Descent 
= m_Height
; 
 438         case wxHTML_ALIGN_CENTER 
: 
 439             m_Descent 
= m_Height 
/ 2; 
 441         case wxHTML_ALIGN_BOTTOM 
: 
 448 void wxHtmlImageCell::SetImage(const wxImage
& img
) 
 450 #if !defined(__WXMSW__) || wxUSE_WXDIB 
 457         hh 
= img
.GetHeight(); 
 459         if ( m_bmpW 
== wxDefaultCoord 
) 
 461         if ( m_bmpH 
== wxDefaultCoord 
) 
 464         // Only scale the bitmap at the rendering stage, 
 465         // so we don't lose quality twice 
 467         if ((m_bmpW != ww) || (m_bmpH != hh)) 
 469             wxImage img2 = img.Scale(m_bmpW, m_bmpH); 
 470             m_bitmap = new wxBitmap(img2); 
 474             m_bitmap 
= new wxBitmap(img
); 
 479 #if wxUSE_GIF && wxUSE_TIMER 
 480 void wxHtmlImageCell::AdvanceAnimation(wxTimer 
*timer
) 
 484     m_gifDecoder
->GoNextFrame(true); 
 486     if ( m_physX 
== wxDefaultCoord 
) 
 488         m_physX 
= m_physY 
= 0; 
 489         for (wxHtmlCell 
*cell 
= this; cell
; cell 
= cell
->GetParent()) 
 491             m_physX 
+= cell
->GetPosX(); 
 492             m_physY 
+= cell
->GetPosY(); 
 496     wxWindow 
*win 
= m_windowIface
->GetHTMLWindow(); 
 498         m_windowIface
->HTMLCoordsToWindow(this, wxPoint(m_physX
, m_physY
)); 
 499     wxRect 
rect(pos
, wxSize(m_Width
, m_Height
)); 
 501     if ( win
->GetClientRect().Intersects(rect
) && 
 502          m_gifDecoder
->ConvertToImage(&img
) ) 
 504 #if !defined(__WXMSW__) || wxUSE_WXDIB 
 505         if ( (int)m_gifDecoder
->GetWidth() != m_Width 
|| 
 506              (int)m_gifDecoder
->GetHeight() != m_Height 
|| 
 507              m_gifDecoder
->GetLeft() != 0 || m_gifDecoder
->GetTop() != 0 ) 
 511             dc
.SelectObject(*m_bitmap
); 
 512             dc
.DrawBitmap(bmp
, m_gifDecoder
->GetLeft(), m_gifDecoder
->GetTop(), 
 513                           true /* use mask */); 
 518         win
->Refresh(img
.HasMask(), &rect
); 
 521     timer
->Start(m_gifDecoder
->GetDelay(), true); 
 524 void wxHtmlImageCell::Layout(int w
) 
 526     wxHtmlCell::Layout(w
); 
 527     m_physX 
= m_physY 
= wxDefaultCoord
; 
 532 wxHtmlImageCell::~wxHtmlImageCell() 
 535 #if wxUSE_GIF && wxUSE_TIMER 
 542 void wxHtmlImageCell::Draw(wxDC
& dc
, int x
, int y
, 
 543                            int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
 544                            wxHtmlRenderingInfo
& WXUNUSED(info
)) 
 548         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 549         dc
.SetPen(*wxBLACK_PEN
); 
 550         dc
.DrawRectangle(x 
+ m_PosX
, y 
+ m_PosY
, m_Width
, m_Height
); 
 555         // We add in the scaling from the desired bitmap width 
 556         // and height, so we only do the scaling once. 
 557         double imageScaleX 
= 1.0; 
 558         double imageScaleY 
= 1.0; 
 559         if (m_bmpW 
!= m_bitmap
->GetWidth()) 
 560             imageScaleX 
= (double) m_bmpW 
/ (double) m_bitmap
->GetWidth(); 
 561         if (m_bmpH 
!= m_bitmap
->GetHeight()) 
 562             imageScaleY 
= (double) m_bmpH 
/ (double) m_bitmap
->GetHeight(); 
 565         dc
.GetUserScale(&us_x
, &us_y
); 
 566         dc
.SetUserScale(us_x 
* m_scale 
* imageScaleX
, us_y 
* m_scale 
* imageScaleY
); 
 568         dc
.DrawBitmap(*m_bitmap
, (int) ((x 
+ m_PosX
) / (m_scale
*imageScaleX
)), 
 569                                  (int) ((y 
+ m_PosY
) / (m_scale
*imageScaleY
)), true); 
 570         dc
.SetUserScale(us_x
, us_y
); 
 574 wxHtmlLinkInfo 
*wxHtmlImageCell::GetLink( int x
, int y 
) const 
 576     if (m_mapName
.empty()) 
 577         return wxHtmlCell::GetLink( x
, y 
); 
 580         wxHtmlContainerCell 
*p
, *op
; 
 581         op 
= p 
= GetParent(); 
 588         wxHtmlCell 
*cell 
= (wxHtmlCell
*)p
->Find(wxHTML_COND_ISIMAGEMAP
, 
 589                                                 (const void*)(&m_mapName
)); 
 592             ((wxString
&)m_mapName
).Clear(); 
 593             return wxHtmlCell::GetLink( x
, y 
); 
 595         {   // dirty hack, ask Joel why he fills m_ImageMap in this place 
 596             // THE problem is that we're in const method and we can't modify m_ImageMap 
 597             wxHtmlImageMapCell 
**cx 
= (wxHtmlImageMapCell
**)(&m_imageMap
); 
 598             *cx 
= (wxHtmlImageMapCell
*)cell
; 
 601     return m_imageMap
->GetLink(x
, y
); 
 606 //-------------------------------------------------------------------------------- 
 608 //-------------------------------------------------------------------------------- 
 610 TAG_HANDLER_BEGIN(IMG
, "IMG,MAP,AREA") 
 611     TAG_HANDLER_CONSTR(IMG
) { } 
 613     TAG_HANDLER_PROC(tag
) 
 615         if (tag
.GetName() == wxT("IMG")) 
 617             if (tag
.HasParam(wxT("SRC"))) 
 619                 int w 
= wxDefaultCoord
, h 
= wxDefaultCoord
; 
 622                 wxString tmp 
= tag
.GetParam(wxT("SRC")); 
 623                 wxString mn 
= wxEmptyString
; 
 625                 str 
= m_WParser
->OpenURL(wxHTML_URL_IMAGE
, tmp
); 
 627                 if (tag
.HasParam(wxT("WIDTH"))) 
 628                     tag
.GetParamAsInt(wxT("WIDTH"), &w
); 
 629                 if (tag
.HasParam(wxT("HEIGHT"))) 
 630                     tag
.GetParamAsInt(wxT("HEIGHT"), &h
); 
 631                 al 
= wxHTML_ALIGN_BOTTOM
; 
 632                 if (tag
.HasParam(wxT("ALIGN"))) 
 634                     wxString alstr 
= tag
.GetParam(wxT("ALIGN")); 
 635                     alstr
.MakeUpper();  // for the case alignment was in ".." 
 636                     if (alstr 
== wxT("TEXTTOP")) 
 637                         al 
= wxHTML_ALIGN_TOP
; 
 638                     else if ((alstr 
== wxT("CENTER")) || (alstr 
== wxT("ABSCENTER"))) 
 639                         al 
= wxHTML_ALIGN_CENTER
; 
 641                 if (tag
.HasParam(wxT("USEMAP"))) 
 643                     mn 
= tag
.GetParam( wxT("USEMAP") ); 
 644                     if (mn
.GetChar(0) == wxT('#')) 
 649                 wxHtmlImageCell 
*cel 
= new wxHtmlImageCell( 
 650                                           m_WParser
->GetWindowInterface(), 
 652                                           m_WParser
->GetPixelScale(), 
 654                 m_WParser
->ApplyStateToCell(cel
); 
 655                 cel
->SetId(tag
.GetParam(wxT("id"))); // may be empty 
 656                 m_WParser
->GetContainer()->InsertCell(cel
); 
 661         if (tag
.GetName() == wxT("MAP")) 
 663             m_WParser
->CloseContainer(); 
 664             m_WParser
->OpenContainer(); 
 665             if (tag
.HasParam(wxT("NAME"))) 
 667                 wxString tmp 
= tag
.GetParam(wxT("NAME")); 
 668                 wxHtmlImageMapCell 
*cel 
= new wxHtmlImageMapCell( tmp 
); 
 669                 m_WParser
->GetContainer()->InsertCell( cel 
); 
 672             m_WParser
->CloseContainer(); 
 673             m_WParser
->OpenContainer(); 
 675         if (tag
.GetName() == wxT("AREA")) 
 677             if (tag
.HasParam(wxT("SHAPE"))) 
 679                 wxString tmp 
= tag
.GetParam(wxT("SHAPE")); 
 680                 wxString coords 
= wxEmptyString
; 
 682                 wxHtmlImageMapAreaCell 
*cel 
= NULL
; 
 683                 if (tag
.HasParam(wxT("COORDS"))) 
 685                     coords 
= tag
.GetParam(wxT("COORDS")); 
 687                 if (tmp 
== wxT("POLY")) 
 689                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY
, coords
, m_WParser
->GetPixelScale() ); 
 691                 else if (tmp 
== wxT("CIRCLE")) 
 693                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE
, coords
, m_WParser
->GetPixelScale() ); 
 695                 else if (tmp 
== wxT("RECT")) 
 697                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT
, coords
, m_WParser
->GetPixelScale() ); 
 699                 if (cel 
!= NULL 
&& tag
.HasParam(wxT("HREF"))) 
 702                     if (tag
.HasParam(wxT("TARGET"))) 
 703                         target 
= tag
.GetParam(wxT("TARGET")); 
 704                     cel
->SetLink(wxHtmlLinkInfo(tag
.GetParam(wxT("HREF")), target
)); 
 707                     m_WParser
->GetContainer()->InsertCell( cel 
); 
 718 TAGS_MODULE_BEGIN(Image
) 
 722 TAGS_MODULE_END(Image
)