diff options
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, ¤t_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", |