fix GifSprite render problem

This commit is contained in:
Nomango 2020-02-07 20:50:27 +08:00
parent 832576d0aa
commit a633669058
18 changed files with 183 additions and 140 deletions

View File

@ -85,13 +85,14 @@ bool GifSprite::Load(GifImagePtr gif)
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
frame_ = GifImage::Frame();
SetSize(Size{ static_cast<float>(gif_->GetWidthInPixels()), static_cast<float>(gif_->GetHeightInPixels()) });
SetSize(float(gif_->GetWidthInPixels()), float(gif_->GetHeightInPixels()));
if (!frame_rt_)
{
Renderer::Instance().CreateTextureRenderTarget(frame_rt_);
Size frame_size = GetSize();
Renderer::Instance().CreateTextureRenderTarget(frame_rt_, &frame_size);
}
if (gif_->GetFramesCount() > 0)
@ -109,7 +110,7 @@ void GifSprite::OnRender(RenderContext& ctx)
{
PrepareToRender(ctx);
ctx.DrawTexture(*frame_to_render_, &frame_.rect, nullptr);
ctx.DrawTexture(*frame_to_render_, nullptr, &GetBounds());
}
}
@ -140,7 +141,7 @@ void GifSprite::RestartAnimation()
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
frame_.disposal_type = GifImage::DisposalType::None;
frame_ = GifImage::Frame();
}
void GifSprite::ComposeNextFrame()
@ -181,7 +182,7 @@ void GifSprite::DisposeCurrentFrame()
void GifSprite::OverlayNextFrame()
{
KGE_ASSERT(frame_rt_);
KGE_ASSERT(gif_ && gif_->IsValid());
KGE_ASSERT(gif_);
frame_ = gif_->GetFrame(next_index_);
@ -196,6 +197,7 @@ void GifSprite::OverlayNextFrame()
if (next_index_ == 0)
{
frame_rt_->Clear();
loop_count_++;
}
@ -217,6 +219,7 @@ void GifSprite::OverlayNextFrame()
}
}
// Execute callback
if (IsLastFrame() && loop_cb_)
{
loop_cb_(loop_count_ - 1);
@ -239,8 +242,7 @@ void GifSprite::SaveComposedFrame()
if (!saved_frame_)
{
saved_frame_ = new Texture;
frame_rt_->CreateTexture(*saved_frame_, frame_to_be_saved->GetSizeInPixels(),
frame_to_be_saved->GetPixelFormat());
frame_rt_->CreateTexture(*saved_frame_, frame_to_be_saved->GetSizeInPixels());
}
saved_frame_->CopyFrom(frame_to_be_saved);

View File

@ -92,20 +92,6 @@ using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>;
/// \~chinese
/// @brief 函数封装器
/// @par
/// 使用函数封装器可以储存、复制和调用任何可调用目标,示例代码如下:
/// @code
/// Function<bool(int)> func1 = StaticFunc; // bool
/// StaticFunc(int x);
/// Function<bool(int)> func2 = Closure(&t, &T::Func); // bool
/// T::Func(int x);
/// Function<bool(int)> func3 = T::StaticFunc; // static bool
/// T::StaticFunc(int x);
/// Function<bool(int)> func4 = [](int x) -> bool {}; // Lambda function
/// Function<bool(int)> func5 = std::bind(&T::Func, &t); // std::bind
/// Function<bool(int)> func5 = Callable(); // Callable
/// objects: struct Callable { bool operator()(int x) {} };
/// @endcode
template <typename _FuncTy>
using Function = oc::function<_FuncTy>;

View File

@ -112,16 +112,6 @@ void Brush::SetOpacity(float opacity)
void Brush::SetColor(Color const& color)
{
if (type_ == Type::SolidColor && raw_)
{
ComPtr<ID2D1SolidColorBrush> solid_brush;
if (SUCCEEDED(raw_->QueryInterface(&solid_brush)))
{
solid_brush->SetColor(DX::ConvertToColorF(color));
return;
}
}
Renderer::Instance().CreateBrush(*this, color);
}
@ -135,14 +125,4 @@ void Brush::SetStyle(RadialGradientStyle const& style)
Renderer::Instance().CreateBrush(*this, style);
}
void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
{
type_ = type;
raw_ = brush;
if (raw_)
{
raw_->SetOpacity(opacity_);
}
}
} // namespace kiwano

