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