font_factory::font_factory(void) :
    nbEnt(0), // Note: this "ents" cache only keeps fonts from being unreffed, does not speed up access
    maxEnt(32),
    ents(static_cast<font_entry*>(g_malloc(maxEnt*sizeof(font_entry)))),

#ifdef USE_PANGO_WIN32
    fontServer(pango_win32_font_map_for_display()),
    fontContext(pango_win32_get_context()),
    pangoFontCache(pango_win32_font_map_get_font_cache(fontServer)),
    hScreenDC(pango_win32_get_dc()),
#else
    fontServer(pango_ft2_font_map_new()),
    fontContext(0),
#endif
    fontSize(512),
    loadedPtr(new FaceMapType())
{
#ifdef USE_PANGO_WIN32
#else
    pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer),
                                      72, 72);
    
    fontContext = pango_font_map_create_context(fontServer);

    pango_ft2_font_map_set_default_substitute(PANGO_FT2_FONT_MAP(fontServer),
                                              FactorySubstituteFunc,
                                              this,
                                              NULL);
#endif
}
Exemple #2
0
static void
init_uniscribe (void)
{
#ifdef HAVE_USP10_H
    HMODULE usp10_dll;

    have_uniscribe = FALSE;

    if ((usp10_dll = LoadLibrary ("usp10.dll")) != NULL)
    {
        (script_get_properties = (pScriptGetProperties)
                                 GetProcAddress (usp10_dll, "ScriptGetProperties")) &&
        (script_itemize = (pScriptItemize)
                          GetProcAddress (usp10_dll, "ScriptItemize")) &&
        (script_shape = (pScriptShape)
                        GetProcAddress (usp10_dll, "ScriptShape")) &&
        (script_place = (pScriptPlace)
                        GetProcAddress (usp10_dll, "ScriptPlace")) &&
        (script_free_cache = (pScriptFreeCache)
                             GetProcAddress (usp10_dll, "ScriptFreeCache")) &&
        (script_is_complex = (pScriptIsComplex)
                             GetProcAddress (usp10_dll, "ScriptIsComplex")) &&
        (have_uniscribe = TRUE);
    }
    if (have_uniscribe)
    {
#ifdef BASIC_WIN32_DEBUGGING
        (*script_get_properties) (&scripts, &nscripts);
#endif
        hdc = pango_win32_get_dc ();
    }
#endif
}
PangoFontDescription *Layout::InputStreamTextSource::styleGetFontDescription() const
{
    if (style->text == NULL) return NULL;
    PangoFontDescription *descr = pango_font_description_new();
    // Pango can't cope with spaces before or after the commas - let's remove them.
    // this code is not exactly unicode-safe, but it's similar to what's done in
    // pango, so it's not the limiting factor
    Glib::ustring family;
    if (style->text->font_family.value == NULL) {
        family = "Sans";
    } else {
        gchar **families = g_strsplit(style->text->font_family.value, ",", -1);
        if (families) {
            for (gchar **f = families ; *f ; ++f) {
                g_strstrip(*f);
                if (!family.empty()) family += ',';
                family += *f;
            }
        }
        g_strfreev(families);
    }

    pango_font_description_set_family(descr,family.c_str());
    pango_font_description_set_weight(descr,(PangoWeight)_enum_converter(style->font_weight.computed,  enum_convert_spstyle_weight_to_pango_weight,   sizeof(enum_convert_spstyle_weight_to_pango_weight)/sizeof(enum_convert_spstyle_weight_to_pango_weight[0])));
    pango_font_description_set_style(descr,(PangoStyle)_enum_converter(style->font_style.computed,   enum_convert_spstyle_style_to_pango_style,     sizeof(enum_convert_spstyle_style_to_pango_style)/sizeof(enum_convert_spstyle_style_to_pango_style[0])));
    pango_font_description_set_variant(descr,(PangoVariant)_enum_converter(style->font_variant.computed, enum_convert_spstyle_variant_to_pango_variant, sizeof(enum_convert_spstyle_variant_to_pango_variant)/sizeof(enum_convert_spstyle_variant_to_pango_variant[0])));
#ifdef USE_PANGO_WIN32
    // damn Pango fudges the size, so we need to unfudge. See source of pango_win32_font_map_init()
    pango_font_description_set_size(descr, (int) ((font_factory::Default())->fontSize*PANGO_SCALE*72/GetDeviceCaps(pango_win32_get_dc(),LOGPIXELSY))); // mandatory huge size (hinting workaround)
    // we don't set stretch on Win32, because pango-win32 has no concept of it
    // (Windows doesn't really provide any useful field it could use).
    // If we did set stretch, then any text with a font-stretch attribute would
    // end up falling back to Arial.
#else
    pango_font_description_set_size(descr, (int) ((font_factory::Default())->fontSize*PANGO_SCALE)); // mandatory huge size (hinting workaround)
    pango_font_description_set_stretch(descr,(PangoStretch)_enum_converter(style->font_stretch.computed, enum_convert_spstyle_stretch_to_pango_stretch, sizeof(enum_convert_spstyle_stretch_to_pango_stretch)/sizeof(enum_convert_spstyle_stretch_to_pango_stretch[0])));
#endif
    return descr;
}
font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail)
{
#ifdef USE_PANGO_WIN32
    // damn Pango fudges the size, so we need to unfudge. See source of pango_win32_font_map_init()
    pango_font_description_set_size(descr, (int) (fontSize*PANGO_SCALE*72/GetDeviceCaps(pango_win32_get_dc(),LOGPIXELSY))); // mandatory huge size (hinting workaround)
#else
    pango_font_description_set_size(descr, (int) (fontSize*PANGO_SCALE)); // mandatory huge size (hinting workaround)
#endif

    font_instance *res = NULL;

    FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr);
    if ( loadedFaces.find(descr) == loadedFaces.end() ) {
        // not yet loaded
        PangoFont *nFace = NULL;

        // workaround for bug #1025565.
        // fonts without families blow up Pango.
        if (sp_font_description_get_family(descr) != NULL) {
            nFace = pango_font_map_load_font(fontServer,fontContext,descr);
        }
        else {
            g_warning("%s", _("Ignoring font without family that will crash Pango"));
        }

        if ( nFace ) {
            // duplicate FcPattern, the hard way
            res = new font_instance();
            // store the descr of the font we asked for, since this is the key where we intend
            // to put the font_instance at in the unordered_map.  the descr of the returned
            // pangofont may differ from what was asked, so we don't know (at this
            // point) whether loadedFaces[that_descr] is free or not (and overwriting
            // an entry will bring deallocation problems)
            res->descr = pango_font_description_copy(descr);
            res->parent = this;
            res->InstallFace(nFace);
            if ( res->pFont == NULL ) {
                // failed to install face -> bitmap font
                // printf("face failed\n");
                res->parent = NULL;
                delete res;
                res = NULL;
                if ( canFail ) {
                    char *tc = pango_font_description_to_string(descr);
                    PANGO_DEBUG("falling back from %s to 'sans-serif' because InstallFace failed\n",tc);
                    g_free(tc);
                    pango_font_description_set_family(descr,"sans-serif");
                    res = Face(descr,false);
                }
            } else {
                loadedFaces[res->descr]=res;
                res->Ref();
                AddInCache(res);
            }
        } else {
            // no match
            if ( canFail ) {
                PANGO_DEBUG("falling back to 'sans-serif'\n");
                descr = pango_font_description_new();
                pango_font_description_set_family(descr,"sans-serif");
                res = Face(descr,false);
                pango_font_description_free(descr);
            }
        }
    } else {
        // already here
        res = loadedFaces[descr];
        res->Ref();
        AddInCache(res);
    }
    if (res) {
        res->InitTheFace();
    }
    return res;
}