Generating Pages and Sprite animation [Testing]

This commit is contained in:
Kushal K S V S 2017-08-24 04:08:34 -07:00
parent 637fb40ac9
commit 3a2869a929
14 changed files with 10778 additions and 116 deletions

View File

@ -13,20 +13,11 @@ CC = gcc
INCLUDE = -I $(includedir)/freetype2
LIBS = -lpng -lharfbuzz -lbz2 -ldl
DPI ?= 72
FT_TEST_RENDER_MODE ?= RGB
all: tests
tests: $(SRC_SPRITE) render_modes dpi
$(CC) $(CFLAGS) $(INCLUDE) -DDPI=$(DPI) -DFT_TEST_RENDER_MODE=$(FT_TEST_RENDER_MODE) -o $@ $(SRC_SPRITE) $(SRC_LIB) $(OBJS) $(LIBS)
tests: $(SRC_SPRITE)
$(CC) $(CFLAGS) $(INCLUDE) -o $@ $(SRC_SPRITE) $(SRC_LIB) $(OBJS) $(LIBS)
.PHONY: clean force
clean:
-rm -f *.o
render_modes: force
echo '$(FT_TEST_RENDER_MODE)' | cmp -s - $@ || echo '$(FT_TEST_RENDER_MODE)' > $@
dpi: force
echo '$(DPI)' | cmp -s - $@ || echo '$(DPI)' > $@

View File

@ -23,7 +23,7 @@ NOTE: One version of FreeType is referred as "base" version and the
-------------------------------------
Go to the "base" version's folder and compile the library
./configure
./configure --enable-shared --disable-static
make
Repeat step 2. for the "test" version as well.

View File

@ -289,7 +289,7 @@ int Generate_PNG (IMAGE *bitmap,
status = 0;
printf("Generated image %s\n", path );
printf("%s\n", path );
for (y = 0; y < bitmap->height; y++) {
png_free (png_ptr, row_pointers[y]);
}
@ -623,22 +623,18 @@ void Stitch(IMAGE* left, IMAGE* right, IMAGE* result){
}
/* This prints table-headers to a HTML file for the list-view page */
void Print_Head( FILE* fp, char* family, char* style, int size ){
void Print_Head( FILE* fp, char* fam, char* style, int size, int dpi){
printf(" *** Generating Images *** \n");
fprintf(fp,
"<html>\n\
<head>\n\
<title>\n\
Glyph_Diff\n\
</title>\n\
<script src=\"script.js\" type=\"text/javascript\"></script>\n\
<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n\
<script src=\"../../../../../scripts/top.js\" type=\"text/javascript\"></script>\n\
<link href=\"../../../../../styles/top.css\" rel=\"stylesheet\" type=\"text/css\" >\n\
</head>\n\
<body>\n\
<div class=\"freeze\">\n\
<h4>Font Family: %s</h4>\n\
<h4>Style: %s</h4>\n\
<p><b>%d</b>pt at <b>%d</b>ppi</p>\n\
</div>\n\
<table>\n\
<thead>\n\
<tr>\n\
@ -656,10 +652,7 @@ void Print_Head( FILE* fp, char* family, char* style, int size ){
</th>\n\
</tr>\n\
</thead>\n\
<tbody id=\"data\">\n", family,
style,
size,
DPI );
<tbody id=\"data\">\n" );
}
/* This prints a row to the HTML file for the list-view page. */
@ -670,7 +663,9 @@ void Print_Row( FILE* fp, int index, char* name, int diff )
<td>%04d</td>\n\
<td>%s</td>\n\
<td>%04d</td>\n\
<td id=\"image_row\"><img id=\"sprite\" src=\"images/%s.png\"></td>\n\
<td id=\"image_row\">\
<img id=\"sprite\" src=\"images/%s.png\" onclick=\"frame_2_source(this)\">\
</td>\n\
</tr>\n", index, name, diff, name);
}

View File

