]>
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 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  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
)) {} 
  76     DECLARE_NO_COPY_CLASS(wxHtmlImageMapAreaCell
) 
  83 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t
, wxString 
&incoords
, double pixel_scale 
) 
  86     wxString x 
= incoords
, y
; 
  89     while ((i 
= x
.Find( ',' )) != wxNOT_FOUND
) 
  91         coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.Left( i 
).c_str())) ); 
  94     coords
.Add( (int)(pixel_scale 
* (double)wxAtoi( x
.c_str())) ); 
  97 wxHtmlLinkInfo 
*wxHtmlImageMapAreaCell::GetLink( int x
, int y 
) const 
 109                 if (x 
>= l 
&& x 
<= r 
&& y 
>= t 
&& y 
<= b
) 
 123                 d 
= sqrt( (double) (((x 
- l
) * (x 
- l
)) + ((y 
- t
) * (y 
- t
))) ); 
 132                 if (coords
.GetCount() >= 6) 
 137                     int totalv 
= coords
.GetCount() / 2; 
 138                     int totalc 
= totalv 
* 2; 
 139                     int xval 
= coords
[totalc 
- 2]; 
 140                     int yval 
= coords
[totalc 
- 1]; 
 144                     if ((yval 
>= wherey
) != (coords
[pointer
] >= wherey
)) 
 146                         if ((xval 
>= wherex
) == (coords
[0] >= wherex
)) 
 148                             intersects 
+= (xval 
>= wherex
) ? 1 : 0; 
 152                             intersects 
+= ((xval 
- (yval 
- wherey
) * 
 154                                             (coords
[pointer
] - yval
)) >= wherex
) ? 1 : 0; 
 158                     while (pointer 
< end
) 
 160                         yval 
= coords
[pointer
]; 
 164                             while ((pointer 
< end
) && (coords
[pointer
] >= wherey
)) 
 172                             if ((coords
[pointer 
- 3] >= wherex
) == 
 173                                     (coords
[pointer 
- 1] >= wherex
)) { 
 174                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 179                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 180                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 181                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 186                             while ((pointer 
< end
) && (coords
[pointer
] < wherey
)) 
 194                             if ((coords
[pointer 
- 3] >= wherex
) == 
 195                                     (coords
[pointer 
- 1] >= wherex
)) 
 197                                 intersects 
+= (coords
[pointer 
- 3] >= wherex
) ? 1 : 0; 
 202                                     ((coords
[pointer 
- 3] - (coords
[pointer 
- 2] - wherey
) * 
 203                                       (coords
[pointer 
- 1] - coords
[pointer 
- 3]) / 
 204                                       (coords
[pointer
] - coords
[pointer 
- 2])) >= wherex
) ? 1 : 0; 
 208                     if ((intersects 
& 1) != 0) 
 219         wxHtmlImageMapAreaCell  
*a 
= (wxHtmlImageMapAreaCell
*)m_Next
; 
 220         return a
->GetLink( x
, y 
); 
 232 //-------------------------------------------------------------------------------- 
 233 // wxHtmlImageMapCell 
 234 //                  0-width, 0-height cell that represents map from imagemaps 
 235 //                  it is always placed before wxHtmlImageMapAreaCells 
 236 //                  It responds to Find(wxHTML_COND_ISIMAGEMAP) 
 237 //-------------------------------------------------------------------------------- 
 240 class wxHtmlImageMapCell 
: public wxHtmlCell
 
 243         wxHtmlImageMapCell( wxString 
&name 
); 
 247         virtual wxHtmlLinkInfo 
*GetLink( int x 
= 0, int y 
= 0 ) const; 
 248         virtual const wxHtmlCell 
*Find( int cond
, const void *param 
) const; 
 249         void Draw(wxDC
& WXUNUSED(dc
), 
 250                   int WXUNUSED(x
), int WXUNUSED(y
), 
 251                   int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
 252                   wxHtmlRenderingInfo
& WXUNUSED(info
)) {} 
 254     DECLARE_NO_COPY_CLASS(wxHtmlImageMapCell
) 
 258 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString 
&name 
) 
 263 wxHtmlLinkInfo 
*wxHtmlImageMapCell::GetLink( int x
, int y 
) const 
 265     wxHtmlImageMapAreaCell  
*a 
= (wxHtmlImageMapAreaCell
*)m_Next
; 
 267         return a
->GetLink( x
, y 
); 
 268     return wxHtmlCell::GetLink( x
, y 
); 
 271 const wxHtmlCell 
