e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
7554d91998-10-31Mirar (Pontus Hagland)  #include "config.h" #include "global.h"
51ef5c2002-10-21Marcus Comstedt #include "module.h"
7554d91998-10-31Mirar (Pontus Hagland)  #ifdef HAVE_LIBTTF
b421242000-01-17Henrik Grubbström (Grubba) #if defined(HAVE_FREETYPE_FREETYPE_H) && defined(HAVE_FREETYPE_FTXKERN_H) #include <freetype/freetype.h> #include <freetype/ftxkern.h> #else /* !HAVE_FREETYPE_FREETYPE_H || !HAVE_FREETYPE_FTXKERN_H */
7554d91998-10-31Mirar (Pontus Hagland) #include <freetype.h>
ddeb981998-11-01Per Hedbor #include <ftxkern.h>
b421242000-01-17Henrik Grubbström (Grubba)  #endif /* HAVE_FREETYPE_FREETYPE_H && HAVE_FREETYPE_FTXKERN_H */
7554d91998-10-31Mirar (Pontus Hagland) #endif /* HAVE_LIBTTF */ #include "pike_macros.h" #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "threads.h" #include "array.h" #include "mapping.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
7554d91998-10-31Mirar (Pontus Hagland) #include "stralloc.h" #include "builtin_functions.h"
132f0d2000-08-13Henrik Grubbström (Grubba) #include "operators.h"
7554d91998-10-31Mirar (Pontus Hagland)  #ifdef HAVE_LIBTTF #include "../Image/image.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
7554d91998-10-31Mirar (Pontus Hagland) #ifdef DYNAMIC_MODULE static struct program *image_program=NULL; #else
26815d2000-02-05Per Hedbor extern struct program *image_program;
7554d91998-10-31Mirar (Pontus Hagland) /* Image module is probably linked static too. */ #endif static TT_Engine engine; #endif /* HAVE_LIBTTF */
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
7554d91998-10-31Mirar (Pontus Hagland) static struct pike_string *param_baseline; static struct pike_string *param_quality; #ifdef HAVE_LIBTTF /* **! module Image **! submodule TTF **!
26815d2000-02-05Per Hedbor **! This module adds TTF (Truetype font) capability **! to the Image module.
7554d91998-10-31Mirar (Pontus Hagland) **! **! note **! This module needs the <tt>libttf</tt> "Freetype" library **! */ void my_tt_error(char *where,char *extra,int err) { char *errc="Unknown"; if (err==TT_Err_Invalid_Face_Handle) errc="TT_Err_Invalid_Face_Handle"; else if (err==TT_Err_Invalid_Instance_Handle) errc="TT_Err_Invalid_Instance_Handle"; else if (err==TT_Err_Invalid_Glyph_Handle) errc="TT_Err_Invalid_Glyph_Handle"; else if (err==TT_Err_Invalid_CharMap_Handle) errc="TT_Err_Invalid_CharMap_Handle"; else if (err==TT_Err_Invalid_Result_Address) errc="TT_Err_Invalid_Result_Address"; else if (err==TT_Err_Invalid_Glyph_Index) errc="TT_Err_Invalid_Glyph_Index"; else if (err==TT_Err_Invalid_Argument) errc="TT_Err_Invalid_Argument"; else if (err==TT_Err_Could_Not_Open_File) errc="TT_Err_Could_Not_Open_File"; else if (err==TT_Err_File_Is_Not_Collection) errc="TT_Err_File_Is_Not_Collection"; else if (err==TT_Err_Table_Missing) errc="TT_Err_Table_Missing"; else if (err==TT_Err_Invalid_Horiz_Metrics) errc="TT_Err_Invalid_Horiz_Metrics"; else if (err==TT_Err_Invalid_CharMap_Format) errc="TT_Err_Invalid_CharMap_Format"; else if (err==TT_Err_Invalid_PPem) errc="TT_Err_Invalid_PPem"; else if (err==TT_Err_Invalid_File_Format) errc="TT_Err_Invalid_File_Format"; else if (err==TT_Err_Invalid_Engine) errc="TT_Err_Invalid_Engine"; else if (err==TT_Err_Too_Many_Extensions) errc="TT_Err_Too_Many_Extensions"; else if (err==TT_Err_Extensions_Unsupported) errc="TT_Err_Extensions_Unsupported"; else if (err==TT_Err_Invalid_Extension_Id) errc="TT_Err_Invalid_Extension_Id"; else if (err==TT_Err_Max_Profile_Missing) errc="TT_Err_Max_Profile_Missing"; else if (err==TT_Err_Header_Table_Missing) errc="TT_Err_Header_Table_Missing"; else if (err==TT_Err_Horiz_Header_Missing) errc="TT_Err_Horiz_Header_Missing"; else if (err==TT_Err_Locations_Missing) errc="TT_Err_Locations_Missing"; else if (err==TT_Err_Name_Table_Missing) errc="TT_Err_Name_Table_Missing"; else if (err==TT_Err_CMap_Table_Missing) errc="TT_Err_CMap_Table_Missing"; else if (err==TT_Err_Hmtx_Table_Missing) errc="TT_Err_Hmtx_Table_Missing"; else if (err==TT_Err_OS2_Table_Missing) errc="TT_Err_OS2_Table_Missing"; else if (err==TT_Err_Post_Table_Missing) errc="TT_Err_Post_Table_Missing"; else if (err==TT_Err_Out_Of_Memory) errc="TT_Err_Out_Of_Memory"; else if (err==TT_Err_Invalid_File_Offset) errc="TT_Err_Invalid_File_Offset"; else if (err==TT_Err_Invalid_File_Read) errc="TT_Err_Invalid_File_Read"; else if (err==TT_Err_Invalid_Frame_Access) errc="TT_Err_Invalid_Frame_Access"; else if (err==TT_Err_Too_Many_Points) errc="TT_Err_Too_Many_Points"; else if (err==TT_Err_Too_Many_Contours) errc="TT_Err_Too_Many_Contours"; else if (err==TT_Err_Invalid_Composite) errc="TT_Err_Invalid_Composite"; else if (err==TT_Err_Too_Many_Ins) errc="TT_Err_Too_Many_Ins"; else if (err==TT_Err_Invalid_Opcode) errc="TT_Err_Invalid_Opcode"; else if (err==TT_Err_Too_Few_Arguments) errc="TT_Err_Too_Few_Arguments"; else if (err==TT_Err_Stack_Overflow) errc="TT_Err_Stack_Overflow"; else if (err==TT_Err_Code_Overflow) errc="TT_Err_Code_Overflow"; else if (err==TT_Err_Bad_Argument) errc="TT_Err_Bad_Argument"; else if (err==TT_Err_Divide_By_Zero) errc="TT_Err_Divide_By_Zero"; else if (err==TT_Err_Storage_Overflow) errc="TT_Err_Storage_Overflow"; else if (err==TT_Err_Cvt_Overflow) errc="TT_Err_Cvt_Overflow"; else if (err==TT_Err_Invalid_Reference) errc="TT_Err_Invalid_Reference"; else if (err==TT_Err_Invalid_Distance) errc="TT_Err_Invalid_Distance"; else if (err==TT_Err_Interpolate_Twilight) errc="TT_Err_Interpolate_Twilight"; else if (err==TT_Err_Debug_OpCode) errc="TT_Err_Debug_OpCode"; else if (err==TT_Err_ENDF_In_Exec_Stream) errc="TT_Err_ENDF_In_Exec_Stream"; else if (err==TT_Err_Out_Of_CodeRanges) errc="TT_Err_Out_Of_CodeRanges"; else if (err==TT_Err_Nested_DEFS) errc="TT_Err_Nested_DEFS"; else if (err==TT_Err_Invalid_CodeRange) errc="TT_Err_Invalid_CodeRange"; else if (err==TT_Err_Invalid_Displacement) errc="TT_Err_Invalid_Displacement"; else if (err==TT_Err_Nested_Frame_Access) errc="TT_Err_Nested_Frame_Access"; else if (err==TT_Err_Invalid_Cache_List) errc="TT_Err_Invalid_Cache_List"; else if (err==TT_Err_Could_Not_Find_Context) errc="TT_Err_Could_Not_Find_Context"; else if (err==TT_Err_Unlisted_Object) errc="TT_Err_Unlisted_Object"; else if (err==TT_Err_Raster_Pool_Overflow) errc="TT_Err_Raster_Pool_Overflow"; else if (err==TT_Err_Raster_Negative_Height) errc="TT_Err_Raster_Negative_Height"; else if (err==TT_Err_Raster_Invalid_Value) errc="TT_Err_Raster_Invalid_Value"; else if (err==TT_Err_Raster_Not_Initialized) errc="TT_Err_Raster_Not_Initialized";
a4a1722000-12-05Per Hedbor  Pike_error("%s: %sFreeType error 0x%03x (%s)\n",
7554d91998-10-31Mirar (Pontus Hagland)  where,extra,err,errc); } /* **! method object `()(string filename) **! method object `()(string filename,mapping options) **! **! Makes a new TTF Face object. **! **! returns 0 if failed. **! **! arg string filename **! The filename of the <tt>TTF</tt> font or the <tt>TTC</tt> **! font collection. **! **! arg mapping options **! <pre> **! advanced options: **! "face":int **! If opening a font collection, '<tt>.TTC</tt>', **! this is used to get other fonts than the first. **! </pre> **! */ struct image_ttf_face_struct { TT_Face face; }; struct image_ttf_faceinstance_struct { TT_Instance instance; struct object *faceobj; int load_flags; int baseline,height; /* "baseline" position */ int trans; /* translation of position (ypos) in 26.6*/ }; static struct program *image_ttf_face_program=NULL; static struct program *image_ttf_faceinstance_program=NULL; static void image_ttf_make(INT32 args) {
ddeb981998-11-01Per Hedbor  int col=0, i=0;
7554d91998-10-31Mirar (Pontus Hagland)  struct object *o; TT_Error res; TT_Face face;
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF(): illegal argument 1\n");
7554d91998-10-31Mirar (Pontus Hagland)  res=TT_Open_Collection(engine, sp[-args].u.string->str, col, &face); if (res) my_tt_error("Image.TTF()","",res);
f258372000-09-08Henrik Grubbström (Grubba)  while(! TT_Load_Kerning_Table( face, (TT_UShort)(i++) ) );
7554d91998-10-31Mirar (Pontus Hagland)  pop_n_elems(args); o=clone_object(image_ttf_face_program,0); ((struct image_ttf_face_struct*)o->storage)->face=face; push_object(o); } /* **! class Face
26815d2000-02-05Per Hedbor **!
7554d91998-10-31Mirar (Pontus Hagland) **! This represents instances of TTF Faces. */
39221e2000-07-07Henrik Grubbström (Grubba) #define THISOBJ (Pike_fp->current_object)
cdac262014-12-06Bill Welliver #define THISf ((struct image_ttf_face_struct *)get_storage(THISOBJ,image_ttf_face_program)) #define THISi ((struct image_ttf_faceinstance_struct *)get_storage(THISOBJ,image_ttf_faceinstance_program))
7554d91998-10-31Mirar (Pontus Hagland) 
e13b5e2000-02-06Henrik Grubbström (Grubba) static void image_ttf_face_exit(struct object *o)
7554d91998-10-31Mirar (Pontus Hagland) {
c1c1cd2001-05-24David Hedbor  if(THISf) TT_Close_Face(THISf->face);
7554d91998-10-31Mirar (Pontus Hagland) }
e13b5e2000-02-06Henrik Grubbström (Grubba) static void image_ttf_faceinstance_exit(struct object *o)
7554d91998-10-31Mirar (Pontus Hagland) {
c1c1cd2001-05-24David Hedbor  if (THISi) { if(THISi->faceobj->prog)
eb9cfc1999-11-23Martin Stjernholm  TT_Done_Instance(THISi->instance);
c1c1cd2001-05-24David Hedbor  free_object(THISi->faceobj); }
7554d91998-10-31Mirar (Pontus Hagland) }
362bfa1999-06-01Marcus Comstedt #ifdef TTF_DEBUG_INFO
7554d91998-10-31Mirar (Pontus Hagland) /* **! method mapping properties() **! This gives back a structure of the face's properties. **! Most of this stuff is information you can skip. **! **! The most interesting item to look at may be **! <tt>->num_Faces</tt>, which describes the number of faces **! in a <tt>.TTC</tt> font collection.
26815d2000-02-05Per Hedbor **!
7554d91998-10-31Mirar (Pontus Hagland) **! returns a mapping of a lot of properties */ static void image_ttf_face_properties(INT32 args) { int res; TT_Face_Properties prop; pop_n_elems(args); res=TT_Get_Face_Properties(THISf->face,&prop); if (res) my_tt_error("Image.TTF.Face->properties()","",res);
26815d2000-02-05Per Hedbor 
5e9fc02015-08-18Per Hedbor  push_static_text("num_Glyphs"); push_int(prop.num_Glyphs); push_static_text("max_Points"); push_int(prop.max_Points); push_static_text("max_Contours"); push_int(prop.max_Contours); push_static_text("num_Faces"); push_int(prop.num_Faces);
7554d91998-10-31Mirar (Pontus Hagland) 
5e9fc02015-08-18Per Hedbor  push_static_text("header");
7554d91998-10-31Mirar (Pontus Hagland)  if (prop.header) {
5e9fc02015-08-18Per Hedbor  push_static_text("Table_Version"); push_int(prop.header->Table_Version); push_static_text("Font_Revision"); push_int(prop.header->Font_Revision); push_static_text("CheckSum_Adjust"); push_int(prop.header->CheckSum_Adjust); push_static_text("Magic_Number"); push_int(prop.header->Magic_Number); push_static_text("Flags"); push_int(prop.header->Flags); push_static_text("Units_Per_EM"); push_int(prop.header->Units_Per_EM); push_static_text("Created");
7554d91998-10-31Mirar (Pontus Hagland)  push_int(prop.header->Created[0]); push_int(prop.header->Created[1]); f_aggregate(2);
5e9fc02015-08-18Per Hedbor  push_static_text("Modified");
7554d91998-10-31Mirar (Pontus Hagland)  push_int(prop.header->Modified[0]); push_int(prop.header->Modified[1]); f_aggregate(2);
5e9fc02015-08-18Per Hedbor  push_static_text("xMin"); push_int(prop.header->xMin); push_static_text("yMin"); push_int(prop.header->yMin); push_static_text("xMax"); push_int(prop.header->xMax); push_static_text("yMax"); push_int(prop.header->yMax); push_static_text("Mac_Style"); push_int(prop.header->Mac_Style); push_static_text("Lowest_Rec_PPEM"); push_int(prop.header->Lowest_Rec_PPEM); push_static_text("Font_Direction"); push_int(prop.header->Font_Direction); push_static_text("Index_To_Loc_Format");
7554d91998-10-31Mirar (Pontus Hagland)  push_int(prop.header->Index_To_Loc_Format);
5e9fc02015-08-18Per Hedbor  push_static_text("Glyph_Data_Format");
7554d91998-10-31Mirar (Pontus Hagland)  push_int(prop.header->Glyph_Data_Format); f_aggregate_mapping(17*2); } else push_int(0);
5e9fc02015-08-18Per Hedbor  push_static_text("horizontal");
7554d91998-10-31Mirar (Pontus Hagland)  if (prop.horizontal) {
5e9fc02015-08-18Per Hedbor  push_static_text("Version"); push_int(prop.horizontal->Version); push_static_text("Ascender"); push_int(prop.horizontal->Ascender); push_static_text("Descender"); push_int(prop.horizontal->Descender); push_static_text("Line_Gap"); push_int(prop.horizontal->Line_Gap); push_static_text("advance_Width_Max"); push_int(prop.horizontal->advance_Width_Max); push_static_text("min_Left_Side_Bearing"); push_int(prop.horizontal->min_Left_Side_Bearing); push_static_text("min_Right_Side_Bearing"); push_int(prop.horizontal->min_Right_Side_Bearing); push_static_text("xMax_Extent"); push_int(prop.horizontal->xMax_Extent); push_static_text("caret_Slope_Rise"); push_int(prop.horizontal->caret_Slope_Rise); push_static_text("caret_Slope_Run"); push_int(prop.horizontal->caret_Slope_Run); push_static_text("metric_Data_Format"); push_int(prop.horizontal->metric_Data_Format); push_static_text("number_Of_HMetrics"); push_int(prop.horizontal->number_Of_HMetrics);
7554d91998-10-31Mirar (Pontus Hagland)  f_aggregate_mapping(13*2); } else push_int(0);
26815d2000-02-05Per Hedbor 
5e9fc02015-08-18Per Hedbor  push_static_text("os2");
7554d91998-10-31Mirar (Pontus Hagland)  if (prop.os2) {
5e9fc02015-08-18Per Hedbor  push_static_text("version"); push_int(prop.os2->version); push_static_text("xAvgCharWidth"); push_int(prop.os2->xAvgCharWidth); push_static_text("usWeightClass"); push_int(prop.os2->usWeightClass); push_static_text("usWidthClass"); push_int(prop.os2->usWidthClass); push_static_text("fsType"); push_int(prop.os2->fsType); push_static_text("ySubscriptXSize"); push_int(prop.os2->ySubscriptXSize); push_static_text("ySubscriptYSize"); push_int(prop.os2->ySubscriptYSize); push_static_text("ySubscriptXOffset"); push_int(prop.os2->ySubscriptXOffset); push_static_text("ySubscriptYOffset"); push_int(prop.os2->ySubscriptYOffset); push_static_text("ySuperscriptXSize"); push_int(prop.os2->ySuperscriptXSize); push_static_text("ySuperscriptYSize"); push_int(prop.os2->ySuperscriptYSize); push_static_text("ySuperscriptXOffset"); push_int(prop.os2->ySuperscriptXOffset); push_static_text("ySuperscriptYOffset"); push_int(prop.os2->ySuperscriptYOffset); push_static_text("yStrikeoutSize"); push_int(prop.os2->yStrikeoutSize); push_static_text("yStrikeoutPosition"); push_int(prop.os2->yStrikeoutPosition); push_static_text("sFamilyClass"); push_int(prop.os2->sFamilyClass); push_static_text("panose");
7554d91998-10-31Mirar (Pontus Hagland)  push_string(make_shared_binary_string(prop.os2->panose,10));
5e9fc02015-08-18Per Hedbor  push_static_text("ulUnicodeRange1"); push_int(prop.os2->ulUnicodeRange1); push_static_text("ulUnicodeRange2"); push_int(prop.os2->ulUnicodeRange2); push_static_text("ulUnicodeRange3"); push_int(prop.os2->ulUnicodeRange3); push_static_text("ulUnicodeRange4"); push_int(prop.os2->ulUnicodeRange4);
7554d91998-10-31Mirar (Pontus Hagland) 
5e9fc02015-08-18Per Hedbor  push_static_text("achVendID");
7554d91998-10-31Mirar (Pontus Hagland)  push_string(make_shared_binary_string(prop.os2->achVendID,4));
5e9fc02015-08-18Per Hedbor  push_static_text("fsSelection"); push_int(prop.os2->fsSelection); push_static_text("usFirstCharIndex"); push_int(prop.os2->usFirstCharIndex); push_static_text("usLastCharIndex"); push_int(prop.os2->usLastCharIndex); push_static_text("sTypoAscender"); push_int(prop.os2->sTypoAscender); push_static_text("sTypoDescender"); push_int(prop.os2->sTypoDescender); push_static_text("sTypoLineGap"); push_int(prop.os2->sTypoLineGap); push_static_text("usWinAscent"); push_int(prop.os2->usWinAscent); push_static_text("usWinDescent"); push_int(prop.os2->usWinDescent); push_static_text("ulCodePageRange1"); push_int(prop.os2->ulCodePageRange1); push_static_text("ulCodePageRange2"); push_int(prop.os2->ulCodePageRange2);
7554d91998-10-31Mirar (Pontus Hagland)  f_aggregate_mapping(32*2); } else push_int(0);
5e9fc02015-08-18Per Hedbor  push_static_text("postscript");
7554d91998-10-31Mirar (Pontus Hagland)  if (prop.postscript) {
5e9fc02015-08-18Per Hedbor  push_static_text("FormatType"); push_int(prop.postscript->FormatType); push_static_text("italicAngle"); push_int(prop.postscript->italicAngle); push_static_text("underlinePosition"); push_int(prop.postscript->underlinePosition); push_static_text("underlineThickness"); push_int(prop.postscript->underlineThickness); push_static_text("isFixedPitch"); push_int(prop.postscript->isFixedPitch); push_static_text("minMemType42"); push_int(prop.postscript->minMemType42); push_static_text("maxMemType42"); push_int(prop.postscript->maxMemType42); push_static_text("minMemType1"); push_int(prop.postscript->minMemType1); push_static_text("maxMemType1"); push_int(prop.postscript->maxMemType1);
7554d91998-10-31Mirar (Pontus Hagland)  f_aggregate_mapping(9*2); } else push_int(0);
26815d2000-02-05Per Hedbor 
5e9fc02015-08-18Per Hedbor  push_static_text("hdmx");
7554d91998-10-31Mirar (Pontus Hagland)  if (prop.hdmx) { int i;
5e9fc02015-08-18Per Hedbor  push_static_text("version"); push_int(prop.hdmx->version); push_static_text("num_records"); push_int(prop.hdmx->num_records); push_static_text("records");
7554d91998-10-31Mirar (Pontus Hagland)  for (i=0; i<prop.hdmx->num_records; i++) {
5e9fc02015-08-18Per Hedbor  push_static_text("ppem"); push_int(prop.hdmx->records[i].ppem); push_static_text("max_width"); push_int(prop.hdmx->records[i].max_width);
7554d91998-10-31Mirar (Pontus Hagland)  /* push_text("widths"); push_int(prop.hdmx->records[i].widths);*/ f_aggregate_mapping(2*2); } f_aggregate(prop.hdmx->num_records); f_aggregate_mapping(3*2); } else push_int(0); f_aggregate_mapping(9*2); }
362bfa1999-06-01Marcus Comstedt #endif /* TTF_DEBUG_INFO */
7554d91998-10-31Mirar (Pontus Hagland)  /* **! method object flush() **! This flushes all cached information. **! Might be used to save memory - the face **! information is read back from disk upon need.
26815d2000-02-05Per Hedbor **!
ba33022003-01-20Martin Nilsson **! returns the object being called
7554d91998-10-31Mirar (Pontus Hagland) */ static void image_ttf_face_flush(INT32 args) { int res; pop_n_elems(args); if ((res=TT_Flush_Face(THISf->face))) my_tt_error("Image.TTF.Face->flush()","",res); ref_push_object(THISOBJ); } /* **! method mapping names() **! method array(array) _names() **! Gives back the names or the complete name-list
26815d2000-02-05Per Hedbor **! of this face.
7554d91998-10-31Mirar (Pontus Hagland) **! **! The result from <ref>names</ref>() is a mapping, **! which has any or all of these indices: **! <pre> **! "copyright": ("Copyright the Foo Corporation...bla bla") **! "family": ("My Little Font") **! "style": ("Bold") **! "full": ("Foo: My Little Font: 1998") **! "expose": ("My Little Font Bold") **! "version": ("June 1, 1998; 1.00, ...") **! "postscript": ("MyLittleFont-Bold") **! "trademark": ("MyLittleFont is a registered...bla bla") **! </pre> **! **! This is extracted from the information from _names(), **! and fit into pike-strings using unicode or iso-8859-1, **! if possible. **!
26815d2000-02-05Per Hedbor **! The result from <ref>_names</ref>() is a
7554d91998-10-31Mirar (Pontus Hagland) **! matrix, on this form: <pre> **! ({ ({ int platform, encoding, language, id, string name }), **! ({ int platform, encoding, language, id, string name }), **! ... **! }) **! </pre> **! **! returns the name as a mapping to string or the names as a matrix **! **! note: **! To use the values from <ref>_names</ref>(), **! check the TrueType standard documentation. */ static void image_ttf_face__names(INT32 args) {
ddeb981998-11-01Per Hedbor  int ns,res; TT_UShort i;
7554d91998-10-31Mirar (Pontus Hagland)  TT_Face face=THISf->face; pop_n_elems(args); if ((ns=TT_Get_Name_Count(face))==-1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.Face->names(): Illegal face handler\n");
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  for (i=0; i<ns; i++) {
e13b5e2000-02-06Henrik Grubbström (Grubba)  unsigned short platformID,encodingID,languageID,nameID;
ddeb981998-11-01Per Hedbor  TT_UShort length;
7554d91998-10-31Mirar (Pontus Hagland)  char *stringPtr;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_Get_Name_ID(face,i, &platformID,&encodingID,&languageID,&nameID))) my_tt_error("Image.TTF.Face->names()","TT_Get_Name_ID: ",res); push_int(platformID); push_int(encodingID); push_int(languageID); push_int(nameID);
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_Get_Name_String(face,i,&stringPtr,&length))) my_tt_error("Image.TTF.Face->names()","TT_Get_Name_String: ",res); push_string(make_shared_binary_string(stringPtr,length));
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  f_aggregate(5); } f_aggregate(ns); } static void image_ttf_face_names(INT32 args) { int n,i; int has[8]={0,0,0,0,0,0,0,0}; /* iso8859=20, unicode=30, any=1 */ char *hasname[8]={"copyright","family","style","full", "expose","version","postscript","trademark"}; struct array *a,*b; image_ttf_face__names(args);
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-1]) != T_ARRAY)
334e872003-03-12Marcus Agehall  Pike_error("Image.TTF.Face->names(): internal error, weird _names()\n");
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  a=sp[-1].u.array; n=0; for (i=0; i<a->size; i++) { int ihas=1; int what; b=a->item[i].u.array; what=b->item[3].u.integer;
334e872003-03-12Marcus Agehall  if (what>=8 || what<0) continue; /* weird */
7554d91998-10-31Mirar (Pontus Hagland)  switch (b->item[0].u.integer*100+b->item[1].u.integer) { case 301: /* M$: unicode */ case 300: /* M$: unicode (?) */ ihas=30; break; case 202: /* ISO: iso-8859-1 */ ihas=20; break; } if (ihas<has[what]) continue; /* worse */ push_text(hasname[what]);
26815d2000-02-05Per Hedbor 
334e872003-03-12Marcus Agehall  if (ihas==30) /* unicode, M$ but weird enough correct byteorder */
e1ba2c1999-09-07Mirar (Pontus Hagland)  {
d7ae232000-08-10Henrik Grubbström (Grubba)  ptrdiff_t n = b->item[4].u.string->len/2;
e1ba2c1999-09-07Mirar (Pontus Hagland)  struct pike_string *ps=begin_wide_shared_string(n,1); p_wchar1 *d=STR1(ps); p_wchar0 *s=STR0(b->item[4].u.string); while (n--) *(d++)=((p_wchar1)s[0]<<8)|(p_wchar1)s[1],s+=2; push_string(end_shared_string(ps)); }
7554d91998-10-31Mirar (Pontus Hagland)  else push_svalue(b->item+4);
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  n++; } f_aggregate_mapping(n*2); stack_swap(); pop_stack(); } /* **! method object `()() **! This instantiates the face for normal usage - **! to convert font data to images.
26815d2000-02-05Per Hedbor **!
eeb7771999-05-11Mirar (Pontus Hagland) **! returns a <ref>Image.TTF.FaceInstance</ref> object.
7554d91998-10-31Mirar (Pontus Hagland) */ static void image_ttf_face_make(INT32 args) { pop_n_elems(args); ref_push_object(THISOBJ); push_object(clone_object(image_ttf_faceinstance_program,1)); } /* **! class FaceInstance **! This is the instance of a face, with geometrics, **! encodings and stuff.
26815d2000-02-05Per Hedbor **!
cc60cc1999-04-09Mirar (Pontus Hagland) **! method void create(object face)
7554d91998-10-31Mirar (Pontus Hagland) **! creates a new Instance from a face. */ static void ttf_instance_setc(struct image_ttf_face_struct *face_s, struct image_ttf_faceinstance_struct *face_i, int towhat, char *where) { TT_Face_Properties prop; TT_Instance_Metrics metr; int res; int resol; if ((res=TT_Get_Face_Properties(face_s->face,&prop))) my_tt_error(where,"TT_Get_Face_Properties",res);
73d8f61999-02-01Per Hedbor  resol=58; /* should be 72, but glyphs fit using this value */
7554d91998-10-31Mirar (Pontus Hagland)  /* (int)((72*(prop.horizontal->Ascender+ prop.horizontal->Descender)/ (float)prop.horizontal->Ascender)); */
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Set_Instance_Resolutions(face_i->instance, (TT_UShort)resol, (TT_UShort)resol)))
7554d91998-10-31Mirar (Pontus Hagland)  my_tt_error("Image.TTF.FaceInstance()", "TT_Set_Instance_Resolutions: ",res); if ((res=TT_Get_Instance_Metrics(face_i->instance,&metr))) my_tt_error(where,"TT_Get_Instance_Metrics",res);
9af51c1999-05-13Per Hedbor  if ((res=TT_Set_Instance_CharSize(face_i->instance,towhat))) my_tt_error(where,"TT_Set_Instance_CharSize: ",res);
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  face_i->baseline=
9a15272017-08-30Henrik Grubbström (Grubba)  (int)(((double)(towhat/64.0+towhat/640.0)* prop.horizontal->Ascender)/ (prop.horizontal->Ascender - prop.horizontal->Descender));
73d8f61999-02-01Per Hedbor 
26815d2000-02-05Per Hedbor  face_i->height= (towhat/64 + towhat/640);
73d8f61999-02-01Per Hedbor 
d7ae232000-08-10Henrik Grubbström (Grubba)  face_i->trans = ~63 & (32 +
9a15272017-08-30Henrik Grubbström (Grubba)  (int)(64*((towhat/64.0+towhat/640.0)* prop.horizontal->Ascender)/ (prop.horizontal->Ascender-prop.horizontal->Descender)));
7554d91998-10-31Mirar (Pontus Hagland) } static void image_ttf_faceinstance_create(INT32 args) {
36a00c2000-08-15Henrik Grubbström (Grubba)  struct image_ttf_face_struct *face_s = NULL;
7554d91998-10-31Mirar (Pontus Hagland)  struct image_ttf_faceinstance_struct *face_i=THISi; int res; if (!args)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance(): too few arguments\n");
7554d91998-10-31Mirar (Pontus Hagland) 
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_OBJECT ||
76f7462014-05-26Martin Nilsson  !(face_s=get_storage(sp[-args].u.object,image_ttf_face_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance(): illegal argument 1\n");
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_New_Instance(face_s->face,&(face_i->instance)))) my_tt_error("Image.TTF.FaceInstance()","TT_New_Instance: ",res); face_i->load_flags = TTLOAD_SCALE_GLYPH|TTLOAD_HINT_GLYPH;
0b8b7d1999-08-16Henrik Grubbström (Grubba)  add_ref(face_i->faceobj=sp[-args].u.object);
7554d91998-10-31Mirar (Pontus Hagland)  ttf_instance_setc(face_s,face_i,32*64,"Image.TTF.FaceInstance()"); } static void image_ttf_faceinstance_set_height(INT32 args) { struct image_ttf_face_struct *face_s; struct image_ttf_faceinstance_struct *face_i=THISi; int h=0; if (!args)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->set_height(): missing arguments\n");
7554d91998-10-31Mirar (Pontus Hagland) 
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) == T_INT)
d7ae232000-08-10Henrik Grubbström (Grubba)  h = sp[-args].u.integer*64;
dd24fe2011-10-29Henrik Grubbström (Grubba)  else if (TYPEOF(sp[-args]) == T_FLOAT)
9a15272017-08-30Henrik Grubbström (Grubba)  h = (int)(sp[-args].u.float_number*64);
7554d91998-10-31Mirar (Pontus Hagland)  else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->set_height(): illegal argument 1\n");
7554d91998-10-31Mirar (Pontus Hagland)  if (h<1) h=1;
76f7462014-05-26Martin Nilsson  if (!(face_s=get_storage(THISi->faceobj,image_ttf_face_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->write(): lost Face\n");
7554d91998-10-31Mirar (Pontus Hagland)  ttf_instance_setc(face_s,face_i,h,"Image.TTF.FaceInstance->set_height()"); pop_n_elems(args); ref_push_object(THISOBJ); } static void ttf_translate_8bit(TT_CharMap charMap, unsigned char *what, int **dest, int len, int base) { int i;
dc8d022014-04-27Martin Nilsson  dest[0]=xalloc(len*sizeof(int));
7554d91998-10-31Mirar (Pontus Hagland)  THREADS_ALLOW(); for (i=0; i<len; i++)
a309212000-09-11Henrik Grubbström (Grubba)  dest[0][i]=TT_Char_Index(charMap, (TT_UShort)(what[i]+base));
7554d91998-10-31Mirar (Pontus Hagland)  THREADS_DISALLOW(); }
ddeb981998-11-01Per Hedbor  static void ttf_translate_16bit(TT_CharMap charMap, unsigned short *what, int **dest, int len, int base) { int i;
dc8d022014-04-27Martin Nilsson  dest[0]=xalloc(len*sizeof(int));
ddeb981998-11-01Per Hedbor  THREADS_ALLOW(); for (i=0; i<len; i++)
f258372000-09-08Henrik Grubbström (Grubba)  dest[0][i] = TT_Char_Index(charMap, (TT_UShort)(what[i] + base));
ddeb981998-11-01Per Hedbor  THREADS_DISALLOW(); }
7554d91998-10-31Mirar (Pontus Hagland) static void ttf_get_nice_charmap(TT_Face face, TT_CharMap *charMap, char *where) { int n,i,res,got=-1,best=-1;
26815d2000-02-05Per Hedbor  if (-1==(n=TT_Get_CharMap_Count(face)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("%s: illegal face handle\n",where);
7554d91998-10-31Mirar (Pontus Hagland)  for (i=0; i<n; i++) { int ihas=0;
f258372000-09-08Henrik Grubbström (Grubba)  TT_UShort platformID, encodingID;
26815d2000-02-05Per Hedbor 
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Get_CharMap_ID(face, (TT_UShort)i, &platformID, &encodingID)))
7554d91998-10-31Mirar (Pontus Hagland)  my_tt_error(where,"TT_Get_CharMap_ID: ",res); switch (platformID*100+encodingID) { case 301: /* M$: unicode */ case 300: /* M$: unicode (?) */ ihas=30; break; case 202: /* ISO: iso-8859-1 */ ihas=20; break;
dd65171999-03-23Per Hedbor  default: ihas = 1; break;
7554d91998-10-31Mirar (Pontus Hagland)  }
26815d2000-02-05Per Hedbor  if (ihas>got)
7554d91998-10-31Mirar (Pontus Hagland)  { best=i; got=ihas; } } if (got==-1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("%s: no charmaps at all\n",where);
7554d91998-10-31Mirar (Pontus Hagland) 
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Get_CharMap(face, (TT_UShort)best, charMap)))
7554d91998-10-31Mirar (Pontus Hagland)  my_tt_error(where,"TT_Get_CharMap: ",res); } static void ttf_please_translate_8bit(TT_Face face, struct pike_string *s, int **dest,int *dlen, int base, char *where) { TT_CharMap charMap;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  ttf_get_nice_charmap(face,&charMap,where);
cc7cf42015-10-14Martin Nilsson  (*dlen) = s->len;
7554d91998-10-31Mirar (Pontus Hagland)  ttf_translate_8bit(charMap,(unsigned char*)(s->str),dest,*dlen,base); }
ddeb981998-11-01Per Hedbor  static void ttf_please_translate_16bit(TT_Face face, struct pike_string *s, int **dest,int *dlen, int base, char *where) { TT_CharMap charMap;
26815d2000-02-05Per Hedbor 
ddeb981998-11-01Per Hedbor  ttf_get_nice_charmap(face,&charMap,where);
cc7cf42015-10-14Martin Nilsson  (*dlen) = s->len;
ddeb981998-11-01Per Hedbor  ttf_translate_16bit(charMap,(unsigned short*)(s->str),dest,*dlen,base); }
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland) static void image_ttf_faceinstance_ponder(INT32 args) { int *sstr; int len,i,res,base=0; struct image_ttf_face_struct *face_s; struct image_ttf_faceinstance_struct *face_i=THISi;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  int xmin=1000,xmax=-1000,pos=0;
76f7462014-05-26Martin Nilsson  if (!(face_s=get_storage(THISi->faceobj,image_ttf_face_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->ponder(): lost Face\n");
7554d91998-10-31Mirar (Pontus Hagland) 
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (args && TYPEOF(sp[-1]) == T_INT)
7554d91998-10-31Mirar (Pontus Hagland)  { base=sp[-1].u.integer; args--; pop_stack(); }
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-args]) != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->ponder(): illegal argument 1\n");
7554d91998-10-31Mirar (Pontus Hagland) 
e27e632000-12-12Per Hedbor  switch( sp[-args].u.string->size_shift ) { case 0: ttf_please_translate_8bit(face_s->face, sp[-args].u.string,&sstr,&len,base, "Image.TTF.FaceInstance->ponder()"); break; case 1: ttf_please_translate_16bit(face_s->face, sp[-args].u.string,&sstr,&len,base, "Image.TTF.FaceInstance->ponder()"); break; default:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too wide string for truetype\n");
e27e632000-12-12Per Hedbor  }
7554d91998-10-31Mirar (Pontus Hagland)  pop_n_elems(args); for (i=0; i<len; i++) { TT_Glyph glyph; TT_Glyph_Metrics metrics; int ind;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  ind=sstr[i];
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"glyph: %d\n",ind); */
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_New_Glyph(face_s->face,&glyph))) my_tt_error("Image.TTF.FaceInstance->ponder()","TT_New_Glyph: ",res);
26815d2000-02-05Per Hedbor 
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind, (TT_UShort)face_i->load_flags)))
7554d91998-10-31Mirar (Pontus Hagland)  my_tt_error("Image.TTF.FaceInstance->ponder()","TT_Load_Glyph: ",res); if ((res=TT_Get_Glyph_Metrics(glyph,&metrics))) my_tt_error("Image.TTF.FaceInstance->ponder()", "TT_Get_Glyph_Metrics: ",res); if (pos+metrics.bbox.xMin<xmin) xmin=pos+metrics.bbox.xMin; if (pos+metrics.bbox.xMax>xmax) xmax=pos+metrics.bbox.xMax; pos+=metrics.advance; /* insert kerning stuff here */
26815d2000-02-05Per Hedbor 
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"bbox: (%f,%f)-(%f,%f)\n", */ /* metrics.bbox.xMin/64.0, */ /* metrics.bbox.yMin/64.0, */ /* metrics.bbox.xMax/64.0, */ /* metrics.bbox.yMax/64.0); */
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"BearingX: %f\n",metrics.bearingX/64.0); */ /* fprintf(stderr,"BearingY: %f\n",metrics.bearingY/64.0); */ /* fprintf(stderr,"advance: %f\n",metrics.advance/64.0); */
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"\n"); */
7554d91998-10-31Mirar (Pontus Hagland)  } free(sstr);
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"xmin: %f\n",xmin/64.0); */ /* fprintf(stderr,"xmax: %f\n",xmax/64.0); */
7554d91998-10-31Mirar (Pontus Hagland)  ref_push_object(THISOBJ); }
ddeb981998-11-01Per Hedbor static int find_kerning( TT_Kerning kerning, int c1, int c2 ) {
4d4cc22001-09-24Henrik Grubbström (Grubba)  int j;
ddeb981998-11-01Per Hedbor /* fprintf(stderr, "kern: %d %d\n", c1, c2); */ for(j=0; j<kerning.nTables; j++) { if( (kerning.tables[j].coverage & 0x0f) != 1 ) /* We don't want it */ continue; switch(kerning.tables[j].format) { case 2: /* The smart one */ { int ind; int lclass=0, rclass=0; TT_Kern_2 table = kerning.tables[j].t.kern2; ind = c1 - table.leftClass.firstGlyph; if(ind >= table.leftClass.nGlyphs || ind < 0) continue; lclass = table.leftClass.classes[ ind ]; ind = c2 - table.rightClass.firstGlyph; if(ind >= table.rightClass.nGlyphs || ind < 0) continue; rclass = table.rightClass.classes[ ind ]; return table.array[ rclass+lclass ]; } case 0: /* The microsoft one */ { TT_Kern_0 table = kerning.tables[j].t.kern0;
1759901999-09-18Mirar (Pontus Hagland)  int a=0,b=table.nPairs-1;
ddeb981998-11-01Per Hedbor 
1759901999-09-18Mirar (Pontus Hagland)  while (a<b)
ddeb981998-11-01Per Hedbor  {
1759901999-09-18Mirar (Pontus Hagland)  int i=(a+b)/2; if(table.pairs[i].left == c1) { if(table.pairs[i].right == c2) { /* fprintf(stderr, "found kerning\n"); */ return table.pairs[i].value; } else if(table.pairs[i].right < c2) a=i+1;
26815d2000-02-05Per Hedbor  else
1759901999-09-18Mirar (Pontus Hagland)  b=i-1;
26815d2000-02-05Per Hedbor  } else if(table.pairs[i].left < c1)
1759901999-09-18Mirar (Pontus Hagland)  a=i+1;
26815d2000-02-05Per Hedbor  else
1759901999-09-18Mirar (Pontus Hagland)  b=i-1;
ddeb981998-11-01Per Hedbor  } } break; default:
26815d2000-02-05Per Hedbor  fprintf(stderr, "Warning: Unknown kerning table format %d\n",
ddeb981998-11-01Per Hedbor  kerning.tables[j].format); } } return 0; }
7554d91998-10-31Mirar (Pontus Hagland) static void image_ttf_faceinstance_write(INT32 args) { int **sstr; int *slen; int i,res=0,base=0,a; struct image_ttf_face_struct *face_s; struct image_ttf_faceinstance_struct *face_i=THISi; TT_CharMap charMap;
ddeb981998-11-01Per Hedbor  TT_Kerning kerning; int has_kerning = 0;
7554d91998-10-31Mirar (Pontus Hagland)  char *errs=NULL;
ddeb981998-11-01Per Hedbor  int scalefactor=0;
7554d91998-10-31Mirar (Pontus Hagland)  int xmin=1000,xmax=-1000,pos=0,ypos; int width,height,mod;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  unsigned char* pixmap;
22413a1998-11-03Per Hedbor  int maxcharwidth = 0;
ddeb981998-11-01Per Hedbor 
76f7462014-05-26Martin Nilsson  if (!(face_s=get_storage(THISi->faceobj,image_ttf_face_program)))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->write(): lost Face\n");
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor  if(!TT_Get_Kerning_Directory( face_s->face, &kerning )) { TT_Instance_Metrics metrics; /* fprintf(stderr, "has kerning!\n"); */ has_kerning = 1; if(TT_Get_Instance_Metrics( face_i->instance, &metrics ))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Nope. No way.\n");
ddeb981998-11-01Per Hedbor  scalefactor = metrics.x_scale; /* fprintf(stderr, "offset=%d\n", (int)metrics.x_scale); */ }
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (args && TYPEOF(sp[-1]) == T_INT)
7554d91998-10-31Mirar (Pontus Hagland)  { base=sp[-1].u.integer; args--; pop_stack(); } if (!args) {
00734c2007-12-20Martin Nilsson  push_empty_string();
7554d91998-10-31Mirar (Pontus Hagland)  args=1; } ttf_get_nice_charmap(face_s->face,&charMap, "Image.TTF.FaceInstance->write()"); sstr=alloca(args*sizeof(int*)); slen=alloca(args*sizeof(int)); /* first pass: figure out total bounding box */ for (a=0; a<args; a++) {
ddeb981998-11-01Per Hedbor  char *errs=NULL; TT_Glyph_Metrics metrics;
7554d91998-10-31Mirar (Pontus Hagland) 
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[a-args]) != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->write(): illegal argument %d\n",a+1);
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor  switch(sp[a-args].u.string->size_shift) { case 0: ttf_translate_8bit(charMap,(unsigned char*)sp[a-args].u.string->str,
d7ae232000-08-10Henrik Grubbström (Grubba)  sstr+a,
cc7cf42015-10-14Martin Nilsson  slen[a]=sp[a-args].u.string->len,
d7ae232000-08-10Henrik Grubbström (Grubba)  base);
ddeb981998-11-01Per Hedbor  break; case 1: ttf_translate_16bit(charMap,(unsigned short*)sp[a-args].u.string->str,
d7ae232000-08-10Henrik Grubbström (Grubba)  sstr+a,
cc7cf42015-10-14Martin Nilsson  slen[a]=sp[a-args].u.string->len,
d7ae232000-08-10Henrik Grubbström (Grubba)  base);
ddeb981998-11-01Per Hedbor  break; case 2:
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Too wide string for truetype\n");
26815d2000-02-05Per Hedbor  break;
ddeb981998-11-01Per Hedbor  }
7554d91998-10-31Mirar (Pontus Hagland)  pos=0; for (i=0; i<slen[a]; i++) { TT_Glyph glyph; int ind;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  ind=sstr[a][i];
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"glyph: %d\n",ind); */
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_New_Glyph(face_s->face,&glyph))) { errs="TT_New_Glyph: "; break; }
26815d2000-02-05Per Hedbor 
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind, (TT_UShort)face_i->load_flags)))
7554d91998-10-31Mirar (Pontus Hagland)  { errs="TT_Load_Glyph: "; break; } if ((res=TT_Get_Glyph_Metrics(glyph,&metrics))) { errs="TT_Get_Glyph_Metrics: "; break; }
26815d2000-02-05Per Hedbor  if (pos+metrics.bbox.xMin<xmin)
22413a1998-11-03Per Hedbor  xmin=pos+metrics.bbox.xMin;
26815d2000-02-05Per Hedbor  if (pos+metrics.bbox.xMax>xmax)
ddeb981998-11-01Per Hedbor  xmax=pos+metrics.bbox.xMax;
7554d91998-10-31Mirar (Pontus Hagland) 
22413a1998-11-03Per Hedbor  if((metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0)) >maxcharwidth) maxcharwidth = (metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0));
26815d2000-02-05Per Hedbor 
ddeb981998-11-01Per Hedbor  pos+=metrics.advance; if(has_kerning && i<slen[a]-1) { int kern = find_kerning( kerning, ind, sstr[a][i+1] );
9a15272017-08-30Henrik Grubbström (Grubba)  pos += (int)(kern * (scalefactor/65535.0));
ddeb981998-11-01Per Hedbor  }
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_Done_Glyph(glyph))) { errs="TT_Done_Glyph: "; break; } }
ddeb981998-11-01Per Hedbor  pos -= metrics.advance; pos += metrics.bbox.xMax-metrics.bbox.xMin;
26815d2000-02-05Per Hedbor  if (pos>xmax)
ddeb981998-11-01Per Hedbor  xmax=pos;
7554d91998-10-31Mirar (Pontus Hagland)  if (errs) { for (i=0; i<a; i++) free(sstr[i]); my_tt_error("Image.TTF.FaceInstance->write()",errs,res); } } pop_n_elems(args);
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"xmin=%f xmax=%f\n",xmin/64.0,xmax/64.0); */
7554d91998-10-31Mirar (Pontus Hagland)  xmin&=~63;
ddeb981998-11-01Per Hedbor  width=((xmax-xmin+63)>>6)+4;
7554d91998-10-31Mirar (Pontus Hagland)  height=face_i->height*args;
22413a1998-11-03Per Hedbor  mod=(4-(maxcharwidth&3))&3;
7554d91998-10-31Mirar (Pontus Hagland)  if (width<1) width=1;
22413a1998-11-03Per Hedbor  if ((pixmap=malloc((maxcharwidth+mod)*face_i->height)))
7554d91998-10-31Mirar (Pontus Hagland)  { /* second pass: write the stuff */ TT_Raster_Map rastermap; struct object *o; struct image *img; rgb_group *d;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor  rastermap.rows=face_i->height;
22413a1998-11-03Per Hedbor  rastermap.cols=rastermap.width=maxcharwidth+mod;
7554d91998-10-31Mirar (Pontus Hagland)  rastermap.flow=TT_Flow_Down; rastermap.bitmap=pixmap;
ddeb981998-11-01Per Hedbor  rastermap.size=rastermap.cols*rastermap.rows;
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor  ypos=0;
7554d91998-10-31Mirar (Pontus Hagland) 
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"rastermap.rows=%d cols=%d width=%d\n", */ /* rastermap.rows,rastermap.cols,rastermap.width); */
26815d2000-02-05Per Hedbor 
ddeb981998-11-01Per Hedbor  push_int(width); push_int(height); o=clone_object(image_program,2);
13b5ed2014-05-26Per Hedbor  img=get_storage(o,image_program);
ddeb981998-11-01Per Hedbor  d=img->img;
7554d91998-10-31Mirar (Pontus Hagland)  for (a=0; a<args; a++) {
ddeb981998-11-01Per Hedbor  pos=-xmin;
7554d91998-10-31Mirar (Pontus Hagland)  for (i=0; i<slen[a]; i++) {
22413a1998-11-03Per Hedbor  int sw, xp;
7554d91998-10-31Mirar (Pontus Hagland)  TT_Glyph glyph; TT_Glyph_Metrics metrics;
ddeb981998-11-01Per Hedbor  int ind, x, y;
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  ind=sstr[a][i];
ddeb981998-11-01Per Hedbor /* fprintf(stderr,"glyph: %d\n",ind); */
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_New_Glyph(face_s->face,&glyph))) { errs="TT_New_Glyph: "; break; }
26815d2000-02-05Per Hedbor 
f258372000-09-08Henrik Grubbström (Grubba)  if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind, (TT_UShort)face_i->load_flags)))
7554d91998-10-31Mirar (Pontus Hagland)  { errs="TT_Load_Glyph: "; break; } if ((res=TT_Get_Glyph_Metrics(glyph,&metrics))) { errs="TT_Get_Glyph_Metrics: "; break; }
21b12a2014-09-03Martin Nilsson  memset(pixmap,0,rastermap.size);
ddeb981998-11-01Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_Get_Glyph_Pixmap(glyph, &rastermap,
73d8f61999-02-01Per Hedbor  -metrics.bbox.xMin /*+pos%64*/,
ddeb981998-11-01Per Hedbor  face_i->height*64- face_i->trans)))
7554d91998-10-31Mirar (Pontus Hagland)  { errs="TT_Get_Glyph_Pixmap: "; break; }
22413a1998-11-03Per Hedbor  sw = metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0); /* Copy source pixmap to destination image object. */
c0a3d31998-11-01Per Hedbor  for(y=0; y<face_i->height; y++) {
22413a1998-11-03Per Hedbor  unsigned int s; unsigned char * source = pixmap+rastermap.width*y; rgb_group *dt=d+(ypos+y)*width+(xp=(metrics.bbox.xMin+pos)/64);
26815d2000-02-05Per Hedbor 
22413a1998-11-03Per Hedbor  for(x=0; x<sw && xp<width; x++,xp++,source++,dt++)
26815d2000-02-05Per Hedbor  if(xp<0 || !(s = *source))
22413a1998-11-03Per Hedbor  continue; else if((s=dt->r+s) < 256) dt->r=dt->g=dt->b=s; else dt->r=dt->g=dt->b=255;
c0a3d31998-11-01Per Hedbor  }
26815d2000-02-05Per Hedbor 
22413a1998-11-03Per Hedbor  pos+=metrics.advance; /* if(metrics.bbox.xMin < 0) */ /* pos += metrics.bbox.xMin; */
ddeb981998-11-01Per Hedbor  if(has_kerning && i<slen[a]-1) { int kern = find_kerning( kerning, sstr[a][i], sstr[a][i+1] );
9a15272017-08-30Henrik Grubbström (Grubba)  pos += (int)(kern * (scalefactor/65535.0));
ddeb981998-11-01Per Hedbor /* fprintf(stderr, "Adjusted is %d\n", */ /* (int)(kern * (scalefactor/65535.0))); */ }
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  if ((res=TT_Done_Glyph(glyph))) { errs="TT_Done_Glyph: "; break; } } if (errs) { for (a=0; a<args; a++) free(sstr[a]); free(pixmap);
ddeb981998-11-01Per Hedbor  free_object(o);
7554d91998-10-31Mirar (Pontus Hagland)  my_tt_error("Image.TTF.FaceInstance->write()",errs,res); }
ddeb981998-11-01Per Hedbor  ypos+=face_i->height;
7554d91998-10-31Mirar (Pontus Hagland)  }
073fb31998-11-11Per Hedbor  free(pixmap);
7554d91998-10-31Mirar (Pontus Hagland)  push_object(o); }
26815d2000-02-05Per Hedbor  else
7554d91998-10-31Mirar (Pontus Hagland)  {
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.TTF.FaceInstance->write(): out of memory\n");
7554d91998-10-31Mirar (Pontus Hagland)  } for (a=0; a<args; a++) free(sstr[a]); } static void image_ttf_faceinstance_face(INT32 args) { pop_n_elems(args); ref_push_object(THISi->faceobj); } #endif /* HAVE_LIBTTF */ /*** module init & exit & stuff *****************************************/
51ef5c2002-10-21Marcus Comstedt PIKE_MODULE_EXIT
7554d91998-10-31Mirar (Pontus Hagland) { free_string(param_baseline); free_string(param_quality); #ifdef HAVE_LIBTTF TT_Done_FreeType(engine);
a69d8e1999-07-29Henrik Grubbström (Grubba)  if (image_ttf_faceinstance_program) { free_program(image_ttf_faceinstance_program); image_ttf_faceinstance_program = NULL; }
412aca1999-07-30Henrik Grubbström (Grubba)  if (image_ttf_face_program) { free_program(image_ttf_face_program); image_ttf_face_program = NULL; }
2217fb1999-07-30Henrik Grubbström (Grubba) #endif /* HAVE_LIBTTF */
7554d91998-10-31Mirar (Pontus Hagland) }
51ef5c2002-10-21Marcus Comstedt PIKE_MODULE_INIT
7554d91998-10-31Mirar (Pontus Hagland) { #ifdef HAVE_LIBTTF unsigned char palette[5]={0,64,128,192,255};
277f422000-04-05Henrik Grubbström (Grubba)  TT_Error errcode; #endif /* HAVE_LIBTTF */ param_baseline=make_shared_string("baseline"); param_quality=make_shared_string("quality"); #ifdef HAVE_LIBTTF /* First check that we actually can initialize the FreeType library. */ if ((errcode = TT_Init_FreeType(&engine))) {
35e1152016-02-07Martin Nilsson  DWERR("TT_Init_FreeType() failed with code 0x%03lx!\n", (unsigned long)errcode);
277f422000-04-05Henrik Grubbström (Grubba)  return; }
c870812004-04-14Henrik Grubbström (Grubba)  TT_Set_Raster_Gray_Palette(engine, palette);
277f422000-04-05Henrik Grubbström (Grubba)  TT_Init_Kerning_Extension( engine );
7554d91998-10-31Mirar (Pontus Hagland)  #ifdef DYNAMIC_MODULE
5e9fc02015-08-18Per Hedbor  push_static_text("Image.Image");
660a6d2003-12-01Martin Nilsson  SAFE_APPLY_MASTER("resolv",1);
dd24fe2011-10-29Henrik Grubbström (Grubba)  if (TYPEOF(sp[-1]) == T_PROGRAM)
7554d91998-10-31Mirar (Pontus Hagland)  image_program=program_from_svalue(sp-1);
660a6d2003-12-01Martin Nilsson  pop_stack();
7554d91998-10-31Mirar (Pontus Hagland) #endif /* DYNAMIC_MODULE */ if (image_program) {
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(string,void|mapping(string:int):object) */ ADD_FUNCTION("`()",image_ttf_make,tFunc(tStr tOr(tVoid,tMap(tStr,tInt)),tObj),0);
7554d91998-10-31Mirar (Pontus Hagland)  /* make face program */ start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct image_ttf_face_struct);
7554d91998-10-31Mirar (Pontus Hagland) 
362bfa1999-06-01Marcus Comstedt #ifdef TTF_DEBUG_INFO
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:mapping) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("properties",image_ttf_face_properties,tFunc(tNone,tMapping),0);
362bfa1999-06-01Marcus Comstedt #endif /* TTF_DEBUG_INFO */
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:object) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("flush",image_ttf_face_flush,tFunc(tNone,tObj),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:mapping(string:string)) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("names",image_ttf_face_names,tFunc(tNone,tMap(tStr,tStr)),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:array(array)) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("_names",image_ttf_face__names,tFunc(tNone,tArr(tArray)),0);
7554d91998-10-31Mirar (Pontus Hagland) 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:object) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("`()",image_ttf_face_make,tFunc(tNone,tObj),0);
7554d91998-10-31Mirar (Pontus Hagland)  set_exit_callback(image_ttf_face_exit); image_ttf_face_program=end_program(); /* make face instance program */ start_new_program();
90e9781999-01-31Fredrik Hübinette (Hubbe)  ADD_STORAGE(struct image_ttf_faceinstance_struct);
26815d2000-02-05Per Hedbor 
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(object:void) */ ADD_FUNCTION("create",image_ttf_faceinstance_create,tFunc(tObj,tVoid),0); /* function(string:object) */ ADD_FUNCTION("ponder",image_ttf_faceinstance_ponder,tFunc(tStr,tObj),0); /* function(string...:object) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("write",image_ttf_faceinstance_write,tFuncV(tNone,tStr,tObj),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(:object) */
07228a1999-06-19Fredrik Hübinette (Hubbe)  ADD_FUNCTION("face",image_ttf_faceinstance_face,tFunc(tNone,tObj),0);
45ee5d1999-02-10Fredrik Hübinette (Hubbe)  /* function(int:object) */ ADD_FUNCTION("set_height",image_ttf_faceinstance_set_height,tFunc(tInt,tObj),0);
26815d2000-02-05Per Hedbor 
7554d91998-10-31Mirar (Pontus Hagland)  set_exit_callback(image_ttf_faceinstance_exit); image_ttf_faceinstance_program=end_program(); } #endif /* HAVE_LIBTTF */ }