View File

@ -150,14 +150,17 @@ private:
/// @brief ÉèÖÃ͸Ã÷¶È
void SetOpacity(float opacity);
private:
Type type_;
float opacity_;
#if defined(KGE_WIN32)
void SetBrush(ComPtr<ID2D1Brush> brush, Type type);
ComPtr<ID2D1Brush> GetBrush() const;
private:
Type type_;
float opacity_;
ComPtr<ID2D1Brush> raw_;
#endif
};
/** @} */
@ -167,8 +170,21 @@ inline Brush::Type Brush::GetType() const
return type_;
}
#if defined(KGE_WIN32)
inline void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
{
type_ = type;
raw_ = brush;
if (raw_)
{
raw_->SetOpacity(opacity_);
}
}
inline ComPtr<ID2D1Brush> Brush::GetBrush() const
{
return raw_;
}
#endif
} // namespace kiwano

View File

@ -62,17 +62,19 @@ public:
/// @brief ¼ÓÔØ×ÖÌå×ÊÔ´
bool Load(Resource const& resource);
#if defined(KGE_WIN32)
private:
ComPtr<IDWriteFontCollection> GetCollection() const;
void SetCollection(ComPtr<IDWriteFontCollection> collection);
private:
ComPtr<IDWriteFontCollection> collection_;
#endif
};
/** @} */
#if defined(KGE_WIN32)
inline ComPtr<IDWriteFontCollection> Font::GetCollection() const
{
return collection_;
@ -82,4 +84,6 @@ inline void Font::SetCollection(ComPtr<IDWriteFontCollection> collection)
{
collection_ = collection;
}
#endif
} // namespace kiwano

View File

@ -60,12 +60,10 @@ bool GifImage::Load(String const& file_path)
if (IsValid())
{
if (FAILED(GetGlobalMetadata()))
{
SetDecoder(nullptr);
return false;
}
if (GetGlobalMetadata())
return true;
SetDecoder(nullptr);
}
return false;
}
@ -76,12 +74,10 @@ bool GifImage::Load(Resource const& res)
if (IsValid())
{
if (FAILED(GetGlobalMetadata()))
{
SetDecoder(nullptr);
return false;
}
if (GetGlobalMetadata())
return true;
SetDecoder(nullptr);
}
return false;
}
@ -98,7 +94,8 @@ GifImage::Frame GifImage::GetFrame(uint32_t index)
return frame;
}
HRESULT GifImage::GetGlobalMetadata()
#if defined(KGE_WIN32)
bool GifImage::GetGlobalMetadata()
{
HRESULT hr = decoder_ ? S_OK : E_FAIL;
@ -194,7 +191,8 @@ HRESULT GifImage::GetGlobalMetadata()
::PropVariantClear(&prop_val);
}
}
return hr;
return SUCCEEDED(hr);
}
#endif
} // namespace kiwano

View File

@ -105,18 +105,20 @@ public:
Frame GetFrame(uint32_t index);
private:
ComPtr<IWICBitmapDecoder> GetDecoder() const;
void SetDecoder(ComPtr<IWICBitmapDecoder> decoder);
HRESULT GetGlobalMetadata();
bool GetGlobalMetadata();
private:
uint32_t frames_count_;
uint32_t width_in_pixels_;
uint32_t height_in_pixels_;
#if defined(KGE_WIN32)
ComPtr<IWICBitmapDecoder> GetDecoder() const;
void SetDecoder(ComPtr<IWICBitmapDecoder> decoder);
ComPtr<IWICBitmapDecoder> decoder_;
#endif
};
/** @} */
@ -141,6 +143,7 @@ inline uint32_t GifImage::GetFramesCount() const
return frames_count_;
}
#if defined(KGE_WIN32)
inline ComPtr<IWICBitmapDecoder> GifImage::GetDecoder() const
{
return decoder_;
@ -150,4 +153,6 @@ inline void GifImage::SetDecoder(ComPtr<IWICBitmapDecoder> decoder)
{
decoder_ = decoder;
}
#endif
} // namespace kiwano

