Example #1
0
int
_PGFT_TryLoadFont_RWops(FreeTypeInstance *ft,
        PgFaceObject *faceobj, SDL_RWops *src, int face_index)
{
    FT_Stream stream;
    int position;

    position = SDL_RWtell(src);
    if (position < 0) {
        RAISE(PyExc_SDLError, "Failed to seek in font stream");
        return -1;
    }

    stream = _PGFT_malloc(sizeof(*stream));
    if (!stream) {
        PyErr_NoMemory();
        return -1;
    }
    memset(stream, 0, sizeof(*stream));
    stream->read = RWops_read;
    stream->descriptor.pointer = src;
    stream->pos = (unsigned long)position;
    SDL_RWseek(src, 0, SEEK_END);
    stream->size = (unsigned long)(SDL_RWtell(src) - position);
    SDL_RWseek(src, position, SEEK_SET);

    faceobj->id.face_index = face_index;
    faceobj->id.open_args.flags = FT_OPEN_STREAM;
    faceobj->id.open_args.stream = stream;

    return init(ft, faceobj);
}
Example #2
0
int
_PGFT_TryLoadFont_Filename(FreeTypeInstance *ft,
    PgFaceObject *faceobj,
    const char *filename,
    int face_index)
{
    char *filename_alloc;
    size_t file_len;

    file_len = strlen(filename);
    filename_alloc = _PGFT_malloc(file_len + 1);
    if (!filename_alloc) {
        PyErr_NoMemory();
        return -1;
    }

    strcpy(filename_alloc, filename);
    filename_alloc[file_len] = 0;

    faceobj->id.face_index = face_index;
    faceobj->id.open_args.flags = FT_OPEN_PATHNAME;
    faceobj->id.open_args.pathname = filename_alloc;

    return init(ft, faceobj);
}
Example #3
0
/*********************************************************
 *
 * Library (de)initialization
 *
 *********************************************************/
