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}