| // Copyright 2015 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef COBALT_RENDER_TREE_RESOURCE_PROVIDER_STUB_H_ |
| #define COBALT_RENDER_TREE_RESOURCE_PROVIDER_STUB_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/aligned_memory.h" |
| #include "cobalt/base/polymorphic_downcast.h" |
| #include "cobalt/render_tree/font.h" |
| #include "cobalt/render_tree/font_provider.h" |
| #include "cobalt/render_tree/image.h" |
| #include "cobalt/render_tree/lottie_animation.h" |
| #include "cobalt/render_tree/mesh.h" |
| #include "cobalt/render_tree/resource_provider.h" |
| #include "third_party/ots/include/opentype-sanitiser.h" |
| #include "third_party/ots/include/ots-memory-stream.h" |
| |
| namespace cobalt { |
| namespace render_tree { |
| |
| namespace Internal { |
| |
| const int kDefaultTypefaceSizeInBytes = 256; |
| const render_tree::TypefaceId kDefaultTypefaceId = 0xffffffff; |
| |
| const float kRobotoAscentSizeMultiplier = 0.927734f; |
| const float kRobotoDescentSizeMultiplier = 0.244141f; |
| const float kRobotoLeadingSizeMultiplier = 0.f; |
| const float kRobotoXHeightSizeMultiplier = 0.52832f; |
| |
| const int32 kDefaultCharacter = 48; // Decimal value for '0' |
| const render_tree::GlyphIndex kDefaultGlyphIndex = 1; |
| |
| const float kDefaultCharacterRobotoGlyphWidthSizeMultiplier = 0.562012f; |
| const float kDefaultCharacterRobotoGlyphHeightSizeMultiplier = 0.7f; |
| |
| } // namespace Internal |
| |
| // The ResourceProvider defined in this file provides a bare minimum of |
| // implementation necessary. It is useful for tests that do not care about |
| // actually rasterizing render trees. For certain resources like Images, |
| // it provides introspection of internal pixel data so that tests can check |
| // that images do indeed contain the data they are expected to contain. |
| |
| // Simple in-memory pixel data. |
| class ImageDataStub : public ImageData { |
| public: |
| ImageDataStub(const math::Size& size, PixelFormat pixel_format, |
| AlphaFormat alpha_format) |
| : descriptor_(size, pixel_format, alpha_format, |
| size.width() * BytesPerPixel(pixel_format)), |
| memory_(new uint8[static_cast<size_t>(size.height() * |
| descriptor_.pitch_in_bytes)]) {} |
| |
| const ImageDataDescriptor& GetDescriptor() const override { |
| return descriptor_; |
| } |
| |
| void ReleaseMemory() { memory_.reset(); } |
| uint8* GetMemory() override { return memory_.get(); } |
| |
| private: |
| ImageDataDescriptor descriptor_; |
| std::unique_ptr<uint8[]> memory_; |
| }; |
| |
| // Wraps an ImageDataStub object or a RawImageMemory and its associated image |
| // descriptor. It also makes the wrapped object visible to the public so that |
| // tests can access the pixel data. |
| class ImageStub : public Image { |
| public: |
| explicit ImageStub(std::unique_ptr<ImageDataStub> image_data) |
| : image_data_(std::move(image_data)) {} |
| ImageStub(std::unique_ptr<RawImageMemory> raw_image_memory, |
| const MultiPlaneImageDataDescriptor& multi_plane_descriptor) |
| : raw_image_memory_(std::move(raw_image_memory)), |
| multi_plane_descriptor_(multi_plane_descriptor) {} |
| |
| const math::Size& GetSize() const override { |
| return is_multi_plane_image() |
| ? multi_plane_descriptor_->GetPlaneDescriptor(0).size |
| : image_data_->GetDescriptor().size; |
| } |
| |
| bool is_multi_plane_image() const { |
| if (image_data_ == NULL) { |
| DCHECK(raw_image_memory_ != NULL); |
| return true; |
| } |
| DCHECK(raw_image_memory_ == NULL); |
| return false; |
| } |
| |
| ImageDataStub* GetImageData() { |
| DCHECK(!is_multi_plane_image()); |
| return image_data_.get(); |
| } |
| |
| RawImageMemory* GetRawImageMemory() { |
| DCHECK(is_multi_plane_image()); |
| return raw_image_memory_.get(); |
| } |
| |
| const MultiPlaneImageDataDescriptor& multi_plane_descriptor() const { |
| DCHECK(is_multi_plane_image()); |
| return multi_plane_descriptor_.value(); |
| } |
| |
| private: |
| ~ImageStub() override {} |
| |
| std::unique_ptr<ImageDataStub> image_data_; |
| |
| std::unique_ptr<RawImageMemory> raw_image_memory_; |
| base::Optional<MultiPlaneImageDataDescriptor> multi_plane_descriptor_; |
| }; |
| |
| // Simple class that returns dummy data for metric information modeled on |
| // Roboto. |
| class FontStub : public Font { |
| public: |
| FontStub(const scoped_refptr<Typeface>& typeface, float font_size) |
| : typeface_(typeface), |
| font_metrics_(Internal::kRobotoAscentSizeMultiplier * font_size, |
| Internal::kRobotoDescentSizeMultiplier * font_size, |
| Internal::kRobotoLeadingSizeMultiplier * font_size, |
| Internal::kRobotoXHeightSizeMultiplier * font_size), |
| glyph_bounds_( |
| 0, |
| std::max( |
| Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier * |
| font_size, |
| 1.0f), |
| Internal::kDefaultCharacterRobotoGlyphWidthSizeMultiplier * |
| font_size, |
| std::max( |
| Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier * |
| font_size, |
| 1.0f)) {} |
| |
| TypefaceId GetTypefaceId() const override { return typeface_->GetId(); } |
| |
| FontMetrics GetFontMetrics() const override { return font_metrics_; } |
| |
| GlyphIndex GetGlyphForCharacter(int32 utf32_character) override { |
| return typeface_->GetGlyphForCharacter(utf32_character); |
| } |
| |
| const math::RectF& GetGlyphBounds(GlyphIndex glyph) override { |
| return glyph_bounds_; |
| } |
| |
| float GetGlyphWidth(GlyphIndex glyph) override { |
| return glyph_bounds_.width(); |
| } |
| |
| private: |
| ~FontStub() override {} |
| |
| const scoped_refptr<Typeface> typeface_; |
| const FontMetrics font_metrics_; |
| math::RectF glyph_bounds_; |
| }; |
| |
| // Simple class that returns dummy data for metric information modeled on |
| // Roboto. |
| class TypefaceStub : public Typeface { |
| public: |
| explicit TypefaceStub(const void* data) {} |
| |
| TypefaceId GetId() const override { return Internal::kDefaultTypefaceId; } |
| |
| uint32 GetEstimatedSizeInBytes() const override { |
| return Internal::kDefaultTypefaceSizeInBytes; |
| } |
| |
| scoped_refptr<Font> CreateFontWithSize(float font_size) override { |
| return base::WrapRefCounted(new FontStub(this, font_size)); |
| } |
| |
| GlyphIndex GetGlyphForCharacter(int32 utf32_character) override { |
| return Internal::kDefaultGlyphIndex; |
| } |
| |
| private: |
| ~TypefaceStub() override {} |
| }; |
| |
| class RawImageMemoryStub : public RawImageMemory { |
| public: |
| typedef std::unique_ptr<uint8_t, base::AlignedFreeDeleter> ScopedMemory; |
| |
| RawImageMemoryStub(size_t size_in_bytes, size_t alignment) |
| : size_in_bytes_(size_in_bytes) { |
| memory_ = ScopedMemory( |
| static_cast<uint8_t*>(base::AlignedAlloc(size_in_bytes, alignment))); |
| } |
| |
| size_t GetSizeInBytes() const override { return size_in_bytes_; } |
| |
| uint8_t* GetMemory() override { return memory_.get(); } |
| |
| private: |
| ~RawImageMemoryStub() override {} |
| |
| size_t size_in_bytes_; |
| ScopedMemory memory_; |
| }; |
| |
| class MeshStub : public render_tree::Mesh { |
| public: |
| MeshStub(std::unique_ptr<std::vector<render_tree::Mesh::Vertex> > vertices, |
| render_tree::Mesh::DrawMode draw_mode) |
| : vertices_(std::move(vertices)), draw_mode_(draw_mode) {} |
| |
| uint32 GetEstimatedSizeInBytes() const override { |
| return static_cast<uint32>(vertices_->size() * 5 * sizeof(float) + |
| sizeof(DrawMode)); |
| } |
| |
| render_tree::Mesh::DrawMode GetDrawMode() const { return draw_mode_; } |
| const std::vector<render_tree::Mesh::Vertex>& GetVertices() const { |
| return *vertices_.get(); |
| } |
| |
| private: |
| const std::unique_ptr<std::vector<render_tree::Mesh::Vertex> > vertices_; |
| const render_tree::Mesh::DrawMode draw_mode_; |
| }; |
| |
| // Return the stub versions defined above for each resource. |
| class ResourceProviderStub : public ResourceProvider { |
| public: |
| ResourceProviderStub() : release_image_data_(false) {} |
| explicit ResourceProviderStub(bool release_image_data) |
| : release_image_data_(release_image_data) {} |
| ~ResourceProviderStub() override {} |
| |
| base::TypeId GetTypeId() const override { |
| return base::GetTypeId<ResourceProviderStub>(); |
| } |
| |
| void Finish() override {} |
| |
| bool PixelFormatSupported(PixelFormat pixel_format) override { |
| return true; |
| } |
| |
| bool AlphaFormatSupported(AlphaFormat alpha_format) override { |
| return true; |
| } |
| |
| std::unique_ptr<ImageData> AllocateImageData( |
| const math::Size& size, PixelFormat pixel_format, |
| AlphaFormat alpha_format) override { |
| return std::unique_ptr<ImageData>( |
| new ImageDataStub(size, pixel_format, alpha_format)); |
| } |
| |
| scoped_refptr<Image> CreateImage( |
| std::unique_ptr<ImageData> source_data) override { |
| std::unique_ptr<ImageDataStub> skia_source_data( |
| base::polymorphic_downcast<ImageDataStub*>(source_data.release())); |
| if (release_image_data_) { |
| skia_source_data->ReleaseMemory(); |
| } |
| return base::WrapRefCounted(new ImageStub(std::move(skia_source_data))); |
| } |
| |
| scoped_refptr<Image> CreateImageFromSbDecodeTarget( |
| SbDecodeTarget decode_target) override { |
| NOTREACHED(); |
| SbDecodeTargetRelease(decode_target); |
| return NULL; |
| } |
| |
| bool SupportsSbDecodeTarget() override { return false; } |
| |
| SbDecodeTargetGraphicsContextProvider* |
| GetSbDecodeTargetGraphicsContextProvider() override { |
| return NULL; |
| } |
| |
| std::unique_ptr<RawImageMemory> AllocateRawImageMemory( |
| size_t size_in_bytes, size_t alignment) override { |
| RawImageMemory* ptr = new RawImageMemoryStub(size_in_bytes, alignment); |
| return std::unique_ptr<RawImageMemory>(ptr); |
| } |
| |
| scoped_refptr<Image> CreateMultiPlaneImageFromRawMemory( |
| std::unique_ptr<RawImageMemory> raw_image_memory, |
| const MultiPlaneImageDataDescriptor& descriptor) override { |
| return base::WrapRefCounted( |
| new ImageStub(std::move(raw_image_memory), descriptor)); |
| } |
| |
| bool HasLocalFontFamily(const char* font_family_name) const override { |
| return true; |
| } |
| |
| scoped_refptr<Typeface> GetLocalTypeface(const char* font_family_name, |
| FontStyle font_style) override { |
| return base::WrapRefCounted(new TypefaceStub(NULL)); |
| } |
| |
| scoped_refptr<render_tree::Typeface> GetLocalTypefaceByFaceNameIfAvailable( |
| const char* font_face_name) override { |
| return base::WrapRefCounted(new TypefaceStub(NULL)); |
| } |
| |
| scoped_refptr<Typeface> GetCharacterFallbackTypeface( |
| int32 utf32_character, FontStyle font_style, |
| const std::string& language) override { |
| return base::WrapRefCounted(new TypefaceStub(NULL)); |
| } |
| |
| scoped_refptr<Typeface> CreateTypefaceFromRawData( |
| std::unique_ptr<RawTypefaceDataVector> raw_data, |
| std::string* error_string) override { |
| if (raw_data == NULL) { |
| *error_string = "No data to process"; |
| return NULL; |
| } |
| |
| ots::OTSContext context; |
| ots::ExpandingMemoryStream sanitized_data( |
| raw_data->size(), render_tree::ResourceProvider::kMaxTypefaceDataSize); |
| if (!context.Process(&sanitized_data, &((*raw_data)[0]), |
| raw_data->size())) { |
| *error_string = "OpenType sanitizer unable to process data"; |
| return NULL; |
| } |
| return base::WrapRefCounted(new TypefaceStub(NULL)); |
| } |
| |
| float GetTextWidth(const base::char16* text_buffer, size_t text_length, |
| const std::string& language, bool is_rtl, |
| FontProvider* font_provider, |
| FontVector* maybe_used_fonts) override { |
| render_tree::GlyphIndex glyph_index; |
| const scoped_refptr<render_tree::Font>& font = |
| font_provider->GetCharacterFont(Internal::kDefaultCharacter, |
| &glyph_index); |
| if (maybe_used_fonts) { |
| maybe_used_fonts->push_back(font); |
| } |
| return font->GetGlyphWidth(glyph_index) * text_length; |
| } |
| |
| // Creates a glyph buffer, which is populated with shaped text, and used to |
| // render that text. |
| scoped_refptr<GlyphBuffer> CreateGlyphBuffer( |
| const base::char16* text_buffer, size_t text_length, |
| const std::string& language, bool is_rtl, |
| FontProvider* font_provider) override { |
| render_tree::GlyphIndex glyph_index; |
| const scoped_refptr<render_tree::Font>& font = |
| font_provider->GetCharacterFont(Internal::kDefaultCharacter, |
| &glyph_index); |
| const math::RectF& glyph_bounds = font->GetGlyphBounds(glyph_index); |
| return base::WrapRefCounted(new GlyphBuffer( |
| math::RectF(0, glyph_bounds.y(), glyph_bounds.width() * text_length, |
| glyph_bounds.height()))); |
| } |
| |
| // Creates a glyph buffer, which is populated with shaped text, and used to |
| // render that text. |
| scoped_refptr<GlyphBuffer> CreateGlyphBuffer( |
| const std::string& utf8_string, |
| const scoped_refptr<Font>& font) override { |
| const math::RectF& glyph_bounds = |
| font->GetGlyphBounds(Internal::kDefaultGlyphIndex); |
| return base::WrapRefCounted(new GlyphBuffer(math::RectF( |
| 0, glyph_bounds.y(), glyph_bounds.width() * utf8_string.size(), |
| glyph_bounds.height()))); |
| } |
| |
| scoped_refptr<LottieAnimation> CreateLottieAnimation(const char* data, |
| size_t length) override { |
| return scoped_refptr<LottieAnimation>(NULL); |
| } |
| |
| // Create a mesh which can map replaced boxes to 3D shapes. |
| scoped_refptr<render_tree::Mesh> CreateMesh( |
| std::unique_ptr<std::vector<render_tree::Mesh::Vertex> > vertices, |
| render_tree::Mesh::DrawMode draw_mode) override { |
| return new MeshStub(std::move(vertices), draw_mode); |
| } |
| |
| scoped_refptr<Image> DrawOffscreenImage( |
| const scoped_refptr<render_tree::Node>& root) override { |
| return scoped_refptr<Image>(NULL); |
| } |
| |
| bool release_image_data_; |
| }; |
| |
| } // namespace render_tree |
| } // namespace cobalt |
| |
| #endif // COBALT_RENDER_TREE_RESOURCE_PROVIDER_STUB_H_ |