/src/freetype/src/smooth/ftsmooth.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 504 lines · 336 code · 122 blank · 46 comment · 49 complexity · 9da7b26a585d878689b3b33cac362847 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ftsmooth.c */
  4. /* */
  5. /* Anti-aliasing renderer interface (body). */
  6. /* */
  7. /* Copyright 2000-2006, 2009-2012 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_INTERNAL_DEBUG_H
  19. #include FT_INTERNAL_OBJECTS_H
  20. #include FT_OUTLINE_H
  21. #include "ftsmooth.h"
  22. #include "ftgrays.h"
  23. #include "ftspic.h"
  24. #include "ftsmerrs.h"
  25. /* initialize renderer -- init its raster */
  26. static FT_Error
  27. ft_smooth_init( FT_Renderer render )
  28. {
  29. FT_Library library = FT_MODULE_LIBRARY( render );
  30. render->clazz->raster_class->raster_reset( render->raster,
  31. library->raster_pool,
  32. library->raster_pool_size );
  33. return 0;
  34. }
  35. /* sets render-specific mode */
  36. static FT_Error
  37. ft_smooth_set_mode( FT_Renderer render,
  38. FT_ULong mode_tag,
  39. FT_Pointer data )
  40. {
  41. /* we simply pass it to the raster */
  42. return render->clazz->raster_class->raster_set_mode( render->raster,
  43. mode_tag,
  44. data );
  45. }
  46. /* transform a given glyph image */
  47. static FT_Error
  48. ft_smooth_transform( FT_Renderer render,
  49. FT_GlyphSlot slot,
  50. const FT_Matrix* matrix,
  51. const FT_Vector* delta )
  52. {
  53. FT_Error error = Smooth_Err_Ok;
  54. if ( slot->format != render->glyph_format )
  55. {
  56. error = Smooth_Err_Invalid_Argument;
  57. goto Exit;
  58. }
  59. if ( matrix )
  60. FT_Outline_Transform( &slot->outline, matrix );
  61. if ( delta )
  62. FT_Outline_Translate( &slot->outline, delta->x, delta->y );
  63. Exit:
  64. return error;
  65. }
  66. /* return the glyph's control box */
  67. static void
  68. ft_smooth_get_cbox( FT_Renderer render,
  69. FT_GlyphSlot slot,
  70. FT_BBox* cbox )
  71. {
  72. FT_MEM_ZERO( cbox, sizeof ( *cbox ) );
  73. if ( slot->format == render->glyph_format )
  74. FT_Outline_Get_CBox( &slot->outline, cbox );
  75. }
  76. /* convert a slot's glyph image into a bitmap */
  77. static FT_Error
  78. ft_smooth_render_generic( FT_Renderer render,
  79. FT_GlyphSlot slot,
  80. FT_Render_Mode mode,
  81. const FT_Vector* origin,
  82. FT_Render_Mode required_mode )
  83. {
  84. FT_Error error;
  85. FT_Outline* outline = NULL;
  86. FT_BBox cbox;
  87. FT_Pos width, height, pitch;
  88. #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  89. FT_Pos height_org, width_org;
  90. #endif
  91. FT_Bitmap* bitmap;
  92. FT_Memory memory;
  93. FT_Int hmul = mode == FT_RENDER_MODE_LCD;
  94. FT_Int vmul = mode == FT_RENDER_MODE_LCD_V;
  95. FT_Pos x_shift, y_shift, x_left, y_top;
  96. FT_Raster_Params params;
  97. /* check glyph image format */
  98. if ( slot->format != render->glyph_format )
  99. {
  100. error = Smooth_Err_Invalid_Argument;
  101. goto Exit;
  102. }
  103. /* check mode */
  104. if ( mode != required_mode )
  105. return Smooth_Err_Cannot_Render_Glyph;
  106. outline = &slot->outline;
  107. /* translate the outline to the new origin if needed */
  108. if ( origin )
  109. FT_Outline_Translate( outline, origin->x, origin->y );
  110. /* compute the control box, and grid fit it */
  111. FT_Outline_Get_CBox( outline, &cbox );
  112. cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
  113. cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
  114. cbox.xMax = FT_PIX_CEIL( cbox.xMax );
  115. cbox.yMax = FT_PIX_CEIL( cbox.yMax );
  116. if ( cbox.xMin < 0 && cbox.xMax > FT_INT_MAX + cbox.xMin )
  117. {
  118. FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
  119. " xMin = %d, xMax = %d\n",
  120. cbox.xMin >> 6, cbox.xMax >> 6 ));
  121. return Smooth_Err_Raster_Overflow;
  122. }
  123. else
  124. width = ( cbox.xMax - cbox.xMin ) >> 6;
  125. if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
  126. {
  127. FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
  128. " yMin = %d, yMax = %d\n",
  129. cbox.yMin >> 6, cbox.yMax >> 6 ));
  130. return Smooth_Err_Raster_Overflow;
  131. }
  132. else
  133. height = ( cbox.yMax - cbox.yMin ) >> 6;
  134. bitmap = &slot->bitmap;
  135. memory = render->root.memory;
  136. #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  137. width_org = width;
  138. height_org = height;
  139. #endif
  140. /* release old bitmap buffer */
  141. if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  142. {
  143. FT_FREE( bitmap->buffer );
  144. slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  145. }
  146. /* allocate new one */
  147. pitch = width;
  148. if ( hmul )
  149. {
  150. width = width * 3;
  151. pitch = FT_PAD_CEIL( width, 4 );
  152. }
  153. if ( vmul )
  154. height *= 3;
  155. x_shift = (FT_Int) cbox.xMin;
  156. y_shift = (FT_Int) cbox.yMin;
  157. x_left = (FT_Int)( cbox.xMin >> 6 );
  158. y_top = (FT_Int)( cbox.yMax >> 6 );
  159. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  160. if ( slot->library->lcd_filter_func )
  161. {
  162. FT_Int extra = slot->library->lcd_extra;
  163. if ( hmul )
  164. {
  165. x_shift -= 64 * ( extra >> 1 );
  166. width += 3 * extra;
  167. pitch = FT_PAD_CEIL( width, 4 );
  168. x_left -= extra >> 1;
  169. }
  170. if ( vmul )
  171. {
  172. y_shift -= 64 * ( extra >> 1 );
  173. height += 3 * extra;
  174. y_top += extra >> 1;
  175. }
  176. }
  177. #endif
  178. #if FT_UINT_MAX > 0xFFFFU
  179. /* Required check is ( pitch * height < FT_ULONG_MAX ), */
  180. /* but we care realistic cases only. Always pitch <= width. */
  181. if ( width > 0x7FFF || height > 0x7FFF )
  182. {
  183. FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
  184. width, height ));
  185. return Smooth_Err_Raster_Overflow;
  186. }
  187. #endif
  188. bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
  189. bitmap->num_grays = 256;
  190. bitmap->width = width;
  191. bitmap->rows = height;
  192. bitmap->pitch = pitch;
  193. /* translate outline to render it into the bitmap */
  194. FT_Outline_Translate( outline, -x_shift, -y_shift );
  195. if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
  196. goto Exit;
  197. slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
  198. /* set up parameters */
  199. params.target = bitmap;
  200. params.source = outline;
  201. params.flags = FT_RASTER_FLAG_AA;
  202. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  203. /* implode outline if needed */
  204. {
  205. FT_Vector* points = outline->points;
  206. FT_Vector* points_end = points + outline->n_points;
  207. FT_Vector* vec;
  208. if ( hmul )
  209. for ( vec = points; vec < points_end; vec++ )
  210. vec->x *= 3;
  211. if ( vmul )
  212. for ( vec = points; vec < points_end; vec++ )
  213. vec->y *= 3;
  214. }
  215. /* render outline into the bitmap */
  216. error = render->raster_render( render->raster, &params );
  217. /* deflate outline if needed */
  218. {
  219. FT_Vector* points = outline->points;
  220. FT_Vector* points_end = points + outline->n_points;
  221. FT_Vector* vec;
  222. if ( hmul )
  223. for ( vec = points; vec < points_end; vec++ )
  224. vec->x /= 3;
  225. if ( vmul )
  226. for ( vec = points; vec < points_end; vec++ )
  227. vec->y /= 3;
  228. }
  229. if ( slot->library->lcd_filter_func )
  230. slot->library->lcd_filter_func( bitmap, mode, slot->library );
  231. #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  232. /* render outline into bitmap */
  233. error = render->raster_render( render->raster, &params );
  234. /* expand it horizontally */
  235. if ( hmul )
  236. {
  237. FT_Byte* line = bitmap->buffer;
  238. FT_UInt hh;
  239. for ( hh = height_org; hh > 0; hh--, line += pitch )
  240. {
  241. FT_UInt xx;
  242. FT_Byte* end = line + width;
  243. for ( xx = width_org; xx > 0; xx-- )
  244. {
  245. FT_UInt pixel = line[xx-1];
  246. end[-3] = (FT_Byte)pixel;
  247. end[-2] = (FT_Byte)pixel;
  248. end[-1] = (FT_Byte)pixel;
  249. end -= 3;
  250. }
  251. }
  252. }
  253. /* expand it vertically */
  254. if ( vmul )
  255. {
  256. FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
  257. FT_Byte* write = bitmap->buffer;
  258. FT_UInt hh;
  259. for ( hh = height_org; hh > 0; hh-- )
  260. {
  261. ft_memcpy( write, read, pitch );
  262. write += pitch;
  263. ft_memcpy( write, read, pitch );
  264. write += pitch;
  265. ft_memcpy( write, read, pitch );
  266. write += pitch;
  267. read += pitch;
  268. }
  269. }
  270. #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  271. FT_Outline_Translate( outline, x_shift, y_shift );
  272. /*
  273. * XXX: on 16bit system, we return an error for huge bitmap
  274. * to prevent an overflow.
  275. */
  276. if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
  277. return Smooth_Err_Invalid_Pixel_Size;
  278. if ( error )
  279. goto Exit;
  280. slot->format = FT_GLYPH_FORMAT_BITMAP;
  281. slot->bitmap_left = (FT_Int)x_left;
  282. slot->bitmap_top = (FT_Int)y_top;
  283. Exit:
  284. if ( outline && origin )
  285. FT_Outline_Translate( outline, -origin->x, -origin->y );
  286. return error;
  287. }
  288. /* convert a slot's glyph image into a bitmap */
  289. static FT_Error
  290. ft_smooth_render( FT_Renderer render,
  291. FT_GlyphSlot slot,
  292. FT_Render_Mode mode,
  293. const FT_Vector* origin )
  294. {
  295. if ( mode == FT_RENDER_MODE_LIGHT )
  296. mode = FT_RENDER_MODE_NORMAL;
  297. return ft_smooth_render_generic( render, slot, mode, origin,
  298. FT_RENDER_MODE_NORMAL );
  299. }
  300. /* convert a slot's glyph image into a horizontal LCD bitmap */
  301. static FT_Error
  302. ft_smooth_render_lcd( FT_Renderer render,
  303. FT_GlyphSlot slot,
  304. FT_Render_Mode mode,
  305. const FT_Vector* origin )
  306. {
  307. FT_Error error;
  308. error = ft_smooth_render_generic( render, slot, mode, origin,
  309. FT_RENDER_MODE_LCD );
  310. if ( !error )
  311. slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
  312. return error;
  313. }
  314. /* convert a slot's glyph image into a vertical LCD bitmap */
  315. static FT_Error
  316. ft_smooth_render_lcd_v( FT_Renderer render,
  317. FT_GlyphSlot slot,
  318. FT_Render_Mode mode,
  319. const FT_Vector* origin )
  320. {
  321. FT_Error error;
  322. error = ft_smooth_render_generic( render, slot, mode, origin,
  323. FT_RENDER_MODE_LCD_V );
  324. if ( !error )
  325. slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
  326. return error;
  327. }
  328. FT_DEFINE_RENDERER( ft_smooth_renderer_class,
  329. FT_MODULE_RENDERER,
  330. sizeof ( FT_RendererRec ),
  331. "smooth",
  332. 0x10000L,
  333. 0x20000L,
  334. 0, /* module specific interface */
  335. (FT_Module_Constructor)ft_smooth_init,
  336. (FT_Module_Destructor) 0,
  337. (FT_Module_Requester) 0
  338. ,
  339. FT_GLYPH_FORMAT_OUTLINE,
  340. (FT_Renderer_RenderFunc) ft_smooth_render,
  341. (FT_Renderer_TransformFunc)ft_smooth_transform,
  342. (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
  343. (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
  344. (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
  345. )
  346. FT_DEFINE_RENDERER( ft_smooth_lcd_renderer_class,
  347. FT_MODULE_RENDERER,
  348. sizeof ( FT_RendererRec ),
  349. "smooth-lcd",
  350. 0x10000L,
  351. 0x20000L,
  352. 0, /* module specific interface */
  353. (FT_Module_Constructor)ft_smooth_init,
  354. (FT_Module_Destructor) 0,
  355. (FT_Module_Requester) 0
  356. ,
  357. FT_GLYPH_FORMAT_OUTLINE,
  358. (FT_Renderer_RenderFunc) ft_smooth_render_lcd,
  359. (FT_Renderer_TransformFunc)ft_smooth_transform,
  360. (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
  361. (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
  362. (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
  363. )
  364. FT_DEFINE_RENDERER( ft_smooth_lcdv_renderer_class,
  365. FT_MODULE_RENDERER,
  366. sizeof ( FT_RendererRec ),
  367. "smooth-lcdv",
  368. 0x10000L,
  369. 0x20000L,
  370. 0, /* module specific interface */
  371. (FT_Module_Constructor)ft_smooth_init,
  372. (FT_Module_Destructor) 0,
  373. (FT_Module_Requester) 0
  374. ,
  375. FT_GLYPH_FORMAT_OUTLINE,
  376. (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v,
  377. (FT_Renderer_TransformFunc)ft_smooth_transform,
  378. (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox,
  379. (FT_Renderer_SetModeFunc) ft_smooth_set_mode,
  380. (FT_Raster_Funcs*) &FT_GRAYS_RASTER_GET
  381. )
  382. /* END */