12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "jni.h"
27 #include "jni_util.h"
28 #include "jlong.h"
29 #include "sunfontids.h"
30 #include "sun_font_FreetypeFontScaler.h"
31
32 #include<stdlib.h>
33 #include <math.h>
34 #include "ft2build.h"
35 #include FT_FREETYPE_H
36 #include FT_GLYPH_H
37 #include FT_BBOX_H
38 #include FT_SIZES_H
39 #include FT_OUTLINE_H
40 #include FT_SYNTHESIS_H
41 #include FT_LCD_FILTER_H
42
43 #include "fontscaler.h"
44
45 #define ftFixed1 (FT_Fixed) (1 << 16)
46 #define FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1))
47 #define FTFixedToFloat(x) ((x) / (float)(ftFixed1))
48 #define FT26Dot6ToFloat(x) ((x) / ((float) (1<<6)))
49 #define FT26Dot6ToInt(x) (((int)(x)) >> 6)
50
51 typedef struct {
52 /* Important note:
53 JNI forbids sharing same env between different threads.
54 We are safe, because pointer is overwritten every time we get into
55 JNI call (see setupFTContext).
56
57 Pointer is used by font data reading callbacks
58 such as ReadTTFontFileFunc.
59
60 NB: We may consider switching to JNI_GetEnv. */
61 JNIEnv* env;
187 unsigned cacheOffset = offset - scalerInfo->fontDataOffset;
188
189 memcpy(destBuffer, scalerInfo->fontData+(size_t)cacheOffset, numBytes);
190 return numBytes;
191 } else {
192 /* Must fill the cache */
193 scalerInfo->fontDataOffset = offset;
194 scalerInfo->fontDataLength =
195 (offset + FILEDATACACHESIZE > scalerInfo->fileSize) ?
196 scalerInfo->fileSize - offset : FILEDATACACHESIZE;
197 bBuffer = scalerInfo->directBuffer;
198 bread = (*env)->CallIntMethod(env, scalerInfo->font2D,
199 sunFontIDs.ttReadBlockMID,
200 bBuffer, offset,
201 scalerInfo->fontDataLength);
202 memcpy(destBuffer, scalerInfo->fontData, numBytes);
203 return numBytes;
204 }
205 }
206
207 /*
208 * Class: sun_font_FreetypeFontScaler
209 * Method: initNativeScaler
210 * Signature: (Lsun/font/Font2D;IIZI)J
211 */
212 JNIEXPORT jlong JNICALL
213 Java_sun_font_FreetypeFontScaler_initNativeScaler(
214 JNIEnv *env, jobject scaler, jobject font2D, jint type,
215 jint indexInCollection, jboolean supportsCJK, jint filesize) {
216 FTScalerInfo* scalerInfo = NULL;
217 FT_Open_Args ft_open_args;
218 int error;
219 jobject bBuffer;
220 scalerInfo = (FTScalerInfo*) calloc(1, sizeof(FTScalerInfo));
221
222 if (scalerInfo == NULL)
223 return 0;
224
225 scalerInfo->env = env;
226 scalerInfo->font2D = font2D;
227 scalerInfo->fontDataOffset = 0;
228 scalerInfo->fontDataLength = 0;
229 scalerInfo->fileSize = filesize;
230
231 /*
232 We can consider sharing freetype library between different
233 scalers. However, Freetype docs suggest to use different libraries
234 for different threads. Also, our architecture implies that single
235 FontScaler object is shared for different sizes/transforms/styles
236 of the same font.
237
238 On other hand these methods can not be concurrently executed
239 becaused they are "synchronized" in java.
240 */
241 error = FT_Init_FreeType(&scalerInfo->library);
242 if (error) {
243 free(scalerInfo);
244 return 0;
245 }
246
247 #define TYPE1_FROM_JAVA 2
248
249 error = 1; /* triggers memory freeing unless we clear it */
250 if (type == TYPE1_FROM_JAVA) { /* TYPE1 */
251 scalerInfo->fontData = (unsigned char*) malloc(filesize);
252 scalerInfo->directBuffer = NULL;
253 scalerInfo->fontDataLength = filesize;
254
255 if (scalerInfo->fontData != NULL) {
256 bBuffer = (*env)->NewDirectByteBuffer(env,
257 scalerInfo->fontData,
258 scalerInfo->fontDataLength);
259 if (bBuffer != NULL) {
260 (*env)->CallVoidMethod(env, font2D,
261 sunFontIDs.readFileMID, bBuffer);
262
263 error = FT_New_Memory_Face(scalerInfo->library,
264 scalerInfo->fontData,
265 scalerInfo->fontDataLength,
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "jni.h"
27 #include "jni_util.h"
28 #include "jlong.h"
29 #include "sunfontids.h"
30 #include "sun_font_FreetypeFontScaler.h"
31
32 #include <stdlib.h>
33 #if !defined(_WIN32) && !defined(__APPLE_)
34 #include <dlfcn.h>
35 #endif
36 #include <math.h>
37 #include "ft2build.h"
38 #include FT_FREETYPE_H
39 #include FT_GLYPH_H
40 #include FT_BBOX_H
41 #include FT_SIZES_H
42 #include FT_OUTLINE_H
43 #include FT_SYNTHESIS_H
44 #include FT_LCD_FILTER_H
45 #include FT_MODULE_H
46
47 #include "fontscaler.h"
48
49 #define ftFixed1 (FT_Fixed) (1 << 16)
50 #define FloatToFTFixed(f) (FT_Fixed)((f) * (float)(ftFixed1))
51 #define FTFixedToFloat(x) ((x) / (float)(ftFixed1))
52 #define FT26Dot6ToFloat(x) ((x) / ((float) (1<<6)))
53 #define FT26Dot6ToInt(x) (((int)(x)) >> 6)
54
55 typedef struct {
56 /* Important note:
57 JNI forbids sharing same env between different threads.
58 We are safe, because pointer is overwritten every time we get into
59 JNI call (see setupFTContext).
60
61 Pointer is used by font data reading callbacks
62 such as ReadTTFontFileFunc.
63
64 NB: We may consider switching to JNI_GetEnv. */
65 JNIEnv* env;
191 unsigned cacheOffset = offset - scalerInfo->fontDataOffset;
192
193 memcpy(destBuffer, scalerInfo->fontData+(size_t)cacheOffset, numBytes);
194 return numBytes;
195 } else {
196 /* Must fill the cache */
197 scalerInfo->fontDataOffset = offset;
198 scalerInfo->fontDataLength =
199 (offset + FILEDATACACHESIZE > scalerInfo->fileSize) ?
200 scalerInfo->fileSize - offset : FILEDATACACHESIZE;
201 bBuffer = scalerInfo->directBuffer;
202 bread = (*env)->CallIntMethod(env, scalerInfo->font2D,
203 sunFontIDs.ttReadBlockMID,
204 bBuffer, offset,
205 scalerInfo->fontDataLength);
206 memcpy(destBuffer, scalerInfo->fontData, numBytes);
207 return numBytes;
208 }
209 }
210
211 typedef FT_Error (*FT_Prop_Set_Func)(FT_Library library,
212 const FT_String* module_name,
213 const FT_String* property_name,
214 const void* value );
215
216 /**
217 * Prefer the older v35 freetype byte code interpreter.
218 */
219 static void setInterpreterVersion(FT_Library library) {
220
221 char* props = getenv("FREETYPE_PROPERTIES");
222 int version = 35;
223 const char* module = "truetype";
224 const char* property = "interpreter-version";
225
226 /* If some one is setting this, don't override it */
227 if (props != NULL && strstr(property, props)) {
228 return;
229 }
230 /*
231 * FT_Property_Set was introduced in 2.4.11.
232 * Some older supported Linux OSes may not include it so look
233 * this up dynamically.
234 * And if its not available it doesn't matter, since the reason
235 * we need it dates from 2.7.
236 * On Windows & Mac the library is always bundled so it is safe
237 * to use directly in those cases.
238 */
239 #if defined(_WIN32) || defined(__APPLE__)
240 FT_Property_Set(library, module, property, (void*)(&version));
241 #else
242 void *lib = dlopen("libfreetype.so", RTLD_LOCAL|RTLD_LAZY);
243 if (lib == NULL) {
244 lib = dlopen("libfreetype.so.6", RTLD_LOCAL|RTLD_LAZY);
245 if (lib == NULL) {
246 return;
247 }
248 }
249 FT_Prop_Set_Func func = (FT_Prop_Set_Func)dlsym(lib, "FT_Property_Set");
250 if (func != NULL) {
251 func(library, module, property, (void*)(&version));
252 }
253 dlclose(lib);
254 #endif
255 }
256
257 /*
258 * Class: sun_font_FreetypeFontScaler
259 * Method: initNativeScaler
260 * Signature: (Lsun/font/Font2D;IIZI)J
261 */
262 JNIEXPORT jlong JNICALL
263 Java_sun_font_FreetypeFontScaler_initNativeScaler(
264 JNIEnv *env, jobject scaler, jobject font2D, jint type,
265 jint indexInCollection, jboolean supportsCJK, jint filesize) {
266 FTScalerInfo* scalerInfo = NULL;
267 FT_Open_Args ft_open_args;
268 int error;
269 jobject bBuffer;
270 scalerInfo = (FTScalerInfo*) calloc(1, sizeof(FTScalerInfo));
271
272 if (scalerInfo == NULL)
273 return 0;
274
275 scalerInfo->env = env;
276 scalerInfo->font2D = font2D;
277 scalerInfo->fontDataOffset = 0;
278 scalerInfo->fontDataLength = 0;
279 scalerInfo->fileSize = filesize;
280
281 /*
282 We can consider sharing freetype library between different
283 scalers. However, Freetype docs suggest to use different libraries
284 for different threads. Also, our architecture implies that single
285 FontScaler object is shared for different sizes/transforms/styles
286 of the same font.
287
288 On other hand these methods can not be concurrently executed
289 becaused they are "synchronized" in java.
290 */
291 error = FT_Init_FreeType(&scalerInfo->library);
292 if (error) {
293 free(scalerInfo);
294 return 0;
295 }
296 setInterpreterVersion(scalerInfo->library);
297
298 #define TYPE1_FROM_JAVA 2
299
300 error = 1; /* triggers memory freeing unless we clear it */
301 if (type == TYPE1_FROM_JAVA) { /* TYPE1 */
302 scalerInfo->fontData = (unsigned char*) malloc(filesize);
303 scalerInfo->directBuffer = NULL;
304 scalerInfo->fontDataLength = filesize;
305
306 if (scalerInfo->fontData != NULL) {
307 bBuffer = (*env)->NewDirectByteBuffer(env,
308 scalerInfo->fontData,
309 scalerInfo->fontDataLength);
310 if (bBuffer != NULL) {
311 (*env)->CallVoidMethod(env, font2D,
312 sunFontIDs.readFileMID, bBuffer);
313
314 error = FT_New_Memory_Face(scalerInfo->library,
315 scalerInfo->fontData,
316 scalerInfo->fontDataLength,
|