*wxHtmlImageMapCell::Find( int cond
, const void *param 
) const 
 273     if (cond 
== wxHTML_COND_ISIMAGEMAP
) 
 275         if (m_Name 
== *((wxString
*)(param
))) 
 278     return wxHtmlCell::Find(cond
, param
); 
 285 //-------------------------------------------------------------------------------- 
 288 //-------------------------------------------------------------------------------- 
 290 class wxHtmlImageCell 
: public wxHtmlCell
 
 293     wxHtmlImageCell(wxWindow 
*window
, 
 294                     wxFSFile 
*input
, int w 
= wxDefaultCoord
, int h 
= wxDefaultCoord
, 
 295                     double scale 
= 1.0, int align 
= wxHTML_ALIGN_BOTTOM
, 
 296                     const wxString
& mapname 
= wxEmptyString
); 
 298     void Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
, 
 299               wxHtmlRenderingInfo
& info
); 
 300     virtual wxHtmlLinkInfo 
*GetLink(int x 
= 0, int y 
= 0) const; 
 302     void SetImage(const wxImage
& img
); 
 303 #if wxUSE_GIF && wxUSE_TIMER 
 304     void AdvanceAnimation(wxTimer 
*timer
); 
 305     virtual void Layout(int w
); 
 312     wxScrolledWindow   
*m_window
; 
 313 #if wxUSE_GIF && wxUSE_TIMER 
 314     wxGIFDecoder       
*m_gifDecoder
; 
 316     int                 m_physX
, m_physY
; 
 319     wxHtmlImageMapCell 
*m_imageMap
; 
 322     DECLARE_NO_COPY_CLASS(wxHtmlImageCell
) 
 325 #if wxUSE_GIF && wxUSE_TIMER 
 326 class wxGIFTimer 
: public wxTimer
 
 329         wxGIFTimer(wxHtmlImageCell 
*cell
) : m_cell(cell
) {} 
 330         virtual void Notify() 
 332             m_cell
->AdvanceAnimation(this); 
 336         wxHtmlImageCell 
*m_cell
; 
 338     DECLARE_NO_COPY_CLASS(wxGIFTimer
) 
 343 //---------------------------------------------------------------------------- 
 345 //---------------------------------------------------------------------------- 
 348 wxHtmlImageCell::wxHtmlImageCell(wxWindow 
*window
, wxFSFile 
*input
, 
 349                                  int w
, int h
, double scale
, int align
, 
 350                                  const wxString
& mapname
) : wxHtmlCell() 
 352     m_window 
= window 
? wxStaticCast(window
, wxScrolledWindow
) : NULL
; 
 360     SetCanLiveOnPagebreak(false); 
 361 #if wxUSE_GIF && wxUSE_TIMER 
 364     m_physX 
= m_physY 
= wxDefaultCoord
; 
 367     if ( m_bmpW 
&& m_bmpH 
) 
 371             wxInputStream 
*s 
= input
->GetStream(); 
 377 #if wxUSE_GIF && wxUSE_TIMER 
 378                 if ( (input
->GetLocation().Matches(wxT("*.gif")) || 
 379                       input
->GetLocation().Matches(wxT("*.GIF"))) && m_window 
) 
 381                     m_gifDecoder 
= new wxGIFDecoder(s
, true); 
 382                     if ( m_gifDecoder
->ReadGIF() == wxGIF_OK 
) 
 385                         if ( m_gifDecoder
->ConvertToImage(&img
) ) 
 390                         if ( m_gifDecoder
->IsAnimation() ) 
 392                             m_gifTimer 
= new wxGIFTimer(this); 
 393                             m_gifTimer
->Start(m_gifDecoder
->GetDelay(), true); 
 397                             wxDELETE(m_gifDecoder
); 
 402                         wxDELETE(m_gifDecoder
); 
 407 #endif // wxUSE_GIF && wxUSE_TIMER 
 409                     wxImage 
image(*s
, wxBITMAP_TYPE_ANY
); 
 415         else // input==NULL, use "broken image" bitmap 
 417             if ( m_bmpW 
== wxDefaultCoord 
&& m_bmpH 
== wxDefaultCoord 
) 
 425                 if ( m_bmpW 
== wxDefaultCoord 
) m_bmpW 
= 31; 
 426                 if ( m_bmpH 
== wxDefaultCoord 
) m_bmpH 
= 33; 
 429                 new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE
)); 
 432     //else: ignore the 0-sized images used sometimes on the Web pages 
 434     m_Width 
= (int)(scale 
* (double)m_bmpW
); 
 435     m_Height 
= (int)(scale 
* (double)m_bmpH
); 
 439         case wxHTML_ALIGN_TOP 
: 
 440             m_Descent 
= m_Height
; 
 442         case wxHTML_ALIGN_CENTER 
: 
 443             m_Descent 
= m_Height 
/ 2; 
 445         case wxHTML_ALIGN_BOTTOM 
