• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 16, 文章 - 0, 評論 - 55, 引用 - 0
            數(shù)據(jù)加載中……

            在windows下,當(dāng)FLTK界面上包含中文的時候啟動速度很慢,以下為修正過程

            問題描述:
            在windows下,當(dāng)FLTK界面包含中文的時候,打開程序的時候會花費好幾秒的時間才能完整顯示界面

            原因:
            查了代碼,最后發(fā)現(xiàn)原因在于繪制字符的時候通過GetTextExtentPoint32W這個函數(shù)獲取字符寬度,由于這個函數(shù)本身速度不夠快,所以FLTK使用緩存方式來保存寬度,問題在于緩存的方式不適合中文這種寬字符,當(dāng)前的緩存方式是每當(dāng)獲取一個字符寬度時,把這個字符左右共1024個相鄰字符的寬度提前獲取并保存,以后每次獲取字符寬度之前先搜索緩存,如果沒有再通過API實際獲取。

            這個做法對于英文沒有問題,因為GetTextExtentPoint32W處理英文的速度很快,而且一次獲取1024個相鄰字符基本就把程序可能會用到的字符全部囊括了,但是當(dāng)界面出現(xiàn)中文的時候這種做法就出現(xiàn)問題了,中文的字符集是很大的,一次獲取相鄰個1024字符寬度并不能保證囊括了絕大多數(shù)的字符,所以每次界面顯示之前都會花很多時間獲取很多用不到的字符寬度,雖然顯示一次之后的速度很快,但是啟動程序的時候會出現(xiàn)卡頓

            所以我做了修正,每當(dāng)需要獲取字符寬度的時候只保存當(dāng)前字符的寬度,不獲取相鄰字符的寬度,這樣就避免了問題

            修正代碼:
            一共修改2個文件,當(dāng)前修改的是FLTK3,如果要修改FLTK1.3.X,只要找到對應(yīng)的代碼即可
            src/fltk3/font.h (fltk1.3.X對應(yīng)的文件是src/fl_font.h)
            class Fl_Font_Descriptor {
            public:
              ...
            #  ifdef WIN32
              HFONT fid;
              int *width[64];
              unsigned char *widthcached[64]; // 0-not cache, 1-cached //這里增加定義
            ...
            };

            src/fltk3/win32_font.cxx(fltk1.3.X對應(yīng)的文件是src/fl_font_win32.cxx)
            Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, fltk3::Fontsize fsize)
            {
               ...
                int i;
                for (i = 0; i < 64; i++) {
                    width[i] = NULL;
                    widthcached[i] = NULL; // 這里增加
                }
              ...
            }

            Fl_Font_Descriptor::~Fl_Font_Descriptor()
            {
              ...
                int i;
                for (i = 0; i < 64; i++) {
                    if ( width[i] != NULL ) free(width[i]);
                    if ( widthcached[i] != NULL ) free(widthcached[i]); // 這里增加
                }
            }
            double fltk3::GDIGraphicsDriver::width(unsigned int c) // 修改主體就是這個方法,具體代碼如下
            {
                Fl_Font_Descriptor *fontsize = font_descriptor();
                unsigned int r;
                SIZE s;
                // Special Case Handling of Unicode points over U+FFFF.
                // The logic (below) computes a lookup table for char widths
                // on-the-fly, but the table only covers codepoints up to
                // U+FFFF, which covers the basic multilingual plane, but
                // not any higher plane, or glyphs that require surrogate-pairs
                // to encode them in WinXX, which is UTF16.
                // This code assumes that these glyphs are rarely used and simply
                // measures them explicitly if they occur - This will be slow...
                if(c > 0x0000FFFF) { // UTF16 surrogate pair is needed
                    if (!fl_gc) { // We have no valid gc, so nothing to measure - bail out
                        return 0.0;
                    }
                    int cc; // cell count
                    unsigned short u16[4]; // Array for UTF16 representation of c
                    // Creates a UTF16 string from a UCS code point.
                    cc = fltk3::ucs_to_Utf16(c, u16, 4);
                    // Make sure the current font is selected before we make the measurement
                    SelectObject(fl_gc, fontsize->fid);
                    // measure the glyph width
                    GetTextExtentPoint32W(fl_gc, (WCHAR*)u16, cc, &s);
                    return (double)s.cx;
                }
                // else - this falls through to the lookup-table for glyph widths
                // in the basic multilingual plane
                r = (c & 0xFC00) >> 10;
                unsigned short ii;
                HDC gc;
                HWND hWnd;
                if (!fontsize->width[r]) {
                    fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400);
                    fontsize->widthcached[r] = (unsigned char *)malloc(sizeof(unsigned char) * 0x0400);
                    for (int k=0; k<0x0400; k++) fontsize->widthcached[r][k] = 0;
                    ii = r * 0x400;
                    // The following code makes a best effort attempt to obtain a valid fl_gc.
                    // If no fl_gc is available at the time we call fltk3::width(), then we first
                    // try to obtain a gc from the first fltk window.
                    // If that is null then we attempt to obtain the gc from the current screen
                    // using (GetDC(NULL)).
                    // This should resolve STR #2086
                    gc = fl_gc;
                    hWnd = 0;
                    if (!gc) { // We have no valid gc, try and obtain one
                        // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
                        hWnd = fltk3::first_window() ? fl_xid(fltk3::first_window()) : NULL;
                        gc = GetDC(hWnd);
                    }
                    if (!gc) fltk3::fatal("Invalid graphic context: fltk3::width() failed because no valid HDC was found!");
                    SelectObject(gc, fontsize->fid);
                    ii += c &0x03FF;
                    GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s);
                    fontsize->width[r][c&0x03FF] = s.cx;
                    fontsize->widthcached[r][c&0x03FF] = 1;
                    if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc);
                    //printf("[%d,%X]\n", s.cx, c);
                } else {
                    if ( fontsize->widthcached[r][c&0x03FF] == 1 ) return (double) fontsize->width[r][c & 0x03FF];
                    ii = r * 0x400;
                    gc = fl_gc;
                    hWnd = 0;
                    if (!gc) { // We have no valid gc, try and obtain one
                        // Use our first fltk window, or fallback to using the screen via GetDC(NULL)
                        hWnd = fltk3::first_window() ? fl_xid(fltk3::first_window()) : NULL;
                        gc = GetDC(hWnd);
                    }
                    if (!gc) fltk3::fatal("Invalid graphic context: fltk3::width() failed because no valid HDC was found!");
                    SelectObject(gc, fontsize->fid);
                    ii += c &0x03FF;
                    GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s);
                    fontsize->width[r][c&0x03FF] = s.cx;
                    fontsize->widthcached[r][c&0x03FF] = 1;
                    if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc);
                    //printf("[%d,%X]\n", s.cx, c);
                }
                return (double) fontsize->width[r][c & 0x03FF];
            }

            posted on 2014-04-29 17:28 cyantree 閱讀(2070) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            亚洲精品无码久久千人斩| 亚洲AV日韩AV天堂久久| 久久99精品国产自在现线小黄鸭 | 久久精品一区二区三区不卡| 99精品久久久久久久婷婷| 亚洲天堂久久久| 一本色道久久99一综合| 亚洲va久久久噜噜噜久久男同| 久久综合狠狠综合久久| a高清免费毛片久久| 久久亚洲国产成人影院网站| 亚洲欧美日韩久久精品| 久久99精品久久久久久动态图 | 久久综合一区二区无码| 一本大道久久香蕉成人网| 久久午夜伦鲁片免费无码| 91秦先生久久久久久久| 亚洲一区精品伊人久久伊人| 久久99精品久久久久久动态图| 久久久久人妻一区精品果冻| 久久久久久曰本AV免费免费| 久久九九亚洲精品| 久久久久久精品免费看SSS| 久久美女人爽女人爽| 久久久久久国产精品美女 | 久久久久久久久久久免费精品| 久久综合亚洲色一区二区三区| 久久精品人人做人人妻人人玩| 久久国产香蕉视频| 九九久久99综合一区二区| 久久亚洲AV无码精品色午夜麻豆 | 久久久精品久久久久特色影视| 日产精品久久久一区二区| 人人狠狠综合88综合久久| 久久国产精品99精品国产987| 99精品国产99久久久久久97| 少妇被又大又粗又爽毛片久久黑人 | 久久久久亚洲AV成人片| 麻豆精品久久久久久久99蜜桃 | 久久99国产综合精品| 2021国内久久精品|