1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
|
/*
** ClanLib SDK
** Copyright (c) 1997-2005 The ClanLib Team
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
** Note: Some of the libraries ClanLib may link to may have additional
** requirements or restrictions.
**
** File Author(s):
**
** Magnus Norddahl
** (if your name is missing here, please add it)
*/
//! clanDisplay="Fonts"
//! header=display.h
#ifndef header_text_styler
#define header_text_styler
#ifdef CL_API_DLL
#ifdef CL_DISPLAY_EXPORT
#define CL_API_DISPLAY __declspec(dllexport)
#else
#define CL_API_DISPLAY __declspec(dllimport)
#endif
#else
#define CL_API_DISPLAY
#endif
#if _MSC_VER > 1000
#pragma once
#endif
#ifdef _MSC_VER
#pragma warning( disable : 4786)
#endif
#include <string>
#include <map>
#include <list>
#include "font.h"
#include "glyph_buffer.h"
#include "../Core/Math/origin.h"
#include "../Core/Math/rect.h"
#include "../Core/Math/point.h"
#include "../Core/Resources/resource.h"
class CL_GraphicContext;
class CL_ResourceManager;
//: Draws specially formatted text in one or several fonts.
//- !group=Display/Fonts!
//- !header=display.h!
//- <p> A CL_TextStyler consists of a collection of named CL_Fonts.
//- When passed a string to draw, it uses vaguely HTMLish tags to select
//- which font to draw text in. For example:</p>
//- <code> "Here's some text, {italic}isn't it {bold}amazing?{/bold}{/italic}" </code>
//- <p> CL_TextStyler does not have any mechanisms on its own for bold
//- and italic text, so in order for this to work, there must be fonts named 'bold' and
//- 'italic' that it knows of. Text outside font tags is
//- drawn in the font named 'default', if it exists. No blending
//- or anything like that is performed with nested fonts; the innermost font
//- is the one used, and the nesting is for convienence.</p>
//- <p>There are also special tags which are bounded by [ and ].
//- These can be used for justification, scaling, color, and newlines.</p>
//- <p>Justification can be
//- either left, center, or right, shown by this example:</p>
//- <code> "This line is left justified.\n[j center]This line is center
//- justified.\n[j right]This line is right justified.\n[/j][/j]Back to
//- left justification." </code>
//- <p>Scaling tags affect both x and y scaling the same amount when given a single number, but
//- can be given two numbers to affect both:</p>
//- <code> "Regular size.[s 2.0 1.0]Double wide text.[/s][s 1.0 2.0]Double tall text." </code>
//- <p>Scaling tags are also cumulative, as shown by this example:</p>
//- <code> "This text is at regular size.[s 2.0]This text is at double size.[s 2.0]This text is at quadruple
//- size.[/s]Double size again.[/s]Regular size again." </code>
//- <p>Color tags allow specification of RGB and RGBA values, as well as use of named colors (see CL_Color's
//- documentation for a reference). The color overrides the font's existing color entirely, and does not blend
//- with it. Be sure that the blending functions of a font are set properly before using that font in a TextStyler
//- with color tags.</p>
//- <code> "This text is in whatever the font's default color is.[c blue]This text is blue.[c red]This text
//- is red, not blue-red; there's no blending between nested colors.[/c][/c][c 0 255 0]This text is green.[/c]
//- [c 255 0 255 175]This text is translucent purple; the fourth number is the alpha value, which
//- is set to opaque (255) if unspecified.[/c]" </code>
//- <p>Newline tags are only helpful when loading TextStyler-intented strings from XML resource
//- files, where there's no easy way to insert an actual newline character:</p>
//- <code> "First line.[n]Second line." </code>
//- <p>To draw a real a left brace or left square bracket and not start a tag, just escape it by putting two
//- of the characters in a row; right braces and right square brackets don't need to be escaped,
//- and CL_TextStyler will take them literally if they don't seem to end an open tag. References to fonts which are
//- not in the CL_TextStyler's font map will be silently ignored. Using bad nesting order is
//- also allowed (i.e. {a}{b}{/a}{/b}). However, you can't have a partial tag in the string
//- (that is, "blah blah {tag doesnt end"), and you are not allowed to
//- put any of the four tag opening/closing characters inside a tag, or in
//- a font name, even if they're escaped. </p>
//- <p>Like with CL_Font, scaling affects the calculation
//- of any bounding rectangles (such as the result returned
//- by draw() or bounding_rect(), or the rectangle calculated internally by
//- draw() for alignment). This is because scaling
//- the CL_TextStyler is effectively just changing the point size of the glyphs,
//- and that affects all sorts of things, such as word wrapping.</p>
class CL_API_DISPLAY CL_TextStyler
{
//! Construction:
public:
//: Constructs a text styler.
CL_TextStyler();
CL_TextStyler(const CL_TextStyler& other);
CL_TextStyler(
const std::string &resource_id,
CL_ResourceManager *manager);
//: Destruction
virtual ~CL_TextStyler() {resource.unload();}
//! Attributes:
public:
//: Returns a reference to the font map.
std::map<std::string, CL_Font>& get_fonts()
{return fonts;}
const std::map<std::string, CL_Font>& get_fonts() const
{return fonts;}
//: Returns scale for x and y.
//- <p> 1.0f is normal scale, 2.0f is twice the size, etc. </p>
void get_scale(float &x, float &y) const
{x = scale_x, y = scale_y;}
//: Returns translation hotspot.
void get_alignment(CL_Origin &origin, int &x, int &y) const
{origin = trans_origin; x = trans_x; y = trans_y;}
//: Returns the drawn height of some source text, or of the default font if no arguments passed.
//return: The height in pixels.
//param str: The source string to parse and render.
//param start: A starting iterator, inclusive.
//param end: An ending iterator, exclusive.
//param max_size: Acts like the size of a dest rectangle passed to draw(), for height truncating and word wrapping.
//- <p> Generally, get_height(" ") will return zero, since usually
//- the space glyph isn't given in the font, and so it has a height and width of zero.
//- Calling get_height() on a CL_TextStyler without arguments is the same as calling
//- get_height() without arguments on that CL_TextStyler's default font.</p>
int get_height() const;
int get_height(
const std::string &str,
CL_Size max_size = CL_Size(0,0)) const
{return get_size(str, max_size).height;}
int get_height(
std::string::const_iterator start,
std::string::const_iterator end,
CL_Size max_size = CL_Size(0,0)) const
{return get_size(start, end, max_size).height;}
//: Returns the drawn width of some source text.
//return: The width in pixels.
//param str: The source string to parse and render.
//param start: A starting iterator, inclusive.
//param end: An ending iterator, exclusive.
//param max_size: Acts like the size of a dest rectangle passed to draw(), for height truncating and word wrapping.
//- <p>Newlines have a width of zero unless you gave them a glyph (which is pretty useless anyways).
//- Other unknown characters have the width of a space in their respective font.</p>
int get_width(
const std::string &str,
CL_Size max_size = CL_Size(0,0)) const
{return get_size(str, max_size).width;}
int get_width(
std::string::const_iterator start,
std::string::const_iterator end,
CL_Size max_size = CL_Size(0,0)) const
{return get_size(start, end, max_size).width;}
//: Returns the drawn size of some source text.
//return: The size in pixels.
//param str: The source string to parse and render.
//param start: A starting iterator, inclusive.
//param end: An ending iterator, exclusive.
//param max_size: Acts like the size of a dest rectangle passed to draw(), for height truncating and word wrapping.
//- <p>Newlines have a width of zero unless you gave them a glyph (which is pretty useless anyways).
//- Other unknown characters have the width of a space in their respective font.</p>
CL_Size get_size(
const std::string &str,
CL_Size max_size = CL_Size(0,0)) const
{return get_size(str.begin(), str.end(), max_size);}
CL_Size get_size(
std::string::const_iterator start,
std::string::const_iterator end,
CL_Size max_size = CL_Size(0,0)) const;
//: Calculate the rectangle that would be occupied by a draw operation.
//param x, y: Anchor position of where to render text. Actual rendering position depends on the alignment mode.
//param dest: Rectangle to draw text in. The text will be word-wrapped against delimiters to fit inside the rectangle.
//param str: The source string to parse and render.
//param start: String position to begin rendering at, inclusive.
//param end: String position to end rendering at, exclusive.
//- <p> You can specify a dest rectangle with a width or height of zero or less to disable word wrapping
//- or height truncating, respectively. </p>
//- <p> It's more efficient to draw text into a GlyphBuffer, then use that for drawing and bounding
//- rect calculation. This method is just for convienence. </p>
CL_Rect bounding_rect(
int x,
int y,
const std::string& str) const
{return bounding_rect(CL_Rect(x, y, x, y), str.begin(), str.end());}
CL_Rect bounding_rect(
CL_Rect dest,
const std::string& str) const
{return bounding_rect(dest, str.begin(), str.end());}
CL_Rect bounding_rect(
int x,
int y,
std::string::const_iterator start,
std::string::const_iterator end) const
{return bounding_rect(CL_Rect(x, y, x, y), start, end);}
CL_Rect bounding_rect(
CL_Rect dest,
std::string::const_iterator start,
std::string::const_iterator end) const;
//: Resource owning this text styler, if any.
CL_Resource resource;
//! Operations:
public:
//: Copy assignment
CL_TextStyler& operator=(const CL_TextStyler& other);
//: Adds a new font to the map
void add_font(std::string name, const CL_Font& font)
{fonts.insert(std::pair<std::string, CL_Font>(name, font));}
//: Draws text onto a graphics context.
//return: The number of glyphs that were drawn.
//param x, y: Anchor position of where to draw at. Actual rendering position depends on the alignment mode.
//param dest: Rectangle to draw text in. The text will be word-wrapped against delimiters to fit inside the rectangle.
//param str: The source string to parse and render.
//param start: String position to begin rendering at, inclusive.
//param end: String position to end rendering at, exclusive.
//param context: Graphic context on which to render upon. If null, will use CL_Display's current graphic context.
//- <p> You can specify a dest rectangle with a width or height of zero or less to disable word wrapping
//- or height truncating, respectively. </p>
int draw(
int x,
int y,
const std::string& str,
CL_GraphicContext *context = 0) const
{return draw(CL_Rect(x, y, x, y), str.begin(), str.end(), context);}
int draw(
CL_Rect dest,
const std::string& str,
CL_GraphicContext *context = 0) const
{return draw(dest, str.begin(), str.end(), context);}
int draw(
int x,
int y,
std::string::const_iterator start,
std::string::const_iterator end,
CL_GraphicContext *context = 0) const
{return draw(CL_Rect(x, y, x, y), start, end, context);}
int draw(
CL_Rect dest,
std::string::const_iterator start,
std::string::const_iterator end,
CL_GraphicContext *context = 0) const;
//: Inserts data into a CL_GlyphBuffer, treating the glyphs already there as part of a previous draw_to_gb().
//return: The number of glyphs that were drawn.
//param str: The input string to draw.
//param start: String position to begin drawing at, inclusive.
//param end: String position to end drawing at, exclusive.
//param max_size: Sets size for word wrapping and height truncating. Either can be zero to disable that feature.
//param gb: The glyph buffer to mess with.
//- <p> The CL_GlyphBuffer's contents (the glyphs vector, the font markers map, and the effects maps),
//- if any, must not have been created/altered by anything but CL_Font::draw_to_gb() and/or CL_TextStyler::draw_to_gb()
//- for this method to work.</p>
//- <p> If you are doing draw_to_gb several sequential times
//- to the same CL_GlyphBuffer, then you must pass the same maximum width to each call of
//- draw_to_gb. </p>
//- <p> You can tell when you've filled the buffer up to the height in max_size when a call to this method returns
//- anything less than the size of the string. There's also the chance that it will backtrack and return
//- a negative value if it runs out
//- of vertical space in the process of wrapping a just-completed word; this is still a sign that you've
//- ran out of vertical space.</p>
//- <p> Scale tags create new font markers in the GB, they don't use the GB scale effects map. </p>
int draw_to_gb(
const std::string &str,
CL_GlyphBuffer &gb,
CL_Size max_size = CL_Size(0,0)) const
{return draw_to_gb(str.begin(), str.end(), gb, max_size);}
int draw_to_gb(
std::string::const_iterator start,
std::string::const_iterator end,
CL_GlyphBuffer &gb,
CL_Size max_size = CL_Size(0,0)) const;
//: Set scale for x and y directions individually.
//- <p> 1.0f is normal scale, 2.0f is twice the size, etc. </p>
void set_scale(float x, float y)
{scale_x = x; scale_y = y;}
//: Sets translation hotspot.
void set_alignment(CL_Origin origin, int x = 0, int y = 0)
{trans_origin = origin; trans_x = x; trans_y = y;}
// Implementation:
private:
//: Scale.
float scale_x;
float scale_y;
//: Alignment.
CL_Origin trans_origin;
int trans_x;
int trans_y;
//: The font map.
std::map<std::string, CL_Font> fonts;
};
#endif
|