Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
OpeningMoviePresentation.cpp
Go to the documentation of this file.
3#include <algorithm>
5{
6 std::expected<data::LegacyBitmapRGBA8,std::string> movieBackdrop(
8 {
9 const auto [left,top,right,bottom]=movie;
10 // Frame must fit wholly outside the actual movie; full-screen/unknown layouts fall back.
11 if(left<3 || top<3 || right>797 || bottom>597 || left>=right || top>=bottom)
12 return std::unexpected("opening movie rectangle has no safe outside frame");
13 data::LegacyBitmapRGBA8 image{800,600,std::vector<std::uint8_t>(800*600*4,0)};
14 for(int y=0;y<600;++y)for(int x=0;x<800;++x)
15 {
16 if(x>=left && x<right && y>=top && y<bottom)continue;
17 const bool rim=x>=left-3 && x<right+3 && y>=top-3 && y<bottom+3;
18 const auto pixel=(std::size_t(y)*800+x)*4;
19 image.pixels[pixel]=rim?188:13;
20 image.pixels[pixel+1]=rim?157:35;
21 image.pixels[pixel+2]=rim?94:38;image.pixels[pixel+3]=255;
22 }
23 if(bottom<=548)
24 {
25 if(!rasterize)return std::unexpected("opening skip hint font unavailable");
26 auto text=rasterize("Press any key or click to skip");
27 if(!text)return std::unexpected(text.error());
28 if(!text->width || !text->height || text->width>752 || text->height>36 ||
29 text->pixels.size()!=std::size_t(text->width)*text->height*4)
30 return std::unexpected("opening skip hint raster cannot fit below movie");
31 const unsigned ox=(800-text->width)/2,oy=unsigned(bottom)+12;
32 for(unsigned y=0;y<text->height;++y)for(unsigned x=0;x<text->width;++x)
33 {
34 const auto src=(std::size_t(y)*text->width+x)*4;
35 const auto dst=(std::size_t(oy+y)*800+ox+x)*4;
36 const unsigned alpha=text->pixels[src+3];
37 for(unsigned c=0;c<3;++c)
38 image.pixels[dst+c]=std::uint8_t((unsigned(text->pixels[src+c])*alpha+
39 unsigned(image.pixels[dst+c])*(255-alpha)+127)/255);
40 }
41 }
42 return image;
43 }
44
45 std::expected<void,std::string> Presentation::reset(engine::SequencePlayback& playback)
46 {
47 if(surface_)
48 {
49 const auto stopped=playback.stop(*surface_,Priority);
50 if(!stopped)return std::unexpected(stopped.error());
51 (void)playback.runtimeBitmaps().remove(*surface_);
52 }
53 surface_.reset();rectangle_.reset();return {};
54 }
55
56 std::expected<void,std::string> Presentation::sync(std::optional<MovieRect> movie,
58 {
59 if(!movie)return reset(playback);
60 if(surface_ && rectangle_==movie)return {};
62 if(!image)
63 {
64 if(const auto retired=reset(playback);!retired)return retired;
65 return std::unexpected(image.error());
66 }
67 if(surface_)
68 {
69 const auto updated=playback.runtimeBitmaps().update(*surface_,std::move(*image),std::array<float,4>{0,0,800,600},true);
70 if(!updated)return std::unexpected(updated.error());
71 rectangle_=movie;return {};
72 }
73 const auto created=playback.runtimeBitmaps().create(800,600,true);
74 if(!created)return std::unexpected(created.error());
75 const auto updated=playback.runtimeBitmaps().update(*created,std::move(*image),std::array<float,4>{0,0,800,600},true);
76 if(!updated){(void)playback.runtimeBitmaps().remove(*created);return std::unexpected(updated.error());}
77 const auto started=playback.startMoved(*created,Priority,sequence::identity2D());
78 if(!started){(void)playback.runtimeBitmaps().remove(*created);return std::unexpected(started.error());}
79 surface_=*created;rectangle_=movie;return {};
80 }
81}
std::string_view text
std::atomic< float > left
std::atomic< float > right
LegacyBitmapRGBA8 image
int bottom
int top
unsigned index
std::expected< void, std::string > reset(engine::SequencePlayback &playback)
std::expected< void, std::string > sync(std::optional< MovieRect > movie, const HintRasterizer &rasterize, engine::SequencePlayback &playback)
std::function< std::expected< data::LegacyBitmapRGBA8, std::string >(std::string_view)> HintRasterizer
std::expected< data::LegacyBitmapRGBA8, std::string > movieBackdrop(MovieRect movie, const HintRasterizer &rasterize)
Matrix2D identity2D() noexcept
std::vector< std::uint8_t > pixels