001    package railo.runtime.tag;
002    
003    import java.io.IOException;
004    
005    import railo.commons.digest.MD5;
006    import railo.commons.io.IOUtil;
007    import railo.commons.io.res.Resource;
008    import railo.commons.io.res.util.ResourceUtil;
009    import railo.commons.lang.StringUtil;
010    import railo.runtime.PageContextImpl;
011    import railo.runtime.PageSource;
012    import railo.runtime.exp.PageException;
013    import railo.runtime.ext.tag.TagImpl;
014    import railo.runtime.functions.image.ImageNew;
015    import railo.runtime.functions.image.ImageWrite;
016    import railo.runtime.img.Image;
017    import railo.runtime.op.Caster;
018    import railo.runtime.type.util.ListUtil;
019    
020    public final class Sprite extends TagImpl {
021            
022            private String _id;
023            private String _ids;
024            private String _srcs;
025            
026            String src;
027                    
028    
029            
030            @Override
031            public void release()   {
032                    this._id=null;
033                    this._ids=null;
034                    this.src=null;
035                    this._srcs=null;
036                    super.release();
037            }
038            
039            
040            
041            public void set_ids(String _ids){
042                    this._ids=_ids;
043            }
044    
045            public void set_id(String _id){
046                    this._id=_id;
047            }
048    
049            public void set_srcs(String _srcs){
050                    this._srcs=_srcs;
051            }
052    
053            public void setSrc(String src){
054                    this.src=src;
055            }
056            
057            @Override
058    
059            public int doStartTag() throws PageException    {
060                    try {
061                            return _doStartTag();
062                    } catch (Throwable e) {
063                            throw Caster.toPageException(e);
064                    }
065            }
066            
067            
068            public int _doStartTag() throws Throwable       {
069                    
070                    // write out div for single item
071                    pageContext.write("<div id=\""+_id+"\"></div>");
072                    
073                    
074                    
075                    
076                    
077                    
078                    // handle all items
079                    if(!StringUtil.isEmpty(_ids)) {
080                            String[] ids=ListUtil.listToStringArray(_ids, ',');
081                            String[] strSrcs=ListUtil.listToStringArray(_srcs, ',');
082                            Resource[] srcs=new Resource[strSrcs.length];
083                            Image[] images=new Image[strSrcs.length];
084                            for(int i=0;i<srcs.length;i++){
085                                    srcs[i]=ResourceUtil.toResourceExisting(pageContext, strSrcs[i]);
086                                    images[i] = new Image(srcs[i]);
087                            }
088                            
089                            // TODO use the same resource as for cfimage
090                            PageSource ps = pageContext.getCurrentTemplatePageSource();
091                            Resource curr = ps.getResource();
092                            Resource dir = curr.getParentResource();
093                            Resource cssDir = dir.getRealResource("css");
094                            Resource pathdir = cssDir;
095                            cssDir.mkdirs();
096                            
097                            
098                            //the base name for the files we are going to create as a css and image
099                            String baseRenderedFileName = MD5.getDigestAsString(_ids);
100                            Resource cssFileName = cssDir.getRealResource(baseRenderedFileName+".css");
101                            Resource imgFileName = pathdir.getRealResource(baseRenderedFileName+"."+ResourceUtil.getExtension(src,""));
102                            
103                            //if the files don't exist, then we create them, otherwise
104                            boolean bCreate = !cssFileName.isFile() || !imgFileName.isFile();
105                            
106                            
107                            //Are we going to create it, let's say no
108                            String css = "";
109                            if(bCreate){
110                                    int imgMaxHeight = 0;
111                                    int imgMaxWidth = 0;
112                                    Image img;
113                                    int actualWidth,actualHeight;
114                                    //Setup the max height and width of the new image. 
115                                    for(int i=0;i<srcs.length;i++){
116                                            img = images[i];
117                                            
118                                            //set the image original height and width 
119                                            actualWidth = img.getWidth();;
120                                            actualHeight = img.getHeight();
121                                                                            
122                                                                            
123                                            
124                                            //Check if there is a height, 
125                                            imgMaxHeight += actualHeight;
126                                            if(actualWidth  > imgMaxWidth) imgMaxWidth  =  actualWidth;
127                                    }
128                                    
129                                    //Create the new image (hence we needed to do two of these items)
130                                    Image spriteImage = (Image) ImageNew.call(pageContext,"", ""+imgMaxWidth,""+imgMaxHeight, "argb");
131                                    
132                                    int placedHeight = 0;
133                                    //Loop again but this time, lets do the copy and paste
134                                    for(int i=0;i<srcs.length;i++){
135                                            img = images[i];
136                                            spriteImage.paste(img,1,placedHeight);
137                                            
138                                                    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";
139                                                    placedHeight += img.getHeight();
140                                    }
141                                    
142                                    //Now Write the CSS and the Sprite Image
143                                    
144                                    ImageWrite.call(pageContext, spriteImage, imgFileName.getAbsolutePath());
145                                    IOUtil.write(cssFileName, css,"UTF-8",false);
146                                    
147                            }
148    
149                            
150                            //pageContext.write("<style>"+css+"</style>");
151    
152                            try {
153                                    ((PageContextImpl)pageContext).getRootOut()
154                                            .appendHTMLHead("<link rel=\"stylesheet\" href=\"css/"+baseRenderedFileName+".css\" type=\"text/css\" media=\"screen\" title=\"no title\" charset=\"utf-8\">");
155                            } catch (IOException e) {
156                                    Caster.toPageException(e);
157                            } 
158                            
159                    }
160                    
161                    
162                    
163                    
164                    return SKIP_BODY;
165            }
166    
167    
168    
169            @Override
170            public int doEndTag()   {
171                    return EVAL_PAGE;
172            }
173    }