diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h index c6bc06b94..db3c9130b 100644 --- a/code/nel/include/nel/gui/group_html.h +++ b/code/nel/include/nel/gui/group_html.h @@ -73,6 +73,33 @@ namespace NLGUI }; static SWebOptions options; + + class CStyleParams + { + public: + CStyleParams () : TextColor(255,255,255,255) + { + FontSize=10; + FontWeight=400; + FontOblique=false; + Underlined=false; + StrikeThrough=false; + Width=-1; + Height=-1; + MaxWidth=-1; + MaxHeight=-1; + } + uint FontSize; + uint FontWeight; + bool FontOblique; + NLMISC::CRGBA TextColor; + bool Underlined; + bool StrikeThrough; + sint32 Width; + sint32 Height; + sint32 MaxWidth; + sint32 MaxHeight; + }; // Constructor CGroupHTML(const TCtorParam ¶m); @@ -311,7 +338,7 @@ namespace NLGUI void addString(const ucstring &str); // Add an image in the current paragraph - void addImage(const char *image, bool globalColor, bool reloadImg=false); + void addImage(const char *image, bool globalColor, bool reloadImg=false, const CStyleParams &style = CStyleParams()); // Add a text area in the current paragraph CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength); @@ -321,7 +348,8 @@ namespace NLGUI // Add a button in the current paragraph. actionHandler, actionHandlerParams and tooltip can be NULL. CCtrlButton *addButton(CCtrlButton::EType type, const std::string &name, const std::string &normalBitmap, const std::string &pushedBitmap, - const std::string &overBitmap, bool useGlobalColor, const char *actionHandler, const char *actionHandlerParams, const char *tooltip); + const std::string &overBitmap, bool useGlobalColor, const char *actionHandler, const char *actionHandlerParams, const char *tooltip, + const CStyleParams &style = CStyleParams()); // Set the background color void setBackgroundColor (const NLMISC::CRGBA &bgcolor); @@ -625,26 +653,6 @@ namespace NLGUI }; std::vector _CellParams; - class CStyleParams - { - public: - CStyleParams () : TextColor(255,255,255,255) - { - FontSize=10; - FontWeight=400; - FontOblique=false; - Underlined=false; - StrikeThrough=false; - } - uint FontSize; - uint FontWeight; - bool FontOblique; - NLMISC::CRGBA TextColor; - bool Underlined; - bool StrikeThrough; - - }; - // Indentation uint _Indent; @@ -719,6 +727,7 @@ namespace NLGUI // read style attribute void getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit = true); + void applyCssMinMax(sint32 &width, sint32 &height, sint32 minw=0, sint32 minh=0, sint32 maxw=0, sint32 maxh=0); // load and render local html file (from bnp for example) void doBrowseLocalFile(const std::string &filename); @@ -738,13 +747,24 @@ namespace NLGUI // ImageDownload system enum TDataType {ImgType= 0, BnpType}; + + struct CDataImageDownload + { + public: + CDataImageDownload(CViewBase *img, CStyleParams style): Image(img), Style(style) + { + } + public: + CViewBase * Image; + CStyleParams Style; + }; struct CDataDownload { public: - CDataDownload(CURL *c, const std::string &u, const std::string &d, FILE *f, TDataType t, CViewBase *i, const std::string &s, const std::string &m) : curl(c), url(u), dest(d), luaScript(s), md5sum(m), type(t), fp(f) + CDataDownload(CURL *c, const std::string &u, const std::string &d, FILE *f, TDataType t, CViewBase *i, const std::string &s, const std::string &m, const CStyleParams &style = CStyleParams()) : curl(c), url(u), dest(d), luaScript(s), md5sum(m), type(t), fp(f) { - if (t == ImgType) imgs.push_back(i); + if (t == ImgType) imgs.push_back(CDataImageDownload(i, style)); } public: @@ -755,7 +775,7 @@ namespace NLGUI std::string md5sum; TDataType type; FILE *fp; - std::vector imgs; + std::vector imgs; }; std::vector Curls; @@ -764,12 +784,13 @@ namespace NLGUI void initImageDownload(); void checkImageDownload(); - void addImageDownload(const std::string &url, CViewBase *img); + void addImageDownload(const std::string &url, CViewBase *img, const CStyleParams &style = CStyleParams()); std::string localImageName(const std::string &url); std::string getAbsoluteUrl(const std::string &url); bool isTrustedDomain(const std::string &domain); void setImage(CViewBase *view, const std::string &file); + void setImageSize(CViewBase *view, const CStyleParams &style = CStyleParams()); // BnpDownload system void initBnpDownload(); diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp index 7494f9540..a1ec1971e 100644 --- a/code/nel/src/gui/group_html.cpp +++ b/code/nel/src/gui/group_html.cpp @@ -126,6 +126,7 @@ namespace NLGUI return it != options.trustedDomains.end(); } + // Update view after download has finished void CGroupHTML::setImage(CViewBase * view, const string &file) { CCtrlButton *btn = dynamic_cast(view); @@ -166,7 +167,90 @@ namespace NLGUI } } } + + // Force image width, height + void CGroupHTML::setImageSize(CViewBase *view, const CStyleParams &style) + { + sint32 width = style.Width; + sint32 height = style.Height; + sint32 maxw = style.MaxWidth; + sint32 maxh = style.MaxHeight; + + sint32 imageWidth, imageHeight; + bool changed = true; + + // get image texture size + // if image is being downloaded, then correct size is set after thats done + CCtrlButton *btn = dynamic_cast(view); + if(btn) + { + btn->fitTexture(); + imageWidth = btn->getW(false); + imageHeight = btn->getH(false); + } + else + { + CViewBitmap *btm = dynamic_cast(view); + if(btm) + { + btm->fitTexture(); + imageWidth = btm->getW(false); + imageHeight = btm->getH(false); + } + else + { + // not supported + return; + } + } + + // if width/height is not requested, then use image size + // else recalculate missing value, keep image ratio + if (width == -1 && height == -1) + { + width = imageWidth; + height = imageHeight; + + changed = false; + } + else + if (width == -1 || height == -1) { + float ratio = (float) imageWidth / std::max(1, imageHeight); + if (width == -1) + width = height * ratio; + else + height = width / ratio; + } + + // apply max-width, max-height rules if asked + if (maxw > -1 || maxh > -1) + { + applyCssMinMax(width, height, 0, 0, maxw, maxh); + changed = true; + } + if (changed) + { + CCtrlButton *btn = dynamic_cast(view); + if(btn) + { + btn->setScale(true); + btn->setW(width); + btn->setH(height); + } + else + { + CViewBitmap *image = dynamic_cast(view); + if(image) + { + image->setScale(true); + image->setW(width); + image->setH(height); + } + } + } + } + // Get an url and return the local filename with the path where the url image should be string CGroupHTML::localImageName(const string &url) { @@ -177,7 +261,7 @@ namespace NLGUI } // Add a image download request in the multi_curl - void CGroupHTML::addImageDownload(const string &url, CViewBase *img) + void CGroupHTML::addImageDownload(const string &url, CViewBase *img, const CStyleParams &style) { string finalUrl = getAbsoluteUrl(url); @@ -189,7 +273,7 @@ namespace NLGUI #ifdef LOG_DL nlwarning("already downloading '%s' img %p", finalUrl.c_str(), img); #endif - Curls[i].imgs.push_back(img); + Curls[i].imgs.push_back(CDataImageDownload(img, style)); return; } } @@ -234,7 +318,7 @@ namespace NLGUI curl_easy_setopt(curl, CURLOPT_FILE, fp); curl_multi_add_handle(MultiCurl, curl); - Curls.push_back(CDataDownload(curl, finalUrl, dest, fp, ImgType, img, "", "")); + Curls.push_back(CDataDownload(curl, finalUrl, dest, fp, ImgType, img, "", "", style)); #ifdef LOG_DL nlwarning("adding handle %x, %d curls", curl, Curls.size()); #endif @@ -243,6 +327,7 @@ namespace NLGUI else { setImage(img, dest); + setImageSize(img, style); } } @@ -499,7 +584,8 @@ namespace NLGUI { for(uint i = 0; i < it->imgs.size(); i++) { - setImage(it->imgs[i], it->dest); + setImage(it->imgs[i].Image, it->dest); + setImageSize(it->imgs[i].Image, it->imgs[i].Style); } } } @@ -1272,6 +1358,17 @@ namespace NLGUI // Get the string name if (present[MY_HTML_IMG_SRC] && value[MY_HTML_IMG_SRC]) { + CStyleParams style; + float tmpf; + + if (present[MY_HTML_IMG_WIDTH] && value[MY_HTML_IMG_WIDTH]) + getPercentage(style.Width, tmpf, value[MY_HTML_IMG_WIDTH]); + if (present[MY_HTML_IMG_HEIGHT] && value[MY_HTML_IMG_HEIGHT]) + getPercentage(style.Height, tmpf, value[MY_HTML_IMG_HEIGHT]); + // width, height from inline css + if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE]) + getStyleParams(value[MY_HTML_IMG_STYLE], style); + // Get the global color name bool globalColor = false; if (present[MY_HTML_IMG_GLOBAL_COLOR]) @@ -1286,20 +1383,20 @@ namespace NLGUI string params = "name=" + getId() + "|url=" + getLink (); addButton(CCtrlButton::PushButton, value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], value[MY_HTML_IMG_SRC], - "", globalColor, "browse", params.c_str(), tooltip); + "", globalColor, "browse", params.c_str(), tooltip, style); } else { // Get the option to reload (class==reload) bool reloadImg = false; - - string style; + + string styleString; if (present[MY_HTML_IMG_STYLE] && value[MY_HTML_IMG_STYLE]) - style = value[MY_HTML_IMG_STYLE]; + styleString = value[MY_HTML_IMG_STYLE]; - if (!style.empty()) + if (!styleString.empty()) { - TStyle styles = parseStyle(style); + TStyle styles = parseStyle(styleString); TStyle::iterator it; it = styles.find("reload"); @@ -1307,7 +1404,7 @@ namespace NLGUI reloadImg = true; } - addImage (value[MY_HTML_IMG_SRC], globalColor, reloadImg); + addImage (value[MY_HTML_IMG_SRC], globalColor, reloadImg, style); } } } @@ -1346,6 +1443,11 @@ namespace NLGUI string type = toLower(value[MY_HTML_INPUT_TYPE]); if (type == "image") { + CStyleParams style; + // width, height from inline css + if (present[MY_HTML_INPUT_STYLE] && value[MY_HTML_INPUT_STYLE]) + getStyleParams(value[MY_HTML_INPUT_STYLE], style); + // The submit button string name; string normal; @@ -1361,7 +1463,7 @@ namespace NLGUI // Add the ctrl button addButton (CCtrlButton::PushButton, name, normal, pushed.empty()?normal:pushed, over, - globalColor, "html_submit_form", param.c_str(), tooltip); + globalColor, "html_submit_form", param.c_str(), tooltip, style); } if (type == "button" || type == "submit") { @@ -3569,7 +3671,7 @@ namespace NLGUI // *************************************************************************** - void CGroupHTML::addImage(const char *img, bool globalColor, bool reloadImg) + void CGroupHTML::addImage(const char *img, bool globalColor, bool reloadImg, const CStyleParams &style) { // In a paragraph ? if (!_Paragraph) @@ -3615,14 +3717,16 @@ namespace NLGUI // 3/ if it doesn't work, display a placeholder and ask to dl the image into the cache // image = "web_del.tga"; - addImageDownload(img, newImage); + addImageDownload(img, newImage, style); } } newImage->setTexture (image); newImage->setModulateGlobalColor(globalColor); - getParagraph()->addChild(newImage); + getParagraph()->addChild(newImage); paragraphChange (); + + setImageSize(newImage, style); } // *************************************************************************** @@ -3720,7 +3824,7 @@ namespace NLGUI CCtrlButton *CGroupHTML::addButton(CCtrlButton::EType type, const std::string &/* name */, const std::string &normalBitmap, const std::string &pushedBitmap, const std::string &overBitmap, bool useGlobalColor, const char *actionHandler, const char *actionHandlerParams, - const char *tooltip) + const char *tooltip, const CStyleParams &style) { // In a paragraph ? if (!_Paragraph) @@ -3748,7 +3852,7 @@ namespace NLGUI if(!CFile::fileExists(normal)) { normal = "web_del.tga"; - addImageDownload(normalBitmap, ctrlButton); + addImageDownload(normalBitmap, ctrlButton, style); } } } @@ -3803,6 +3907,8 @@ namespace NLGUI getParagraph()->addChild (ctrlButton); paragraphChange (); + + setImageSize(ctrlButton, style); return ctrlButton; } @@ -5116,6 +5222,7 @@ namespace NLGUI // style.StrikeThrough; // text-decoration: line-through; text-decoration-line: line-through; void CGroupHTML::getStyleParams(const std::string &styleString, CStyleParams &style, bool inherit) { + float tmpf; TStyle styles = parseStyle(styleString); TStyle::iterator it; for (it=styles.begin(); it != styles.end(); ++it) @@ -5179,6 +5286,18 @@ namespace NLGUI style.Underlined = (prop.find("underline") != std::string::npos); style.StrikeThrough = (prop.find("line-through") != std::string::npos); } + else + if (it->first == "width") + getPercentage(style.Width, tmpf, it->second.c_str()); + else + if (it->first == "height") + getPercentage(style.Height, tmpf, it->second.c_str()); + else + if (it->first == "max-width") + getPercentage(style.MaxWidth, tmpf, it->second.c_str()); + else + if (it->first == "max-height") + getPercentage(style.MaxHeight, tmpf, it->second.c_str()); } if (inherit) { @@ -5187,6 +5306,74 @@ namespace NLGUI } } + // *************************************************************************** + void CGroupHTML::applyCssMinMax(sint32 &width, sint32 &height, sint32 minw, sint32 minh, sint32 maxw, sint32 maxh) + { + if (maxw <= 0) maxw = width; + if (maxh <= 0) maxh = height; + + maxw = std::max(minw, maxw); + maxh = std::max(minh, maxh); + + float ratio = (float) width / std::max(1, height); + if (width > maxw) + { + width = maxw; + height = std::max((sint32)(maxw /ratio), minh); + } + if (width < minw) + { + width = minw; + height = std::min((sint32)(minw / ratio), maxh); + } + if (height > maxh) + { + width = std::max((sint32)(maxh * ratio), minw); + height = maxh; + } + if (height < minh) + { + width = std::min((sint32)(minh * ratio), maxw); + height = minh; + } + if (width > maxw && height > maxh) + { + if (maxw/width <= maxh/height) + { + width = maxw; + height = std::max(minh, (sint32)(maxw / ratio)); + } + else + { + width = std::max(minw, (sint32)(maxh * ratio)); + height = maxh; + } + } + if (width < minw && height < minh) + { + if (minw / width <= minh / height) + { + width = std::min(maxw, (sint32)(minh * ratio)); + height = minh; + } + else + { + width = minw; + height = std::min(maxh, (sint32)(minw / ratio)); + } + } + if (width < minw && height > maxh) + { + width = minw; + height = maxh; + } + if (width > maxw && height < minh) + { + width = maxw; + height = minh; + } + } + // *************************************************************************** size_t CGroupHTML::curlHeaderCallback(char *buffer, size_t size, size_t nmemb, void *pCCurlWWWData) {