@ -85,4 +85,4 @@ int Image_Diff( IMAGE* base, IMAGE* test);
/* Print the row in list-view webpage */
void Print_Row( FILE* fp, int index, char* name, int diff );
/* Print the table-headers in list-view webpage */
void Print_Head( FILE* fp, char* family, char* style, int size );
void Print_Head( FILE* fp, char* fam, char* style, int size, int dpi);

View File

@ -1 +0,0 @@
The HTML files generated are in this directory

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html id="body">
<head>
<title>Detailed Comparison</title>
<script type="text/javascript" src ="scripts/jquery-3.2.1.js"></script>
<script type="text/javascript" src ="scripts/jquery.animateSprite.js"></script>
<script type="text/javascript" src ="scripts/top.js" ></script>
<link rel="stylesheet" type="text/css" href="styles/top.css">
</head>
<p id="demo"></p>
<div id="animation" class="animation"></div><br>
<button id="set_dim"onclick="set_dim()">SetDim</button>
<button id="start">Start</button>
<button id="play">Play</button>
<button id="stop">Stop</button>
<button id="changeFPS">Change FPS</button><br>
<script>
/* global $ */
var currentFps = 1;
var animationSettings = {
fps: currentFps,
loop: true,
autoplay: false,
animations: {
walkRight: [0, 3]
}
};
$(document).ready(function(){
$("#start").click(function(){
$('.animation').animateSprite(animationSettings);
var play = function(){
$('.animation').animateSprite('play');
}
$('#play').on('click', play);
$('#stop').on('click', function(){
$('.animation').animateSprite('stop');
});
$('#changeFPS').on('click', function(){
currentFps = (currentFps === 2) ? 1 : 2;
$('.animation').animateSprite('fps', currentFps);
});
$('body').on('keydown', function(ev){
if (ev.keyCode === 39){
goRight();
} else if (ev.keyCode === 37) {
goLeft();
}
console.log('ev', ev.keyCode);
});
});
});
</script>
</body>
</html>

View File

@ -1,2 +0,0 @@
This folder includes all the images generated

View File

@ -1,22 +0,0 @@
var people, asc1 = 1,asc2 = 1,asc3 = 1;
function sort_t(tbody, col, asc){
var rows = tbody.rows, rlen = rows.length, arr = new Array(), i, j, cells, clen;
// fill the array with values from the table
for(i = 0; i < rlen; i++){
cells = rows[i].cells;
clen = cells.length;
arr[i] = new Array();
for(j = 0; j < clen; j++){
arr[i][j] = cells[j].innerHTML;
}
}
// sort the array by the specified column number (col) and order (asc)
arr.sort(function(a, b){
return (a[col] == b[col]) ? 0 : ((a[col] > b[col]) ? asc : -1*asc);
});
for(i = 0; i < rlen; i++){
arr[i] = "<td>"+arr[i].join("</td><td>")+"</td>";
}
tbody.innerHTML = "<tr>"+arr.join("</tr><tr>")+"</tr>";
}

