// $Id: TGHtmlImage.cxx,v 1.2 2007/05/07 15:28:48 brun Exp $
// Author: Valeriy Onuchin 03/05/2007
/*************************************************************************
* Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
/**************************************************************************
HTML widget for xclass. Based on tkhtml 1.28
Copyright (C) 1997-2000 D. Richard Hipp
Copyright (C) 2002-2003 Hector Peraza.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************/
// Routines used for processing markup
#include
#include
#include "TGHtml.h"
//#include
#include "TImage.h"
#include "TUrl.h"
#include "TSocket.h"
#include "TSystem.h"
//______________________________________________________________________________
TGHtmlImage::TGHtmlImage(TGHtml *htm, const char *url, const char *width,
const char *height)
{
// ctor.
fHtml = htm;
fZUrl = StrDup(url);
fZWidth = StrDup(width);
fZHeight = StrDup(height);
fImage = NULL;
fPNext = NULL;
fPList = NULL;
fW = 0;
fH = 0;
fTimer = NULL;
}
//______________________________________________________________________________
TGHtmlImage::~TGHtmlImage()
{
// dtor.
delete [] fZUrl;
delete [] fZWidth;
delete [] fZHeight;
if (fImage) delete fImage;
if (fTimer) delete fTimer;
}
//______________________________________________________________________________
int TGHtml::GetImageAlignment(TGHtmlElement *p)
{
// Find the alignment for an image
const char *z;
int i;
int result;
static struct {
const char *zName;
int iValue;
} aligns[] = {
{ "bottom", IMAGE_ALIGN_Bottom },
{ "baseline", IMAGE_ALIGN_Bottom },
{ "middle", IMAGE_ALIGN_Middle },
{ "top", IMAGE_ALIGN_Top },
{ "absbottom", IMAGE_ALIGN_AbsBottom },
{ "absmiddle", IMAGE_ALIGN_AbsMiddle },
{ "texttop", IMAGE_ALIGN_TextTop },
{ "left", IMAGE_ALIGN_Left },
{ "right", IMAGE_ALIGN_Right },
};
z = p->MarkupArg("align", 0);
result = IMAGE_ALIGN_Bottom;
if (z) {
for (i = 0; i < int(sizeof(aligns) / sizeof(aligns[0])); i++) {
if (strcasecmp(aligns[i].zName, z) == 0) {
result = aligns[i].iValue;
break;
}
}
}
return result;
}
//______________________________________________________________________________
void TGHtml::ImageChanged(TGHtmlImage *pImage, int newWidth, int newHeight)
{
// This routine is called when an image changes. If the size of the
// images changes, then we need to completely redo the layout. If
// only the appearance changes, then this works like an expose event.
//
// pImage - Pointer to an TGHtmlImage object
// newWidth - New width of the image
// newHeight - New height of the image
TGHtmlImageMarkup *pElem;
if (pImage->fW != newWidth || pImage->fH != newHeight) {
// We have to completely redo the layout after adjusting the size
// of the images
for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
pElem->fW = newWidth;
pElem->fH = newHeight;
}
fFlags |= RELAYOUT;
pImage->fW = newWidth;
pImage->fH = newHeight;
RedrawEverything();
} else {
#if 0
for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
pElem->fRedrawNeeded = 1;
}
fFlags |= REDRAW_IMAGES;
ScheduleRedraw();
#else
for (pElem = pImage->fPList; pElem; pElem = pElem->fINext) {
pElem->fRedrawNeeded = 1;
DrawRegion(pElem->fX, pElem->fY - pElem->fAscent, pElem->fW, pElem->fH);
}
#endif
}
}
//______________________________________________________________________________
TGHtmlImage *TGHtml::GetImage(TGHtmlImageMarkup *p)
{
// Given an markup, find or create an appropriate TGHtmlImage
// object and return a pointer to that object. NULL might be returned.
const char *zWidth;
const char *zHeight;
const char *zSrc;
TGHtmlImage *pImage;
if (p->fType != Html_IMG) { CANT_HAPPEN; return 0; }
zSrc = p->MarkupArg("src", 0);
if (zSrc == 0) return 0;
zSrc = ResolveUri(zSrc);
if (zSrc == 0) return 0;
zWidth = p->MarkupArg("width", "");
zHeight = p->MarkupArg("height", "");
//p->w = atoi(fZWidth);
//p->h = atoi(zHeight);
for (pImage = fImageList; pImage; pImage = pImage->fPNext) {
if (strcmp(pImage->fZUrl, zSrc) == 0
&& strcmp(pImage->fZWidth, zWidth) == 0
&& strcmp(pImage->fZHeight, zHeight) == 0) {
delete [] zSrc;
return pImage;
}
}
TImage *img = LoadImage(zSrc, atoi(zWidth), atoi(zHeight));
if (img) {
pImage = new TGHtmlImage(this, zSrc, zWidth, zHeight);
pImage->fImage = img;
//if (img->IsAnimated()) {
// pImage->timer = new TTimer(this, img->GetAnimDelay());
//}
ImageChanged(pImage, img->GetWidth(), img->GetHeight());
pImage->fPNext = fImageList;
fImageList = pImage;
} else {
pImage = 0;
}
delete [] zSrc;
return pImage;
}
//______________________________________________________________________________
static TImage *ReadRemoteImage(const char *url)
{
// Temporary function to read remote pictures
TImage *image = 0;
FILE *tmp;
char *buf;
TUrl fUrl(url);
TString msg = "GET ";
msg += fUrl.GetProtocol();
msg += "://";
msg += fUrl.GetHost();
msg += ":";
msg += fUrl.GetPort();
msg += "/";
msg += fUrl.GetFile();
msg += "\r\n";
TString uri(url);
if (!uri.BeginsWith("http://") || uri.EndsWith(".html"))
return 0;
TSocket s(fUrl.GetHost(), fUrl.GetPort());
if (!s.IsValid())
return 0;
if (s.SendRaw(msg.Data(), msg.Length()) == -1)
return 0;
Int_t size = 1024*1024;
buf = (char *)calloc(size, sizeof(char));
if (!buf) return 0;
if (s.RecvRaw(buf, size) == -1) {
free(buf);
return 0;
}
TString pathtmp = TString::Format("%s/%s", gSystem->TempDirectory(),
gSystem->BaseName(url));
tmp = fopen(pathtmp.Data(), "wb");
if (!tmp) {
free(buf);
return 0;
}
fwrite(buf, sizeof(char), size, tmp);
fclose(tmp);
free(buf);
image = TImage::Open(pathtmp.Data());
if (image && !image->IsValid()) {
delete image;
image = 0;
}
gSystem->Unlink(pathtmp.Data());
return image;
}
//______________________________________________________________________________
TImage *TGHtml::LoadImage(const char *url, int w, int h)
{
// This is the default LoadImage() procedure. It just tries to load the
// image from a file in the local filesystem.
TImage *image = 0;
//TGHtmlUri uri(url);
TString uri(url);
if (uri.BeginsWith("http://") && !uri.EndsWith(".html"))
image = ReadRemoteImage(url);
else
image = TImage::Open(url);
if (image) {
if (!image->IsValid()) {
delete image;
image = 0;
return 0;
}
if ((w > 0 && h > 0) && ((w != (int)image->GetWidth()) ||
(h != (int)image->GetHeight()))) {
image->Scale(w, h);
}
}
return image;
}
//______________________________________________________________________________
const char *TGHtml::GetPctWidth(TGHtmlElement *p, char *opt, char *ret)
{
// Return the height and width, converting to percent if required
// ret must be at least 16 characters long
int n, m, val;
const char *tz, *z;
TGHtmlElement *pElem = p;
z = pElem->MarkupArg(opt, "");
if (!z) return z;
if (!strchr(z, '%')) return z;
// coverity[secure_coding]
if (!sscanf(z, "%d", &n)) return z;
if (n < 0 || n > 100) return z;
if (opt[0] == 'h') {
val = fCanvas->GetHeight() * 100;
} else {
val = fCanvas->GetWidth() * 100;
}
if (!fInTd) {
snprintf(ret, 15, "%d", val / n);
} else {
while (pElem && pElem->fType != Html_TD) pElem = pElem->fPPrev;
if (!pElem) return z;
tz = pElem->MarkupArg(opt, 0);
// coverity[secure_coding]
if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
snprintf(ret, 15, "%d", m * 100 / n);
return ret;
}
pElem = ((TGHtmlCell *)pElem)->fPTable;
if (!pElem) return z;
tz = pElem->MarkupArg(opt, 0);
// coverity[secure_coding]
if (tz && !strchr(tz, '%') && sscanf(tz, "%d", &m)) {
snprintf(ret, 15, "%d", m * 100 / n);
return ret;
}
return z;
}
return ret;
}
//______________________________________________________________________________
int TGHtml::GetImageAt(int x, int y)
{
// This routine searchs for an image beneath the coordinates x,y
// and returns the token number of the the image, or -1 if no
// image found.
TGHtmlBlock *pBlock;
TGHtmlElement *pElem;
//int n;
for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
if (pBlock->fTop > y || pBlock->fBottom < y ||
pBlock->fLeft > x || pBlock->fRight < x) {
continue;
}
for (pElem = pBlock->fPNext; pElem; pElem = pElem->fPNext) {
if (pBlock->fBNext && pElem == pBlock->fBNext->fPNext) break;
if (pElem->fType == Html_IMG) {
return TokenNumber(pElem);
}
}
}
return -1;
}