/src/freetype/src/base/ftlcdfil.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 376 lines · 257 code · 94 blank · 25 comment · 26 complexity · 7765a542213f0e13ac0d77b0fe051402 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ftlcdfil.c */
  4. /* */
  5. /* FreeType API for color filtering of subpixel bitmap glyphs (body). */
  6. /* */
  7. /* Copyright 2006, 2008, 2009, 2010 by */
  8. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  9. /* */
  10. /* This file is part of the FreeType project, and may only be used, */
  11. /* modified, and distributed under the terms of the FreeType project */
  12. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  13. /* this file you indicate that you have read the license and */
  14. /* understand and accept it fully. */
  15. /* */
  16. /***************************************************************************/
  17. #include <ft2build.h>
  18. #include FT_LCD_FILTER_H
  19. #include FT_IMAGE_H
  20. #include FT_INTERNAL_OBJECTS_H
  21. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  22. /* define USE_LEGACY to implement the legacy filter */
  23. #define USE_LEGACY
  24. /* FIR filter used by the default and light filters */
  25. static void
  26. _ft_lcd_filter_fir( FT_Bitmap* bitmap,
  27. FT_Render_Mode mode,
  28. FT_Library library )
  29. {
  30. FT_Byte* weights = library->lcd_weights;
  31. FT_UInt width = (FT_UInt)bitmap->width;
  32. FT_UInt height = (FT_UInt)bitmap->rows;
  33. /* horizontal in-place FIR filter */
  34. if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
  35. {
  36. FT_Byte* line = bitmap->buffer;
  37. for ( ; height > 0; height--, line += bitmap->pitch )
  38. {
  39. FT_UInt fir[5];
  40. FT_UInt val1, xx;
  41. val1 = line[0];
  42. fir[0] = weights[2] * val1;
  43. fir[1] = weights[3] * val1;
  44. fir[2] = weights[4] * val1;
  45. fir[3] = 0;
  46. fir[4] = 0;
  47. val1 = line[1];
  48. fir[0] += weights[1] * val1;
  49. fir[1] += weights[2] * val1;
  50. fir[2] += weights[3] * val1;
  51. fir[3] += weights[4] * val1;
  52. for ( xx = 2; xx < width; xx++ )
  53. {
  54. FT_UInt val, pix;
  55. val = line[xx];
  56. pix = fir[0] + weights[0] * val;
  57. fir[0] = fir[1] + weights[1] * val;
  58. fir[1] = fir[2] + weights[2] * val;
  59. fir[2] = fir[3] + weights[3] * val;
  60. fir[3] = weights[4] * val;
  61. pix >>= 8;
  62. pix |= -( pix >> 8 );
  63. line[xx - 2] = (FT_Byte)pix;
  64. }
  65. {
  66. FT_UInt pix;
  67. pix = fir[0] >> 8;
  68. pix |= -( pix >> 8 );
  69. line[xx - 2] = (FT_Byte)pix;
  70. pix = fir[1] >> 8;
  71. pix |= -( pix >> 8 );
  72. line[xx - 1] = (FT_Byte)pix;
  73. }
  74. }
  75. }
  76. /* vertical in-place FIR filter */
  77. else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
  78. {
  79. FT_Byte* column = bitmap->buffer;
  80. FT_Int pitch = bitmap->pitch;
  81. for ( ; width > 0; width--, column++ )
  82. {
  83. FT_Byte* col = column;
  84. FT_UInt fir[5];
  85. FT_UInt val1, yy;
  86. val1 = col[0];
  87. fir[0] = weights[2] * val1;
  88. fir[1] = weights[3] * val1;
  89. fir[2] = weights[4] * val1;
  90. fir[3] = 0;
  91. fir[4] = 0;
  92. col += pitch;
  93. val1 = col[0];
  94. fir[0] += weights[1] * val1;
  95. fir[1] += weights[2] * val1;
  96. fir[2] += weights[3] * val1;
  97. fir[3] += weights[4] * val1;
  98. col += pitch;
  99. for ( yy = 2; yy < height; yy++ )
  100. {
  101. FT_UInt val, pix;
  102. val = col[0];
  103. pix = fir[0] + weights[0] * val;
  104. fir[0] = fir[1] + weights[1] * val;
  105. fir[1] = fir[2] + weights[2] * val;
  106. fir[2] = fir[3] + weights[3] * val;
  107. fir[3] = weights[4] * val;
  108. pix >>= 8;
  109. pix |= -( pix >> 8 );
  110. col[-2 * pitch] = (FT_Byte)pix;
  111. col += pitch;
  112. }
  113. {
  114. FT_UInt pix;
  115. pix = fir[0] >> 8;
  116. pix |= -( pix >> 8 );
  117. col[-2 * pitch] = (FT_Byte)pix;
  118. pix = fir[1] >> 8;
  119. pix |= -( pix >> 8 );
  120. col[-pitch] = (FT_Byte)pix;
  121. }
  122. }
  123. }
  124. }
  125. #ifdef USE_LEGACY
  126. /* intra-pixel filter used by the legacy filter */
  127. static void
  128. _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
  129. FT_Render_Mode mode,
  130. FT_Library library )
  131. {
  132. FT_UInt width = (FT_UInt)bitmap->width;
  133. FT_UInt height = (FT_UInt)bitmap->rows;
  134. FT_Int pitch = bitmap->pitch;
  135. static const int filters[3][3] =
  136. {
  137. { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 },
  138. { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 },
  139. { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
  140. };
  141. FT_UNUSED( library );
  142. /* horizontal in-place intra-pixel filter */
  143. if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
  144. {
  145. FT_Byte* line = bitmap->buffer;
  146. for ( ; height > 0; height--, line += pitch )
  147. {
  148. FT_UInt xx;
  149. for ( xx = 0; xx < width; xx += 3 )
  150. {
  151. FT_UInt r = 0;
  152. FT_UInt g = 0;
  153. FT_UInt b = 0;
  154. FT_UInt p;
  155. p = line[xx];
  156. r += filters[0][0] * p;
  157. g += filters[0][1] * p;
  158. b += filters[0][2] * p;
  159. p = line[xx + 1];
  160. r += filters[1][0] * p;
  161. g += filters[1][1] * p;
  162. b += filters[1][2] * p;
  163. p = line[xx + 2];
  164. r += filters[2][0] * p;
  165. g += filters[2][1] * p;
  166. b += filters[2][2] * p;
  167. line[xx] = (FT_Byte)( r / 65536 );
  168. line[xx + 1] = (FT_Byte)( g / 65536 );
  169. line[xx + 2] = (FT_Byte)( b / 65536 );
  170. }
  171. }
  172. }
  173. else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
  174. {
  175. FT_Byte* column = bitmap->buffer;
  176. for ( ; width > 0; width--, column++ )
  177. {
  178. FT_Byte* col = column;
  179. FT_Byte* col_end = col + height * pitch;
  180. for ( ; col < col_end; col += 3 * pitch )
  181. {
  182. FT_UInt r = 0;
  183. FT_UInt g = 0;
  184. FT_UInt b = 0;
  185. FT_UInt p;
  186. p = col[0];
  187. r += filters[0][0] * p;
  188. g += filters[0][1] * p;
  189. b += filters[0][2] * p;
  190. p = col[pitch];
  191. r += filters[1][0] * p;
  192. g += filters[1][1] * p;
  193. b += filters[1][2] * p;
  194. p = col[pitch * 2];
  195. r += filters[2][0] * p;
  196. g += filters[2][1] * p;
  197. b += filters[2][2] * p;
  198. col[0] = (FT_Byte)( r / 65536 );
  199. col[pitch] = (FT_Byte)( g / 65536 );
  200. col[2 * pitch] = (FT_Byte)( b / 65536 );
  201. }
  202. }
  203. }
  204. }
  205. #endif /* USE_LEGACY */
  206. FT_EXPORT_DEF( FT_Error )
  207. FT_Library_SetLcdFilterWeights( FT_Library library,
  208. unsigned char *weights )
  209. {
  210. if ( !library || !weights )
  211. return FT_Err_Invalid_Argument;
  212. ft_memcpy( library->lcd_weights, weights, 5 );
  213. return FT_Err_Ok;
  214. }
  215. FT_EXPORT_DEF( FT_Error )
  216. FT_Library_SetLcdFilter( FT_Library library,
  217. FT_LcdFilter filter )
  218. {
  219. static const FT_Byte light_filter[5] =
  220. { 0x00, 0x55, 0x56, 0x55, 0x00 };
  221. /* the values here sum up to a value larger than 256, */
  222. /* providing a cheap gamma correction */
  223. static const FT_Byte default_filter[5] =
  224. { 0x10, 0x40, 0x70, 0x40, 0x10 };
  225. if ( !library )
  226. return FT_Err_Invalid_Argument;
  227. switch ( filter )
  228. {
  229. case FT_LCD_FILTER_NONE:
  230. library->lcd_filter_func = NULL;
  231. library->lcd_extra = 0;
  232. break;
  233. case FT_LCD_FILTER_DEFAULT:
  234. #if defined( FT_FORCE_LEGACY_LCD_FILTER )
  235. library->lcd_filter_func = _ft_lcd_filter_legacy;
  236. library->lcd_extra = 0;
  237. #elif defined( FT_FORCE_LIGHT_LCD_FILTER )
  238. ft_memcpy( library->lcd_weights, light_filter, 5 );
  239. library->lcd_filter_func = _ft_lcd_filter_fir;
  240. library->lcd_extra = 2;
  241. #else
  242. ft_memcpy( library->lcd_weights, default_filter, 5 );
  243. library->lcd_filter_func = _ft_lcd_filter_fir;
  244. library->lcd_extra = 2;
  245. #endif
  246. break;
  247. case FT_LCD_FILTER_LIGHT:
  248. ft_memcpy( library->lcd_weights, light_filter, 5 );
  249. library->lcd_filter_func = _ft_lcd_filter_fir;
  250. library->lcd_extra = 2;
  251. break;
  252. #ifdef USE_LEGACY
  253. case FT_LCD_FILTER_LEGACY:
  254. library->lcd_filter_func = _ft_lcd_filter_legacy;
  255. library->lcd_extra = 0;
  256. break;
  257. #endif
  258. default:
  259. return FT_Err_Invalid_Argument;
  260. }
  261. library->lcd_filter = filter;
  262. return FT_Err_Ok;
  263. }
  264. #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  265. FT_EXPORT_DEF( FT_Error )
  266. FT_Library_SetLcdFilterWeights( FT_Library library,
  267. unsigned char *weights )
  268. {
  269. FT_UNUSED( library );
  270. FT_UNUSED( weights );
  271. return FT_Err_Unimplemented_Feature;
  272. }
  273. FT_EXPORT_DEF( FT_Error )
  274. FT_Library_SetLcdFilter( FT_Library library,
  275. FT_LcdFilter filter )
  276. {
  277. FT_UNUSED( library );
  278. FT_UNUSED( filter );
  279. return FT_Err_Unimplemented_Feature;
  280. }
  281. #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  282. /* END */