1 | /**************************************************************************** |
2 | * |
3 | * ftrend1.c |
4 | * |
5 | * The FreeType glyph rasterizer interface (body). |
6 | * |
7 | * Copyright (C) 1996-2019 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 | |
18 | |
19 | #include <ft2build.h> |
20 | #include FT_INTERNAL_DEBUG_H |
21 | #include FT_INTERNAL_OBJECTS_H |
22 | #include FT_OUTLINE_H |
23 | #include "ftrend1.h" |
24 | #include "ftraster.h" |
25 | |
26 | #include "rasterrs.h" |
27 | |
28 | |
29 | /* initialize renderer -- init its raster */ |
30 | static FT_Error |
31 | ft_raster1_init( FT_Renderer render ) |
32 | { |
33 | render->clazz->raster_class->raster_reset( render->raster, NULL, 0 ); |
34 | |
35 | return FT_Err_Ok; |
36 | } |
37 | |
38 | |
39 | /* set render-specific mode */ |
40 | static FT_Error |
41 | ft_raster1_set_mode( FT_Renderer render, |
42 | FT_ULong mode_tag, |
43 | FT_Pointer data ) |
44 | { |
45 | /* we simply pass it to the raster */ |
46 | return render->clazz->raster_class->raster_set_mode( render->raster, |
47 | mode_tag, |
48 | data ); |
49 | } |
50 | |
51 | |
52 | /* transform a given glyph image */ |
53 | static FT_Error |
54 | ft_raster1_transform( FT_Renderer render, |
55 | FT_GlyphSlot slot, |
56 | const FT_Matrix* matrix, |
57 | const FT_Vector* delta ) |
58 | { |
59 | FT_Error error = FT_Err_Ok; |
60 | |
61 | |
62 | if ( slot->format != render->glyph_format ) |
63 | { |
64 | error = FT_THROW( Invalid_Argument ); |
65 | goto Exit; |
66 | } |
67 | |
68 | if ( matrix ) |
69 | FT_Outline_Transform( &slot->outline, matrix ); |
70 | |
71 | if ( delta ) |
72 | FT_Outline_Translate( &slot->outline, delta->x, delta->y ); |
73 | |
74 | Exit: |
75 | return error; |
76 | } |
77 | |
78 | |
79 | /* return the glyph's control box */ |
80 | static void |
81 | ft_raster1_get_cbox( FT_Renderer render, |
82 | FT_GlyphSlot slot, |
83 | FT_BBox* cbox ) |
84 | { |
85 | FT_ZERO( cbox ); |
86 | |
87 | if ( slot->format == render->glyph_format ) |
88 | FT_Outline_Get_CBox( &slot->outline, cbox ); |
89 | } |
90 | |
91 | |
92 | /* convert a slot's glyph image into a bitmap */ |
93 | static FT_Error |
94 | ft_raster1_render( FT_Renderer render, |
95 | FT_GlyphSlot slot, |
96 | FT_Render_Mode mode, |
97 | const FT_Vector* origin ) |
98 | { |
99 | FT_Error error = FT_Err_Ok; |
100 | FT_Outline* outline = &slot->outline; |
101 | FT_Bitmap* bitmap = &slot->bitmap; |
102 | FT_Memory memory = render->root.memory; |
103 | FT_Pos x_shift = 0; |
104 | FT_Pos y_shift = 0; |
105 | |
106 | FT_Raster_Params params; |
107 | |
108 | |
109 | /* check glyph image format */ |
110 | if ( slot->format != render->glyph_format ) |
111 | { |
112 | error = FT_THROW( Invalid_Argument ); |
113 | goto Exit; |
114 | } |
115 | |
116 | /* check rendering mode */ |
117 | if ( mode != FT_RENDER_MODE_MONO ) |
118 | { |
119 | /* raster1 is only capable of producing monochrome bitmaps */ |
120 | return FT_THROW( Cannot_Render_Glyph ); |
121 | } |
122 | |
123 | /* release old bitmap buffer */ |
124 | if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) |
125 | { |
126 | FT_FREE( bitmap->buffer ); |
127 | slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; |
128 | } |
129 | |
130 | if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) ) |
131 | { |
132 | error = FT_THROW( Raster_Overflow ); |
133 | goto Exit; |
134 | } |
135 | |
136 | /* allocate new one */ |
137 | if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) ) |
138 | goto Exit; |
139 | |
140 | slot->internal->flags |= FT_GLYPH_OWN_BITMAP; |
141 | |
142 | x_shift = -slot->bitmap_left * 64; |
143 | y_shift = ( (FT_Int)bitmap->rows - slot->bitmap_top ) * 64; |
144 | |
145 | if ( origin ) |
146 | { |
147 | x_shift += origin->x; |
148 | y_shift += origin->y; |
149 | } |
150 | |
151 | /* translate outline to render it into the bitmap */ |
152 | if ( x_shift || y_shift ) |
153 | FT_Outline_Translate( outline, x_shift, y_shift ); |
154 | |
155 | /* set up parameters */ |
156 | params.target = bitmap; |
157 | params.source = outline; |
158 | params.flags = FT_RASTER_FLAG_DEFAULT; |
159 | |
160 | /* render outline into the bitmap */ |
161 | error = render->raster_render( render->raster, ¶ms ); |
162 | |
163 | Exit: |
164 | if ( !error ) |
165 | /* everything is fine; the glyph is now officially a bitmap */ |
166 | slot->format = FT_GLYPH_FORMAT_BITMAP; |
167 | else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) |
168 | { |
169 | FT_FREE( bitmap->buffer ); |
170 | slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; |
171 | } |
172 | |
173 | if ( x_shift || y_shift ) |
174 | FT_Outline_Translate( outline, -x_shift, -y_shift ); |
175 | |
176 | return error; |
177 | } |
178 | |
179 | |
180 | FT_DEFINE_RENDERER( |
181 | ft_raster1_renderer_class, |
182 | |
183 | FT_MODULE_RENDERER, |
184 | sizeof ( FT_RendererRec ), |
185 | |
186 | "raster1" , |
187 | 0x10000L, |
188 | 0x20000L, |
189 | |
190 | NULL, /* module specific interface */ |
191 | |
192 | (FT_Module_Constructor)ft_raster1_init, /* module_init */ |
193 | (FT_Module_Destructor) NULL, /* module_done */ |
194 | (FT_Module_Requester) NULL, /* get_interface */ |
195 | |
196 | FT_GLYPH_FORMAT_OUTLINE, |
197 | |
198 | (FT_Renderer_RenderFunc) ft_raster1_render, /* render_glyph */ |
199 | (FT_Renderer_TransformFunc)ft_raster1_transform, /* transform_glyph */ |
200 | (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, /* get_glyph_cbox */ |
201 | (FT_Renderer_SetModeFunc) ft_raster1_set_mode, /* set_mode */ |
202 | |
203 | (FT_Raster_Funcs*)&ft_standard_raster /* raster_class */ |
204 | ) |
205 | |
206 | |
207 | /* END */ |
208 | |