STLL  0.0
Simple Text Layouting Library
output_SDL.h
Go to the documentation of this file.
1 /*
2  * STLL Simple Text Layouting Library
3  *
4  * STLL is the legal property of its developers, whose
5  * names are listed in the COPYRIGHT file, which is included
6  * within the source distribution.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22 #ifndef STLL_LAYOUTER_SDL
23 #define STLL_LAYOUTER_SDL
24 
29 #include "layouterFont.h"
30 #include "layouter.h"
31 #include "color.h"
32 
33 #include "internal/glyphCache.h"
34 #include "internal/blitter.h"
35 #include "internal/gamma.h"
36 
37 #include <SDL.h>
38 
39 namespace STLL {
40 
48 template <class G = internal::Gamma_c<>>
49 class showSDL
50 {
51  private:
52  G g;
53  internal::GlyphCache_c cache;
54  int cx, cy, cw, ch;
55 
56  // a simple get pixel function for the fallback render methods
57  std::tuple<uint8_t, uint8_t, uint8_t> getpixel(const uint8_t * p, const SDL_PixelFormat * f)
58  {
59  uint32_t val;
60 
61  switch(f->BytesPerPixel) {
62  case 1: val = *p;
63  break;
64 
65  case 2: val = *(Uint16 *)p;
66  break;
67 
68  case 3:
69  if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
70  val = p[0] << 16 | p[1] << 8 | p[2];
71  else
72  val = p[0] | p[1] << 8 | p[2] << 16;
73  break;
74 
75  case 4: val = *(Uint32 *)p;
76  break;
77 
78  default:
79  val = 0; /* shouldn't happen, but avoids warnings */
80  break;
81  }
82 
83  Uint8 r, g, b;
84  SDL_GetRGB(val, f, &r, &g, &b);
85 
86  return std::make_tuple(r, g, b);
87  }
88 
89  // a simple put pixel function for the fallback render methods
90  void putpixel(uint8_t * p, uint8_t r, uint8_t g, uint8_t b, const SDL_PixelFormat * f)
91  {
92  uint32_t pixel = SDL_MapRGB(f, r, g, b);
93 
94  switch(f->BytesPerPixel) {
95  case 1:
96  *p = pixel;
97  break;
98 
99  case 2:
100  *(Uint16 *)p = pixel;
101  break;
102 
103  case 3:
104  if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
105  p[0] = (pixel >> 16) & 0xff;
106  p[1] = (pixel >> 8) & 0xff;
107  p[2] = pixel & 0xff;
108  } else {
109  p[0] = pixel & 0xff;
110  p[1] = (pixel >> 8) & 0xff;
111  p[2] = (pixel >> 16) & 0xff;
112  }
113  break;
114 
115  case 4:
116  *(Uint32 *)p = pixel;
117  break;
118  }
119  }
120 
121  constexpr static int calcFormatID(int format, SubPixelArrangement sp)
122  {
123  return (int)(sp)+format*8;
124  }
125 
126  static int getSurfaceFormat(SDL_Surface * s)
127  {
128  auto f = s->format;
129 
130  #if SDL_BYTEORDER == SDL_LIL_ENDIAN
131  if (f->Rmask == 0xFF0000 && f->Gmask == 0xFF00 && f->Bmask == 0xFF)
132  return 1;
133  #endif
134 
135  // default format
136  return 0;
137  }
138 
139  void outputGlyph(int sx, int sy, const internal::PaintData_c & img, SubPixelArrangement sp, Color_c c, SDL_Surface * s)
140  {
141  // check for the right image format
142 
143  // hub code to decide which function to use for output, there are fast functions
144  // for some of the output functions and fallbacks that always work but use relatively slow
145  // pixel read and write routines
146  // if you need additional surface formats add them here (e.g other 3 or 4 Byte formats with
147  // a different byte order
148  // as I don't know what is a useful set to support I only add the one format I I know of: mine
149 
150  switch (calcFormatID(getSurfaceFormat(s), sp))
151  {
152  default: // use no subpixel and no optimisation as default... should not happen though
153  case calcFormatID(0, SUBP_NONE):
154  outputGlyph_NONE(
155  sx, sy, img, c, (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
156  [s, this](const uint8_t * p) -> auto { return getpixel(p, s->format); },
157  [s, this](uint8_t * p, uint8_t r, uint8_t g, uint8_t b) -> void { putpixel(p, r, g, b, s->format); },
158  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
159  cx, cy, cw, ch);
160  break;
161  case calcFormatID(1, SUBP_NONE):
162  outputGlyph_NONE(
163  sx, sy, img, c, (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
164  [](const uint8_t * p) -> auto { return std::make_tuple(p[2], p[1], p[0]); },
165  [](uint8_t * p, uint8_t r, uint8_t g, uint8_t b) -> void { p[2] = r; p[1] = g; p[0] = b; },
166  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
167  cx, cy, cw, ch);
168  break;
169  case calcFormatID(0, SUBP_RGB):
170  outputGlyph_HorizontalRGB(
171  sx, sy, img, c.r(), c.g(), c.b(), c.a(), (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
172  [s, this](const uint8_t * p) -> auto { return getpixel(p, s->format); },
173  [s, this](uint8_t * p, uint8_t r, uint8_t g, uint8_t b) -> void { putpixel(p, r, g, b, s->format); },
174  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
175  cx, cy, cw, ch);
176  break;
177  case calcFormatID(1, SUBP_RGB):
178  outputGlyph_HorizontalRGB(
179  sx, sy, img, c.r(), c.g(), c.b(), c.a(), (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
180  [](const uint8_t * p) -> auto { return std::make_tuple(p[2], p[1], p[0]); },
181  [](uint8_t * p, uint8_t sp1, uint8_t sp2, uint8_t sp3) -> void { p[2] = sp1; p[1] = sp2; p[0] = sp3; },
182  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
183  cx, cy, cw, ch);
184  break;
185  case calcFormatID(0, SUBP_BGR):
186  outputGlyph_HorizontalRGB(
187  sx, sy, img, c.b(), c.g(), c.r(), c.a(), (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
188  [s, this](const uint8_t * p) -> auto { auto t = getpixel(p, s->format); return std::make_tuple(std::get<2>(t), std::get<1>(t), std::get<0>(t)); },
189  [s, this](uint8_t * p, uint8_t sp1, uint8_t sp2, uint8_t sp3) -> void { putpixel(p, sp3, sp2, sp1, s->format); },
190  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
191  cx, cy, cw, ch);
192  break;
193  case calcFormatID(1, SUBP_BGR):
194  outputGlyph_HorizontalRGB(
195  sx, sy, img, c.b(), c.g(), c.r(), c.a(), (uint8_t*)s->pixels, s->pitch, s->format->BytesPerPixel, s->w, s->h,
196  [](const uint8_t * p) -> auto { return std::make_tuple(p[0], p[1], p[2]); },
197  [](uint8_t * p, uint8_t sp1, uint8_t sp2, uint8_t sp3) -> void { p[0] = sp1; p[1] = sp2; p[2] = sp3; },
198  [this](int a1, int a2, int b1, int b2, int c) -> auto { return internal::blend(a1, a2, b1, b2, c, g); },
199  cx, cy, cw, ch);
200  break;
201  }
202  }
203 
204  public:
205 
206  showSDL(void) : cx(0), cy(0), cw(std::numeric_limits<int>::max()), ch(std::numeric_limits<int>::max())
207  {
208  g.setGamma(22);
209  }
210 
219  {
220  public:
230  virtual void draw(int32_t x, int32_t y, uint32_t w, uint32_t h, SDL_Surface * s, const std::string & url) = 0;
231  };
232 
248  void showLayout(const TextLayout_c & l, int sx, int sy, SDL_Surface * s,
249  SubPixelArrangement sp = SUBP_NONE, ImageDrawer_c * images = 0)
250  {
251  SDL_Rect r;
252 
253  /* render */
254  for (auto & i : l.getData())
255  {
256  switch (i.command)
257  {
259  outputGlyph(sx+i.x, sy+i.y, cache.getGlyph(i.font, i.glyphIndex, sp, i.blurr), sp, g.forward(i.c), s);
260  break;
261 
263  if (i.blurr == 0)
264  {
265  r.x = (i.x+sx+32)/64;
266  r.y = (i.y+sy+32)/64;
267  r.w = (i.x+sx+i.w+32)/64-r.x;
268  r.h = (i.y+sy+i.h+32)/64-r.y;
269  SDL_FillRect(s, &r, SDL_MapRGBA(s->format, i.c.r(), i.c.g(), i.c.b(), i.c.a()));
270  }
271  else
272  {
273  outputGlyph(sx+i.x, sy+i.y, cache.getRect(i.w, i.h, sp, i.blurr), sp, g.forward(i.c), s);
274  }
275  break;
276 
278  if (images)
279  images->draw(i.x+sx, i.y+sy, i.w, i.h, s, i.imageURL);
280  break;
281  }
282  }
283  }
284 
292  void setGamma(uint8_t gamma = 22)
293  {
294  g.setGamma(gamma);
295  }
296 
309  void setClipRect(uint16_t x = 0, uint16_t y = 0, uint16_t w = std::numeric_limits<uint16_t>::max(), uint16_t h = std::numeric_limits<uint16_t>::max())
310  {
311  cx = x;
312  cy = y;
313  cw = w;
314  ch = h;
315  }
316 
326  void trimCache(size_t num)
327  {
328  cache.trim(num);
329  }
330 };
331 
332 }
333 
334 #endif
a little class representing an RGBA colour value, an a value of 255 is assumed to be opaque ...
Definition: color.h:36
void showLayout(const TextLayout_c &l, int sx, int sy, SDL_Surface *s, SubPixelArrangement sp=SUBP_NONE, ImageDrawer_c *images=0)
display a single layout
Definition: output_SDL.h:248
const std::vector< CommandData_c > getData(void) const
get the command vector
Definition: layouter.h:121
use horizontal RGB
Definition: layouterFont.h:62
void trimCache(size_t num)
trims the font cache down to a maximal number of entries
Definition: output_SDL.h:326
SubPixelArrangement
define, which sub-pixel arrangement you want to use for sub-pixel output
Definition: layouterFont.h:59
use horizontal BGR
Definition: layouterFont.h:63
class used to encapsulate image drawing
Definition: output_SDL.h:218
draw a rectangle
Definition: layouter.h:55
The namespace for the library. Every function and class is within this namespace. ...
Definition: color.h:31
a class to output layouts using SDL
Definition: output_SDL.h:49
encapsulates a finished layout.
Definition: layouter.h:105
this file contains just a little helper class for a 4-value colour
void setGamma(uint8_t gamma=22)
update the gamma value used for output
Definition: output_SDL.h:292
a FreeType wrapper
void setClipRect(uint16_t x=0, uint16_t y=0, uint16_t w=std::numeric_limits< uint16_t >::max(), uint16_t h=std::numeric_limits< uint16_t >::max())
set the clip rectangle
Definition: output_SDL.h:309
don't use sub-pixel output (e.g. non LCD)
Definition: layouterFont.h:61
the paragraph layouter and its helpers
draw an image
Definition: layouter.h:56
showSDL(void)
Definition: output_SDL.h:206
draw a glyph from a font
Definition: layouter.h:54
virtual void draw(int32_t x, int32_t y, uint32_t w, uint32_t h, SDL_Surface *s, const std::string &url)=0
function called to draw an image