static void *load_library(const char *name) { char pathname[MAXPATHLEN], symbol[255]; #ifdef _WIN32 HINSTANCE handle; #else void *handle; const char *error; #endif void *entry = NULL; sprintf(pathname, "%s.%s", name, EXTENSION); #ifdef _WIN32 handle = LoadLibrary(pathname); #else handle = dlopen(pathname, RTLD_LAZY); if (handle == NULL) { sprintf(pathname, "%s/%s.%s", "./", name, EXTENSION); handle = dlopen(pathname, RTLD_LAZY); } if (handle == NULL) { sprintf(pathname, "%s/lib/%s.%s", GRDIR, name, EXTENSION); handle = dlopen(pathname, RTLD_LAZY); } #endif if (handle != NULL) { sprintf(symbol, "gks_%s", name); #ifdef _WIN32 entry = GetProcAddress(handle, symbol); #else entry = dlsym(handle, symbol); #endif if (entry == NULL) { #ifdef _WIN32 gks_perror("%s: unresolved symbol", symbol); #else if ((error = dlerror()) != NULL) gks_perror((char *) error); #endif } } else { #ifdef _WIN32 gks_perror("%s: can't load library", pathname); #else if ((error = dlerror()) != NULL) gks_perror((char *) error); #endif } return entry; }
void gks_drv_mac( int fctid, int dx, int dy, int dimx, int *ia, int lr1, double *r1, int lr2, double *r2, int lc, char *chars, void **ptr) { if (fctid == 2) { #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 gks_perror("Quickdraw is deprecated\nConsider using the Quartz driver"); #else gks_perror("Carbon support not compiled in"); #endif ia[0] = 0; } }
/* load a glyph into the slot and compute bearing */ static FT_Error set_glyph(FT_Face face, FT_UInt codepoint, FT_UInt *previous, FT_Vector *pen, FT_Bool vertical, FT_Matrix *rotation, FT_Vector *bearing, FT_Int halign) { FT_Error error; FT_UInt glyph_index; glyph_index = FT_Get_Char_Index(face, codepoint); if (FT_HAS_KERNING(face) && *previous && !vertical && glyph_index) { FT_Vector delta; FT_Get_Kerning(face, *previous, glyph_index, FT_KERNING_DEFAULT, &delta); FT_Vector_Transform(&delta, rotation); pen->x += delta.x; pen->y += delta.y; } error = FT_Load_Glyph(face, glyph_index, vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT); if (error) { gks_perror("glyph could not be loaded: %c", codepoint); return 1; } error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); if (error) { gks_perror("glyph could not be rendered: %c", codepoint); return 1; } *previous = glyph_index; bearing->x = face->glyph->metrics.horiBearingX; bearing->y = 0; if (vertical) { if (halign == GKS_K_TEXT_HALIGN_RIGHT) { bearing->x += face->glyph->metrics.width; } else if (halign == GKS_K_TEXT_HALIGN_CENTER) { bearing->x += face->glyph->metrics.width / 2; } if (bearing->x != 0) FT_Vector_Transform(bearing, rotation); bearing->x = 64 * face->glyph->bitmap_left - bearing->x; bearing->y = 64 * face->glyph->bitmap_top - bearing->y; } else { if (bearing->x != 0) FT_Vector_Transform(bearing, rotation); pen->x -= bearing->x; pen->y -= bearing->y; bearing->x = 64 * face->glyph->bitmap_left; bearing->y = 64 * face->glyph->bitmap_top; } return 0; }
static void set_font(int font) { double rad, scale, ux, uy; int family, size, angle; double width, height, capheight; StyleParameter face; Str255 name; font = abs(font); if (font >= 101 && font <= 129) font -= 100; else if (font >= 1 && font <= 32) font = map[font - 1]; else font = 9; WC_to_NDC_rel(gkss->chup[0], gkss->chup[1], gkss->cntnr, ux, uy); seg_xform_rel(&ux, &uy); rad = -atan2(ux, uy); angle = (int)(rad * 180 / M_PI + 0.5); if (angle < 0) angle += 360; p->path = ((angle + 45) / 90) % 4; scale = sqrt(gkss->chup[0] * gkss->chup[0] + gkss->chup[1] * gkss->chup[1]); ux = gkss->chup[0] / scale * gkss->chh; uy = gkss->chup[1] / scale * gkss->chh; WC_to_NDC_rel(ux, uy, gkss->cntnr, ux, uy); width = 0; height = sqrt(ux * ux + uy * uy); seg_xform_rel(&width, &height); height = sqrt(width * width + height * height); capheight = nint(height * (fabs(p->c) + 1)); p->capheight = nint(capheight); size = nint(capheight / capheights[font - 1]); if (font > 13) font += 3; p->family = (font - 1) / 4; face = (font % 4 == 1 || font % 4 == 2) ? normal : bold; if (font % 4 == 2 || font % 4 == 0) face |= italic; CopyCStringToPascal(fonts[p->family], name); family = FMGetFontFamilyFromName(name); if (family != kInvalidFontFamily) { TextFont(family); TextFace(face); TextSize(size); } else gks_perror("invalid font family (%s)", fonts[p->family]); }
/* set text string, converting UTF-8 into Unicode */ static void utf_to_unicode(FT_Bytes str, FT_UInt *unicode_string, int *length) { FT_UInt num_glyphs = 0; FT_UInt codepoint; FT_Byte following_bytes; FT_Byte offset; int i, j; for (i = 0; i < *length; i++) { if (str[i] < 128) { offset = 0; following_bytes = 0; } else if (str[i] < 128+64+32) { offset = 128+64; following_bytes = 1; } else if (str[i] < 128+64+32+16) { offset = 128+64+32; following_bytes = 2; } else if (str[i] < 128+64+32+16+8) { offset = 128+64+32+16; following_bytes = 3; } else { gks_perror("character ignored due to unicode error"); continue; } codepoint = str[i] - offset; for (j = 0; j < following_bytes; j++) { codepoint = codepoint * 64; i++; if (str[i] < 128 || str[i] >= 128+64) { gks_perror("character ignored due to unicode error"); continue; } codepoint += str[i] - 128; } unicode_string[num_glyphs] = codepoint; num_glyphs++; } unicode_string[num_glyphs] = '\0'; *length = num_glyphs; }
int gks_ft_init(void) { FT_Error error; if (init) return 0; error = FT_Init_FreeType(&library); if (error) { gks_perror("could not initialize freetype library"); init = 0; } else { init = 1; } return error; }
static FT_Pointer safe_realloc(FT_Pointer ptr, size_t size) { FT_Pointer tmp; if (ptr) { tmp = malloc(size); } else { tmp = realloc(ptr, size); } if (tmp != NULL) { ptr = tmp; } else { gks_perror("out of memory"); ptr = NULL; } return ptr; }
static void *load_library(const char *name) { char pathname[MAXPATHLEN], symbol[255]; #ifdef _WIN32 HINSTANCE handle; LPCTSTR grdir; char grbin[MAXPATHLEN]; #else void *handle; const char *grdir, *error; #endif void *entry = NULL; sprintf(pathname, "%s.%s", name, EXTENSION); #ifdef _WIN32 handle = LoadLibrary(pathname); if (handle == NULL) { grdir = gks_getenv("GRDIR"); if (grdir == NULL) grdir = GRDIR; sprintf(grbin, "%s/bin", grdir); SetDllDirectory(grbin); handle = LoadLibrary(pathname); } #else handle = dlopen(pathname, RTLD_LAZY); if (handle == NULL) { sprintf(pathname, "%s/%s.%s", "./", name, EXTENSION); handle = dlopen(pathname, RTLD_LAZY); } if (handle == NULL) { grdir = gks_getenv("GRDIR"); if (grdir == NULL) grdir = GRDIR; sprintf(pathname, "%s/lib/%s.%s", grdir, name, EXTENSION); handle = dlopen(pathname, RTLD_LAZY); } #endif if (handle != NULL) { sprintf(symbol, "gks_%s", name); #ifdef _WIN32 entry = (void *)GetProcAddress(handle, symbol); #else entry = dlsym(handle, symbol); #endif if (entry == NULL) { #ifdef _WIN32 gks_perror("%s: unresolved symbol", symbol); #else if ((error = dlerror()) != NULL) gks_perror((char *)error); #endif } } else { #ifdef _WIN32 DWORD ec = 0; ec = GetLastError(); gks_perror("%s: can't load library, error %d (0x%x)", pathname, ec, ec); #else if ((error = dlerror()) != NULL) gks_perror((char *)error); #endif } return entry; }
void gks_drv_socket(int fctid, int dx, int dy, int dimx, int *ia, int lr1, double *r1, int lr2, double *r2, int lc, char *chars, void **ptr) { ws_state_list *wss; const char *command = NULL, *env; int retry_count; char *cmd = NULL; wss = (ws_state_list *)*ptr; switch (fctid) { case 2: gkss = (gks_state_list_t *)*ptr; wss = (ws_state_list *)gks_malloc(sizeof(ws_state_list)); if (ia[2] == 411) { command = gks_getenv("GKS_QT"); if (command == NULL) { env = gks_getenv("GRDIR"); if (env == NULL) env = GRDIR; cmd = (char *)gks_malloc(MAXPATHLEN); #ifndef _WIN32 #ifdef __APPLE__ sprintf(cmd, "%s/Applications/gksqt.app/Contents/MacOS/gksqt", env); #else sprintf(cmd, "%s/bin/gksqt", env); #endif #else sprintf(cmd, "%s\\bin\\gksqt.exe", env); #endif command = cmd; } } for (retry_count = 1; retry_count <= 10; retry_count++) { if ((wss->s = connect_socket(retry_count != 10)) == -1) { if (command != NULL && retry_count == 1) { if (start(command) != 0) gks_perror("could not auto-start GKS Qt application"); } #ifndef _WIN32 usleep(300000); #else Sleep(300); #endif } else break; } if (cmd != NULL) free(cmd); if (wss->s == -1) { gks_perror("can't connect to GKS socket application\n" "Did you start 'gksqt'?\n"); gks_free(wss); wss = NULL; ia[0] = ia[1] = 0; } else *ptr = wss; break; case 3: close_socket(wss->s); if (wss->dl.buffer) { free(wss->dl.buffer); } gks_free(wss); wss = NULL; break; case 8: if (ia[1] & GKS_K_PERFORM_FLAG) { send_socket(wss->s, (char *)&wss->dl.nbytes, sizeof(int)); send_socket(wss->s, wss->dl.buffer, wss->dl.nbytes); } break; } if (wss != NULL) { gks_dl_write_item(&wss->dl, fctid, dx, dy, dimx, ia, lr1, r1, lr2, r2, lc, chars, gkss); } }
int gks_ft_init(void) { gks_perror("FreeType support not compiled in"); init = 1; return 1; }
unsigned char *gks_ft_get_bitmap(int *x, int *y, int *width, int *height, gks_state_list_t *gkss, const char *text, int length) { FT_Face face; /* font face */ FT_Vector pen; /* glyph position */ FT_BBox bb; /* bounding box */ FT_Vector bearing; /* individual glyph translation */ FT_UInt previous; /* previous glyph index */ FT_Vector spacing; /* amount of additional space between glyphs */ FT_ULong textheight; /* textheight in FreeType convention */ FT_Error error; /* error code */ FT_Matrix rotation; /* text rotation matrix */ FT_UInt size; /* number of pixels of the bitmap */ FT_String *file; /* concatenated font path */ const FT_String *font, *prefix; /* font file name and directory */ FT_UInt *unicode_string; /* unicode text string */ FT_Int halign, valign; /* alignment */ FT_Byte *mono_bitmap = NULL; /* target for rendered text */ FT_Int num_glyphs; /* number of glyphs */ FT_Vector align; FT_Bitmap ftbitmap; FT_UInt codepoint; int i, textfont, dx, dy, value, pos_x, pos_y; unsigned int j, k; double angle; const int windowwidth = *width; const int direction = (gkss->txp <= 3 && gkss->txp >= 0 ? gkss->txp : 0); const FT_Bool vertical = (direction == GKS_K_TEXT_PATH_DOWN || direction == GKS_K_TEXT_PATH_UP); const FT_String *suffix_type1 = ".afm"; if (!init) gks_ft_init(); if (gkss->txal[0] != GKS_K_TEXT_HALIGN_NORMAL) { halign = gkss->txal[0]; } else if (vertical) { halign = GKS_K_TEXT_HALIGN_CENTER; } else if (direction == GKS_K_TEXT_PATH_LEFT) { halign = GKS_K_TEXT_HALIGN_RIGHT; } else { halign = GKS_K_TEXT_HALIGN_LEFT; } valign = gkss->txal[1]; if (valign != GKS_K_TEXT_VALIGN_NORMAL) { valign = gkss->txal[1]; } else { valign = GKS_K_TEXT_VALIGN_BASE; } textfont = abs(gkss->txfont); if (textfont >= 101 && textfont <= 131) textfont -= 100; else if (textfont > 1 && textfont <= 32) textfont = map[textfont - 1]; else textfont = 9; textfont = textfont - 1; font = gks_font_list[textfont]; if (font_face_cache[textfont] == NULL) { prefix = gks_getenv("GKS_FONTPATH"); if (prefix == NULL) { prefix = gks_getenv("GRDIR"); if (prefix == NULL) prefix = GRDIR; } file = (FT_String *) malloc(strlen(prefix) + 7 + strlen(font) + 4 + 1); strcpy(file, prefix); #ifndef _WIN32 strcat(file, "/fonts/"); #else strcat(file, "\\FONTS\\"); #endif strcat(file, font); strcat(file, ".pfb"); error = FT_New_Face(library, file, 0, &face); if (error == FT_Err_Unknown_File_Format) { gks_perror("unknown file format: %s", file); return NULL; } else if (error) { gks_perror("could not open font file: %s", file); return NULL; } if (strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0) { strcpy(file, prefix); #ifndef _WIN32 strcat(file, "/fonts/"); #else strcat(file, "\\FONTS\\"); #endif strcat(file, font); strcat(file, suffix_type1); FT_Attach_File(face, file); } free(file); font_face_cache[textfont] = face; } else { face = font_face_cache[textfont]; } num_glyphs = length; unicode_string = (FT_UInt *) malloc(length * sizeof(FT_UInt) + 1); if (textfont + 1 == 13) { symbol_to_unicode((FT_Bytes)text, unicode_string, num_glyphs); } else { utf_to_unicode((FT_Bytes)text, unicode_string, &num_glyphs); } textheight = nint(gkss->chh * windowwidth * 64 / caps[textfont]); error = FT_Set_Char_Size(face, nint(textheight * gkss->chxp), textheight, 72, 72); if (error) gks_perror("cannot set text height"); if (gkss->chup[0] != 0.0 || gkss->chup[1] != 0.0) { angle = atan2f(gkss->chup[1], gkss->chup[0]) - M_PI / 2; rotation.xx = nint( cosf(angle) * 0x10000L); rotation.xy = nint(-sinf(angle) * 0x10000L); rotation.yx = nint( sinf(angle) * 0x10000L); rotation.yy = nint( cosf(angle) * 0x10000L); FT_Set_Transform(face, &rotation, NULL); } else { FT_Set_Transform(face, NULL, NULL); } spacing.x = spacing.y = 0; if (gkss->chsp != 0.0) { error = FT_Load_Glyph(face, FT_Get_Char_Index(face, ' '), vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT); if (!error) { spacing.x = nint(face->glyph->advance.x * gkss->chsp); spacing.y = nint(face->glyph->advance.y * gkss->chsp); } else { gks_perror("cannot apply character spacing"); } } bb.xMin = bb.yMin = LONG_MAX; bb.xMax = bb.yMax = LONG_MIN; pen.x = pen.y = 0; previous = 0; for (i = 0; i < num_glyphs; i++) { codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ? (num_glyphs - 1 - i) : i]; error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation, &bearing, halign); if (error) continue; bb.xMin = ft_min(bb.xMin, pen.x + bearing.x); bb.xMax = ft_max(bb.xMax, pen.x + bearing.x + 64*face->glyph->bitmap.width); bb.yMin = ft_min(bb.yMin, pen.y + bearing.y - 64*face->glyph->bitmap.rows); bb.yMax = ft_max(bb.yMax, pen.y + bearing.y); if (direction == GKS_K_TEXT_PATH_DOWN) { pen.x -= face->glyph->advance.x + spacing.x; pen.y -= face->glyph->advance.y + spacing.y; } else { pen.x += face->glyph->advance.x + spacing.x; pen.y += face->glyph->advance.y + spacing.y; } } *width = (int)((bb.xMax - bb.xMin) / 64); *height = (int)((bb.yMax - bb.yMin) / 64); if (bb.xMax <= bb.xMin || bb.yMax <= bb.yMin) { gks_perror("invalid bitmap size"); free(unicode_string); return NULL; } size = *width * *height; mono_bitmap = (FT_Byte *) safe_realloc(mono_bitmap, size); memset(mono_bitmap, 0, size); pen.x = 0; pen.y = 0; previous = 0; for (i = 0; i < num_glyphs; i++) { bearing.x = bearing.y = 0; codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ? (num_glyphs - 1 - i) : i]; error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation, &bearing, halign); if (error) continue; pos_x = ( pen.x + bearing.x - bb.xMin) / 64; pos_y = (-pen.y - bearing.y + bb.yMax) / 64; ftbitmap = face->glyph->bitmap; for (j = 0; j < (unsigned int) ftbitmap.rows; j++) { for (k = 0; k < (unsigned int) ftbitmap.width; k++) { dx = k + pos_x; dy = j + pos_y; value = mono_bitmap[dy * *width + dx]; value += ftbitmap.buffer[j * ftbitmap.pitch + k]; if (value > 255) { value = 255; } mono_bitmap[dy * *width + dx] = value; } } if (direction == GKS_K_TEXT_PATH_DOWN) { pen.x -= face->glyph->advance.x + spacing.x; pen.y -= face->glyph->advance.y + spacing.y; } else { pen.x += face->glyph->advance.x + spacing.x; pen.y += face->glyph->advance.y + spacing.y; } } free(unicode_string); /* Alignment */ if (direction == GKS_K_TEXT_PATH_DOWN) { pen.x += spacing.x; pen.y += spacing.y; } else { pen.x -= spacing.x; pen.y -= spacing.y; } align.x = align.y = 0; if (valign != GKS_K_TEXT_VALIGN_BASE) { align.y = nint(gkss->chh * windowwidth * 64); FT_Vector_Transform(&align, &rotation); if (valign == GKS_K_TEXT_VALIGN_HALF) { align.x = nint(0.5 * align.x); align.y = nint(0.5 * align.y); } else if (valign == GKS_K_TEXT_VALIGN_TOP) { align.x = nint(1.2 * align.x); align.y = nint(1.2 * align.y); } else if (valign == GKS_K_TEXT_VALIGN_BOTTOM) { align.x = nint(-0.2 * align.x); align.y = nint(-0.2 * align.y); } } if (!vertical && halign != GKS_K_TEXT_HALIGN_LEFT) { FT_Vector right; right.x = face->glyph->metrics.width + face->glyph->metrics.horiBearingX; right.y = 0; if (right.x != 0) { FT_Vector_Transform(&right, &rotation); } pen.x += right.x - face->glyph->advance.x; pen.y += right.y - face->glyph->advance.y; if (halign == GKS_K_TEXT_HALIGN_CENTER) { align.x += pen.x / 2; align.y += pen.y / 2; } else if (halign == GKS_K_TEXT_HALIGN_RIGHT) { align.x += pen.x; align.y += pen.y; } } *x += (bb.xMin - align.x) / 64; *y += (bb.yMin - align.y) / 64; return mono_bitmap; }
void gks_fatal_error(const char *args, ...) { gks_perror(args); exit(-1); }
void gks_report_error(int routine, int errnum) { const char *name, *message; name = gks_function_name(routine); switch (errnum) { case 0: message = "normal successful completion"; break; case 1: message = "GKS not in proper state. GKS must be in the state\ GKCL in routine %s"; break; case 2: message = "GKS not in proper state. GKS must be in the state\ GKOP in routine %s"; break; case 3: message = "GKS not in proper state. GKS must be in the state\ WSAC in routine %s"; break; case 4: message = "GKS not in proper state. GKS must be in the state\ SGOP in routine %s"; break; case 5: message = "GKS not in proper state. GKS must be either in the\ state WSAC or SGOP in routine %s"; break; case 6: message = "GKS not in proper state. GKS must be either in the\ state WSOP or WSAC in routine %s"; break; case 7: message = "GKS not in proper state. GKS must be in one of the\ states WSOP,WSAC,SGOP in routine %s"; break; case 8: message = "GKS not in proper state. GKS must be in one of the\ states GKOP,WSOP,WSAC,SGOP in routine %s"; break; case 20: message = "Specified workstation identifier is invalid in\ routine %s"; break; case 21: message = "Specified connection identifier is invalid in\ routine %s"; break; case 22: message = "Specified workstation type is invalid in\ routine %s"; break; case 24: message = "Specified workstation is open in routine %s"; break; case 25: message = "Specified workstation is not open in\ routine %s"; break; case 26: message = "Specified workstation cannot be opened in\ routine %s"; break; case 27: message = "Workstation Independent Segment Storage is\ not open in routine %s"; break; case 28: message = "Workstation Independent Segment Storage is\ already open in routine %s"; break; case 29: message = "Specified workstation is active in routine %s"; break; case 30: message = "Specified workstation is not active in\ routine %s"; break; case 34: message = "Specified workstation is not of category MI in\ routine %s"; break; case 38: message = "Specified workstation is neither of category INPUT\ nor of category OUTIN in routine %s"; break; case 50: message = "Transformation number is invalid in routine %s"; break; case 51: message = "Rectangle definition is invalid in routine %s"; break; case 52: message = "Viewport is not within the NDC unit square in\ routine %s"; break; case 53: message = "Workstation window is not within the NDC unit square\ in routine %s"; break; case 60: message = "Polyline index is invalid in routine %s"; break; case 62: message = "Linetype is invalid in routine %s"; break; case 64: message = "Polymarker index is invalid in routine %s"; break; case 65: message = "Colour index is invalid in routine %s"; break; case 66: message = "Marker type is invalid in routine %s"; break; case 68: message = "Text index is invalid in routine %s"; break; case 70: message = "Text font is invalid in routine %s"; break; case 72: message = "Character expansion factor is invalid in\ routine %s"; break; case 73: message = "Character height is invalid in routine %s"; break; case 74: message = "Character up vector is invalid in routine %s"; break; case 75: message = "Fill area index is invalid in routine %s"; break; case 78: message = "Style index is invalid in routine %s"; break; case 81: message = "Pattern size value is invalid in routine %s"; break; case 84: message = "Dimensions of colour index array are invalid in\ routine %s"; break; case 85: message = "Colour index is invalid in routine %s"; break; case 88: message = "Colour is invalid in routine %s"; break; case 91: message = "Dimensions of color index array are invalid in\ routine %s"; break; case 100: message = "Number of points is invalid in routine %s"; break; case 161: message = "Item length is invalid in routine %s"; break; case 163: message = "Metafile item is invalid in routine %s"; break; case 164: message = "Item type is not a valid GKS item in\ routine %s"; break; case 401: message = "Dimensions of image are invalid in routine %s"; break; case 402: message = "Invalid image data pointer in routine %s"; break; case 403: message = "String is too long in routine %s"; break; case 404: message = "Subimage limitation reached in routine %s"; break; case 901: message = "Open failed in routine %s"; break; default: message = "unknown error"; } gks_errno = errnum; gks_perror(message, name); }