1 /*$
2  Copyright (C) 2016-2020 Azel.
3 
4  This file is part of AzPainterB.
5 
6  AzPainterB is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  AzPainterB is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 $*/
19 
20 /*****************************************
21  * fontconfig
22  *****************************************/
23 
24 #include <fontconfig/fontconfig.h>
25 
26 #include "mDef.h"
27 
28 #include "mFontConfig.h"
29 #include "mFont.h"
30 #include "mStr.h"
31 
32 
33 /**
34 @defgroup fontconfig mFontConfig
35 @brief fontconfig ユーティリティ
36 
37 @details
38 文字列は UTF-8 で指定する。
39 
40 @ingroup group_lib
41 
42 @{
43 @file mFontConfig.h
44 
45 @struct mFontInfo
46 
47 */
48 
49 
50 //================================
51 // sub
52 //================================
53 
54 
55 /** mFontInfo から FcPattern 作成 */
56 
_create_fc_pattern(mFontInfo * p)57 static FcPattern *_create_fc_pattern(mFontInfo *p)
58 {
59 	FcPattern *pat;
60 	int weight,slant;
61 
62 	pat = FcPatternCreate();
63 
64 	//フォントファミリー
65 
66 	if((p->mask & MFONTINFO_MASK_FAMILY) && !mStrIsEmpty(&p->strFamily))
67 		FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)p->strFamily.buf);
68 	else
69 		FcPatternAddString(pat, FC_FAMILY, (FcChar8 *)"sans-serif");
70 
71 	//スタイル
72 
73 	if((p->mask & MFONTINFO_MASK_STYLE) && !mStrIsEmpty(&p->strStyle))
74 		FcPatternAddString(pat, FC_STYLE, (FcChar8 *)p->strStyle.buf);
75 
76 	//サイズ
77 
78 	if(p->mask & MFONTINFO_MASK_SIZE)
79 	{
80 		if(p->size < 0)
81 			FcPatternAddDouble(pat, FC_PIXEL_SIZE, -(p->size));
82 		else
83 			FcPatternAddDouble(pat, FC_SIZE, p->size);
84 	}
85 
86 	//太さ (指定なしなら通常)
87 
88 	weight = FC_WEIGHT_NORMAL;
89 
90 	if(p->mask & MFONTINFO_MASK_WEIGHT)
91 	{
92 		switch(p->weight)
93 		{
94 			case MFONTINFO_WEIGHT_BOLD:
95 				weight = FC_WEIGHT_BOLD;
96 				break;
97 		}
98 	}
99 
100 	FcPatternAddInteger(pat, FC_WEIGHT, weight);
101 
102 	//斜体 (指定なしなら通常)
103 
104 	slant = FC_SLANT_ROMAN;
105 
106 	if(p->mask & MFONTINFO_MASK_SLANT)
107 	{
108 		switch(p->slant)
109 		{
110 			case MFONTINFO_SLANT_ITALIC:
111 				slant = FC_SLANT_ITALIC;
112 				break;
113 			case MFONTINFO_SLANT_OBLIQUE:
114 				slant = FC_SLANT_OBLIQUE;
115 				break;
116 		}
117 	}
118 
119 	FcPatternAddInteger(pat, FC_SLANT, slant);
120 
121 	//デフォルトの構成を適用
122 
123 	if(!FcConfigSubstitute(NULL, pat, FcMatchPattern))
124 	{
125 		FcPatternDestroy(pat);
126 		return NULL;
127 	}
128 
129 	return pat;
130 }
131 
132 
133 //================================
134 //
135 //================================
136 
137 
138 /** fontconfig 初期化 */
139 
mFontConfigInit(void)140 mBool mFontConfigInit(void)
141 {
142 	return FcInit();
143 }
144 
145 /** fontconfig 解放 */
146 
mFontConfigEnd(void)147 void mFontConfigEnd(void)
148 {
149 	FcFini();
150 }
151 
152 /** パターンを解放 */
153 
mFontConfigPatternFree(mFcPattern * pat)154 void mFontConfigPatternFree(mFcPattern *pat)
155 {
156 	if(pat)
157 		FcPatternDestroy(pat);
158 }
159 
160 /** 指定した構成にマッチするパターン取得 */
161 
mFontConfigMatch(mFontInfo * conf)162 mFcPattern *mFontConfigMatch(mFontInfo *conf)
163 {
164 	FcPattern *pat,*pat_match;
165 	FcResult ret;
166 
167 	pat = _create_fc_pattern(conf);
168 	if(!pat) return NULL;
169 
170 	pat_match = FcFontMatch(0, pat, &ret);
171 
172 	FcPatternDestroy(pat);
173 
174 	return pat_match;
175 }
176 
177 /** パターンからファイル情報取得
178  *
179  * @param file pat の領域内のポインタが返る。pat を解放するまでは有効 */
180 
mFontConfigGetFileInfo(mFcPattern * pat,char ** file,int * index)181 int mFontConfigGetFileInfo(mFcPattern *pat,char **file,int *index)
182 {
183 	*file  = NULL;
184 	*index = 0;
185 
186 	if(FcPatternGetString(pat, FC_FILE, 0, (FcChar8 **)file) != FcResultMatch)
187 		return -1;
188 
189 	FcPatternGetInteger(pat, FC_INDEX, 0, index);
190 
191 	return 0;
192 }
193 
194 /** パターンから文字列取得
195  *
196  * @return ポインタは解放しないこと。NULL で失敗。 */
197 
mFontConfigGetText(mFcPattern * pat,const char * object)198 char *mFontConfigGetText(mFcPattern *pat,const char *object)
199 {
200 	FcChar8 *text;
201 
202 	if(FcPatternGetString(pat, object, 0, &text) == FcResultMatch)
203 		return (char *)text;
204 	else
205 		return NULL;
206 }
207 
208 /** パターンから bool 値取得 */
209 
mFontConfigGetBool(mFcPattern * pat,const char * object,mBool def)210 mBool mFontConfigGetBool(mFcPattern *pat,const char *object,mBool def)
211 {
212 	FcBool ret;
213 
214 	if(FcPatternGetBool(pat, object, 0, &ret) == FcResultMatch)
215 		return ret;
216 	else
217 		return def;
218 }
219 
220 /** パターンから int 値取得 */
221 
mFontConfigGetInt(mFcPattern * pat,const char * object,int def)222 int mFontConfigGetInt(mFcPattern *pat,const char *object,int def)
223 {
224 	int ret;
225 
226 	if(FcPatternGetInteger(pat, object, 0, &ret) == FcResultMatch)
227 		return ret;
228 	else
229 		return def;
230 }
231 
232 /** パターンから double 値取得 */
233 
mFontConfigGetDouble(mFcPattern * pat,const char * object,double def)234 double mFontConfigGetDouble(mFcPattern *pat,const char *object,double def)
235 {
236 	double ret;
237 
238 	if(FcPatternGetDouble(pat, object, 0, &ret) == FcResultMatch)
239 		return ret;
240 	else
241 		return def;
242 }
243 
244 /** パターンから double 値取得 */
245 
mFontConfigGetDouble2(mFcPattern * pat,const char * object,double * dst)246 mBool mFontConfigGetDouble2(mFcPattern *pat,const char *object,double *dst)
247 {
248 	return (FcPatternGetDouble(pat, object, 0, dst) == FcResultMatch);
249 }
250 
251 /** パターンから matrix 取得 */
252 
mFontConfigGetMatrix(mFcPattern * pat,const char * object,double * matrix)253 mBool mFontConfigGetMatrix(mFcPattern *pat,const char *object,double *matrix)
254 {
255 	FcMatrix *mt;
256 
257 	if(FcPatternGetMatrix(pat, object, 0, &mt) != FcResultMatch)
258 		return FALSE;
259 	else
260 	{
261 		matrix[0] = mt->xx;
262 		matrix[1] = mt->xy;
263 		matrix[2] = mt->yx;
264 		matrix[3] = mt->yy;
265 		return TRUE;
266 	}
267 }
268 
269 /** @} */
270