: 
 452 void wxHtmlImageCell::SetImage(const wxImage
& img
) 
 460         hh 
= img
.GetHeight(); 
 462         if ( m_bmpW 
== wxDefaultCoord 
) 
 464         if ( m_bmpH 
== wxDefaultCoord 
) 
 467         // Only scale the bitmap at the rendering stage, 
 468         // so we don't lose quality twice 
 470         if ((m_bmpW != ww) || (m_bmpH != hh)) 
 472             wxImage img2 = img.Scale(m_bmpW, m_bmpH); 
 473             m_bitmap = new wxBitmap(img2); 
 477             m_bitmap 
= new wxBitmap(img
); 
 481 #if wxUSE_GIF && wxUSE_TIMER 
 482 void wxHtmlImageCell::AdvanceAnimation(wxTimer 
*timer
) 
 486     m_gifDecoder
->GoNextFrame(true); 
 488     if ( m_physX 
== wxDefaultCoord 
) 
 490         m_physX 
= m_physY 
= 0; 
 491         for (wxHtmlCell 
*cell 
= this; cell
; cell 
= cell
->GetParent()) 
 493             m_physX 
+= cell
->GetPosX(); 
 494             m_physY 
+= cell
->GetPosY(); 
 499     m_window
->CalcScrolledPosition(m_physX
, m_physY
, &x
, &y
); 
 500     wxRect 
rect(x
, y
, m_Width
, m_Height
); 
 502     if ( m_window
->GetClientRect().Intersects(rect
) && 
 503          m_gifDecoder
->ConvertToImage(&img
) ) 
 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 */); 
 517         m_window
->Refresh(img
.HasMask(), &rect
); 
 520     timer
->Start(m_gifDecoder
->GetDelay(), true); 
 523 void wxHtmlImageCell::Layout(int w
) 
 525     wxHtmlCell::Layout(w
); 
 526     m_physX 
= m_physY 
= wxDefaultCoord
; 
 531 wxHtmlImageCell::~wxHtmlImageCell() 
 534 #if wxUSE_GIF && wxUSE_TIMER 
 541 void wxHtmlImageCell::Draw(wxDC
& dc
, int x
, int y
, 
 542                            int WXUNUSED(view_y1
), int WXUNUSED(view_y2
), 
 543                            wxHtmlRenderingInfo
& WXUNUSED(info
)) 
 547         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 548         dc
.SetPen(*wxBLACK_PEN
); 
 549         dc
.DrawRectangle(x 
+ m_PosX
, y 
+ m_PosY
, m_Width
, m_Height
); 
 554         // We add in the scaling from the desired bitmap width 
 555         // and height, so we only do the scaling once. 
 556         double imageScaleX 
= 1.0; 
 557         double imageScaleY 
= 1.0; 
 558         if (m_bmpW 
!= m_bitmap
->GetWidth()) 
 559             imageScaleX 
= (double) m_bmpW 
/ (double) m_bitmap
->GetWidth(); 
 560         if (m_bmpH 
!= m_bitmap
->GetHeight()) 
 561             imageScaleY 
= (double) m_bmpH 
/ (double) m_bitmap
->GetHeight(); 
 564         dc
.GetUserScale(&us_x
, &us_y
); 
 565         dc
.SetUserScale(us_x 
* m_scale 
* imageScaleX
, us_y 
* m_scale 
* imageScaleY
); 
 567         dc
.DrawBitmap(*m_bitmap
, (int) ((x 
+ m_PosX
) / (m_scale
*imageScaleX
)), 
 568                                  (int) ((y 
+ m_PosY
) / (m_scale
*imageScaleY
)), true); 
 569         dc
.SetUserScale(us_x
, us_y
); 
 573 wxHtmlLinkInfo 
*wxHtmlImageCell::GetLink( int x
, int y 
) const 
 575     if (m_mapName
.empty()) 
 576         return wxHtmlCell::GetLink( x
, y 
); 
 579         wxHtmlContainerCell 
*p
, *op
; 
 580         op 
= p 
= GetParent(); 
 587         wxHtmlCell 
