TGHtmlDraw.cxx

Go to the documentation of this file.
00001 // $Id: TGHtmlDraw.cxx,v 1.1 2007/05/04 17:07:01 brun Exp $
00002 // Author:  Valeriy Onuchin   03/05/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /**************************************************************************
00013 
00014     HTML widget for xclass. Based on tkhtml 1.28
00015     Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
00016     Copyright (C) 2002-2003 Hector Peraza.
00017 
00018     This library is free software; you can redistribute it and/or
00019     modify it under the terms of the GNU Library General Public
00020     License as published by the Free Software Foundation; either
00021     version 2 of the License, or (at your option) any later version.
00022 
00023     This library is distributed in the hope that it will be useful,
00024     but WITHOUT ANY WARRANTY; without even the implied warranty of
00025     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026     Library General Public License for more details.
00027 
00028     You should have received a copy of the GNU Library General Public
00029     License along with this library; if not, write to the Free
00030     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00031 
00032 **************************************************************************/
00033 
00034 // Routines used to render HTML onto the screen for the TGHtml widget.
00035 
00036 #include <string.h>
00037 #include <stdlib.h>
00038 
00039 #include "TGHtml.h"
00040 #include "TImage.h"
00041 
00042 
00043 //______________________________________________________________________________
00044 TGHtmlBlock::TGHtmlBlock() : TGHtmlElement(Html_Block)
00045 {
00046    // ctor.
00047 
00048    fZ = NULL;
00049    fTop = fBottom = 0;
00050    fLeft = fRight = 0;
00051    fN = 0;
00052    fPPrev = fPNext = 0;
00053 }
00054 
00055 //______________________________________________________________________________
00056 TGHtmlBlock::~TGHtmlBlock()
00057 {
00058    // dtor.
00059 
00060    if (fZ) delete[] fZ;
00061 }
00062 
00063 //______________________________________________________________________________
00064 void TGHtml::UnlinkAndFreeBlock(TGHtmlBlock *pBlock)
00065 {
00066    // Destroy the given Block after first unlinking it from the element list.
00067    // Note that this unlinks the block from the element list only -- not from
00068    // the block list.
00069 
00070    if (pBlock->fPNext) {
00071       pBlock->fPNext->fPPrev = pBlock->fPPrev;
00072    } else {
00073       fPLast = pBlock->fPPrev;
00074    }
00075    if (pBlock->fPPrev) {
00076       pBlock->fPPrev->fPNext = pBlock->fPNext;
00077    } else {
00078       fPFirst = pBlock->fPNext;
00079    }
00080    pBlock->fPPrev = pBlock->fPNext = 0;
00081    delete pBlock;
00082 }
00083 
00084 //______________________________________________________________________________
00085 void TGHtml::AppendBlock(TGHtmlElement *pToken, TGHtmlBlock *pBlock)
00086 {
00087    // Append a block to the block list and insert the block into the
00088    // element list immediately prior to the element given.
00089    //
00090    // pToken - The token that comes after pBlock
00091    // pBlock - The block to be appended
00092 
00093    pBlock->fPPrev = pToken->fPPrev;
00094    pBlock->fPNext = pToken;
00095    pBlock->fBPrev = fLastBlock;
00096    pBlock->fBNext = 0;
00097    if (fLastBlock) {
00098       fLastBlock->fBNext = pBlock;
00099    } else {
00100       fFirstBlock = pBlock;
00101    }
00102    fLastBlock = pBlock;
00103    if (pToken->fPPrev) {
00104       pToken->fPPrev->fPNext = (TGHtmlElement *) pBlock;
00105    } else {
00106       fPFirst = (TGHtmlElement *) pBlock;
00107    }
00108    pToken->fPPrev = (TGHtmlElement *) pBlock;
00109 }
00110 
00111 //______________________________________________________________________________
00112 static void GetLetterIndex(char *zBuf, int index, int isUpper)
00113 {
00114    // Print an ordered list index into the given buffer. Use numbering
00115    // like this:
00116    //
00117    //     A  B  C ... Y Z AA BB CC ... ZZ
00118    //
00119    // Revert to decimal for indices greater than 52.
00120 
00121    int seed;
00122 
00123    if (index < 1 || index > 52) {
00124       sprintf(zBuf, "%d", index);
00125       return;
00126    }
00127 
00128    if (isUpper) {
00129       seed = 'A';
00130    } else {
00131       seed = 'a';
00132    }
00133 
00134    index--;
00135 
00136    if (index < 26) {
00137       zBuf[0] = seed + index;
00138       zBuf[1] = 0;
00139    } else {
00140       index -= 26;
00141       zBuf[0] = seed + index;
00142       zBuf[1] = seed + index;
00143       zBuf[2] = 0;
00144    }
00145 
00146    strcat(zBuf, ".");
00147 }
00148 
00149 //______________________________________________________________________________
00150 static void GetRomanIndex(char *zBuf, int index, int isUpper)
00151 {
00152    // Print an ordered list index into the given buffer.  Use roman
00153    // numerals.  For indices greater than a few thousand, revert to
00154    // decimal.
00155 
00156    int i = 0;
00157    UInt_t j;
00158 
00159    static struct {
00160       int value;
00161       const char *name;
00162    } values[] = {
00163       { 1000, "m"  },
00164       {  999, "im" },
00165       {  990, "xm" },
00166       {  900, "cm" },
00167       {  500, "d"  },
00168       {  499, "id" },
00169       {  490, "xd" },
00170       {  400, "cd" },
00171       {  100, "c"  },
00172       {   99, "ic" },
00173       {   90, "xc" },
00174       {   50, "l"  },
00175       {   49, "il" },
00176       {   40, "xl" },
00177       {   10, "x"  },
00178       {    9, "ix" },
00179       {    5, "v"  },
00180       {    4, "iv" },
00181       {    1, "i"  },
00182    };
00183 
00184    if (index < 1 || index >= 5000) {
00185       sprintf(zBuf, "%d", index);
00186       return;
00187    }
00188    for (j = 0; index > 0 && j < sizeof(values)/sizeof(values[0]); j++) {
00189       int k;
00190       while (index >= values[j].value) {
00191          for (k = 0; values[j].name[k]; k++) {
00192             zBuf[i++] = values[j].name[k];
00193          }
00194          index -= values[j].value;
00195       }
00196    }
00197    zBuf[i] = 0;
00198    if (isUpper) {
00199       for (i = 0; zBuf[i]; i++) {
00200          zBuf[i] += 'A' - 'a';
00201       }
00202    }
00203 
00204    strcat(zBuf, ".");
00205 }
00206 
00207 //______________________________________________________________________________
00208 void TGHtml::DrawSelectionBackground(TGHtmlBlock *pBlock, Drawable_t drawable,
00209                                      int x, int y)
00210 {
00211    // Draw the selection background for the given block
00212    //
00213    // x, y - Virtual coords of top-left of drawable
00214 
00215    int xLeft, xRight;        // Left and right bounds of box to draw
00216    int yTop, yBottom;        // Top and bottom of box
00217    TGHtmlElement *p = 0;     // First element of the block
00218    TGFont *font=0;           // Font
00219    GContext_t gc;            // GC for drawing
00220 
00221    if (pBlock == 0 || (pBlock->fFlags & HTML_Selected) == 0) return;
00222 
00223    xLeft = pBlock->fLeft - x;
00224    if (pBlock == fPSelStartBlock && fSelStartIndex > 0) {
00225       if (fSelStartIndex >= pBlock->fN) return;
00226       p = pBlock->fPNext;
00227       font = GetFont(p->fStyle.fFont);
00228       if (font == 0) return;
00229       if (p->fType == Html_Text) {
00230          TGHtmlTextElement *tp = (TGHtmlTextElement *) p;
00231          xLeft = tp->fX - x + font->TextWidth(pBlock->fZ, fSelStartIndex);
00232       }
00233    }
00234    xRight = pBlock->fRight - x;
00235    if (pBlock == fPSelEndBlock && fSelEndIndex < pBlock->fN) {
00236       if (p == 0) {
00237          p = pBlock->fPNext;
00238          font = GetFont(p->fStyle.fFont);
00239          if (font == 0) return;
00240       }
00241       if (p->fType == Html_Text) {
00242          TGHtmlTextElement *tp = (TGHtmlTextElement *) p;
00243          xRight = tp->fX - x + font->TextWidth(pBlock->fZ, fSelEndIndex);
00244       }
00245    }
00246    yTop = pBlock->fTop - y;
00247    yBottom = pBlock->fBottom - y;
00248    gc = GetGC(COLOR_Selection, FONT_Any);
00249    Int_t xx = xLeft;
00250    Int_t yy = yTop;
00251    UInt_t width = xRight - xLeft;
00252    UInt_t height = yBottom - yTop;
00253    gVirtualX->FillRectangle(drawable, gc, xx, yy, width, height);
00254 }
00255 
00256 //______________________________________________________________________________
00257 void TGHtml::DrawRect(Drawable_t drawable, TGHtmlElement *src,
00258                       int x, int y, int w, int h, int depth, int relief)
00259 {
00260    // Draw a rectangle. The rectangle will have a 3-D appearance if
00261    // flat is 0 and a flat appearance if flat is 1.
00262    //
00263    // depth - width of the relief or the flat line
00264 
00265    Int_t xx, yy;
00266    UInt_t width, height;
00267 
00268    if (depth > 0) {
00269       int i;
00270       GContext_t gcLight, gcDark;
00271 
00272       if (relief != HTML_RELIEF_FLAT) {
00273          int iLight1, iDark1;
00274          iLight1 = GetLightShadowColor(src->fStyle.fBgcolor);
00275          gcLight = GetGC(iLight1, FONT_Any);
00276          iDark1 = GetDarkShadowColor(src->fStyle.fBgcolor);
00277          gcDark = GetGC(iDark1, FONT_Any);
00278          if (relief == HTML_RELIEF_SUNKEN) {
00279             GContext_t gcTemp = gcLight;
00280             gcLight = gcDark;
00281             gcDark = gcTemp;
00282          }
00283       } else {
00284          gcLight = GetGC(src->fStyle.fColor, FONT_Any);
00285          gcDark = gcLight;
00286       }
00287       xx = x;
00288       yy = y;
00289       width = depth;
00290       height = h;
00291       gVirtualX->FillRectangle(drawable, gcLight, xx, yy, width, height);
00292       xx = x + w - depth;
00293       gVirtualX->FillRectangle(drawable, gcLight, xx, yy, width, height);
00294       for (i = 0; i < depth && i < h/2; i++) {
00295          gVirtualX->DrawLine(drawable, gcLight, x+i, y+i, x+w-i-1, y+i);
00296          gVirtualX->DrawLine(drawable, gcDark, x+i, y+h-i-1, x+w-i-1, y+h-i-1);
00297       }
00298    }
00299    if (h > depth*2 && w > depth*2) {
00300       GContext_t gcBg;
00301       gcBg = GetGC(src->fStyle.fBgcolor, FONT_Any);
00302       xx = x + depth;
00303       yy = y + depth;
00304       width = w - depth*2;
00305       height = h - depth*2;
00306       gVirtualX->FillRectangle(drawable, gcBg, xx, yy, width, height);
00307    }
00308 }
00309 
00310 //______________________________________________________________________________
00311 void TGHtml::BlockDraw(TGHtmlBlock *pBlock, Drawable_t drawable,
00312                        int drawableLeft, int drawableTop,
00313                        int drawableWidth, int drawableHeight,
00314                        Pixmap_t pixmap)
00315 {
00316    // Display a single HtmlBlock. This is where all the drawing happens.
00317 
00318    TGFont *font;           // Font to use to render text
00319    GContext_t gc;          // A graphics context
00320    TGHtmlElement *src;     // TGHtmlElement holding style information
00321    TGHtmlTable *pTable;    // The table (when drawing part of a table)
00322    Int_t x, y;             // Where to draw
00323    UInt_t width, height;
00324 
00325    if (pBlock == 0) return;
00326 
00327    src = pBlock->fPNext;
00328    while (src && (src->fFlags & HTML_Visible) == 0) src = src->fPNext;
00329 
00330    if (src == 0) return;
00331 
00332    if (pBlock->fN > 0) {
00333       // We must be dealing with plain old text
00334       if (src->fType == Html_Text) {
00335          TGHtmlTextElement *tsrc = (TGHtmlTextElement *) src;
00336          x = tsrc->fX;
00337          y = tsrc->fY;
00338       } else {
00339          CANT_HAPPEN;
00340          return;
00341       }
00342       if (pBlock->fFlags & HTML_Selected) {
00343          DrawSelectionBackground(pBlock, drawable, drawableLeft, drawableTop);
00344       }
00345       gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
00346       font = GetFont(src->fStyle.fFont);
00347       if (font == 0) return;
00348       font->DrawChars(drawable, gc, pBlock->fZ, pBlock->fN,
00349                       x - drawableLeft, y - drawableTop);
00350       if (src->fStyle.fFlags & STY_Underline) {
00351          font->UnderlineChars(drawable, gc, pBlock->fZ,
00352                               x - drawableLeft, y-drawableTop, 0, pBlock->fN);
00353       }
00354       if (src->fStyle.fFlags & STY_StrikeThru) {
00355          x = pBlock->fLeft - drawableLeft;
00356          y = (pBlock->fTop + pBlock->fBottom) / 2 - drawableTop;
00357          width = pBlock->fRight - pBlock->fLeft;
00358          height = 1 + (pBlock->fBottom - pBlock->fTop > 15);
00359          gVirtualX->FillRectangle(drawable, gc, x, y, width, height);
00360       }
00361       if (pBlock == fPInsBlock && fInsStatus > 0) {
00362          if (fInsIndex < pBlock->fN) {
00363             TGHtmlTextElement *tsrc = (TGHtmlTextElement *) src;
00364             x = tsrc->fX - drawableLeft;
00365             x += font->TextWidth(pBlock->fZ, fInsIndex);
00366          } else {
00367             x = pBlock->fRight - drawableLeft;
00368          }
00369          if (x > 0) --x;
00370             gVirtualX->FillRectangle(drawable, gc, x, pBlock->fTop - drawableTop,
00371                                      2, pBlock->fBottom - pBlock->fTop);
00372          }
00373    } else {
00374       // We are dealing with a single TGHtmlElement which contains something
00375       // other than plain text.
00376       int cnt, w;
00377       char zBuf[30];
00378       TGHtmlLi *li;
00379       TGHtmlImageMarkup *image;
00380       switch (src->fType) {
00381          case Html_LI:
00382             li = (TGHtmlLi *) src;
00383             x = li->fX;
00384             y = li->fY;
00385             switch (li->fLtype) {
00386                case LI_TYPE_Enum_1:
00387                   sprintf(zBuf, "%d.", li->fCnt);
00388                   break;
00389                case LI_TYPE_Enum_A:
00390                   GetLetterIndex(zBuf, li->fCnt, 1);
00391                   break;
00392                case LI_TYPE_Enum_a:
00393                   GetLetterIndex(zBuf, li->fCnt, 0);
00394                   break;
00395                case LI_TYPE_Enum_I:
00396                   GetRomanIndex(zBuf, li->fCnt, 1);
00397                   break;
00398                case LI_TYPE_Enum_i:
00399                   GetRomanIndex(zBuf, li->fCnt, 0);
00400                   break;
00401                default:
00402                   zBuf[0] = 0;
00403                   break;
00404             }
00405             gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
00406             switch (li->fLtype) {
00407                case LI_TYPE_Undefined:
00408                case LI_TYPE_Bullet1:
00409                   //gVirtualX->FillArc(drawable, gc,
00410                   //         x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7,
00411                   //         0, 360*64);
00412                   break;
00413 
00414                case LI_TYPE_Bullet2:
00415                   //gVirtualX->DrawArc(drawable, gc,
00416                   //         x - 7 - drawableLeft, y - 8 - drawableTop, 7, 7,
00417                   //         0, 360*64);
00418                   break;
00419 
00420                case LI_TYPE_Bullet3:
00421                      gVirtualX->DrawRectangle(drawable, gc, x - 7 - drawableLeft,
00422                                               y - 8 - drawableTop, 7, 7);
00423                   break;
00424           
00425                case LI_TYPE_Enum_1:
00426                case LI_TYPE_Enum_A:
00427                case LI_TYPE_Enum_a:
00428                case LI_TYPE_Enum_I:
00429                case LI_TYPE_Enum_i:
00430                   cnt = strlen(zBuf);
00431                   font = GetFont(src->fStyle.fFont);
00432                   if (font == 0) return;
00433                   w = font->TextWidth(zBuf, cnt);
00434                   font->DrawChars(drawable, gc, zBuf, cnt, 
00435                                   x - w - drawableLeft, y - drawableTop);
00436                   break;
00437             }
00438             break;
00439 
00440          case Html_HR: {
00441             TGHtmlHr *hr = (TGHtmlHr *) src;
00442             int relief = fRuleRelief;
00443             switch (relief) {
00444                case HTML_RELIEF_RAISED: 
00445                case HTML_RELIEF_SUNKEN:
00446                break;
00447                default:
00448                   relief = HTML_RELIEF_FLAT;
00449                   break;
00450             }
00451             DrawRect(drawable, src, hr->fX - drawableLeft, hr->fY - drawableTop,
00452                      hr->fW, hr->fH, 1, relief);
00453             break;
00454          }
00455 
00456          case Html_TABLE: {
00457             TGHtmlTable *table = (TGHtmlTable *) src;
00458             int relief = fTableRelief;
00459             if ((!fBgImage || src->fStyle.fExpbg) && !table->fHasbg) {
00460                switch (relief) {
00461                   case HTML_RELIEF_RAISED: 
00462                   case HTML_RELIEF_SUNKEN:
00463                      break;
00464                   default:
00465                      relief = HTML_RELIEF_FLAT;
00466                      break;
00467                }
00468 
00469                DrawRect(drawable, src, table->fX - drawableLeft,
00470                         table->fY - drawableTop, table->fW, table->fH, 
00471                         table->fBorderWidth, relief);
00472             }
00473 
00474             if (table->fBgImage) {
00475                DrawTableBgnd(table->fX, table->fY, table->fW, table->fH, pixmap,
00476                              table->fBgImage);
00477             }
00478             break;
00479          }
00480 
00481          case Html_TH:
00482          case Html_TD: {
00483             TGHtmlCell *cell = (TGHtmlCell *) src;
00484             int depth, relief;
00485             TImage *bgImg;
00486             pTable = cell->fPTable;
00487             if ((!fBgImage || src->fStyle.fExpbg) && !(pTable && pTable->fHasbg)) {
00488                depth = pTable && (pTable->fBorderWidth > 0);
00489                switch (fTableRelief) {
00490                   case HTML_RELIEF_RAISED:  relief = HTML_RELIEF_SUNKEN; break;
00491                   case HTML_RELIEF_SUNKEN:  relief = HTML_RELIEF_RAISED; break;
00492                   default:                  relief = HTML_RELIEF_FLAT;   break;
00493                }
00494                DrawRect(drawable, src,
00495                         cell->fX - drawableLeft, cell->fY - drawableTop,
00496                         cell->fW, cell->fH, depth, relief);
00497             }
00498             // See if row has an image
00499             if (cell->fBgImage) {
00500                DrawTableBgnd(cell->fX, cell->fY, cell->fW, cell->fH, pixmap,
00501                              cell->fBgImage);
00502             } else if (cell->fPRow && (bgImg = ((TGHtmlRef *)cell->fPRow)->fBgImage)) {
00503                DrawTableBgnd(cell->fX, cell->fY, cell->fW, cell->fH, pixmap, bgImg);
00504             }
00505             break;
00506          }
00507 
00508          case Html_IMG:
00509             image = (TGHtmlImageMarkup *) src;
00510             if (image->fPImage) {
00511                DrawImage(image, drawable, drawableLeft, drawableTop,
00512                          drawableLeft + drawableWidth,
00513                          drawableTop + drawableHeight);
00514             } else if (image->fZAlt) {
00515                gc = GetGC(src->fStyle.fColor, src->fStyle.fFont);
00516                font = GetFont(src->fStyle.fFont);
00517                if (font == 0) return;
00518                font->DrawChars(drawable, gc,
00519                                image->fZAlt, strlen(image->fZAlt),
00520                                image->fX - drawableLeft, 
00521                                image->fY - drawableTop);
00522             }    
00523             break;
00524 
00525          default:
00526             break;
00527       }
00528    }
00529 }
00530 
00531 //______________________________________________________________________________
00532 void TGHtml::DrawImage(TGHtmlImageMarkup *image, Drawable_t drawable,
00533                        int drawableLeft, int drawableTop,
00534                        int drawableRight, int drawableBottom)
00535 {
00536    // Draw all or part of an image.
00537 
00538    int imageTop;          // virtual canvas coordinate for top of image
00539    int x, y;              // where to place image on the drawable
00540    int imageX, imageY;    // \__  Subset of image that fits
00541    int imageW, imageH;    // /    on the drawable
00542 
00543    imageTop = image->fY - image->fAscent;
00544    y = imageTop - drawableTop;
00545    if (imageTop + image->fH > drawableBottom) {
00546       imageH = drawableBottom - imageTop;
00547    } else {
00548       imageH = image->fH;
00549    }
00550    if (y < 0) {
00551       imageY = -y;
00552       imageH += y;
00553       y = 0;
00554    } else {
00555       imageY = 0;
00556    }
00557    x = image->fX - drawableLeft;
00558    if (image->fX + image->fW > drawableRight) {
00559       imageW = drawableRight - image->fX;
00560    } else {
00561       imageW = image->fW;
00562    }
00563    if (x < 0) {
00564       imageX = -x;
00565       imageW += x;
00566       x = 0;
00567    } else {
00568       imageX = 0;
00569    }
00570 
00571    TImage *img = image->fPImage->fImage;
00572 
00573    imageH = imageH < 0 ? -imageH : imageH;
00574    imageW = imageW < 0 ? -imageW : imageW;
00575 
00576    img->PaintImage(drawable, x, y, imageX, imageY, imageW, imageH);
00577    //gVirtualX->Update(kFALSE);
00578 
00579    image->fRedrawNeeded = 0;
00580 }
00581 
00582 //______________________________________________________________________________
00583 void TGHtml::AnimateImage(TGHtmlImage * /*image*/)
00584 {
00585    //
00586   //TGImage *img = image->image;
00587 
00588   //if (!img->IsAnimated()) return;
00589   //img->NextFrame();
00590   //delete image->timer;
00591   //image->timer = new TTimer(this, img->GetAnimDelay());
00592   //ImageChanged(image, image->fW, image->fH);
00593 }
00594 
00595 //______________________________________________________________________________
00596 TGHtmlElement *TGHtml::FillOutBlock(TGHtmlBlock *p)
00597 {
00598    // Recompute the following fields of the given block structure:
00599    //
00600    //    base.count         The number of elements described by this
00601    //                       block structure.
00602    //
00603    //    n                  The number of characters of text output
00604    //                       associated with this block.  If the block
00605    //                       renders something other than text (ex: <IMG>)
00606    //                       then set n to 0.
00607    //
00608    //    z                  Pointer to malloced memory containing the
00609    //                       text associated with this block.  NULL if
00610    //                       n is 0.
00611    //
00612    // Return a pointer to the first TGHtmlElement not covered by the block.
00613 
00614 
00615    TGHtmlElement *pElem;
00616    int go, i, n, x, y;
00617    SHtmlStyle_t style;
00618    int firstSelected;      // First selected character in this block
00619    int lastSelected;       // Last selected character in this block
00620    char zBuf[2000];
00621 
00622    // Reset n and z
00623 
00624    if (p->fN) p->fN = 0;
00625 
00626    if (p->fZ) delete[] p->fZ;
00627    p->fZ = 0;
00628 
00629    firstSelected = 1000000;
00630    lastSelected = -1;
00631 
00632    // Skip over TGHtmlElements that aren't directly displayed.
00633 
00634    pElem = p->fPNext;
00635    p->fCount = 0;
00636    while (pElem && (pElem->fFlags & HTML_Visible) == 0) {
00637       TGHtmlElement *fPNext = pElem->fPNext;
00638       if (pElem->fType == Html_Block) {
00639          UnlinkAndFreeBlock((TGHtmlBlock *) pElem);
00640       } else {
00641          p->fCount++;
00642       }
00643       pElem = fPNext;
00644    }
00645    if (pElem == 0) return 0;
00646 
00647    // Handle "special" elements.
00648 
00649    if (pElem->fType != Html_Text) {
00650       switch (pElem->fType) {
00651          case Html_HR: {
00652             TGHtmlHr *hr = (TGHtmlHr *) pElem;
00653             p->fTop    = hr->fY - hr->fH;
00654             p->fBottom = hr->fY;
00655             p->fLeft   = hr->fX;
00656             p->fRight  = hr->fX + hr->fW;
00657             break;
00658          }
00659 
00660          case Html_LI: {
00661             TGHtmlLi *li = (TGHtmlLi *) pElem;
00662             p->fTop    = li->fY - li->fAscent;
00663             p->fBottom = li->fY + li->fDescent;
00664             p->fLeft   = li->fX - 10;
00665             p->fRight  = li->fX + 10;
00666             break;
00667          }
00668 
00669          case Html_TD:
00670          case Html_TH: {
00671             TGHtmlCell *cell = (TGHtmlCell *) pElem;
00672             p->fTop    = cell->fY;
00673             p->fBottom = cell->fY + cell->fH;
00674             p->fLeft   = cell->fX;
00675             p->fRight  = cell->fX + cell->fW;
00676             break;
00677          }
00678 
00679          case Html_TABLE: {
00680             TGHtmlTable *table = (TGHtmlTable *) pElem;
00681             p->fTop    = table->fY;
00682             p->fBottom = table->fY + table->fH;
00683             p->fLeft   = table->fX;
00684             p->fRight  = table->fX + table->fW;
00685             break;
00686          }
00687 
00688          case Html_IMG: {
00689             TGHtmlImageMarkup *image = (TGHtmlImageMarkup *) pElem;
00690             p->fTop    = image->fY - image->fAscent;
00691             p->fBottom = image->fY + image->fDescent;
00692             p->fLeft   = image->fX;
00693             p->fRight  = image->fX + image->fW;
00694             break;
00695          }
00696       }
00697       p->fCount++;
00698 
00699       return pElem->fPNext;
00700    }
00701 
00702    // If we get this far, we must be dealing with text.
00703 
00704    TGHtmlTextElement *text = (TGHtmlTextElement *) pElem;
00705    n = 0;
00706    x = text->fX;
00707    y = text->fY;
00708    p->fTop = y - text->fAscent;
00709    p->fBottom = y + text->fDescent;
00710    p->fLeft = x;
00711    style = pElem->fStyle;
00712    go = 1;
00713    while (pElem) {
00714       TGHtmlElement *fPNext = pElem->fPNext;
00715       switch (pElem->fType) {
00716          case Html_Text: {
00717             TGHtmlTextElement *txt = (TGHtmlTextElement *) pElem;
00718             if (pElem->fFlags & STY_Invisible) {
00719                break;
00720             }
00721             if (txt->fSpaceWidth <= 0) {
00722                //CANT_HAPPEN;
00723                break;
00724             }
00725             if (y != txt->fY 
00726                   ||  style.fFont != pElem->fStyle.fFont
00727                   ||  style.fColor != pElem->fStyle.fColor
00728                   ||  (style.fFlags & STY_FontMask) 
00729                   != (pElem->fStyle.fFlags & STY_FontMask)) {
00730                go = 0;
00731             } else {
00732                int sw = txt->fSpaceWidth;
00733                int nSpace = (txt->fX - x) / sw;
00734                if (nSpace * sw + x != txt->fX) {
00735                   go = 0;
00736                } else if ((n + nSpace + pElem->fCount) >= (int)sizeof(zBuf)) {
00737                   // go = 0; - this caused a hang, instead lets do what we can
00738                   for (i = 0; i < nSpace && (n+1) < (int)sizeof(zBuf); ++i) {
00739                      zBuf[n++] = ' ';
00740                   }
00741                   strncpy(&zBuf[n], txt->fZText, sizeof(zBuf) - n - 1);
00742                   zBuf[sizeof(zBuf)-1] = 0;
00743                   n += i;
00744                   x = txt->fX + txt->fW;
00745                } else {
00746                   for (i = 0; i < nSpace && (n+1) < (int)sizeof(zBuf); ++i) {
00747                      zBuf[n++] = ' ';
00748                   }
00749                   strncpy(&zBuf[n], txt->fZText, sizeof(zBuf) - n - 1);
00750                   zBuf[sizeof(zBuf)-1] = 0;
00751                   n += pElem->fCount;
00752                   x = txt->fX + txt->fW;
00753                }
00754             }
00755             break;
00756          }
00757 
00758          case Html_Space:
00759             if (pElem->fStyle.fFont != style.fFont) {
00760                pElem = pElem->fPNext;
00761                go = 0;
00762             } else if ((style.fFlags & STY_Preformatted) != 0 &&
00763                        (pElem->fFlags & HTML_NewLine) != 0) {
00764                pElem = pElem->fPNext;
00765                go = 0;
00766             }
00767             break;
00768 
00769          case Html_Block:
00770             UnlinkAndFreeBlock((TGHtmlBlock *) pElem);
00771             break;
00772 
00773          case Html_A:
00774          case Html_EndA:
00775             go = 0;
00776             break;
00777 
00778          default:
00779             if (pElem->fFlags & HTML_Visible) go = 0;
00780             break;
00781       }
00782       if (go == 0) break;
00783       p->fCount++;
00784       pElem = fPNext;
00785    }
00786    p->fRight = x;
00787 
00788    while (n > 0 && zBuf[n-1] == ' ') n--;
00789    p->fZ = new char[n+1];
00790    strlcpy(p->fZ, zBuf, n+1);
00791    p->fZ[n] = 0;
00792    p->fN = n;
00793 
00794    return pElem;
00795 }
00796 
00797 //______________________________________________________________________________
00798 TGHtmlElement *TGHtml::FindStartOfNextBlock(TGHtmlElement *p, int *pCnt)
00799 {
00800    // Scan ahead looking for a place to put a block.  Return a pointer
00801    // to the element which should come immediately after the block.
00802    //
00803    // if pCnt != 0, then put the number of elements skipped in *pCnt.
00804    //
00805    // p    - First candidate for the start of a block
00806    // pCnt - Write number of elements skipped here
00807 
00808    int cnt = 0;
00809 
00810    while (p && (p->fFlags & HTML_Visible) == 0) {
00811       TGHtmlElement *fPNext = p->fPNext;
00812       if (p->fType == Html_Block) {
00813          UnlinkAndFreeBlock((TGHtmlBlock *) p);
00814       } else {
00815          cnt++;
00816       }
00817       p = fPNext;
00818    }
00819    if (pCnt) *pCnt = cnt;
00820 
00821    return p;
00822 }
00823 
00824 //______________________________________________________________________________
00825 void TGHtml::FormBlocks()
00826 {
00827    // Add additional blocks to the block list in order to cover
00828    // all elements on the element list.
00829    //
00830    // If any old blocks are found on the element list, they must
00831    // be left over from a prior rendering.  Unlink and delete them.
00832 
00833    TGHtmlElement *pElem;
00834 
00835    if (fLastBlock) {
00836       pElem = FillOutBlock(fLastBlock);
00837    } else {
00838       pElem = fPFirst;
00839    }
00840    while (pElem) {
00841       int cnt;
00842       pElem = FindStartOfNextBlock(pElem, &cnt);
00843       if (pElem) {
00844          TGHtmlBlock *pNew = new TGHtmlBlock();
00845          if (fLastBlock) {
00846             fLastBlock->fCount += cnt;
00847          }
00848          AppendBlock(pElem, pNew);
00849          pElem = FillOutBlock(pNew);
00850       }
00851    }
00852 }
00853 
00854 //______________________________________________________________________________
00855 void TGHtml::DrawTableBgnd(int l, int t, int w, int h, 
00856                            Drawable_t pixmap, TImage *image)
00857 {
00858    // Draw table background
00859 
00860    //int  mx, my, sh, sw, sx, sy, hd;
00861    int iw, ih, dl, dt, dr, db,  left, top, right, bottom; 
00862 
00863    left = l - fVisible.fX;
00864    top  = t - fVisible.fY;
00865 
00866    dl = fDirtyLeft;
00867    dt = fDirtyTop;
00868    dr = fDirtyRight;
00869    db = fDirtyBottom;
00870 
00871    right = left + w - 1;
00872    bottom = top + h - 1;
00873    if (dr == 0 && db == 0) { dr = right; db = bottom; }
00874    if (left > dr || right < dl || top > db || bottom < dt) return;
00875    iw = image->GetWidth();
00876    ih = image->GetHeight();
00877 
00878 #if 0
00879    if (iw < 4 && ih < 4) return;  // CPU burners we ignore.
00880    sx = (left + _visibleStart.x) % iw;   // X offset within image to start from
00881    sw = iw - sx;                         // Width of section of image to draw.
00882    for (mx = left - dl; w > 0; mx += sw, sw = iw, sx = 0) {
00883       if (sw > w) sw = w;
00884       sy = (top + _visibleStart.y) % ih;  // Y offset within image to start from
00885       sh = ih - sy;                       // Height of section of image to draw.
00886       for (my = top - dt, hd = h; hd > 0; my += sh, sh = ih, sy = 0) {
00887          if (sh > hd) sh = hd;
00888          // printf("image: %d %d %d %d %d %d\n", sx, sy, sw, sh, mx,my);
00889          image->Draw(pixmap, GetAnyGC(), sx, sy, sw, sh, mx, my);
00890          hd -= sh;
00891       }
00892       w -= sw;
00893    }
00894 #else
00895    if (!image->GetPixmap()) return;
00896    GContext_t gc = GetAnyGC();
00897    GCValues_t gcv;
00898    unsigned int mask = kGCTile | kGCFillStyle |
00899                        kGCTileStipXOrigin | kGCTileStipYOrigin;
00900    gcv.fTile      = image->GetPixmap();
00901    gcv.fFillStyle = kFillTiled;
00902    gcv.fTsXOrigin = -fVisible.fX - fDirtyLeft;
00903    gcv.fTsYOrigin = -fVisible.fY - fDirtyTop;
00904    gVirtualX->ChangeGC(gc, &gcv);
00905 
00906    gVirtualX->FillRectangle(pixmap, gc, left - dl, top - dt, w, h);
00907 
00908    mask = kGCFillStyle;
00909    gcv.fFillStyle = kFillSolid;
00910    gVirtualX->ChangeGC(gc, &gcv);
00911 #endif
00912 }

Generated on Tue Jul 5 14:22:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1