| /* Pango |
| * pango-ot-info.c: Store tables for OpenType |
| * |
| * Copyright (C) 2000 Red Hat Software |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| #include "pango-ot-private.h" |
| #include <freetype/internal/tterrors.h> |
| #include <freetype/internal/ftobjs.h> |
| #include <freetype/ftmodule.h> |
| |
| static void pango_ot_info_class_init (GObjectClass *object_class); |
| static void pango_ot_info_finalize (GObject *object); |
| |
| static GObjectClass *parent_class; |
| |
| enum |
| { |
| INFO_LOADED_GDEF = 1 << 0, |
| INFO_LOADED_GSUB = 1 << 1, |
| INFO_LOADED_GPOS = 1 << 2 |
| }; |
| |
| GType |
| pango_ot_info_get_type (void) |
| { |
| static GType object_type = 0; |
| |
| if (!object_type) |
| { |
| static const GTypeInfo object_info = |
| { |
| sizeof (PangoOTInfoClass), |
| (GBaseInitFunc) NULL, |
| (GBaseFinalizeFunc) NULL, |
| (GClassInitFunc)pango_ot_info_class_init, |
| NULL, /* class_finalize */ |
| NULL, /* class_data */ |
| sizeof (PangoOTInfo), |
| 0, /* n_preallocs */ |
| NULL /* init */ |
| }; |
| |
| object_type = g_type_register_static (G_TYPE_OBJECT, |
| "PangoOTInfo", |
| &object_info, 0); |
| } |
| |
| return object_type; |
| } |
| |
| static void |
| pango_ot_info_class_init (GObjectClass *object_class) |
| { |
| parent_class = g_type_class_peek_parent (object_class); |
| |
| object_class->finalize = pango_ot_info_finalize; |
| } |
| |
| static void |
| pango_ot_info_finalize (GObject *object) |
| { |
| PangoOTInfo *info = PANGO_OT_INFO (object); |
| |
| if (info->gdef) |
| { |
| TT_Done_GDEF_Table (info->gdef); |
| info->gdef = NULL; |
| } |
| if (info->gsub) |
| { |
| TT_Done_GSUB_Table (info->gsub); |
| info->gsub = NULL; |
| } |
| if (info->gpos) |
| { |
| TT_Done_GPOS_Table (info->gpos); |
| info->gpos = NULL; |
| } |
| } |
| |
| PangoOTInfo * |
| pango_ot_info_new (FT_Face face) |
| { |
| PangoOTInfo *info; |
| |
| info = g_object_new (PANGO_TYPE_OT_INFO, NULL); |
| |
| info->face = face; |
| |
| return info; |
| } |
| |
| /* There must be be a better way to do this |
| */ |
| static gboolean |
| is_truetype (FT_Face face) |
| { |
| return strcmp (FT_MODULE_CLASS (face->driver)->module_name, "truetype") == 0; |
| } |
| |
| TTO_GDEF |
| pango_ot_info_get_gdef (PangoOTInfo *info) |
| { |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!(info->loaded & INFO_LOADED_GDEF)) |
| { |
| FT_Error error; |
| |
| info->loaded |= INFO_LOADED_GDEF; |
| |
| if (is_truetype (info->face)) |
| { |
| error = TT_Load_GDEF_Table (info->face, &info->gdef); |
| |
| if (error && error != TT_Err_Table_Missing) |
| g_warning ("Error loading GDEF table %d", error); |
| } |
| } |
| |
| return info->gdef; |
| } |
| |
| TTO_GSUB |
| pango_ot_info_get_gsub (PangoOTInfo *info) |
| { |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!(info->loaded & INFO_LOADED_GSUB)) |
| { |
| FT_Error error; |
| TTO_GDEF gdef = pango_ot_info_get_gdef (info); |
| |
| info->loaded |= INFO_LOADED_GSUB; |
| |
| if (is_truetype (info->face)) |
| { |
| error = TT_Load_GSUB_Table (info->face, &info->gsub, gdef); |
| |
| if (error && error != TT_Err_Table_Missing) |
| g_warning ("Error loading GSUB table %d", error); |
| } |
| } |
| |
| return info->gsub; |
| } |
| |
| TTO_GPOS |
| pango_ot_info_get_gpos (PangoOTInfo *info) |
| { |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!(info->loaded & INFO_LOADED_GPOS)) |
| { |
| FT_Error error; |
| TTO_GDEF gdef = pango_ot_info_get_gdef (info); |
| |
| info->loaded |= INFO_LOADED_GPOS; |
| |
| if (is_truetype (info->face)) |
| { |
| error = TT_Load_GPOS_Table (info->face, &info->gpos, gdef); |
| |
| if (error && error != TT_Err_Table_Missing) |
| g_warning ("Error loading GPOS table %d", error); |
| } |
| } |
| |
| return info->gpos; |
| } |
| |
| static gboolean |
| get_tables (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| TTO_ScriptList **script_list, |
| TTO_FeatureList **feature_list) |
| { |
| if (table_type == PANGO_OT_TABLE_GSUB) |
| { |
| TTO_GSUB gsub = pango_ot_info_get_gsub (info); |
| |
| if (!gsub) |
| return FALSE; |
| else |
| { |
| if (script_list) |
| *script_list = &gsub->ScriptList; |
| if (feature_list) |
| *feature_list = &gsub->FeatureList; |
| return TRUE; |
| } |
| } |
| else |
| { |
| TTO_GPOS gpos = pango_ot_info_get_gpos (info); |
| |
| if (!gpos) |
| return FALSE; |
| else |
| { |
| if (script_list) |
| *script_list = &gpos->ScriptList; |
| if (feature_list) |
| *feature_list = &gpos->FeatureList; |
| return TRUE; |
| } |
| } |
| } |
| |
| gboolean |
| pango_ot_info_find_script (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| PangoOTTag script_tag, |
| guint *script_index) |
| { |
| TTO_ScriptList *script_list; |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE); |
| |
| if (!get_tables (info, table_type, &script_list, NULL)) |
| return FALSE; |
| |
| for (i=0; i < script_list->ScriptCount; i++) |
| { |
| if (script_list->ScriptRecord[i].ScriptTag == script_tag) |
| { |
| if (script_index) |
| *script_index = i; |
| |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| gboolean |
| pango_ot_info_find_language (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| guint script_index, |
| PangoOTTag language_tag, |
| guint *language_index, |
| guint *required_feature_index) |
| { |
| TTO_ScriptList *script_list; |
| TTO_Script *script; |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE); |
| |
| if (!get_tables (info, table_type, &script_list, NULL)) |
| return FALSE; |
| |
| g_return_val_if_fail (script_index < script_list->ScriptCount, FALSE); |
| |
| script = &script_list->ScriptRecord[script_index].Script; |
| |
| for (i = 0; i < script->LangSysCount; i++) |
| { |
| if (script->LangSysRecord[i].LangSysTag == language_tag) |
| { |
| if (language_index) |
| *language_index = i; |
| if (required_feature_index) |
| *required_feature_index = script->LangSysRecord[i].LangSys.ReqFeatureIndex; |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| gboolean |
| pango_ot_info_find_feature (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| PangoOTTag feature_tag, |
| guint script_index, |
| guint language_index, |
| guint *feature_index) |
| { |
| TTO_ScriptList *script_list; |
| TTO_FeatureList *feature_list; |
| TTO_Script *script; |
| TTO_LangSys *lang_sys; |
| |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), FALSE); |
| |
| if (!get_tables (info, table_type, &script_list, &feature_list)) |
| return FALSE; |
| |
| g_return_val_if_fail (script_index < script_list->ScriptCount, FALSE); |
| |
| script = &script_list->ScriptRecord[script_index].Script; |
| |
| if (language_index == 0xffff) |
| lang_sys = &script->DefaultLangSys; |
| else |
| { |
| g_return_val_if_fail (language_index < script->LangSysCount, FALSE); |
| lang_sys = &script->LangSysRecord[language_index].LangSys; |
| } |
| |
| for (i = 0; i < lang_sys->FeatureCount; i++) |
| { |
| FT_UShort index = lang_sys->FeatureIndex[i]; |
| |
| if (feature_list->FeatureRecord[index].FeatureTag == feature_tag) |
| { |
| if (feature_index) |
| *feature_index = index; |
| |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| PangoOTTag * |
| pango_ot_info_list_scripts (PangoOTInfo *info, |
| PangoOTTableType table_type) |
| { |
| PangoOTTag *result; |
| TTO_ScriptList *script_list; |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!get_tables (info, table_type, &script_list, NULL)) |
| return NULL; |
| |
| result = g_new (PangoOTTag, script_list->ScriptCount + 1); |
| |
| for (i=0; i < script_list->ScriptCount; i++) |
| result[i] = script_list->ScriptRecord[i].ScriptTag; |
| |
| result[i] = 0; |
| |
| return result; |
| } |
| |
| PangoOTTag * |
| pango_ot_info_list_languages (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| guint script_index, |
| PangoOTTag language_tag) |
| { |
| PangoOTTag *result; |
| TTO_ScriptList *script_list; |
| TTO_Script *script; |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!get_tables (info, table_type, &script_list, NULL)) |
| return NULL; |
| |
| g_return_val_if_fail (script_index < script_list->ScriptCount, NULL); |
| |
| script = &script_list->ScriptRecord[script_index].Script; |
| |
| result = g_new (PangoOTTag, script->LangSysCount + 1); |
| |
| for (i = 0; i < script->LangSysCount; i++) |
| result[i] = script->LangSysRecord[i].LangSysTag; |
| |
| result[i] = 0; |
| |
| return result; |
| } |
| |
| PangoOTTag * |
| pango_ot_info_list_features (PangoOTInfo *info, |
| PangoOTTableType table_type, |
| PangoOTTag tag, |
| guint script_index, |
| guint language_index) |
| { |
| PangoOTTag *result; |
| |
| TTO_ScriptList *script_list; |
| TTO_FeatureList *feature_list; |
| TTO_Script *script; |
| TTO_LangSys *lang_sys; |
| |
| int i; |
| |
| g_return_val_if_fail (PANGO_IS_OT_INFO (info), NULL); |
| |
| if (!get_tables (info, table_type, &script_list, &feature_list)) |
| return NULL; |
| |
| g_return_val_if_fail (script_index < script_list->ScriptCount, NULL); |
| |
| script = &script_list->ScriptRecord[script_index].Script; |
| |
| if (language_index == 0xffff) |
| lang_sys = &script->DefaultLangSys; |
| else |
| { |
| g_return_val_if_fail (language_index < script->LangSysCount, NULL); |
| lang_sys = &script->LangSysRecord[language_index].LangSys; |
| } |
| |
| result = g_new (PangoOTTag, lang_sys->FeatureCount + 1); |
| |
| for (i = 0; i < lang_sys->FeatureCount; i++) |
| { |
| FT_UShort index = lang_sys->FeatureIndex[i]; |
| |
| result[i] = feature_list->FeatureRecord[index].FeatureTag; |
| } |
| |
| result[i] = 0; |
| |
| return result; |
| } |
| |
| |