Пример #1
0
main()
{
    gs_glyph g;
        gs_char c;
    gs_const_string str;

    /* Test with a short name. */
    g = gs_c_known_encode((gs_char)0237, 1); /* caron */
    printf("caron is %u, should be %u\n",
           g - gs_c_min_std_encoding_glyph, I_caron);
    gs_c_glyph_name(g, &str);
    fwrite(str.data, 1, str.size, stdout);
    printf(" should be caron\n");

    /* Test with a long name. */
    g = gs_c_known_encode((gs_char)0277, 2); /* carriagereturn */
    printf("carriagereturn is %u, should be %u\n",
           g - gs_c_min_std_encoding_glyph, I_carriagereturn);
    gs_c_glyph_name(g, &str);
    fwrite(str.data, 1, str.size, stdout);
    printf(" should be carriagereturn\n");

    /* Test lookup with 3 kinds of names. */
    g = gs_c_name_glyph((const byte *)"circlemultiply", 14);
    printf("circlemultiply is %u, should be %u\n",
           g - gs_c_min_std_encoding_glyph, I_circlemultiply);
    g = gs_c_name_glyph((const byte *)"numbersign", 10);
    printf("numbersign is %u, should be %u\n",
           g - gs_c_min_std_encoding_glyph, I_numbersign);
    g = gs_c_name_glyph((const byte *)"copyright", 9);
    printf("copyright is %u, should be %u\n",
           g - gs_c_min_std_encoding_glyph, I_copyright);

    /* Test reverse lookup */
    c = gs_c_decode(I_caron + gs_c_min_std_encoding_glyph, 1);
    printf("%u (caron) looked up as %u, should be %u\n",
     I_caron, c, 0237);
    c = gs_c_decode(I_carriagereturn + gs_c_min_std_encoding_glyph, 2);
    printf("%u (carriagereturn) looked up as %u, should be %u\n",
     I_carriagereturn, c, 0277);
    c = gs_c_decode(I_notdefined + gs_c_min_std_encoding_glyph, 1); /* undef'd */
    printf("%u (notdefined) looked up as %d , should be %d\n",
     I_notdefined, c, GS_NO_CHAR);

    exit(0);
}
Пример #2
0
/* Compute the FontDescriptor metrics for a font. */
int
pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
{
    gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false);
    gs_glyph glyph, notdef;
    int index;
    int wmode = bfont->WMode;
    int members = (GLYPH_INFO_WIDTH0 << wmode) |
        GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
    pdf_font_descriptor_values_t desc;
    gs_matrix smat;
    gs_matrix *pmat = NULL;
    int fixed_width = 0;
    int small_descent = 0, small_height = 0;
    bool small_present = false;
    int x_height = 0;
    int cap_height = 0;
    gs_rect bbox_colon, bbox_period, bbox_I;
    bool is_cid = (bfont->FontType == ft_CID_encrypted ||
                   bfont->FontType == ft_CID_TrueType);
    bool have_colon = false, have_period = false, have_I = false;
    int code;

    memset(&bbox_colon, 0, sizeof(bbox_colon)); /* quiet gcc warnings. */
    memset(&bbox_period, 0, sizeof(bbox_period)); /* quiet gcc warnings. */
    memset(&bbox_I, 0, sizeof(bbox_I)); /* quiet gcc warnings. */
    memset(&desc, 0, sizeof(desc));
    if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x &&
                  bfont->FontBBox.p.y != bfont->FontBBox.q.y) {
        int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1);

        desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
        desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale);
        desc.FontBBox.q.x = (int)(bfont->FontBBox.q.x * scale);
        desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale);
        desc.Ascent = desc.FontBBox.q.y;
        members &= ~GLYPH_INFO_BBOX;
    } else {
        desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
        desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
    }
    /*
     * Embedded TrueType fonts use a 1000-unit character space, but the
     * font itself uses a 1-unit space.  Compensate for this here.
     */
    switch (bfont->FontType) {
    case ft_TrueType:
    case ft_CID_TrueType:
        gs_make_scaling(1000.0, 1000.0, &smat);
        pmat = &smat;
        /* Type 3 fonts may use a FontMatrix in PDF, so we don't
         * need to deal with non-standard matrices
         */
    case ft_GL2_531:
    case ft_PCL_user_defined:
    case ft_GL2_stick_user_defined:
    case ft_MicroType:
    case ft_user_defined:
        break;
        /* Other font types may use a non-standard (not 1000x1000) design grid
         * The FontMatrix is used to map to the unit square. However PDF files
         * don't allow FontMatrix entries, all fonts are nominally 1000x1000.
         * If we have a font with a non-standard matrix we must account for that
         * here by scaling the font outline.
         */
    default:
        gs_matrix_scale(&bfont->FontMatrix, 1000.0, 1000.0, &smat);
        pmat = &smat;
        break;
    }

    /*
     * Scan the entire glyph space to compute Ascent, Descent, FontBBox, and
     * the fixed width if any.  For non-symbolic fonts, also note the
     * bounding boxes for Latin letters and a couple of other characters,
     * for computing the remaining descriptor values (CapHeight,
     * ItalicAngle, StemV, XHeight, and flags SERIF, SCRIPT, ITALIC,
     * ALL_CAPS, and SMALL_CAPS).  (The algorithms are pretty crude.)
     */
    notdef = GS_NO_GLYPH;
    for (index = 0;
         (bfont->procs.enumerate_glyph((gs_font *)bfont, &index,
                (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 &&
             index != 0;
         ) {
        gs_glyph_info_t info;
        gs_const_string gname;
        gs_glyph glyph_known_enc;
        gs_char position=0;

        code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info);
        if (code == gs_error_VMerror)
            return code;
        if (code < 0) {
            /*
             * Since this function may be indirtectly called from gx_device_finalize,
             * we are unable to propagate error code to the interpreter.
             * Therefore we skip it here hoping that few errors can be
             * recovered by the integration through entire glyph set.
             */
            continue;
        }
        if (members & GLYPH_INFO_BBOX) {
            /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/
            if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x;
            if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x;
            if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y;
            if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y;
            if (!info.num_pieces)
                desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y);
        }
        if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) {
            notdef = glyph;
            desc.MissingWidth = (int)info.width[wmode].x;
        }
        if (info.width[wmode].y != 0)
            fixed_width = min_int;
        else if (fixed_width == 0)
            fixed_width = (int)info.width[wmode].x;
        else if (info.width[wmode].x != fixed_width)
            fixed_width = min_int;
        if (desc.Flags & FONT_IS_SYMBOLIC)
            continue;		/* skip Roman-only computation */
        if (is_cid)
            continue;
        code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname);
        if (code < 0) {
            /* If we fail to get the glyph name, best assume this is a symbolic font */
            desc.Flags |= FONT_IS_SYMBOLIC;
            continue;
        }
        /* See if the glyph name is in any of the known encodings */
        glyph_known_enc = gs_c_name_glyph(gname.data, gname.size);
        if (glyph_known_enc == gs_no_glyph) {
            desc.Flags |= FONT_IS_SYMBOLIC;
            continue;
        }
        /* Finally check if the encoded glyph is in Standard Encoding */
        /* gs_c_decode always fails to find .notdef, its always present so
         * don't worry about it
         */
        if(strncmp(".notdef", (const char *)gname.data, gname.size)) {
            position = gs_c_decode(glyph_known_enc, 0);
            if (position == GS_NO_CHAR) {
                desc.Flags |= FONT_IS_SYMBOLIC;
                continue;
            }
        }
        switch (gname.size) {
        case 5:
            if (!memcmp(gname.data, "colon", 5))
                bbox_colon = info.bbox, have_colon = true;
            continue;
        case 6:
            if (!memcmp(gname.data, "period", 6))
                bbox_period = info.bbox, have_period = true;
            continue;
        case 1:
            break;
        default:
            continue;
        }

        if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') {
            cap_height = max(cap_height, (int)info.bbox.q.y);
            if (gname.data[0] == 'I')
                bbox_I = info.bbox, have_I = true;
        } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') {
            int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y);

            small_present = true;
            switch (gname.data[0]) {
            case 'b': case 'd': case 'f': case 'h':
            case 'k': case 'l': case 't': /* ascender */
                small_height = max(small_height, y1);
            case 'i':		/* anomalous ascent */
                break;
            case 'j':		/* descender with anomalous ascent */
                small_descent = min(small_descent, y0);
                break;
            case 'g': case 'p': case 'q': case 'y': /* descender */
                small_descent = min(small_descent, y0);
            default:		/* no ascender or descender */
                x_height = max(x_height, y1);
            }
        }
    }
    if (!(desc.Flags & FONT_IS_SYMBOLIC)) {
        desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
        desc.XHeight = (int)x_height;
        if (!small_present && (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType))
            desc.Flags |= FONT_IS_ALL_CAPS;
        desc.CapHeight = cap_height;
        /*
         * Look at various glyphs to determine ItalicAngle, StemV,
         * SERIF, SCRIPT, and ITALIC.
         */
        if (have_colon && have_period) {
            /* Calculate the dominant angle. */
            int angle =
                (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) -
                              (bbox_period.q.y - bbox_period.p.y),
                            (bbox_colon.q.x - bbox_colon.p.x) -
                              (bbox_period.q.x - bbox_period.p.x)) *
                      radians_to_degrees) - 90;

            /* Normalize to [-90..90]. */
            while (angle > 90)
                angle -= 180;
            while (angle < -90)
                angle += 180;
            if (angle < -30)
                angle = -30;
            else if (angle > 30)
                angle = 30;
            /*
             * For script or embellished fonts, we can get an angle that is
             * slightly off from zero even for non-italic fonts.
             * Compensate for this now.
             */
            if (angle <= 2 && angle >= -2)
                angle = 0;
            desc.ItalicAngle = angle;
        }
        if (desc.ItalicAngle)
            desc.Flags |= FONT_IS_ITALIC;
        if (have_I) {
            double wdot = bbox_period.q.x - bbox_period.p.x;
            double wcolon = bbox_I.q.x - bbox_I.p.x;
            double wI = bbox_period.q.x - bbox_period.p.x;

            desc.StemV = (int)wdot;
            if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25)
                desc.Flags |= FONT_IS_SERIF;
        }
    }
    if (desc.Ascent == 0)
        desc.Ascent = desc.FontBBox.q.y;
    desc.Descent = desc.FontBBox.p.y;
    if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
        (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9) &&
        (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType)
        )
        desc.Flags |= FONT_IS_SMALL_CAPS;
    if (fixed_width > 0 && (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType)) {
        desc.Flags |= FONT_IS_FIXED_WIDTH;
        desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
    }
    if (desc.CapHeight == 0)
        desc.CapHeight = desc.Ascent;
    if (desc.StemV == 0)
        desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
    pfd->common.values = desc;
    return 0;
}