void
CBShellEditor::InsertText
	(
	const JString& text
	)
{
	JIndex index;
	const JBoolean hadCaret = GetCaretLocation(&index);

	SetCaretLocation(itsInsertIndex);
	SetCurrentFont(itsInsertFont);
	const JSize count = PasteUNIXTerminalOutput(text);
	SetCurrentFont(GetDefaultFont());
	ClearUndo();

	itsInsertIndex += count;
	if (hadCaret)
		{
		index += count;
		SetCaretLocation(index);
		}

	const JIndex i = itsInsertIndex-1;
	if (GetFontStyle(i).bold)
		{
		SetFontBold(i, i, kJFalse, kJTrue);
		}
}
Example #2
0
// Create font from font attributes.
wxFont wxTextAttr::GetFont() const
{
    if ( !HasFont() )
        return wxNullFont;

    int fontSize = 10;
    if (HasFontSize())
        fontSize = GetFontSize();

    wxFontStyle fontStyle = wxFONTSTYLE_NORMAL;
    if (HasFontItalic())
        fontStyle = GetFontStyle();

    wxFontWeight fontWeight = wxFONTWEIGHT_NORMAL;
    if (HasFontWeight())
        fontWeight = GetFontWeight();

    bool underlined = false;
    if (HasFontUnderlined())
        underlined = GetFontUnderlined();

    bool strikethrough = false;
    if (HasFontStrikethrough())
        strikethrough = GetFontStrikethrough();

    wxString fontFaceName;
    if (HasFontFaceName())
        fontFaceName = GetFontFaceName();

    wxFontEncoding encoding = wxFONTENCODING_DEFAULT;
    if (HasFontEncoding())
        encoding = GetFontEncoding();

    wxFontFamily fontFamily = wxFONTFAMILY_DEFAULT;
    if (HasFontFamily())
        fontFamily = GetFontFamily();

    if (HasFontPixelSize())
    {
        wxFont font(wxSize(0, fontSize), fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding);
        if (strikethrough)
            font.SetStrikethrough(true);
        return font;
    }
    else
    {
        wxFont font(fontSize, fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding);
        if (strikethrough)
            font.SetStrikethrough(true);
        return font;
    }
}
Example #3
0
FT_Face CreateFTFace(Font fnt)
{
	sInitFt();

	FtFontStyle f = GetFontStyle(fnt);
	
	if(!f)
		return NULL;

	FT_Face face;
	if(IsNull(f.path) ? FT_New_Memory_Face(sFTlib, f.data, f.size, 0, &face)
	                  : FT_New_Face(sFTlib, f.path, 0, &face))
		return NULL;

	FT_Set_Pixel_Sizes(face, 0, fnt.GetHeight());
	return face;
}
Example #4
0
void PasswordBox::BasicSetText(std::string const & new_txt)
{
  std::string _new_txt = new_txt;

  if (max_nb_chars != 0 && _new_txt.size() > max_nb_chars) {
    _new_txt.resize(max_nb_chars);
  }
  clear_text = _new_txt;

  //printf("Real text: %s\n", clear_text.c_str());

  Font * font = Font::GetInstance(GetFontSize(), GetFontStyle());

  if (font->GetWidth(_new_txt) < GetSizeX() - 5) {
    Label::SetText(std::string(clear_text.size(), '*'));
  } else {
    cursor_pos = GetText().size();
  }
}
Example #5
0
// Equality test
bool wxTextAttr::operator== (const wxTextAttr& attr) const
{
    return  GetFlags() == attr.GetFlags() &&

            (!HasTextColour() || (GetTextColour() == attr.GetTextColour())) &&
            (!HasBackgroundColour() || (GetBackgroundColour() == attr.GetBackgroundColour())) &&

            (!HasAlignment() || (GetAlignment() == attr.GetAlignment())) &&
            (!HasLeftIndent() || (GetLeftIndent() == attr.GetLeftIndent() &&
                                  GetLeftSubIndent() == attr.GetLeftSubIndent())) &&
            (!HasRightIndent() || (GetRightIndent() == attr.GetRightIndent())) &&
            (!HasTabs() || (TabsEq(GetTabs(), attr.GetTabs()))) &&

            (!HasParagraphSpacingAfter() || (GetParagraphSpacingAfter() == attr.GetParagraphSpacingAfter())) &&
            (!HasParagraphSpacingBefore() || (GetParagraphSpacingBefore() == attr.GetParagraphSpacingBefore())) &&
            (!HasLineSpacing() || (GetLineSpacing() == attr.GetLineSpacing())) &&
            (!HasCharacterStyleName() || (GetCharacterStyleName() == attr.GetCharacterStyleName())) &&
            (!HasParagraphStyleName() || (GetParagraphStyleName() == attr.GetParagraphStyleName())) &&
            (!HasListStyleName() || (GetListStyleName() == attr.GetListStyleName())) &&

            (!HasBulletStyle() || (GetBulletStyle() == attr.GetBulletStyle())) &&
            (!HasBulletText() || (GetBulletText() == attr.GetBulletText())) &&
            (!HasBulletNumber() || (GetBulletNumber() == attr.GetBulletNumber())) &&
            (GetBulletFont() == attr.GetBulletFont()) &&
            (!HasBulletName() || (GetBulletName() == attr.GetBulletName())) &&

            (!HasTextEffects() || (GetTextEffects() == attr.GetTextEffects() &&
                                   GetTextEffectFlags() == attr.GetTextEffectFlags())) &&

            (!HasOutlineLevel() || (GetOutlineLevel() == attr.GetOutlineLevel())) &&

            (!HasFontSize() || (GetFontSize() == attr.GetFontSize())) &&
            (!HasFontItalic() || (GetFontStyle() == attr.GetFontStyle())) &&
            (!HasFontWeight() || (GetFontWeight() == attr.GetFontWeight())) &&
            (!HasFontUnderlined() || (GetFontUnderlined() == attr.GetFontUnderlined())) &&
            (!HasFontStrikethrough() || (GetFontStrikethrough() == attr.GetFontStrikethrough())) &&
            (!HasFontFaceName() || (GetFontFaceName() == attr.GetFontFaceName())) &&
            (!HasFontEncoding() || (GetFontEncoding() == attr.GetFontEncoding())) &&
            (!HasFontFamily() || (GetFontFamily() == attr.GetFontFamily())) &&

            (!HasURL() || (GetURL() == attr.GetURL()));
}
Example #6
0
// Create font from font attributes.
wxFont wxTextAttr::GetFont() const
{
    if ( !HasFont() )
        return wxNullFont;

    int fontSize = 10;
    if (HasFontSize())
        fontSize = GetFontSize();

    int fontStyle = wxNORMAL;
    if (HasFontItalic())
        fontStyle = GetFontStyle();

    int fontWeight = wxNORMAL;
    if (HasFontWeight())
        fontWeight = GetFontWeight();

    bool underlined = false;
    if (HasFontUnderlined())
        underlined = GetFontUnderlined();

    wxString fontFaceName;
    if (HasFontFaceName())
        fontFaceName = GetFontFaceName();

    wxFontEncoding encoding = wxFONTENCODING_DEFAULT;
    if (HasFontEncoding())
        encoding = GetFontEncoding();

    int fontFamily = wxFONTFAMILY_DEFAULT;
    if (HasFontFamily())
        fontFamily = GetFontFamily();

    wxFont font(fontSize, fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding);
    return font;
}
Example #7
0
Widget * TextBox::ClickUp(const Point2i & mousePosition,
                          uint button)
{
  NeedRedrawing();

  if (button == SDL_BUTTON_MIDDLE) {
    std::string new_txt = GetText();
    bool        used    = RetrieveBuffer(new_txt, cursor_pos);

    if (new_txt != GetText())
      BasicSetText(new_txt);
    return used ? this : NULL;
  } else if (button == SDL_BUTTON_LEFT) {
    const std::string      cur_txt = GetText();
    const Font*            font    = Font::GetInstance(GetFontSize(), GetFontStyle());
    std::string            txt     = "";
    std::string::size_type pos     = 0;

    cursor_pos = 0;
    while (pos <= cur_txt.size() &&
           this->position.x + font->GetWidth(txt) < mousePosition.x+2) {
      cursor_pos = pos;
      while ((cur_txt[pos++] & 0xc0) == 0x80
             && pos < cur_txt.size()) { } // eat all UTF-8 characters
      txt = cur_txt.substr(0, pos);
    }

    Label::Draw(mousePosition);
    DrawCursor(position, cursor_pos);

    return this;
  }

  // Om nom nom
  return this;
}
Example #8
0
// Partial equality test taking flags into account
bool wxTextAttr::EqPartial(const wxTextAttr& attr, int flags) const
{
    if ((flags & wxTEXT_ATTR_TEXT_COLOUR) && GetTextColour() != attr.GetTextColour())
        return false;

    if ((flags & wxTEXT_ATTR_BACKGROUND_COLOUR) && GetBackgroundColour() != attr.GetBackgroundColour())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_FACE) &&
        GetFontFaceName() != attr.GetFontFaceName())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_SIZE) &&
        GetFontSize() != attr.GetFontSize())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_WEIGHT) &&
        GetFontWeight() != attr.GetFontWeight())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_ITALIC) &&
        GetFontStyle() != attr.GetFontStyle())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_UNDERLINE) &&
        GetFontUnderlined() != attr.GetFontUnderlined())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_ENCODING) &&
        GetFontEncoding() != attr.GetFontEncoding())
        return false;

    if ((flags & wxTEXT_ATTR_FONT_FAMILY) &&
        GetFontFamily() != attr.GetFontFamily())
        return false;

    if ((flags & wxTEXT_ATTR_URL) && GetURL() != attr.GetURL())
        return false;

    if ((flags & wxTEXT_ATTR_ALIGNMENT) && GetAlignment() != attr.GetAlignment())
        return false;

    if ((flags & wxTEXT_ATTR_LEFT_INDENT) &&
        ((GetLeftIndent() != attr.GetLeftIndent()) || (GetLeftSubIndent() != attr.GetLeftSubIndent())))
        return false;

    if ((flags & wxTEXT_ATTR_RIGHT_INDENT) &&
        (GetRightIndent() != attr.GetRightIndent()))
        return false;

    if ((flags & wxTEXT_ATTR_PARA_SPACING_AFTER) &&
        (GetParagraphSpacingAfter() != attr.GetParagraphSpacingAfter()))
        return false;

    if ((flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
        (GetParagraphSpacingBefore() != attr.GetParagraphSpacingBefore()))
        return false;

    if ((flags & wxTEXT_ATTR_LINE_SPACING) &&
        (GetLineSpacing() != attr.GetLineSpacing()))
        return false;

    if ((flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
        (GetCharacterStyleName() != attr.GetCharacterStyleName()))
        return false;

    if ((flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
        (GetParagraphStyleName() != attr.GetParagraphStyleName()))
        return false;

    if ((flags & wxTEXT_ATTR_LIST_STYLE_NAME) &&
        (GetListStyleName() != attr.GetListStyleName()))
        return false;

    if ((flags & wxTEXT_ATTR_BULLET_STYLE) &&
        (GetBulletStyle() != attr.GetBulletStyle()))
         return false;

    if ((flags & wxTEXT_ATTR_BULLET_NUMBER) &&
        (GetBulletNumber() != attr.GetBulletNumber()))
         return false;

    if ((flags & wxTEXT_ATTR_BULLET_TEXT) &&
        (GetBulletText() != attr.GetBulletText()) &&
        (GetBulletFont() != attr.GetBulletFont()))
         return false;

    if ((flags & wxTEXT_ATTR_BULLET_NAME) &&
        (GetBulletName() != attr.GetBulletName()))
         return false;

    if ((flags & wxTEXT_ATTR_TABS) &&
        !TabsEq(GetTabs(), attr.GetTabs()))
        return false;

    if ((flags & wxTEXT_ATTR_PAGE_BREAK) &&
        (HasPageBreak() != attr.HasPageBreak()))
         return false;

    if (flags & wxTEXT_ATTR_EFFECTS)
    {
        if (HasTextEffects() != attr.HasTextEffects())
            return false;
        if (!BitlistsEqPartial(GetTextEffects(), attr.GetTextEffects(), attr.GetTextEffectFlags()))
            return false;
    }

    if ((flags & wxTEXT_ATTR_OUTLINE_LEVEL) &&
        (GetOutlineLevel() != attr.GetOutlineLevel()))
         return false;

    return true;
}
Example #9
0
// Partial equality test. Only returns false if an attribute doesn't match.
bool wxTextAttr::EqPartial(const wxTextAttr& attr, bool weakTest) const
{
    int flags = attr.GetFlags();

    if (!weakTest &&
        ((!HasTextColour() && attr.HasTextColour()) ||
         (!HasBackgroundColour() && attr.HasBackgroundColour()) ||
         (!HasFontFaceName() && attr.HasFontFaceName()) ||
         (!HasFontSize() && attr.HasFontSize()) ||
         (!HasFontWeight() && attr.HasFontWeight()) ||
         (!HasFontItalic() && attr.HasFontItalic()) ||
         (!HasFontUnderlined() && attr.HasFontUnderlined()) ||
         (!HasFontStrikethrough() && attr.HasFontStrikethrough()) ||
         (!HasFontEncoding() && attr.HasFontEncoding()) ||
         (!HasFontFamily() && attr.HasFontFamily()) ||
         (!HasURL() && attr.HasURL()) ||
         (!HasAlignment() && attr.HasAlignment()) ||
         (!HasLeftIndent() && attr.HasLeftIndent()) ||
         (!HasParagraphSpacingAfter() && attr.HasParagraphSpacingAfter()) ||
         (!HasParagraphSpacingBefore() && attr.HasParagraphSpacingBefore()) ||
         (!HasLineSpacing() && attr.HasLineSpacing()) ||
         (!HasCharacterStyleName() && attr.HasCharacterStyleName()) ||
         (!HasParagraphStyleName() && attr.HasParagraphStyleName()) ||
         (!HasListStyleName() && attr.HasListStyleName()) ||
         (!HasBulletStyle() && attr.HasBulletStyle()) ||
         (!HasBulletNumber() && attr.HasBulletNumber()) ||
         (!HasBulletText() && attr.HasBulletText()) ||
         (!HasBulletName() && attr.HasBulletName()) ||
         (!HasTabs() && attr.HasTabs()) ||
         (!HasTextEffects() && attr.HasTextEffects()) ||
         (!HasOutlineLevel() && attr.HasOutlineLevel())))
    {
        return false;
    }

    if (HasTextColour() && attr.HasTextColour() && GetTextColour() != attr.GetTextColour())
        return false;

    if (HasBackgroundColour() && attr.HasBackgroundColour() && GetBackgroundColour() != attr.GetBackgroundColour())
        return false;

    if (HasFontFaceName() && attr.HasFontFaceName() && GetFontFaceName() != attr.GetFontFaceName())
        return false;

    // This checks whether the two objects have the same font size dimension (px versus pt)
    if (HasFontSize() && attr.HasFontSize() && (flags & wxTEXT_ATTR_FONT) != (GetFlags() & wxTEXT_ATTR_FONT))
        return false;

    if (HasFontPointSize() && attr.HasFontPointSize() && GetFontSize() != attr.GetFontSize())
        return false;

    if (HasFontPixelSize() && attr.HasFontPixelSize() && GetFontSize() != attr.GetFontSize())
        return false;

    if (HasFontWeight() && attr.HasFontWeight() && GetFontWeight() != attr.GetFontWeight())
        return false;

    if (HasFontItalic() && attr.HasFontItalic() && GetFontStyle() != attr.GetFontStyle())
        return false;

    if (HasFontUnderlined() && attr.HasFontUnderlined() && GetFontUnderlined() != attr.GetFontUnderlined())
        return false;

    if (HasFontStrikethrough() && attr.HasFontStrikethrough() && GetFontStrikethrough() != attr.GetFontStrikethrough())
        return false;

    if (HasFontEncoding() && attr.HasFontEncoding() && GetFontEncoding() != attr.GetFontEncoding())
        return false;

    if (HasFontFamily() && attr.HasFontFamily() && GetFontFamily() != attr.GetFontFamily())
        return false;

    if (HasURL() && attr.HasURL() && GetURL() != attr.GetURL())
        return false;

    if (HasAlignment() && attr.HasAlignment() && GetAlignment() != attr.GetAlignment())
        return false;

    if (HasLeftIndent() && attr.HasLeftIndent() &&
        ((GetLeftIndent() != attr.GetLeftIndent()) || (GetLeftSubIndent() != attr.GetLeftSubIndent())))
        return false;

    if (HasRightIndent() && attr.HasRightIndent() && (GetRightIndent() != attr.GetRightIndent()))
        return false;

    if (HasParagraphSpacingAfter() && attr.HasParagraphSpacingAfter() &&
        (GetParagraphSpacingAfter() != attr.GetParagraphSpacingAfter()))
        return false;

    if (HasParagraphSpacingBefore() && attr.HasParagraphSpacingBefore() &&
        (GetParagraphSpacingBefore() != attr.GetParagraphSpacingBefore()))
        return false;

    if (HasLineSpacing() && attr.HasLineSpacing() && (GetLineSpacing() != attr.GetLineSpacing()))
        return false;

    if (HasCharacterStyleName() && attr.HasCharacterStyleName() && (GetCharacterStyleName() != attr.GetCharacterStyleName()))
        return false;

    if (HasParagraphStyleName() && attr.HasParagraphStyleName() && (GetParagraphStyleName() != attr.GetParagraphStyleName()))
        return false;

    if (HasListStyleName() && attr.HasListStyleName() && (GetListStyleName() != attr.GetListStyleName()))
        return false;

    if (HasBulletStyle() && attr.HasBulletStyle() && (GetBulletStyle() != attr.GetBulletStyle()))
         return false;

    if (HasBulletNumber() && attr.HasBulletNumber() && (GetBulletNumber() != attr.GetBulletNumber()))
         return false;

    if (HasBulletText() && attr.HasBulletText() &&
        (GetBulletText() != attr.GetBulletText()) &&
        (GetBulletFont() != attr.GetBulletFont()))
         return false;

    if (HasBulletName() && attr.HasBulletName() && (GetBulletName() != attr.GetBulletName()))
         return false;

    if (HasTabs() && attr.HasTabs() && !TabsEq(GetTabs(), attr.GetTabs()))
        return false;

    if ((HasPageBreak() != attr.HasPageBreak()))
         return false;

    if (HasTextEffects() && attr.HasTextEffects())
    {
        if (!BitlistsEqPartial(GetTextEffects(), attr.GetTextEffects(), attr.GetTextEffectFlags()))
            return false;
    }

    if (HasOutlineLevel() && attr.HasOutlineLevel() && (GetOutlineLevel() != attr.GetOutlineLevel()))
         return false;

    return true;
}
bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
                                                 SkString* outFamilyName,
                                                 SkTArray<FontIdentity>* ids) {
    SkAutoMutexAcquire ac(mutex_);

#if 0
    SkString familyStr(familyName ? familyName : "");
    if (familyStr.size() > kMaxFontFamilyLength) {
        return false;
    }

    SkAutoMutexAcquire ac(mutex_);

    FcPattern* pattern = FcPatternCreate();

    if (familyName) {
        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
    }
    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);

    FcConfigSubstitute(NULL, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    // Font matching:
    // CSS often specifies a fallback list of families:
    //    font-family: a, b, c, serif;
    // However, fontconfig will always do its best to find *a* font when asked
    // for something so we need a way to tell if the match which it has found is
    // "good enough" for us. Otherwise, we can return NULL which gets piped up
    // and lets WebKit know to try the next CSS family name. However, fontconfig
    // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
    // wish to support that.
    //
    // Thus, if a specific family is requested we set @family_requested. Then we
    // record two strings: the family name after config processing and the
    // family name after resolving. If the two are equal, it's a good match.
    //
    // So consider the case where a user has mapped Arial to Helvetica in their
    // config.
    //    requested family: "Arial"
    //    post_config_family: "Helvetica"
    //    post_match_family: "Helvetica"
    //      -> good match
    //
    // and for a missing font:
    //    requested family: "Monaco"
    //    post_config_family: "Monaco"
    //    post_match_family: "Times New Roman"
    //      -> BAD match
    //
    // However, we special-case fallback fonts; see IsFallbackFontAllowed().

    const char* post_config_family = get_name(pattern, FC_FAMILY);

    FcResult result;
    FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
    if (!font_set) {
        FcPatternDestroy(pattern);
        return false;
    }

    FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
    if (!match) {
        FcPatternDestroy(pattern);
        FcFontSetDestroy(font_set);
        return false;
    }

    FcPatternDestroy(pattern);

    // From here out we just extract our results from 'match'

    if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }

    FcChar8* c_filename;
    if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }

    int face_index;
    if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }

    FcFontSetDestroy(font_set);

    if (outIdentity) {
        outIdentity->fTTCIndex = face_index;
        outIdentity->fString.set((const char*)c_filename);
    }
    if (outFamilyName) {
        outFamilyName->set((const char*)post_config_family);
    }
    if (outStyle) {
        *outStyle = GetFontStyle(match);
    }
    return true;

