2019年3月18日 星期一

初探FreeType

初探FreeType

前言

  繪圖API並不支援畫字型的功能,以前使用Direct2D搭配DirectWrite來畫字型,但不幸地現在繪圖引擎要跨平台,Direct2D的方法最多只能在Windows平台使用,FreeType就是我找到的可以跨平台的畫字型方法,這裡把學習心得做個紀錄。

內容

  首先先來說說"建置",FreeType自帶的建置個人覺得實在是不怎麼好用,Windows版的建置是由官方給個Visual studio專案直接開啟後建置即可,但Linux的建置就完全不一樣,是類似透過Shell script的方式來建置,Android則是透過NDK的專案來建置,最後我並沒選擇官方的建置是因為FreeType在下載時是在Windows平台,所以裡面的文字檔的換行是"\r\n",結果當我在Ubuntu建置時都會報錯,也就是說跟建置相關的檔案絕不能在Windows的環境編輯,不然上傳後就沒辦法用了。解決的方案很簡單,就是自己建置,還記得官方有自帶一個Visual studio專案嗎?我依據該專案的建置方案來製作Linux與Android的建置,這方法有風險,但我還是做了,幸運的是Linux與Android的建置與Windows是差不多,差別的地方是Linux與Android版並沒有所謂的"Debug"版,編譯時不用加"FT_DEBUG_LEVEL_ERROR"與"FT_DEBUG_LEVEL_TRACE"編譯,其它的部分和Windows版是一樣的。

  接著來看看如何使用,先看以下範例
#include "ft2build.h"
#include FT_FREETYPE_H

int main()
{
  //...
  //
  FT_Library library;
  FT_Error error=FT_Init_FreeType(&library);
  if(error!=0)
    return 1;
  //
  //...
  //Free
  FT_Done_FreeType(library);

  return 0;
}

這個範例會去製造FT_Library,整個程式應該只要製造一個,在程式要結束時,透過FT_Done_FreeType()來釋放。FT_Library製造完後就可以來讀取font檔,範例如下
#include "ft2build.h"
#include FT_FREETYPE_H

int main()
{
  //...
  //
  FT_Library library;
  FT_Error error=FT_Init_FreeType(&library);
  if(error!=0)
    return 1;
  //Load font file
  FT_Face face;
  error=FT_New_Face(library,"arial.ttf",0,&face);
  //...
  //Free
  FT_Done_Face(face);
  FT_Done_FreeType(library);

  return 0;
}

讀取的方法很簡單,透過FT_New_Face()來讀取,透過FT_Done_Face()來釋放。在Android時,由於Android的Asset不提供Handle,如果要將Font檔放在Asset的話,就要透過FT_New_Memory_Face()來讀取。接下來就來讀取字型的資料,範例如下
#include "ft2build.h"
#include FT_FREETYPE_H

int main()
{
  //...
  //
  FT_Library library;
  FT_Error error=FT_Init_FreeType(&library);
  if(error!=0)
    return 1;
  //Load font file
  FT_Face face;
  error=FT_New_Face(library,"arial.ttf",0,&face);
  //Set font size
  error=FT_Set_Pixel_Sizes(face,0,60);
  //Load glyph
  FT_UInt glyphIndex=FT_Get_Char_Index(face,'a');
  if(glyphIndex==0)
    return 1;
  error=FT_Load_Glyph(face,glyphIndex,FT_LOAD_DEFAULT);
  if(face->glyph->format!=FT_GLYPH_FORMAT_BITMAP)
  {
    error=FT_Render_Glyph(face->glyph,FT_RENDER_MODE_MONO);
    if(error!=0)
      return 1;
  }
  //Get glyph bitmap data from face->glyph->bitmap.buffer
  //...
  //Free
  FT_Done_Face(face);
  FT_Done_FreeType(library);

  return 0;
}

 透過FT_Set_Pixel_Sizes()來設定字型的大小,接著透過Glyph index來寫資料到"buffer"裡,"buffer"在哪呢?透過face->glyph->bitmap.buffer來取得。

  Buffer的資料就是一張圖,整個Buffer的資料的大小為face->glyph->bitmap.pitch*face->glyph->bitmap.rows,"face->glyph->bitmap.rows"就是高,但"face->glyph->bitmap.pitch"並不是寬,每個Pitch指的是把寬度以每8個Pixel存成一個Byte來計算的話會有幾個Byte,如果寬度是60Pixel,Pitch值為8,如果寬度是40Pixel,Pitch值為5,依此類推。

參考資料

FreeType官網
Text Rendering with Direct2D and DirectWrite

2019年3月11日 星期一

箭頭函式的注意事項

箭頭函式的注意事項

前言

  ECMAScript6新增了箭頭函示語法,在網路上找到這篇ECMAScript 6 入门,看起來是個方便的語法,至少程式碼看起來比較簡短。在實際使用後發生了問題,在此做個紀錄。

