00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "fontfactoryttf_qws.h"
00022
00023 #include <opie2/odebug.h>
00024 using namespace Opie::Core;
00025
00026 #ifdef QT_NO_FREETYPE
00027
00028 #include "qfontdata_p.h"
00029 #include <string.h>
00030 #include <stdio.h>
00031
00032 #define FLOOR(x) ((x) & -64)
00033 #define CEIL(x) (((x)+63) & -64)
00034 #define TRUNC(x) ((x) >> 6)
00035
00036
00037 extern "C" {
00038
00039 #include <ft2build.h>
00040 #include FT_FREETYPE_H
00041
00042 #include <freetype/freetype.h>
00043 #include <freetype/ftglyph.h>
00044 #include <freetype/ftoutln.h>
00045 #include <freetype/ftbbox.h>
00046 }
00047
00048 class QDiskFontFT : public QDiskFontPrivate {
00049 public:
00050 FT_Face face;
00051 };
00052
00053 class QRenderedFontFT : public QRenderedFont {
00054 public:
00055 QRenderedFontFT(QDiskFont* f, const QFontDef &d) :
00056 QRenderedFont(f,d)
00057 {
00058 QDiskFontFT *df = (QDiskFontFT*)(f->p);
00059 myface=df->face;
00060 selectThisSize();
00061
00062
00063
00064 fascent=CEIL(myface->size->metrics.ascender)/64;
00065 fdescent=-FLOOR(myface->size->metrics.descender)/64-1;
00066 fmaxwidth=CEIL(myface->size->metrics.max_advance)/64;
00067 fleading=CEIL(myface->size->metrics.height)/64
00068 - fascent - fdescent + 1;
00069
00070
00071 funderlinepos = ptsize/200+1;
00072 funderlinewidth = ptsize/200+1;
00073 }
00074
00075 ~QRenderedFontFT()
00076 {
00077
00078
00079 }
00080
00081 bool unicode(int & i) const
00082 {
00083 int ret;
00084
00085 FT_Face theface=myface;
00086
00087 ret=FT_Get_Char_Index(theface,i);
00088
00089 if (ret==0) {
00090 return FALSE;
00091 } else {
00092 i=ret;
00093 return TRUE;
00094 }
00095 }
00096
00097 bool inFont(QChar ch) const
00098 {
00099 int index = ch.unicode();
00100 return unicode(index);
00101 }
00102
00103 QGlyph render(QChar ch)
00104 {
00105 selectThisSize();
00106
00107 int index = ch.unicode();
00108 if ( !unicode(index) )
00109 index = 0;
00110 QGlyph result;
00111
00112 FT_Error err;
00113
00114 err=FT_Load_Glyph(myface,index,FT_LOAD_DEFAULT);
00115 if(err)
00116 ofatal << "Load glyph error " << err << "" << oendl;
00117
00118 int width=0,height=0,pitch=0,size=0;
00119 FT_Glyph glyph;
00120 err=FT_Get_Glyph( myface->glyph, &glyph );
00121 if(err)
00122 ofatal << "Get glyph error " << err << "" << oendl;
00123
00124 FT_BBox bbox;
00125 FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_gridfit, &bbox);
00126
00127 FT_Vector origin;
00128 origin.x = -bbox.xMin;
00129 origin.y = -bbox.yMin;
00130
00131 if ( FT_IS_SCALABLE(myface) ) {
00132 err=FT_Glyph_To_Bitmap(&glyph,
00133 smooth ? ft_render_mode_normal : ft_render_mode_mono,
00134 &origin, 1);
00135 if(err)
00136 owarn << "Get bitmap error " << err << "" << oendl;
00137 }
00138
00139 if ( !err ) {
00140 FT_Bitmap bm = ((FT_BitmapGlyph)glyph)->bitmap;
00141 pitch = bm.pitch;
00142 size=pitch*bm.rows;
00143 result.data = new uchar[size];
00144 width=bm.width;
00145 height=bm.rows;
00146 if ( size ) {
00147 memcpy( result.data, bm.buffer, size );
00148 } else {
00149 result.data = new uchar[0];
00150 }
00151 } else {
00152 result.data = new uchar[0];
00153 }
00154
00155 result.metrics = new QGlyphMetrics;
00156 memset((char*)result.metrics, 0, sizeof(QGlyphMetrics));
00157 result.metrics->bearingx=myface->glyph->metrics.horiBearingX/64;
00158 result.metrics->advance=myface->glyph->metrics.horiAdvance/64;
00159 result.metrics->bearingy=myface->glyph->metrics.horiBearingY/64;
00160
00161 result.metrics->linestep=pitch;
00162 result.metrics->width=width;
00163 result.metrics->height=height;
00164
00165
00166
00167
00168
00169
00170
00171 FT_Done_Glyph( glyph );
00172
00173 return result;
00174 }
00175
00176 FT_Face myface;
00177
00178 private:
00179 void selectThisSize()
00180 {
00181 int psize=(ptsize<<6)/10;
00182
00183
00184 const int dpi=72;
00185 FT_Error err;
00186 err=FT_Set_Char_Size(myface, psize,psize,dpi,dpi);
00187 if (err) {
00188 if (FT_IS_SCALABLE(myface) ) {
00189 owarn << "Set char size error " << err << " for size " << ptsize << "" << oendl;
00190 } else {
00191 int best=-1;
00192 int bdh=99;
00193 for (int i=0; i<myface->num_fixed_sizes; i++) {
00194 FT_Bitmap_Size& sz=myface->available_sizes[i];
00195 int dh = sz.height - ptsize*dpi/72/10;
00196 dh = QABS(dh);
00197 if ( dh < bdh ) {
00198 bdh=dh;
00199 best=i;
00200 }
00201 }
00202 if ( best >= 0 )
00203 err=FT_Set_Pixel_Sizes(myface,
00204 myface->available_sizes[best].width,
00205 myface->available_sizes[best].height);
00206 if ( err )
00207 owarn << "Set char size error " << err << " for size " << ptsize << "" << oendl;
00208 }
00209 }
00210 }
00211 };
00212
00213 QFontFactoryFT::QFontFactoryFT()
00214 {
00215 FT_Error err;
00216 err=FT_Init_FreeType(&library);
00217 if(err) {
00218 ofatal << "Couldn't initialise Freetype library" << oendl;
00219 }
00220 }
00221
00222 QFontFactoryFT::~QFontFactoryFT()
00223 {
00224 }
00225
00226 QString QFontFactoryFT::name()
00227 {
00228 return "FT";
00229 }
00230
00231 QRenderedFont * QFontFactoryFT::get(const QFontDef & f,QDiskFont * f2)
00232 {
00233 return new QRenderedFontFT(f2, f);
00234 }
00235
00236 void QFontFactoryFT::load(QDiskFont * qdf) const
00237 {
00238 if(qdf->loaded)
00239 return;
00240 QDiskFontFT *f = new QDiskFontFT;
00241 qdf->p=f;
00242 FT_Error err;
00243 err=FT_New_Face(library,qdf->file.ascii(),0,&(f->face));
00244 if(err) {
00245 ofatal << "Error " << err << " opening face" << oendl;
00246 }
00247 qdf->loaded=true;
00248 }
00249
00250
00251 #endif // QT_NO_FREETYPE