View File

@ -77,17 +77,19 @@ public:
/// @brief <20>零섯부촁꿔긴뻣
void SetMaskTransform(Matrix3x2 const& matrix);
private:
ComPtr<ID2D1Layer> GetLayer() const;
void SetLayer(ComPtr<ID2D1Layer> layer);
private:
Rect area_;
float opacity_;
ShapePtr mask_;
Matrix3x2 mask_transform_;
#if defined(KGE_WIN32)
ComPtr<ID2D1Layer> GetLayer() const;
void SetLayer(ComPtr<ID2D1Layer> layer);
ComPtr<ID2D1Layer> layer_;
#endif
};
/** @} */
@ -137,6 +139,7 @@ inline void LayerArea::SetMaskTransform(Matrix3x2 const& matrix)
mask_transform_ = matrix;
}
#if defined(KGE_WIN32)
inline ComPtr<ID2D1Layer> LayerArea::GetLayer() const
{
return layer_;
@ -146,4 +149,6 @@ inline void LayerArea::SetLayer(ComPtr<ID2D1Layer> layer)
{
layer_ = layer;
}
#endif
} // namespace kiwano

View File

@ -316,23 +316,21 @@ void RenderContext::DrawTextLayout(TextLayout const& layout, Point const& offset
}
}
void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size, D2D1_PIXEL_FORMAT format)
void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
ComPtr<ID2D1Bitmap> saved_bitmap;
HRESULT hr =
render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(format), &saved_bitmap);
HRESULT hr = render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(), &saved_bitmap);
if (SUCCEEDED(hr))
{
texture.SetBitmap(saved_bitmap);
}
else
{
win32::ThrowIfFailed(hr);
}
}
void RenderContext::PushClipRect(Rect const& clip_rect)
{

View File

@ -122,7 +122,7 @@ public:
/// \~chinese
/// @brief 是否有效
void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size, D2D1_PIXEL_FORMAT format);
void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size);
/// \~chinese
/// @brief 是否有效

View File

@ -361,6 +361,7 @@ void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif,
if (SUCCEEDED(hr))
{
ComPtr<IWICBitmapFrameDecode> wic_frame;
HRESULT hr = gif.GetDecoder()->GetFrame(UINT(frame_index), &wic_frame);
if (SUCCEEDED(hr))
@ -459,6 +460,7 @@ void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif,
if (SUCCEEDED(hr))
{
uint32_t udelay = 0;
hr = UIntMult(prop_val.uiVal, 10, &udelay);
if (SUCCEEDED(hr))
{
@ -749,7 +751,7 @@ void Renderer::CreateShapeSink(ShapeSink& sink)
win32::ThrowIfFailed(hr);
}
void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context)
void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context, const Size* desired_size)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@ -757,15 +759,24 @@ void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context
hr = E_UNEXPECTED;
}
TextureRenderContextPtr output;
if (SUCCEEDED(hr))
{
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&bitmap_rt);
TextureRenderContextPtr output = new TextureRenderContext;
if (SUCCEEDED(hr))
{
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
if (desired_size)
{
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(DX::ConvertToSizeF(*desired_size),
&bitmap_rt);
}
else
{
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&bitmap_rt);
}
if (SUCCEEDED(hr))
{
output = new TextureRenderContext;
hr = output->CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt);
}
@ -793,12 +804,24 @@ void Renderer::CreateBrush(Brush& brush, Color const& color)
if (SUCCEEDED(hr))
{
ComPtr<ID2D1SolidColorBrush> output;
hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &output);
ComPtr<ID2D1SolidColorBrush> solid_brush;
if (brush.GetType() == Brush::Type::SolidColor && brush.GetBrush())
{
hr = brush.GetBrush()->QueryInterface(&solid_brush);
if (SUCCEEDED(hr))
{
solid_brush->SetColor(DX::ConvertToColorF(color));
}
}
else
{
hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &solid_brush);
if (SUCCEEDED(hr))
{
brush.SetBrush(output, Brush::Type::SolidColor);
brush.SetBrush(solid_brush, Brush::Type::SolidColor);
}
}
}