內容

  箭頭函式剛用起來都沒什麼問題,但在使用到和'this'有關的時候可能會發生問題,範例如下
function CA(){
  this.value = 1234;
  this.myCall = function(callBackFun){
    callBackFun.call(this);
    
  };
  this.arrowCall = ()=>{
    console.log(this.value);
  };
}
let a = new CA();
//normal funciton call
a.myCall( function(){
  //output:1234
  console.log(this.value);
  
});
//arrow function call
a.myCall( ()=>{
  //output:undefined
  console.log(this.value);
  
} );
//output:1234
a.arrowCall();

這個範例在使用箭頭函式傳入"myCall"後會發現無法正常存取"value",如果把當下的"this"應出來會發現是"global",再來看看"arrowCall",在建構時使用箭頭函式,結果是正確的,this可以正常存取"value"。箭頭函式的"this"是建構當下的物件,無法透過call()來賦予"this",詳細的規則可以參考箭頭函式。如果覺得麻煩的話就在使用時想想這個函式會不會使用到"this",如果會就用舊的方式,如果不會就使用箭頭函式(看起來比較簡短)。

參考資料

ECMAScript 6 入门
箭頭函式

2019年3月4日 星期一

在Atom裡關閉預設外掛

在Atom裡關閉預設外掛

前言

  最近開啟Atom時會發生卡死的情況,畫面會停留上次開啟的檔案,但ㄏ不會有對任何輸入有反應,一陣子後會出現"Editor is not responding"的視窗,選擇"Force close"會直接關閉Atom,選另一個就在等一陣子又跳"Editor is not responding"視窗,這個情形要怎麼解決呢?在此把過程作個紀錄。

內容

  遇到這個問題馬上就google到這篇‘restore to default settings’ setting,這篇會說Atom的資料夾在"~/.atom",所有的設定包含外掛都會儲存在該資料夾,只要將該資料夾刪除後再開啟Atom就可以正常開啟,但不幸地的是所有的外掛與設定與開啟的專案都會消失,實在不是個好方法。

  到底是什麼樣的資料造成這個問題呢?答案是"外掛",外掛安裝的資料夾在"~/.atom/packages",所以我就一個一個刪掉來實驗室哪一個外掛,最後找到兇手
"linter-eslint",只要刪掉就可以正常開啟Atom了,只需重裝"linter-eslint"即可,比整個重裝好多了。但這樣還是不夠的,因為"linter-eslint"的安裝時間不算短,既然只有在開啟時會有問題,所以只要在開啟時不啟動該外掛不就可以了,接著我注意到這個檔案"~/.atom/config.cson",打開後可以看到以下
"*":
  core:
    disabledPackages: [
      "wrap-guide"
      "bracket-matcher"
      "welcome"
    ]
  "exception-reporting":
    userId: "a8e98b83-80d4-4e7b-aa3f-f3465fae1a95"
  "linter-ui-default": {}
  welcome:
    showOnStartup: false

注意"disabledPackages",我觀察了一下內容,都是我disable的外掛,接著我以實驗的精神在內容填上"linter-eslint",如下
"*":
  core:
    disabledPackages: [
      "wrap-guide"
      "bracket-matcher"
      "welcome"
      "linter-eslint"
    ]
  "exception-reporting":
    userId: "a8e98b83-80d4-4e7b-aa3f-f3465fae1a95"
  "linter-ui-default": {}
  welcome:
    showOnStartup: false

就這樣"linter-eslint"如我所願在開啟時不會被啟動,Atom也順利開啟。

參考資料

‘restore to default settings’ setting

2019年2月25日 星期一

在Atom裡使用makefile建置C++

在Atom裡使用makefile建置C++

前言

  在Linux使用makefile建置C++時有個麻煩,當Target很多的時候會發生忘記Target的名稱,所以就會要開起makefile來複製Target的名稱,如果可以直接選擇Target不是很好嗎?最近發現Atom有個外掛可以達成,在此做個紀錄。

內容

  首先來安裝需要的外掛,外掛的名稱是"build-make-file",如下圖所示
安裝外掛"build-make-file"

裝完後,開啟一個makefile的檔案,接著按下"F7"後就可以看到下圖
選擇Target

選擇後就會執行,用起來非常簡單。這個外掛有些小缺陷,有時按下"F7"後會沒有即時更新Target,請等個1~2後再按"F7"就會即時更新Target,另外這個外掛只有當開啟的檔案是makefile時才會動作,並不是選取專案的任意檔案就會自動偵測的類型,這點請注意。

2019年2月18日 星期一

在Atom裡使用node.js

在Atom裡使用node.js

前言

  以前要跑node.js的專案我會選用NetBeans來建置專案,雖然NetBeans是跨平台,但編輯器的使用習慣跟我的習慣有落差,所以考慮使用Atom來替代,在此做個紀錄。