////////////////////

        int count;
        FcPattern** match = MatchFont(font_set, post_config_family, &count);
        if (!match) {
            FcPatternDestroy(pattern);
            FcFontSetDestroy(font_set);
            return NULL;
        }

        FcPatternDestroy(pattern);

        SkTDArray<FcPattern*> trimmedMatches;
        for (int i = 0; i < count; ++i) {
            const char* justName = find_just_name(get_name(match[i], FC_FILE));
            if (!is_lower(*justName)) {
                *trimmedMatches.append() = match[i];
            }
        }

        SkFontStyleSet_FC* sset = new SkFontStyleSet_FC                                               (trimmedMatches.begin(),                                               trimmedMatches.count());
#endif
    return false;
}
bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
                                                  SkTypeface::Style style,
                                                  FontIdentity* outIdentity,
                                                  SkString* outFamilyName,
                                                  SkTypeface::Style* outStyle) {
    SkString familyStr(familyName ? familyName : "");
    if (familyStr.size() > kMaxFontFamilyLength) {
        return false;
    }

    SkAutoMutexAcquire ac(mutex_);

    FcPattern* pattern = FcPatternCreate();

    if (familyName) {
        FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
    }
    FcPatternAddInteger(pattern, FC_WEIGHT,
                        (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
                                                    : FC_WEIGHT_NORMAL);
    FcPatternAddInteger(pattern, FC_SLANT,
                        (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC
                                                      : FC_SLANT_ROMAN);
    FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);

    FcConfigSubstitute(NULL, pattern, FcMatchPattern);
    FcDefaultSubstitute(pattern);

    // Font matching:
    // CSS often specifies a fallback list of families:
    //    font-family: a, b, c, serif;
    // However, fontconfig will always do its best to find *a* font when asked
    // for something so we need a way to tell if the match which it has found is
    // "good enough" for us. Otherwise, we can return NULL which gets piped up
    // and lets WebKit know to try the next CSS family name. However, fontconfig
    // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
    // wish to support that.
    //
    // Thus, if a specific family is requested we set @family_requested. Then we
    // record two strings: the family name after config processing and the
    // family name after resolving. If the two are equal, it's a good match.
    //
    // So consider the case where a user has mapped Arial to Helvetica in their
    // config.
    //    requested family: "Arial"
    //    post_config_family: "Helvetica"
    //    post_match_family: "Helvetica"
    //      -> good match
    //
    // and for a missing font:
    //    requested family: "Monaco"
    //    post_config_family: "Monaco"
    //    post_match_family: "Times New Roman"
    //      -> BAD match
    //
    // However, we special-case fallback fonts; see IsFallbackFontAllowed().

    const char* post_config_family = get_name(pattern, FC_FAMILY);
    if (!post_config_family) {
        // we can just continue with an empty name, e.g. default font
        post_config_family = "";
    }

    FcResult result;
    FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
    if (!font_set) {
        FcPatternDestroy(pattern);
        return false;
    }

    FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
    if (!match) {
        FcPatternDestroy(pattern);
        FcFontSetDestroy(font_set);
        return false;
    }

    FcPatternDestroy(pattern);

    // From here out we just extract our results from 'match'

    post_config_family = get_name(match, FC_FAMILY);
    if (!post_config_family) {
        FcFontSetDestroy(font_set);
        return false;
    }

    const char* c_filename = get_name(match, FC_FILE);
    if (!c_filename) {
        FcFontSetDestroy(font_set);
        return false;
    }

    int face_index;
    if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
        FcFontSetDestroy(font_set);
        return false;
    }

    FcFontSetDestroy(font_set);

    if (outIdentity) {
        outIdentity->fTTCIndex = face_index;
        outIdentity->fString.set(c_filename);
    }
    if (outFamilyName) {
        outFamilyName->set(post_config_family);
    }
    if (outStyle) {
        *outStyle = GetFontStyle(match);
    }
    return true;
}