View File

@ -167,7 +167,8 @@ public:
/// \~chinese
/// @brief 创建纹理渲染上下文
/// @param[out] render_context 渲染上下文
void CreateTextureRenderTarget(TextureRenderContextPtr& render_context);
/// @param[in] desired_size 期望的输出大小
void CreateTextureRenderTarget(TextureRenderContextPtr& render_context, const Size* desired_size = nullptr);
/// \~chinese
/// @brief 创建纯色画刷

View File

@ -115,6 +115,7 @@ public:
/// @brief 헌뇜近榴
void Clear();
#if defined(KGE_WIN32)
private:
ComPtr<ID2D1Geometry> GetGeometry() const;
@ -122,10 +123,12 @@ private:
private:
ComPtr<ID2D1Geometry> geo_;
#endif
};
/** @} */
#if defined(KGE_WIN32)
inline ComPtr<ID2D1Geometry> Shape::GetGeometry() const
{
return geo_;
@ -135,5 +138,6 @@ inline void Shape::SetGeometry(ComPtr<ID2D1Geometry> shape)
{
geo_ = shape;
}
#endif
} // namespace kiwano

View File

@ -133,6 +133,10 @@ public:
/// @brief Çå¿ÕͼÐÎ
void Clear();
private:
ShapePtr shape_;
#if defined(KGE_WIN32)
private:
ComPtr<ID2D1PathGeometry> GetPathGeometry() const;
@ -142,14 +146,14 @@ private:
void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink);
private:
ShapePtr shape_;
ComPtr<ID2D1PathGeometry> path_geo_;
ComPtr<ID2D1GeometrySink> sink_;
ComPtr<ID2D1PathGeometry> path_geo_;
#endif
};
/** @} */
#if defined(KGE_WIN32)
inline ComPtr<ID2D1PathGeometry> ShapeSink::GetPathGeometry() const
{
return path_geo_;
@ -169,4 +173,6 @@ inline void ShapeSink::SetGeometrySink(ComPtr<ID2D1GeometrySink> sink)
{
sink_ = sink;
}
#endif
} // namespace kiwano

View File

@ -114,6 +114,7 @@ public:
/// @brief ĘǡńÓĐЧ
bool IsValid() const;
#if defined(KGE_WIN32)
private:
ComPtr<ID2D1StrokeStyle> GetStrokeStyle() const;
@ -121,15 +122,17 @@ private:
private:
ComPtr<ID2D1StrokeStyle> style_;
#endif
};
/** @} */
inline bool StrokeStyle::IsValid() const
{
return true; // Always valid
return style_ != nullptr;
}
#if defined(KGE_WIN32)
inline ComPtr<ID2D1StrokeStyle> StrokeStyle::GetStrokeStyle() const
{
return style_;
@ -139,4 +142,6 @@ inline void StrokeStyle::SetStrokeStyle(ComPtr<ID2D1StrokeStyle> style)
{
style_ = style;
}
#endif
} // namespace kiwano

View File

