真 もわ爛漫

しゃーら、しゃーらしゃーら

うみねこのMusic Modeが ONScripter on Linux で動かない件

さっきからずーっと調べてるのだが分からないのでとりあえずメモ。

ONScripterLabel_text.cpp の実装で

#define DLOG(a) ({printf("%s\n", (a)); fflush(stdout);})

...

void ONScripterLabel::drawGlyph( SDL_Surface *dst_surface, FontInfo *info, SDL_Color &color, char* text, int xy[2], bool shadow_flag, AnimationInfo *cache_info, SDL_Rect *clip, SDL_Rect &dst_rect )
{
    unsigned short unicode;
    if (IS_TWO_BYTE(text[0])){
        unsigned index = *1;
#endif    
    TTF_GlyphMetrics( (TTF_Font*)info->ttf_font, unicode,
                      &minx, &maxx, &miny, &maxy, &advanced );
    //printf("min %d %d %d %d %d %d\n", minx, maxx, miny, maxy, advanced,TTF_FontAscent((TTF_Font*)info->ttf_font)  );
    DLOG("drawGlyph 3");
    // test
    static SDL_Color fcol={0xff, 0xff, 0xff}, bcol={0, 0, 0};
    // SDL_Surface *tmp_surface = renderGlyph( (TTF_Font*)info->ttf_font, unicode );
    SDL_Surface *tmp_surface = TTF_RenderGlyph_Shaded( (TTF_Font*)info->ttf_font, unicode, fcol, bcol );
    DLOG("drawGlyph 4");

    bool rotate_flag = false;
    if ( info->getTateyokoMode() == FontInfo::TATE_MODE && IS_ROTATION_REQUIRED(text) ) rotate_flag = true;

    dst_rect.x = xy[0] + minx;
    dst_rect.y = xy[1] + TTF_FontAscent((TTF_Font*)info->ttf_font) - maxy;
    if ( rotate_flag ) dst_rect.x += miny - minx;

    if ( info->getTateyokoMode() == FontInfo::TATE_MODE && IS_TRANSLATION_REQUIRED(text) ){
        dst_rect.x += info->font_size_xy[0]/2;
        dst_rect.y -= info->font_size_xy[0]/2;
    }

    if ( shadow_flag ){
        dst_rect.x += shade_distance[0];
        dst_rect.y += shade_distance[1];
    }

    if ( tmp_surface ){
        if (rotate_flag){
            dst_rect.w = tmp_surface->h;
            dst_rect.h = tmp_surface->w;
        }
        else{
            dst_rect.w = tmp_surface->w;
            dst_rect.h = tmp_surface->h;
        }

        if (cache_info)
            cache_info->blendBySurface( tmp_surface, dst_rect.x, dst_rect.y, color, clip, rotate_flag );

        if (dst_surface)
            alphaBlend32( dst_surface, dst_rect, tmp_surface, color, clip, rotate_flag );

        // test
        printf("refcount %d\n", tmp_surface->refcount);
        DLOG("drawGlyph 5");
        SDL_FreeSurface(tmp_surface);
        DLOG("drawGlyph 6");
    }
}

"drawGlyph 6" が表示されないか、SDL_FreeSurface()の中で落ちる。

SDL_ttf 2.0.7:

Render the glyph for the UNICODE ch using font with fg color onto a new surface filled with the bg color, using the Shaded mode (see section Shaded). The caller (you!) is responsible for freeing any returned surface.

SDL_FreeSurface() を呼ぶのは正しい気がするんだがなー。

      • -

もう少し調べてみたら以下のようなことが分かった。

"SDL_Surface *tmp_surface = TTF_RenderGlyph_Shaded( (TTF_Font*)info->ttf_font, unicode, fcol, bcol );" の部分で TTF_RenderUNICODE_Shaded() を使うと問題ない。

ただしフォントの位置計算がその関数用になってないので以下のような感じになる。

とりあえずここまでにしとくかー。

*1:unsigned char*)text)[0]; index = index << 8 | ((unsigned char*)text)[1]; unicode = convSJIS2UTF16( index ); } else{ if ((text[0] & 0xe0) == 0xa0 || (text[0] & 0xe0) == 0xc0) unicode = ((unsigned char*)text)[0] - 0xa0 + 0xff60; else unicode = text[0]; } int minx, maxx, miny, maxy, advanced; #if 0 if (TTF_GetFontStyle( (TTF_Font*)info->ttf_font ) != (info->is_bold?TTF_STYLE_BOLD:TTF_STYLE_NORMAL) ) TTF_SetFontStyle( (TTF_Font*)info->ttf_font, (info->is_bold?TTF_STYLE_BOLD:TTF_STYLE_NORMAL