<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [上一篇](http://blog.csdn.net/foruok/article/details/50486788)理解了一下PPAPI的設計,并從代碼角度理解了一下相關主題,這篇文章關注下面幾點: - 插件實例對象的創建與使用流程 - 實例大小的確認 - 渲染(繪圖) - 處理輸入事件 > foruok原創,如需轉載請關注foruok的微信訂閱號“程序視界”聯系foruok。 # 插件實例對象的創建與使用流程 畫了一個簡單的調用流程圖: ![pppapi_call_flow](https://box.kancloud.cn/2016-02-22_56caac332a630.jpg "") 結合stub.c或graphics_2d_example.c的代碼,應該比較容易理解。 前兩步我們在上一篇文章“[**理解PPAPI的設計**]()”里已經介紹了。接著往下說。 當PPP_GetInterface()被調用后,瀏覽器拿到了PPP_Instance接口,會調用PPP_Instance::DidCreate()來創建插件實例對象。一般我們在這個函數里會分配一些數據結構來保存新創建的實例。graphics_2d_example.c是這么實現DidCreate函數的: ~~~ PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc, const char* argn[], const char* argv[]) { struct InstanceInfo* info = (struct InstanceInfo*)malloc(sizeof(struct InstanceInfo)); info->pp_instance = instance; info->last_size.width = 0; info->last_size.height = 0; info->graphics = 0; /* Insert into linked list of live instances. */ info->next = all_instances; all_instances = info; return PP_TRUE; } ~~~ 上面的代碼,僅僅是malloc了struct InstanceInfo,做了初始化,保存插件實例對象的句柄,將新實例加入一個全局的實例對象鏈表。 一般的插件實例對象會對應網頁所在視圖(view)上的一個區域,這個區域會有坐標、大小,插件繪制的內容就顯示在這個區域內,用戶也通過這個區域和插件交互(比如鼠標、按鍵、觸摸等)。這個區域的大小,是在插件實例對象與view關聯起來時確定的。 當插件實例對象與view關聯時,PPP_Instance::DidChangeView方法會被調用。下面是graphics_2d_example中的實現: ~~~ void Instance_DidChangeView(PP_Instance pp_instance, PP_Resource view) { struct PP_Rect position; struct InstanceInfo* info = FindInstance(pp_instance); if (!info) return; if (g_view_interface->GetRect(view, &position) == PP_FALSE) return; if (info->last_size.width != position.size.width || info->last_size.height != position.size.height) { /* Got a resize, repaint the plugin. */ Repaint(info, &position.size); info->last_size.width = position.size.width; info->last_size.height = position.size.height; } } ~~~ 上面的代碼,先根據插件實例對象的句柄從全局鏈表找到插件實例對象,然后通過之前在PPP_InitializeModule()方法中獲取到的PPP_View接口(g_view_interface)來獲取由view所代表的視圖(區域)的rect,再接著重繪,保存大小; 再接下來,就進入到了交互和渲染循環,直到Web頁面被關閉時,PPP_Instance::DidDestroy被調用,再后來,PPP_ShutdownModule被調用。 # 渲染(繪圖) 這里只說明PPAPI插件這一側的渲染邏輯。實際上插件是在一塊代表圖像的內存上渲染,渲染完畢后通知瀏覽器,瀏覽器在合適的時候更新。 前面我們展示了graphics_2d_example中的DidChangeView函數實現。它在view尺寸變化時會調用Repaint方法來更新自己。Repaint方法里包含了基本的繪圖邏輯,我們來分析一下。代碼如下: ~~~ void Repaint(struct InstanceInfo* instance, const struct PP_Size* size) { PP_Resource image; struct PP_ImageDataDesc image_desc; uint32_t* image_data; int num_words, i; /* Ensure the graphics 2d is ready. */ if (!instance->graphics) { instance->graphics = MakeAndBindGraphics2D(instance->pp_instance, size); if (!instance->graphics) return; } /* Create image data to paint into. */ image = g_image_data_interface->Create( instance->pp_instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, PP_TRUE); if (!image) return; g_image_data_interface->Describe(image, &image_desc); /* Fill the image with blue. */ image_data = (uint32_t*)g_image_data_interface->Map(image); if (!image_data) { g_core_interface->ReleaseResource(image); return; } num_words = image_desc.stride * size->height / 4; for (i = 0; i < num_words; i++) image_data[i] = 0xFF0000FF; /* Paint image to graphics 2d. */ g_graphics_2d_interface->ReplaceContents(instance->graphics, image); g_graphics_2d_interface->Flush(instance->graphics, PP_MakeCompletionCallback(&FlushCompletionCallback, NULL)); g_core_interface->ReleaseResource(image); } ~~~ 首先它會確保當前插件實例對象綁定了2D圖形上下文。這是在MakeAndBindGraphics2D()函數內完成,代碼如下: ~~~ PP_Resource MakeAndBindGraphics2D(PP_Instance instance, const struct PP_Size* size) { PP_Resource graphics; graphics = g_graphics_2d_interface->Create(instance, size, PP_FALSE); if (!graphics) return 0; if (!g_instance_interface->BindGraphics(instance, graphics)) { g_core_interface->ReleaseResource(graphics); return 0; } return graphics; } ~~~ 可以看到它使用了g_graphics_2d_interface接口指針(類型是PPP_Graphics2D),這個接口在PPP_InitializeModule()中使用get_browser_interface獲取,名字是PPP_GRAPHICS_2D_INTERFACE。 PPP_Graphics2D操作圖形上下文(2D Graphics Context)的接口,它的Create方法可以創建一個2D Graphics Context。2D圖形上下文與插件實例對象綁定后,插件實例對象就可以操作圖形上下文,進行渲染。 圖形上下文與插件實例對象的綁定是通過PPP_Instance接口的BindGraphics方法完成的(參見ppb_instance.h)。PPP_Instance接口在PPP_InitializeModule()中使用get_browser_interface獲取,名字是PPP_INSTANCE_INTERFACE。 PPP_Graphics2D能操作2D圖形上下文,通知瀏覽器更新。但是更新的圖像數據,是放在別處的(一個由句柄標識的內存區域),不在PPP_Graphics2D內。保存在內存中的圖形數據,可以通過PPP_ImageData接口來操作。這個接口,同樣也是在PPP_InitializeModule()中使用get_browser_interface獲取,名字是PPP_IMAGEDATA_INTERFACE。接口的具體定義在ppb_image_data.h文件內。 PPP_ImageData的Create方法可以根據指定格式和大小分配一塊代表圖形數據的內存資源,Map方法可以把圖形數據資源映射到插件模塊所在的進程內,返回內存起始地址,我們可以操作內存進行繪圖操作。前面的Repaint方法就是這么干的。 Repaint方法繪圖完成后,調用PPP_Graphics2D的ReplaceContents方法來更新上下文,調用Flush來刷新(不調用不生效哦)。 刷新是異步的,你可以指定一個回調接口(PP_CompletionCallback,見pp_completion_callback.h),當刷新完成后,PP_CompletionCallback的func成員會被調用。有一個方便的內聯函數PP_MakeCompletionCallback可以幫你創建一個PP_CompletionCallback實例,它接受一個回調函數和一個void*作為user_data。 graphics_2d_example中的回調函數FlushCompletionCallback嘛事兒沒干。我們在實際開發時,可以在回調完成后繼續復用我們的分配的圖形資源,這樣可以提高效率。 好啦,這就是繪圖的基本流程了。 # 處理輸入事件 輸入事件在ppb_input_event.h中定義。看文件名開頭,就明白輸入事件接口是由瀏覽器這端提供的。 輸入事件的處理也分瀏覽器和插件兩側。 瀏覽器側實現了PPP_InputEvent接口,定義接口名字的宏是PPP_INPUT_EVENT_INTERFACE。插件可以在PPP_InitializeModule函數中通過get_browser_interface函數指針按名字獲取到。 PPP_InputEvent是入口,通過這個接口,插件實例對象可以通過RequestInputEvents和RequestFilteringInputEvents兩個函數來聲明自己感興趣的輸入事件(鼠標、鍵盤、觸摸、滾輪、輸入法等,見ppb_input_event.h)。 瀏覽器發現有插件實例對象關心某一類輸入事件,就會根據這個插件模塊導出的PPP_GetInterface函數來獲取名為PPP_INPUT_EVENT_INTERFACE的接口。PPP_GetInterface應該返回PPP_InputEvent接口。 插件側負責實現PPP_InputEvent接口(見ppp_input_event.h),這個接口(結構體)定義了一個HandleInputEvent方法。瀏覽器通過調用HandleInputEvent方法把事件傳遞給插件實例對象。 PPP_InputEvent的HandleInputEvent函數原型如下: ~~~ PP_Bool (*HandleInputEvent)(PP_Instance instance, PP_Resource input_event); ~~~ 第一個參數是插件實例對象句柄,第二個參數是輸入事件句柄(32位整數)。使用PPP_InputEvent接口和輸入事件句柄,可以判斷事件類型、獲取事件的其它信息。 但是某一類別的事件,有時需要專門的接口來獲取特定的信息,比如鼠標事件對應的瀏覽器側接口是PPP_MouseInputEvent,可以以PPP_MOUSE_INPUT_EVENT_INTERFACE為參數調用get_browser_interface函數指針獲取。 PPP_MouseInputEvent定義了一些方法,比如GetButton可以獲取是左鍵還是右鍵點擊,GetPosition可以獲取鼠標點擊的坐標,這些方法允許我們獲取完整的事件信息,根據事件信息做邏輯處理。 好啦,處理輸入事件的流程就這樣子了。 這次到這里,下篇我們結合繪圖和交互,來完成一個簡單的示例。 相關文章參考: - [**CEF Windows開發環境搭建**](http://blog.csdn.net/foruok/article/details/50468642) - [**CEF加載PPAPI插件**](http://blog.csdn.net/foruok/article/details/50485448) - [**VS2013編譯最簡單的PPAPI插件**](http://blog.csdn.net/foruok/article/details/50485461) - [**理解PPAPI的設計**](http://blog.csdn.net/foruok/article/details/50486788)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看