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 }