static undef_int i_init_t1_low(int t1log) { int init_flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE; mm_log((1,"init_t1(%d)\n", t1log)); i_clear_error(); if (t1_active_fonts) { mm_log((1, "Cannot re-initialize T1 - active fonts\n")); i_push_error(0, "Cannot re-initialize T1 - active fonts"); return 1; } if (t1_initialized) { T1_CloseLib(); t1_initialized = 0; } if (t1log) init_flags |= LOGFILE; if ((T1_InitLib(init_flags) == NULL)){ mm_log((1,"Initialization of t1lib failed\n")); i_push_error(0, "T1_InitLib failed"); return(1); } T1_SetLogLevel(T1LOG_DEBUG); ++t1_initialized; return(0); }
static i_tt_engine * i_init_tt(void) { TT_Error error; im_context_t ctx = im_get_context(); TT_Byte palette[] = { 0, 64, 127, 191, 255 }; i_tt_engine *result = im_context_slot_get(ctx, slot); i_clear_error(); if (result == NULL) { result = mymalloc(sizeof(i_tt_engine)); memset(result, 0, sizeof(*result)); im_context_slot_set(ctx, slot, result); mm_log((1, "allocated FT1 state %p\n", result)); } mm_log((1,"init_tt()\n")); if (result->initialized) return result; error = TT_Init_FreeType( &result->engine ); if ( error ){ mm_log((1,"Initialization of freetype failed, code = 0x%x\n", (unsigned)error)); i_tt_push_error(error); i_push_error(0, "Could not initialize freetype 1.x"); return NULL; } #ifdef FTXPOST error = TT_Init_Post_Extension( result->engine ); if (error) { mm_log((1, "Initialization of Post extension failed = 0x%x\n", (unsigned)error)); i_tt_push_error(error); i_push_error(0, "Could not initialize FT 1.x POST extension"); return NULL; } #endif error = TT_Set_Raster_Gray_Palette(result->engine, palette); if (error) { mm_log((1, "Initialization of gray levels failed = 0x%x\n", (unsigned)error)); i_tt_push_error(error); i_push_error(0, "Could not initialize FT 1.x POST extension"); return NULL; } mm_log((1, "initialized FT1 state %p\n", result)); result->initialized = 1; return result; }
size_t i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, size_t name_buf_size) { #ifdef FTXPOST TT_Error rc; TT_String *psname; TT_UShort index; i_clear_error(); if (!handle->loaded_names) { TT_Post post; mm_log((1, "Loading PS Names")); handle->load_cond = TT_Load_PS_Names(handle->face, &post); ++handle->loaded_names; } if (handle->load_cond) { i_push_errorf(handle->load_cond, "error loading names (%#x)", (unsigned)handle->load_cond); return 0; } index = TT_Char_Index(handle->char_map, ch); if (!index) { i_push_error(0, "no such character"); return 0; } rc = TT_Get_PS_Name(handle->face, index, &psname); if (rc) { i_push_error(rc, "error getting name"); return 0; } strncpy(name_buf, psname, name_buf_size); name_buf[name_buf_size-1] = '\0'; return strlen(psname) + 1; #else mm_log((1, "FTXPOST extension not enabled\n")); i_clear_error(); i_push_error(0, "Use of FTXPOST extension disabled"); return 0; #endif }
static char * t1_from_utf8(char const *in, size_t len, int *outlen) { /* at this point len is from a STRLEN which should be size_t and can't be too big for mymalloc */ char *out = mymalloc(len+1); /* rechecked 29jul11 tonyc */ char *p = out; unsigned long c; while (len) { c = i_utf8_advance(&in, &len); if (c == ~0UL) { myfree(out); i_push_error(0, "invalid UTF8 character"); return 0; } /* yeah, just drop them */ if (c < 0x100) { *p++ = (char)c; } } *p = '\0'; *outlen = p - out; return out; }
/* =item i_tt_push_error(code) Push an error message and code onto the Imager error stack. =cut */ static void i_tt_push_error(TT_Error rc) { #ifdef FTXERR18 TT_String const *msg = TT_ErrToString18(rc); i_push_error(rc, msg); #else i_push_errorf(rc, "Error code 0x%04x", (unsigned)rc); #endif }
static int my_handler(Display *display, XErrorEvent *error) { char buffer[500]; XGetErrorText(display, error->error_code, buffer, sizeof(buffer)); i_push_error(error->error_code, buffer); return 0; }
int i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8, char *out) { int count = 0; int font_num = font->font_id; i_mutex_lock(mutex); mm_log((1, "i_t1_has_chars(font_num %d, text %p, len %u, utf8 %d)\n", font_num, text, (unsigned)len, utf8)); i_clear_error(); if (T1_LoadFont(font_num)) { t1_push_error(); i_mutex_unlock(mutex); return 0; } while (len) { unsigned long c; if (utf8) { c = i_utf8_advance(&text, &len); if (c == ~0UL) { i_push_error(0, "invalid UTF8 character"); i_mutex_unlock(mutex); return 0; } } else { c = (unsigned char)*text++; --len; } if (c >= 0x100) { /* limit of 256 characters for T1 */ *out++ = 0; } else { char const * name = T1_GetCharName(font_num, (unsigned char)c); if (name) { *out++ = strcmp(name, ".notdef") != 0; } else { mm_log((2, " No name found for character %lx\n", c)); *out++ = 0; } } ++count; } i_mutex_unlock(mutex); return count; }
i_t1_font_t i_t1_new(char *pfb,char *afm) { int font_id; i_t1_font_t font; i_mutex_lock(mutex); i_clear_error(); if (!t1_initialized && i_init_t1_low(0)) { i_mutex_unlock(mutex); return NULL; } mm_log((1,"i_t1_new(pfb %s,afm %s)\n",pfb,(afm?afm:"NULL"))); font_id = T1_AddFont(pfb); if (font_id<0) { mm_log((1,"i_t1_new: Failed to load pfb file '%s' - return code %d.\n",pfb,font_id)); t1_push_error(); i_mutex_unlock(mutex); return NULL; } if (afm != NULL) { mm_log((1,"i_t1_new: requesting afm file '%s'.\n",afm)); if (T1_SetAfmFileName(font_id,afm)<0) mm_log((1,"i_t1_new: afm loading of '%s' failed.\n",afm)); } if (T1_LoadFont(font_id)) { mm_log((1, "i_t1_new() -> -1 - T1_LoadFont failed (%d)\n", T1_errno)); t1_push_error(); i_push_error(0, "loading font"); T1_DeleteFont(font_id); i_mutex_unlock(mutex); return NULL; } ++t1_active_fonts; i_mutex_unlock(mutex); font = mymalloc(sizeof(*font)); font->font_id = font_id; mm_log((1, "i_t1_new() -> %p (%d)\n", font, font_id)); return font; }
static int i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim cords[6], char const* txt, size_t len, int smooth, int utf8 ) { unsigned long j; TT_F26Dot6 x,y; mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n", handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8)); /* y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM); */ x=-cords[0]; /* FIXME: If you font is antialiased this should be expanded by one to allow for aa expansion and the allocation too - do before passing here */ y=-cords[4]; while (len) { if (utf8) { j = i_utf8_advance(&txt, &len); if (j == ~0UL) { i_push_error(0, "invalid UTF8 character"); return 0; } } else { j = (unsigned char)*txt++; --len; } if ( !i_tt_get_glyph(handle,inst,j) ) continue; i_tt_render_glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, &handle->instanceh[inst].gmetrics[TT_HASH(j)], bit, small_bit, x, y, smooth ); x += handle->instanceh[inst].gmetrics[TT_HASH(j)].advance / 64; } return 1; }
size_t i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8, char *out) { size_t count = 0; mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n", handle, text, (long)len, utf8)); while (len) { unsigned long c; int index; if (utf8) { c = i_utf8_advance(&text, &len); if (c == ~0UL) { i_push_error(0, "invalid UTF8 character"); return 0; } } else { c = (unsigned char)*text++; --len; } if (TT_VALID(handle->char_map)) { index = TT_Char_Index(handle->char_map, c); } else { index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1); if (index >= handle->properties.num_Glyphs) index = 0; } *out++ = index != 0; ++count; } return count; }
static void mathom_i_push_error(int code, const char *msg) { i_push_error(code, msg); }
i_img * imss_darwin(i_img_dim left, i_img_dim top, i_img_dim right, i_img_dim bottom) { CGDisplayCount count; CGDisplayErr err; CGRect rect; CGLPixelFormatObj pix; GLint npix; CGLContextObj ctx; i_img *im; CGDirectDisplayID disp; i_img_dim screen_width, screen_height; i_img_dim width, height; CGLPixelFormatAttribute pix_attrs[] = { kCGLPFADisplayMask, 0, /* filled in later */ kCGLPFAColorSize, 24, kCGLPFAAlphaSize, 0, kCGLPFAFullScreen, 0 }; i_clear_error(); disp = CGMainDisplayID(); if (!disp) { i_push_error(0, "No main display"); return NULL; } /* for now, only interested in the first display */ rect = CGDisplayBounds(disp); screen_width = rect.size.width; screen_height = rect.size.height; /* adjust negative/zero values to window size */ if (left < 0) left += screen_width; if (top < 0) top += screen_height; if (right <= 0) right += screen_width; if (bottom <= 0) bottom += screen_height; /* clamp */ if (left < 0) left = 0; if (right > screen_width) right = screen_width; if (top < 0) top = 0; if (bottom > screen_height) bottom = screen_height; /* validate */ if (right <= left || bottom <= top) { i_push_error(0, "image would be empty"); return NULL; } width = right - left; height = bottom - top; /* select a pixel format */ pix_attrs[1] = CGDisplayIDToOpenGLDisplayMask(disp); err = CGLChoosePixelFormat(pix_attrs, &pix, &npix); if (err) { i_push_errorf(err, "CGLChoosePixelFormat: %d", (int)err); return NULL; } if (!npix) { i_push_error(0, "No pixel format found - hidden display?"); return NULL; } /* make ourselves a context */ err = CGLCreateContext(pix, NULL, &ctx); CGLDestroyPixelFormat(pix); if (err) { i_push_errorf(err, "CGLCreateContext: %d", (int)err); return NULL; } err = CGLSetCurrentContext(ctx); if (err) { i_push_errorf(err, "CGLSetCurrentContext: %d", (int)err); return NULL; } err = CGLSetFullScreen(ctx); if (err) { i_push_errorf(err, "CGLSetFullScreen: %d", (int)err); return NULL; } /* capture */ im = i_img_8_new(width, height, 3); if (im) { size_t line_size = width * 4; size_t buf_size = line_size * height; unsigned char *buf = malloc(buf_size); i_img_dim y = height - 1; i_color *bufp = (i_color *)buf; /* hackish */ /* GL has the vertical axis going from bottom to top, so translate it */ glReadBuffer(GL_FRONT); glReadPixels(left, screen_height - top - height, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); /* transfer */ while (y >= 0) { i_plin(im, 0, width, y, bufp); bufp += width; --y; } free(buf); i_tags_setn(&im->tags, "ss_window_width", width); i_tags_setn(&im->tags, "ss_window_height", height); i_tags_set(&im->tags, "ss_type", "Darwin", 6); i_tags_set(&im->tags, "ss_variant", "<11", 3); i_tags_setn(&im->tags, "ss_left", left); i_tags_setn(&im->tags, "ss_top", top); } /* clean up */ CGLSetCurrentContext(NULL); CGLDestroyContext(ctx); return im; }
static void t1_push_error(void) { #if T1LIB_VERSION > 5 || T1LIB_VERSION == 5 && T1LIB_VERSION >= 1 /* I don't know when T1_StrError() was introduced, be conservative */ i_push_error(T1_errno, T1_StrError(T1_errno)); #else switch (T1_errno) { case 0: i_push_error(0, "No error"); break; #ifdef T1ERR_SCAN_FONT_FORMAT case T1ERR_SCAN_FONT_FORMAT: i_push_error(T1ERR_SCAN_FONT_FORMAT, "Attempt to Load Multiple Master Font"); break; #endif #ifdef T1ERR_SCAN_FILE_OPEN_ERR case T1ERR_SCAN_FILE_OPEN_ERR: i_push_error(T1ERR_SCAN_FILE_OPEN_ERR, "Type 1 Font File Open Error"); break; #endif #ifdef T1ERR_SCAN_OUT_OF_MEMORY case T1ERR_SCAN_OUT_OF_MEMORY: i_push_error(T1ERR_SCAN_OUT_OF_MEMORY, "Virtual Memory Exceeded"); break; #endif #ifdef T1ERR_SCAN_ERROR case T1ERR_SCAN_ERROR: i_push_error(T1ERR_SCAN_ERROR, "Syntactical Error Scanning Font File"); break; #endif #ifdef T1ERR_SCAN_FILE_EOF case T1ERR_SCAN_FILE_EOF: i_push_error(T1ERR_SCAN_FILE_EOF, "Premature End of Font File Encountered"); break; #endif #ifdef T1ERR_PATH_ERROR case T1ERR_PATH_ERROR: i_push_error(T1ERR_PATH_ERROR, "Path Construction Error"); break; #endif #ifdef T1ERR_PARSE_ERROR case T1ERR_PARSE_ERROR: i_push_error(T1ERR_PARSE_ERROR, "Font is Corrupt"); break; #endif #ifdef T1ERR_TYPE1_ABORT case T1ERR_TYPE1_ABORT: i_push_error(T1ERR_TYPE1_ABORT, "Rasterization Aborted"); break; #endif #ifdef T1ERR_INVALID_FONTID case T1ERR_INVALID_FONTID: i_push_error(T1ERR_INVALID_FONTID, "Font ID Invalid in this Context"); break; #endif #ifdef T1ERR_INVALID_PARAMETER case T1ERR_INVALID_PARAMETER: i_push_error(T1ERR_INVALID_PARAMETER, "Invalid Argument in Function Call"); break; #endif #ifdef T1ERR_OP_NOT_PERMITTED case T1ERR_OP_NOT_PERMITTED: i_push_error(T1ERR_OP_NOT_PERMITTED, "Operation not Permitted"); break; #endif #ifdef T1ERR_ALLOC_MEM case T1ERR_ALLOC_MEM: i_push_error(T1ERR_ALLOC_MEM, "Memory Allocation Error"); break; #endif #ifdef T1ERR_FILE_OPEN_ERR case T1ERR_FILE_OPEN_ERR: i_push_error(T1ERR_FILE_OPEN_ERR, "Error Opening File"); break; #endif #ifdef T1ERR_UNSPECIFIED case T1ERR_UNSPECIFIED: i_push_error(T1ERR_UNSPECIFIED, "Unspecified T1Lib Error"); break; #endif #ifdef T1ERR_NO_AFM_DATA case T1ERR_NO_AFM_DATA: i_push_error(T1ERR_NO_AFM_DATA, "Missing AFM Data"); break; #endif #ifdef T1ERR_X11 case T1ERR_X11: i_push_error(T1ERR_X11, "X11 Interface Error"); break; #endif #ifdef T1ERR_COMPOSITE_CHAR case T1ERR_COMPOSITE_CHAR: i_push_error(T1ERR_COMPOSITE_CHAR, "Missing Component of Composite Character"); break; #endif #ifdef T1ERR_SCAN_ENCODING case T1ERR_SCAN_ENCODING: i_push_error(T1ERR_SCAN_ENCODING, "Error Scanning Encoding File"); break; #endif default: i_push_errorf(T1_errno, "unknown error %d", (int)T1_errno); } #endif }
TT_Fonthandle* i_tt_new(const char *fontname) { TT_Error error; TT_Fonthandle *handle; unsigned short i,n; unsigned short platform,encoding; i_tt_engine *tteng; if ((tteng = i_init_tt()) == NULL) { i_push_error(0, "Could not initialize FT1 engine"); return NULL; } i_clear_error(); mm_log((1,"i_tt_new(fontname '%s')\n",fontname)); /* allocate memory for the structure */ handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */ /* load the typeface */ error = TT_Open_Face( tteng->engine, fontname, &handle->face ); if ( error ) { myfree(handle); if ( error == TT_Err_Could_Not_Open_File ) { mm_log((1, "Could not find/open %s.\n", fontname )); } else { mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname, (unsigned)error )); } i_tt_push_error(error); return NULL; } TT_Get_Face_Properties( handle->face, &(handle->properties) ); /* First, look for a Unicode charmap */ n = handle->properties.num_CharMaps; USTRCT( handle->char_map )=NULL; /* Invalidate character map */ for ( i = 0; i < n; i++ ) { TT_Get_CharMap_ID( handle->face, i, &platform, &encoding ); if ( (platform == 3 && encoding == 1 ) || (platform == 0 && encoding == 0 ) ) { mm_log((2,"i_tt_new - found char map platform %u encoding %u\n", platform, encoding)); TT_Get_CharMap( handle->face, i, &(handle->char_map) ); break; } } if (!USTRCT(handle->char_map) && n != 0) { /* just use the first one */ TT_Get_CharMap( handle->face, 0, &(handle->char_map)); } /* Zero the pointsizes - and ordering */ for(i=0;i<TT_CHC;i++) { USTRCT(handle->instanceh[i].instance)=NULL; handle->instanceh[i].order=i; handle->instanceh[i].ptsize=0; handle->instanceh[i].smooth=-1; } #ifdef FTXPOST handle->loaded_names = 0; #endif mm_log((1,"i_tt_new <- %p\n",handle)); return handle; }
static int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) { unsigned short load_flags, code; TT_Error error; mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n", handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.'))); /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/ if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) { mm_log((1,"i_tt_get_glyph: %lu in cache\n",j)); return 1; } if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) { /* clean up the entry */ TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ); USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL; handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR; } /* Ok - it wasn't cached - try to get it in */ load_flags = TTLOAD_SCALE_GLYPH; if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH; if ( !TT_VALID(handle->char_map) ) { code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1); if ( code >= handle->properties.num_Glyphs ) code = 0; } else code = TT_Char_Index( handle->char_map, j ); if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) { mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error )); i_push_error(error, "TT_New_Glyph()"); return 0; } if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) { mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error )); /* Don't leak */ TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ); USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL; i_push_error(error, "TT_Load_Glyph()"); return 0; } /* At this point the glyph should be allocated and loaded */ handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j; /* Next get the glyph metrics */ error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, &handle->instanceh[inst].gmetrics[TT_HASH(j)] ); if (error) { mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error )); TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ); USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL; handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR; i_push_error(error, "TT_Get_Glyph_Metrics()"); return 0; } return 1; }
undef_int i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl, double points,const char* str,size_t len,int align, int utf8, char const *flags, int aa) { GLYPH *glyph; int xsize,ysize,y; int mod_flags = t1_get_flags(flags); i_render *r; int fontnum = font->font_id; mm_log((1, "i_t1_text(font %p (%d), im %p, (xb,yb)=" i_DFp ", cl (%d,%d,%d,%d), points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n", font, fontnum, im, i_DFcp(xb, yb), cl->rgba.r, cl->rgba.g, cl->rgba.b, cl->rgba.a, points, str, (unsigned)len, align, utf8, flags, aa)); i_clear_error(); if (im == NULL) { i_push_error(0, "null image"); mm_log((1,"i_t1_text: Null image in input\n")); return(0); } i_mutex_lock(mutex); i_t1_set_aa(aa); if (utf8) { int worklen; char *work = t1_from_utf8(str, len, &worklen); if (!work) { i_mutex_unlock(mutex); return 0; } glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL); myfree(work); } else { /* T1_AASetString() accepts a char * not a const char */ glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL); } if (glyph == NULL) { mm_log((1, "T1_AASetString failed\n")); t1_push_error(); i_push_error(0, "i_t1_text(): T1_AASetString failed"); i_mutex_unlock(mutex); return 0; } mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent)); mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing)); mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY)); mm_log((1,"bpp: %lu\n",(unsigned long)glyph->bpp)); xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing; ysize=glyph->metrics.ascent-glyph->metrics.descent; mm_log((1,"width: %d height: %d\n",xsize,ysize)); if (align==1) { xb+=glyph->metrics.leftSideBearing; yb-=glyph->metrics.ascent; } r = i_render_new(im, xsize); for(y=0;y<ysize;y++) { i_render_color(r, xb, yb+y, xsize, (unsigned char *)glyph->bits+y*xsize, cl); } i_render_delete(r); i_mutex_unlock(mutex); return 1; }
/* =item i_tt_face_name(handle, name_buf, name_buf_size) Retrieve's the font's postscript name. This is complicated by the need to handle encodings and so on. =cut */ size_t i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) { TT_Face_Properties props; int name_count; int i; TT_UShort platform_id, encoding_id, lang_id, name_id; TT_UShort name_len; TT_String *name; int want_index = -1; /* an acceptable but not perfect name */ int score = 0; i_clear_error(); TT_Get_Face_Properties(handle->face, &props); name_count = props.num_Names; for (i = 0; i < name_count; ++i) { TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id, &name_id); TT_Get_Name_String(handle->face, i, &name, &name_len); if (platform_id != TT_PLATFORM_APPLE_UNICODE && name_len && name_id == TT_NAME_ID_PS_NAME) { int might_want_index = -1; int might_score = 0; if ((platform_id == TT_PLATFORM_MACINTOSH && encoding_id == TT_MAC_ID_ROMAN) || (platform_id == TT_PLATFORM_MICROSOFT && encoding_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) { /* exactly what we want */ want_index = i; break; } if (platform_id == TT_PLATFORM_MICROSOFT && (encoding_id & 0xFF) == TT_MS_LANGID_ENGLISH_GENERAL) { /* any english is good */ might_want_index = i; might_score = 9; } /* there might be something in between */ else { /* anything non-unicode is better than nothing */ might_want_index = i; might_score = 1; } if (might_score > score) { score = might_score; want_index = might_want_index; } } } if (want_index != -1) { TT_Get_Name_String(handle->face, want_index, &name, &name_len); strncpy(name_buf, name, name_buf_size); name_buf[name_buf_size-1] = '\0'; return strlen(name) + 1; } else { i_push_error(0, "no face name present"); return 0; } }
i_img * imss_x11(unsigned long display_ul, int window_id, int left, int top, int right, int bottom) { Display *display = (Display *)display_ul; int own_display = 0; /* non-zero if we connect */ XImage *image; XWindowAttributes attr; i_img *result; i_color *line, *cp; int x, y; XColor *colors; XErrorHandler old_handler; int width, height; i_clear_error(); /* we don't want the default noisy error handling */ old_handler = XSetErrorHandler(my_handler); if (!display) { display = XOpenDisplay(NULL); ++own_display; if (!display) { XSetErrorHandler(old_handler); i_push_error(0, "No display supplied and cannot connect"); return NULL; } } if (!window_id) { int screen = DefaultScreen(display); window_id = RootWindow(display, screen); } if (!XGetWindowAttributes(display, window_id, &attr)) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "Cannot XGetWindowAttributes"); return NULL; } /* adjust negative/zero values to window size */ if (left < 0) left += attr.width; if (top < 0) top += attr.height; if (right <= 0) right += attr.width; if (bottom <= 0) bottom += attr.height; /* clamp */ if (left < 0) left = 0; if (right > attr.width) right = attr.width; if (top < 0) top = 0; if (bottom > attr.height) bottom = attr.height; /* validate */ if (right <= left || bottom <= top) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "image would be empty"); return NULL; } width = right - left; height = bottom - top; image = XGetImage(display, window_id, left, top, width, height, -1, ZPixmap); if (!image) { XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_push_error(0, "Cannot XGetImage"); return NULL; } result = i_img_8_new(width, height, 3); line = mymalloc(sizeof(i_color) * width); colors = mymalloc(sizeof(XColor) * width); for (y = 0; y < height; ++y) { cp = line; /* XQueryColors seems to be a round-trip, so do one big request instead of one per pixel */ for (x = 0; x < width; ++x) { colors[x].pixel = XGetPixel(image, x, y); } XQueryColors(display, attr.colormap, colors, width); for (x = 0; x < width; ++x) { cp->rgb.r = colors[x].red >> 8; cp->rgb.g = colors[x].green >> 8; cp->rgb.b = colors[x].blue >> 8; ++cp; } i_plin(result, 0, width, y, line); } myfree(line); myfree(colors); XDestroyImage(image); XSetErrorHandler(old_handler); if (own_display) XCloseDisplay(display); i_tags_setn(&result->tags, "ss_window_width", attr.width); i_tags_setn(&result->tags, "ss_window_height", attr.height); i_tags_set(&result->tags, "ss_type", "X11", 3); i_tags_setn(&result->tags, "ss_left", left); i_tags_setn(&result->tags, "ss_top", top); return result; }
undef_int i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa) { GLYPH *glyph; int xsize,ysize,x,y; i_color val; int mod_flags = t1_get_flags(flags); int fontnum = font->font_id; unsigned int ch_mask_store; i_clear_error(); mm_log((1, "i_t1_cp(font %p (%d), im %p, (xb,yb)=" i_DFp ", channel %d, points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n", font, fontnum, im, i_DFcp(xb, yb), channel, points, str, (unsigned)len, align, utf8, flags, aa)); if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); i_push_error(0, "null image"); return(0); } i_mutex_lock(mutex); i_t1_set_aa(aa); if (utf8) { int worklen; char *work = t1_from_utf8(str, len, &worklen); if (work == NULL) { i_mutex_unlock(mutex); return 0; } glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL); myfree(work); } else { glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL); } if (glyph == NULL) { t1_push_error(); i_push_error(0, "i_t1_cp: T1_AASetString failed"); i_mutex_unlock(mutex); return 0; } mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent)); mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing)); mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY)); mm_log((1,"bpp: %lu\n", (unsigned long)glyph->bpp)); xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing; ysize=glyph->metrics.ascent-glyph->metrics.descent; mm_log((1,"width: %d height: %d\n",xsize,ysize)); ch_mask_store=im->ch_mask; im->ch_mask=1<<channel; if (align==1) { xb+=glyph->metrics.leftSideBearing; yb-=glyph->metrics.ascent; } for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) { val.channel[channel]=glyph->bits[y*xsize+x]; i_ppix(im,x+xb,y+yb,&val); } im->ch_mask=ch_mask_store; i_mutex_unlock(mutex); return 1; }
static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[BOUNDING_BOX_COUNT], int utf8 ) { int upm, casc, cdesc, first; int start = 0; i_img_dim width = 0; int gdescent = 0; int gascent = 0; int descent = 0; int ascent = 0; int rightb = 0; unsigned long j; mm_log((1,"i_tt_box_inst(handle %p,inst %d,txt '%.*s', len %ld, utf8 %d)\n", handle, inst, (int)len, txt, (long)len, utf8)); upm = handle->properties.header->Units_Per_EM; gascent = ( handle->properties.horizontal->Ascender * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm; gdescent = ( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem - upm + 1) / upm; width = 0; start = 0; mm_log((1, "i_tt_box_inst: gascent=%d gdescent=%d\n", gascent, gdescent)); first=1; while (len) { if (utf8) { j = i_utf8_advance(&txt, &len); if (j == ~0UL) { i_push_error(0, "invalid UTF8 character"); return 0; } } else { j = (unsigned char)*txt++; --len; } if ( i_tt_get_glyph(handle,inst,j) ) { TT_Glyph_Metrics *gm = handle->instanceh[inst].gmetrics + TT_HASH(j); width += gm->advance / 64; casc = (gm->bbox.yMax+63) / 64; cdesc = (gm->bbox.yMin-63) / 64; mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n", (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc)); if (first) { start = gm->bbox.xMin / 64; ascent = (gm->bbox.yMax+63) / 64; descent = (gm->bbox.yMin-63) / 64; first = 0; } if (!len) { /* if at end of string */ /* the right-side bearing - in case the right-side of a character goes past the right of the advance width, as is common for italic fonts */ rightb = gm->advance - gm->bearingX - (gm->bbox.xMax - gm->bbox.xMin); /* fprintf(stderr, "font info last: %d %d %d %d\n", gm->bbox.xMax, gm->bbox.xMin, gm->advance, rightb); */ } ascent = (ascent > casc ? ascent : casc ); descent = (descent < cdesc ? descent : cdesc); } } cords[BBOX_NEG_WIDTH]=start; cords[BBOX_GLOBAL_DESCENT]=gdescent; cords[BBOX_POS_WIDTH]=width; if (rightb < 0) cords[BBOX_POS_WIDTH] -= rightb / 64; cords[BBOX_GLOBAL_ASCENT]=gascent; cords[BBOX_DESCENT]=descent; cords[BBOX_ASCENT]=ascent; cords[BBOX_ADVANCE_WIDTH] = width; cords[BBOX_RIGHT_BEARING] = rightb / 64; return BBOX_RIGHT_BEARING + 1; }