Skip to content

Commit

Permalink
fix for screenshot's base64 string NULL-termination (pxscene#768)
Browse files Browse the repository at this point in the history
  • Loading branch information
npoltorapavlo authored and mfiess committed Jan 10, 2018
1 parent 6cdff9d commit df0c92e
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 7 deletions.
7 changes: 2 additions & 5 deletions examples/pxScene2d/src/pxScene2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,6 @@ char *base64_encode(const unsigned char *data,
for (int i = 0; i < mod_table[input_length % 3]; i++)
encoded_data[*output_length - 1 - i] = '=';

#ifdef PX_PLATFORM_MAC
encoded_data[*output_length] = '\0';
#endif //PX_PLATFORM_MAC

return encoded_data;
}

Expand Down Expand Up @@ -2939,7 +2935,8 @@ rtError pxScene2d::screenshot(rtString type, rtString& pngData)
{
// We return a data Url string containing the image data
pngData = "data:image/png;base64,";
pngData.append(d);
rtString base64str(d, l); // NULL-terminated
pngData.append(base64str.cString());
free(d);
return RT_OK;
}
Expand Down
2 changes: 2 additions & 0 deletions examples/pxScene2d/src/pxScene2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ extern rtThreadQueue gUIThreadQueue;
// Constants
static pxConstants CONSTANTS;

char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length);
unsigned char *base64_decode(const unsigned char *data, size_t input_length, size_t *output_length);

