source: trunk/docx4j/src/main/java/org/docx4j/openpackaging/parts/WordprocessingML/ObfuscatedFontPart.java @ 1234

Revision 1234, 6.7 KB checked in by jharrop, 20 months ago (diff)

Include source code for fop-fonts, as org.docx4j.fonts.fop.
Use FOP 1.0.
Move panose to org.docx4j.fonts.foray
Add LICENSE, NOTICE

Line 
1/*
2 *  Copyright 2007-2008, Plutext Pty Ltd.
3 *   
4 *  This file is part of docx4j.
5
6    docx4j is licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18
19 */
20
21package org.docx4j.openpackaging.parts.WordprocessingML;
22
23import org.apache.log4j.Logger;
24import org.docx4j.fonts.fop.fonts.CustomFont;
25import org.docx4j.fonts.fop.fonts.EncodingMode;
26import org.docx4j.fonts.fop.fonts.FontLoader;
27import org.docx4j.fonts.fop.fonts.FontResolver;
28import org.docx4j.fonts.fop.fonts.FontSetup;
29import org.docx4j.fonts.fop.fonts.autodetect.FontFileFinder;
30import org.docx4j.fonts.fop.fonts.autodetect.FontInfoFinder;
31import org.docx4j.openpackaging.exceptions.InvalidFormatException;
32import org.docx4j.openpackaging.parts.PartName;
33import org.docx4j.openpackaging.parts.relationships.Namespaces;
34
35import java.io.File;
36import java.io.IOException;
37import java.io.InputStream;
38import java.io.ByteArrayOutputStream;
39import java.net.MalformedURLException;
40
41public class ObfuscatedFontPart extends BinaryPart {
42
43        private static Logger log = Logger.getLogger(ObfuscatedFontPart.class);         
44       
45    /** docx4j's user directory name */
46    private static final String DOCX4J_USER_DIR = ".docx4all"; 
47        // docx4all already creates a dir; no point creating a second
48
49    /** font cache file path */
50    private static final String TEMPORARY_FONT_DIR = "temporary embedded fonts";
51       
52    private static File tmpFontDir = null; 
53   
54    static {
55        File userHome = getUserHome();
56        if (userHome != null) {
57            File docx4jUserDir = new File(userHome, DOCX4J_USER_DIR);
58            docx4jUserDir.mkdir();
59            tmpFontDir = new File(docx4jUserDir, TEMPORARY_FONT_DIR);
60            tmpFontDir.mkdir();
61        }       
62    }
63   
64    public static String getTemporaryEmbeddedFontsDir() {
65        try {
66                        return tmpFontDir.getCanonicalPath();
67                } catch (IOException e) {
68                        e.printStackTrace();
69                        return null;
70                }
71    }
72   
73    private static File getUserHome() {
74        String s = System.getProperty("user.home");
75        if (s != null) {
76            File userDir = new File(s);
77            if (userDir.exists()) {
78                return userDir;
79            }
80        }
81        return null;
82    }
83
84        public ObfuscatedFontPart(PartName partName) throws InvalidFormatException {
85                super(partName);
86                init();                         
87        }
88       
89        public void init() {
90                // Used if this Part is added to [Content_Types].xml
91                setContentType(new  org.docx4j.openpackaging.contenttype.ContentType( 
92                                org.docx4j.openpackaging.contenttype.ContentTypes.OFFICEDOCUMENT_FONT));
93
94                // Used when this Part is added to a rels
95                // TODO
96                //setRelationshipType(Namespaces.);
97        }
98       
99       
100        /**
101         * deObfuscate this font, and save it using fontName
102         *
103         * @param fontName - the name to save the font as. We
104         * could read the font name from the deObfuscated data,
105         * but FontLoader can't readily load from a byte array.
106         * @param fontKey
107         */
108        public void deObfuscate(String fontName, String fontKey ) {
109               
110                byte[] fontData = null;
111                               
112        bb.clear();
113        fontData = new byte[bb.capacity()];
114        bb.get(fontData, 0, fontData.length);
115               
116                log.debug("bytes: " + fontData.length);
117               
118                log.info("deObfuscating with fontkey: " + fontKey);                     
119                // INPUT: {1DF903E3-2F14-4575-8028-881FEBABF2AB}
120
121                // See http://openiso.org/Ecma/376/Part4/2.8.1
122                // for how to do this.
123               
124               
125                // First, strip {,}
126                String tmpString = fontKey.substring(1, fontKey.length()-1);
127                log.debug(tmpString);
128               
129                // Now strip -
130                String guidString = tmpString.replace(target, replacement);
131                log.debug(guidString);
132
133               
134                // Make the font key into a byte array
135                byte[] guidByteArray = new byte[16];
136                for (int i = 0; i < guidByteArray.length; i++) {
137                        guidByteArray[i] = fromHexString(guidString.substring(i * 2,
138                                        (i * 2) + 2));
139                }
140               
141                // XOR the reverse of the guidByteArray with
142                // the first and second 16 bytes
143                for (int j = 0; j < 2; j++) {
144                        for (int i = 0; i < 16; i++) {
145                                fontData[(j * 16) + i] ^= guidByteArray[15 - i];  // Reverse happens here
146                        }
147                }
148               
149                // Save the result
150                java.io.File f = new File(tmpFontDir, fontName +".ttf"); 
151                String path = null; 
152               
153                java.io.FileOutputStream fos = null; 
154                try {
155                        path = f.getCanonicalPath();
156                        fos = new java.io.FileOutputStream(f);
157                        fos.write(fontData);
158                        log.debug("wrote: " + fontData.length);
159                        fos.close();
160                } catch (IOException e) {
161                        // TODO Auto-generated catch block
162                        e.printStackTrace();
163                } 
164               
165                log.info("Done!");
166               
167                // Save to "Temporary Font Files" directory.
168        FontResolver fontResolver = FontSetup.createMinimalFontResolver();
169
170                if (log.isDebugEnabled()) {
171                CustomFont customFont = null;
172                try {
173                        log.debug("Loading from: " + path);
174                        String subFontName = null; // TODO set this if its a TTC
175                        boolean embedded = true;   
176                        boolean useKerning = true;
177                    customFont = FontLoader.loadFont("file:" + path, 
178                                subFontName, embedded, EncodingMode.AUTO, useKerning, fontResolver);
179                } catch (Exception e) {
180                                e.printStackTrace();
181                }
182                if (customFont!=null) {
183                        log.info("Successfully reloaded " + customFont.getFontName());
184                        if (customFont.isEmbeddable()) {
185                                log.debug("confirmed embeddable");
186                        } else {
187                                // Sanity check
188                                log.error("this embedded font claims it is not embeddable!");                   
189                        }
190                }
191                }
192               
193                // Add this font to our known physical fonts 
194        try {
195                        org.docx4j.fonts.PhysicalFonts.addPhysicalFont(new java.net.URL("file:" + path) );
196                       
197                        // This needs to be done before populateFontMappings,
198                        // otherwise this font will be ignored, and references
199                        // to it mapped to some substitute font!
200                       
201                } catch (MalformedURLException e) {
202                        // TODO Auto-generated catch block
203                        e.printStackTrace();
204                }
205               
206        }
207       
208       
209        public static byte fromHexString( String hexStr ){
210        byte firstNibble  = Byte.parseByte(hexStr.substring(0,1),16); 
211        byte secondNibble = Byte.parseByte(hexStr.substring(1,2),16);
212        int finalByte = (secondNibble) | (firstNibble << 4 ); 
213        return (byte) finalByte;
214        }
215       
216       
217        static java.lang.CharSequence target = (new String("-")).subSequence(0, 1);
218    static java.lang.CharSequence replacement = (new String("")).subSequence(0, 0);
219       
220       
221       
222}
Note: See TracBrowser for help on using the repository browser.