cairotools



【cairotools.h】

#ifndef _CAIROTOOLS_H_
#define _CAIROTOOLS_H_
#include <cmath>
#include <vector>
#include <cairo.h>
using namespace std;

//draw a center aligned text
template<class T>
void cairotools_show_text_center_aligned(cairo_t* cr, double cx, double cy, T text)
{
 ostringstream oss;
 oss<<text;
 string str = oss.str();
 const char* cstr = str.c_str();
 cairo_text_extents_t te;
 cairo_text_extents (cr, cstr, &te);
 cairo_move_to (cr, cx-te.width/2, cy+te.height/2);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_show_text (cr, cstr);
}

//draw and scale an image to an area specified with left upper corner (x,y) and width, height
void cairotools_draw_image(cairo_t* cr, const char * imageFileName, double x, double y, double width, double height);

//draw and scale an image to an area specified with center (cx,cy) and width, height
inline void cairotools_draw_image_at_center(cairo_t* cr, const char * imageFileName, double cx, double cy, double width, double height)
{
 cairotools_draw_image (cr, imageFileName, cx-width/2, cy-height/2, width, height);
};

//draw a round node with a text within it and a description under it
void cairotools_draw_round_node(cairo_t* cr, double cx, double cy, double radius, const char* text, const char* description);

void cairotools_draw_round_node(cairo_t* cr, double cx, double cy, double radius, const char* text);

//draw a connection line with text between two round nodes
void cairotools_draw_round_node_connection(cairo_t* cr, double cx1, double cy1, double cx2, double cy2, double radius, const char* text);

class ChessBoard
{
private:
 cairo_t* cr;
 int m; //row count
 int n; //column count
 vector<vector<bool> > chess; //2 dimentional array indicating whether there is a chess at a location
 
 void Initialize();
 void DrawChess(int row, int column); //draw a chess at place [row, column], row, column starts from 0
public:
 double x; //coordinates of left upper conner
 double y;
 double cellWidth;
 bool showLabel;
 
 ChessBoard(cairo_t* cr, int m, int n):cr(cr),m(m),n(n),x(0),y(0),cellWidth(40),showLabel(true){ Initialize(); };
 ChessBoard(cairo_t* cr, int m, int n, double x, double y):cr(cr),m(m),n(n),x(x),y(y),cellWidth(40),showLabel(true){ Initialize(); };
 ChessBoard(cairo_t* cr, int m, int n, double x, double y, double cellWidth):cr(cr),m(m),n(n),x(x),y(y),cellWidth(cellWidth),showLabel(true){ Initialize(); };
 
 friend ostream& operator<<(ostream& os, const ChessBoard& chessBoard);
 void Draw(); //draw the chess board at location (x,y) with cell width "cellWidth"
 void PutChess(int row, int column); //put a chess at place [row, column]. row, column starts form 0
 void PutChess(vector<vector<bool> >& chess); //put chess specified by the 2-dimentional array
 void RemoveChess(int row, int column); //remove a chess from place [row, column]. row, column starts form 0
 void Clear(); //clear the board
};
#endif // _CAIROTOOLS_H_


【cairotools.cpp】

#include <cmath>
#include <iostream>
#include <sstream>
#include <cairo.h>
#include "cairotools.h"

using namespace std;

void cairotools_draw_image(cairo_t* cr, const char * imageFileName, double x, double y, double width, double height)
{
 cairo_surface_t* image;
 image = cairo_image_surface_create_from_png (imageFileName);
 double w, h;
 w = cairo_image_surface_get_width (image);
 h = cairo_image_surface_get_height (image);
 cairo_save(cr);
 double scaleX=width/w, scaleY=height/h;
 cairo_scale(cr, scaleX, scaleY);
 cairo_set_source_surface(cr, image, x/scaleX, y/scaleY);
 cairo_rectangle(cr, x/scaleX, y/scaleY, w, h);
 cairo_fill(cr);
 cairo_surface_destroy (image);
 cairo_restore(cr);
}

void cairotools_draw_round_node(cairo_t* cr, double cx, double cy, double radius, const char* text, const char* description)
{
 //circle
 cairo_move_to (cr, cx+radius, cy);
 cairo_arc (cr, cx, cy, radius, 0, 360);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);
 
 //text
 if(text!=0)
 {
  cairotools_show_text_center_aligned(cr, cx, cy, text);
 }
 //description
 if(description!=0)
 {
  cairotools_show_text_center_aligned(cr, cx, cy, description);
 }
};

void cairotools_draw_round_node(cairo_t* cr, double cx, double cy, double radius, const char* text)
{
 cairotools_draw_round_node (cr, cx, cy, radius, text, 0);
};

void cairotools_draw_round_node_connection(cairo_t* cr, double cx1, double cy1, double cx2, double cy2, double radius, const char* text)
{
 double dx = cx2-cx1;
 double dy = cy2-cy1;
 double sin = (cy2-cy1)/sqrt(dx*dx+dy*dy);
 double cos = (cx2-cx1)/sqrt(dx*dx+dy*dy);
 double x1 = cx1+radius*cos, y1 = cy1+radius*sin;
 double x2 = cx2-radius*cos, y2 = cy2-radius*sin;

 //line
 cairo_move_to(cr, x1, y1);
 cairo_line_to(cr, x2, y2);
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke (cr);

 //text
 if(text!=0)
 {  
  cairo_move_to (cr, x2-(x2-x1)/2, y2-(y2-y1)/2);
  cairo_set_source_rgb (cr, 0, 0, 0);
  cairo_show_text(cr, text);
 }
};


//class ChessBoard

void ChessBoard::Initialize()
{
 for(int i=0; i<n; ++i)
 {
  vector<bool> row;
  for(int j=0; j<n; ++j)
   row.push_back(false);
  chess.push_back(row);
 }
}

ostream& operator<<(ostream& os, const ChessBoard& chessBoard)
{
 for(int i=0; i<chessBoard.m; ++i)
 {
  for(int j=0; j<chessBoard.n; ++j)
  {
   os << chessBoard.chess[i][j] << ' ';
  }
  os << '\n';
 }
 return os;
}

void ChessBoard::Draw()
{
 //draw labels
 if(showLabel)
 {
  double cx, cy;
  cx = x-cellWidth/2;
  cy = y+cellWidth/2;
  for(int i=1; i<=m; ++i)
  {
   ostringstream oss;
   oss<<i;
   cairotools_show_text_center_aligned (cr, cx, cy, oss.str().c_str());
   cy+=cellWidth;
  }

  cx = x+cellWidth/2;
  cy = y-cellWidth/2;
  for(int j=1; j<=n; ++j)
  {
   ostringstream oss;
   oss<<j;
   cairotools_show_text_center_aligned (cr, cx, cy, oss.str().c_str());
   cx+=cellWidth;
  }
 }

 //draw rows
 double rowY1=y, rowY2=y+cellWidth*n;
 for(int i=0; i<=m; ++i)
 {
  cairo_move_to(cr, x+cellWidth*i, rowY1);
  cairo_line_to(cr, x+cellWidth*i, rowY2);
 }

 //draw columns
 double columnX1=x, columnX2=x+cellWidth*n;
 for(int j=0; j<=n; ++j)
 {
  cairo_move_to (cr, columnX1, y+cellWidth*j);
  cairo_line_to (cr, columnX2, y+cellWidth*j);
 }
 
 cairo_set_source_rgb (cr, 0, 0, 0);
 cairo_stroke(cr);

 //draw chess
 for(int i=0; i<m; ++i)
  for(int j=0; j<n; ++j)
  {
   if(chess[i][j])
    DrawChess (i, j);
  }
}

void ChessBoard::DrawChess(int row, int column)
{
 double cx = x+column*cellWidth+cellWidth/2;
 double cy = y+row*cellWidth+cellWidth/2;
 cairotools_draw_image_at_center (cr, "circle.png", cx, cy, cellWidth/2, cellWidth/2);
}

void ChessBoard::PutChess(int row, int column)
{
 chess[row][column] = true;
}

void ChessBoard::PutChess(vector<vector<bool> >& chess)
{
 for(int i=0; i<m; ++i)
  for(int j=0; j<n; ++j)
   this->chess[i][j] = chess[i][j];
}

void ChessBoard::RemoveChess(int row, int column)
{
 chess[row][column] = false;
}

void ChessBoard::Clear()
{
 for(int i=0; i<m; ++i)
  for(int j=0; j<n; ++j)
   chess[i][j] = false;
}


【main.cpp】

 InitCairo(800);

 ChessBoard board(cr, 8, 8, 30, 30, 40);
 board.PutChess(1, 1);
 board.Draw();

 CompleteCairo("test.png");


【注意】
以上代码需要在项目的根目录下面建立一个circle.png文件作为棋子使用。
默认的图片如下:



  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

kongdir

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值