10253
tests/make_png/html/scripts/jquery-3.2.1.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
/*! jqueryanimatesprite - v1.3.5 - 2014-10-17
* http://blaiprat.github.io/jquery.animateSprite/
* Copyright (c) 2014 blai Pratdesaba; Licensed MIT */
(function ($, window, undefined) {
'use strict';
var init = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
// ASYNC
// If we don't specify the columns, we
// can discover using the background size
var discoverColumns = function (cb) {
var imageSrc = $this.css('background-image').replace(/url\((['"])?(.*?)\1\)/gi, '$2');
var image = new Image();
image.onload = function () {
var width = image.width,
height = image.height;
cb(width, height);
};
image.src = imageSrc;
};
if (!data) {
$this.data('animateSprite', {
settings: $.extend({
width: $this.width(),
height: $this.height(),
totalFrames: false,
columns: false,
fps: 12,
complete: function () {},
loop: false,
autoplay: true
}, options),
currentFrame: 0,
controlAnimation: function () {
var checkLoop = function (currentFrame, finalFrame) {
currentFrame++;
if (currentFrame >= finalFrame) {
if (this.settings.loop === true) {
currentFrame = 0;
data.controlTimer();
} else {
this.settings.complete();
}
} else {
data.controlTimer();
}
return currentFrame;
};
if (this.settings.animations === undefined) {
$this.animateSprite('frame', this.currentFrame);
this.currentFrame = checkLoop.call(this, this.currentFrame, this.settings.totalFrames);
} else {
if (this.currentAnimation === undefined) {
for (var k in this.settings.animations) {
this.currentAnimation = this.settings.animations[k];
break;
}
}
var newFrame = this.currentAnimation[this.currentFrame];
$this.animateSprite('frame', newFrame);
this.currentFrame = checkLoop.call(this, this.currentFrame, this.currentAnimation.length);
}
},
controlTimer: function () {
// duration overrides fps
var speed = 1000 / data.settings.fps;
if (data.settings.duration !== undefined) {
speed = data.settings.duration / data.settings.totalFrames;
}
data.interval = setTimeout(function () {
data.controlAnimation();
}, speed);
}
});
data = $this.data('animateSprite');
// Setting up columns and total frames
if (!data.settings.columns) {
// this is an async function
discoverColumns(function (width, height) {
// getting amount of columns
data.settings.columns = Math.round(width / data.settings.width);
// if totalframes are not specified
if (!data.settings.totalFrames) {
// total frames is columns times rows
var rows = Math.round(height / data.settings.height);
data.settings.totalFrames = data.settings.columns * rows;
}
if (data.settings.autoplay) {
data.controlTimer();
}
});
} else {
// if everything is already set up
// we start the interval
if (data.settings.autoplay) {
data.controlTimer();
}
}
}
});
};
var frame = function (frameNumber) {
// frame: number of the frame to be displayed
return this.each(function () {
if ($(this).data('animateSprite') !== undefined) {
var $this = $(this),
data = $this.data('animateSprite'),
row = Math.floor(frameNumber / data.settings.columns),
column = frameNumber % data.settings.columns;
$this.css('background-position', (-data.settings.width * column) + 'px ' + (-data.settings.height * row) + 'px');
}
});
};
var stop = function () {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
clearTimeout(data.interval);
});
};
var resume = function () {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
// always st'op animation to prevent overlapping intervals
$this.animateSprite('stopAnimation');
data.controlTimer();
});
};
var restart = function () {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
$this.animateSprite('stopAnimation');
data.currentFrame = 0;
data.controlTimer();
});
};
var play = function (animationName) {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
if (typeof animationName === 'string') {
$this.animateSprite('stopAnimation');
if (data.settings.animations[animationName] !== data.currentAnimation) {
data.currentFrame = 0;
data.currentAnimation = data.settings.animations[animationName];
}
data.controlTimer();
} else {
$this.animateSprite('stopAnimation');
data.controlTimer();
}
});
};
var fps = function (val) {
return this.each(function () {
var $this = $(this),
data = $this.data('animateSprite');
// data.fps
data.settings.fps = val;
});
};
var methods = {
init: init,
frame: frame,
stop: stop,
resume: resume,
restart: restart,
play: play,
stopAnimation: stop,
resumeAnimation: resume,
restartAnimation: restart,
fps: fps
};
$.fn.animateSprite = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || ! method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.animateSprite');
}
};
})(jQuery, window);

View File