#if 0
typedef rtError (*objectFactory)(void* context, const char* t, rtObjectRef& o);
Expand Down
4 changes: 2 additions & 2 deletions tests/pxScene2d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
set(BUILD_UNIT_TEST 1)
set(TEST_WAYLAND_SOURCE_FILES "")
#set(TEST_WAYLAND_SOURCE_FILES test_pxWayland.cpp test_pxWaylandContainer.cpp)
set(PLATFORM_TEST_FILES test_jsfiles.cpp test_rtError.cpp test_pxUtil.cpp)
set(PLATFORM_TEST_FILES test_jsfiles.cpp test_rtError.cpp test_pxUtil.cpp test_screenshot.cpp)
if (PXSCENE_TEST_HTTP_CACHE)
message("Enabling http cache tests")
set(PLATFORM_TEST_FILES ${PLATFORM_TEST_FILES} test_imagecache.cpp)
Expand Down Expand Up @@ -110,7 +110,7 @@ add_definitions(-D${PX_PLATFORM} -DENABLE_RT_NODE -DRUNINMAIN -DENABLE_HTTP_CACH

set(TEST_SOURCE_FILES pxscene2dtestsmain.cpp test_example.cpp test_api.cpp test_pxcontext.cpp test_memoryleak.cpp test_rtnode.cpp test_rtMutex.cpp
test_pxAnimate.cpp test_rtFile.cpp test_rtZip.cpp test_rtString.cpp test_rtValue.cpp test_pxImage.cpp test_pxOffscreen.cpp test_pxMatrix4T.cpp test_rtObject.cpp
test_pxWindowUtil.cpp test_pxTexture.cpp test_pxWindow.cpp test_ioapi.cpp test_rtLog.cpp test_pxTimerNative.cpp
test_pxWindowUtil.cpp test_pxTexture.cpp test_pxWindow.cpp test_ioapi.cpp test_rtLog.cpp test_pxTimerNative.cpp
test_rtUrlUtils.cpp test_pxArchive.cpp ${PLATFORM_TEST_FILES} ${TEST_WAYLAND_SOURCE_FILES})

if (DEFINED ENV{USE_HTTP_CACHE})
Expand Down
188 changes: 188 additions & 0 deletions tests/pxScene2d/test_screenshot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#include <sstream>

#include "pxScene2d.h"
#include "pxContext.h"
#include "pxWindow.h"
#include "test_includes.h" // Needs to be included last

class screenshotTest : public testing::Test
{
public:
virtual void SetUp()
{
}

virtual void TearDown()
{
}

void test_scene_screenshot()
{
pxScene2d* scene = new pxScene2d(true, NULL);
rtString type("image/png;base64");
rtString pngData;
EXPECT_EQ ((int)RT_OK, (int)scene->screenshot(type, pngData));
EXPECT_GT ((int)pngData.length(), 0);
delete scene;
}

void test_base64_encode()
{
for (int i = 0; i<100; i++)
{
rtData pngData2;
pngData2.init(i);
size_t l;
char* d = base64_encode(pngData2.data(), pngData2.length(), &l);
EXPECT_EQ ((int)l, 4*((i+2)/3));
EXPECT_TRUE (i == 0 || (NULL != d && *d != 0));
if (NULL != d && *d != 0)
{
size_t sl = strlen(rtString(d, l).cString());
EXPECT_EQ (sl, l);
free(d);
}
}
}

void test_base64_encode_decode()
{
for (int i = 0; i<100; i++)
{
rtData pngData2;
pngData2.init(i);
size_t l;
char* d = base64_encode(pngData2.data(), pngData2.length(), &l);
EXPECT_TRUE (i == 0 || (NULL != d && *d != 0));
if (NULL != d && *d != 0)
{
size_t l2;
unsigned char *d2 = base64_decode((const unsigned char *)d, l, &l2);
EXPECT_TRUE (NULL != d2);
if (d2)
{
int eq = memcmp(pngData2.data(), d2, pngData2.length());
EXPECT_EQ (eq, 0);
free(d2);
}
free(d);
}
}
}

void test_pxStorePNGImage_empty()
{
pxOffscreen o;
o.setUpsideDown(true);
rtData pngData2;
EXPECT_EQ ((int)RT_OK, (int)pxStorePNGImage(o, pngData2));
EXPECT_EQ ((int)pngData2.length(), 0);
}

void test_pxStorePNGImage_zero()
{
pxOffscreen o;
EXPECT_EQ (RT_OK, o.init(0, 0));
o.setUpsideDown(true);
rtData pngData2;
EXPECT_EQ ((int)RT_OK, (int)pxStorePNGImage(o, pngData2));
EXPECT_EQ ((int)pngData2.length(), 0);
}

void test_pxStorePNGImage_normal()
{
for (int i = 1; i<=100; i++)
{
pxOffscreen o;
EXPECT_EQ ((int)RT_OK, (int)o.init(i, i));
o.setUpsideDown(true);
rtData pngData2;
EXPECT_EQ ((int)RT_OK, (int)pxStorePNGImage(o, pngData2));
EXPECT_GT ((int)pngData2.length(), 0);
}
}

void test_pixels()
{
int fbo_w = 101;
int fbo_h = 102;
pxContext c;
c.init();
pxContextFramebufferRef f = c.createFramebuffer(fbo_w,fbo_h,false);
rtError e = c.setFramebuffer(NULL);
EXPECT_EQ ((int)RT_OK, (int)e);
if (RT_OK != e)
return;

e = c.setFramebuffer(f);
EXPECT_EQ ((int)RT_OK, (int)e);
if (RT_OK != e)
return;

float fillColor[] = {0,0,0,0};
c.clear(0,0,fillColor);
float fillColorRect[4] = {1,0,1,1};
float lineColorRect[4] = {1,1,0,1};
c.drawRect(fbo_w,fbo_h,10,fillColorRect,lineColorRect);
pxOffscreen o;
GLint mode;
glGetIntegerv(GL_READ_BUFFER, &mode);
glReadBuffer(GL_COLOR_ATTACHMENT0);
c.snapshot(o);
glReadBuffer(mode);

// verify image
EXPECT_TRUE (o.upsideDown());
EXPECT_EQ (fbo_w,o.width());
EXPECT_EQ (fbo_h,o.height());

if (o.width() != fbo_w || o.height() != fbo_h)
return;

pxPixel* pix1 = o.pixel(0,0);
EXPECT_EQ (lineColorRect[0]*255, pix1->r);
EXPECT_EQ (lineColorRect[1]*255, pix1->g);
EXPECT_EQ (lineColorRect[2]*255, pix1->b);

pxPixel* pix2 = o.pixel(fbo_w/2,fbo_h/2);
EXPECT_EQ (fillColorRect[0]*255, pix2->r);
EXPECT_EQ (fillColorRect[1]*255, pix2->g);
EXPECT_EQ (fillColorRect[2]*255, pix2->b);

// pxOffscreen <-> PNG
rtData pngData2;
EXPECT_EQ ((int)RT_OK, (int)pxStorePNGImage(o, pngData2));
EXPECT_GT ((int)pngData2.length(), 0);
pxOffscreen o2;
EXPECT_EQ ((int)RT_OK, (int)pxLoadPNGImage((const char *)pngData2.data(), pngData2.length(), o2));

// verify image
EXPECT_FALSE (o2.upsideDown());
EXPECT_EQ (fbo_w,o2.width());
EXPECT_EQ (fbo_h,o2.height());

if (o2.width() != fbo_w || o2.height() != fbo_h)
return;

pix1 = o2.pixel(0,0);
EXPECT_EQ (lineColorRect[0]*255, pix1->r);
EXPECT_EQ (lineColorRect[1]*255, pix1->g);
EXPECT_EQ (lineColorRect[2]*255, pix1->b);

pix2 = o2.pixel(fbo_w/2,fbo_h/2);
EXPECT_EQ (fillColorRect[0]*255, pix2->r);
EXPECT_EQ (fillColorRect[1]*255, pix2->g);
EXPECT_EQ (fillColorRect[2]*255, pix2->b);
}
};

TEST_F(screenshotTest, screenshotTests)
{
test_scene_screenshot();
test_base64_encode();
test_base64_encode_decode();
test_pxStorePNGImage_empty();
test_pxStorePNGImage_zero();
test_pxStorePNGImage_normal();
test_pixels();
}

0 comments on commit df0c92e

Please sign in to comment.