001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.tag; 020 021import java.io.IOException; 022 023import lucee.commons.digest.MD5; 024import lucee.commons.io.IOUtil; 025import lucee.commons.io.res.Resource; 026import lucee.commons.io.res.util.ResourceUtil; 027import lucee.commons.lang.StringUtil; 028import lucee.runtime.PageContextImpl; 029import lucee.runtime.PageSource; 030import lucee.runtime.exp.PageException; 031import lucee.runtime.ext.tag.TagImpl; 032import lucee.runtime.functions.image.ImageNew; 033import lucee.runtime.functions.image.ImageWrite; 034import lucee.runtime.img.Image; 035import lucee.runtime.op.Caster; 036import lucee.runtime.type.util.ListUtil; 037 038public final class Sprite extends TagImpl { 039 040 private String _id; 041 private String _ids; 042 private String _srcs; 043 044 String src; 045 046 047 048 @Override 049 public void release() { 050 this._id=null; 051 this._ids=null; 052 this.src=null; 053 this._srcs=null; 054 super.release(); 055 } 056 057 058 059 public void set_ids(String _ids){ 060 this._ids=_ids; 061 } 062 063 public void set_id(String _id){ 064 this._id=_id; 065 } 066 067 public void set_srcs(String _srcs){ 068 this._srcs=_srcs; 069 } 070 071 public void setSrc(String src){ 072 this.src=src; 073 } 074 075 @Override 076 077 public int doStartTag() throws PageException { 078 try { 079 return _doStartTag(); 080 } catch (Throwable e) { 081 throw Caster.toPageException(e); 082 } 083 } 084 085 086 public int _doStartTag() throws Throwable { 087 088 // write out div for single item 089 pageContext.write("<div id=\""+_id+"\"></div>"); 090 091 092 093 094 095 096 // handle all items 097 if(!StringUtil.isEmpty(_ids)) { 098 String[] ids=ListUtil.listToStringArray(_ids, ','); 099 String[] strSrcs=ListUtil.listToStringArray(_srcs, ','); 100 Resource[] srcs=new Resource[strSrcs.length]; 101 Image[] images=new Image[strSrcs.length]; 102 for(int i=0;i<srcs.length;i++){ 103 srcs[i]=ResourceUtil.toResourceExisting(pageContext, strSrcs[i]); 104 images[i] = new Image(srcs[i]); 105 } 106 107 // TODO use the same resource as for cfimage 108 PageSource ps = pageContext.getCurrentTemplatePageSource(); 109 Resource curr = ps.getResource(); 110 Resource dir = curr.getParentResource(); 111 Resource cssDir = dir.getRealResource("css"); 112 Resource pathdir = cssDir; 113 cssDir.mkdirs(); 114 115 116 //the base name for the files we are going to create as a css and image 117 String baseRenderedFileName = MD5.getDigestAsString(_ids); 118 Resource cssFileName = cssDir.getRealResource(baseRenderedFileName+".css"); 119 Resource imgFileName = pathdir.getRealResource(baseRenderedFileName+"."+ResourceUtil.getExtension(src,"")); 120 121 //if the files don't exist, then we create them, otherwise 122 boolean bCreate = !cssFileName.isFile() || !imgFileName.isFile(); 123 124 125 //Are we going to create it, let's say no 126 String css = ""; 127 if(bCreate){ 128 int imgMaxHeight = 0; 129 int imgMaxWidth = 0; 130 Image img; 131 int actualWidth,actualHeight; 132 //Setup the max height and width of the new image. 133 for(int i=0;i<srcs.length;i++){ 134 img = images[i]; 135 136 //set the image original height and width 137 actualWidth = img.getWidth();; 138 actualHeight = img.getHeight(); 139 140 141 142 //Check if there is a height, 143 imgMaxHeight += actualHeight; 144 if(actualWidth > imgMaxWidth) imgMaxWidth = actualWidth; 145 } 146 147 //Create the new image (hence we needed to do two of these items) 148 Image spriteImage = (Image) ImageNew.call(pageContext,"", ""+imgMaxWidth,""+imgMaxHeight, "argb"); 149 150 int placedHeight = 0; 151 //Loop again but this time, lets do the copy and paste 152 for(int i=0;i<srcs.length;i++){ 153 img = images[i]; 154 spriteImage.paste(img,1,placedHeight); 155 156 css += "#"+ids[i]+" {\n\tbackground: url("+baseRenderedFileName+"."+ResourceUtil.getExtension(strSrcs[i],"")+") 0px -"+placedHeight+"px no-repeat; width:"+img.getWidth()+"px; height:"+img.getHeight()+"px;\n} \n"; 157 placedHeight += img.getHeight(); 158 } 159 160 //Now Write the CSS and the Sprite Image 161 162 ImageWrite.call(pageContext, spriteImage, imgFileName.getAbsolutePath()); 163 IOUtil.write(cssFileName, css,"UTF-8",false); 164 165 } 166 167 168 //pageContext.write("<style>"+css+"</style>"); 169 170 try { 171 ((PageContextImpl)pageContext).getRootOut() 172 .appendHTMLHead("<link rel=\"stylesheet\" href=\"css/"+baseRenderedFileName+".css\" type=\"text/css\" media=\"screen\" title=\"no title\" charset=\"utf-8\">"); 173 } catch (IOException e) { 174 Caster.toPageException(e); 175 } 176 177 } 178 179 180 181 182 return SKIP_BODY; 183 } 184 185 186 187 @Override 188 public int doEndTag() { 189 return EVAL_PAGE; 190 } 191}