@ -0,0 +1,82 @@
function change() {
var dpi = document.getElementById('dpi').value;
var font = document.getElementById('font').value;
var mode = document.getElementById('mode').value;
var size = document.getElementById('size').value;
var frame = document.getElementById('frame_1');
var string = "pages/"+dpi+"/"+font+"/"+mode+"/"+size+"/index.html";
frame.src = string;
}
var people, asc1 = 1,asc2 = 1,asc3 = 1;
function sort_t(tbody, col, asc){
var rows = tbody.rows, rlen = rows.length, arr = new Array(), i, j, cells, clen;
// fill the array with values from the table
for(i = 0; i < rlen; i++){
cells = rows[i].cells;
clen = cells.length;
arr[i] = new Array();
for(j = 0; j < clen; j++){
arr[i][j] = cells[j].innerHTML;
}
}
// sort the array by the specified column number (col) and order (asc)
arr.sort(function(a, b){
return (a[col] == b[col]) ? 0 : ((a[col] > b[col]) ? asc : -1*asc);
});
for(i = 0; i < rlen; i++){
arr[i] = "<td>"+arr[i].join("</td><td>")+"</timaged>";
}
tbody.innerHTML = "<tr>"+arr.join("</tr><tr>")+"</tr>";
}
function frame_2_source(image){
var path = "url("+image.src+")";
var fr_2 = parent.frame_2.document;
var div = fr_2.getElementById('animation');
div.style.backgroundImage=path;
}
function set_dim() {
var imageSrc = document
.getElementById('animation')
.style
.backgroundImage
.replace(/url\((['"])?(.*?)\1\)/gi, '$2')
.split(',')[0];
var image = new Image();
image.src = imageSrc;
var src_w = image.width;
var src_h = image.height;
var win_w = window.innerWidth;
var win_h = window.innerHeight-60;
var r_w = (win_w/(src_w/4)).toString();
r_w = parseInt(r_w);
var r_h = (win_h/src_h).toString();
r_h = parseInt(r_h);
var div_w = 0;
var div_h = 0;
if (r_w > r_h)
{
div_w = src_w * r_h;
div_h = src_h * r_h;
} else {
div_w = src_w * r_w;
div_h = src_h * r_w;
}
document.getElementById('animation').style.width= div_w/4 + "px";
document.getElementById('animation').style.height= div_h + "px";
}

View File

@ -1,8 +1,3 @@
.freeze{
height: 50px;
line-height: 60%;
padding: 4px 16px;
}
#sprite {
image-rendering: optimizeSpeed; /* STOP SMOOTHING, GIVE ME SPEED */
image-rendering: -moz-crisp-edges; /* Firefox */
@ -11,14 +6,13 @@
image-rendering: pixelated; /* Chrome */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
width: 50%;
width: 70%;
height: auto;
}
table {
border-collapse: collapse;
border: none;
position: relative;
top: 60px;
}
th,
td {
@ -32,7 +26,40 @@ th {
background-color: #C8C8C8;
cursor: pointer;
}
#hash{
font-size: 12px;
/*Top Page styling begins*/
#frame_1{
width:49%;
height:500px;
align-self: right;
}
#frame_2{
width:49%;
height:500px;
align-self: left;
}
.select {
font-family: "Courier New", Courier, monospace;
font-size: 16px;
text-align: left;
}
.animation {
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: pixelated;
image-rendering: optimize-contrast;
-ms-interpolation-mode: nearest-neighbor;
margin: auto;
display: block;
background: url("braceleft.png");
background-repeat: no-repeat;
background-size: cover;
width: 120px;
height: 130px;
}

View File

@ -2,10 +2,9 @@
int main(int argc, char const *argv[])
{
if(argc != 5)
if(argc != 7)
{
printf("Usage: ./tests <base .so> <test .so>\
<fnt_file> <pt_size>\n");
printf("Not enough arguments. Refer README\n");
return 0;
}
@ -15,6 +14,8 @@ int main(int argc, char const *argv[])
const char* test_version;
const char* font_file;
int size;
int render_mode;
int dpi;
int load_flag; /* FT_LOAD_XXX */
int render_flag; /* FT_RENDER_MODE_XXX */
@ -25,6 +26,8 @@ int main(int argc, char const *argv[])
font_file = argv[3];
size = atoi(argv[4]);
render_mode = atoi(argv[5]);
dpi = atoi(argv[6]);
FT_Library base_library;
FT_Face base_face;
@ -41,7 +44,7 @@ int main(int argc, char const *argv[])
FT_Error error;
int alignment = 4;
char * output_file_name = ( char * )calloc(50,sizeof(char));
char * output_file_name = ( char * )calloc(100,sizeof(char));
IMAGE* base_png = (IMAGE*)malloc(sizeof(IMAGE));
IMAGE* test_png = (IMAGE*)malloc(sizeof(IMAGE));
@ -208,7 +211,7 @@ int main(int argc, char const *argv[])
/*******************************************************************/
switch ( FT_TEST_RENDER_MODE ) {
switch ( render_mode ) {
case 0: render_flag = FT_RENDER_MODE_MONO;
load_flag = FT_LOAD_MONOCHROME;
target_flag = FT_LOAD_TARGET_MONO;
@ -255,7 +258,7 @@ int main(int argc, char const *argv[])
exit(1);
}
if (FT_TEST_RENDER_MODE > 1 )
if (render_mode > 1 )
{
error = Base_Library_SetLcdFilter( base_library,
FT_LCD_FILTER_DEFAULT );
@ -291,7 +294,7 @@ int main(int argc, char const *argv[])
error = Base_Set_Char_Size( base_face,
size * 64,
0,
DPI,
dpi,
0 );
if(error){
printf("Error setting character size\n");
@ -300,7 +303,7 @@ int main(int argc, char const *argv[])
error = Test_Set_Char_Size( test_face,
size * 64,
0,
DPI,
dpi,
0 );
if(error){
printf("Error setting character size\n");
@ -310,20 +313,12 @@ int main(int argc, char const *argv[])
base_slot = base_face->glyph;
test_slot = test_face->glyph;
/* If folders aren't there, create folders */
struct stat st = {0};
if (stat("./html/", &st) == -1) {
mkdir("./html/", 0777);
}
if (stat("./html/images/", &st) == -1) {
mkdir("./html/images/", 0777);
}
/* Initialising file pointer for the list-view*/
FILE* fp = fopen("html/index.html","w");
Print_Head(fp,base_face->family_name, base_face->style_name, size);
sprintf( output_file_name, "./html/pages/%d/%s/%d/%d/index.html",dpi, font_file, render_mode, size );
FILE* fp = fopen(output_file_name,"w");
Print_Head(fp,base_face->family_name,base_face->style_name,size,dpi);
/* Need to write code to check the values in FT_Face and compare */
for ( i = 0; i < base_face->num_glyphs; ++i)
@ -369,8 +364,8 @@ int main(int argc, char const *argv[])
test_murmur = Generate_Hash_x64_128(test_bitmap,test_murmur);
Is_Different = Compare_Hash(base_murmur, test_murmur);
/* To convert 1-bit monochrome to 8-bit bitmap */
/* because we need 8-bit colour to generate images */
/* To convert 1-bit monochrome to 8-bit bitmap */
/* because we need 8-bit colour to generate images */
Base_Bitmap_Init( &base_target );
Test_Bitmap_Init( &test_target );
@ -395,15 +390,15 @@ int main(int argc, char const *argv[])
{
total_count++;
pixel_diff = 0; /* Difference metric*/
if (FT_TEST_RENDER_MODE == 0)
if (render_mode == 0)
{ /* If monochrome, take the converted image*/
Make_PNG( &base_target, base_png, i, FT_TEST_RENDER_MODE );
Make_PNG( &test_target, test_png, i, FT_TEST_RENDER_MODE );
Make_PNG( &base_target, base_png, i, render_mode );
Make_PNG( &test_target, test_png, i, render_mode );
}else{
Make_PNG( base_bitmap, base_png, i, FT_TEST_RENDER_MODE );
Make_PNG( test_bitmap, test_png, i, FT_TEST_RENDER_MODE );
Make_PNG( base_bitmap, base_png, i, render_mode );
Make_PNG( test_bitmap, test_png, i, render_mode );
}
/* Aligning images and appending rows */
if (base_png->height < test_png->height)
@ -440,15 +435,15 @@ int main(int argc, char const *argv[])
50 );
}
sprintf( output_file_name, "./html/images/%s.png", glyph_name );
sprintf( output_file_name, "./html/pages/%d/%s/%d/%d/images/%s.png",dpi, font_file, render_mode, size, glyph_name );
Generate_PNG ( output, output_file_name, FT_TEST_RENDER_MODE );
Generate_PNG ( output, output_file_name, render_mode );
/* To print table row to HTML file */
Print_Row(fp,i,glyph_name,pixel_diff );
}
}
printf("Total %ld\nFaulty %d\n",base_face->num_glyphs,
total_count );
printf("Total : %ld\nFaulty : %d\n",base_face->num_glyphs,
total_count );
/* HTML footer */
fprintf(fp,
"</tbody>\n\

View File

@ -1,26 +1,80 @@
rm -f ./html/images/*
BASE_DIR=$1
TEST_DIR=../..
BASE_LIB=$BASE_DIR/objs/.libs/libfreetype.so
TEST_LIB=$TEST_DIR/objs/.libs/libfreetype.so
FONT_FILE=$2
PT_SIZE=$3
echo
echo "*** Generating Images ***"
echo
./tests $BASE_LIB $TEST_LIB $FONT_FILE $PT_SIZE
echo "Font: " $FONT_FILE
echo "Size: " $PT_SIZE
# Removing the current DPI and Render Mode settings
# for future compilations.
rm -f ./render_modes ./dpi
rm -rf ./html/pages
rm -f ./html/top.html
#####################################################################
FT_TEST_TEST_DIR=../..
FT_TEST_BASE_LIB=$FT_TEST_BASE_DIR/objs/.libs/libfreetype.so
FT_TEST_TEST_LIB=$FT_TEST_TEST_DIR/objs/.libs/libfreetype.so
#####################################################################
mkdir ./html/pages
touch ./html/top.html;
#####################################################################
echo '
<!DOCTYPE html>
<head>
<script type="text/javascript" src ="scripts/jquery-3.2.1.js"></script>
<script type="text/javascript" src ="scripts/jquery.animateSprite.js"></script>
<script type="text/javascript" src ="scripts/top.js" ></script>
<link rel="stylesheet" type="text/css" href="styles/top.css">
</head>
<html>
<body>
<iframe id="frame_1" name="frame_1" src="" ></iframe>
<iframe id="frame_2" name="frame_2" src="diff.html" ></iframe>
<div class="select">
'>./html/top.html;
#####################################################################
for i in $FT_TEST_DPI; do
mkdir ./html/pages/$i
for j in $FT_TEST_FONT_FILE; do
mkdir ./html/pages/$i/$j
for k in $FT_TEST_RENDER_MODE; do
mkdir ./html/pages/$i/$j/$k
for l in $FT_TEST_PT_SIZE; do
mkdir ./html/pages/$i/$j/$k/$l
mkdir ./html/pages/$i/$j/$k/$l/images
./tests $FT_TEST_BASE_LIB $FT_TEST_TEST_LIB $j $l $k $i
done
done
done
done
#####################################################################
echo '<label>DPI&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp:<select name="dpi" id="dpi" onchange="change()">'>>./html/top.html;
for i in $FT_TEST_DPI; do
echo " <option value= $i > $i </option>">>./html/top.html;
done
echo '</select>
</label><br>'>>./html/top.html;
#####################################################################
echo '<label>Font&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp:<select name="font" id="font" onchange="change()">'>>./html/top.html;
for i in $FT_TEST_FONT_FILE; do
echo " <option value= $i > $i </option>">>./html/top.html;
done
echo '</select>
</label><br>'>>./html/top.html;
#####################################################################
echo '<label>Render Mode:<select name="mode" id="mode" onchange="change()">'>>./html/top.html;
for i in $FT_TEST_RENDER_MODE; do
echo " <option value= $i > $i </option>">>./html/top.html;
done
echo '</select>
</label><br>'>>./html/top.html;
#####################################################################
echo '<label>Size&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp:<select name="size" id="size" onchange="change()">'>>./html/top.html;
for i in $FT_TEST_PT_SIZE; do
echo " <option value= $i > $i </option>">>./html/top.html;
done
echo '</select>
</label><br>'>>./html/top.html;
#####################################################################
echo '</div>
</body>
</html>'>>./html/top.html;
#####################################################################
echo "Font : " $FT_TEST_FONT_FILE
echo "Size : " $FT_TEST_PT_SIZE
echo "Render_Mode: " $FT_TEST_RENDER_MODE
echo "DPI : " $FT_TEST_DPI