@ -165,6 +165,7 @@ public:
void SetDirtyFlag(uint8_t flag);
#if defined(KGE_WIN32)
private:
ComPtr<IDWriteTextFormat> GetTextFormat() const;
@ -174,11 +175,12 @@ private:
void SetTextLayout(ComPtr<IDWriteTextLayout> layout);
private:
uint8_t dirty_flag_;
ComPtr<IDWriteTextFormat> text_format_;
ComPtr<IDWriteTextLayout> text_layout_;
#endif
private:
uint8_t dirty_flag_;
String text_;
TextStyle style_;
@ -216,16 +218,6 @@ inline void TextLayout::SetDirtyFlag(uint8_t flag)
dirty_flag_ = flag;
}
inline ComPtr<IDWriteTextFormat> TextLayout::GetTextFormat() const
{
return text_format_;
}
inline ComPtr<IDWriteTextLayout> TextLayout::GetTextLayout() const
{
return text_layout_;
}
inline BrushPtr TextLayout::GetFillBrush() const
{
return style_.fill_brush;
@ -241,16 +233,6 @@ inline void TextLayout::SetFillBrush(BrushPtr brush)
style_.fill_brush = brush;
}
inline void TextLayout::SetTextFormat(ComPtr<IDWriteTextFormat> format)
{
text_format_ = format;
}
inline void TextLayout::SetTextLayout(ComPtr<IDWriteTextLayout> layout)
{
text_layout_ = layout;
}
inline void TextLayout::SetOutlineBrush(BrushPtr brush)
{
style_.outline_brush = brush;
@ -265,4 +247,27 @@ inline void TextLayout::SetOutlineStroke(StrokeStylePtr outline_stroke)
{
style_.outline_stroke = outline_stroke;
}
#if defined(KGE_WIN32)
inline ComPtr<IDWriteTextFormat> TextLayout::GetTextFormat() const
{
return text_format_;
}
inline ComPtr<IDWriteTextLayout> TextLayout::GetTextLayout() const
{
return text_layout_;
}
inline void TextLayout::SetTextFormat(ComPtr<IDWriteTextFormat> format)
{
text_format_ = format;
}
inline void TextLayout::SetTextLayout(ComPtr<IDWriteTextLayout> layout)
{
text_layout_ = layout;
}
#endif
} // namespace kiwano

View File

@ -170,6 +170,17 @@ void Texture::SetInterpolationMode(InterpolationMode mode)
}
}
void Texture::SetDefaultInterpolationMode(InterpolationMode mode)
{
default_interpolation_mode_ = mode;
}
InterpolationMode Texture::GetDefaultInterpolationMode()
{
return default_interpolation_mode_;
}
#if defined(KGE_WIN32)
D2D1_PIXEL_FORMAT Texture::GetPixelFormat() const
{
if (bitmap_)
@ -188,15 +199,6 @@ void Texture::SetBitmap(ComPtr<ID2D1Bitmap> bitmap)
{
bitmap_ = bitmap;
}
void Texture::SetDefaultInterpolationMode(InterpolationMode mode)
{
default_interpolation_mode_ = mode;
}
InterpolationMode Texture::GetDefaultInterpolationMode()
{
return default_interpolation_mode_;
}
#endif
} // namespace kiwano

View File

@ -42,9 +42,8 @@ KGE_DECLARE_SMART_PTR(Texture);
*/
enum class InterpolationMode
{
Linear, ///< 双线性插值,对周围四个像素进行两次线性插值计算,
///在图像放大时可能会模糊
Nearest, ///< 最邻近插值,取最邻近的像素点的颜色值
Linear, ///< 双线性插值,对周围四个像素进行两次线性插值计算,在图像放大时可能会模糊
Nearest ///< 最邻近插值,取最邻近的像素点的颜色值
};
/**
@ -110,10 +109,6 @@ public:
/// @brief 获取像素插值方式
InterpolationMode GetBitmapInterpolationMode() const;
/// \~chinese
/// @brief 获取像素格式
D2D1_PIXEL_FORMAT GetPixelFormat() const;
/// \~chinese
/// @brief 拷贝纹理
/// @param copy_from 源纹理
@ -138,6 +133,7 @@ public:
/// @brief 获取默认的像素插值方式
static InterpolationMode GetDefaultInterpolationMode();
#if defined(KGE_WIN32)
private:
/// \~chinese
/// @brief 获取源位图
@ -147,12 +143,19 @@ private:
/// @brief 设置源位图
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
private:
/// \~chinese
/// @brief 获取像素格式
D2D1_PIXEL_FORMAT GetPixelFormat() const;
ComPtr<ID2D1Bitmap> bitmap_;
#endif
private:
InterpolationMode interpolation_mode_;
static InterpolationMode default_interpolation_mode_;
};
/** @} */
} // namespace kiwano