]>
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"
42 FORCE_LINK_ME(m_image
)
47 WX_DECLARE_OBJARRAY(int, CoordArray
);
48 #include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
49 WX_DEFINE_OBJARRAY(CoordArray
);
52 //--------------------------------------------------------------------------------
53 // wxHtmlImageMapAreaCell
54 // 0-width, 0-height cell that represents single area in imagemap
55 // (it's GetLink is called from wxHtmlImageCell's)
56 //--------------------------------------------------------------------------------
58 class wxHtmlImageMapAreaCell
: public wxHtmlCell
61 enum celltype
{ CIRCLE
, RECT
, POLY
};
67 wxHtmlImageMapAreaCell( celltype t
, wxString
&coords
, double pixel_scale
= 1.0);
68 virtual wxHtmlLinkInfo
*GetLink( int x
= 0, int y
= 0 ) const;
75 wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t
, wxString
&incoords
, double pixel_scale
)
78 wxString x
= incoords
, y
;
81 while ((i
= x
.Find( ',' )) != -1)
83 coords
.Add( (int)(pixel_scale
* (double)wxAtoi( x
.Left( i
).c_str())) );
86 coords
.Add( (int)(pixel_scale
* (double)wxAtoi( x
.c_str())) );
89 wxHtmlLinkInfo
*wxHtmlImageMapAreaCell::GetLink( int x
, int y
) const
101 if (x
>= l
&& x
<= r
&& y
>= t
&& y
<= b
)
115 d
= sqrt( (double) (((x
- l
) * (x
- l
)) + ((y
- t
) * (y
- t
))) );
124 if (coords
.GetCount() >= 6)
129 int totalv
= coords
.GetCount() / 2;
130 int totalc
= totalv
* 2;
131 int xval
= coords
[totalc
- 2];
132 int yval
= coords
[totalc
- 1];
136 if ((yval
>= wherey
) != (coords
[pointer
] >= wherey
))
138 if ((xval
>= wherex
) == (coords
[0] >= wherex
))
140 intersects
+= (xval
>= wherex
) ? 1 : 0;
144 intersects
+= ((xval
- (yval
- wherey
) *
146 (coords
[pointer
] - yval
)) >= wherex
) ? 1 : 0;
150 while (pointer
< end
)
152 yval
= coords
[pointer
];
156 while ((pointer
< end
) && (coords
[pointer
] >= wherey
))
164 if ((coords
[pointer
- 3] >= wherex
) ==
165 (coords
[pointer
- 1] >= wherex
)) {
166 intersects
+= (coords
[pointer
- 3] >= wherex
) ? 1 : 0;
171 ((coords
[pointer
- 3] - (coords
[pointer
- 2] - wherey
) *
172 (coords
[pointer
- 1] - coords
[pointer
- 3]) /
173 (coords
[pointer
] - coords
[pointer
- 2])) >= wherex
) ? 1 : 0;
178 while ((pointer
< end
) && (coords
[pointer
] < wherey
))
186 if ((coords
[pointer
- 3] >= wherex
) ==
187 (coords
[pointer
- 1] >= wherex
))
189 intersects
+= (coords
[pointer
- 3] >= wherex
) ? 1 : 0;
194 ((coords
[pointer
- 3] - (coords
[pointer
- 2] - wherey
) *
195 (coords
[pointer
- 1] - coords
[pointer
- 3]) /
196 (coords
[pointer
] - coords
[pointer
- 2])) >= wherex
) ? 1 : 0;
200 if ((intersects
& 1) != 0)
211 wxHtmlImageMapAreaCell
*a
= (wxHtmlImageMapAreaCell
*)m_Next
;
212 return a
->GetLink( x
, y
);
224 //--------------------------------------------------------------------------------
225 // wxHtmlImageMapCell
226 // 0-width, 0-height cell that represents map from imagemaps
227 // it is always placed before wxHtmlImageMapAreaCells
228 // It responds to Find(wxHTML_COND_ISIMAGEMAP)
229 //--------------------------------------------------------------------------------
232 class wxHtmlImageMapCell
: public wxHtmlCell
235 wxHtmlImageMapCell( wxString
&name
);
239 virtual wxHtmlLinkInfo
*GetLink( int x
= 0, int y
= 0 ) const;
240 virtual const wxHtmlCell
*Find( int cond
, const void *param
) const;
244 wxHtmlImageMapCell::wxHtmlImageMapCell( wxString
&name
)
249 wxHtmlLinkInfo
*wxHtmlImageMapCell::GetLink( int x
, int y
) const
251 wxHtmlImageMapAreaCell
*a
= (wxHtmlImageMapAreaCell
*)m_Next
;
253 return a
->GetLink( x
, y
);
254 return wxHtmlCell::GetLink( x
, y
);
257 const wxHtmlCell
*wxHtmlImageMapCell::Find( int cond
, const void *param
) const
259 if (cond
== wxHTML_COND_ISIMAGEMAP
)
261 if (m_Name
== *((wxString
*)(param
)))
264 return wxHtmlCell::Find(cond
, param
);
271 //--------------------------------------------------------------------------------
274 //--------------------------------------------------------------------------------
276 class wxHtmlImageCell
: public wxHtmlCell
279 wxHtmlImageCell(wxWindow
*window
,
280 wxFSFile
*input
, int w
= -1, int h
= -1,
281 double scale
= 1.0, int align
= wxHTML_ALIGN_BOTTOM
,
282 const wxString
& mapname
= wxEmptyString
);
284 void Draw(wxDC
& dc
, int x
, int y
, int view_y1
, int view_y2
);
285 virtual wxHtmlLinkInfo
*GetLink(int x
= 0, int y
= 0) const;
287 void SetImage(const wxImage
& img
);
288 #if wxUSE_GIF && wxUSE_TIMER
289 void AdvanceAnimation(wxTimer
*timer
);
290 virtual void Layout(int w
);
297 wxScrolledWindow
*m_window
;
298 #if wxUSE_GIF && wxUSE_TIMER
299 wxGIFDecoder
*m_gifDecoder
;
301 int m_physX
, m_physY
;
304 wxHtmlImageMapCell
*m_imageMap
;
307 DECLARE_NO_COPY_CLASS(wxHtmlImageCell
)
310 #if wxUSE_GIF && wxUSE_TIMER
311 class wxGIFTimer
: public wxTimer
314 wxGIFTimer(wxHtmlImageCell
*cell
) : m_cell(cell
) {}
315 virtual void Notify()
317 m_cell
->AdvanceAnimation(this);
321 wxHtmlImageCell
*m_cell
;
323 DECLARE_NO_COPY_CLASS(wxGIFTimer
)
328 //--------------------------------------------------------------------------------
330 //--------------------------------------------------------------------------------
333 static const char * broken_image_xpm
[] = {
342 "..................... ",
343 ".+++++++++++++++++++.. ",
344 ".+++++++++++++++++++.@. ",
345 ".++@@@@@@@@@@@@@@@@@.+@. ",
346 ".++@@@@@@@@@@@@@@@@@.++@. ",
347 ".++@@@@@.@@@@.@@@@@@.+++@. ",
348 ".++@@@@@@@@@@@@@@@@@.++++@. ",
349 ".++@@@@@@@@@@@@@@@@@.+++++@. ",
350 ".++@@.@@@@@@@@@@.@@@######## ",
351 ".++@@@@@@@@@@@@@@@@@@$$$$$$#.",
352 ".######@@@@@@@@@@@@@@@.....#.",
353 " ###@@@@@@@@@@@@@@@++#.",
354 " #####@@@@@@@@@@++#.",
357 ".+.... #@@@@@@++#.",
358 ".++@@@... ####@@++#.",
359 ".++@@@@@@.. #####.",
362 ".++@@@@@@%%%%@@.... ",
363 ".++@@@@@@%%%%@@@@@@.... ",
364 ".++@@@@@@%%%%@@@@@@@@@@.... ",
365 ".++@@@@@@@@@@@@@@@@@@@@@@++#.",
366 ".++@@@@@@@@@@@@@@@@@@@@@@++#.",
367 ".++@@@@@@@@@@@@@@@@@@@@@@++#.",
368 ".++@@@@@@@@@@@@@@@@@@@@@@++#.",
369 ".++@@@@@@@@@@@@@@@@@@@@@@++#.",
370 ".++++++++++++++++++++++++++#.",
371 ".++++++++++++++++++++++++++#.",
372 "############################."};
374 wxHtmlImageCell::wxHtmlImageCell(wxWindow
*window
, wxFSFile
*input
,
375 int w
, int h
, double scale
, int align
,
376 const wxString
& mapname
) : wxHtmlCell()
378 m_window
= window
? wxStaticCast(window
, wxScrolledWindow
) : NULL
;
386 SetCanLiveOnPagebreak(FALSE
);
387 #if wxUSE_GIF && wxUSE_TIMER
390 m_physX
= m_physY
= -1;
393 if ( m_bmpW
&& m_bmpH
)
397 wxInputStream
*s
= input
->GetStream();
403 #if wxUSE_GIF && wxUSE_TIMER
404 if ( (input
->GetLocation().Matches(wxT("*.gif")) ||
405 input
->GetLocation().Matches(wxT("*.GIF"))) && m_window
)
407 m_gifDecoder
= new wxGIFDecoder(s
, TRUE
);
408 if ( m_gifDecoder
->ReadGIF() == wxGIF_OK
)
411 if ( m_gifDecoder
->ConvertToImage(&img
) )
416 if ( m_gifDecoder
->IsAnimation() )
418 m_gifTimer
= new wxGIFTimer(this);
419 m_gifTimer
->Start(m_gifDecoder
->GetDelay(), TRUE
);
423 wxDELETE(m_gifDecoder
);
428 wxDELETE(m_gifDecoder
);
433 #endif // wxUSE_GIF && wxUSE_TIMER
435 wxImage
image(*s
, wxBITMAP_TYPE_ANY
);
441 else // input==NULL, use "broken image" bitmap
443 if ( m_bmpW
== -1 && m_bmpH
== -1 )
451 if ( m_bmpW
== -1 ) m_bmpW
= 31;
452 if ( m_bmpH
== -1 ) m_bmpH
= 33;
454 m_bitmap
= new wxBitmap(broken_image_xpm
);
457 //else: ignore the 0-sized images used sometimes on the Web pages
459 m_Width
= (int)(scale
* (double)m_bmpW
);
460 m_Height
= (int)(scale
* (double)m_bmpH
);
464 case wxHTML_ALIGN_TOP
:
465 m_Descent
= m_Height
;
467 case wxHTML_ALIGN_CENTER
:
468 m_Descent
= m_Height
/ 2;
470 case wxHTML_ALIGN_BOTTOM
:
477 void wxHtmlImageCell::SetImage(const wxImage
& img
)
485 hh
= img
.GetHeight();
492 if ((m_bmpW
!= ww
) || (m_bmpH
!= hh
))
494 wxImage img2
= img
.Scale(m_bmpW
, m_bmpH
);
495 m_bitmap
= new wxBitmap(img2
);
498 m_bitmap
= new wxBitmap(img
);
502 #if wxUSE_GIF && wxUSE_TIMER
503 void wxHtmlImageCell::AdvanceAnimation(wxTimer
*timer
)
507 m_gifDecoder
->GoNextFrame(TRUE
);
511 m_physX
= m_physY
= 0;
512 for (wxHtmlCell
*cell
= this; cell
; cell
= cell
->GetParent())
514 m_physX
+= cell
->GetPosX();
515 m_physY
+= cell
->GetPosY();
520 m_window
->CalcScrolledPosition(m_physX
, m_physY
, &x
, &y
);
521 wxRect
rect(x
, y
, m_Width
, m_Height
);
523 if ( m_window
->GetClientRect().Intersects(rect
) &&
524 m_gifDecoder
->ConvertToImage(&img
) )
526 if ( (int)m_gifDecoder
->GetWidth() != m_Width
||
527 (int)m_gifDecoder
->GetHeight() != m_Height
||
528 m_gifDecoder
->GetLeft() != 0 || m_gifDecoder
->GetTop() != 0 )
532 dc
.SelectObject(*m_bitmap
);
533 dc
.DrawBitmap(bmp
, m_gifDecoder
->GetLeft(), m_gifDecoder
->GetTop());
537 m_window
->Refresh(img
.HasMask(), &rect
);
540 timer
->Start(m_gifDecoder
->GetDelay(), TRUE
);
543 void wxHtmlImageCell::Layout(int w
)
545 wxHtmlCell::Layout(w
);
546 m_physX
= m_physY
= -1;
551 wxHtmlImageCell::~wxHtmlImageCell()
554 #if wxUSE_GIF && wxUSE_TIMER
561 void wxHtmlImageCell::Draw(wxDC
& dc
, int x
, int y
, int WXUNUSED(view_y1
), int WXUNUSED(view_y2
))
565 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
566 dc
.SetPen(*wxBLACK_PEN
);
567 dc
.DrawRectangle(x
+ m_PosX
, y
+ m_PosY
, m_Width
, m_Height
);
573 dc
.GetUserScale(&us_x
, &us_y
);
574 dc
.SetUserScale(us_x
* m_scale
, us_y
* m_scale
);
576 dc
.DrawBitmap(*m_bitmap
, (int) ((x
+ m_PosX
) / m_scale
),
577 (int) ((y
+ m_PosY
) / m_scale
), TRUE
);
578 dc
.SetUserScale(us_x
, us_y
);
582 wxHtmlLinkInfo
*wxHtmlImageCell::GetLink( int x
, int y
) const
584 if (m_mapName
.IsEmpty())
585 return wxHtmlCell::GetLink( x
, y
);
588 wxHtmlContainerCell
*p
, *op
;
589 op
= p
= GetParent();
596 wxHtmlCell
*cell
= (wxHtmlCell
*)p
->Find(wxHTML_COND_ISIMAGEMAP
,
597 (const void*)(&m_mapName
));
600 ((wxString
&)m_mapName
).Clear();
601 return wxHtmlCell::GetLink( x
, y
);
603 { // dirty hack, ask Joel why he fills m_ImageMap in this place
604 // THE problem is that we're in const method and we can't modify m_ImageMap
605 wxHtmlImageMapCell
**cx
= (wxHtmlImageMapCell
**)(&m_imageMap
);
606 *cx
= (wxHtmlImageMapCell
*)cell
;
609 return m_imageMap
->GetLink(x
, y
);
614 //--------------------------------------------------------------------------------
616 //--------------------------------------------------------------------------------
618 TAG_HANDLER_BEGIN(IMG
, "IMG,MAP,AREA")
620 TAG_HANDLER_PROC(tag
)
622 if (tag
.GetName() == wxT("IMG"))
624 if (tag
.HasParam(wxT("SRC")))
629 wxString tmp
= tag
.GetParam(wxT("SRC"));
630 wxString mn
= wxEmptyString
;
632 str
= m_WParser
->OpenURL(wxHTML_URL_IMAGE
, tmp
);
634 if (tag
.HasParam(wxT("WIDTH")))
635 tag
.GetParamAsInt(wxT("WIDTH"), &w
);
636 if (tag
.HasParam(wxT("HEIGHT")))
637 tag
.GetParamAsInt(wxT("HEIGHT"), &h
);
638 al
= wxHTML_ALIGN_BOTTOM
;
639 if (tag
.HasParam(wxT("ALIGN")))
641 wxString alstr
= tag
.GetParam(wxT("ALIGN"));
642 alstr
.MakeUpper(); // for the case alignment was in ".."
643 if (alstr
== wxT("TEXTTOP"))
644 al
= wxHTML_ALIGN_TOP
;
645 else if ((alstr
== wxT("CENTER")) || (alstr
== wxT("ABSCENTER")))
646 al
= wxHTML_ALIGN_CENTER
;
648 if (tag
.HasParam(wxT("USEMAP")))
650 mn
= tag
.GetParam( wxT("USEMAP") );
651 if (mn
.GetChar(0) == wxT('#'))
656 wxHtmlImageCell
*cel
= new wxHtmlImageCell(
657 m_WParser
->GetWindow(),
659 m_WParser
->GetPixelScale(),
661 cel
->SetLink(m_WParser
->GetLink());
662 cel
->SetId(tag
.GetParam(wxT("id"))); // may be empty
663 m_WParser
->GetContainer()->InsertCell(cel
);
668 if (tag
.GetName() == wxT("MAP"))
670 m_WParser
->CloseContainer();
671 m_WParser
->OpenContainer();
672 if (tag
.HasParam(wxT("NAME")))
674 wxString tmp
= tag
.GetParam(wxT("NAME"));
675 wxHtmlImageMapCell
*cel
= new wxHtmlImageMapCell( tmp
);
676 m_WParser
->GetContainer()->InsertCell( cel
);
679 m_WParser
->CloseContainer();
680 m_WParser
->OpenContainer();
682 if (tag
.GetName() == wxT("AREA"))
684 if (tag
.HasParam(wxT("SHAPE")))
686 wxString tmp
= tag
.GetParam(wxT("SHAPE"));
687 wxString coords
= wxEmptyString
;
689 wxHtmlImageMapAreaCell
*cel
= NULL
;
690 if (tag
.HasParam(wxT("COORDS")))
692 coords
= tag
.GetParam(wxT("COORDS"));
694 if (tmp
== wxT("POLY"))
696 cel
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY
, coords
, m_WParser
->GetPixelScale() );
698 else if (tmp
== wxT("CIRCLE"))
700 cel
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE
, coords
, m_WParser
->GetPixelScale() );
702 else if (tmp
== wxT("RECT"))
704 cel
= new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT
, coords
, m_WParser
->GetPixelScale() );
706 if (cel
!= NULL
&& tag
.HasParam(wxT("HREF")))
708 wxString tmp
= tag
.GetParam(wxT("HREF"));
709 wxString target
= wxEmptyString
;
710 if (tag
.HasParam(wxT("TARGET"))) target
= tag
.GetParam(wxT("TARGET"));
711 cel
->SetLink( wxHtmlLinkInfo(tmp
, target
));
713 if (cel
!= NULL
) m_WParser
->GetContainer()->InsertCell( cel
);
724 TAGS_MODULE_BEGIN(Image
)
728 TAGS_MODULE_END(Image
)