static SCRIPT_STRING_ANALYSIS analyze(HDC hdc, char *utf8, int utf8Length) { SCRIPT_STRING_ANALYSIS ssa = NULL; SCRIPT_CONTROL scriptControl = {0}; SCRIPT_STATE scriptState = {0}; if (utf8Length == 0) return NULL; g_wLength = MultiByteToWideChar( CP_UTF8, 0, utf8, utf8Length, g_wStr, sizeof(g_wStr) / sizeof(WCHAR)); if (g_wLength < 1) return NULL; if (g_font == NULL) unicodeSetFont("", 12, 0, 0, 0); if (g_font != NULL) SelectObject(hdc, g_font); ScriptStringAnalyse( hdc, g_wStr, g_wLength, (2 * g_wLength) + 16, -1, // Unicode string SSA_GLYPHS | SSA_FALLBACK, 0, // no clipping &scriptControl, &scriptState, 0, 0, 0, &ssa); return ssa; }
//TODO: Double check/ensure this function is only called via the gui thread.. SIZE ProjectTreeItem::GetPreferredSize() { SIZE sz = defaultSize; if(!m_size.cx) { m_size.cy = defaultSize.cy; HDC dc = GetDC(m_parentHwnd); if(dc) { HGDIOBJ oldFont = SelectObject(dc, s_hFont); SetTextAlign(dc, TA_LEFT); loadngo::gui::NativeString title(m_pTask->GetTitle()); const TCHAR *pTitle = title; long strLen = _tcslen(pTitle); SCRIPT_STRING_ANALYSIS ssa; SecureZeroMemory(&ssa, sizeof(SCRIPT_STRING_ANALYSIS)); HRESULT hr = ScriptStringAnalyse(dc, pTitle, strLen, 0, -1, SSA_GLYPHS, 0, 0, 0, 0, 0, 0, &ssa); if(SUCCEEDED(hr)) { sz.cx = ScriptString_pSize(ssa)->cx + 20; ScriptStringFree(&ssa); m_size.cx = sz.cx > defaultSize.cx? sz.cx: defaultSize.cx; } SelectObject(dc, oldFont); ReleaseDC(m_parentHwnd, dc); } } return m_size.cx? m_size: sz; }
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; WCHAR sometext[] = {'C','h','i','n','a','1','2','3',0}; int len = (sizeof(sometext) / sizeof(WCHAR)) - 1; RECT rc = {0, 0, 100, 100}; SCRIPT_STRING_ANALYSIS ssa = NULL; HFONT hFont; switch (message) { case WM_CREATE: return 0; case WM_COMMAND: break; case WM_PAINT: BeginPaint(hwnd, &ps); hdc = GetDC(hwnd); hFont = CreateFontA(-32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Hiragino Sans GB W3"); SelectObject(hdc, hFont); ScriptStringAnalyse(hdc, sometext, len, len * 2, -1, SSA_GLYPHS|SSA_FALLBACK, 0, NULL, NULL, NULL, NULL, NULL, &ssa); ScriptStringOut(ssa, 10, 10, 0, &rc, 0, 0, FALSE); EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
/* * This is a hack used by Chrome and WebKit to expose the fallback font used * by Uniscribe for some given text for use with custom shapers / font engines. */ static char *UniscribeFallback( const char *psz_family, uni_char_t codepoint ) { HDC hdc = NULL; HDC meta_file_dc = NULL; HENHMETAFILE meta_file = NULL; LPTSTR psz_fbuffer = NULL; char *psz_result = NULL; hdc = CreateCompatibleDC( NULL ); if( !hdc ) return NULL; meta_file_dc = CreateEnhMetaFile( hdc, NULL, NULL, NULL ); if( !meta_file_dc ) goto error; LOGFONT lf; memset( &lf, 0, sizeof( lf ) ); psz_fbuffer = ToT( psz_family ); if( !psz_fbuffer ) goto error; _tcsncpy( ( LPTSTR ) &lf.lfFaceName, psz_fbuffer, LF_FACESIZE ); free( psz_fbuffer ); lf.lfCharSet = DEFAULT_CHARSET; HFONT hFont = CreateFontIndirect( &lf ); if( !hFont ) goto error; HFONT hOriginalFont = SelectObject( meta_file_dc, hFont ); TCHAR text = codepoint; SCRIPT_STRING_ANALYSIS script_analysis; HRESULT hresult = ScriptStringAnalyse( meta_file_dc, &text, 1, 0, -1, SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK, 0, NULL, NULL, NULL, NULL, NULL, &script_analysis ); if( SUCCEEDED( hresult ) ) { hresult = ScriptStringOut( script_analysis, 0, 0, 0, NULL, 0, 0, FALSE ); ScriptStringFree( &script_analysis ); } SelectObject( meta_file_dc, hOriginalFont ); DeleteObject( hFont ); meta_file = CloseEnhMetaFile( meta_file_dc ); if( SUCCEEDED( hresult ) ) { LOGFONT log_font; log_font.lfFaceName[ 0 ] = 0; EnumEnhMetaFile( 0, meta_file, MetaFileEnumProc, &log_font, NULL ); if( log_font.lfFaceName[ 0 ] ) psz_result = FromT( log_font.lfFaceName ); } DeleteEnhMetaFile(meta_file); DeleteDC( hdc ); return psz_result; error: if( meta_file_dc ) DeleteEnhMetaFile( CloseEnhMetaFile( meta_file_dc ) ); if( hdc ) DeleteDC( hdc ); return NULL; }
static bool MCTextLayoutStyleItem(MCTextLayoutState& self, SCRIPT_ANALYSIS p_analysis, const unichar_t *p_chars, uint32_t p_char_count, MCTextLayoutFont *p_primary_font) { bool t_success; t_success = true; // Create a metafile dc into which we render the text HDC t_metafile_dc; t_metafile_dc = nil; if (t_success) { t_metafile_dc = CreateEnhMetaFile(nil, nil, nil, nil); if (t_metafile_dc == nil) t_success = false; } // Choose the primary font if (t_success) SelectObject(t_metafile_dc, p_primary_font -> handle); // Now use ScriptStringAnalyse to output the text into the metafile. SCRIPT_STRING_ANALYSIS t_ssa; t_ssa = nil; if (t_success) { SCRIPT_STATE t_script_state; SCRIPT_CONTROL t_script_control; MCMemoryClear(&t_script_state, sizeof(SCRIPT_STATE)); MCMemoryClear(&t_script_control, sizeof(SCRIPT_CONTROL)); if (ScriptStringAnalyse(t_metafile_dc, p_chars, p_char_count, 0, -1, SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK, 0, &t_script_control, &t_script_state, nil, nil, nil, &t_ssa) != S_OK) t_success = false; } // Render the analysed text into the metafile. if (t_success) if (ScriptStringOut(t_ssa, 0, 0, 0, nil, 0, 0, FALSE) != S_OK) t_success = false; // Fetch the metafile (we are done with the DC now) HENHMETAFILE t_metafile; t_metafile = nil; if (t_metafile_dc != nil) { t_metafile = CloseEnhMetaFile(t_metafile_dc); if (t_metafile == nil) t_success = false; } // Now process the metafile to get the subranges of text styled to the // appropriate fallback font. if (t_success) { MCTextLayoutStyleItemContext t_context; t_context . state = &self; t_context . chars = p_chars; t_context . char_count = p_char_count; t_context . analysis = p_analysis; t_context . primary_font = p_primary_font; t_context . current_font = p_primary_font; t_context . pending_x = 0; t_context . pending_font = nil; t_context . pending_chars = nil; t_context . pending_char_count = 0; if (!EnumEnhMetaFile(nil, t_metafile, MCTextLayoutStyleItemCallback, &t_context, nil)) t_success = false; } // Free the metafile if (t_metafile != nil) DeleteEnhMetaFile(t_metafile); return t_success; }