d744308e8eb3303b4cc2e84b0400f4d19c85b881
[platform/core/uifw/dali-adaptor.git] / platform-abstractions / emscripten / emscripten-platform-abstraction.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include "emscripten-platform-abstraction.h"
19
20 // EXTERNAL INCLUDES
21 #include <set>
22 #include <stdint.h>
23 #include <cstring>
24 #include <SDL_surface.h>
25 #include <SDL_image.h>
26 #include "emscripten/emscripten.h"
27 #include "emscripten-callbacks.h"
28
29 #define EM_LOG(x); // EM_ASM( console.log( x ) );
30
31
32 // INTERNAL INCLUDES
33 #include <dali/integration-api/platform-abstraction.h>
34 #include <dali/devel-api/common/ref-counted-dali-vector.h>
35
36 namespace
37 {
38
39 Dali::Integration::BitmapPtr LoadResourceEncodedImage( Dali::RefCountedVector<uint8_t>* encodedBlob )
40 {
41   Dali::Integration::BitmapPtr bitmapPtr = NULL;
42
43   if( encodedBlob != 0 )
44   {
45     const size_t blobSize     = encodedBlob->GetVector().Size();
46     uint8_t * const blobBytes = &(encodedBlob->GetVector()[0]);
47     DALI_ASSERT_DEBUG( blobSize > 0U );
48     DALI_ASSERT_DEBUG( blobBytes != 0U );
49
50     if( blobBytes != 0 && blobSize > 0U )
51     {
52
53       SDL_RWops *memory = SDL_RWFromMem(blobBytes, blobSize);
54
55       if(!memory)
56       {
57         printf("  Error Null pointer from SDL RW memory?\n");
58       }
59
60       SDL_Surface *surface = IMG_Load_RW(memory, 0);
61
62       if(surface)
63       {
64         bitmapPtr = Dali::Integration::Bitmap::New( Dali::Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,
65                                                     Dali::ResourcePolicy::OWNED_DISCARD ); // DISCARD; Dali manages
66
67         Dali::Integration::Bitmap::PackedPixelsProfile* packedProfile = bitmapPtr->GetPackedPixelsProfile();
68         DALI_ASSERT_ALWAYS(packedProfile);
69
70         unsigned char bytesPerPixel = surface->format->BytesPerPixel;
71
72         Dali::Integration::PixelBuffer* pixels = NULL;
73
74         unsigned char targetBytesPerPixel = 3; // bytesPerPixel;
75
76         // SDL in emscripten returns us a 4byteperpixel image regardless of rgb/png etc
77         // Theres no apparent way to differentiate an image with an alpha channel
78         // In Dali if an image has an alpha channel it gets sorted. This introduces odd artifacts on rotation
79         // as the sorting algorithm presumes front on view.
80         // So here well just support pngs with an alpha channel.
81         // We're poking around in the format as emscripten currently lacks a file memory api where we could use
82         // Dali's machinery to read the format.
83         unsigned char *pBytes = blobBytes;
84
85         if( 0x89 == *(pBytes+0) && 0x50 == *(pBytes+1) ) // magic bytes for png_all_filters
86         {
87           pBytes+=8; // 8 bytes for header
88           pBytes+=4; // 4 bytes for chunk length
89           pBytes+=4; // 4 bytes for chunk type
90           // ihdr data (must be first chunk)
91           pBytes+=4; // 4 for width,height
92           pBytes+=4;
93           pBytes+=1; // 1 for bit depth
94           unsigned char ihdr_colorType= *pBytes;    // 1 for bit colorType
95           if( (4 == ihdr_colorType ||               // 4 is 8,16 bit depth with alpha LA
96                6 == ihdr_colorType) )               // 6 is 8,16 bit depth with alpha RGBA
97           {
98             targetBytesPerPixel = 4;
99           }
100         }
101
102         if(3 == targetBytesPerPixel)
103         {
104           pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGB888,
105                                                 surface->w, surface->h,
106                                                 surface->w, surface->h);
107         }
108         else if(4 == targetBytesPerPixel)
109         {
110           pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGBA8888,
111                                                 surface->w, surface->h,
112                                                 surface->w, surface->h);
113         }
114         else
115         {
116           DALI_ASSERT_ALWAYS(0 && "bad bytes per pixel");
117         }
118
119         unsigned char* fromPtr = static_cast<unsigned char*>(surface->pixels);
120
121         int stride = surface->pitch;
122         int index = 0;
123         for(int h = 0; h < surface->h; ++h)
124         {
125           for(int w = 0; w < (surface->w*bytesPerPixel); w+=bytesPerPixel)
126           {
127             for(int j = 0; j < targetBytesPerPixel; ++j)
128             {
129               pixels[ index++ ] = *( (fromPtr + (h * stride) ) + w + j );
130             }
131           }
132         }
133       } // if surface
134       else
135       {
136         printf("  Error empty surface when decoding image? (SDL RW Memory ptr=%llx) %s. %d\n", (long long)(memory), SDL_GetError(), blobSize);
137       }
138
139     } // if blobSize
140     else
141     {
142       printf(" Error No bytes in image?\n");
143     }
144
145   } // if encodedBlob
146   else
147   {
148     printf("  Error Null pointer given for decoding image?\n");
149   }
150
151   if(bitmapPtr)
152   {
153     int x = 0;
154     EM_ASM( console.log( "LoadResourceEncodedImage: Image:-" ) );
155     x = EM_ASM_INT({
156         console.log( $0 ) }, bitmapPtr->GetImageWidth() );
157     x = EM_ASM_INT({
158         console.log( $0 ) }, bitmapPtr->GetImageHeight() );
159     x = EM_ASM_INT({
160         console.log( $0 ) }, bitmapPtr->GetBufferSize() );
161
162   }
163   else
164   {
165     EM_ASM( console.log( "LoadResourceEncodedImage: no bitmap data?" ) );
166   }
167
168   return bitmapPtr;
169 }
170
171 } // anon namespace
172
173 namespace Dali
174 {
175
176 EmscriptenPlatformAbstraction::EmscriptenPlatformAbstraction()
177   :
178     mSize(10,10)
179 {
180 }
181
182
183 EmscriptenPlatformAbstraction::~EmscriptenPlatformAbstraction()
184 {
185 }
186
187 void EmscriptenPlatformAbstraction::GetTimeMicroseconds(unsigned int &seconds, unsigned int &microSeconds)
188 {
189   double current = EM_ASM_DOUBLE_V({ return new Date().getTime(); }); // getTime() in ms
190
191   seconds         = static_cast<unsigned int>(current/1000.0);
192   microSeconds    = (static_cast<unsigned int>(current) - seconds*1000.0) * 1000;
193 }
194
195 ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( const std::string& filename,
196                                                              ImageDimensions size,
197                                                              FittingMode::Type fittingMode,
198                                                              SamplingMode::Type samplingMode,
199                                                              bool orientationCorrection )
200 {
201   return Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
202 }
203
204 ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
205                                                              ImageDimensions size,
206                                                              FittingMode::Type fittingMode,
207                                                              SamplingMode::Type samplingMode,
208                                                              bool orientationCorrection )
209 {
210   // @todo
211   return Dali::ImageDimensions(); // Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
212 }
213
214 Integration::ResourcePointer EmscriptenPlatformAbstraction::LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath )
215 {
216   Integration::ResourcePointer ret;
217
218   switch(resourceType.id)
219   {
220     case Integration::ResourceBitmap:
221     {
222       const Integration::BitmapResourceType& bitmapResource( static_cast<const Integration::BitmapResourceType&>(resourceType) );
223
224       Integration::BitmapPtr bitmapPtr = Dali::Internal::Emscripten::GetImage( bitmapResource.size,
225                                                                                bitmapResource.scalingMode,
226                                                                                bitmapResource.samplingMode,
227                                                                                bitmapResource.orientationCorrection,
228                                                                                resourcePath );
229
230       ret = bitmapPtr;
231     }
232     break;
233   } // switch(resourceType->id)
234
235   return ret;
236 }
237
238 Integration::BitmapPtr EmscriptenPlatformAbstraction::DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t bufferSize )
239 {
240   return Integration::BitmapPtr();
241 }
242
243
244 bool EmscriptenPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
245 {
246   EM_LOG("EmscriptenPlatformAbstraction::LoadShaderBinaryFile");
247   return false;
248 }
249
250 void EmscriptenPlatformAbstraction::UpdateDefaultsFromDevice()
251 {
252   DALI_ASSERT_ALWAYS("!Unimplemented");
253   mGetDefaultFontFamilyResult+=1.0f;
254 }
255
256 void EmscriptenPlatformAbstraction::IncrementGetTimeResult(size_t milliseconds)
257 {
258 }
259
260 } // Dali