1 /** \file lvdrawbuf.h
2 \brief Drawing buffer, gray bitmap buffer
3
4 CoolReader Engine
5
6 (c) Vadim Lopatin, 2000-2006
7 This source code is distributed under the terms of
8 GNU General Public License.
9
10 See LICENSE file for details.
11
12 */
13
14 #ifndef __LVDRAWBUF_H_INCLUDED__
15 #define __LVDRAWBUF_H_INCLUDED__
16
17 #include "crsetup.h"
18
19 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
20 extern "C" {
21 #include <windows.h>
22 }
23 #elif __SYMBIAN32__
24 #include <e32base.h>
25 #include <w32std.h>
26 #endif
27
28 #include "lvtypes.h"
29 #include "lvimg.h"
30
31 enum cr_rotate_angle_t {
32 CR_ROTATE_ANGLE_0 = 0,
33 CR_ROTATE_ANGLE_90,
34 CR_ROTATE_ANGLE_180,
35 CR_ROTATE_ANGLE_270
36 };
37
38 class LVFont;
39 class GLDrawBuf; // workaround for no-rtti builds
40
41 /// Abstract drawing buffer
42 class LVDrawBuf : public CacheableObject
43 {
44 public:
45 // GL draw buffer support
46 /// GL draw buffer compatibility - requires this call before any drawing
beforeDrawing()47 virtual void beforeDrawing() {}
48 /// GL draw buffer compatibility - requires this call after any drawing
afterDrawing()49 virtual void afterDrawing() {}
50
51 // tiles support
52 /// returns true if drawing buffer is tiled
isTiled()53 virtual bool isTiled() { return false; }
54 /// returns tile width (or just width if no tiles)
tileWidth()55 virtual int tileWidth() { return GetWidth(); }
56 /// returns tile height (or just height if no tiles)
tileHeight()57 virtual int tileHeight() { return GetHeight(); }
58 /// returns tile drawbuf for tiled image, returns this for non tiled draw buffer
getTile(int x,int y)59 virtual LVDrawBuf * getTile(int x, int y) {
60 CR_UNUSED2(x, y);
61 return this;
62 }
63 /// returns number of tiles in row
getXtiles()64 virtual int getXtiles() {
65 return 1;
66 }
67 /// returns number of tiles in column
getYtiles()68 virtual int getYtiles() {
69 return 1;
70 }
71
72 /// returns tile rectangle
getTileRect(lvRect & rc,int x,int y)73 virtual void getTileRect(lvRect & rc, int x, int y) {
74 CR_UNUSED2(x, y);
75 rc.left = rc.top = 0;
76 rc.right = GetWidth();
77 rc.bottom = GetHeight();
78 }
79
80 /// rotates buffer contents by specified angle
81 virtual void Rotate( cr_rotate_angle_t angle ) = 0;
82 /// returns white pixel value
83 virtual lUInt32 GetWhiteColor() = 0;
84 /// returns black pixel value
85 virtual lUInt32 GetBlackColor() = 0;
86 /// returns current background color
87 virtual lUInt32 GetBackgroundColor() = 0;
88 /// sets current background color
89 virtual void SetBackgroundColor( lUInt32 cl ) = 0;
90 /// returns current text color
91 virtual lUInt32 GetTextColor() = 0;
92 /// sets current text color
93 virtual void SetTextColor( lUInt32 cl ) = 0;
94 /// gets clip rect
95 virtual void GetClipRect( lvRect * clipRect ) = 0;
96 /// sets clip rect
97 virtual void SetClipRect( const lvRect * clipRect ) = 0;
98 /// set to true for drawing in Paged mode, false for Scroll mode
99 virtual void setHidePartialGlyphs( bool hide ) = 0;
100 /// set to true to invert images only (so they get inverted back to normal by nightmode)
101 virtual void setInvertImages( bool invert ) = 0;
102 /// set to true to enforce dithering (only relevant for 8bpp Gray drawBuf)
103 virtual void setDitherImages( bool dither ) = 0;
104 /// set to true to switch to a more costly smooth scaler instead of nearest neighbor
105 virtual void setSmoothScalingImages( bool smooth ) = 0;
106 /// invert image
107 virtual void Invert() = 0;
108 /// get buffer width, pixels
109 virtual int GetWidth() = 0;
110 /// get buffer height, pixels
111 virtual int GetHeight() = 0;
112 /// get buffer bits per pixel
113 virtual int GetBitsPerPixel() = 0;
114 /// fills buffer with specified color
115 virtual int GetRowSize() = 0;
116 /// fills buffer with specified color
117 virtual void Clear( lUInt32 color ) = 0;
118 /// get pixel value
119 virtual lUInt32 GetPixel( int x, int y ) = 0;
120 /// get average pixel value for area (coordinates are fixed floating points *16)
121 virtual lUInt32 GetAvgColor(lvRect & rc16) = 0;
122 /// get linearly interpolated pixel value (coordinates are fixed floating points *16)
123 virtual lUInt32 GetInterpolatedColor(int x16, int y16) = 0;
124 /// draw gradient filled rectangle with colors for top-left, top-right, bottom-right, bottom-left
GradientRect(int x0,int y0,int x1,int y1,lUInt32 color1,lUInt32 color2,lUInt32 color3,lUInt32 color4)125 virtual void GradientRect(int x0, int y0, int x1, int y1, lUInt32 color1, lUInt32 color2, lUInt32 color3, lUInt32 color4) {
126 CR_UNUSED8(x0, x1, y0, y1, color1, color2, color3, color4);
127 }
128 /// fills rectangle with specified color
129 virtual void FillRect( int x0, int y0, int x1, int y1, lUInt32 color ) = 0;
130 /// draw frame
131 inline void DrawFrame(const lvRect & rc, lUInt32 color, int width = 1)
132 {
133 FillRect( rc.left, rc.top, rc.right, rc.top + width, color );
134 FillRect( rc.left, rc.bottom - width, rc.right, rc.bottom, color );
135 FillRect( rc.left, rc.top + width, rc.left + width, rc.bottom - width, color );
136 FillRect( rc.right - width, rc.top + width, rc.right, rc.bottom - width, color );
137 }
138 /// fills rectangle with specified color
FillRect(const lvRect & rc,lUInt32 color)139 inline void FillRect( const lvRect & rc, lUInt32 color )
140 {
141 FillRect( rc.left, rc.top, rc.right, rc.bottom, color );
142 }
143 /// draws rectangle with specified color
Rect(int x0,int y0,int x1,int y1,lUInt32 color)144 inline void Rect( int x0, int y0, int x1, int y1, lUInt32 color )
145 {
146 FillRect( x0, y0, x1-1, y0+1, color );
147 FillRect( x0, y0, x0+1, y1-1, color );
148 FillRect( x1-1, y0, x1, y1, color );
149 FillRect( x0, y1-1, x1, y1, color );
150 }
151 /// draws rectangle with specified width and color
Rect(int x0,int y0,int x1,int y1,int borderWidth,lUInt32 color)152 inline void Rect( int x0, int y0, int x1, int y1, int borderWidth, lUInt32 color )
153 {
154 FillRect( x0, y0, x1-1, y0+borderWidth, color );
155 FillRect( x0, y0, x0+borderWidth, y1-1, color );
156 FillRect( x1-borderWidth, y0, x1, y1, color );
157 FillRect( x0, y1-borderWidth, x1, y1, color );
158 }
159 /// draws rounded rectangle with specified line width, rounding radius, and color
160 void RoundRect( int x0, int y0, int x1, int y1, int borderWidth, int radius, lUInt32 color, int cornerFlags=0x0F );
161 /// draws rectangle with specified color
Rect(const lvRect & rc,lUInt32 color)162 inline void Rect( const lvRect & rc, lUInt32 color )
163 {
164 Rect( rc.left, rc.top, rc.right, rc.bottom, color );
165 }
166 /// draws rectangle with specified color
Rect(const lvRect & rc,int borderWidth,lUInt32 color)167 inline void Rect( const lvRect & rc, int borderWidth, lUInt32 color )
168 {
169 Rect( rc.left, rc.top, rc.right, rc.bottom, borderWidth, color );
170 }
171 /// fills rectangle with pattern
172 virtual void FillRectPattern( int x0, int y0, int x1, int y1, lUInt32 color0, lUInt32 color1, lUInt8 * pattern ) = 0;
173 /// inverts image in specified rectangle
174 virtual void InvertRect(int x0, int y0, int x1, int y1) = 0;
175 /// sets new size
176 virtual void Resize( int dx, int dy ) = 0;
177 /// draws bitmap (1 byte per pixel) using specified palette
178 virtual void Draw( int x, int y, const lUInt8 * bitmap, int width, int height, lUInt32 * palette ) = 0;
179 /// draws image
180 virtual void Draw( LVImageSourceRef img, int x, int y, int width, int height, bool dither=true ) = 0;
181 /// draws part of source image, possible rescaled
182 virtual void Draw( LVImageSourceRef img, int x, int y, int width, int height, int srcx, int srcy, int srcwidth, int srcheight, bool dither=true ) { CR_UNUSED10(img, x, y, width, height, srcx, srcy, srcwidth, srcheight, dither); }
183 /// for GL buf only - rotated drawing
DrawRotated(LVImageSourceRef img,int x,int y,int width,int height,int rotationAngle)184 virtual void DrawRotated( LVImageSourceRef img, int x, int y, int width, int height, int rotationAngle) { Draw(img, x, y, width, height); CR_UNUSED(rotationAngle); }
185 /// draws buffer content to another buffer doing color conversion if necessary
186 virtual void DrawTo( LVDrawBuf * buf, int x, int y, int options, lUInt32 * palette ) = 0;
187 // draws buffer on top of another buffer to implement background
188 virtual void DrawOnTop( LVDrawBuf * buf, int x, int y) = 0;
189 /// draws rescaled buffer content to another buffer doing color conversion if necessary
190 virtual void DrawRescaled(LVDrawBuf * src, int x, int y, int dx, int dy, int options) = 0;
191 /// draws rescaled buffer content to another buffer doing color conversion if necessary
DrawFragment(LVDrawBuf * src,int srcx,int srcy,int srcdx,int srcdy,int x,int y,int dx,int dy,int options)192 virtual void DrawFragment(LVDrawBuf * src, int srcx, int srcy, int srcdx, int srcdy, int x, int y, int dx, int dy, int options) {
193 CR_UNUSED10(src, srcx, srcy, srcdx, srcdy, x, y, dx, dy, options);
194 }
195 /// draw lines
196 virtual void DrawLine(int x0,int y0,int x1,int y1,lUInt32 color0 ,int length1,int length2,int direction)=0;
197 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
198 /// draws buffer content to another buffer doing color conversion if necessary
199 virtual void DrawTo( HDC dc, int x, int y, int options, lUInt32 * palette ) = 0;
200 #endif
201 /// draws text string
202 /*
203 virtual void DrawTextString( int x, int y, LVFont * pfont,
204 const lChar32 * text, int len,
205 lChar32 def_char, lUInt32 * palette, bool addHyphen=false ) = 0;
206 */
207
208 /*
209 /// draws formatted text
210 virtual void DrawFormattedText( formatted_text_fragment_t * text, int x, int y ) = 0;
211 */
212 /// returns scanline pointer
213 virtual lUInt8 * GetScanLine( int y ) = 0;
214
215
getAlpha()216 virtual int getAlpha() { return 0; }
setAlpha(int alpha)217 virtual void setAlpha(int alpha) { CR_UNUSED(alpha); }
applyAlpha(lUInt32 cl)218 virtual lUInt32 applyAlpha(lUInt32 cl) { return cl; }
219
220 /// virtual destructor
~LVDrawBuf()221 virtual ~LVDrawBuf() { }
asGLDrawBuf()222 virtual GLDrawBuf * asGLDrawBuf() { return NULL; }
223 };
224
225 /// LVDrawBufferBase
226 class LVBaseDrawBuf : public LVDrawBuf
227 {
228 protected:
229 int _dx;
230 int _dy;
231 int _rowsize;
232 lvRect _clip;
233 unsigned char * _data;
234 lUInt32 _backgroundColor;
235 lUInt32 _textColor;
236 bool _hidePartialGlyphs;
237 bool _invertImages;
238 bool _ditherImages;
239 bool _smoothImages;
240 int _drawnImagesCount;
241 int _drawnImagesSurface;
242 public:
243 /// set to true for drawing in Paged mode, false for Scroll mode
setHidePartialGlyphs(bool hide)244 virtual void setHidePartialGlyphs( bool hide ) { _hidePartialGlyphs = hide; }
245 /// set to true to invert images only (so they get inverted back to normal by nightmode)
setInvertImages(bool invert)246 virtual void setInvertImages( bool invert ) { _invertImages = invert; }
247 /// set to true to enforce dithering (only relevant for 8bpp Gray drawBuf)
setDitherImages(bool dither)248 virtual void setDitherImages( bool dither ) { _ditherImages = dither; }
249 /// set to true to switch to a more costly smooth scaler instead of nearest neighbor
setSmoothScalingImages(bool smooth)250 virtual void setSmoothScalingImages( bool smooth ) { _smoothImages = smooth; }
251 /// returns current background color
GetBackgroundColor()252 virtual lUInt32 GetBackgroundColor() { return _backgroundColor; }
253 /// sets current background color
SetBackgroundColor(lUInt32 cl)254 virtual void SetBackgroundColor( lUInt32 cl ) { _backgroundColor=cl; }
255 /// returns current text color
GetTextColor()256 virtual lUInt32 GetTextColor() { return _textColor; }
257 /// sets current text color
SetTextColor(lUInt32 cl)258 virtual void SetTextColor( lUInt32 cl ) { _textColor = cl; }
259 /// gets clip rect
GetClipRect(lvRect * clipRect)260 virtual void GetClipRect( lvRect * clipRect ) { *clipRect = _clip; }
261 /// sets clip rect
262 virtual void SetClipRect( const lvRect * clipRect );
263 /// get average pixel value for area (coordinates are fixed floating points *16)
264 virtual lUInt32 GetAvgColor(lvRect & rc16);
265 /// get linearly interpolated pixel value (coordinates are fixed floating points *16)
266 virtual lUInt32 GetInterpolatedColor(int x16, int y16);
267 /// get buffer width, pixels
268 virtual int GetWidth();
269 /// get buffer height, pixels
270 virtual int GetHeight();
271 /// get row size (bytes)
GetRowSize()272 virtual int GetRowSize() { return _rowsize; }
273 virtual void DrawLine(int x0, int y0, int x1, int y1, lUInt32 color0,int length1,int length2,int direction)=0;
274 /// draws text string
275 /*
276 virtual void DrawTextString( int x, int y, LVFont * pfont,
277 const lChar32 * text, int len,
278 lChar32 def_char,
279 lUInt32 * palette, bool addHyphen=false );
280 */
281 /// draws formatted text
282 //virtual void DrawFormattedText( formatted_text_fragment_t * text, int x, int y );
283
284 /// Get nb of images drawn on buffer
getDrawnImagesCount()285 int getDrawnImagesCount() { return _drawnImagesCount; }
286 /// Get surface of images drawn on buffer
getDrawnImagesSurface()287 int getDrawnImagesSurface() { return _drawnImagesSurface; }
288
LVBaseDrawBuf()289 LVBaseDrawBuf() : _dx(0), _dy(0), _rowsize(0), _data(NULL), _hidePartialGlyphs(true),
290 _invertImages(false), _ditherImages(false), _smoothImages(false),
291 _drawnImagesCount(0), _drawnImagesSurface(0) { }
~LVBaseDrawBuf()292 virtual ~LVBaseDrawBuf() { }
293 };
294
295 /// use to simplify saving draw buffer state
296 class LVDrawStateSaver
297 {
298 LVDrawBuf & _buf;
299 lUInt32 _textColor;
300 lUInt32 _backgroundColor;
301 int _alpha;
302 lvRect _clipRect;
303 LVDrawStateSaver & operator = (LVDrawStateSaver &) {
304 // no assignment
305 return *this;
306 }
307 public:
308 /// save settings
LVDrawStateSaver(LVDrawBuf & buf)309 LVDrawStateSaver( LVDrawBuf & buf )
310 : _buf( buf )
311 , _textColor( buf.GetTextColor() )
312 , _backgroundColor( buf.GetBackgroundColor() )
313 , _alpha(buf.getAlpha())
314 {
315 _buf.GetClipRect( &_clipRect );
316 }
restore()317 void restore()
318 {
319 _buf.SetTextColor( _textColor );
320 _buf.SetBackgroundColor( _backgroundColor );
321 _buf.setAlpha(_alpha);
322 _buf.SetClipRect( &_clipRect );
323 }
324 /// restore settings on destroy
~LVDrawStateSaver()325 ~LVDrawStateSaver()
326 {
327 restore();
328 }
329 };
330
331 #define SAVE_DRAW_STATE( buf ) LVDrawStateSaver drawBufSaver( buf )
332
333 enum DrawBufPixelFormat
334 {
335 DRAW_BUF_1_BPP = 1, /// 1 bpp, 8 pixels per byte packed
336 DRAW_BUF_2_BPP = 2, /// 2 bpp, 4 pixels per byte packed
337 DRAW_BUF_3_BPP = 3, /// 3 bpp, 1 pixel per byte, higher 3 bits are significant
338 DRAW_BUF_4_BPP = 4, /// 4 bpp, 1 pixel per byte, higher 4 bits are significant
339 DRAW_BUF_8_BPP = 8, /// 8 bpp, 1 pixel per byte, all 8 bits are significant
340 DRAW_BUF_16_BPP = 16, /// color 16bit RGB 565
341 DRAW_BUF_32_BPP = 32 /// color 32bit RGB 888
342 };
343
344 /**
345 * 2-bit gray bitmap buffer, partial support for 1-bit buffer
346 * Supported pixel formats for LVGrayDrawBuf :
347 * 1 bpp, 8 pixels per byte packed
348 * 2 bpp, 4 pixels per byte packed
349 * 3 bpp, 1 pixel per byte, higher 3 bits are significant
350 * 4 bpp, 1 pixel per byte, higher 4 bits are significant
351 * 8 bpp, 1 pixel per byte, all 8 bits are significant
352 *
353 */
354 class LVGrayDrawBuf : public LVBaseDrawBuf
355 {
356 private:
357 int _bpp;
358 bool _ownData;
359 public:
360 /// rotates buffer contents by specified angle
361 virtual void Rotate( cr_rotate_angle_t angle );
362 /// returns white pixel value
363 virtual lUInt32 GetWhiteColor();
364 /// returns black pixel value
365 virtual lUInt32 GetBlackColor();
366 /// draws buffer content to another buffer doing color conversion if necessary
367 virtual void DrawTo( LVDrawBuf * buf, int x, int y, int options, lUInt32 * palette );
368 // draws buffer on top of another buffer to implement background
369 virtual void DrawOnTop( LVDrawBuf * buf, int x, int y);
370 /// draws rescaled buffer content to another buffer doing color conversion if necessary
371 virtual void DrawRescaled(LVDrawBuf * src, int x, int y, int dx, int dy, int options);
372 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
373 /// draws buffer content to another buffer doing color conversion if necessary
374 virtual void DrawTo( HDC dc, int x, int y, int options, lUInt32 * palette );
375 #endif
376 /// invert image
377 virtual void Invert();
378 /// get buffer bits per pixel
379 virtual int GetBitsPerPixel();
380 /// returns scanline pointer
381 virtual lUInt8 * GetScanLine( int y );
382 /// fills buffer with specified color
383 virtual void Clear( lUInt32 color );
384 /// get pixel value
385 virtual lUInt32 GetPixel( int x, int y );
386 /// fills rectangle with specified color
387 virtual void FillRect( int x0, int y0, int x1, int y1, lUInt32 color );
388 /// inverts image in specified rectangle
389 virtual void InvertRect( int x0, int y0, int x1, int y1 );
390 /// fills rectangle with pattern
391 virtual void FillRectPattern( int x0, int y0, int x1, int y1, lUInt32 color0, lUInt32 color1, lUInt8 * pattern );
392 /// sets new size
393 virtual void Resize( int dx, int dy );
394 /// draws image
395 virtual void Draw( LVImageSourceRef img, int x, int y, int width, int height, bool dither );
396 /// draws bitmap (1 byte per pixel) using specified palette
397 virtual void Draw( int x, int y, const lUInt8 * bitmap, int width, int height, lUInt32 * palette );
398 /// constructor
399 LVGrayDrawBuf(int dx, int dy, int bpp=2, void * auxdata = NULL );
400 /// destructor
401 virtual ~LVGrayDrawBuf();
402 /// convert to 1-bit bitmap
403 void ConvertToBitmap(bool flgDither);
404 virtual void DrawLine(int x0, int y0, int x1, int y1, lUInt32 color0,int length1,int length2,int direction=0);
405 };
406
407 // NOTE: By default, CRe assumes RGB (array order) actually means BGR
408 // We don't, so, instead of fixing this at the root (i.e., in a *lot* of places),
409 // we simply swap R<->B when rendering to 32bpp, limiting the tweaks to lvdrawbuf
410 // c.f., https://github.com/koreader/koreader-base/pull/878#issuecomment-476723747
411 #ifdef CR_RENDER_32BPP_RGB_PXFMT
RevRGB(lUInt32 cl)412 inline lUInt32 RevRGB( lUInt32 cl ) {
413 return ((cl<<16)&0xFF0000) | ((cl>>16)&0x0000FF) | (cl&0x00FF00);
414 }
415
RevRGBA(lUInt32 cl)416 inline lUInt32 RevRGBA( lUInt32 cl ) {
417 // Swap B <-> R, keep G & A
418 return ((cl<<16)&0x00FF0000) | ((cl>>16)&0x000000FF) | (cl&0xFF00FF00);
419 }
420 #else
RevRGB(lUInt32 cl)421 inline lUInt32 RevRGB( lUInt32 cl ) {
422 return cl;
423 }
424
RevRGBA(lUInt32 cl)425 inline lUInt32 RevRGBA( lUInt32 cl ) {
426 return cl;
427 }
428 #endif
429
rgb565to888(lUInt32 cl)430 inline lUInt32 rgb565to888( lUInt32 cl ) {
431 return ((cl & 0xF800)<<8) | ((cl & 0x07E0)<<5) | ((cl & 0x001F)<<3);
432 }
433
rgb888to565(lUInt32 cl)434 inline lUInt16 rgb888to565( lUInt32 cl ) {
435 return (lUInt16)(((cl>>8)& 0xF800) | ((cl>>5 )& 0x07E0) | ((cl>>3 )& 0x001F));
436 }
437
438 #define DIV255(V, t) \
439 { \
440 auto _v = (V) + 128; \
441 (t) = (((_v >> 8U) + _v) >> 8U); \
442 }
443
444 // Because of course we're not using <stdint.h> -_-".
445 #ifndef UINT8_MAX
446 #define UINT8_MAX (255)
447 #endif
448
449 // Quantize an 8-bit color value down to a palette of 16 evenly spaced colors, using an ordered 8x8 dithering pattern.
450 // With a grayscale input, this happens to match the eInk palette perfectly ;).
451 // If the input is not grayscale, and the output fb is not grayscale either,
452 // this usually still happens to match the eInk palette after the EPDC's own quantization pass.
453 // c.f., https://en.wikipedia.org/wiki/Ordered_dithering
454 // & https://github.com/ImageMagick/ImageMagick/blob/ecfeac404e75f304004f0566557848c53030bad6/MagickCore/threshold.c#L1627
455 // NOTE: As the references imply, this is straight from ImageMagick,
456 // with only minor simplifications to enforce Q8 & avoid fp maths.
dither_o8x8(int x,int y,lUInt8 v)457 static inline lUInt8 dither_o8x8(int x, int y, lUInt8 v)
458 {
459 // c.f., https://github.com/ImageMagick/ImageMagick/blob/ecfeac404e75f304004f0566557848c53030bad6/config/thresholds.xml#L107
460 static const lUInt8 threshold_map_o8x8[] = { 1, 49, 13, 61, 4, 52, 16, 64, 33, 17, 45, 29, 36, 20, 48, 32,
461 9, 57, 5, 53, 12, 60, 8, 56, 41, 25, 37, 21, 44, 28, 40, 24,
462 3, 51, 15, 63, 2, 50, 14, 62, 35, 19, 47, 31, 34, 18, 46, 30,
463 11, 59, 7, 55, 10, 58, 6, 54, 43, 27, 39, 23, 42, 26, 38, 22 };
464
465 // Constants:
466 // Quantum = 8; Levels = 16; map Divisor = 65
467 // QuantumRange = 0xFF
468 // QuantumScale = 1.0 / QuantumRange
469 //
470 // threshold = QuantumScale * v * ((L-1) * (D-1) + 1)
471 // NOTE: The initial computation of t (specifically, what we pass to DIV255) would overflow an uint8_t.
472 // With a Q8 input value, we're at no risk of ever underflowing, so, keep to unsigned maths.
473 // Technically, an uint16_t would be wide enough, but it gains us nothing,
474 // and requires a few explicit casts to make GCC happy ;).
475 lUInt32 t;
476 DIV255(v * ((15U << 6) + 1U), t);
477 // level = t / (D-1);
478 lUInt32 l = (t >> 6);
479 // t -= l * (D-1);
480 t = (t - (l << 6));
481
482 // map width & height = 8
483 // c = ClampToQuantum((l+(t >= map[(x % mw) + mw * (y % mh)])) * QuantumRange / (L-1));
484 lUInt32 q = ((l + (t >= threshold_map_o8x8[(x & 7U) + 8U * (y & 7U)])) * 17);
485 // NOTE: We're doing unsigned maths, so, clamping is basically MIN(q, UINT8_MAX) ;).
486 // The only overflow we should ever catch should be for a few white (v = 0xFF) input pixels
487 // that get shifted to the next step (i.e., q = 272 (0xFF + 17)).
488 return (q > UINT8_MAX ? UINT8_MAX : static_cast<lUInt8>(q));
489 }
490
491 // Declare our bit of scaler ripped from Qt5...
492 namespace CRe {
493 lUInt8* qSmoothScaleImage(const lUInt8* src, int sw, int sh, bool ignore_alpha, int dw, int dh);
494 }
495
496 /// 32-bit RGB buffer
497 class LVColorDrawBuf : public LVBaseDrawBuf
498 {
499 private:
500 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
501 HDC _drawdc;
502 HBITMAP _drawbmp;
503 #endif
504 int _bpp;
505 bool _ownData;
506 public:
507 /// rotates buffer contents by specified angle
508 virtual void Rotate( cr_rotate_angle_t angle );
509 /// returns white pixel value
510 virtual lUInt32 GetWhiteColor();
511 /// returns black pixel value
512 virtual lUInt32 GetBlackColor();
513 /// draws buffer content to another buffer doing color conversion if necessary
514 virtual void DrawTo( LVDrawBuf * buf, int x, int y, int options, lUInt32 * palette );
515 // draws buffer on top of another buffer to implement background
516 virtual void DrawOnTop( LVDrawBuf * buf, int x, int y);
517 /// draws rescaled buffer content to another buffer doing color conversion if necessary
518 virtual void DrawRescaled(LVDrawBuf * src, int x, int y, int dx, int dy, int options);
519 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
520 /// draws buffer content to another buffer doing color conversion if necessary
521 virtual void DrawTo( HDC dc, int x, int y, int options, lUInt32 * palette );
522 #endif
523 /// invert image
524 virtual void Invert();
525 /// get buffer bits per pixel
526 virtual int GetBitsPerPixel();
527 /// fills buffer with specified color
528 virtual void Clear( lUInt32 color );
529 /// get pixel value
530 virtual lUInt32 GetPixel( int x, int y );
531 /// fills rectangle with specified color
532 virtual void FillRect( int x0, int y0, int x1, int y1, lUInt32 color );
533 /// fills rectangle with pattern
534 virtual void FillRectPattern( int x0, int y0, int x1, int y1, lUInt32 color0, lUInt32 color1, lUInt8 * pattern );
535 /// inverts specified rectangle
536 virtual void InvertRect( int x0, int y0, int x1, int y1 );
537 /// sets new size
538 virtual void Resize( int dx, int dy );
539 /// draws image
540 virtual void Draw( LVImageSourceRef img, int x, int y, int width, int height, bool dither );
541 /// draws bitmap (1 byte per pixel) using specified palette
542 virtual void Draw( int x, int y, const lUInt8 * bitmap, int width, int height, lUInt32 * palette );
543 /// returns scanline pointer
544 virtual lUInt8 * GetScanLine( int y );
545
546 /// create own draw buffer
547 LVColorDrawBuf(int dx, int dy, int bpp=32);
548 /// creates wrapper around external RGBA buffer
549 LVColorDrawBuf(int dx, int dy, lUInt8 * externalBuffer, int bpp=32 );
550 /// destructor
551 virtual ~LVColorDrawBuf();
552 /// convert to 1-bit bitmap
553 void ConvertToBitmap(bool flgDither);
554 /// draw line
555 virtual void DrawLine(int x0,int y0,int x1,int y1,lUInt32 color0 ,int length1=1,int length2=0,int direction=0);
556 #if !defined(__SYMBIAN32__) && defined(_WIN32) && !defined(QT_GL)
557 /// returns device context for bitmap buffer
GetDC()558 HDC GetDC() { return _drawdc; }
559 #endif
560 };
561
562
563
564 #endif
565
566