// $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; }