*cell 
= (wxHtmlCell
*)p
->Find(wxHTML_COND_ISIMAGEMAP
, 
 588                                                 (const void*)(&m_mapName
)); 
 591             ((wxString
&)m_mapName
).Clear(); 
 592             return wxHtmlCell::GetLink( x
, y 
); 
 594         {   // dirty hack, ask Joel why he fills m_ImageMap in this place 
 595             // THE problem is that we're in const method and we can't modify m_ImageMap 
 596             wxHtmlImageMapCell 
**cx 
= (wxHtmlImageMapCell
**)(&m_imageMap
); 
 597             *cx 
= (wxHtmlImageMapCell
*)cell
; 
 600     return m_imageMap
->GetLink(x
, y
); 
 605 //-------------------------------------------------------------------------------- 
 607 //-------------------------------------------------------------------------------- 
 609 TAG_HANDLER_BEGIN(IMG
, "IMG,MAP,AREA") 
 610     TAG_HANDLER_CONSTR(IMG
) { } 
 612     TAG_HANDLER_PROC(tag
) 
 614         if (tag
.GetName() == wxT("IMG")) 
 616             if (tag
.HasParam(wxT("SRC"))) 
 618                 int w 
= wxDefaultCoord
, h 
= wxDefaultCoord
; 
 621                 wxString tmp 
= tag
.GetParam(wxT("SRC")); 
 622                 wxString mn 
= wxEmptyString
; 
 624                 str 
= m_WParser
->OpenURL(wxHTML_URL_IMAGE
, tmp
); 
 626                 if (tag
.HasParam(wxT("WIDTH"))) 
 627                     tag
.GetParamAsInt(wxT("WIDTH"), &w
); 
 628                 if (tag
.HasParam(wxT("HEIGHT"))) 
 629                     tag
.GetParamAsInt(wxT("HEIGHT"), &h
); 
 630                 al 
= wxHTML_ALIGN_BOTTOM
; 
 631                 if (tag
.HasParam(wxT("ALIGN"))) 
 633                     wxString alstr 
= tag
.GetParam(wxT("ALIGN")); 
 634                     alstr
.MakeUpper();  // for the case alignment was in ".." 
 635                     if (alstr 
== wxT("TEXTTOP")) 
 636                         al 
= wxHTML_ALIGN_TOP
; 
 637                     else if ((alstr 
== wxT("CENTER")) || (alstr 
== wxT("ABSCENTER"))) 
 638                         al 
= wxHTML_ALIGN_CENTER
; 
 640                 if (tag
.HasParam(wxT("USEMAP"))) 
 642                     mn 
= tag
.GetParam( wxT("USEMAP") ); 
 643                     if (mn
.GetChar(0) == wxT('#')) 
 648                 wxHtmlImageCell 
*cel 
= new wxHtmlImageCell( 
 649                                           m_WParser
->GetWindow(), 
 651                                           m_WParser
->GetPixelScale(), 
 653                 cel
->SetLink(m_WParser
->GetLink()); 
 654                 cel
->SetId(tag
.GetParam(wxT("id"))); // may be empty 
 655                 m_WParser
->GetContainer()->InsertCell(cel
); 
 660         if (tag
.GetName() == wxT("MAP")) 
 662             m_WParser
->CloseContainer(); 
 663             m_WParser
->OpenContainer(); 
 664             if (tag
.HasParam(wxT("NAME"))) 
 666                 wxString tmp 
= tag
.GetParam(wxT("NAME")); 
 667                 wxHtmlImageMapCell 
*cel 
= new wxHtmlImageMapCell( tmp 
); 
 668                 m_WParser
->GetContainer()->InsertCell( cel 
); 
 671             m_WParser
->CloseContainer(); 
 672             m_WParser
->OpenContainer(); 
 674         if (tag
.GetName() == wxT("AREA")) 
 676             if (tag
.HasParam(wxT("SHAPE"))) 
 678                 wxString tmp 
= tag
.GetParam(wxT("SHAPE")); 
 679                 wxString coords 
= wxEmptyString
; 
 681                 wxHtmlImageMapAreaCell 
*cel 
= NULL
; 
 682                 if (tag
.HasParam(wxT("COORDS"))) 
 684                     coords 
= tag
.GetParam(wxT("COORDS")); 
 686                 if (tmp 
== wxT("POLY")) 
 688                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY
, coords
, m_WParser
->GetPixelScale() ); 
 690                 else if (tmp 
== wxT("CIRCLE")) 
 692                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE
, coords
, m_WParser
->GetPixelScale() ); 
 694                 else if (tmp 
== wxT("RECT")) 
 696                     cel 
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT
, coords
, m_WParser
->GetPixelScale() ); 
 698                 if (cel 
!= NULL 
&& tag
.HasParam(wxT("HREF"))) 
 700                     wxString tmp 
= tag
.GetParam(wxT("HREF")); 
 701                     wxString target 
= wxEmptyString
; 
 702                     if (tag
.HasParam(wxT("TARGET"))) target 
= tag
.GetParam(wxT("TARGET")); 
 703                     cel
->SetLink( wxHtmlLinkInfo(tmp
, target
)); 
 705                 if (cel 
!= NULL
) m_WParser
->GetContainer()->InsertCell( cel 
); 
 716 TAGS_MODULE_BEGIN(Image
) 
 720 TAGS_MODULE_END(Image
)