]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/html/m_image.cpp
better learn the operators...
[wxWidgets.git] / src / html / m_image.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: m_image.cpp
3// Purpose: wxHtml module for displaying images
4// Author: Vaclav Slavik
5// RCS-ID: $Id$
6// Copyright: (c) 1999 Vaclav Slavik, Joel Lucsy
7// Licence: wxWindows Licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation
12#endif
13
14#include "wx/wxprec.h"
15
16#include "wx/defs.h"
17#if wxUSE_HTML && wxUSE_STREAMS
18
19#ifdef __BORDLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WXPRECOMP
24 #include "wx/dc.h"
25#endif
26
27#include "wx/html/forcelnk.h"
28#include "wx/html/m_templ.h"
29
30#include "wx/image.h"
31#include "wx/dynarray.h"
32
33#include <math.h>
34#include <float.h>
35
36FORCE_LINK_ME(m_image)
37
38
39
40
41WX_DECLARE_OBJARRAY(int, CoordArray);
42#include "wx/arrimpl.cpp" // this is a magic incantation which must be done!
43WX_DEFINE_OBJARRAY(CoordArray);
44
45
46//--------------------------------------------------------------------------------
47// wxHtmlImageMapAreaCell
48// 0-width, 0-height cell that represents single area in imagemap
49// (it's GetLink is called from wxHtmlImageCell's)
50//--------------------------------------------------------------------------------
51
52class wxHtmlImageMapAreaCell : public wxHtmlCell
53{
54 public:
55 enum celltype { CIRCLE, RECT, POLY };
56 protected:
57 CoordArray coords;
58 celltype type;
59 int radius;
60 public:
61 wxHtmlImageMapAreaCell( celltype t, wxString &coords, double pixel_scale = 1.0);
62 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
63};
64
65
66
67
68
69wxHtmlImageMapAreaCell::wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::celltype t, wxString &incoords, double pixel_scale )
70{
71 int i;
72 wxString x = incoords, y;
73
74 type = t;
75 while ((i = x.Find( ',' )) != -1)
76 {
77 coords.Add( (int)(pixel_scale * (double)wxAtoi( x.Left( i ).c_str())) );
78 x = x.Mid( i + 1 );
79 }
80 coords.Add( (int)(pixel_scale * (double)wxAtoi( x.c_str())) );
81}
82
83wxHtmlLinkInfo *wxHtmlImageMapAreaCell::GetLink( int x, int y ) const
84{
85 switch (type)
86 {
87 case RECT:
88 {
89 int l, t, r, b;
90
91 l = coords[ 0 ];
92 t = coords[ 1 ];
93 r = coords[ 2 ];
94 b = coords[ 3 ];
95 if (x >= l && x <= r && y >= t && y <= b)
96 {
97 return m_Link;
98 }
99 break;
100 }
101 case CIRCLE:
102 {
103 int l, t, r;
104 double d;
105
106 l = coords[ 0 ];
107 t = coords[ 1 ];
108 r = coords[ 2 ];
109 d = sqrt( (double) (((x - l) * (x - l)) + ((y - t) * (y - t))) );
110 if (d < (double)r)
111 {
112 return m_Link;
113 }
114 }
115 break;
116 case POLY:
117 {
118 if (coords.GetCount() >= 6)
119 {
120 int intersects = 0;
121 int wherex = x;
122 int wherey = y;
123 int totalv = coords.GetCount() / 2;
124 int totalc = totalv * 2;
125 int xval = coords[totalc - 2];
126 int yval = coords[totalc - 1];
127 int end = totalc;
128 int pointer = 1;
129
130 if ((yval >= wherey) != (coords[pointer] >= wherey))
131 {
132 if ((xval >= wherex) == (coords[0] >= wherex))
133 {
134 intersects += (xval >= wherex) ? 1 : 0;
135 }
136 else
137 {
138 intersects += ((xval - (yval - wherey) *
139 (coords[0] - xval) /
140 (coords[pointer] - yval)) >= wherex) ? 1 : 0;
141 }
142 }
143
144 while (pointer < end)
145 {
146 yval = coords[pointer];
147 pointer += 2;
148 if (yval >= wherey)
149 {
150 while ((pointer < end) && (coords[pointer] >= wherey))
151 {
152 pointer += 2;
153 }
154 if (pointer >= end)
155 {
156 break;
157 }
158 if ((coords[pointer - 3] >= wherex) ==
159 (coords[pointer - 1] >= wherex)) {
160 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
161 }
162 else
163 {
164 intersects +=
165 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
166 (coords[pointer - 1] - coords[pointer - 3]) /
167 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
168 }
169 }
170 else
171 {
172 while ((pointer < end) && (coords[pointer] < wherey))
173 {
174 pointer += 2;
175 }
176 if (pointer >= end)
177 {
178 break;
179 }
180 if ((coords[pointer - 3] >= wherex) ==
181 (coords[pointer - 1] >= wherex))
182 {
183 intersects += (coords[pointer - 3] >= wherex) ? 1 : 0;
184 }
185 else
186 {
187 intersects +=
188 ((coords[pointer - 3] - (coords[pointer - 2] - wherey) *
189 (coords[pointer - 1] - coords[pointer - 3]) /
190 (coords[pointer] - coords[pointer - 2])) >= wherex) ? 1 : 0;
191 }
192 }
193 }
194 if ((intersects & 1) != 0)
195 {
196 return m_Link;
197 }
198 }
199 }
200 break;
201 }
202
203 if (m_Next)
204 {
205 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
206 return a->GetLink( x, y );
207 }
208 return NULL;
209}
210
211
212
213
214
215
216
217
218//--------------------------------------------------------------------------------
219// wxHtmlImageMapCell
220// 0-width, 0-height cell that represents map from imagemaps
221// it is always placed before wxHtmlImageMapAreaCells
222// It responds to Find(wxHTML_COND_ISIMAGEMAP)
223//--------------------------------------------------------------------------------
224
225
226class wxHtmlImageMapCell : public wxHtmlCell
227{
228 public:
229 wxHtmlImageMapCell( wxString &name );
230 protected:
231 wxString m_Name;
232 public:
233 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
234 virtual const wxHtmlCell *Find( int cond, const void *param ) const;
235};
236
237
238wxHtmlImageMapCell::wxHtmlImageMapCell( wxString &name )
239{
240 m_Name = name ;
241}
242
243wxHtmlLinkInfo *wxHtmlImageMapCell::GetLink( int x, int y ) const
244{
245 wxHtmlImageMapAreaCell *a = (wxHtmlImageMapAreaCell*)m_Next;
246 if (a)
247 return a->GetLink( x, y );
248 return wxHtmlCell::GetLink( x, y );
249}
250
251const wxHtmlCell *wxHtmlImageMapCell::Find( int cond, const void *param ) const
252{
253 if (cond == wxHTML_COND_ISIMAGEMAP)
254 {
255 if (m_Name == *((wxString*)(param)))
256 return this;
257 }
258 return wxHtmlCell::Find(cond, param);
259}
260
261
262
263
264
265//--------------------------------------------------------------------------------
266// wxHtmlImageCell
267// Image/bitmap
268//--------------------------------------------------------------------------------
269
270class wxHtmlImageCell : public wxHtmlCell
271{
272 public:
273 wxBitmap *m_Image;
274 double m_Scale;
275 wxHtmlImageMapCell *m_ImageMap;
276 wxString m_MapName;
277
278 wxHtmlImageCell(wxFSFile *input, int w = -1, int h = -1, double scale = 1.0, int align = wxHTML_ALIGN_BOTTOM, wxString mapname = wxEmptyString);
279 ~wxHtmlImageCell() {if (m_Image) delete m_Image; }
280 void Draw(wxDC& dc, int x, int y, int view_y1, int view_y2);
281 virtual wxHtmlLinkInfo *GetLink( int x = 0, int y = 0 ) const;
282};
283
284
285
286
287//--------------------------------------------------------------------------------
288// wxHtmlImageCell
289//--------------------------------------------------------------------------------
290
291wxHtmlImageCell::wxHtmlImageCell(wxFSFile *input, int w, int h, double scale, int align, wxString mapname) : wxHtmlCell()
292{
293 wxImage *img;
294 int ww, hh, bw, bh;
295 wxInputStream *s = input->GetStream();
296
297 m_Scale = scale;
298 img = new wxImage(*s, wxBITMAP_TYPE_ANY);
299 m_Image = NULL;
300 if (img && (img->Ok()))
301 {
302 ww = img->GetWidth();
303 hh = img->GetHeight();
304 if (w != -1) bw = w; else bw = ww;
305 if (h != -1) bh = h; else bh = hh;
306
307 m_Width = (int)(scale * (double)bw);
308 m_Height = (int)(scale * (double)bh);
309
310 if ((bw != ww) || (bh != hh))
311 {
312 wxImage img2 = img->Scale(bw, bh);
313 m_Image = new wxBitmap(img2.ConvertToBitmap());
314 }
315 else
316 m_Image = new wxBitmap(img->ConvertToBitmap());
317 delete img;
318 }
319 switch (align)
320 {
321 case wxHTML_ALIGN_TOP :
322 m_Descent = m_Height;
323 break;
324 case wxHTML_ALIGN_CENTER :
325 m_Descent = m_Height / 2;
326 break;
327 case wxHTML_ALIGN_BOTTOM :
328 default :
329 m_Descent = 0;
330 break;
331 }
332
333 m_ImageMap = NULL;
334 m_MapName = mapname;
335 SetCanLiveOnPagebreak(FALSE);
336}
337
338
339
340void wxHtmlImageCell::Draw(wxDC& dc, int x, int y, int WXUNUSED(view_y1), int WXUNUSED(view_y2))
341{
342 if (m_Image)
343 {
344 double us_x, us_y;
345 dc.GetUserScale(&us_x, &us_y);
346 dc.SetUserScale(us_x * m_Scale, us_y * m_Scale);
347
348// dc.DrawBitmap(*m_Image, x + m_PosX, y + m_PosY, (m_Image->GetMask() != (wxMask*) 0));
349 dc.DrawBitmap(*m_Image, (int) ((x + m_PosX) / m_Scale),
350 (int) ((y + m_PosY) / m_Scale), TRUE);
351 dc.SetUserScale(us_x, us_y);
352 }
353}
354
355wxHtmlLinkInfo *wxHtmlImageCell::GetLink( int x, int y ) const
356{
357 if (m_MapName.IsEmpty())
358 return wxHtmlCell::GetLink( x, y );
359 if (!m_ImageMap)
360 {
361 wxHtmlContainerCell *p, *op;
362 op = p = GetParent();
363 while (p)
364 {
365 op = p;
366 p = p->GetParent();
367 }
368 p = op;
369 wxHtmlCell *cell = (wxHtmlCell*)p->Find( wxHTML_COND_ISIMAGEMAP, (const void*)(&m_MapName));
370 if (!cell)
371 {
372 ((wxString&)m_MapName).Clear();
373 return wxHtmlCell::GetLink( x, y );
374 }
375 { // dirty hack, ask Joel why he fills m_ImageMap in this place
376 // THE problem is that we're in const method and we can't modify m_ImageMap
377 wxHtmlImageMapCell **cx = (wxHtmlImageMapCell**)(&m_ImageMap);
378 *cx = (wxHtmlImageMapCell*)cell;
379 }
380 }
381 return m_ImageMap->GetLink( x, y );
382}
383
384
385
386//--------------------------------------------------------------------------------
387// tag handler
388//--------------------------------------------------------------------------------
389
390TAG_HANDLER_BEGIN(IMG, "IMG,MAP,AREA")
391
392 TAG_HANDLER_PROC(tag)
393 {
394 if (tag.GetName() == wxT("IMG"))
395 {
396 if (tag.HasParam(wxT("SRC")))
397 {
398 int w = -1, h = -1;
399 int al;
400 wxFSFile *str;
401 wxString tmp = tag.GetParam(wxT("SRC"));
402 wxString mn = wxEmptyString;
403
404 str = m_WParser->GetFS()->OpenFile(tmp);
405 if (tag.HasParam(wxT("WIDTH")))
406 tag.GetParamAsInt(wxT("WIDTH"), &w);
407 if (tag.HasParam(wxT("HEIGHT")))
408 tag.GetParamAsInt(wxT("HEIGHT"), &h);
409 al = wxHTML_ALIGN_BOTTOM;
410 if (tag.HasParam(wxT("ALIGN")))
411 {
412 wxString alstr = tag.GetParam(wxT("ALIGN"));
413 alstr.MakeUpper(); // for the case alignment was in ".."
414 if (alstr == wxT("TEXTTOP"))
415 al = wxHTML_ALIGN_TOP;
416 else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
417 al = wxHTML_ALIGN_CENTER;
418 }
419 if (tag.HasParam(wxT("USEMAP")))
420 {
421 mn = tag.GetParam( wxT("USEMAP") );
422 if (mn.GetChar(0) == wxT('#'))
423 {
424 mn = mn.Mid( 1 );
425 }
426 }
427 wxHtmlImageCell *cel = NULL;
428 if (str)
429 {
430 cel = new wxHtmlImageCell(str, w, h, m_WParser->GetPixelScale(), al, mn);
431 cel->SetLink(m_WParser->GetLink());
432 cel->SetId(tag.GetParam(wxT("id"))); // may be empty
433 m_WParser->GetContainer()->InsertCell(cel);
434 delete str;
435 }
436 }
437 }
438 if (tag.GetName() == wxT("MAP"))
439 {
440 m_WParser->CloseContainer();
441 m_WParser->OpenContainer();
442 if (tag.HasParam(wxT("NAME")))
443 {
444 wxString tmp = tag.GetParam(wxT("NAME"));
445 wxHtmlImageMapCell *cel = new wxHtmlImageMapCell( tmp );
446 m_WParser->GetContainer()->InsertCell( cel );
447 }
448 ParseInner( tag );
449 m_WParser->CloseContainer();
450 m_WParser->OpenContainer();
451 }
452 if (tag.GetName() == wxT("AREA"))
453 {
454 if (tag.HasParam(wxT("SHAPE")))
455 {
456 wxString tmp = tag.GetParam(wxT("SHAPE"));
457 wxString coords = wxEmptyString;
458 tmp.MakeUpper();
459 wxHtmlImageMapAreaCell *cel = NULL;
460 if (tag.HasParam(wxT("COORDS")))
461 {
462 coords = tag.GetParam(wxT("COORDS"));
463 }
464 if (tmp == wxT("POLY"))
465 {
466 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::POLY, coords, m_WParser->GetPixelScale() );
467 }
468 else if (tmp == wxT("CIRCLE"))
469 {
470 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::CIRCLE, coords, m_WParser->GetPixelScale() );
471 }
472 else if (tmp == wxT("RECT"))
473 {
474 cel = new wxHtmlImageMapAreaCell( wxHtmlImageMapAreaCell::RECT, coords, m_WParser->GetPixelScale() );
475 }
476 if (cel != NULL && tag.HasParam(wxT("HREF")))
477 {
478 wxString tmp = tag.GetParam(wxT("HREF"));
479 wxString target = wxEmptyString;
480 if (tag.HasParam(wxT("TARGET"))) target = tag.GetParam(wxT("TARGET"));
481 cel->SetLink( wxHtmlLinkInfo(tmp, target));
482 }
483 if (cel != NULL) m_WParser->GetContainer()->InsertCell( cel );
484 }
485 }
486
487 return FALSE;
488 }
489
490TAG_HANDLER_END(IMG)
491
492
493
494TAGS_MODULE_BEGIN(Image)
495
496 TAGS_MODULE_ADD(IMG)
497
498TAGS_MODULE_END(Image)
499
500
501#endif