Ejemplo n.º 1
0
QStringList QBasicUnixFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file)
{
    extern FT_Library qt_getFreetype();
    FT_Library library = qt_getFreetype();

    int index = 0;
    int numFaces = 0;
    QStringList families;
    do {
        FT_Face face;
        FT_Error error;
        if (!fontData.isEmpty()) {
            error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
        } else {
            error = FT_New_Face(library, file.constData(), index, &face);
        }
        if (error != FT_Err_Ok) {
            qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
            break;
        }
        numFaces = face->num_faces;

        QFont::Weight weight = QFont::Normal;

        QFont::Style style = QFont::StyleNormal;
        if (face->style_flags & FT_STYLE_FLAG_ITALIC)
            style = QFont::StyleItalic;

        if (face->style_flags & FT_STYLE_FLAG_BOLD)
            weight = QFont::Bold;

        QSupportedWritingSystems writingSystems;
        // detect symbol fonts
        for (int i = 0; i < face->num_charmaps; ++i) {
            FT_CharMap cm = face->charmaps[i];
            if (cm->encoding == ft_encoding_adobe_custom
                    || cm->encoding == ft_encoding_symbol) {
                writingSystems.setSupported(QFontDatabase::Symbol);
                break;
            }
        }

        TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
        if (os2) {
            quint32 unicodeRange[4] = {
                quint32(os2->ulUnicodeRange1), quint32(os2->ulUnicodeRange2),
                quint32(os2->ulUnicodeRange3), quint32(os2->ulUnicodeRange4)
                    };
            quint32 codePageRange[2] = {
                quint32(os2->ulCodePageRange1), quint32(os2->ulCodePageRange2)
                    };

            writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
        }

        QString family = QString::fromAscii(face->family_name);
        FontFile *fontFile = new FontFile;
        fontFile->fileName = file;
        fontFile->indexValue = index;

        QFont::Stretch stretch = QFont::Unstretched;

        registerFont(family,"",weight,style,stretch,true,true,0,writingSystems,fontFile);

        families.append(family);

        FT_Done_Face(face);
        ++index;
    } while (index < numFaces);
    return families;
}
Ejemplo n.º 2
0
QStringList QBasicFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file, QSupportedWritingSystems *supportedWritingSystems)
{
    FT_Library library = qt_getFreetype();

    int index = 0;
    int numFaces = 0;
    QStringList families;
    do {
        FT_Face face;
        FT_Error error;
        if (!fontData.isEmpty()) {
            error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
        } else {
            error = FT_New_Face(library, file.constData(), index, &face);
        }
        if (error != FT_Err_Ok) {
            qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
            break;
        }
        numFaces = face->num_faces;

        QFont::Weight weight = QFont::Normal;

        QFont::Style style = QFont::StyleNormal;
        if (face->style_flags & FT_STYLE_FLAG_ITALIC)
            style = QFont::StyleItalic;

        if (face->style_flags & FT_STYLE_FLAG_BOLD)
            weight = QFont::Bold;

        bool fixedPitch = (face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);

        QSupportedWritingSystems writingSystems;
        // detect symbol fonts
        for (int i = 0; i < face->num_charmaps; ++i) {
            FT_CharMap cm = face->charmaps[i];
            if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM
                    || cm->encoding == FT_ENCODING_MS_SYMBOL) {
                writingSystems.setSupported(QFontDatabase::Symbol);
                if (supportedWritingSystems)
                    supportedWritingSystems->setSupported(QFontDatabase::Symbol);
                break;
            }
        }

        TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
        if (os2) {
            quint32 unicodeRange[4] = {
                quint32(os2->ulUnicodeRange1),
                quint32(os2->ulUnicodeRange2),
                quint32(os2->ulUnicodeRange3),
                quint32(os2->ulUnicodeRange4)
            };
            quint32 codePageRange[2] = {
                quint32(os2->ulCodePageRange1),
                quint32(os2->ulCodePageRange2)
            };

            writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
            if (supportedWritingSystems)
                *supportedWritingSystems = writingSystems;

            if (os2->usWeightClass == 0)
                ;
            else if (os2->usWeightClass < 350)
                weight = QFont::Light;
            else if (os2->usWeightClass < 450)
                weight = QFont::Normal;
            else if (os2->usWeightClass < 650)
                weight = QFont::DemiBold;
            else if (os2->usWeightClass < 750)
                weight = QFont::Bold;
            else if (os2->usWeightClass < 1000)
                weight = QFont::Black;

            if (os2->panose[2] >= 2) {
                int w = os2->panose[2];
                if (w <= 3)
                    weight = QFont::Light;
                else if (w <= 5)
                    weight = QFont::Normal;
                else if (w <= 7)
                    weight = QFont::DemiBold;
                else if (w <= 8)
                    weight = QFont::Bold;
                else if (w <= 10)
                    weight = QFont::Black;
            }
        }

        QString family = QString::fromLatin1(face->family_name);
        FontFile *fontFile = new FontFile;
        fontFile->fileName = QFile::decodeName(file);
        fontFile->indexValue = index;

        QFont::Stretch stretch = QFont::Unstretched;

        registerFont(family,QString::fromLatin1(face->style_name),QString(),weight,style,stretch,true,true,0,fixedPitch,writingSystems,fontFile);

        families.append(family);

        FT_Done_Face(face);
        ++index;
    } while (index < numFaces);
    return families;
}
Ejemplo n.º 3
0
static int
doDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
{
    char *dirname, *fontscale_name, *filename, *encdir;
    FILE *fontscale, *encfile;
    DIR *dirp;
    struct dirent *entry;
    FT_Error ftrc;
    FT_Face face;
    ListPtr encoding, xlfd, lp;
    HashTablePtr entries;
    HashBucketPtr *array;
    int i, n, found, rc;
    int isBitmap=0,xl=0;

    if (exclusionSuffix)
        xl = strlen (exclusionSuffix);

    i = strlen(dirname_given);
    if(i == 0)
        dirname = dsprintf("./");
    else if(dirname_given[i - 1] != '/')
        dirname = dsprintf("%s/", dirname_given);
    else
        dirname = dsprintf("%s", dirname_given);

    if(dirname == NULL) {
        perror("dirname");
        exit(1);
    }

    if (onlyEncodings)
	goto encodings;

    entries = makeHashTable();
    if(doBitmaps && !doScalable) {
        readFontScale(entries, dirname);
    }

    if(strcmp(outfilename, "-") == 0)
        fontscale_name = NULL;
    else {
        if(outfilename[0] == '/')
            fontscale_name = dsprintf("%s", outfilename);
        else
            fontscale_name = dsprintf("%s%s", dirname, outfilename);
        if(fontscale_name == NULL) {
            perror("fontscale_name");
            exit(1);
        }
    }

    dirp = opendir(dirname);
    if(dirp == NULL) {
        fprintf(stderr, "%s: ", dirname);
        perror("opendir");
        return 0;
    }

    if(fontscale_name == NULL)
        fontscale = stdout;
    else
        fontscale = fopen(fontscale_name, "wb");

    if(fontscale == NULL) {
        fprintf(stderr, "%s: ", fontscale_name);
        perror("fopen(w)");
        return 0;
    }

    while((entry = readdir(dirp)) != NULL) {
        int have_face = 0;
        char *xlfd_name = NULL;
	struct stat f_stat;
	int tprio = 1;

        xlfd = NULL;

	if (xl) {
	    int dl = strlen (entry->d_name);
	    if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
		continue;
	}

        filename = dsprintf("%s%s", dirname, entry->d_name);

#define PRIO(x) ((x << 1) + tprio)
#ifdef DT_LNK
	if (entry->d_type != DT_UNKNOWN) {
	    if (entry->d_type == DT_LNK)
		tprio = 0;
	} else
#endif
#ifdef S_ISLNK
	{
	    if (lstat(filename, &f_stat))
		goto done;
	    if (S_ISLNK(f_stat.st_mode))
		tprio = 0;
	}
#else
	;
#endif
        if(doBitmaps)
            rc = bitmapIdentify(filename, &xlfd_name);
        else
            rc = 0;

        if(rc < 0)
            goto done;

        if(rc == 0) {
            ftrc = FT_New_Face(ft_library, filename, 0, &face);
            if(ftrc)
                goto done;
            have_face = 1;

            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);

            if(!isBitmap) {
                /* Workaround for bitmap-only SFNT fonts */
                if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
                   strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
                    TT_MaxProfile *maxp;
                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
                    if(maxp != NULL && maxp->maxContours == 0)
                        isBitmap = 1;
                }
            }

            if(isBitmap) {
                if(!doBitmaps)
                    goto done;
            } else {
                if(!doScalable)
                    goto done;
            }

            if(isBitmap) {
                BDF_PropertyRec prop;
                rc = FT_Get_BDF_Property(face, "FONT", &prop);
                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
                    xlfd_name = strdup(prop.u.atom);
                    if(xlfd_name == NULL)
                        goto done;
                }
            }
        }

        if(xlfd_name) {
            /* We know it's a bitmap font, and we know its XLFD */
            int n = strlen(xlfd_name);
            if(reencodeLegacy &&
               n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
                char *s;

                s = malloc(n - 10);
                memcpy(s, xlfd_name, n - 11);
                s[n - 11] = '\0';
                xlfd = listCons(s, xlfd);
            } else {
                /* Not a reencodable font -- skip all the rest of the loop body */
                putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
                goto done;
            }
        }

        if(!have_face) {
            ftrc = FT_New_Face(ft_library, filename, 0, &face);
            if(ftrc)
                goto done;
            have_face = 1;
            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);

            if(!isBitmap) {
                if(face->num_fixed_sizes > 0) {
                    TT_MaxProfile *maxp;
                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
                    if(maxp != NULL && maxp->maxContours == 0)
                        isBitmap = 1;
                }
            }
        }

        if(xlfd == NULL)
            xlfd = makeXLFD(entry->d_name, face, isBitmap);

        found = 0;

        for(lp = xlfd; lp; lp = lp->next) {
            char buf[MAXFONTNAMELEN];
            for(encoding = encodings; encoding; encoding = encoding->next) {
                if(checkEncoding(face, encoding->value)) {
                    found = 1;
                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
                            lp->value, encoding->value);
                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
                }
            }
            for(encoding = extra_encodings; encoding;
                encoding = encoding->next) {
                if(checkExtraEncoding(face, encoding->value, found)) {
                    /* Do not set found! */
                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
                            lp->value, encoding->value);
                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
                }
            }
        }
    done:
        if(have_face)
            FT_Done_Face(face);
        deepDestroyList(xlfd);
        xlfd = NULL;
        free(filename);
