git-svn-id: https://pdfsharp.svn.codeplex.com/svn@39620 56d0cb2f-6006-4f69-a5a2-94740...
[pdfsharp:pdfsharp.git] / PDFsharp / code / PdfSharp / PdfSharp.Fonts / FontDescriptorStock.cs
1 #region PDFsharp - A .NET library for processing PDF\r
2 //\r
3 // Authors:\r
4 //   Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)\r
5 //\r
6 // Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)\r
7 //\r
8 // http://www.pdfsharp.com\r
9 // http://sourceforge.net/projects/pdfsharp\r
10 //\r
11 // Permission is hereby granted, free of charge, to any person obtaining a\r
12 // copy of this software and associated documentation files (the "Software"),\r
13 // to deal in the Software without restriction, including without limitation\r
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
15 // and/or sell copies of the Software, and to permit persons to whom the\r
16 // Software is furnished to do so, subject to the following conditions:\r
17 //\r
18 // The above copyright notice and this permission notice shall be included\r
19 // in all copies or substantial portions of the Software.\r
20 //\r
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
24 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r
27 // DEALINGS IN THE SOFTWARE.\r
28 #endregion\r
29 \r
30 using System;\r
31 using System.Diagnostics;\r
32 using System.Collections.Generic;\r
33 using PdfSharp.Drawing;\r
34 using PdfSharp.Fonts.OpenType;\r
35 \r
36 namespace PdfSharp.Fonts\r
37 {\r
38 #if true\r
39   /// <summary>\r
40   /// Global table of TrueType fontdescriptor objects.\r
41   /// </summary>\r
42   class FontDescriptorStock\r
43   {\r
44     FontDescriptorStock()\r
45     {\r
46       this.table = new Dictionary<FontSelector, FontDescriptor>();\r
47     }\r
48 \r
49     /// <summary>\r
50     /// Gets the FontDescriptor identified by the specified FontSelector. Returns null if no\r
51     /// such objects exists.\r
52     /// </summary>\r
53     public FontDescriptor FindDescriptor(FontSelector selector)\r
54     {\r
55       if (selector == null)\r
56         return null;\r
57 \r
58       FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
59       return descriptor;\r
60     }\r
61 \r
62     ///// <summary>\r
63     ///// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
64     ///// exists, a new FontDescriptor is created and added to the stock.\r
65     ///// </summary>\r
66     //public FontDescriptor CreateDescriptor(FontSelector selector)\r
67     //{\r
68     //  if (selector == null)\r
69     //    throw new ArgumentNullException("selector");\r
70 \r
71     //  FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
72     //  if (descriptor == null)\r
73     //  {\r
74     //    descriptor = new TrueTypeDescriptor(selector);\r
75     //    this.table.Add(selector, descriptor);\r
76     //  }\r
77     //  return descriptor;\r
78     //}\r
79 \r
80     /// <summary>\r
81     /// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
82     /// exists, a new FontDescriptor is created and added to the stock.\r
83     /// </summary>\r
84     public FontDescriptor CreateDescriptor(XFont font)\r
85     {\r
86       if (font == null)\r
87         throw new ArgumentNullException("font");\r
88 \r
89       FontSelector selector = new FontSelector(font);\r
90       FontDescriptor descriptor;\r
91       if (!this.table.TryGetValue(selector, out descriptor))\r
92       {\r
93         lock (typeof(FontDescriptorStock))\r
94         {\r
95           // may be created by other thread meanwhile\r
96           if (!this.table.TryGetValue(selector, out descriptor))\r
97           {\r
98             descriptor = new OpenTypeDescriptor(font);\r
99             this.table.Add(selector, descriptor);\r
100           }\r
101         }\r
102       }\r
103       return descriptor;\r
104     }\r
105 \r
106     /// <summary>\r
107     /// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
108     /// exists, a new FontDescriptor is created and added to the stock.\r
109     /// </summary>\r
110     public FontDescriptor CreateDescriptor(XFontFamily family, XFontStyle style)\r
111     {\r
112       if (family == null)\r
113         throw new ArgumentNullException("family");\r
114 \r
115       FontSelector selector = new FontSelector(family, style);\r
116       FontDescriptor descriptor;\r
117       if (!this.table.TryGetValue(selector, out descriptor))\r
118       {\r
119         lock (typeof(FontDescriptorStock))\r
120         {\r
121           // may be created by other thread meanwhile\r
122           if (!this.table.TryGetValue(selector, out descriptor))\r
123           {\r
124             XFont font = new XFont(family.Name, 10, style);\r
125             descriptor = new OpenTypeDescriptor(font);\r
126             if (this.table.ContainsKey(selector))\r
127               GetType();\r
128             else\r
129               this.table.Add(selector, descriptor);\r
130           }\r
131         }\r
132       }\r
133       return descriptor;\r
134     }\r
135 \r
136     public FontDescriptor CreateDescriptor(string idName, byte[] fontData)\r
137     {\r
138       FontSelector selector = new FontSelector(idName);\r
139       FontDescriptor descriptor;\r
140       if (!this.table.TryGetValue(selector, out descriptor))\r
141       {\r
142         lock (typeof(FontDescriptorStock))\r
143         {\r
144           // may be created by other thread meanwhile\r
145           if (!this.table.TryGetValue(selector, out descriptor))\r
146           {\r
147             descriptor = new OpenTypeDescriptor(idName, fontData);\r
148             this.table.Add(selector, descriptor);\r
149           }\r
150         }\r
151       }\r
152       return descriptor;\r
153     }\r
154 \r
155     //public FontDescriptor RegisterFontDate(byte[] fontData)\r
156     //{\r
157     //  uint checksum = CalcChecksum(fontData);\r
158     //  string name = String.Format("??{0:X}", checksum);\r
159     //  FontSelector selector = new FontSelector(name); // HACK: font data distinguished only by checksum\r
160     //  FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
161     //  if (descriptor == null)\r
162     //  {\r
163     //    lock (typeof(FontDescriptorStock))\r
164     //    {\r
165     //      // may be created by other thread meanwhile\r
166     //      descriptor = this.table[selector] as FontDescriptor;\r
167     //      if (descriptor == null)\r
168     //      {\r
169     //        descriptor = new TrueTypeDescriptor(fontData);\r
170     //        this.table.Add(selector, descriptor);\r
171     //      }\r
172     //    }\r
173     //  }\r
174     //  return descriptor;\r
175     //}\r
176 \r
177     ///// <summary>\r
178     ///// Calculates an Adler32 checksum.\r
179     ///// </summary>\r
180     //uint CalcChecksum(byte[] buffer)\r
181     //{\r
182     //  if (buffer == null)\r
183     //    throw new ArgumentNullException("buffer");\r
184 \r
185     //  const uint BASE = 65521; // largest prime smaller than 65536\r
186     //  uint s1 = 0;\r
187     //  uint s2 = 0;\r
188     //  int length = buffer.Length;\r
189     //  int offset = 0;\r
190     //  while (length > 0)\r
191     //  {\r
192     //    int n = 3800;\r
193     //    if (n > length)\r
194     //      n = length;\r
195     //    length -= n;\r
196     //    while (--n >= 0)\r
197     //    {\r
198     //      s1 = s1 + (uint)(buffer[offset++] & 0xFF);\r
199     //      s2 = s2 + s1;\r
200     //    }\r
201     //    s1 %= BASE;\r
202     //    s2 %= BASE;\r
203     //  }\r
204     //  return (s2 << 16) | s1;\r
205     //}\r
206 \r
207     public static FontDescriptorStock Global\r
208     {\r
209       get\r
210       {\r
211         if (global == null)\r
212         {\r
213           lock (typeof(FontDescriptorStock))\r
214           {\r
215             if (global == null)\r
216               global = new FontDescriptorStock();\r
217           }\r
218         }\r
219         return global;\r
220       }\r
221     }\r
222     static FontDescriptorStock global;\r
223 \r
224     Dictionary<FontSelector, FontDescriptor> table;\r
225 \r
226     /// <summary>\r
227     /// A collection of information that uniquely identifies a particular font.\r
228     /// Used to map XFont to PdfFont.\r
229     /// There is a one to one relationship between a FontSelector and a TrueType/OpenType file.\r
230     /// </summary>\r
231     internal class FontSelector\r
232     {\r
233       public FontSelector(XFont font)\r
234       {\r
235         this.name = font.Name;\r
236         this.style = font.Style;\r
237       }\r
238 \r
239       public FontSelector(XFontFamily family, XFontStyle style)\r
240       {\r
241         this.name = family.Name;\r
242         this.style = style;\r
243       }\r
244 \r
245       public FontSelector(string idName)\r
246       {\r
247         this.name = idName;\r
248         this.style = XFontStyle.Regular;\r
249       }\r
250 \r
251       public string Name\r
252       {\r
253         get { return this.name; }\r
254       }\r
255       string name;\r
256 \r
257       public XFontStyle Style\r
258       {\r
259         get { return this.style; }\r
260       }\r
261       XFontStyle style;\r
262 \r
263       public static bool operator ==(FontSelector selector1, FontSelector selector2)\r
264       {\r
265         if (!Equals(selector1, null))\r
266           selector1.Equals(selector2);\r
267         return Equals(selector2, null);\r
268       }\r
269 \r
270       public static bool operator !=(FontSelector selector1, FontSelector selector2)\r
271       {\r
272         return !(selector1 == selector2);\r
273       }\r
274 \r
275       public override bool Equals(object obj)\r
276       {\r
277         if (obj == null)  // removing this can lead to stack overflow\r
278           return false;\r
279         FontSelector selector = obj as FontSelector;\r
280         if (!Equals(selector, null))\r
281           return this.name == selector.name && this.style == selector.style;\r
282         return false;\r
283       }\r
284 \r
285       public override int GetHashCode()\r
286       {\r
287         return this.name.GetHashCode() ^ this.style.GetHashCode();\r
288       }\r
289 \r
290       /// <summary>\r
291       /// Returns a string for diagnostic purposes only.\r
292       /// </summary>\r
293       public override string ToString()\r
294       {\r
295         string variation = "";\r
296         switch (this.style)\r
297         {\r
298           case XFontStyle.Regular:\r
299             variation = "(Regular)";\r
300             break;\r
301 \r
302           case XFontStyle.Bold:\r
303             variation = "(Bold)";\r
304             break;\r
305 \r
306           case XFontStyle.Italic:\r
307             variation = "(Italic)";\r
308             break;\r
309 \r
310           case XFontStyle.Bold | XFontStyle.Italic:\r
311             variation = "(BoldItalic)";\r
312             break;\r
313         }\r
314         return this.name + variation;\r
315       }\r
316     }\r
317   }\r
318 #else\r
319   /// <summary>\r
320   /// Global table of TrueType fontdescriptor objects.\r
321   /// </summary>\r
322   class FontDescriptorStock\r
323   {\r
324     private FontDescriptorStock()\r
325     {\r
326       this.table = new Hashtable();\r
327     }\r
328 \r
329     /// <summary>\r
330     /// Gets the FontDescriptor identified by the specified FontSelector. Returns null if no\r
331     /// such objects exists.\r
332     /// </summary>\r
333     public FontDescriptor FindDescriptor(FontSelector selector)\r
334     {\r
335       if (selector == null)\r
336         return null;\r
337 \r
338       FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
339       return descriptor;\r
340     }\r
341 \r
342     ///// <summary>\r
343     ///// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
344     ///// exists, a new FontDescriptor is created and added to the stock.\r
345     ///// </summary>\r
346     //public FontDescriptor CreateDescriptor(FontSelector selector)\r
347     //{\r
348     //  if (selector == null)\r
349     //    throw new ArgumentNullException("selector");\r
350 \r
351     //  FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
352     //  if (descriptor == null)\r
353     //  {\r
354     //    descriptor = new TrueTypeDescriptor(selector);\r
355     //    this.table.Add(selector, descriptor);\r
356     //  }\r
357     //  return descriptor;\r
358     //}\r
359 \r
360     /// <summary>\r
361     /// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
362     /// exists, a new FontDescriptor is created and added to the stock.\r
363     /// </summary>\r
364     public FontDescriptor CreateDescriptor(XFont font)\r
365     {\r
366       if (font == null)\r
367         throw new ArgumentNullException("font");\r
368 \r
369       FontSelector selector = new FontSelector(font);\r
370       FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
371       if (descriptor == null)\r
372       {\r
373         lock (typeof(FontDescriptorStock))\r
374         {\r
375           // may be created by other thread meanwhile\r
376           descriptor = this.table[selector] as FontDescriptor;\r
377           if (descriptor == null)\r
378           {\r
379             descriptor = new TrueTypeDescriptor(font, font.privateFontCollection);\r
380             this.table.Add(selector, descriptor);\r
381           }\r
382         }\r
383       }\r
384       return descriptor;\r
385     }\r
386 \r
387     /// <summary>\r
388     /// Gets the FontDescriptor identified by the specified FontSelector. If no such objects \r
389     /// exists, a new FontDescriptor is created and added to the stock.\r
390     /// </summary>\r
391     public FontDescriptor CreateDescriptor(XFontFamily family, XFontStyle style)\r
392     {\r
393       if (family == null)\r
394         throw new ArgumentNullException("family");\r
395 \r
396       FontSelector selector = new FontSelector(family, style);\r
397       FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
398       if (descriptor == null)\r
399       {\r
400         lock (typeof(FontDescriptorStock))\r
401         {\r
402           // may be created by other thread meanwhile\r
403           descriptor = this.table[selector] as FontDescriptor;\r
404           if (descriptor == null)\r
405           {\r
406             XFont font = new XFont(family.Name, 10, style);\r
407             descriptor = new TrueTypeDescriptor(font, font.privateFontCollection);\r
408             if (this.table.ContainsKey(selector))\r
409               GetType();\r
410             else\r
411               this.table.Add(selector, descriptor);\r
412           }\r
413         }\r
414       }\r
415       return descriptor;\r
416     }\r
417 \r
418     public FontDescriptor CreateDescriptor(string idName, byte[] fontData)\r
419     {\r
420       FontSelector selector = new FontSelector(idName);\r
421       FontDescriptor descriptor = this.table[selector] as FontDescriptor;\r
422       if (descriptor == null)\r
423       {\r
424         lock (typeof(FontDescriptorStock))\r
425         {\r
426           // may be created by other thread meanwhile\r
427           descriptor = this.table[selector] as FontDescriptor;\r
428           if (descriptor == null)\r
429           {\r
430             descriptor = new TrueTypeDescriptor(idName, fontData);\r
431             this.table.Add(selector, descriptor);\r
432           }\r
433         }\r
434       }\r
435       return descriptor;\r
436     }\r
437 \r
438     public static FontDescriptorStock Global\r
439     {\r
440       get\r
441       {\r
442         if (FontDescriptorStock.global == null)\r
443         {\r
444           lock (typeof(FontDescriptorStock))\r
445           {\r
446             if (FontDescriptorStock.global == null)\r
447               FontDescriptorStock.global = new FontDescriptorStock();\r
448           }\r
449         }\r
450         return FontDescriptorStock.global;\r
451       }\r
452     }\r
453     static FontDescriptorStock global;\r
454 \r
455     H ashtable table;\r
456 \r
457     /// <summary>\r
458     /// A collection of information that uniquely identifies a particular font.\r
459     /// Used to map XFont to PdfFont.\r
460     /// There is a one to one relationship between a FontSelector and a TrueType/OpenType file.\r
461     /// </summary>\r
462     internal class FontSelector\r
463     {\r
464       public FontSelector(XFont font)\r
465       {\r
466         this.name = font.Name;\r
467         this.style = font.Style;\r
468       }\r
469 \r
470       public FontSelector(XFontFamily family, XFontStyle style)\r
471       {\r
472         this.name = family.Name;\r
473         this.style = style;\r
474       }\r
475 \r
476       public FontSelector(string idName)\r
477       {\r
478         this.name = idName;\r
479         this.style = XFontStyle.Regular;\r
480       }\r
481 \r
482       public string Name\r
483       {\r
484         get { return this.name; }\r
485       }\r
486       string name;\r
487 \r
488       public XFontStyle Style\r
489       {\r
490         get { return this.style; }\r
491       }\r
492       XFontStyle style;\r
493 \r
494       public static bool operator ==(FontSelector selector1, FontSelector selector2)\r
495       {\r
496         if (selector1 != null)\r
497           selector1.Equals(selector2);\r
498         return selector2 == null;\r
499       }\r
500 \r
501       public static bool operator !=(FontSelector selector1, FontSelector selector2)\r
502       {\r
503         return !(selector1 == selector2);\r
504       }\r
505 \r
506       public override bool Equals(object obj)\r
507       {\r
508         FontSelector selector = obj as FontSelector;\r
509         if (obj != null && this.name == selector.name)\r
510           return this.style == selector.style;\r
511         return false;\r
512       }\r
513 \r
514       public override int GetHashCode()\r
515       {\r
516         return this.name.GetHashCode() ^ this.style.GetHashCode();\r
517       }\r
518 \r
519       /// <summary>\r
520       /// Returns a string for diagnostic purposes only.\r
521       /// </summary>\r
522       public override string ToString()\r
523       {\r
524         string variation = "";\r
525         switch (this.style)\r
526         {\r
527           case XFontStyle.Regular:\r
528             variation = "(Regular)";\r
529             break;\r
530 \r
531           case XFontStyle.Bold:\r
532             variation = "(Bold)";\r
533             break;\r
534 \r
535           case XFontStyle.Italic:\r
536             variation = "(Italic)";\r
537             break;\r
538 \r
539           case XFontStyle.Bold | XFontStyle.Italic:\r
540             variation = "(BoldItalic)";\r
541             break;\r
542         }\r
543         return this.name + variation;\r
544       }\r
545     }\r
546   }\r
547 #endif\r
548 }