1 module skia.SKTypeface;
2 
3 import skia.SKObject;
4 import skia.SKFont;
5 import skia.SkiaApi;
6 import skia.SKFontStyle;
7 import skia.Definitions;
8 import skia.SKStream;
9 import skia.SKData;
10 import skia.Exceptions;
11 import skia.SKFontManager;
12 import skia.SKString;
13 import skia.Util;
14 
15 import std.concurrency : initOnce;
16 
17 enum SKTypefaceStyle
18 {
19 	Normal = 0,
20 	Bold = 0x01,
21 	Italic = 0x02,
22 	BoldItalic = 0x03
23 }
24 
25 class SKTypeface : SKObject
26 {
27 	// private static const SKTypeface defaultTypeface;
28 
29 	private static SKTypeface defaultTypeface()
30 	{
31 		__gshared SKTypeface inst;
32 		return initOnce!inst(new SKTypefaceStatic (SkiaApi.sk_typeface_ref_default ()));
33 	}
34 
35 	private SKFont font;
36 
37 
38 	static void EnsureStaticInstanceAreInitialized ()
39 	{
40 		// IMPORTANT: do not remove to ensure that the static instances
41 		//            are initialized before any access is made to them
42 	}
43 
44 	this (void* handle, bool owns)
45 	{
46     super (handle, owns);
47 	}
48 
49 	// Default
50 
51 	protected override void Dispose (bool disposing)
52   {
53     return super.Dispose (disposing);
54   }
55 		
56 
57 	static SKTypeface Default()
58   {
59     return defaultTypeface;
60   }
61 
62 	static SKTypeface CreateDefault ()
63 	{
64 		return GetObject (SkiaApi.sk_typeface_create_default ());
65 	}
66 
67 	// FromFamilyName
68 
69 	static SKTypeface FromFamilyName (string familyName, SKTypefaceStyle style)
70 	{
71 		// auto weight = style.HasFlag (SKTypefaceStyle.Bold) ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal;
72 		// auto slant = style.HasFlag (SKTypefaceStyle.Italic) ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
73 
74 		// return FromFamilyName (familyName, weight, SKFontStyleWidth.Normal, slant);
75     return null;
76 	}
77 
78 	static SKTypeface FromFamilyName (string familyName, int weight, int width, SKFontStyleSlant slant)
79 	{
80 		return FromFamilyName (familyName, new SKFontStyle (weight, width, slant));
81 	}
82 
83 	static SKTypeface FromFamilyName (string familyName)
84 	{
85 		return FromFamilyName (familyName, SKFontStyle.Normal);
86 	}
87 
88 	static SKTypeface FromFamilyName (string familyName, SKFontStyle style)
89 	{
90 		if (style is null)
91 			throw new ArgumentNullException (style.stringof);
92 
93 		auto tf = GetObject (SkiaApi.sk_typeface_create_from_name (familyName, cast(sk_fontstyle_t*)style.Handle));
94 		tf.PreventPublicDisposal ();
95 		return tf;
96 	}
97 
98 	static SKTypeface FromFamilyName (string familyName, SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant)
99 	{
100 		return FromFamilyName (familyName, cast(int)weight, cast(int)width, slant);
101 	}
102 
103 	// From*
104 
105 	static SKTypeface FromTypeface (SKTypeface typeface, SKTypefaceStyle style)
106 	{
107 		if (typeface is null)
108 			throw new ArgumentNullException (typeface.stringof);
109 
110 		auto weight = style.HasFlag (SKTypefaceStyle.Bold) ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal;
111 		auto width = SKFontStyleWidth.Normal;
112 		auto slant = style.HasFlag (SKTypefaceStyle.Italic) ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
113 
114 		return SKFontManager.Default.MatchTypeface (typeface, new SKFontStyle (weight, width, slant));
115 	}
116 
117 	static SKTypeface FromFile (string path, int index = 0)
118 	{
119 		if (path is null)
120 			throw new ArgumentNullException (path.stringof);
121 
122 		// auto utf8path = StringUtilities.GetEncodedText (path, SKTextEncoding.Utf8, true);
123 		string u = path;
124 		return GetObject (SkiaApi.sk_typeface_create_from_file (u, index));
125 	}
126 
127 	// static SKTypeface FromStream (Stream stream, int index = 0)
128 	// {
129 	// 	if (stream is null)
130 	// 		throw new ArgumentNullException (stream.stringof);
131 
132 	// 	return FromStream (new SKManagedStream (stream, true), index);
133 	// }
134 
135 	static SKTypeface FromStream (SKStreamAsset stream, int index = 0)
136 	{
137 		if (stream is null)
138 			throw new ArgumentNullException (stream.stringof);
139 
140 	// 	if (stream is SKManagedStream) {
141     //   // auto managed = stream;
142 	// 		// stream = managed.ToMemoryStream ();
143 	// 		// managed.Dispose ();
144 	// 	}
145 
146 		auto typeface = GetObject (SkiaApi.sk_typeface_create_from_stream (cast(sk_stream_asset_t*)stream.Handle, index));
147 		stream.RevokeOwnership (typeface);
148 		return typeface;
149 	}
150 
151 	static SKTypeface FromData (SKData data, int index = 0)
152 	{
153 		if (data is null)
154 			throw new ArgumentNullException (data.stringof);
155 
156 		return GetObject (SkiaApi.sk_typeface_create_from_data (cast(sk_data_t*)data.Handle, index));
157 	}
158 
159 	// CharsToGlyphs
160 	// [Obsolete ("Use GetGlyphs(string, out ushort[]) instead.")]
161 	int CharsToGlyphs (string chars, out ushort[] glyphs)
162   {
163     return GetGlyphs (chars, glyphs);
164   }
165 	
166 	// [Obsolete ("Use GetGlyphs(void*, int, SKTextEncoding, out ushort[]) instead.")]
167 	int CharsToGlyphs (void* str, int strlen, SKEncoding encoding, out ushort[] glyphs)
168   {
169     return GetGlyphs (str, strlen, encoding, glyphs);
170   }
171 		
172 
173 	// Properties
174 
175 	string FamilyName()
176   {
177     return cast(string)SKString.GetObject (SkiaApi.sk_typeface_get_family_name (cast(sk_typeface_t*)Handle));
178   }
179 
180 	SKFontStyle FontStyle()
181   {
182     return SKFontStyle.GetObject (SkiaApi.sk_typeface_get_fontstyle (cast(sk_typeface_t*)Handle));
183   }
184 
185 	int FontWeight()
186   {
187     return SkiaApi.sk_typeface_get_font_weight (cast(sk_typeface_t*)Handle);
188   } 
189 
190 	int FontWidth()
191   {
192     return SkiaApi.sk_typeface_get_font_width (cast(sk_typeface_t*)Handle);
193   }
194 
195 	SKFontStyleSlant FontSlant()
196   {
197     return SkiaApi.sk_typeface_get_font_slant (cast(sk_typeface_t*)Handle);
198   }
199 
200 	bool IsBold()
201   {
202     return FontStyle.Weight >= cast(int)SKFontStyleWeight.SemiBold;
203   }
204 
205 	bool IsItalic()
206   {
207     return FontStyle.Slant != SKFontStyleSlant.Upright;
208   }
209 
210 	bool IsFixedPitch()
211   {
212     return SkiaApi.sk_typeface_is_fixed_pitch (cast(sk_typeface_t*)Handle);
213   }
214 
215 	SKTypefaceStyle Style() {
216 	
217 			auto style = SKTypefaceStyle.Normal;
218 			if (FontWeight >= cast(int)SKFontStyleWeight.SemiBold)
219 				style |= SKTypefaceStyle.Bold;
220 			if (FontSlant != cast(int)SKFontStyleSlant.Upright)
221 				style |= SKTypefaceStyle.Italic;
222 			return style;
223 		
224 	}
225 
226 	int UnitsPerEm()
227   {
228     return SkiaApi.sk_typeface_get_units_per_em (cast(sk_typeface_t*)Handle);
229   }
230 
231 	int GlyphCount()
232   {
233     return SkiaApi.sk_typeface_count_glyphs (cast(sk_typeface_t*)Handle);
234   }
235 
236 	// GetTableTags
237 
238 	int TableCount()
239   {
240     return SkiaApi.sk_typeface_count_tables (cast(sk_typeface_t*)Handle);
241   } 
242 
243 	uint[] GetTableTags ()
244 	{
245     uint[] result;
246 		if (!TryGetTableTags ( result)) {
247 			throw new Exception ("Unable to read the tables for the file.");
248 		}
249 		return result;
250 	}
251 
252 	bool TryGetTableTags (out uint[] tags)
253 	{
254 		auto buffer = new uint[TableCount];
255 		uint* b = buffer.ptr; {
256 			if (SkiaApi.sk_typeface_get_table_tags (cast(sk_typeface_t*)Handle, b) == 0) {
257 				tags = null;
258 				return false;
259 			}
260 		}
261 		tags = buffer;
262 		return true;
263 	}
264 
265 	// GetTableSize
266 
267 	int GetTableSize (uint tag)
268   {
269     return cast(int)SkiaApi.sk_typeface_get_table_size (cast(sk_typeface_t*)Handle, tag);
270   }
271 		
272 
273 	// GetTableData
274 
275 	byte[] GetTableData (uint tag)
276 	{
277     byte[] result;
278 		if (!TryGetTableData (tag,  result)) {
279 			throw new Exception ("Unable to read the data table.");
280 		}
281 		return result;
282 	}
283 
284 	bool TryGetTableData (uint tag, out byte[] tableData)
285 	{
286 		auto length = GetTableSize (tag);
287 		auto buffer = new byte[length];
288 		byte* b = buffer.ptr; {
289 			if (!TryGetTableData (tag, 0, length, cast(void*)b)) {
290 				tableData = null;
291 				return false;
292 			}
293 		}
294 		tableData = buffer;
295 		return true;
296 	}
297 
298 	bool TryGetTableData (uint tag, int offset, int length, void* tableData)
299 	{
300 		auto actual = SkiaApi.sk_typeface_get_table_data (cast(sk_typeface_t*)Handle, tag, cast(void*)offset, cast(void*)length, cast(byte*)tableData);
301 		return actual !is null;
302 	}
303 
304 	// CountGlyphs (string/char)
305 
306 	int CountGlyphs (string str)
307   {
308     return GetFont ().CountGlyphs (str);
309   }
310 		
311 
312 	int CountGlyphs (string str, SKEncoding encoding)
313   {
314     return 	GetFont ().CountGlyphs (str);
315   }
316 	
317 
318 	int CountGlyphs (const(char)[] str)
319   {
320     return GetFont ().CountGlyphs (str);
321   }
322 		
323 
324 	// CountGlyphs (byte[])
325 	// [Obsolete ("Use CountGlyphs(byte[], SKTextEncoding) instead.")]
326 	int CountGlyphs (byte[] str, SKEncoding encoding)
327   {
328     return 	GetFont ().CountGlyphs (str, encoding.ToTextEncoding ());
329   }
330 	
331 
332 	int CountGlyphs (byte[] str, SKTextEncoding encoding)
333   {
334     return 	GetFont ().CountGlyphs (str, encoding);
335   }
336 	
337 
338 	int CountGlyphs (const(byte)[] str, SKEncoding encoding)	
339   {
340 		return GetFont ().CountGlyphs (str, encoding.ToTextEncoding ());
341 	}
342 
343 	int CountGlyphs (const(byte)[] str, SKTextEncoding encoding)	
344   {
345 		return GetFont ().CountGlyphs (str, encoding);
346 	}
347 
348 	// CountGlyphs (void*)
349 
350 	int CountGlyphs (void* str, int strLen, SKEncoding encoding)	
351   {
352 		return CountGlyphs (str, strLen, encoding.ToTextEncoding ());
353 	}
354 
355 	int CountGlyphs (void* str, int strLen, SKTextEncoding encoding)	
356   {
357     return GetFont ().CountGlyphs (str, strLen, encoding);
358 		// return GetFont ().CountGlyphs (str, strLen * encoding.GetCharacterByteSize (), encoding);
359 	}
360 
361 	// GetGlyph (int)
362 
363 	ushort GetGlyph (int codepoint)	
364   {
365 		return GetFont ().GetGlyph (codepoint);
366 	}
367 
368 	// GetGlyphs (int)
369 
370 	ushort[] GetGlyphs (const(int)[] codepoints)
371   {
372     return GetFont ().GetGlyphs (codepoints);
373   }
374 		
375 
376 	// GetGlyphs (string/char, out)
377 
378 	int GetGlyphs (string text, out ushort[] glyphs)
379 	{
380 		glyphs = GetGlyphs (text);
381 		return cast(int)glyphs.length;
382 	}
383 
384 	int GetGlyphs (string text, SKEncoding encoding, out ushort[] glyphs)
385   {
386     return GetGlyphs (text, glyphs);
387   }
388 	
389 
390 	// GetGlyphs (byte[], out)
391 	// [Obsolete ("Use GetGlyphs(byte[], SKTextEncoding) instead.")]
392 	int GetGlyphs (byte[] text, SKEncoding encoding, out ushort[] glyphs)
393   {
394     return GetGlyphs (cast(const(byte)[])text, encoding,  glyphs);
395   }
396 		
397 
398 	int GetGlyphs (const(byte)[] text, SKEncoding encoding, out ushort[] glyphs)
399 	{
400 		glyphs = GetGlyphs (text, encoding);
401 		return cast(int)glyphs.length;
402 	}
403 
404 	// GetGlyphs (void*, out)
405 
406 	int GetGlyphs (void* text, int length, SKEncoding encoding, out ushort[] glyphs)
407 	{
408 		glyphs = GetGlyphs (text, length, encoding);
409 		return cast(int)glyphs.length;
410 	}
411 
412 	// GetGlyphs (string/char)
413 
414 	ushort[] GetGlyphs (string text)
415   {
416     return 	GetGlyphs (cast(const(char)[])text);
417   }
418 	
419 
420 	ushort[] GetGlyphs (string text, SKEncoding encoding)
421   {
422     return GetGlyphs (cast(const(char)[])text);
423   }
424 		
425 
426 	ushort[] GetGlyphs (const(char)[] text)
427 	{
428 		auto font =  ToFont ();
429 		scope(exit) {
430 		    font.Dispose();
431 		}
432 
433 		return font.GetGlyphs (text);
434 	}
435 
436 	// GetGlyphs (byte[])
437 
438 	ushort[] GetGlyphs (byte[] text, SKEncoding encoding)	
439   {
440 		return GetGlyphs (cast(const(byte)[])text, encoding.ToTextEncoding ());
441 	}
442 
443 	ushort[] GetGlyphs (const(byte)[] text, SKEncoding encoding)	
444   {
445 		return GetGlyphs (text, encoding.ToTextEncoding ());
446 	}
447 
448 	ushort[] GetGlyphs (const(byte)[] text, SKTextEncoding encoding)
449 	{
450 		auto font =  ToFont ();
451 		scope(exit) {
452 		    font.Dispose();
453 		}
454 
455 		return font.GetGlyphs (text, encoding);
456 	}
457 
458 	// GetGlyphs (void*)
459 
460 	ushort[] GetGlyphs (void* text, int length, SKEncoding encoding)	
461   {
462 		return GetGlyphs (text, length, encoding.ToTextEncoding ());
463 	}
464 
465 	ushort[] GetGlyphs (void* text, int length, SKTextEncoding encoding)
466 	{
467 		auto font =  ToFont ();
468 		scope(exit) {
469 		    font.Dispose();
470 		}
471 
472     return font.GetGlyphs (text, length , encoding);
473 		// return font.GetGlyphs (text, length * encoding.GetCharacterByteSize (), encoding);
474 	}
475 
476 	// ContainsGlyph
477 
478 	bool ContainsGlyph (int codepoint)	
479   {
480 		return GetFont ().ContainsGlyph (codepoint);
481 	}
482 
483 	// ContainsGlyphs
484 
485 	bool ContainsGlyphs (const(int)[] codepoints)	
486   {
487 		return GetFont ().ContainsGlyphs (codepoints);
488 	}
489 
490 	bool ContainsGlyphs (string text)	
491   {
492 		return GetFont ().ContainsGlyphs (text);
493 	}
494 
495 	bool ContainsGlyphs (const(char)[] text)	
496   {
497 		return GetFont ().ContainsGlyphs (text);
498 	}
499 
500 	bool ContainsGlyphs (const(byte)[] text, SKTextEncoding encoding)	
501   {
502 		return ContainsGlyphs (text, encoding);
503 	}
504 
505 	bool ContainsGlyphs (void* text, int length, SKTextEncoding encoding)	
506   {
507     return GetFont ().ContainsGlyphs (text, length , encoding);
508 		// return GetFont ().ContainsGlyphs (text, length * encoding.GetCharacterByteSize (), encoding);
509 	}
510 
511 	// GetFont
512 
513 	SKFont GetFont ()
514   {
515 		if(font is null) {
516 			font = OwnedBy (new SKFont (this), this);
517 		}
518 
519 		return font;
520     // return font ? font : OwnedBy (new SKFont (this), this);
521   }
522 		
523 
524 	// ToFont
525 
526 	SKFont ToFont () 
527   {
528     return new SKFont (this);
529   }
530 		
531 
532 	SKFont ToFont (float size, float scaleX = SKFont.DefaultScaleX, float skewX = SKFont.DefaultSkewX)
533   {
534     return new SKFont (this, size, scaleX, skewX);
535   }
536 		
537 
538 	// OpenStream
539 
540 	SKStreamAsset OpenStream ()
541   {
542     // return OpenStream ( _);
543     return null;
544   }
545 		
546 
547 	SKStreamAsset OpenStream (out int ttcIndex)
548 	{
549 		// int* ttc = &ttcIndex;
550 		// return SKStreamAsset.GetObject (SkiaApi.sk_typeface_open_stream (cast(sk_typeface_t*)Handle, ttc));
551     return null;
552 	}
553 
554 	// GetKerningPairAdjustments
555 
556 	int[] GetKerningPairAdjustments (ushort[] glyphs)
557 	{
558 		auto adjustments = new int[glyphs.length];
559 		ushort* gp = glyphs.ptr;
560 		int* ap = adjustments.ptr;
561 		SkiaApi.sk_typeface_get_kerning_pair_adjustments (cast(sk_typeface_t*)Handle, gp, cast(int)glyphs.length, ap);
562 		return adjustments;
563 	}
564 
565 	//
566 
567 	static SKTypeface GetObject (void* handle)
568   {
569     // return GetOrAddObject (handle, (h, o){return new SKTypeface (h, o);});
570     return GetOrAddObject!(SKTypeface)(handle, delegate SKTypeface (h, o) { return new SKTypeface (h, o);});
571   }
572 		
573 
574 }
575 
576 
577 	//
578 
579 	class SKTypefaceStatic : SKTypeface
580 	{
581 		this (void* x)
582 		{
583       super (x, true);
584 			// IgnorePublicDispose = true;
585 		}
586 	}