summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--o3d/converter/cross/renderer_stub.cc5
-rw-r--r--o3d/converter/cross/renderer_stub.h8
-rw-r--r--o3d/converter/cross/texture_stub.h6
-rw-r--r--o3d/core/cross/bitmap.cc4
-rw-r--r--o3d/core/cross/bitmap.h9
-rw-r--r--o3d/core/cross/bitmap_png.cc87
-rw-r--r--o3d/core/cross/client.cc12
-rw-r--r--o3d/core/cross/client.h5
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.cc5
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.h5
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.h6
-rw-r--r--o3d/core/cross/gl/renderer_gl.cc16
-rw-r--r--o3d/core/cross/gl/renderer_gl.h5
-rw-r--r--o3d/core/cross/gl/texture_gl.h6
-rw-r--r--o3d/core/cross/gl/utils_gl.h6
-rw-r--r--o3d/core/cross/image_utils.h3
-rw-r--r--o3d/core/cross/image_utils_test.cc19
-rw-r--r--o3d/core/cross/object_base.h6
-rw-r--r--o3d/core/cross/precompile.h6
-rw-r--r--o3d/core/cross/renderer.h5
-rw-r--r--o3d/core/cross/sampler.h6
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.cc60
-rw-r--r--o3d/core/win/d3d9/renderer_d3d9.h5
-rw-r--r--o3d/plugin/cross/plugin_main.h6
-rw-r--r--o3d/plugin/idl/client.idl24
-rw-r--r--o3d/tests/build.scons2
-rw-r--r--o3d/tests/selenium/selenium_utilities.py14
-rw-r--r--o3d/utils/build.scons2
-rw-r--r--o3d/utils/cross/base64.cc90
-rw-r--r--o3d/utils/cross/base64.h56
-rw-r--r--o3d/utils/cross/base64_test.cc65
-rw-r--r--o3d/utils/cross/dataurl.cc53
-rw-r--r--o3d/utils/cross/dataurl.h52
-rw-r--r--o3d/utils/cross/dataurl_test.cc56
-rw-r--r--o3d/utils/utils.gyp6
35 files changed, 572 insertions, 149 deletions
diff --git a/o3d/converter/cross/renderer_stub.cc b/o3d/converter/cross/renderer_stub.cc
index c53d2d5..9f71be6 100644
--- a/o3d/converter/cross/renderer_stub.cc
+++ b/o3d/converter/cross/renderer_stub.cc
@@ -196,9 +196,8 @@ StreamBank::Ref RendererStub::CreateStreamBank() {
return StreamBank::Ref(new StreamBankStub(service_locator()));
}
-bool RendererStub::SaveScreen(const String &) {
- DCHECK(false);
- return true;
+Bitmap::Ref RendererStub::TakeScreenshot() {
+ return Bitmap::Ref();
}
ParamCache *RendererStub::CreatePlatformSpecificParamCache(void) {
diff --git a/o3d/converter/cross/renderer_stub.h b/o3d/converter/cross/renderer_stub.h
index afd5d41..9ebc860b 100644
--- a/o3d/converter/cross/renderer_stub.h
+++ b/o3d/converter/cross/renderer_stub.h
@@ -35,8 +35,8 @@
// can use it for serialization of the scene graph on all systems
// without needing graphics.
-#ifndef O3D_CONVERTER_CROSS_RENDERER_STUB_H__
-#define O3D_CONVERTER_CROSS_RENDERER_STUB_H__
+#ifndef O3D_CONVERTER_CROSS_RENDERER_STUB_H_
+#define O3D_CONVERTER_CROSS_RENDERER_STUB_H_
#include "core/cross/renderer.h"
@@ -79,7 +79,7 @@ class RendererStub : public Renderer {
virtual RenderDepthStencilSurface::Ref CreateDepthStencilSurface(int width,
int height);
virtual StreamBank::Ref CreateStreamBank();
- virtual bool SaveScreen(const String& file_name);
+ virtual Bitmap::Ref TakeScreenshot();
ParamCache *CreatePlatformSpecificParamCache();
virtual void SetViewportInPixels(int left,
int top,
@@ -123,4 +123,4 @@ class RendererStub : public Renderer {
} // namespace o3d
-#endif // O3D_CONVERTER_CROSS_RENDERER_STUB_H__
+#endif // O3D_CONVERTER_CROSS_RENDERER_STUB_H_
diff --git a/o3d/converter/cross/texture_stub.h b/o3d/converter/cross/texture_stub.h
index 43888d4..9ded546 100644
--- a/o3d/converter/cross/texture_stub.h
+++ b/o3d/converter/cross/texture_stub.h
@@ -32,8 +32,8 @@
// This file contains the declarations for Texture2DStub and TextureCUBEStub.
-#ifndef O3D_CONVERTER_CROSS_TEXTURE_STUB_H__
-#define O3D_CONVERTER_CROSS_TEXTURE_STUB_H__
+#ifndef O3D_CONVERTER_CROSS_TEXTURE_STUB_H_
+#define O3D_CONVERTER_CROSS_TEXTURE_STUB_H_
#include "core/cross/bitmap.h"
#include "core/cross/texture.h"
@@ -175,4 +175,4 @@ class TextureCUBEStub : public TextureCUBE {
} // namespace o3d
-#endif // O3D_CONVERTER_CROSS_TEXTURE_STUB_H__
+#endif // O3D_CONVERTER_CROSS_TEXTURE_STUB_H_
diff --git a/o3d/core/cross/bitmap.cc b/o3d/core/cross/bitmap.cc
index 8069451..cdccc66 100644
--- a/o3d/core/cross/bitmap.cc
+++ b/o3d/core/cross/bitmap.cc
@@ -146,8 +146,8 @@ void Bitmap::SetRect(
uint8* dst =
GetMipData(level) +
- image::ComputeMipChainSize(mip_width, dst_top, format(), 1) +
- image::ComputeMipChainSize(dst_left, 1, format(), 1);
+ image::ComputePitch(format(), mip_width) * dst_top +
+ image::ComputePitch(format(), dst_left);
const uint8* src = static_cast<const uint8*>(src_data);
if (!compressed) {
diff --git a/o3d/core/cross/bitmap.h b/o3d/core/cross/bitmap.h
index 5bd3687..a86b76a 100644
--- a/o3d/core/cross/bitmap.h
+++ b/o3d/core/cross/bitmap.h
@@ -242,13 +242,10 @@ class Bitmap : public ParamObject {
// from a flippable format back to a DXT format.
void FlipVertically();
- // Saves to a PNG file. The image must be of the ARGB8 format, be a 2D image
- // with no mip-maps (only the base level).
- // Parameters:
- // filename: the name of the file to into.
+ // Returns the contents of the bitmap as a data URL
// Returns:
- // true if successful.
- bool SaveToPNGFile(const char* filename);
+ // A data url that represents the content of the bitmap.
+ String ToDataURL();
// Checks that the alpha channel for the entire bitmap is 1.0
bool CheckAlphaIsOne() const;
diff --git a/o3d/core/cross/bitmap_png.cc b/o3d/core/cross/bitmap_png.cc
index 770ced0..047f585 100644
--- a/o3d/core/cross/bitmap_png.cc
+++ b/o3d/core/cross/bitmap_png.cc
@@ -37,6 +37,7 @@
#include <fstream>
#include "core/cross/bitmap.h"
+#include "core/cross/error.h"
#include "core/cross/types.h"
#include "utils/cross/file_path_utils.h"
#include "base/file_path.h"
@@ -44,22 +45,38 @@
#include "import/cross/memory_buffer.h"
#include "import/cross/memory_stream.h"
#include "png.h"
+#include "utils/cross/dataurl.h"
using file_util::OpenFile;
using file_util::CloseFile;
namespace o3d {
+namespace {
+
// Helper function for LoadFromPNGFile that converts a stream into the
// necessary abstract byte reading function.
-static void stream_read_data(png_structp png_ptr,
- png_bytep data,
- png_size_t length) {
+void StreamReadData(png_structp png_ptr, png_bytep data, png_size_t length) {
MemoryReadStream *stream =
static_cast<MemoryReadStream*>(png_get_io_ptr(png_ptr));
stream->Read(data, length);
}
+// Helper function for ToDataURL that converts a stream into the necessary
+// abstract byte writing function.
+void StreamWriteData(png_structp png_ptr, png_bytep data, png_size_t length) {
+ std::vector<uint8>* stream =
+ static_cast<std::vector<uint8>*>(png_get_io_ptr(png_ptr));
+ stream->insert(stream->end(),
+ static_cast<uint8*>(data),
+ static_cast<uint8*>(data) + length);
+}
+
+// Because libpng requires a flush function according to the docs.
+void StreamFlush(png_structp png_ptr) {
+}
+
+} // anonymous namespace
// Loads the raw RGB data from a compressed PNG file.
bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
@@ -117,7 +134,7 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
}
// Set up our STL stream input control
- png_set_read_fn(png_ptr, stream, &stream_read_data);
+ png_set_read_fn(png_ptr, stream, &StreamReadData);
// We have already read some of the signature, advance the pointer.
png_set_sig_bytes(png_ptr, sizeof(magic));
@@ -263,27 +280,17 @@ bool Bitmap::LoadFromPNGStream(MemoryReadStream *stream,
return true;
}
-// Saves the BGRA data from a compressed PNG file.
-bool Bitmap::SaveToPNGFile(const char* filename) {
- if (format_ != Texture::ARGB8) {
- DLOG(ERROR) << "Can only save ARGB8 images.";
- return false;
- }
- if (num_mipmaps_ != 1 || is_cubemap_) {
- DLOG(ERROR) << "Only 2D images with only the base level can be saved.";
- return false;
- }
- FILE *fp = fopen(filename, "wb");
- if (!fp) {
- DLOG(ERROR) << "Could not open file " << filename << " for writing.";
- return false;
- }
+namespace {
+
+bool CreatePNGInUInt8Vector(const Bitmap& bitmap, std::vector<uint8>* buffer) {
+ DCHECK(bitmap.format() == Texture::ARGB8);
+ DCHECK(bitmap.num_mipmaps() == 1);
+ DCHECK(!bitmap.is_cubemap());
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
if (!png_ptr) {
DLOG(ERROR) << "Could not create PNG structure.";
- fclose(fp);
return false;
}
@@ -291,26 +298,27 @@ bool Bitmap::SaveToPNGFile(const char* filename) {
if (!info_ptr) {
DLOG(ERROR) << "Could not create PNG info structure.";
png_destroy_write_struct(&png_ptr, png_infopp_NULL);
- fclose(fp);
return false;
}
- scoped_array<png_bytep> row_pointers(new png_bytep[height_]);
- for (int i = 0; i < height_; ++i) {
- row_pointers[height_-1-i] = image_data_.get() + i * width_ * 4;
+ unsigned width = bitmap.width();
+ unsigned height = bitmap.height();
+ scoped_array<png_bytep> row_pointers(new png_bytep[height]);
+ for (int i = 0; i < height; ++i) {
+ row_pointers[height - 1 - i] = bitmap.GetMipData(0) + i * width * 4;
}
if (setjmp(png_jmpbuf(png_ptr))) {
// If we get here, we had a problem reading the file.
- DLOG(ERROR) << "Error while writing file " << filename << ".";
+ DLOG(ERROR) << "Error while getting dataURL.";
png_destroy_write_struct(&png_ptr, &info_ptr);
- fclose(fp);
return false;
}
- png_init_io(png_ptr, fp);
+ // Set up our STL stream output.
+ png_set_write_fn(png_ptr, buffer, &StreamWriteData, &StreamFlush);
- png_set_IHDR(png_ptr, info_ptr, width_, height_, 8,
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8,
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_bgr(png_ptr);
@@ -318,8 +326,27 @@ bool Bitmap::SaveToPNGFile(const char* filename) {
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
- fclose(fp);
- return true;
+}
+
+} // anonymous namespace
+
+String Bitmap::ToDataURL() {
+ if (format_ != Texture::ARGB8) {
+ O3D_ERROR(service_locator()) << "Can only get data URL from ARGB8 images.";
+ return dataurl::kEmptyDataURL;
+ }
+ if (num_mipmaps_ != 1 || is_cubemap_) {
+ O3D_ERROR(service_locator()) <<
+ "Can only get data URL from 2d images with no mips.";
+ return dataurl::kEmptyDataURL;
+ }
+
+ std::vector<uint8> stream;
+ if (!CreatePNGInUInt8Vector(*this, &stream)) {
+ return dataurl::kEmptyDataURL;
+ }
+
+ return dataurl::ToDataURL("image/png", &stream[0], stream.size());
}
} // namespace o3d
diff --git a/o3d/core/cross/client.cc b/o3d/core/cross/client.cc
index 7b70496..cfbce23 100644
--- a/o3d/core/cross/client.cc
+++ b/o3d/core/cross/client.cc
@@ -55,6 +55,7 @@
#include "core/cross/profiler.h"
#include "utils/cross/string_writer.h"
#include "utils/cross/json_writer.h"
+#include "utils/cross/dataurl.h"
#ifdef OS_WIN
#include "core/cross/core_metrics.h"
@@ -401,12 +402,17 @@ void Client::InvalidateAllParameters() {
evaluation_counter_->InvalidateAllParameters();
}
-bool Client::SaveScreen(const String& file_name) {
+String Client::ToDataURL() {
if (!renderer_.IsAvailable()) {
O3D_ERROR(service_locator_) << "No Render Device Available";
- return false;
+ return dataurl::kEmptyDataURL;
} else {
- return renderer_->SaveScreen(file_name);
+ Bitmap::Ref bitmap(renderer_->TakeScreenshot());
+ if (bitmap.IsNull()) {
+ return dataurl::kEmptyDataURL;
+ } else {
+ return bitmap->ToDataURL();
+ }
}
}
diff --git a/o3d/core/cross/client.h b/o3d/core/cross/client.h
index b7de85c..153e354 100644
--- a/o3d/core/cross/client.h
+++ b/o3d/core/cross/client.h
@@ -395,9 +395,8 @@ class Client {
// Dumps all profiler state to a string.
String ProfileToString();
- // Saves a png screenshot of the display buffer.
- // Returns true on success and false on failure.
- bool SaveScreen(const String& file_name);
+ // Reutrns a data: URL of the client area in png format.
+ String ToDataURL();
// This class is intended to be used on the stack, such that the variable gets
// incremented on scope entry and decremented on scope exit. It's currently
diff --git a/o3d/core/cross/command_buffer/renderer_cb.cc b/o3d/core/cross/command_buffer/renderer_cb.cc
index 493da78..9de0617 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.cc
+++ b/o3d/core/cross/command_buffer/renderer_cb.cc
@@ -368,9 +368,8 @@ void RendererCB::SetViewportInPixels(int left,
helper_->AddCommand(command_buffer::SET_VIEWPORT, 6, args);
}
-bool RendererCB::SaveScreen(const String& file_name) {
- // TODO
- return false;
+Bitmap::Ref RendererCB::TakeScreenshot() {
+ return Bitmap::Ref();
}
const int* RendererCB::GetRGBAUByteNSwizzleTable() {
diff --git a/o3d/core/cross/command_buffer/renderer_cb.h b/o3d/core/cross/command_buffer/renderer_cb.h
index df13f9b..e7f8963 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.h
+++ b/o3d/core/cross/command_buffer/renderer_cb.h
@@ -141,9 +141,8 @@ class RendererCB : public Renderer {
return RenderDepthStencilSurface::Ref();
}
- // Saves a png screenshot.
- // Returns true on success and false on failure.
- virtual bool SaveScreen(const String& file_name);
+ // Overridden from Renderer.
+ virtual Bitmap::Ref TakeScreenshot();
// Gets the allocator for vertex buffer IDs.
IdAllocator &vertex_buffer_ids() { return vertex_buffer_ids_; }
diff --git a/o3d/core/cross/command_buffer/texture_cb.h b/o3d/core/cross/command_buffer/texture_cb.h
index e000a8e..c08cfcd 100644
--- a/o3d/core/cross/command_buffer/texture_cb.h
+++ b/o3d/core/cross/command_buffer/texture_cb.h
@@ -32,8 +32,8 @@
// This file contains the declarations for Texture2DCB and TextureCUBECB.
-#ifndef O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H__
-#define O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H__
+#ifndef O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H_
+#define O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H_
// Precompiled header comes before everything else.
#include "core/cross/precompile.h"
@@ -212,4 +212,4 @@ class TextureCUBECB : public TextureCUBE {
} // namespace o3d
-#endif // O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H__
+#endif // O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H_
diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc
index c22cda3..4a8b215 100644
--- a/o3d/core/cross/gl/renderer_gl.cc
+++ b/o3d/core/cross/gl/renderer_gl.cc
@@ -1560,10 +1560,7 @@ RenderDepthStencilSurface::Ref RendererGL::CreateDepthStencilSurface(
height));
}
-// Saves a png screenshot 'file_name.png'.
-// Returns true on success and false on failure.
-bool RendererGL::SaveScreen(const String& file_name) {
-#ifdef TESTING
+Bitmap::Ref RendererGL::TakeScreenshot() {;
MakeCurrentLazy();
Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
bitmap->Allocate(Texture::ARGB8, width(), height(), 1, false);
@@ -1574,16 +1571,7 @@ bool RendererGL::SaveScreen(const String& file_name) {
// might exhibit suprise translucency.
::glReadPixels(0, 0, width(), height(), GL_BGRA, GL_UNSIGNED_BYTE,
bitmap->image_data());
- bool result = bitmap->SaveToPNGFile((file_name + ".png").c_str());
- if (!result) {
- O3D_ERROR(service_locator())
- << "Failed to save screen into " << file_name;
- }
- return result;
-#else
- // Not a test build, always return false.
- return false;
-#endif
+ return bitmap;
}
const int* RendererGL::GetRGBAUByteNSwizzleTable() {
diff --git a/o3d/core/cross/gl/renderer_gl.h b/o3d/core/cross/gl/renderer_gl.h
index 24d8d01..534ea9c 100644
--- a/o3d/core/cross/gl/renderer_gl.h
+++ b/o3d/core/cross/gl/renderer_gl.h
@@ -144,9 +144,8 @@ class RendererGL : public Renderer {
int width,
int height);
- // Saves a png screenshot 'file_name.png'.
- // Returns true on success and false on failure.
- virtual bool SaveScreen(const String& file_name);
+ // Overridden from Renderer.
+ virtual Bitmap::Ref TakeScreenshot();
// Overridden from Renderer.
virtual const int* GetRGBAUByteNSwizzleTable();
diff --git a/o3d/core/cross/gl/texture_gl.h b/o3d/core/cross/gl/texture_gl.h
index 6b97b7f..567bf2b 100644
--- a/o3d/core/cross/gl/texture_gl.h
+++ b/o3d/core/cross/gl/texture_gl.h
@@ -32,8 +32,8 @@
// This file contains the declarations for Texture2DGL and TextureCUBEGL.
-#ifndef O3D_CORE_CROSS_GL_TEXTURE_GL_H__
-#define O3D_CORE_CROSS_GL_TEXTURE_GL_H__
+#ifndef O3D_CORE_CROSS_GL_TEXTURE_GL_H_
+#define O3D_CORE_CROSS_GL_TEXTURE_GL_H_
// Precompiled header comes before everything else.
#include "core/cross/precompile.h"
@@ -235,4 +235,4 @@ class TextureCUBEGL : public TextureCUBE {
} // namespace o3d
-#endif // O3D_CORE_CROSS_GL_TEXTURE_GL_H__
+#endif // O3D_CORE_CROSS_GL_TEXTURE_GL_H_
diff --git a/o3d/core/cross/gl/utils_gl.h b/o3d/core/cross/gl/utils_gl.h
index b6b87ff..a7af934 100644
--- a/o3d/core/cross/gl/utils_gl.h
+++ b/o3d/core/cross/gl/utils_gl.h
@@ -30,8 +30,8 @@
*/
-#ifndef O3D_CORE_CROSS_GL_UTILS_GL_H__
-#define O3D_CORE_CROSS_GL_UTILS_GL_H__
+#ifndef O3D_CORE_CROSS_GL_UTILS_GL_H_
+#define O3D_CORE_CROSS_GL_UTILS_GL_H_
#include "base/basictypes.h"
#include "core/cross/stream.h"
@@ -44,4 +44,4 @@ Stream::Semantic GLVertexAttributeToStream(const unsigned int attr, int *index);
} // namespace o3d
-#endif // O3D_CORE_CROSS_GL_UTILS_GL_H__
+#endif // O3D_CORE_CROSS_GL_UTILS_GL_H_
diff --git a/o3d/core/cross/image_utils.h b/o3d/core/cross/image_utils.h
index 12f29b8..2b6212e 100644
--- a/o3d/core/cross/image_utils.h
+++ b/o3d/core/cross/image_utils.h
@@ -59,8 +59,7 @@ enum ImageFileType {
unsigned int GetNumComponentsForFormat(Texture::Format format);
inline bool CheckImageDimensions(unsigned int width, unsigned int height) {
- return width > 0 && height > 0 &&
- width <= kMaxImageDimension && height <= kMaxImageDimension;
+ return width <= kMaxImageDimension && height <= kMaxImageDimension;
}
// Gets the number of mip-maps required for a full chain starting at
diff --git a/o3d/core/cross/image_utils_test.cc b/o3d/core/cross/image_utils_test.cc
index 99edc489..4f6a1c3 100644
--- a/o3d/core/cross/image_utils_test.cc
+++ b/o3d/core/cross/image_utils_test.cc
@@ -41,16 +41,14 @@ namespace o3d {
class ImageTest : public testing::Test {
};
-TEST_F(ImageTest, CheckImageDimensions) {
- EXPECT_TRUE(image::CheckImageDimensions(1u, 1u));
- EXPECT_FALSE(image::CheckImageDimensions(0u, 1u));
- EXPECT_FALSE(image::CheckImageDimensions(1u, 0u));
- EXPECT_TRUE(image::CheckImageDimensions(image::kMaxImageDimension,
- image::kMaxImageDimension));
- EXPECT_FALSE(image::CheckImageDimensions(0u, image::kMaxImageDimension));
- EXPECT_FALSE(image::CheckImageDimensions(image::kMaxImageDimension, 0u));
-}
-
+TEST_F(ImageTest, CheckImageDimensions) {
+ EXPECT_TRUE(image::CheckImageDimensions(1u, 1u));
+ EXPECT_TRUE(image::CheckImageDimensions(image::kMaxImageDimension,
+ image::kMaxImageDimension));
+ EXPECT_FALSE(image::CheckImageDimensions(0u, image::kMaxImageDimension + 1));
+ EXPECT_FALSE(image::CheckImageDimensions(image::kMaxImageDimension + 1, 0u));
+}
+
TEST_F(ImageTest, ComputeMipMapCount) {
EXPECT_EQ(image::ComputeMipMapCount(1, 1), 1u);
EXPECT_EQ(image::ComputeMipMapCount(2, 2), 2u);
@@ -301,3 +299,4 @@ TEST_F(ImageTest, GetFileTypeFromMimeType) {
} // namespace
+
diff --git a/o3d/core/cross/object_base.h b/o3d/core/cross/object_base.h
index 9a174c0..b4939c1 100644
--- a/o3d/core/cross/object_base.h
+++ b/o3d/core/cross/object_base.h
@@ -33,8 +33,8 @@
// This file contains the declaration of the ObjectBase class and definitions
// for the macros used to define the O3D object classes.
-#ifndef O3D_CORE_CROSS_OBJECT_BASE_H__
-#define O3D_CORE_CROSS_OBJECT_BASE_H__
+#ifndef O3D_CORE_CROSS_OBJECT_BASE_H_
+#define O3D_CORE_CROSS_OBJECT_BASE_H_
#include <vector>
@@ -240,4 +240,4 @@ typedef std::vector<ObjectBase*> ObjectBaseArray;
} // namespace o3d
-#endif // O3D_CORE_CROSS_OBJECT_BASE_H__
+#endif // O3D_CORE_CROSS_OBJECT_BASE_H_
diff --git a/o3d/core/cross/precompile.h b/o3d/core/cross/precompile.h
index bc9ba64..3e11e99 100644
--- a/o3d/core/cross/precompile.h
+++ b/o3d/core/cross/precompile.h
@@ -33,8 +33,8 @@
// This file contains includes for common headers used by O3D files. It
// is used for pre-compiled header support.
-#ifndef O3D_CORE_CROSS_PRECOMPILE_H__
-#define O3D_CORE_CROSS_PRECOMPILE_H__
+#ifndef O3D_CORE_CROSS_PRECOMPILE_H_
+#define O3D_CORE_CROSS_PRECOMPILE_H_
#include <build/build_config.h>
@@ -63,4 +63,4 @@
#include <map>
#include <vector>
-#endif // O3D_CORE_CROSS_PRECOMPILE_H__
+#endif // O3D_CORE_CROSS_PRECOMPILE_H_
diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h
index 15717ed..d766b24 100644
--- a/o3d/core/cross/renderer.h
+++ b/o3d/core/cross/renderer.h
@@ -364,9 +364,8 @@ class Renderer {
int width,
int height) = 0;
- // Saves a png screenshot.
- // Returns true on success and false on failure.
- virtual bool SaveScreen(const String& file_name) = 0;
+ // Returns the screen as a Bitmap. Will return a null reference on error.
+ virtual Bitmap::Ref TakeScreenshot() = 0;
ServiceLocator* service_locator() const { return service_locator_; }
diff --git a/o3d/core/cross/sampler.h b/o3d/core/cross/sampler.h
index 20ead52..c6dcf54 100644
--- a/o3d/core/cross/sampler.h
+++ b/o3d/core/cross/sampler.h
@@ -32,8 +32,8 @@
// This file contains the declaration for the Sampler class.
-#ifndef O3D_CORE_CROSS_SAMPLER_H__
-#define O3D_CORE_CROSS_SAMPLER_H__
+#ifndef O3D_CORE_CROSS_SAMPLER_H_
+#define O3D_CORE_CROSS_SAMPLER_H_
#include "core/cross/param_object.h"
#include "core/cross/param.h"
@@ -204,4 +204,4 @@ class ParamSampler : public TypedRefParam<Sampler> {
} // namespace o3d
-#endif // O3D_CORE_CROSS_SAMPLER_H__
+#endif // O3D_CORE_CROSS_SAMPLER_H_
diff --git a/o3d/core/win/d3d9/renderer_d3d9.cc b/o3d/core/win/d3d9/renderer_d3d9.cc
index 5779eb7..02e79aa 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.cc
+++ b/o3d/core/win/d3d9/renderer_d3d9.cc
@@ -1708,20 +1708,18 @@ RenderDepthStencilSurface::Ref RendererD3D9::CreateDepthStencilSurface(
depth_constructor));
}
-// Saves a png screenshot 'filename.png'.
-// Returns true on success and false on failure.
-bool RendererD3D9::SaveScreen(const String& file_name) {
-#ifdef TESTING
+Bitmap::Ref RendererD3D9::TakeScreenshot() {
+ Bitmap::Ref empty;
LPDIRECT3DDEVICE9 device = d3d_device();
CComPtr<IDirect3DSurface9> system_surface;
CComPtr<IDirect3DSurface9> current_surface;
if (!HR(device->GetRenderTarget(0, &current_surface)))
- return false;
+ return empty;
D3DSURFACE_DESC surface_description;
if (!HR(current_surface->GetDesc(&surface_description)))
- return false;
+ return empty;
// Construct an intermediate surface with multi-sampling disabled.
// This surface is required because GetRenderTargetData(...) will fail
@@ -1737,7 +1735,7 @@ bool RendererD3D9::SaveScreen(const String& file_name) {
FALSE,
&intermediate_target,
NULL))) {
- return false;
+ return empty;
}
if (!HR(device->StretchRect(current_surface,
@@ -1745,7 +1743,7 @@ bool RendererD3D9::SaveScreen(const String& file_name) {
intermediate_target,
NULL,
D3DTEXF_NONE))) {
- return false;
+ return empty;
}
if (!HR(device->CreateOffscreenPlainSurface(surface_description.Width,
@@ -1754,27 +1752,39 @@ bool RendererD3D9::SaveScreen(const String& file_name) {
D3DPOOL_SYSTEMMEM,
&system_surface,
NULL))) {
- return false;
+ return empty;
}
if (!HR(device->GetRenderTargetData(intermediate_target, system_surface)))
- return false;
+ return empty;
- // append .png to the end of file_name
- String png_file_name = file_name;
- png_file_name.append(String(".png"));
- // convert file name to utf16
- std::wstring file_name_utf16 = UTF8ToWide(png_file_name);
-
- return HR(o3d::D3DXSaveSurfaceToFile(file_name_utf16.c_str(),
- D3DXIFF_PNG,
- system_surface,
- NULL,
- NULL));
-#else
- // Not a test build, always return false.
- return false;
-#endif
+ D3DLOCKED_RECT out_rect = {0};
+ if (!HR(system_surface->LockRect(&out_rect, NULL, D3DLOCK_READONLY))) {
+ O3D_ERROR(service_locator()) << "Failed to Lock Surface (D3D9)";
+ return empty;
+ }
+
+ Bitmap::Ref bitmap = Bitmap::Ref(new Bitmap(service_locator()));
+ bitmap->Allocate(Texture::ARGB8,
+ surface_description.Width,
+ surface_description.Height,
+ 1,
+ false);
+ bitmap->SetRect(0, 0, 0,
+ surface_description.Width,
+ surface_description.Height,
+ out_rect.pBits,
+ out_rect.Pitch);
+ // TODO(gman): Remove this when we get the D3D backbuffer to be RGBA
+ // Set the Alpha to 0xFF
+ uint8* data = bitmap->image_data();
+ uint8* end = data + bitmap->width() * bitmap->height() * 4;
+ while (data != end) {
+ data[3] = 0xFF;
+ data += 4;
+ }
+ bitmap->FlipVertically();
+ return bitmap;
}
const int* RendererD3D9::GetRGBAUByteNSwizzleTable() {
diff --git a/o3d/core/win/d3d9/renderer_d3d9.h b/o3d/core/win/d3d9/renderer_d3d9.h
index 632ba9a..f81a6c7 100644
--- a/o3d/core/win/d3d9/renderer_d3d9.h
+++ b/o3d/core/win/d3d9/renderer_d3d9.h
@@ -156,9 +156,8 @@ class RendererD3D9 : public Renderer {
int width,
int height);
- // Saves a png screenshot 'file_name.png'.
- // Returns true on success and false on failure.
- virtual bool SaveScreen(const String& file_name);
+ // Overridden from Renderer.
+ virtual Bitmap::Ref TakeScreenshot();
inline LPDIRECT3DDEVICE9 d3d_device() const { return d3d_device_; }
inline LPDIRECT3D9 d3d() const { return d3d_; }
diff --git a/o3d/plugin/cross/plugin_main.h b/o3d/plugin/cross/plugin_main.h
index e0af989..8528571 100644
--- a/o3d/plugin/cross/plugin_main.h
+++ b/o3d/plugin/cross/plugin_main.h
@@ -30,9 +30,9 @@
*/
-#ifndef TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H__
-#define TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H__
+#ifndef TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H_
+#define TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H_
#include "plugin/cross/o3d_glue.h"
-#endif // TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H__
+#endif // TOOLS_IDLGLUE_NG_O3D_GLUE_PLUGIN_MAIN_H_
diff --git a/o3d/plugin/idl/client.idl b/o3d/plugin/idl/client.idl
index a635508..fb36b53 100644
--- a/o3d/plugin/idl/client.idl
+++ b/o3d/plugin/idl/client.idl
@@ -486,11 +486,21 @@ class Client {
void InvalidateAllParameters();
%[
- This function is only available in the test version of the plugin.
- \param file_name Name to save screenshot to.
- \return True on success.
+ Gets a copy of the current backbuffer of O3D as a data: url.
+
+ NOTE: Calling it will cause a render to happen.
+
+ \return A Data URL for the backbuffer.
+ %]
+ String ToDataURL();
+
+ %[
+ Gets a copy of the current backbuffer of O3D as a data: url.
+ \param mime_type The type of data url you want. Currently O3D only supports
+ image/png. See HTML5 canvas tag for info about toDataURL.
+ \return A Data URL for the backbuffer.
%]
- bool SaveScreen(String file_name);
+ [userglue] String ToDataURL(String mime_type);
%[
Returns the status of initializing the renderer so we can display the
@@ -585,6 +595,12 @@ class Client {
&modes);
return modes;
}
+ o3d::String userglue_method_ToDataURL(o3d::Client* self,
+ const o3d::String& mime_type) {
+ // We ignore the mime_type since it's only a suggestion
+ // and we only return the required image/png type.
+ return self->ToDataURL();
+ }
void userglue_method_SetFullscreenClickRegion(
void *plugin_data, o3d::Client *self, int x, int y, int width,
int height, int mode_id) {
diff --git a/o3d/tests/build.scons b/o3d/tests/build.scons
index f37d5a7..dc6b23a 100644
--- a/o3d/tests/build.scons
+++ b/o3d/tests/build.scons
@@ -254,6 +254,8 @@ tests = [
'import/cross/threaded_stream_processor_test.cc',
'serializer/cross/serializer_test.cc',
'tests/common/cross/test_utils.cc',
+ 'utils/cross/base64_test.cc',
+ 'utils/cross/dataurl_test.cc',
'utils/cross/file_path_utils_test.cc',
'utils/cross/file_text_reader_test.cc',
'utils/cross/json_writer_test.cc',
diff --git a/o3d/tests/selenium/selenium_utilities.py b/o3d/tests/selenium/selenium_utilities.py
index 8f8ccc0..da35e8a 100644
--- a/o3d/tests/selenium/selenium_utilities.py
+++ b/o3d/tests/selenium/selenium_utilities.py
@@ -39,6 +39,7 @@ import os
import re
import time
import unittest
+import base64
import gflags
import selenium_constants
@@ -174,7 +175,8 @@ def TakeScreenShotAtPath(session,
full_path = filename.replace("\\", "/")
# Attempt to take a screenshot of the display buffer
- eval_string = ("%s.saveScreen('%s')" % (client, full_path))
+ eval_string = ("%s.toDataURL()" % client)
+
# Set Post render call back to take screenshot
script = ["window.g_selenium_post_render = false;",
@@ -196,9 +198,13 @@ def TakeScreenShotAtPath(session,
session.wait_for_condition("window.g_selenium_post_render", 20000)
# Get result
- success = session.get_eval("window.g_selenium_save_screen_result")
-
- if success == u"true":
+ data_url = session.get_eval("window.g_selenium_save_screen_result")
+ expected_header = "data:image/png;base64,"
+ if data_url.startswith(expected_header):
+ png = base64.b64decode(data_url[len(expected_header):])
+ file = open(full_path + ".png", 'wb')
+ file.write(png)
+ file.close()
print "Saved screenshot %s." % full_path
return True
diff --git a/o3d/utils/build.scons b/o3d/utils/build.scons
index f06781e..0255261 100644
--- a/o3d/utils/build.scons
+++ b/o3d/utils/build.scons
@@ -31,6 +31,8 @@
Import('env')
inputs = [
+ 'cross/base64.cc',
+ 'cross/dataurl.cc',
'cross/file_path_utils.cc',
'cross/file_text_reader.cc',
'cross/file_text_writer.cc',
diff --git a/o3d/utils/cross/base64.cc b/o3d/utils/cross/base64.cc
new file mode 100644
index 0000000..3662258
--- /dev/null
+++ b/o3d/utils/cross/base64.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file contains the declaration of functions for dealing with base64
+// encoding and decoding
+
+#include "utils/cross/base64.h"
+#include "core/cross/types.h"
+
+namespace o3d {
+namespace base64 {
+
+size_t GetEncodeLength(size_t length) {
+ return (length + 2) / 3 * 4;
+}
+
+void Encode(const void* src_ptr, size_t length, void* dst_ptr) {
+ const int kEncodePad = 64;
+
+ static const char kEncode[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/=";
+
+ const uint8* src = reinterpret_cast<const uint8*>(src_ptr);
+ uint8* dst = reinterpret_cast<uint8*>(dst_ptr);
+ if (dst) {
+ size_t remainder = length % 3;
+ const uint8* end = &src[length - remainder];
+ while (src < end) {
+ unsigned a = *src++;
+ unsigned b = *src++;
+ unsigned c = *src++;
+ unsigned d = c & 0x3F;
+ c = (c >> 6 | b << 2) & 0x3F;
+ b = (b >> 4 | a << 4) & 0x3F;
+ a = a >> 2;
+ *dst++ = kEncode[a];
+ *dst++ = kEncode[b];
+ *dst++ = kEncode[c];
+ *dst++ = kEncode[d];
+ }
+ if (remainder > 0) {
+ unsigned k1 = 0;
+ unsigned k2 = kEncodePad;
+ unsigned a = *src++;
+ if (remainder == 2) {
+ int b = *src++;
+ k1 = b >> 4;
+ k2 = (b << 2) & 0x3F;
+ }
+ *dst++ = kEncode[a >> 2];
+ *dst++ = kEncode[(k1 | a << 4) & 0x3F];
+ *dst++ = kEncode[k2];
+ *dst++ = kEncode[kEncodePad];
+ }
+ }
+}
+
+} // namespace base64
+} // namespace o3d
+
diff --git a/o3d/utils/cross/base64.h b/o3d/utils/cross/base64.h
new file mode 100644
index 0000000..881f988
--- /dev/null
+++ b/o3d/utils/cross/base64.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file contains the declaration of functions for dealing with base64
+// encoding and decoding
+
+#ifndef O3D_UTILS_CROSS_BASE64_H_
+#define O3D_UTILS_CROSS_BASE64_H_
+
+namespace o3d {
+namespace base64 {
+
+// Returns the number of bytes needed to encode length bytes in base64.
+size_t GetEncodeLength(size_t length);
+
+// Encodes the src into base64 into the dst. The dst must have enough
+// space to hold the result.
+// Parameters:
+// src: pointer to source data.
+// length: the length of the source data
+// dst: pointer to place to store result.
+void Encode(const void* src, size_t length, void* dst);
+
+} // namespace base64
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_BASE64_H_
+
diff --git a/o3d/utils/cross/base64_test.cc b/o3d/utils/cross/base64_test.cc
new file mode 100644
index 0000000..205ce7b
--- /dev/null
+++ b/o3d/utils/cross/base64_test.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of base64 functions
+
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/base64.h"
+
+namespace o3d {
+
+class Base64Test : public testing::Test {
+};
+
+TEST_F(Base64Test, GetEncodeLength) {
+ EXPECT_EQ(0, base64::GetEncodeLength(0));
+ EXPECT_EQ(4, base64::GetEncodeLength(1));
+ EXPECT_EQ(4, base64::GetEncodeLength(2));
+ EXPECT_EQ(4, base64::GetEncodeLength(3));
+ EXPECT_EQ(8, base64::GetEncodeLength(4));
+}
+
+TEST_F(Base64Test, Encode) {
+ unsigned char buffer[100];
+ memset(buffer, 0xFF, sizeof(buffer));
+ base64::Encode("abc", 3, buffer);
+ EXPECT_EQ(0, memcmp(buffer, "YWJj", 4));
+ EXPECT_EQ(0xFF, buffer[4]);
+ memset(buffer, 0xFF, sizeof(buffer));
+ base64::Encode("ab\0c", 4, buffer);
+ EXPECT_EQ(0, memcmp(buffer, "YWIAYw==", 8));
+ EXPECT_EQ(0xFF, buffer[8]);
+}
+
+} // namespace o3d
+
+
diff --git a/o3d/utils/cross/dataurl.cc b/o3d/utils/cross/dataurl.cc
new file mode 100644
index 0000000..8334b8d
--- /dev/null
+++ b/o3d/utils/cross/dataurl.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file contains the definition of functions for dealing with data urls.
+
+#include "utils/cross/dataurl.h"
+#include "core/cross/types.h"
+#include "utils/cross/base64.h"
+
+namespace o3d {
+namespace dataurl {
+
+const char* const kEmptyDataURL = "data:,";
+
+String ToDataURL(const String& mime_type, const void* data, size_t length) {
+ String header(String("data:") + mime_type + ";base64,");
+ String result(header.size() + base64::GetEncodeLength(length), ' ');
+ result.replace(0, header.size(), header);
+ base64::Encode(data, length, &result[header.size()]);
+ return result;
+}
+
+} // namespace dataurl
+} // namespace o3d
+
diff --git a/o3d/utils/cross/dataurl.h b/o3d/utils/cross/dataurl.h
new file mode 100644
index 0000000..cc46e01
--- /dev/null
+++ b/o3d/utils/cross/dataurl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file contains the declaration of functions for dealing with data urls.
+
+#ifndef O3D_UTILS_CROSS_DATAURL_H_
+#define O3D_UTILS_CROSS_DATAURL_H_
+
+#include "core/cross/types.h"
+
+namespace o3d {
+namespace dataurl {
+
+// An empty data URL. ("data:,")
+extern const char* const kEmptyDataURL;
+
+// Creates a data URL for the given data.
+String ToDataURL(const String& mime_type, const void* data, size_t length);
+
+} // namespace dataurl
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_DATAURL_H_
+
diff --git a/o3d/utils/cross/dataurl_test.cc b/o3d/utils/cross/dataurl_test.cc
new file mode 100644
index 0000000..8404650
--- /dev/null
+++ b/o3d/utils/cross/dataurl_test.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of dataurl functions
+
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/dataurl.h"
+
+namespace o3d {
+
+class DataURLTest : public testing::Test {
+};
+
+TEST_F(DataURLTest, kEmptyDataURL) {
+ EXPECT_STREQ("data:,", dataurl::kEmptyDataURL);
+}
+
+TEST_F(DataURLTest, ToDataURL) {
+ EXPECT_STREQ("data:a/b;base64,YWJj",
+ dataurl::ToDataURL("a/b", "abc", 3).c_str());
+ EXPECT_STREQ("data:de/ej;base64,YWIAYw==",
+ dataurl::ToDataURL("de/ej", "ab\0c", 4).c_str());
+}
+
+} // namespace o3d
+
+
diff --git a/o3d/utils/utils.gyp b/o3d/utils/utils.gyp
index 9fb5e45..14e3fa6 100644
--- a/o3d/utils/utils.gyp
+++ b/o3d/utils/utils.gyp
@@ -21,6 +21,10 @@
'target_name': 'o3dUtils',
'type': 'static_library',
'sources': [
+ "cross/base64.cc",
+ "cross/base64.h",
+ "cross/dataurl.cc",
+ "cross/dataurl.h",
"cross/file_path_utils.cc",
"cross/file_path_utils.h",
"cross/file_text_reader.cc",
@@ -50,6 +54,8 @@
],
'direct_dependent_settings': {
'sources': [
+ "cross/base64_test.cc",
+ "cross/dataurl_test.cc",
"cross/file_path_utils_test.cc",
"cross/file_text_reader_test.cc",
"cross/json_writer_test.cc",