1 /* 2 * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. 3 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. 4 * All rights reserved. Distributed under the terms of the MIT License. 5 * 6 * Base class for different drawing modes. 7 * 8 */ 9 10 #ifndef DRAWING_MODE_H 11 #define DRAWING_MODE_H 12 13 #include "drawing_support.h" 14 15 #include "PatternHandler.h" 16 #include "PixelFormat.h" 17 18 class PatternHandler; 19 20 typedef PixelFormat::color_type color_type; 21 typedef PixelFormat::agg_buffer agg_buffer; 22 23 // BLEND 24 // 25 // This macro assumes source alpha in range 0..255 and 26 // ignores dest alpha (is assumed to equal 255). 27 // TODO: We need the assignment of alpha only when drawing into bitmaps! 28 #define BLEND(d, r, g, b, a) \ 29 { \ 30 pixel32 _p; \ 31 _p.data32 = *(uint32*)d; \ 32 d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 8)) >> 8); \ 33 d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 8)) >> 8); \ 34 d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 8)) >> 8); \ 35 d[3] = 255; \ 36 } 37 38 39 #define BLEND_SUBPIX(d, r, g, b, a1, a2, a3) \ 40 { \ 41 pixel32 _p; \ 42 _p.data32 = *(uint32*)d; \ 43 d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \ 44 d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \ 45 d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \ 46 d[3] = 255; \ 47 } 48 49 // BLEND_FROM 50 // 51 // This macro assumes source alpha in range 0..255 and 52 // ignores dest alpha (is assumed to equal 255). 53 // It uses two colors for the blending (f and s) and writes 54 // the result into a third color (d). 55 // TODO: We need the assignment of alpha only when drawing into bitmaps! 56 #define BLEND_FROM(d, r1, g1, b1, r2, g2, b2, a) \ 57 { \ 58 d[0] = (((((b2) - (b1)) * (a)) + ((b1) << 8)) >> 8); \ 59 d[1] = (((((g2) - (g1)) * (a)) + ((g1) << 8)) >> 8); \ 60 d[2] = (((((r2) - (r1)) * (a)) + ((r1) << 8)) >> 8); \ 61 d[3] = 255; \ 62 } 63 64 #define BLEND_FROM_SUBPIX(d, r1, g1, b1, r2, g2, b2, a1, a2, a3) \ 65 { \ 66 d[0] = (((((b2) - (b1)) * (a1)) + ((b1) << 8)) >> 8); \ 67 d[1] = (((((g2) - (g1)) * (a2)) + ((g1) << 8)) >> 8); \ 68 d[2] = (((((r2) - (r1)) * (a3)) + ((r1) << 8)) >> 8); \ 69 d[3] = 255; \ 70 } 71 72 // BLEND16 73 // 74 // This macro assumes source alpha in range 0..65025 and 75 // ignores dest alpha (is assumed to equal 255). 76 // TODO: We need the assignment of alpha only when drawing into bitmaps! 77 // BLEND16 78 #define BLEND16(d, r, g, b, a) \ 79 { \ 80 pixel32 _p; \ 81 _p.data32 = *(uint32*)d; \ 82 d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 16)) >> 16); \ 83 d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 16)) >> 16); \ 84 d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 16)) >> 16); \ 85 d[3] = 255; \ 86 } 87 88 // BLEND16_SUBPIX 89 #define BLEND16_SUBPIX(d, r, g, b, a1, a2, a3) \ 90 { \ 91 pixel32 _p; \ 92 _p.data32 = *(uint32*)d; \ 93 d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 16)) >> 16); \ 94 d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 16)) >> 16); \ 95 d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 16)) >> 16); \ 96 d[3] = 255; \ 97 } 98 99 // BLEND_COMPOSITE 100 // 101 // This macro assumes source alpha in range 0..255 and 102 // composes the source color over a possibly semi-transparent background. 103 #define BLEND_COMPOSITE(d, r, g, b, a) \ 104 { \ 105 pixel32 _p; \ 106 _p.data32 = *(uint32*)d; \ 107 if (_p.data8[3] == 255) { \ 108 d[0] = (((((b) - _p.data8[0]) * (a)) + (_p.data8[0] << 8)) >> 8); \ 109 d[1] = (((((g) - _p.data8[1]) * (a)) + (_p.data8[1] << 8)) >> 8); \ 110 d[2] = (((((r) - _p.data8[2]) * (a)) + (_p.data8[2] << 8)) >> 8); \ 111 d[3] = 255; \ 112 } else { \ 113 if (_p.data8[3] == 0) { \ 114 d[0] = (b); \ 115 d[1] = (g); \ 116 d[2] = (r); \ 117 d[3] = (a); \ 118 } else { \ 119 uint8 alphaRest = 255 - (a); \ 120 uint32 alphaTemp = (65025 - alphaRest * (255 - _p.data8[3])); \ 121 uint32 alphaDest = _p.data8[3] * alphaRest; \ 122 uint32 alphaSrc = 255 * (a); \ 123 d[0] = (_p.data8[0] * alphaDest + (b) * alphaSrc) / alphaTemp; \ 124 d[1] = (_p.data8[1] * alphaDest + (g) * alphaSrc) / alphaTemp; \ 125 d[2] = (_p.data8[2] * alphaDest + (r) * alphaSrc) / alphaTemp; \ 126 d[3] = alphaTemp / 255; \ 127 } \ 128 } \ 129 } 130 131 // BLEND_COMPOSITE_SUBPIX 132 #define BLEND_COMPOSITE_SUBPIX(d, r, g, b, a1, a2, a3) \ 133 { \ 134 pixel32 _p; \ 135 _p.data32 = *(uint32*)d; \ 136 if (_p.data8[3] == 255) { \ 137 d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \ 138 d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \ 139 d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \ 140 d[3] = 255; \ 141 } else { \ 142 if (_p.data8[3] == 0) { \ 143 d[0] = (b); \ 144 d[1] = (g); \ 145 d[2] = (r); \ 146 d[3] = (a1 + a2 + a3)/3; \ 147 } else { \ 148 uint8 alphaRest1 = 255 - (a1); \ 149 uint8 alphaRest2 = 255 - (a2); \ 150 uint8 alphaRest3 = 255 - (a3); \ 151 uint32 alphaTemp1 = (65025 - alphaRest1 * (255 - _p.data8[3])); \ 152 uint32 alphaTemp2 = (65025 - alphaRest2 * (255 - _p.data8[3])); \ 153 uint32 alphaTemp3 = (65025 - alphaRest3 * (255 - _p.data8[3])); \ 154 uint32 alphaDest1 = _p.data8[3] * alphaRest1; \ 155 uint32 alphaDest2 = _p.data8[3] * alphaRest2; \ 156 uint32 alphaDest3 = _p.data8[3] * alphaRest3; \ 157 uint32 alphaSrc1 = 255 * (a1); \ 158 uint32 alphaSrc2 = 255 * (a2); \ 159 uint32 alphaSrc3 = 255 * (a3); \ 160 d[0] = (_p.data8[0] * alphaDest1 + (b) * alphaSrc1) / alphaTemp1; \ 161 d[1] = (_p.data8[1] * alphaDest2 + (g) * alphaSrc2) / alphaTemp2; \ 162 d[2] = (_p.data8[2] * alphaDest3 + (r) * alphaSrc3) / alphaTemp3; \ 163 d[3] = (alphaTemp1 + alphaTemp2 + alphaTemp3)/765; \ 164 } \ 165 } \ 166 } 167 168 // BLEND_COMPOSITE16 169 // 170 // This macro assumes source alpha in range 0..65025 and 171 // composes the source color over a possibly semi-transparent background. 172 // TODO: implement a faster version 173 #define BLEND_COMPOSITE16(d, r, g, b, a) \ 174 { \ 175 uint16 _a = (a) / 255; \ 176 BLEND_COMPOSITE(d, r, g, b, _a); \ 177 } 178 179 // BLEND_COMPOSITE16_SUBPIX 180 #define BLEND_COMPOSITE16_SUBPIX(d, r, g, b, a1, a2, a3) \ 181 { \ 182 uint16 _a1 = (a1) / 255; \ 183 uint16 _a2 = (a2) / 255; \ 184 uint16 _a3 = (a3) / 255; \ 185 BLEND_COMPOSITE_SUBPIX(d, r, g, b, _a1, _a2, _a3); \ 186 } 187 188 static inline 189 uint8 190 brightness_for(uint8 red, uint8 green, uint8 blue) 191 { 192 // brightness = 0.301 * red + 0.586 * green + 0.113 * blue 193 // we use for performance reasons: 194 // brightness = (308 * red + 600 * green + 116 * blue) / 1024 195 return uint8((308 * red + 600 * green + 116 * blue) / 1024); 196 } 197 198 #endif // DRAWING_MODE_H 199 200