內容

  由於Atom本身並不支援node.js,但可以透過外掛來支援,所以安裝完後要先裝外掛,請依下圖只是開啟設定
Atom開啟設定
開啟後可以看到下圖
選擇要安裝的外掛
在"2"的地方輸入可以搜尋外掛,下方顯示的就是搜尋的成果,那要安裝那些外掛呢?請看下圖
node.js所需的外掛
第一個外掛是"build",這個外掛很重要,很多需要"建置"的外掛都需要透過這個外掛,第二個外掛是"build-npm-apm",這個就是基於"build"外掛來支援npm。

  安裝完後,建一個專案來測試外掛式正常,如下圖
測試專案
選擇"package.json"後按下"F7"後,可以看到下圖
選擇要執行的Target
這裡就可以選擇要執行的Target,按下後就會執行很簡單。如果沒跳出Target的話,請重開Atom,這個外掛似乎只會在開啟後掃描一次,之後就不會重新掃描,所以如果Target有進行更新的話也請重開Atom。

  整個用起來和上次在初探Visual studio code裡介紹的VSCode(Visual studio code)差不多,VSCode建置時需要比較多次的選擇,但Target會即時更新,Atom則是有比較少的選擇步驟,但Target不會即時更新,最後我選了Atom,雖然Target不會即時更新,但Target其實並不會時常更新,反倒是執行Target要時常使用。

相關文章

初探Visual studio code

2019年2月11日 星期一

解決Afterburner繪圖API是OpenGL但卻顯示D3D10的問題

解決Afterburner繪圖API是OpenGL但卻顯示D3D10的問題

前言

  Afterburner可以用來監控GPU的相關數據,而且可以直接將數據顯示在視窗上,如下圖
GLFW的範例使用Afterburner顯示數據
圖中箭頭所指的是使用的繪圖API,如果只安裝Afterburner的話,這裡就會顯示"D3D10"(Direct3D10)而不是"OGL"(OpenGL),是什麼問題呢?

內容

  顯示繪圖API不正確的問題本以為是Afterburner沒設定好,所以在設定介面花了不少時間,但發現沒有參數可以調整,接著就Google了這個問題,發現問題都有個關鍵字"RTSS",查了一下全名是"RivaTuner Statistics Sever",這個軟體才是真正提供顯示數據在視窗上的功能,Afterburner只是去啟動它,可以在系統右下的Icon找到它,如下圖
RTSS2的Icon
圖中的1是Afterburner的Icon,而2所指的就是RTSS,點選後可以看到操作的視窗,如下圖
RTSS的操作視窗
本以為是在這個視窗做調整,但最後發現是把它更新到最新版後就正常了,可以到Guru3D RTSS Rivatuner Statistics Server Download下載,看了一下google相關問題的討論,都超過一年以上,所以推測這個問題應該是Afterburner的安裝程式裡的RTSS是舊版的所造成的問題。

參考資料

Guru3D RTSS Rivatuner Statistics Server Download

2019年2月4日 星期一

初探Visual studio code

初探Visual studio code

前言

  最近在查找資料時發現有個跨平台的編輯器Visual studio code,就想到我在Ubuntu一直以來都用Console在建置專案,搞不好可以取代,在此把學習的過程做個紀錄。

內容

  Visual studio code用起來和Atom的感覺滿像的,尤其是把某個資料夾就直接當成專案的資料夾這點,這次會說明如何安裝外掛與如何執行npm的script。

  安裝外掛的部分可以參考下圖
Visual studio code安裝外掛
先點選最左側的Icon(圖中被圈起來的),接著可以在Icon右邊看到已安裝的外掛,下方的視窗(圖中被箭頭所指)可以選擇要安裝的外掛,用起來相當直觀簡單。

  執行npm的script的部分,先建一個專案,範例如下
{
  "name": "mylib",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "mytest2":"echo \"This is my test!\" "
  },
  "author": "",
  "license": "ISC"
}

基本上就是用"npm init"來建,紅字的部分是新增的。建完後如何跑呢?本以為是透過外掛來達成的,所以google了一陣子後才發現不是,Visual studio code本身有內建的命令,要透過內建的命令來執行命令,先看下圖
開啟Visual studio code命令列
注意這是Visual studio code的命令列,並不是console,開啟後可以看到下圖
執行命令
如果圖中的"Tasks:Run Task"沒出現在正下選項中可以在上方的輸入"Tasks:Run Task",該輸入會篩選符合的命令,點選"Tasks:Run Task"後可以看到下圖
執行Target
這裡可以選擇要執行哪個Target,選完後可以看到下圖
選擇執行項目
這裡選"Continue without scanning the task output",選完後就執行命令。

參考資料

Visual Studio Code Tips and Tricks