1 /*
2  * Copyright (C) 2017-2020 by the Widelands Development Team
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  *
18  */
19 
20 #ifndef WL_GRAPHIC_TEXT_RENDERED_TEXT_H
21 #define WL_GRAPHIC_TEXT_RENDERED_TEXT_H
22 
23 #include <memory>
24 
25 #include "base/rect.h"
26 #include "base/vector.h"
27 #include "graphic/image.h"
28 #include "graphic/rendertarget.h"
29 #include "graphic/texture.h"
30 
31 namespace UI {
32 
33 /// A rectangle that contains blitting information for rendered text.
34 class RenderedRect {
35 public:
36 	/// Whether the RenderedRect's image should be blitted once or tiled
37 	enum class DrawMode {
38 		kBlit,  // The image texture is considered a foreground image and blitted as is
39 		kTile   // The image texture is considered a background image and is tiled to fill the rect
40 	};
41 
42 private:
43 	// The image is managed by a transient cache
44 	RenderedRect(const Recti& init_rect,
45 	             std::shared_ptr<const Image> init_image,
46 	             bool visited,
47 	             const RGBColor& color,
48 	             bool is_background_color_set,
49 	             DrawMode init_mode);
50 	// The image is managed by a pernament cache
51 	RenderedRect(const Recti& init_rect,
52 	             const Image* init_image,
53 	             bool visited,
54 	             const RGBColor& color,
55 	             bool is_background_color_set,
56 	             DrawMode init_mode);
57 
58 public:
59 	/// RenderedRect will contain a background image that should be tiled
60 	explicit RenderedRect(const Recti& init_rect, const Image* init_image);
61 
62 	/// RenderedRect will contain a background color that should be tiled
63 	explicit RenderedRect(const Recti& init_rect, const RGBColor& color);
64 
65 	/// RenderedRect will contain a normal image that is managed by a transient cache.
66 	/// Use this if the image is managed by an instance of TextureCache.
67 	explicit RenderedRect(std::shared_ptr<const Image> init_image);
68 
69 	/// RenderedRect will contain a normal image that is managed by a permanent cache.
70 	/// Use this if the image is managed by g_gr->images().
71 	explicit RenderedRect(const Image* init_image);
~RenderedRect()72 	~RenderedRect() {
73 	}
74 
75 	/// An image to be blitted. Can be nullptr.
76 	const Image* image() const;
77 
78 	/// The x position of the rectangle
79 	int x() const;
80 	/// The y position of the rectangle
81 	int y() const;
82 	/// The width of the rectangle
83 	int width() const;
84 	/// The height of the rectangle
85 	int height() const;
86 
87 	/// Change x and y position of the rectangle.
88 	void set_origin(const Vector2i& new_origin);
89 
90 	/// Set that this rectangle was already visited by the font renderer. Needed by the font renderer
91 	/// for correct positioning.
92 	void set_visited();
93 	/// Whether this rectangle was already visited by the font renderer
94 	bool was_visited() const;
95 
96 	/// Whether this rectangle contains a background color
97 	bool has_background_color() const;
98 	/// This rectangle's background color
99 	const RGBColor& background_color() const;
100 
101 	/// Whether the RenderedRect's image should be blitted once or tiled
102 	DrawMode mode() const;
103 
104 private:
105 	Recti rect_;
106 	// We have 2 image objects depending on the caching situation - only use one of them at the same
107 	// time.
108 	std::shared_ptr<const Image> transient_image_;  // Shared ownership, managed by a transient cache
109 	const Image* permanent_image_;                  // Not owned, managed by a permanent cache
110 	bool visited_;
111 	const RGBColor background_color_;
112 	const bool is_background_color_set_;
113 	const DrawMode mode_;
114 };
115 
116 struct RenderedText {
117 	/// RenderedRects that can be drawn on screen
118 	std::vector<std::unique_ptr<RenderedRect>> rects;
119 
120 	/// The width occupied  by all rects in pixels.
121 	int width() const;
122 	/// The height occupied  by all rects in pixels.
123 	int height() const;
124 
125 	enum class CropMode {
126 		// The RenderTarget will handle all cropping. Use this for scrollable elements or when you
127 		// don't expect any cropping.
128 		kRenderTarget,
129 		// The draw() method will handle horizontal cropping. Use this for table entries.
130 		kSelf
131 	};
132 
133 	/// Draw the rects. 'position', 'region' and 'align' are used to control the overall drawing
134 	/// position and cropping.
135 	/// For 'cropmode', use kRenderTarget if you wish the text to fill the whole RenderTarget, e.g.
136 	/// for scrolling panels. Use kHorizontal for horizontal cropping in smaller elements, e.g. table
137 	/// cells.
138 	void draw(RenderTarget& dst,
139 	          const Vector2i& position,
140 	          const Recti& region,
141 	          UI::Align align = UI::Align::kLeft,
142 	          CropMode cropmode = CropMode::kRenderTarget) const;
143 
144 	/// Draw the rects without cropping. 'position' and 'align' are used to control the overall
145 	/// drawing position
146 	void draw(RenderTarget& dst, const Vector2i& position, UI::Align align = UI::Align::kLeft) const;
147 
148 private:
149 	/// Helper function for draw(). Blits the rect's background color and images. The rect will be
150 	/// positioned according to 'aligned_position' and cropped according to 'region'. 'offxet_x' and
151 	/// 'align' are used by the cropping algorithm when we use CropMode::kSelf mode.
152 	void blit_rect(RenderTarget& dst,
153 	               int offset_x,
154 	               const Vector2i& aligned_position,
155 	               const RenderedRect& rect,
156 	               const Recti& region,
157 	               Align align,
158 	               CropMode cropmode) const;
159 
160 	/// Helper function for CropMode::kSelf. It only does horizontal cropping since the RenderTarget
161 	/// itself still seems to take care of vertical stuff for us in tables.
162 	void blit_cropped(RenderTarget& dst,
163 	                  int offset_x,
164 	                  const Vector2i& position,
165 	                  const Vector2i& blit_point,
166 	                  const RenderedRect& rect,
167 	                  const Recti& region,
168 	                  Align align) const;
169 };
170 
171 }  // namespace UI
172 
173 #endif  // end of include guard: WL_GRAPHIC_TEXT_RENDERED_TEXT_H
174