123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- #include "cairo_font.h"
- cairo_font::cairo_font(IMLangFontLink2* fl, HFONT hFont, int size )
- {
- init();
- m_font_link = fl;
- if(m_font_link)
- {
- m_font_link->AddRef();
- }
- m_size = size;
- set_font(hFont);
- }
- cairo_font::cairo_font(IMLangFontLink2* fl, LPCWSTR facename, int size, int weight, BOOL italic, BOOL strikeout, BOOL underline )
- {
- init();
- m_size = size;
- m_font_link = fl;
- if(m_font_link)
- {
- m_font_link->AddRef();
- }
- LOGFONT lf;
- ZeroMemory(&lf, sizeof(lf));
- if(!lstrcmpi(facename, L"monospace"))
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Courier New");
- } else if(!lstrcmpi(facename, L"serif"))
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Times New Roman");
- } else if(!lstrcmpi(facename, L"sans-serif"))
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Arial");
- } else if(!lstrcmpi(facename, L"fantasy"))
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Impact");
- } else if(!lstrcmpi(facename, L"cursive"))
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, L"Comic Sans MS");
- } else
- {
- wcscpy_s(lf.lfFaceName, LF_FACESIZE, facename);
- }
- lf.lfHeight = -size;
- lf.lfWeight = weight;
- lf.lfItalic = italic;
- lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf.lfQuality = DEFAULT_QUALITY;
- lf.lfStrikeOut = strikeout;
- lf.lfUnderline = underline;
- HFONT fnt = CreateFontIndirect(&lf);
- set_font(fnt);
- }
- cairo_font::~cairo_font()
- {
- if(m_font_face)
- {
- cairo_font_face_destroy(m_font_face);
- }
- for(size_t i = 0; i < m_linked_fonts.size(); i++)
- {
- if(m_linked_fonts[i]->hFont)
- {
- m_font_link->ReleaseFont(m_linked_fonts[i]->hFont);
- }
- if(m_linked_fonts[i]->font_face)
- {
- cairo_font_face_destroy(m_linked_fonts[i]->font_face);
- }
- }
- m_linked_fonts.clear();
- if(m_font_link)
- {
- m_font_link->AddRef();
- }
- if(m_hFont)
- {
- DeleteObject(m_hFont);
- }
- }
- void cairo_font::show_text( cairo_t* cr, int x, int y, const litehtml::tchar_t* str )
- {
- lock();
- text_chunk::vector chunks;
- split_text(str, chunks);
- cairo_set_font_size(cr, m_size);
- cairo_move_to(cr, x, y);
- for(size_t i = 0; i < chunks.size(); i++)
- {
- if(chunks[i]->font)
- {
- cairo_set_font_face(cr, chunks[i]->font->font_face);
- } else
- {
- cairo_set_font_face(cr, m_font_face);
- }
- cairo_show_text(cr, chunks[i]->text);
- }
- unlock();
- if(m_bUnderline)
- {
- int tw = text_width(cr, chunks);
- lock();
- cairo_set_line_width(cr, 1);
- cairo_move_to(cr, x, y + 1.5);
- cairo_line_to(cr, x + tw, y + 1.5);
- cairo_stroke(cr);
- unlock();
- }
- if(m_bStrikeOut)
- {
- int tw = text_width(cr, chunks);
- cairo_font_metrics fm;
- get_metrics(cr, &fm);
- int ln_y = y - fm.x_height / 2;
- lock();
- cairo_set_line_width(cr, 1);
- cairo_move_to(cr, x, (double) ln_y - 0.5);
- cairo_line_to(cr, x + tw, (double) ln_y - 0.5);
- cairo_stroke(cr);
- unlock();
- }
- free_text_chunks(chunks);
- }
- void cairo_font::split_text( const litehtml::tchar_t* src, text_chunk::vector& chunks )
- {
- wchar_t* str;
- #ifdef LITEHTML_UTF8
- str = cairo_font::utf8_to_wchar(src);
- wchar_t* str_start = str;
- #else
- str = (wchar_t*) src;
- #endif
- int cch = lstrlen(str);
- HDC hdc = GetDC(NULL);
- SelectObject(hdc, m_hFont);
- HRESULT hr = S_OK;
- while(cch > 0)
- {
- DWORD dwActualCodePages;
- long cchActual;
- if(m_font_link)
- {
- hr = m_font_link->GetStrCodePages(str, cch, m_font_code_pages, &dwActualCodePages, &cchActual);
- } else
- {
- hr = S_FALSE;
- }
-
- if(hr != S_OK)
- {
- break;
- }
-
- text_chunk* chk = new text_chunk;
- int sz = WideCharToMultiByte(CP_UTF8, 0, str, cchActual, chk->text, 0, NULL, NULL) + 1;
- chk->text = new CHAR[sz];
- sz = WideCharToMultiByte(CP_UTF8, 0, str, cchActual, chk->text, sz, NULL, NULL);
- chk->text[sz] = 0;
- chk->font = NULL;
- if(!(dwActualCodePages & m_font_code_pages))
- {
- for(linked_font::vector::iterator i = m_linked_fonts.begin(); i != m_linked_fonts.end(); i++)
- {
- if((*i)->code_pages == dwActualCodePages)
- {
- chk->font = (*i);
- break;
- }
- }
- if(!chk->font)
- {
- linked_font* lkf = new linked_font;
- lkf->code_pages = dwActualCodePages;
- lkf->hFont = NULL;
- m_font_link->MapFont(hdc, dwActualCodePages, 0, &lkf->hFont);
- if (lkf->hFont)
- {
- lkf->font_face = create_font_face(lkf->hFont);
- m_linked_fonts.push_back(lkf);
- }
- else
- {
- delete lkf;
- lkf = NULL;
- }
- chk->font = lkf;
- }
- }
- chunks.push_back(chk);
- cch -= cchActual;
- str += cchActual;
- }
- if(hr != S_OK)
- {
- text_chunk* chk = new text_chunk;
- int sz = WideCharToMultiByte(CP_UTF8, 0, str, -1, chk->text, 0, NULL, NULL) + 1;
- chk->text = new CHAR[sz];
- sz = WideCharToMultiByte(CP_UTF8, 0, str, -1, chk->text, sz, NULL, NULL);
- chk->text[sz] = 0;
- chk->font = NULL;
- chunks.push_back(chk);
- }
- ReleaseDC(NULL, hdc);
- #ifdef LITEHTML_UTF8
- delete str_start;
- #endif
- }
- void cairo_font::free_text_chunks( text_chunk::vector& chunks )
- {
- for(size_t i = 0; i < chunks.size(); i++)
- {
- delete chunks[i];
- }
- chunks.clear();
- }
- cairo_font_face_t* cairo_font::create_font_face( HFONT fnt )
- {
- LOGFONT lf;
- GetObject(fnt, sizeof(LOGFONT), &lf);
- return cairo_win32_font_face_create_for_logfontw(&lf);
- }
- int cairo_font::text_width( cairo_t* cr, const litehtml::tchar_t* str )
- {
- text_chunk::vector chunks;
- split_text(str, chunks);
- int ret = text_width(cr, chunks);
- free_text_chunks(chunks);
- return (int) ret;
- }
- int cairo_font::text_width( cairo_t* cr, text_chunk::vector& chunks )
- {
- lock();
- cairo_set_font_size(cr, m_size);
- double ret = 0;
- for(size_t i = 0; i < chunks.size(); i++)
- {
- if(chunks[i]->font)
- {
- cairo_set_font_face(cr, chunks[i]->font->font_face);
- } else
- {
- cairo_set_font_face(cr, m_font_face);
- }
- cairo_text_extents_t ext;
- cairo_text_extents(cr, chunks[i]->text, &ext);
- ret += ext.x_advance;
- }
- unlock();
- return (int) ret;
- }
- void cairo_font::get_metrics(cairo_t* cr, cairo_font_metrics* fm )
- {
- lock();
- cairo_set_font_face(cr, m_font_face);
- cairo_set_font_size(cr, m_size);
- cairo_font_extents_t ext;
- cairo_font_extents(cr, &ext);
- cairo_text_extents_t tex;
- cairo_text_extents(cr, "x", &tex);
- fm->ascent = (int) ext.ascent;
- fm->descent = (int) ext.descent;
- fm->height = (int) (ext.ascent + ext.descent);
- fm->x_height = (int) tex.height;
- unlock();
- }
- void cairo_font::set_font( HFONT hFont )
- {
- clear();
- m_hFont = hFont;
- m_font_face = create_font_face(m_hFont);
- m_font_code_pages = 0;
- if(m_font_link)
- {
- HDC hdc = GetDC(NULL);
- SelectObject(hdc, m_hFont);
- m_font_link->GetFontCodePages(hdc, m_hFont, &m_font_code_pages);
- ReleaseDC(NULL, hdc);
- }
- LOGFONT lf;
- GetObject(m_hFont, sizeof(LOGFONT), &lf);
- m_bUnderline = lf.lfUnderline;
- m_bStrikeOut = lf.lfStrikeOut;
- }
- void cairo_font::clear()
- {
- if(m_font_face)
- {
- cairo_font_face_destroy(m_font_face);
- m_font_face = NULL;
- }
- for(size_t i = 0; i < m_linked_fonts.size(); i++)
- {
- if(m_linked_fonts[i]->hFont && m_font_link)
- {
- m_font_link->ReleaseFont(m_linked_fonts[i]->hFont);
- }
- if(m_linked_fonts[i]->font_face)
- {
- cairo_font_face_destroy(m_linked_fonts[i]->font_face);
- }
- }
- m_linked_fonts.clear();
- if(m_hFont)
- {
- DeleteObject(m_hFont);
- m_hFont = NULL;
- }
- }
- void cairo_font::init()
- {
- m_hFont = NULL;
- m_font_face = NULL;
- m_font_link = NULL;
- m_font_code_pages = 0;
- m_size = 0;
- m_bUnderline = FALSE;
- m_bStrikeOut = FALSE;
- }
- wchar_t* cairo_font::utf8_to_wchar( const char* src )
- {
- if(!src) return NULL;
- int len = (int) strlen(src);
- wchar_t* ret = new wchar_t[len + 1];
- MultiByteToWideChar(CP_UTF8, 0, src, -1, ret, len + 1);
- return ret;
- }
- char* cairo_font::wchar_to_utf8( const wchar_t* src )
- {
- if(!src) return NULL;
- int len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
- char* ret = new char[len];
- WideCharToMultiByte(CP_UTF8, 0, src, -1, ret, len, NULL, NULL);
- return ret;
- }
|