#undef PRIO
    }

    closedir(dirp);
    n = hashElements(entries);
    fprintf(fontscale, "%d\n", n);
    array = hashArray(entries, 1);
    for(i = 0; i < n; i++)
        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
    destroyHashArray(array);
    entries = NULL;
    if(fontscale_name) {
        fclose(fontscale);
        free(fontscale_name);
    }

 encodings:
    encdir = dsprintf("%s%s", dirname, "encodings.dir");

    if(encdir == NULL) {
	perror("encodings");
	exit(1);
    }
    unlink(encdir);

    if (numEncodings) {
	encfile = fopen(encdir, "w");
	if(encfile == NULL) {
	    perror("open(encodings.dir)");
	    exit(1);
	}
        fprintf(encfile, "%d\n", numEncodings);
        encodingsToDo = sortList(encodingsToDo);
        for(lp = encodingsToDo; lp; lp = lp->next) {
            fprintf(encfile, "%s\n", lp->value);
        }
	fclose (encfile);
    }

    free(dirname);
    return 1;
}
Ejemplo n.º 4
0
int
FTPickMapping(char *xlfd, int length, char *filename, FT_Face face,
              FTMappingPtr tm)
{
    FontEncPtr encoding;
    FontMapPtr mapping;
    FT_CharMap cmap;
    int ftrc;
    int symbol = 0;
    const char *enc, *reg;
    char *encoding_name = 0;
    char buf[20];

    if(xlfd)
      encoding_name = FontEncFromXLFD(xlfd, length);
    if(!encoding_name)
        encoding_name = "iso8859-1";

    symbol = FTEncFontSpecific(encoding_name);

    ftrc = FT_Get_BDF_Charset_ID(face, &enc, &reg);
    if(ftrc == 0) {
        /* Disable reencoding for non-Unicode fonts.  This will
           currently only work for BDFs. */
        if(strlen(enc) + strlen(reg) > 18)
            goto native;
        strcpy(buf, enc);
        strcat(buf, "-");
        strcat(buf, reg);
        ErrorF("%s %s\n", buf, encoding_name);
        if(strcasecmp(buf, "iso10646-1") != 0) {
            if(strcasecmp(buf, encoding_name) == 0)
                goto native;
            return BadFontFormat;
        }
    } else if(symbol) {
        ftrc = FT_Select_Charmap(face, ft_encoding_adobe_custom);
        if(ftrc == 0)
            goto native;
    }

    encoding = FontEncFind(encoding_name, filename);
    if(symbol && encoding == NULL)
        encoding = FontEncFind("microsoft-symbol", filename);
    if(encoding == NULL) {
        ErrorF("FreeType: couldn't find encoding '%s' for '%s'\n",
               encoding_name, filename);
        return BadFontName;
    }

    if(FT_Has_PS_Glyph_Names(face)) {
        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
                tm->named = 1;
                tm->base = 0;
                tm->mapping = mapping;
                return Successful;
            }
        }
    }
    
    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face, 
                     &cmap)) {
            tm->named = 0;
            tm->cmap = cmap;
            if(symbol) {
                /* deal with an undocumented ``feature'' of the
                   Microsft-Symbol cmap */
                TT_OS2 *os2;
                os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
                if(os2)
                    tm->base = os2->usFirstCharIndex - 0x20;
                else
                    tm->base = 0;
            } else
                tm->base = 0;
            tm->mapping = mapping;
            return Successful;
        }
    }
    
    return BadFontFormat;

  native:
    tm->named = 0;
    tm->cmap = face->charmap;
    tm->base = 0;
    tm->mapping = NULL;
    return Successful;
}
Ejemplo n.º 5
0
ListPtr
makeXLFD(char *filename, FT_Face face, int isBitmap)
{
    ListPtr xlfd = NULL;
    const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
        *spacing, *full_name, *tmp;
    TT_Header *head;
    TT_HoriHeader *hhea;
    TT_OS2 *os2;
    TT_Postscript *post;
    PS_FontInfoRec *t1info, t1info_rec;
    int rc;

    foundry = NULL;
    family = NULL;
    weight = NULL;
    slant = NULL;
    sWidth = NULL;
    adstyle = NULL;
    spacing = NULL;
    full_name = NULL;

    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);

    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
    if(rc == 0)
        t1info = &t1info_rec;
    else
        t1info = NULL;

    if(!family)
        family = getName(face, TT_NAME_ID_FONT_FAMILY);
    if(!family)
        family = getName(face, TT_NAME_ID_FULL_NAME);
    if(!family)
        family = getName(face, TT_NAME_ID_PS_NAME);

    if(!full_name)
        full_name = getName(face, TT_NAME_ID_FULL_NAME);
    if(!full_name)
        full_name = getName(face, TT_NAME_ID_PS_NAME);

    if(os2 && os2->version != 0xFFFF) {
        if(!weight)
            weight = os2Weight(os2->usWeightClass);
        if(!sWidth)
            sWidth = os2Width(os2->usWidthClass);
        if(!foundry)
            foundry = vendor_foundry(os2->achVendID);
        if(!slant)
            slant = os2->fsSelection & 1 ? "i" : "r";
    }

    if(post) {
        if(!spacing) {
            if(post->isFixedPitch) {
                if(hhea->min_Left_Side_Bearing >= 0 &&
                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
                    spacing = "c";
                } else {
                    spacing = "m";
                }
            } else {
                spacing = "p";
            }
        }
    }

    if(t1info) {
        if(!family)
            family = strdup(t1info->family_name);
        if(!family)
            family = strdup(t1info->full_name);
        if(!full_name)
            full_name = strdup(t1info->full_name);
        if(!foundry)
            foundry = notice_foundry(t1info->notice);
        if(!weight)
            weight = t1Weight(t1info->weight);
        if(!spacing)
            spacing = t1info->is_fixed_pitch ? "m" : "p";
        if(!slant) {
            /* Bitstream fonts have positive italic angle. */
            slant =
                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
                "i" : "r";
        }
    }

    if(!full_name) {
        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
        full_name = strdup(filename);
    }

    if(head) {
        if(!slant)
            slant = head->Mac_Style & 2 ? "i" : "r";
        if(!weight)
            weight = head->Mac_Style & 1 ? "bold" : "medium";
    }

    if(!slant) {
        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
        slant = "r";
    }

    if(!weight) {
        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
        weight = "medium";
    }

    if(!foundry) {
        char *notice;
        notice = getName(face, TT_NAME_ID_TRADEMARK);
        if(notice) {
            foundry = notice_foundry(notice);
            free(notice);
        }
        if(!foundry) {
            notice = getName(face, TT_NAME_ID_MANUFACTURER);
            if(notice) {
                foundry = notice_foundry(notice);
                free(notice);
            }
        }
    }

    if(strcmp(slant, "i") == 0) {
        if(strstr(full_name, "Oblique"))
            slant = "o";
        if(strstr(full_name, "Slanted"))
            slant = "o";
    }

    if(!sWidth)
        sWidth = nameWidth(full_name);

    if(!foundry) foundry = "misc";
    if(!family) {
        fprintf(stderr, "Couldn't get family name for %s\n", filename);
        family = strdup(filename);
    }

    if(!weight) weight = "medium";
    if(!slant) slant = "r";
    if(!sWidth) sWidth = "normal";
    if(!adstyle) adstyle = "";
    if(!spacing) spacing = "p";

    foundry = safe(foundry);

    tmp = family;
    family = safe(family);
    free((void *)tmp);

    if(!isBitmap) {
        xlfd = listConsF(xlfd,
                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
                         foundry, family,
                         weight, slant, sWidth, adstyle, spacing);
    } else {
        int i, w, h, xres, yres;
        for(i = 0; i < face->num_fixed_sizes; i++) {
            w = face->available_sizes[i].width;
            h = face->available_sizes[i].height;
            xres = 75;
            yres = (double)h / w * xres;
            xlfd = listConsF(xlfd,
                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
                             foundry, family,
                             weight, slant, sWidth, adstyle,
                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
                             xres, yres,
                             spacing, 60);
        }
    }

    free((void *)family);
    free((void *)foundry);
    free((void *)full_name);
    return xlfd;
}