【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");