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