Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGHtmlImage.cxx
Go to the documentation of this file.
1 // $Id: TGHtmlImage.cxx,v 1.2 2007/05/07 15:28:48 brun Exp $
2 // Author: Valeriy Onuchin 03/05/2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**************************************************************************
13 
14  HTML widget for xclass. Based on tkhtml 1.28
15  Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
16  Copyright (C) 2002-2003 Hector Peraza.
17 
18  This library is free software; you can redistribute it and/or
19  modify it under the terms of the GNU Library General Public
20  License as published by the Free Software Foundation; either
21  version 2 of the License, or (at your option) any later version.
22 
23  This library is distributed in the hope that it will be useful,
24  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26  Library General Public License for more details.
27 
28  You should have received a copy of the GNU Library General Public
29  License along with this library; if not, write to the Free
30  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 
32 **************************************************************************/
33 
34 // Routines used for processing <IMG> markup
35 
36 #include <string.h>
37 #include <stdlib.h>
38 
39 #include "TGHtml.h"
40 //#include <TGHtmlUri.h>
41 #include "TImage.h"
42 #include "TUrl.h"
43 #include "TSocket.h"
44 #include "TSystem.h"
45 #include "TError.h"
46 #ifdef R__SSL
47 #include "TSSLSocket.h"
48 #endif
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// ctor.
52 
53 TGHtmlImage::TGHtmlImage(TGHtml *htm, const char *url, const char *width,
54  const char *height)
55 {
56  fHtml = htm;
57  fZUrl = StrDup(url);
58  fZWidth = StrDup(width);
59  fZHeight = StrDup(height);
60  fImage = NULL;
61  fPNext = NULL;
62  fPList = NULL;
63  fW = 0;
64  fH = 0;
65  fTimer = NULL;
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// dtor.
70 
71 TGHtmlImage::~TGHtmlImage()
72 {
73  delete [] fZUrl;
74  delete [] fZWidth;
75  delete [] fZHeight;
76 
77  if (fImage) delete fImage;
78  if (fTimer) delete fTimer;
79 }
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Find the alignment for an image
83 
84 int TGHtml::GetImageAlignment(TGHtmlElement *p)
85 {
86  const char *z;
87  int i;
88  int result;
89 
90  static struct {
91  const char *zName;
92  int iValue;
93  } aligns[] = {
94  { "bottom", IMAGE_ALIGN_Bottom },
95  { "baseline", IMAGE_ALIGN_Bottom },
96  { "middle", IMAGE_ALIGN_Middle },
97  { "top", IMAGE_ALIGN_Top },
98  { "absbottom", IMAGE_ALIGN_AbsBottom },
99  { "absmiddle", IMAGE_ALIGN_AbsMiddle },
100  { "texttop", IMAGE_ALIGN_TextTop },
101  { "left", IMAGE_ALIGN_Left },
102  { "right", IMAGE_ALIGN_Right },
103  };
104 
105  z = p->MarkupArg("align", 0);
106  result = IMAGE_ALIGN_Bottom;
107  if (z) {
108  for (i = 0; i < int(sizeof(aligns) / sizeof(aligns[0])); i++) {
109  if (strcasecmp(aligns[i].zName, z) == 0) {
110  result = aligns[i].iValue;
111  break;
112  }
113  }
114  }
115  return result;
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
119 /// This routine is called when an image changes. If the size of the
120 /// images changes, then we need to completely redo the layout. If
121 /// only the appearance changes, then this works like an expose event.
122 ///
123 /// pImage - Pointer to an TGHtmlImage object
124 /// newWidth - New width of the image
125 /// newHeight - New height of the image
126 
127 void TGHtml::ImageChanged(TGHtmlImage *pImage, int newWidth, int newHeight)
128 {
129  TGHtmlImageMarkup *pElem;
130 
131  if (pImage->fW != newWidth || pImage->fH != newHeight) {
132  // We have to completely redo the layout after adjusting the size
133  // of the images
134  for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
135  pElem->fW = newWidth;
136  pElem->fH = newHeight;
137  }
138  fFlags |= RELAYOUT;
139  pImage->fW = newWidth;
140  pImage->fH = newHeight;
141  RedrawEverything();
142  } else {
143 #if 0
144  for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
145  pElem->fRedrawNeeded = 1;
146  }
147  fFlags |= REDRAW_IMAGES;
148  ScheduleRedraw();
149 #else
150  for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
151  pElem->fRedrawNeeded = 1;
152  DrawRegion(pElem->fX, pElem->fY - pElem->fAscent, pElem->fW, pElem->fH);
153  }
154 #endif
155  }
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Given an <IMG> markup, find or create an appropriate TGHtmlImage
160 /// object and return a pointer to that object. NULL might be returned.
161 
162 TGHtmlImage *TGHtml::GetImage(TGHtmlImageMarkup *p)
163 {
164  const char *zWidth;
165  const char *zHeight;
166  const char *zSrc;
167  TGHtmlImage *pImage;
168 
169  if (p->fType != Html_IMG) { CANT_HAPPEN; return 0; }
170 
171  zSrc = p->MarkupArg("src", 0);
172  if (zSrc == 0) return 0;
173 
174  zSrc = ResolveUri(zSrc);
175  if (zSrc == 0) return 0;
176 
177  zWidth = p->MarkupArg("width", "");
178  zHeight = p->MarkupArg("height", "");
179 
180  //p->w = atoi(fZWidth);
181  //p->h = atoi(zHeight);
182 
183  for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
184  if (strcmp(pImage->fZUrl, zSrc) == 0
185  && strcmp(pImage->fZWidth, zWidth) == 0
186  && strcmp(pImage->fZHeight, zHeight) == 0) {
187  delete [] zSrc;
188  return pImage;
189  }
190  }
191 
192  TImage *img = LoadImage(zSrc, atoi(zWidth), atoi(zHeight));
193 
194  if (img) {
195  pImage = new TGHtmlImage(this, zSrc, zWidth, zHeight);
196  pImage->fImage = img;
197  //if (img->IsAnimated()) {
198  // pImage->timer = new TTimer(this, img->GetAnimDelay());
199  //}
200  ImageChanged(pImage, img->GetWidth(), img->GetHeight());
201  pImage->fPNext = fImageList;
202  fImageList = pImage;
203  } else {
204  pImage = 0;
205  }
206 
207  delete [] zSrc;
208 
209  return pImage;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Temporary function to read remote pictures
214 
215 static TImage *ReadRemoteImage(const char *url)
216 {
217  TImage *image = 0;
218  FILE *tmp;
219  char *buf;
220  TUrl fUrl(url);
221 
222  TString msg = "GET ";
223  msg += fUrl.GetProtocol();
224  msg += "://";
225  msg += fUrl.GetHost();
226  msg += ":";
227  msg += fUrl.GetPort();
228  msg += "/";
229  msg += fUrl.GetFile();
230  msg += "\r\n";
231 
232  TString uri(url);
233  if ((!uri.BeginsWith("http://") && !uri.BeginsWith("https://")) ||
234  uri.EndsWith(".html"))
235  return 0;
236  TSocket *s;
237  if (uri.BeginsWith("https://")) {
238 #ifdef R__SSL
239  s = new TSSLSocket(fUrl.GetHost(), fUrl.GetPort());
240 #else
241  ::Error("ReadRemoteImage", "library compiled without SSL, https not supported");
242  return 0;
243 #endif
244  }
245  else {
246  s = new TSocket(fUrl.GetHost(), fUrl.GetPort());
247  }
248  if (!s->IsValid()) {
249  delete s;
250  return 0;
251  }
252  if (s->SendRaw(msg.Data(), msg.Length()) == -1) {
253  delete s;
254  return 0;
255  }
256  Int_t size = 1024*1024;
257  buf = (char *)calloc(size, sizeof(char));
258  if (!buf) {
259  delete s;
260  return 0;
261  }
262  if (s->RecvRaw(buf, size) == -1) {
263  free(buf);
264  delete s;
265  return 0;
266  }
267  TString pathtmp = TString::Format("%s/%s", gSystem->TempDirectory(),
268  gSystem->BaseName(url));
269  tmp = fopen(pathtmp.Data(), "wb");
270  if (!tmp) {
271  free(buf);
272  delete s;
273  return 0;
274  }
275  fwrite(buf, sizeof(char), size, tmp);
276  fclose(tmp);
277  free(buf);
278  image = TImage::Open(pathtmp.Data());
279  if (image && !image->IsValid()) {
280  delete image;
281  image = 0;
282  }
283  gSystem->Unlink(pathtmp.Data());
284  delete s;
285  return image;
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// This is the default LoadImage() procedure. It just tries to load the
290 /// image from a file in the local filesystem.
291 
292 TImage *TGHtml::LoadImage(const char *url, int w, int h)
293 {
294  TImage *image = 0;
295 
296  //TGHtmlUri uri(url);
297 
298  TString uri(url);
299  if ((uri.BeginsWith("http://") || uri.BeginsWith("https://")) &&
300  !uri.EndsWith(".html"))
301  image = ReadRemoteImage(url);
302  else
303  image = TImage::Open(url);
304  if (image) {
305  if (!image->IsValid()) {
306  delete image;
307  image = 0;
308  return 0;
309  }
310  if ((w > 0 && h > 0) && ((w != (int)image->GetWidth()) ||
311  (h != (int)image->GetHeight()))) {
312  image->Scale(w, h);
313  }
314  }
315  return image;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Return the height and width, converting to percent if required
320 /// ret must be at least 16 characters long
321 
322 const char *TGHtml::GetPctWidth(TGHtmlElement *p, char *opt, char *ret)
323 {
324  int n, m, val;
325  const char *tz, *z;
326  TGHtmlElement *pElem = p;
327 
328  z = pElem->MarkupArg(opt, "");
329  if (!z) return z;
330  if (!strchr(z, '%')) return z;
331  // coverity[secure_coding]
332  if (!sscanf(z, "%d", &n)) return z;
333  if (n <= 0 || n > 100) return z;
334  if (opt[0] == 'h') {
335  val = fCanvas->GetHeight() * 100;
336  } else {
337  val = fCanvas->GetWidth() * 100;
338  }
339  if (!fInTd) {
340  snprintf(ret, 15, "%d", val / n);
341  } else {
342  while (pElem && pElem->fType != Html_TD) pElem = pElem->fPPrev;
343  if (!pElem) return z;
344  tz = pElem->MarkupArg(opt, 0);
345  // coverity[secure_coding]
346  if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
347  snprintf(ret, 15, "%d", m * 100 / n);
348  return ret;
349  }
350  pElem = ((TGHtmlCell *)pElem)->fPTable;
351  if (!pElem) return z;
352  tz = pElem->MarkupArg(opt, 0);
353  // coverity[secure_coding]
354  if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
355  snprintf(ret, 15, "%d", m * 100 / n);
356  return ret;
357  }
358  return z;
359  }
360  return ret;
361 }
362 
363 ////////////////////////////////////////////////////////////////////////////////
364 /// This routine searchs for an image beneath the coordinates x,y
365 /// and returns the token number of the the image, or -1 if no
366 /// image found.
367 
368 int TGHtml::GetImageAt(int x, int y)
369 {
370  TGHtmlBlock *pBlock;
371  TGHtmlElement *pElem;
372  //int n;
373 
374  for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
375  if (pBlock->fTop > y || pBlock->fBottom < y ||
376  pBlock->fLeft > x || pBlock->fRight < x) {
377  continue;
378  }
379  for (pElem = pBlock->fPNext; pElem; pElem = pElem->fPNext) {
380  if (pBlock->fBNext && pElem == pBlock->fBNext->fPNext) break;
381  if (pElem->fType == Html_IMG) {
382  return TokenNumber(pElem);
383  }
384  }
385  }
386 
387  return -1;
388 }