int
_PGFT_Init(FreeTypeInstance **_instance, int cache_size)
{
    FreeTypeInstance *inst = 0;
    int error;

    inst = _PGFT_malloc(sizeof(FreeTypeInstance));

    if (!inst) {
        PyErr_NoMemory();
        goto error_cleanup;
    }

    memset(inst, 0, sizeof(FreeTypeInstance));
    inst->cache_size = cache_size;

    error = FT_Init_FreeType(&inst->library);
    if (error) {
        RAISE(PyExc_RuntimeError,
              "pygame (_PGFT_Init): failed to initialize FreeType library");
        goto error_cleanup;
    }

    if (FTC_Manager_New(inst->library, 0, 0, 0,
            &_PGFT_face_request, 0,
            &inst->cache_manager) != 0) {
        RAISE(PyExc_RuntimeError,
              "pygame (_PGFT_Init): failed to create new FreeType manager");
        goto error_cleanup;
    }

    if (FTC_CMapCache_New(inst->cache_manager,
            &inst->cache_charmap) != 0) {
        RAISE(PyExc_RuntimeError,
              "pygame (_PGFT_Init): failed to create new FreeType cache");
        goto error_cleanup;
    }

    *_instance = inst;
    return 0;

error_cleanup:
    _PGFT_Quit(inst);
    *_instance = 0;

    return -1;
}
Example #4
0
static int init(FreeTypeInstance *ft, PgFaceObject *faceobj)
{
    faceobj->_internals = 0;

    if (!_PGFT_GetFace(ft, faceobj)) {
        RAISE(PyExc_IOError, _PGFT_GetError(ft));
        return -1;
    }

    faceobj->_internals = _PGFT_malloc(sizeof(FaceInternals));
    if (!faceobj->_internals) {
        PyErr_NoMemory();
        return -1;
    }
    memset(faceobj->_internals, 0x0, sizeof(FaceInternals));

    if (_PGFT_FaceTextInit(ft, faceobj)) {
        _PGFT_free(faceobj->_internals);
        faceobj->_internals = 0;
        return -1;
    }

    return 0;
}
Example #5
0
FontText *
_PGFT_LoadFontText(FreeTypeInstance *ft, PgFontObject *fontobj,
                   const FontRenderMode *mode, PGFT_String *text)
{
    Py_ssize_t  string_length = PGFT_String_GET_LENGTH(text);

    PGFT_char * buffer = PGFT_String_GET_DATA(text);
    PGFT_char * buffer_end;
    PGFT_char * ch;

    FontText    *ftext = &(PGFT_INTERNALS(fontobj)->active_text);
    FontGlyph   *glyph = 0;
    FontGlyph   **glyph_array = 0;
    FontMetrics *metrics;
    FT_BitmapGlyph image;
    TextContext context;

    FT_Face     font;
    FT_Size_Metrics *sz_metrics;

    FT_Vector   pen = {0, 0};                /* untransformed origin  */
    FT_Vector   pen1 = {0, 0};
    FT_Vector   pen2;

    FT_Vector   *next_pos;

    int         vertical = mode->render_flags & FT_RFLAG_VERTICAL;
    int         use_kerning = mode->render_flags & FT_RFLAG_KERNING;
    int         pad = mode->render_flags & FT_RFLAG_PAD;
    FT_UInt     prev_glyph_index = 0;

    /* All these are 16.16 precision */
    FT_Angle    rotation_angle = mode->rotation_angle;

    /* All these are 26.6 precision */
    FT_Vector   kerning;
    FT_Pos      min_x = FX6_MAX;
    FT_Pos      max_x = FX6_MIN;
    FT_Pos      min_y = FX6_MAX;
    FT_Pos      max_y = FX6_MIN;
    FT_Pos      glyph_width;
    FT_Pos      glyph_height;
    FT_Pos      top = FX6_MIN;
    FT_Fixed    y_scale;

    FT_Error    error = 0;

    /* load our sized font */
    font = _PGFT_GetFontSized(ft, fontobj, mode->pt_size);
    if (!font) {
        PyErr_SetString(PyExc_SDLError, _PGFT_GetError(ft));
        return 0;
    }
    sz_metrics = &font->size->metrics;
    y_scale = sz_metrics->y_scale;

    /* cleanup the cache */
    _PGFT_Cache_Cleanup(&ftext->glyph_cache);

    /* create the text struct */
    if (string_length > ftext->buffer_size) {
        _PGFT_free(ftext->glyphs);
        ftext->glyphs = (FontGlyph **)
                        _PGFT_malloc((size_t)string_length * sizeof(FontGlyph *));
        if (!ftext->glyphs) {
            PyErr_NoMemory();
            return 0;
        }

        _PGFT_free(ftext->posns);
        ftext->posns = (FT_Vector *)
                       _PGFT_malloc((size_t)string_length * sizeof(FT_Vector));
        if (!ftext->posns) {
            PyErr_NoMemory();
            return 0;
        }
        ftext->buffer_size = string_length;
    }
    ftext->length = string_length;
    ftext->ascender = sz_metrics->ascender;
    ftext->underline_pos = -FT_MulFix(font->underline_position, y_scale);
    ftext->underline_size = FT_MulFix(font->underline_thickness, y_scale);
    if (mode->style & FT_STYLE_STRONG) {
        FT_Fixed bold_str = mode->strength * sz_metrics->x_ppem;

        ftext->underline_size = FT_MulFix(ftext->underline_size,
                                          FX16_ONE + bold_str / 4);
    }

    /* fill it with the glyphs */
    fill_context(&context, ft, fontobj, mode, font);
    glyph_array = ftext->glyphs;
    next_pos = ftext->posns;

    for (ch = buffer, buffer_end = ch + string_length; ch < buffer_end; ++ch) {
        pen2.x = pen1.x;
        pen2.y = pen1.y;
        pen1.x = pen.x;
        pen1.y = pen.y;
        /*
         * Load the corresponding glyph from the cache
         */
        glyph = _PGFT_Cache_FindGlyph(*((FT_UInt32 *)ch), mode,
                                      &ftext->glyph_cache, &context);

        if (!glyph) {
            --ftext->length;
            continue;
        }
        image = glyph->image;
        glyph_width = glyph->width;
        glyph_height = glyph->height;

        /*
         * Do size calculations for all the glyphs in the text
         */
        if (use_kerning && prev_glyph_index) {
            error = FT_Get_Kerning(font, prev_glyph_index,
                                   glyph->glyph_index,
                                   FT_KERNING_UNFITTED, &kerning);
            if (error) {
                _PGFT_SetError(ft, "Loading glyphs", error);
                PyErr_SetString(PyExc_SDLError, _PGFT_GetError(ft));
                return 0;
            }
            if (rotation_angle != 0) {
                FT_Vector_Rotate(&kerning, rotation_angle);
            }
            pen.x += FX6_ROUND(kerning.x);
            pen.y += FX6_ROUND(kerning.y);
            if (FT_Vector_Length(&pen2) > FT_Vector_Length(&pen)) {
                pen.x = pen2.x;
                pen.y = pen2.y;
            }
        }

        prev_glyph_index = glyph->glyph_index;
        metrics = vertical ? &glyph->v_metrics : &glyph->h_metrics;
        if (metrics->bearing_rotated.y > top) {
            top = metrics->bearing_rotated.y;
        }
        if (pen.x + metrics->bearing_rotated.x < min_x) {
            min_x = pen.x + metrics->bearing_rotated.x;
        }
        if (pen.x + metrics->bearing_rotated.x + glyph_width > max_x) {
            max_x = pen.x + metrics->bearing_rotated.x + glyph_width;
        }
        next_pos->x = pen.x + metrics->bearing_rotated.x;
        pen.x += metrics->advance_rotated.x;
        if (vertical) {
            if (pen.y + metrics->bearing_rotated.y < min_y) {
                min_y = pen.y + metrics->bearing_rotated.y;
            }
            if (pen.y + metrics->bearing_rotated.y + glyph_height > max_y) {
                max_y = pen.y + metrics->bearing_rotated.y + glyph_height;
            }
            next_pos->y = pen.y + metrics->bearing_rotated.y;
            pen.y += metrics->advance_rotated.y;
        }
        else {
            if (pen.y - metrics->bearing_rotated.y < min_y) {
                min_y = pen.y - metrics->bearing_rotated.y;
            }
            if (pen.y - metrics->bearing_rotated.y + glyph_height > max_y) {
                max_y = pen.y - metrics->bearing_rotated.y + glyph_height;
            }
            next_pos->y = pen.y - metrics->bearing_rotated.y;
            pen.y -= metrics->advance_rotated.y;
        }
        *glyph_array++ = glyph;
        ++next_pos;
    }

    if (ftext->length == 0) {
        min_x = 0;
        max_x = 0;
        if (vertical) {
            ftext->min_y = 0;
            max_y = sz_metrics->height;
        }
        else {
            FT_Size_Metrics *sz_metrics = &font->size->metrics;

            min_y = -sz_metrics->ascender;
            max_y = -sz_metrics->descender;
        }
    }

    if (pad) {
        FT_Size_Metrics *sz_metrics = &font->size->metrics;

        if (pen.x > max_x) {
            max_x = pen.x;
        }
        else if (pen.x < min_x) {
            min_x = pen.x;
        }
        if (pen.y > max_y) {
            max_y = pen.y;
        }
        else if (pen.y < min_y) {
            min_y = pen.y;
        }
        if (vertical) {
            FT_Fixed right = sz_metrics->max_advance / 2;

            if (max_x < right) {
                max_x = right;
            }
            if (min_x > -right) {
                min_x = -right;
            }
            if (min_y > 0) {
                min_y = 0;
            }
            else if (max_y < pen.y) {
                max_y = pen.y;
            }
        }
        else {
            FT_Fixed ascender = sz_metrics->ascender;
            FT_Fixed descender = sz_metrics->descender;

            if (min_x > 0) {
                min_x = 0;
            }
            if (max_x < pen.x) {
                max_x = pen.x;
            }
            if (min_y > -ascender) {
                min_y = -ascender;
            }
            if (max_y <= -descender) {
                max_y = -descender + /* baseline */ FX6_ONE;
            }
        }
    }

    ftext->left = FX6_TRUNC(FX6_FLOOR(min_x));
    ftext->top = FX6_TRUNC(FX6_CEIL(top));
    ftext->min_x = min_x;
    ftext->max_x = max_x;
    ftext->min_y = min_y;
    ftext->max_y = max_y;
    ftext->advance.x = pen.x;
    ftext->advance.y = pen.y;

    return ftext;
}