Basic FreeType renderer implementation.
[gdipp.git] / gdipp_server / helper.cpp
blob36b2956901af145f6cb399e69f50cf0f60d9b481
1 #include "stdafx.h"
2 #include "helper.h"
4 namespace gdipp
7 FIXED fixed_from_26dot6(signed long x)
9 signed long y = (x << 10);
10 return *(reinterpret_cast<FIXED *>(&y));
13 signed long fixed_to_26dot6(const FIXED &x)
15 return *(reinterpret_cast<const signed long *>(&x)) >> 10;
18 signed long float_to_16dot16(double x)
20 return static_cast<FT_Pos>(x * 65536);
23 LONG int_from_16dot16(signed long x)
25 const LONG ret = (x >> 16);
27 if (ret == 0 && x > 0)
28 return 1;
29 else
30 return ret;
33 LONG int_from_26dot6(signed long x)
35 const LONG ret = (x >> 6);
37 if (ret == 0 && x > 0)
38 return 1;
39 else
40 return ret;
43 DWORD create_tls_index()
45 DWORD new_tls_index = TlsAlloc();
46 assert(new_tls_index != TLS_OUT_OF_INDEXES);
48 return new_tls_index;
51 BOOL free_tls_index(DWORD tls_index)
53 return TlsFree(tls_index);
56 BYTE division_by_255(short number, short numerator)
58 // there are many approaches to approximate number * numerator / 255
59 // it is a trade-off between efficiency and accuracy
61 const int t = number * numerator;
62 return (((t + 255) >> 8) + t) >> 8;
65 uint128_t generate_render_trait(const LOGFONTW *logfont, int render_mode)
67 // the LOGFONTW structure and render mode are the minimal set that uniquely determine font metrics used by any renderer
69 // exclude the bytes after the face name, which may contain junk data
70 const int lf_metric_size = sizeof(LOGFONTW) - sizeof(logfont->lfFaceName);
71 const int lf_facename_size = static_cast<const int>((wcslen(logfont->lfFaceName) * sizeof(wchar_t)));
72 const int lf_total_size = lf_metric_size + lf_facename_size;
74 uint128_t render_trait;
75 #ifdef _M_X64
76 MurmurHash3_x64_128(logfont, lf_total_size, render_mode, &render_trait);
77 #else
78 MurmurHash3_x86_128(logfont, lf_total_size, render_mode, &render_trait);
79 #endif
80 return render_trait;
83 POINT get_baseline(UINT alignment, int x, int y, int width, int ascent, int descent)
85 POINT baseline = {x, y};
87 switch ((TA_LEFT | TA_RIGHT | TA_CENTER) & alignment)
89 case TA_LEFT:
90 break;
91 case TA_RIGHT:
92 baseline.x -= width;
93 break;
94 case TA_CENTER:
95 baseline.x -= width / 2;
96 break;
99 switch ((TA_TOP | TA_BOTTOM | TA_BASELINE) & alignment)
101 case TA_TOP:
102 baseline.y += ascent;
103 break;
104 case TA_BOTTOM:
105 baseline.y -= descent;
106 break;
107 case TA_BASELINE:
108 break;
111 return baseline;
114 int get_bmp_pitch(int width, WORD bpp)
116 #define FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) )
117 #define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n )
118 #define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n )
120 return FT_PAD_CEIL(static_cast<int>(ceil(static_cast<double>(width * bpp) / 8)), sizeof(LONG));
123 bool get_dc_bmp_header(HDC hdc, BITMAPINFOHEADER &dc_bmp_header)
125 dc_bmp_header.biSize = sizeof(BITMAPINFOHEADER);
127 const HBITMAP dc_bitmap = static_cast<const HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
128 if (dc_bitmap == NULL)
130 // currently no selected bitmap
131 // use DC capability
133 dc_bmp_header.biWidth = GetDeviceCaps(hdc, HORZRES);
134 dc_bmp_header.biHeight = GetDeviceCaps(hdc, VERTRES);
135 dc_bmp_header.biPlanes = GetDeviceCaps(hdc, PLANES);
136 dc_bmp_header.biBitCount = GetDeviceCaps(hdc, BITSPIXEL);
138 return false;
140 else
142 // do not return the color table
143 dc_bmp_header.biBitCount = 0;
144 const int i_ret = GetDIBits(hdc, dc_bitmap, 0, 0, NULL, reinterpret_cast<LPBITMAPINFO>(&dc_bmp_header), DIB_RGB_COLORS);
145 assert(i_ret != 0);
147 return true;
151 OUTLINETEXTMETRICW *get_dc_metrics(HDC hdc, std::vector<BYTE> &metric_buf)
153 // get outline metrics of the DC, which also include the text metrics
155 UINT metric_size = GetOutlineTextMetricsW(hdc, 0, NULL);
156 if (metric_size == 0)
157 return NULL;
159 metric_buf.resize(metric_size);
160 OUTLINETEXTMETRICW *outline_metrics = reinterpret_cast<OUTLINETEXTMETRICW *>(&metric_buf[0]);
161 metric_size = GetOutlineTextMetricsW(hdc, metric_size, outline_metrics);
162 assert(metric_size != 0);
164 return outline_metrics;
167 int get_glyph_bmp_width(const FT_Bitmap &bitmap)
169 if (bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
170 return bitmap.width / 3;
171 else
172 return bitmap.width;
175 /*LONG get_glyph_run_width(const glyph_run *a_glyph_run, bool is_control_width)
177 assert(a_glyph_run != NULL);
179 std::list<RECT>::const_iterator first_box_iter;
180 std::list<RECT>::const_reverse_iterator last_box_iter;
182 if (is_control_width)
184 // use control box metrics
185 first_box_iter = a_glyph_run->ctrl_boxes.begin();
186 last_box_iter = a_glyph_run->ctrl_boxes.rbegin();
188 else
190 // use black box metrics
191 first_box_iter = a_glyph_run->black_boxes.begin();
192 last_box_iter = a_glyph_run->black_boxes.rbegin();
195 if (a_glyph_run->ctrl_boxes.back().left >= a_glyph_run->ctrl_boxes.front().left)
196 return last_box_iter->right - first_box_iter->left;
197 else
198 return first_box_iter->right - last_box_iter->left;
201 LOGFONTW get_log_font(HDC hdc)
203 HFONT h_font = reinterpret_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
204 assert(h_font != NULL);
206 LOGFONTW font_attr;
207 GetObject(h_font, sizeof(LOGFONTW), &font_attr);
209 return font_attr;
212 bool get_render_mode(const render_config_static::render_mode_static &render_mode_conf, WORD dc_bmp_bpp, BYTE font_quality, FT_Render_Mode *render_mode)
214 // return true if successfully find an appropriate render mode
215 // otherwise return false
217 if (render_mode_conf.mono == 2)
219 *render_mode = FT_RENDER_MODE_MONO;
220 return true;
223 if (render_mode_conf.gray == 2)
225 *render_mode = FT_RENDER_MODE_NORMAL;
226 return true;
229 if (render_mode_conf.subpixel == 2)
231 *render_mode = FT_RENDER_MODE_LCD;
232 return true;
235 if (!render_mode_conf.aliased && font_quality == NONANTIALIASED_QUALITY)
236 return false;
238 if (render_mode_conf.mono == 1 && dc_bmp_bpp == 1)
240 *render_mode = FT_RENDER_MODE_MONO;
241 return true;
244 if (render_mode_conf.gray == 1 && dc_bmp_bpp == 8)
246 *render_mode = FT_RENDER_MODE_NORMAL;
247 return true;
250 // we do not support 16 bpp currently
252 if (render_mode_conf.subpixel == 1 && dc_bmp_bpp >= 24)
254 *render_mode = FT_RENDER_MODE_LCD;
255 return true;
258 return false;
261 bool operator<(const LOGFONTW &lf1, const LOGFONTW &lf2)
263 return memcmp(&lf1, &lf2, sizeof(LOGFONTW)) < 0;
266 bool mb_to_wc(const char *multi_byte_str, int count, std::wstring &wide_char_str)
268 int wc_str_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, multi_byte_str, count, NULL, 0);
269 if (wc_str_len == 0)
270 return false;
272 wide_char_str.resize(wc_str_len);
273 wc_str_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, multi_byte_str, count, &wide_char_str[0], wc_str_len);
274 if (wc_str_len == 0)
275 return false;
277 return true;
280 BOOL paint_background(HDC hdc, const RECT *bg_rect, COLORREF bg_color)
282 int i_ret;
284 if (bg_color == CLR_INVALID)
285 return FALSE;
287 const HBRUSH bg_brush = CreateSolidBrush(bg_color);
288 if (bg_brush == NULL)
289 return FALSE;
291 i_ret = FillRect(hdc, bg_rect, bg_brush);
292 if (i_ret == 0)
293 return FALSE;
295 DeleteObject(bg_brush);
296 return TRUE;