1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Implements the `mnit::assets` services with a wraper around the filesystem
18 # API provided by the Android ndk.
20 # This module relies heavily on 3 C libraries:
22 # * zlib (which is included in the Android ndk)
23 # * libpng which must be provided by the Nit compilation framework
35 void mnit_android_png_read_data(png_structp png_ptr,
36 png_bytep data, png_size_t length)
38 struct AAsset *recv = png_get_io_ptr(png_ptr);
39 int read = AAsset_read(recv, data, length);
41 void mnit_android_png_error_fn(png_structp png_ptr,
42 png_const_charp error_msg)
44 LOGW("libpng error: %s", error_msg);
46 void mnit_android_png_warning_fn(png_structp png_ptr,
47 png_const_charp warning_msg)
49 LOGW("libpng warning: %s", warning_msg);
53 extern class AndroidAsset in "C" `{struct AAsset*`}
55 fun read(count: Int): nullable String is extern import String.as nullable, NativeString.to_s `{
56 char
*buffer
= malloc
(sizeof
(char
) * (count
+1));
57 int read
= AAsset_read(recv
, buffer
, count
);
63 return String_as_nullable(NativeString_to_s(buffer
));
67 fun length: Int is extern `{
68 return AAsset_getLength(recv
);
71 fun to_fd: Int is extern `{
74 int fd
= AAsset_openFileDescriptor(recv
, &start
, &length
);
78 fun close is extern `{
84 redef fun try_loading_asset(path)
86 var a = load_asset_from_apk(path)
88 if path.file_extension == "png" then
89 var png = new Opengles1Image.from_android_asset(a)
92 else if path.file_extension == "txt" then
98 print "didn't get asset {path}"
104 protected fun load_asset_from_apk(path: String): nullable AndroidAsset is extern import String.to_cstring, AndroidAsset.as nullable, native_app_glue `{
105 struct android_app
*native_app_glue
= App_native_app_glue(recv
);
106 struct
AAsset* a
= AAssetManager_open(native_app_glue-
>activity-
>assetManager
, String_to_cstring(path
), AASSET_MODE_BUFFER);
110 return null_AndroidAsset
();
114 return AndroidAsset_as_nullable(a
);
119 redef class Opengles1Image
120 # Read a png from a zipped stream
121 new from_android_asset(asset: AndroidAsset) is extern `{
122 struct mnit_opengles_Texture
*recv
= NULL;
124 png_structp png_ptr
= NULL;
125 png_infop info_ptr
= NULL;
127 png_uint_32 width
, height
;
128 int depth
, color_type
;
131 unsigned int row_bytes
;
132 png_bytepp row_pointers
= NULL;
133 unsigned char
*pixels
= NULL;
136 unsigned char sig
[8];
137 int sig_read
= AAsset_read(asset
, sig
, 8);
138 if (png_sig_cmp
(sig
, 0, sig_read
)) {
139 LOGW("invalide png signature");
143 png_ptr
= png_create_read_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
144 if (png_ptr
== NULL) {
145 LOGW("png_create_read_struct failed");
148 png_set_error_fn
(png_ptr
, NULL, mnit_android_png_error_fn
, mnit_android_png_warning_fn
);
150 info_ptr
= png_create_info_struct
(png_ptr
);
151 if (info_ptr
== NULL) {
152 LOGW("png_create_info_struct failed");
156 if (setjmp
(png_jmpbuf
(png_ptr
))) {
157 LOGW("reading png file failed");
161 png_set_read_fn
(png_ptr
, (void
*)asset
, mnit_android_png_read_data
);
163 png_set_sig_bytes
(png_ptr
, sig_read
);
165 png_read_info
(png_ptr
, info_ptr
);
167 png_get_IHDR
( png_ptr
, info_ptr
, &width
, &height
,
168 &depth
, &color_type
, NULL, NULL, NULL);
169 has_alpha
= color_type
& PNG_COLOR_MASK_ALPHA;
171 // If we get gray
and alpha only
, standardize the format of the pixels
.
172 // GA is not supported by
OpenGL ES 1.
173 if (!(color_type
& PNG_COLOR_MASK_COLOR)) {
174 png_set_gray_to_rgb
(png_ptr
);
175 png_set_palette_to_rgb
(png_ptr
);
176 png_read_update_info
(png_ptr
, info_ptr
);
179 LOGW("w: %i, h: %i", width
, height
);
181 row_bytes
= png_get_rowbytes
(png_ptr
, info_ptr
);
182 pixels
= malloc
(row_bytes
* height
);
183 row_pointers
= (png_bytep
*) malloc
(sizeof
(png_bytep
) * height
);
185 for (i
=0; i
<height
; i
++)
186 row_pointers
[i
] = (png_byte
*) malloc
(row_bytes
);
188 png_read_image
(png_ptr
, row_pointers
);
190 for (i
= 0; i
< height
; i
++)
191 memcpy
(pixels
+ (row_bytes
*i
),
192 row_pointers
[i
], row_bytes
);
194 recv
= mnit_opengles_load_image
((const uint_least32_t
*)pixels
, width
, height
, has_alpha
);
198 if (info_ptr
!= NULL)
199 png_destroy_read_struct
(&png_ptr
, &info_ptr
, NULL);
201 png_destroy_read_struct
(&png_ptr
, NULL, NULL);
206 if (row_pointers
!= NULL) {
207 for (i
=0; i
<height
; i
++)
208 free
(row_pointers
[i
]);