スポンサーリンク

FreeType2 FT_Set_Transformで文字を回転させて出力(2)文字列を出力

#include <iostream>
#include <vector>

#include <ft2build.h>
#include FT_FREETYPE_H


#pragma warning(disable:4996)

#pragma comment(lib,"freetype.lib")


void pnmP2_Write(
  const char* const fname,
  const int width,
  const int height,
  const unsigned char* const p);

void draw(
  const int width,
  const int height,
  unsigned char* p,
  const int charw,
  const int charh,
  const int ox,
  const int oy,
  const unsigned char* charp
);

      
int main()
{

  FT_Library  library; // handle to library
  FT_Error error;

  error = FT_Init_FreeType(&library);
  if (error)
    return -1;

  FT_Face face;    // handle to face object

  // フォントファイル読み込み
  error = FT_New_Face(
    library,
    "C:\\Windows\\Fonts\\meiryo.ttc",
    0,
    &face
  );

  //文字コード指定
  error = FT_Select_Charmap(
    face,         // target face object
    FT_ENCODING_UNICODE // エンコード指定
  );


  if (error == FT_Err_Unknown_File_Format)
    return -1;
  else if (error)
    return -1;

  //この二つの値でフォントサイズ調整
  FT_F26Dot6 fontsize = 16 * 64*2;
  FT_UInt CHAR_RESOLUTION = 300;
  error = FT_Set_Char_Size(
    face,        // handle to face object
    0,           // char_width in 1/64th of points
    fontsize,      // char_height in 1/64th of points
    CHAR_RESOLUTION,   // horizontal device resolution
    CHAR_RESOLUTION);  // vertical device resolution


  // 回転の指定
  double theta = -65.0 * 3.1415 / 180.0;
  // matrix.xxの型はFT_Fixedだが、これは typedef signed long FT_Fixed
  FT_Matrix  matrix;
  matrix.xx = (FT_Fixed)(cos(theta) * 0x10000L);
  matrix.xy = (FT_Fixed)(-sin(theta) * 0x10000L);
  matrix.yx = (FT_Fixed)(sin(theta) * 0x10000L);
  matrix.yy = (FT_Fixed)(cos(theta) * 0x10000L);

  FT_Set_Transform(face, &matrix, 0);

      
  // 出力画像のメモリ確保
  const int iw = 1000;
  const int ih = 1000;
  std::vector<unsigned char> image(iw*ih,0);

  // 描画位置
  int posx = 500;
  int posy = 500;
  for (size_t i = 0; i < 3; i++) {
    // 文字の取得
    FT_ULong character = U"あいう"[i];
    FT_UInt char_index = FT_Get_Char_Index(face, character);

    // グリフ(字の形状)読込
    error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER);
    if (error)
      return -1; // ignore errors


    // 文字を画像化
    FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);

    // 出力画像に文字を書き込み
    draw(
      //出力先データ
      iw, ih, image.data(),

      // 文字の画像
      face->glyph->bitmap.width,
      face->glyph->bitmap.rows,
      posx + face->glyph->bitmap_left,
      posy - face->glyph->bitmap_top,
      face->glyph->bitmap.buffer
    );
      
 
    posx += (face->glyph->advance.x >> 6);
    posy -= (face->glyph->advance.y >> 6);

  }

  pnmP2_Write(// ファイル保存
    "C:\\MyData\\freetypetest.pgm",
    iw,
    ih,
    image.data()
  );

  // FreeType2の解放
  FT_Done_Face(face);
  FT_Done_FreeType(library);
}

//! @brief Portable Gray map
//! @param [in] fname ファイル名
//! @param [in] width 画像の幅
//! @param [in] height 画像の高さ
//! @param [in] p 画像のメモリへのアドレス
//! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む
void pnmP2_Write(
  const char* const fname,
  const int width,
  const int height,
  const unsigned char* const p) { // PPM ASCII

  FILE* fp = fopen(fname, "wb");
  fprintf(fp, "P2\n%d %d\n%d\n", width, height, 255);

  size_t k = 0;
  for (size_t i = 0; i < (size_t)height; i++) {
    for (size_t j = 0; j < (size_t)width; j++) {
      fprintf(fp, "%d ", p[k]);
      k++;
    }
    fprintf(fp, "\n");
  }

  fclose(fp);
}

//! @brief 出力画像へ文字を書き込む
//! @param [in] width 出力先のサイズ
//! @param [in] height 出力先のサイズ
//! @param [out] p 出力先
//! @param [in] charw 文字画像のサイズ
//! @param [in] charh 文字画像のサイズ
//! @param [in] ox 描画始点
//! @param [in] oy 描画始点
//! @param [in] charp 文字画像
void draw(
  const int width,
  const int height,
  unsigned char* p,
  const int charw,
  const int charh,
  const int ox,
  const int oy,
  const unsigned char* charp
) {

  for (int cx = 0; cx < charw; cx++) {
    for (int cy = 0; cy < charh; cy++) {

      int x = ox + cx;
      int y = oy + cy;

      if (x < 0 || x >= width)continue;
      if (y < 0 || y >= height)continue;

      int ipos = y * width + x;
      int cpos = cy * charw + cx;

      int c = (int)(p[ipos]) + (int)(charp[cpos]);

      c = std::min(c, 255);

      p[ipos] = c;

    }
  }

}

360度回転させてみた例

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: