Last active
January 8, 2023 19:04
-
-
Save MurphyMc/7a5dfdd77d4a4cd267fc9eb1dfddd42d to your computer and use it in GitHub Desktop.
rfbLoadConsoleFont() replacement for better Linux PSF console font file support in libvncserver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // rfbLoadConsoleFont()'s documentation says that it loads a Linux console | |
| // font, but this is only kind of true. It's limited to loading 256 glyphs, | |
| // which... okay. It's also limited to fonts which are 8x16, which many are. | |
| // More annoyingly, however, it can't actually load from a PSF font file used | |
| // by Linux console fonts, since it doesn't account for the header. In many | |
| // cases, this means that just skipping the first four bytes would make it | |
| // work (it would have been nice if there were just a parameter to tell it | |
| // to do this, or if there was a version you could give a prepared FILE *). | |
| // This function *does* actually load from a PSF file. It wouldn't be too | |
| // hard to make it support v2, but it currently only supports v1 (however, | |
| // the fonts I tried during testing were all v1). It only supports the | |
| // first 256 glyphs even if there are more, and it ignores the Unicode and | |
| // character mapping stuff (again, I got away with this on the fonts I | |
| // tried since I am only immediately worried about ASCII support). It | |
| // does, however, support fonts of different heights. It also supports | |
| // reading from gzipped PSF files, which most of the ones installed by | |
| // default on my system are. | |
| // TLDR: This lets you load at least some normal Linux .psf console fonts | |
| // for use with libvncserver if all you care about is ASCII. | |
| rfbFontDataPtr load_psf_font (char * file) | |
| { | |
| int cmp = strlen(file) >= 3 && !strcmp(file+strlen(file)-3, ".gz"); | |
| int success = 0; | |
| FILE * f = NULL; | |
| gzFile gf = NULL; | |
| rfbFontDataPtr font = NULL; | |
| do | |
| { | |
| font = calloc(1, sizeof(*font)); | |
| if (!font) break; | |
| int magic1, magic2, mode, charsize; | |
| if (cmp) | |
| { | |
| gf = gzopen(file, "rb"); | |
| if (!gf) break; | |
| magic1 = gzgetc(gf); | |
| magic2 = gzgetc(gf); | |
| mode = gzgetc(gf); | |
| charsize = gzgetc(gf); | |
| } | |
| else | |
| { | |
| f = fopen(file, "rb"); | |
| if (!f) break; | |
| magic1 = fgetc(f); | |
| magic2 = fgetc(f); | |
| mode = fgetc(f); | |
| charsize = fgetc(f); | |
| } | |
| if (magic1 != 0x36 || magic2 != 0x04) break; // Not PSF v1 | |
| void * data = malloc(256*charsize); | |
| int * meta = malloc(256*5*4); | |
| font->data = data; | |
| font->metaData = meta; | |
| if (!data || !meta) break; | |
| size_t sz; | |
| if (cmp) | |
| sz = gzfread(data, 256*charsize, 1, gf); | |
| else | |
| sz = fread(data, 256*charsize, 1, f); | |
| if (sz != 1) break; | |
| for (int i = 0; i < 256; ++i) | |
| { | |
| meta[i*5+0] = i*charsize; | |
| meta[i*5+1] = 8; // PSF1 is always 8 pixels wide | |
| meta[i*5+2] = charsize; | |
| meta[i*5+3] = 0; | |
| meta[i*5+4] = 0; | |
| } | |
| success = 1; | |
| } while (0); | |
| if (f) fclose(f); | |
| if (gf) gzclose(gf); | |
| if (success) return font; | |
| rfbFreeFont(font); | |
| return NULL; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment