1 /* libsswf_tag_font.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */
2
3 /*
4
5 Copyright (c) 2002-2008 Made to Order Software Corp.
6
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31
32 */
33
34 /** \file
35 *
36 * \brief The implementation of the sswf::TagFont class
37 *
38 * This file declares the body of the functions which are not
39 * inline. It is part of the SSWF library.
40 */
41
42 #include "sswf/libsswf.h"
43
44 using namespace sswf;
45
46
47
48 /////////////////////////////////////////// TagFont
49
50
51 /** \class sswf::TagFont
52 *
53 * \brief Define a system or embedded font.
54 *
55 * This tag is used to define a font.
56 *
57 * Embedded fonts include definitions for each glyph as required.
58 *
59 * System fonts just define the name of the system font.
60 *
61 * \sa sswf::TagShape
62 * \sa <a href="../SWFalexref.html#tag_definefont">SWF Alexis' Reference—Define Font</a>
63 * \sa <a href="../SWFalexref.html#tag_definefont2">SWF Alexis' Reference—Define Font2</a>
64 * \sa <a href="../SWFalexref.html#tag_definefont3">SWF Alexis' Reference—Define Font3</a>
65 * \sa <a href="../SWFalexref.html#tag_definefontinfo">SWF Alexis' Reference—Define Font Info</a>
66 * \sa <a href="../SWFalexref.html#tag_definefontinfo2">SWF Alexis' Reference—Define Font Info2</a>
67 * \sa <a href="../SWFalexref.html#tag_definefontname">SWF Alexis' Reference—Define Font Name</a>
68 * \sa <a href="../SWFalexref.html#tag_definefontalignzones">SWF Alexis' Reference—Define Font Align Zones</a>
69 * \sa <a href="../SWFalexref.html#tag_defineshape">SWF Alexis' Reference—Define Shape</a>
70 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference—swf_tag</a>
71 */
72
73
74
75 /** \enum sswf::TagFont::font_type_t
76 *
77 * \brief The list of font types.
78 *
79 * This enumeration defines the different types of fonts available.
80 */
81
82 /** \var sswf::TagFont::FONT_TYPE_BEST
83 *
84 * \brief Selects the best type which can be used.
85 *
86 * Use this type to let the font choose what it wants to make it all
87 * work properly.
88 */
89
90 /** \var sswf::TagFont::FONT_TYPE_ASCII
91 *
92 * \brief Select the type ASCII.
93 *
94 * This type represents a font with at most 256 characters.
95 */
96
97 /** \var sswf::TagFont::FONT_TYPE_UNICODE
98 *
99 * \brief Select the type UNICODE
100 *
101 * This type represents any font in all languages. It supports
102 * 65536 characters all together. The character numbers are defined
103 * by the Unicode consortium: http://www.unicode.org
104 *
105 * This is the prefered type since version 6.
106 */
107
108 /** \var sswf::TagFont::FONT_TYPE_SHIFTJIS
109 *
110 * \brief Select the type SHIFTJIS
111 *
112 * This type represents Japanese. I'm not too sure how this was
113 * used. Now, Japanese as well as Chinese, Korean, and any other
114 * language character set is defined using Unicode.
115 */
116
117 /** \enum sswf::TagFont::font_language_t
118 *
119 * \brief Language definition for a font.
120 *
121 * Before version 6, many strange things appeared in Flash including
122 * a language definition for a font. There is really no need for it.
123 * Just use Unicode.
124 */
125
126 /** \var sswf::TagFont::FONT_LANGUAGE_UNKNOWN
127 *
128 * \brief This value is used to mark a font as not having a language.
129 *
130 * This is the default value for a font.
131 */
132
133 /** \var sswf::TagFont::FONT_LANGUAGE_LOCALE
134 *
135 * \brief This value is used so the player uses the current locale.
136 *
137 * I'm not too sure what this was for. How can a font be defined by
138 * a changing locale?
139 */
140
141 /** \var sswf::TagFont::FONT_LANGUAGE_LATIN
142 *
143 * \brief Latin-1 languages.
144 *
145 * This value was for fonts representing the Latin-1 character set.
146 * (code page 0x00 in Unicode.)
147 */
148
149 /** \var sswf::TagFont::FONT_LANGUAGE_JAPANESE
150 *
151 * \brief Japanese language.
152 *
153 * This value was for fonts representing a set of Japanese glyphs.
154 */
155
156 /** \var sswf::TagFont::FONT_LANGUAGE_KOREAN
157 *
158 * \brief Korean language.
159 *
160 * This value was for fonts representing a set of Korean glyphs.
161 */
162
163 /** \var sswf::TagFont::FONT_LANGUAGE_SIMPLIFIED_CHINESE
164 *
165 * \brief Chinese language.
166 *
167 * This value was for fonts representing a set of simplified Chinese glyphs.
168 */
169
170 /** \var sswf::TagFont::FONT_LANGUAGE_TRADITIONAL_CHINESE
171 *
172 * \brief Chinese language.
173 *
174 * This value was for fonts representing a set of traditional Chinese glyphs.
175 */
176
177 /** \var sswf::TagFont::FONT_LANGUAGE_max
178 *
179 * \brief This represents the largest possible language code
180 *
181 * This can be used as a limit boundary.
182 */
183
184
185 /** \enum sswf::TagFont::font_thickness_t
186 *
187 * \brief Defines the thickness of the font.
188 *
189 * The Flash player will by default determine the thickness of a font
190 * using a lookup table. If the font isn't found in that table, then
191 * it uses the thickness defined in the SWF file.
192 */
193
194 /** \var sswf::TagFont::FONT_THICKNESS_UNKNOWN
195 *
196 * \brief The default: the thickness is not specified.
197 *
198 * The thickness is a feature of the fonts since SWF version 8. By
199 * default the thickness is not specified.
200 */
201
202 /** \var sswf::TagFont::FONT_THICKNESS_THIN
203 *
204 * \brief Defines the thickness of the font as thin.
205 *
206 * This is a thin font. This means thinner than normal (light).
207 */
208
209 /** \var sswf::TagFont::FONT_THICKNESS_MEDIUM
210 *
211 * \brief Defines the thickness of the font as medium.
212 *
213 * This is a medium font. This means a mostly normal font.
214 */
215
216 /** \var sswf::TagFont::FONT_THICKNESS_THICK
217 *
218 * \brief Defines the thickness of the font as thick.
219 *
220 * This is a thick font. This means thicker than normal (bold).
221 */
222
223
224
225
226
227
228
229 /** \brief Initializes the font object.
230 *
231 * This function sets the font object to defaults.
232 *
233 * By default a font has no name, no display name, no copyrigth,
234 * no predefined language, no type, no specific style, no
235 * glyph, etc.
236 *
237 * \param[in] parent The TagHeader where the TagFont is included.
238 */
TagFont(TagBase * parent)239 TagFont::TagFont(TagBase *parent)
240 : TagBaseID("font", parent)
241 {
242 f_font_name = 0;
243 f_display_name = 0;
244 f_copyright = 0;
245 f_language = FONT_LANGUAGE_UNKNOWN;
246 f_type = FONT_TYPE_BEST;
247 f_bold = false;
248 f_italic = false;
249 f_small_text = false;
250 f_wide = false;
251 f_has_wide_char = false; // defined in PreSave2ndPass() and used in Save()
252 f_has_wide_offsets = false; // defined in PreSave2ndPass() and used in Save()
253 f_has_layout = false; // defined in PreSave2ndPass() and used in Save()
254 f_used_by_edit_text = false;
255 f_define_font2 = false; // defined in PreSave2ndPass() and used in Save()
256 f_thickness = FONT_THICKNESS_UNKNOWN;
257 f_font_em_size = FONT_EM_SMALL;
258 f_ascent = DefaultAscent();
259 f_descent = DefaultDescent();
260 f_leading_height = DefaultLeadingHeight();
261 f_default_advance = 0;
262 f_space_advance = LONG_MIN;
263 f_offsets_max = 0; // defined in PreSave2ndPass() and used in Save()
264 f_offsets = 0; // defined in PreSave2ndPass() and used in Save()
265 f_count = 0;
266 //f_save_glyphs = ...
267 //f_glyphs = ...
268 //f_kerns = ...
269 }
270
271
272
273 /** \brief The flags defining a font.
274 *
275 * A font is a definition and it has an identifier.
276 *
277 * \return SWF_TYPE_DEFINE and SWF_TYPE_HAS_ID
278 */
TypeFlags(void) const279 TagBase::swf_type_t TagFont::TypeFlags(void) const
280 {
281 return SWF_TYPE_DEFINE | SWF_TYPE_HAS_ID;
282 }
283
284
285 /** \brief Prepare the font for saving.
286 *
287 * This function ensures that the font will properly be saved (as
288 * obtimized as possible.)
289 *
290 * The main action of this function is to clear the
291 * \em in \em use flag of all the glyphs to \em false.
292 * This means no glyphs will be saved in that font. The
293 * next step is for the other tags to mark exactly which
294 * glyphs are necessary for them. For instance, an edit text
295 * box could ask for all capital letters (A-Z) and another
296 * ask for digits (0-9).
297 *
298 * In order to complete the preparations before the Save()
299 * function is called, the PreSave2ndPass() will be called.
300 * That's at that time that the font can determine the index
301 * of each glyph since now it knows which glyph will be saved
302 * in the final font.
303 *
304 * \return An error code or ErrorManager::ERROR_CODE_NONE
305 */
PreSave(void)306 ErrorManager::error_code_t TagFont::PreSave(void)
307 {
308 long idx;
309
310 // reset the IN USE flag of each glyph
311 idx = f_glyphs.Count();
312 while(idx > 0) {
313 idx--;
314 dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx))->f_in_use = false;
315 }
316
317 f_used_by_edit_text = false;
318
319 // if not unknown it was defined by the user
320 // if not locale, then we need v6.x
321 if(f_language != FONT_LANGUAGE_UNKNOWN
322 && f_language != FONT_LANGUAGE_LOCALE) {
323 MinimumVersion(6);
324 }
325
326 // a font name with an underscore as the first
327 // character is taken as a "direct font name"
328 // and thus we need V6.x -- this way we avoid
329 // testing specific names and not be forward
330 // compatible at a later date when Macromedia
331 // decides to add new names.
332 if(f_font_name != 0 && *f_font_name == '_') {
333 MinimumVersion(6);
334 }
335
336 // the small text font hint appeared in version 7
337 if(f_small_text) {
338 MinimumVersion(7);
339 }
340
341 // with a proper thickness, we need a V8 and the DefineFontAlignZone
342 // for kerns to be useful, we need a V8 Flash animation
343 if(f_font_em_size == FONT_EM_LARGE
344 || f_kerns.Count() > 0) {
345 MinimumVersion(8);
346 }
347
348 // license info; display name defaults to font name
349 // if there is a copyright and no display name
350 if(f_display_name != 0 || f_copyright != 0) {
351 MinimumVersion(9);
352 }
353
354 return ErrorManager::ERROR_CODE_NONE;
355 }
356
357
358 /** \brief Finilize the font preparations for saving.
359 *
360 * This function is called after all the other objects PreSave()
361 * was called giving them a chance to define which of the embedded
362 * glyphs they use.
363 *
364 * At this point we also know whether the font must be defined
365 * with a DefineFont2 and using Unicode (wide) characters.
366 *
367 * \return An error code or ErrorManager::ERROR_CODE_NONE
368 */
PreSave2ndPass(void)369 ErrorManager::error_code_t TagFont::PreSave2ndPass(void)
370 {
371 font_glyph_t *glyph;
372 int idx, rmax;
373 unsigned long extra;
374 unsigned short *short_offsets;
375 #if DEBUG
376 sswf_ucs4_t previous;
377 #endif
378
379 // Now we know what character is used and whether an
380 // edit text is referencing this font - from the
381 // Macromedia documents, we have to have a DefineFont2
382 // if an edit text references a font
383 // Also, if anything said to use v6.x then the fonts
384 // must be saved in Unicode (no choice!)
385 //
386 // WARNING: it is not possible to change from prior
387 // version 6 to version 6 or more in the
388 // 2nd pass
389
390 f_define_font2 = false;
391
392 // by default we use the user defined f_wide flag
393 // which is forced to true if one or more glyph has
394 // an ID of 256 or more or we are using v6+
395 f_has_wide_char = f_wide || Version() >= 6;
396
397 // to know the size of the glyphs we need to compute it
398 // and that means creating the actual buffer of all the
399 // glyphs
400 rmax = f_glyphs.Count();
401
402 // the default layout flag value is set to true if some
403 // of the layout parameters are defined -- note that having
404 // a layout in a font doesn't mean we will use them (we do
405 // only if a DefineTextField -- an edit text -- references
406 // the font)
407 f_has_layout = f_ascent != DefaultAscent()
408 || f_descent != DefaultDescent()
409 || f_leading_height != DefaultLeadingHeight()
410 || f_kerns.Count() != 0;
411 /* Note: Macromedia says they are not currently taking
412 * the kerning in account... what about other players?
413 * -- Update: this has changed since version 8 -- now
414 * Macromedia has its own font renderer which takes
415 * the kernel in account.
416 */
417
418 // try to avoid re-allocating the offsets buffer if possible
419 if(f_offsets != 0) {
420 if(f_offsets_max < rmax + 1) {
421 MemClean(&f_offsets);
422 }
423 }
424 if(f_offsets == 0) {
425 f_offsets = (unsigned long *) MemAlloc((rmax + 1) * sizeof(unsigned long), "offsets to the glyphs");
426 f_offsets_max = rmax + 1;
427 }
428 // by default we have no glyphs (use only the DefineFontInfo[2]
429 // if no edit text references this font!)
430 #if DEBUG
431 previous = -1;
432 #endif
433 f_count = 0;
434 f_save_glyphs.Empty();
435 for(idx = 0; idx < rmax; idx++) {
436 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
437
438 #if DEBUG
439 // ensure that the glyphs are ordered properly
440 assert((long) glyph->f_name > (long) previous,
441 "TagFont::PreSave2ndPass() found unordered glyphs (%ld >= %ld)",
442 (long) previous, (long) glyph->f_name);
443 previous = glyph->f_name;
444 #endif
445
446 //printf("Glyph [%c] %s\n", glyph->f_name, glyph->f_in_use ? "in use" : "never referenced");
447
448 if(!glyph->f_in_use) {
449 // unused, just skip it
450 continue;
451 }
452 if(glyph->f_name > 255) {
453 f_has_wide_char = true;
454 }
455 /*
456 * Note: Macromedia says they don't use the per char
457 * bounding boxes -- what about other players?
458 */
459 if(glyph->f_shape->HasBounds()) {
460 f_has_layout = true;
461 }
462 glyph->f_index = (unsigned short) f_count; // index at which the glyph is being saved
463 f_offsets[f_count] = f_save_glyphs.ByteSize();
464 (const_cast<TagShape *>(glyph->f_shape))->SaveWithoutStyles(f_save_glyphs);
465 f_save_glyphs.Align();
466 f_count++;
467 }
468 // save the total size in the last offset entry
469 f_offsets[f_count] = f_save_glyphs.ByteSize();
470 f_count++;
471 // got to include this last entry here to make sure we don't
472 // overflow anything
473
474 // if an EditText tag references this font
475 // if the EM square of the font is large
476 //
477 // then we need a DefineFont2
478 //
479 // otherwise it depends on whether we need large
480 // offsets to access the glyphs
481 if(f_used_by_edit_text
482 || f_font_em_size == FONT_EM_LARGE) {
483 // NOTE: the MinimumVersion(3) is useless since the
484 // TagEditText forces v4.x already!
485 //MinimumVersion(3);
486 f_define_font2 = true;
487 }
488 else {
489 // we don't want any layout if we don't have
490 // an edit text (would be unused!)
491 f_has_layout = false;
492 }
493
494 // compute the size of the offset table
495 extra = (f_count - 1) * 2 + (f_define_font2 ? 2 : 0);
496 f_has_wide_offsets = f_offsets[f_count - 1] + extra > USHRT_MAX;
497 if(f_has_wide_offsets) {
498 MinimumVersion(3);
499
500 // only DefineFont2 accepts large offsets
501 if(!f_define_font2) {
502 f_define_font2 = true;
503 extra += 2;
504 }
505
506 // wide offsets! we need to add 2 x extra because
507 // that's the actual size of the table! Also include
508 // the offset to the map
509 extra *= 2;
510 for(idx = 0; (unsigned int) idx < f_count; idx++) {
511 #if BYTE_ORDER == BIG_ENDIAN
512 f_offsets[idx] = swap_int(f_offsets[idx] + extra);
513 #else
514 f_offsets[idx] += extra;
515 #endif
516 }
517 }
518 else {
519 short_offsets = reinterpret_cast<unsigned short *>(f_offsets);
520 for(idx = 0; (unsigned int) idx < f_count; idx++) {
521 #if BYTE_ORDER == BIG_ENDIAN
522 short_offsets[idx] = swap_short((unsigned short) (f_offsets[idx] + extra));
523 #else
524 short_offsets[idx] = (unsigned short) (f_offsets[idx] + extra);
525 #endif
526 }
527 }
528
529 return ErrorManager::ERROR_CODE_NONE;
530 }
531
532
533 /** \brief Save the TagFont in the specified Data buffer
534 *
535 * This function saves the font in the specified Data buffer.
536 *
537 * It will save the glyphs in the DefineFont or DefineFont2 tag.
538 * And some extraneous information in a DefineFontInfo or
539 * DefineFontInfo2 tag. And it saves the name and license in a
540 * DefineFontName tag.
541 *
542 * To save the glyphs, the TagFont calls the
543 * sswf::TagShape::SaveWithoutStyles(Data& data) function.
544 *
545 * \param[in] data The Data buffer where the font tags are saved
546 *
547 * \return An error code or ErrorManager::ERROR_CODE_NONE
548 *
549 * \sa sswf::TagShape::SaveWithoutStyles(Data& data)
550 */
Save(Data & data)551 ErrorManager::error_code_t TagFont::Save(Data& data)
552 {
553 Data sub_data, kern_data;
554 font_glyph_t *glyph;
555 font_kern_t *kern;
556 const char *name, *license;
557 int idx, max, rmax, cnt, used, l1, l2;
558 bool has_align_zones;
559
560 rmax = f_glyphs.Count();
561
562 // if the f_font_define2 is set, then we save that type of a
563 // font, otherwise save a define font + define font info if
564 // required
565 if(f_define_font2) {
566 SaveID(sub_data);
567 sub_data.WriteBits(f_has_layout, 1);
568
569 // by default we assume that we have alignment zones
570 // unless there are no glyphs
571 has_align_zones = rmax != 0;
572
573 // can types be all set? it isn't clear in any doc.
574 if(Version() <= 5) {
575 switch(f_type) {
576 case FONT_TYPE_BEST:
577 sub_data.WriteBits(0, 3); /* not specific */
578 break;
579
580 case FONT_TYPE_ASCII:
581 sub_data.WriteBits(1, 3);
582 break;
583
584 /*
585 * this is now defined as always zero in v6.x doc.
586 * it was properly defined as the Unicode flag
587 * before and is perfectly valid in prior v6.x
588 * movies!
589 */
590 case FONT_TYPE_UNICODE:
591 sub_data.WriteBits(2, 3);
592 break;
593
594 case FONT_TYPE_SHIFTJIS:
595 sub_data.WriteBits(4, 3);
596 break;
597
598 }
599 }
600 else {
601 sub_data.WriteBits(0, 1);
602 sub_data.WriteBits(f_small_text, 1);
603 sub_data.WriteBits(0, 1);
604 }
605
606 // determine whether we need to use wide offsets
607 sub_data.WriteBits(f_has_wide_offsets, 1);
608
609 sub_data.WriteBits(f_has_wide_char, 1);
610
611 sub_data.WriteBits(f_italic, 1);
612 sub_data.WriteBits(f_bold, 1);
613
614 // language in v6.x, 0 otherwise
615 if(Version() <= 5) {
616 sub_data.PutByte(0);
617 }
618 else {
619 sub_data.PutByte(f_language);
620 }
621
622 cnt = f_font_name == 0 ? 0 : strlen(f_font_name);
623 if(cnt > 255) {
624 OnError(ErrorManager::ERROR_CODE_NAME_TOO_LONG, "a font name cannot be more than 255 characters long, change \"%s\"", f_font_name);
625 cnt = 255;
626 }
627 sub_data.PutByte(cnt); /* this one is a Pstring, why is that, dunno... */
628 sub_data.Write(f_font_name, cnt);
629
630 // save the number of glyphs
631 // we MUST have one extra "offset" that actually represents the size of the
632 // table so one can skip all the glyphs at once
633 sub_data.PutShort((short) (f_count - 1));
634
635 // save the array of offsets
636 sub_data.Write(f_offsets, f_count * (f_has_wide_offsets ? 4 : 2));
637
638 // save the shapes
639 sub_data.Append(f_save_glyphs);
640
641 // save the mapping between the shapes and characters
642 for(idx = 0; idx < rmax; idx++) {
643 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
644 if(!glyph->f_in_use) {
645 // unused, just skip it
646 continue;
647 }
648 if(f_has_wide_char) {
649 sub_data.PutShort((unsigned short) glyph->f_name);
650 }
651 else {
652 sub_data.PutByte((unsigned char) glyph->f_name);
653 }
654 if(!glyph->f_shape->HasAlignZone()) {
655 has_align_zones = false;
656 }
657 }
658
659 if(f_has_layout) {
660 sub_data.PutShort((short) f_ascent);
661 sub_data.PutShort((short) f_descent);
662 sub_data.PutShort((short) f_leading_height);
663 for(idx = 0; idx < rmax; idx++) {
664 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
665 if(!glyph->f_in_use) {
666 // unused, just skip it
667 continue;
668 }
669 if(glyph->f_advance != LONG_MIN) {
670 sub_data.PutShort((short) glyph->f_advance);
671 }
672 else {
673 // if not specific to a character, use the default
674 sub_data.PutShort((short) f_default_advance);
675 }
676 }
677 for(idx = 0; idx < rmax; idx++) {
678 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
679 if(!glyph->f_in_use) {
680 // unused, just skip it
681 continue;
682 }
683 glyph->f_shape->Bounds(0).Save(sub_data);
684 sub_data.Align(); // <- is this correct? shouldn't it be in the rectangle Save() function?
685 }
686 // New max (i.e. the # of kerning entries)
687 max = f_kerns.Count();
688 for(idx = 0, cnt = 0; idx < max; idx++) {
689 kern = dynamic_cast<font_kern_t *>(f_kerns.Get(idx));
690 /*
691 * before to save a kern we want to make sure it's not
692 * useless; we go through the list of glyph and ensures
693 * that BOTH the glyphs are defined in the font; if not
694 * then this kerning can't even happen so we don't need
695 * it and thus don't save it.
696 */
697 for(idx = 0, used = 0; idx < rmax && used != 3; idx++) {
698 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
699 if(glyph->f_name == kern->f_code[0]) {
700 if(!glyph->f_in_use) {
701 break;
702 }
703 used |= 1;
704 }
705 // don't put an 'else' here since code0 == code1
706 // is possible! (though probably really rare?)
707 if(glyph->f_name == kern->f_code[1]) {
708 if(!glyph->f_in_use) {
709 break;
710 }
711 used |= 2;
712 }
713 }
714 if(used == 3) {
715 if(f_has_wide_char) {
716 kern_data.PutShort((unsigned short) kern->f_code[0]);
717 kern_data.PutShort((unsigned short) kern->f_code[1]);
718 }
719 else {
720 kern_data.PutByte((unsigned char) kern->f_code[0]);
721 kern_data.PutByte((unsigned char) kern->f_code[1]);
722 }
723 kern_data.PutShort((short) kern->f_advance);
724 cnt++;
725 }
726 }
727 // now we can save the kerning tables
728 sub_data.PutShort(cnt);
729 sub_data.Append(kern_data);
730 }
731 SaveTag(data, f_font_em_size == FONT_EM_LARGE ? SWF_TAG_DEFINE_FONT3 : SWF_TAG_DEFINE_FONT2, sub_data.ByteSize());
732 data.Append(sub_data);
733
734 // if we had zones, then we save them now
735 if(has_align_zones) {
736 if(f_font_em_size == FONT_EM_LARGE) {
737 // There is no compression for this tag so we can compute the
738 // size at once and avoid saving things in an intermediate buffer
739 SaveTag(data, SWF_TAG_DEFINE_FONT_ALIGN_ZONES, 5 + (f_count - 1) * 8);
740 data.PutShort(Identification());
741 if(f_thickness == FONT_THICKNESS_UNKNOWN) {
742 data.WriteBits(FONT_THICKNESS_MEDIUM, 2);
743 }
744 else {
745 data.WriteBits(f_thickness, 2);
746 }
747 data.WriteBits(0, 6);
748 data.PutByte(2); // 2 entries per zone
749 for(idx = 0; idx < rmax; idx++) {
750 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
751 if(!glyph->f_in_use) {
752 // unused, just skip it
753 continue;
754 }
755 glyph->f_shape->SaveAlignZone(data);
756 }
757 data.WriteBits(1, 1); // zone_x
758 data.WriteBits(1, 1); // zone_y
759 data.WriteBits(0, 6); // reserver
760 }
761 else {
762 OnError(ErrorManager::ERROR_CODE_INVALID_EM_SQUARE, "alignment zones in glyphs cannot be saved unless the font is marked as having a Large EM Square");
763 }
764 }
765 }
766 else {
767 // if there isn't any glyph we still need a DefineFont tag
768 SaveID(sub_data);
769 sub_data.Write(f_offsets, f_count == 1 ? 2 : (f_count - 1) * 2);
770 sub_data.Append(f_save_glyphs);
771 SaveTag(data, SWF_TAG_DEFINE_FONT, sub_data.ByteSize());
772 data.Append(sub_data);
773
774 // in some cases we also want to save a DefineFontInfo
775 if((f_font_name != 0 && *f_font_name != '\0')
776 || f_bold || f_italic
777 || (f_language != FONT_LANGUAGE_UNKNOWN && f_language != FONT_LANGUAGE_LOCALE)
778 || f_count == 1) {
779 sub_data.Empty();
780 SaveID(sub_data); // same ID as the font
781
782 cnt = f_font_name == 0 ? 0 : strlen(f_font_name);
783 if(cnt > 255) {
784 OnError(ErrorManager::ERROR_CODE_NAME_TOO_LONG, "a font name cannot be more than 255 characters long, change \"%s\"", f_font_name);
785 cnt = 255;
786 }
787 sub_data.PutByte(cnt); /* this one is a Pstring, why is that, dunno... */
788 sub_data.Write(f_font_name, cnt);
789
790 sub_data.WriteBits(0, 2);
791 if(Version() >= 6) {
792 sub_data.WriteBits(f_small_text, 1);
793 sub_data.WriteBits(0, 2);
794 }
795 else {
796 switch(f_type) {
797 case FONT_TYPE_BEST:
798 sub_data.WriteBits(0, 3); /* not specific */
799 break;
800
801 case FONT_TYPE_ASCII:
802 sub_data.WriteBits(1, 3);
803 break;
804
805 case FONT_TYPE_SHIFTJIS:
806 sub_data.WriteBits(2, 3);
807 break;
808
809 /*
810 * this is now defined as always zero in v6.x doc.
811 * it was properly defined as the Unicode flag
812 * before and is perfectly valid in prior v6.x
813 * movies!
814 */
815 case FONT_TYPE_UNICODE:
816 sub_data.WriteBits(4, 3);
817 break;
818
819 }
820 }
821 sub_data.WriteBits(f_italic, 1);
822 sub_data.WriteBits(f_bold, 1);
823
824 // here we know that f_has_wide_char is
825 // already 1 when Version() >= 6
826 sub_data.WriteBits(f_has_wide_char, 1);
827
828 if(Version() >= 6) {
829 sub_data.PutByte(f_language);
830 }
831
832 // save the mapping between the shapes and characters
833 for(idx = 0; idx < rmax; idx++) {
834 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx));
835 if(!glyph->f_in_use) {
836 // unused, just skip it
837 continue;
838 }
839 if(f_has_wide_char) {
840 sub_data.PutShort((unsigned short) glyph->f_name);
841 }
842 else {
843 sub_data.PutByte((unsigned char) glyph->f_name);
844 }
845 }
846
847 SaveTag(data, Version() >= 6 ? SWF_TAG_DEFINE_FONT_INFO2 : SWF_TAG_DEFINE_FONT_INFO, sub_data.ByteSize());
848 data.Append(sub_data);
849 }
850 }
851
852 // Add another tag when there is a display name and/or copyright
853 if(f_display_name != 0 || f_copyright != 0) {
854 name = f_display_name;
855 if(name == 0) {
856 // default to the other name if it exists
857 name = f_font_name;
858 if(name == 0) {
859 // otherwise nothing
860 name = "";
861 }
862 }
863 l1 = strlen(name) + 1;
864 license = f_copyright;
865 if(license == 0) {
866 // make sure we don't crash with strlen() + Write()
867 license = "";
868 }
869 l2 = strlen(license) + 1;
870 SaveTag(data, SWF_TAG_DEFINE_FONT_NAME, 2 + l1 + l2);
871 SaveID(data);
872 data.Write(name, l1);
873 data.Write(license, l2);
874 }
875
876 return ErrorManager::ERROR_CODE_NONE;
877 }
878
879
880 const char * TagFont::g_font_language_name[FONT_LANGUAGE_max] = {
881 "LOCALE",
882 "LATIN",
883 "JAPANESE",
884 "KOREAN",
885 "SIMPLIFIED_CHINESE",
886 "TRADITIONAL_CHINESE"
887 };
888
889
890 /** \brief Defines the language number from its name.
891 *
892 * This function searches for a language by name and return the corresponding
893 * language code.
894 *
895 * \code
896 * LOCALE
897 * LATIN
898 * JAPANESE
899 * KOREAN
900 * SIMPLIFIED_CHINESE
901 * TRADITIONAL_CHINESE
902 * \endcode
903 *
904 * \param[in] language The name of the language this font is for
905 */
StringToLanguage(const char * language)906 TagFont::font_language_t TagFont::StringToLanguage(const char *language)
907 {
908 font_language_t idx;
909
910 for(idx = FONT_LANGUAGE_LOCALE; idx < FONT_LANGUAGE_max; idx = (font_language_t) ((int) idx + 1)) {
911 if(strcasecmp(g_font_language_name[(int) idx], language) == 0) {
912 return idx;
913 }
914 }
915
916 return FONT_LANGUAGE_UNKNOWN;
917 }
918
919
920 /** \brief Transform a language index to the corresponding name.
921 *
922 * This function transform a language index in a corresponding string.
923 *
924 * \param[in] language The language index to convert to a string.
925 *
926 * \return A constant string with the language name or "invalid".
927 */
LanguageToString(font_language_t language)928 const char *TagFont::LanguageToString(font_language_t language)
929 {
930 if(language < 0 || language >= FONT_LANGUAGE_max) {
931 return "invalid";
932 }
933
934 return g_font_language_name[language];
935 }
936
937
938 /** \brief Add a glyph to an embedded font.
939 *
940 * This function adds the ref shape as the character defined with the code
941 * defined in the name parameter.
942 *
943 * If you want to use the normal advance for a character, set the advance
944 * paramter to LONG_MIN. Wider or smaller characters need to use a
945 * specific value here.
946 *
947 * \param[in] name The name (unicode number) of the glyph
948 * \param[in] ref The corresponding shape
949 * \param[in] advance The number of twips to the next character
950 *
951 * \return An error code or ErrorManager::ERROR_CODE_NONE
952 */
AddGlyph(sswf_ucs4_t name,const TagBase * ref,long advance)953 ErrorManager::error_code_t TagFont::AddGlyph(sswf_ucs4_t name, const TagBase *ref, long advance)
954 {
955 font_glyph_t *glyph;
956 font_info_t info;
957
958 if(ref == 0 || strcmp(ref->Name(), "shape") != 0) {
959 return OnError(ErrorManager::ERROR_CODE_MISSING_SHAPE, "a glyph reference must be of type TagShape and it has to exist");
960 }
961
962 info.f_glyph = name;
963 if(FindGlyph(info)) {
964 // the user has the right to redefine the space as an
965 // empty character!
966 if(info.f_index != SSWF_FONT_SPACE_INDEX) {
967 return OnError(ErrorManager::ERROR_CODE_GLYPH_DEFINED_TWICE, "glyph 'u%ld' defined twice. Second instance ignored.", (long) name);
968 }
969 }
970
971 glyph = new font_glyph_t;
972 MemAttach(glyph, sizeof(font_glyph_t), "TagFont::AddGlyph() -- glyph of font");
973 glyph->f_name = name;
974 glyph->f_shape = dynamic_cast<const TagShape *>(ref);
975 glyph->f_advance = advance; // if LONG_MIN, use the default
976 glyph->f_in_use = false; // if true, must be saved
977
978 // Glyphs MUST be sorted for Macromedia players
979 // This allow for binary searches which are very effective
980 // and since we searched for the character with the FindGlyph()
981 // we already know where we need to insert this new glyph
982 f_glyphs.Insert(info.f_position, glyph);
983
984 return ErrorManager::ERROR_CODE_NONE;
985 }
986
987
988 /** \brief Add a special kern between two glyphs.
989 *
990 * Defines two glyphs and the space to add when they are encountered
991 * in that specific order in a word.
992 *
993 * For instance, a capital W followed by a lower case I need to be
994 * closer to each others than what the default advance of the W
995 * character implies.
996 *
997 * This advance is added to the normal advance (cumulative) this it
998 * often ends up being negative.
999 *
1000 * \todo
1001 * We would need to make sure that all kerns are distinct.
1002 *
1003 * \param[in] code0 The first glyph
1004 * \param[in] code1 The second glyph
1005 * \param[in] advance The advance to add when these two glyphs are found in a string
1006 */
AddKern(sswf_ucs4_t code0,sswf_ucs4_t code1,long advance)1007 void TagFont::AddKern(sswf_ucs4_t code0, sswf_ucs4_t code1, long advance)
1008 {
1009 font_kern_t *kern;
1010
1011 kern = new font_kern_t;
1012 MemAttach(kern, sizeof(font_kern_t), "TagFont::AddKern() -- font kern");
1013 kern->f_code[0] = code0;
1014 kern->f_code[1] = code1;
1015 kern->f_advance = advance;
1016 f_kerns.Set(-1, kern);
1017 }
1018
1019
1020 /** \brief Gets the name of the font.
1021 *
1022 * This function returns the current name of the font.
1023 *
1024 * \return The name of the font.
1025 */
FontName(void) const1026 const char *TagFont::FontName(void) const
1027 {
1028 return f_font_name;
1029 }
1030
1031
1032 /** \brief Retrieve the information (advance, etc.) of the specified glyph.
1033 *
1034 * For this function, define info.f_index with the glyph information
1035 * you want to retrieve. Call the function, and if the glyph exists,
1036 * the information for that glyph will be saved in the other fields
1037 * of the structure.
1038 *
1039 * It is an error to put a glyph index larger than the number of glyphs
1040 * available.
1041 *
1042 * Note that the index represents the index in the array of glyphs, not
1043 * the glyph Unicode number. Use the FindGlyph() function instead to
1044 * find a glyph using its glyph Unicode number.
1045 *
1046 * \param[in,out] info A glyph information structure with it's f_index
1047 * properly defined; returned with the other glyph
1048 * information
1049 *
1050 * \return An error code or ErrorManager::ERROR_CODE_NONE
1051 *
1052 * \sa sswf::TagFont::FindGlyph(font_info_t& info, bool mark_empty_in_use) const
1053 */
GlyphInfo(font_info_t & info) const1054 ErrorManager::error_code_t TagFont::GlyphInfo(font_info_t& info) const
1055 {
1056 font_glyph_t *glyph;
1057
1058 if(info.f_index >= static_cast<unsigned long>(f_glyphs.Count())) {
1059 return OnError(ErrorManager::ERROR_CODE_INVALID_GLYPH, "invalid index for a GlyphInfo request");
1060 }
1061
1062 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(info.f_index));
1063 info.f_glyph = glyph->f_name;
1064 info.f_saved_index = glyph->f_index;
1065 if(glyph->f_advance == LONG_MIN) {
1066 info.f_advance = f_default_advance;
1067 }
1068 else {
1069 info.f_advance = glyph->f_advance;
1070 }
1071 info.f_is_empty = glyph->f_shape->IsEmpty();
1072
1073 return ErrorManager::ERROR_CODE_NONE;
1074 }
1075
1076
1077 /** \brief Check whether the font has glyphs.
1078 *
1079 * This function returns true if the font defins one or more glyphs.
1080 * This can be used to know whether the font is an embedded or a
1081 * ssytem font.
1082 *
1083 * \return true when the font has glyphs
1084 */
HasGlyph(void) const1085 bool TagFont::HasGlyph(void) const
1086 {
1087 return f_glyphs.Count() != 0;
1088 }
1089
1090
1091 /** \brief Retrieve the information (advance, etc.) of the specified glyph.
1092 *
1093 * For this function, define info.f_glyph with the glyph Unicode number
1094 * you want to retrieve. Call the function, and if the glyph exists,
1095 * the information for that glyph will be saved in the other fields
1096 * of the structure.
1097 *
1098 * The glyph is searched with a binary search so it is fast.
1099 *
1100 * When the fonction does not find the glyph, it is not considered an
1101 * error. It returns the structure with f_index set to the location
1102 * where the glyph defined in f_glyph can be inserted (this is used
1103 * internally whenever a new glyph is added to the TagFont.)
1104 *
1105 * \param[in,out] info A glyph information structure with its f_glyph
1106 * properly defined; returned with the other glyph
1107 * information
1108 * \param[in] mark_empty_in_use Whether to mark empty glyphs in use or not
1109 *
1110 * \return true when the glyph was found
1111 *
1112 * \sa sswf::TagFont::GlyphInfo(font_info_t& info) const
1113 */
FindGlyph(font_info_t & info,bool mark_empty_in_use) const1114 bool TagFont::FindGlyph(font_info_t& info, bool mark_empty_in_use) const
1115 {
1116 font_glyph_t *glyph;
1117 int i, j, p;
1118 bool found;
1119
1120 // avoid warnings -- also crashes better if an error occurs
1121 glyph = 0;
1122
1123 /*
1124 * search the list of available glyphs and
1125 * determine the index which represents the character 'c'
1126 * note that the glyphs are always ordered
1127 */
1128 p = 0; // necessary for empty lists!
1129 found = false;
1130 j = f_glyphs.Count();
1131 if(j < 4) {
1132 /* ugly bubble search when not enough entries yet */
1133 while(j > 0) {
1134 j--;
1135 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(j));
1136 if(glyph->f_name == info.f_glyph) {
1137 p = j;
1138 found = true;
1139 break;
1140 }
1141 if(glyph->f_name < info.f_glyph) {
1142 // user glyph larger than any of the glyphs
1143 // in out list
1144 p = j + 1;
1145 break;
1146 }
1147 }
1148 }
1149 else {
1150 // binary search -- you can't go faster
1151 i = 0;
1152 while(i < j) {
1153 // get the center position of the current range
1154 p = i + (j - i) / 2;
1155 glyph = dynamic_cast<font_glyph_t *>(f_glyphs.Get(p));
1156 if(glyph->f_name == info.f_glyph) {
1157 found = true;
1158 break;
1159 }
1160 if(glyph->f_name < info.f_glyph) {
1161 p++;
1162 i = p;
1163 }
1164 else {
1165 j = p;
1166 }
1167 }
1168 }
1169
1170 if(found) {
1171 info.f_index = info.f_position = p;
1172 info.f_saved_index = glyph->f_index;
1173 if(glyph->f_advance == LONG_MIN) {
1174 info.f_advance = f_default_advance;
1175 }
1176 else {
1177 info.f_advance = glyph->f_advance;
1178 }
1179 info.f_is_empty = glyph->f_shape->IsEmpty();
1180 glyph->f_in_use = info.f_is_empty ? mark_empty_in_use : true;
1181 return true;
1182 }
1183
1184 if(info.f_glyph == ' ' && f_space_advance != LONG_MIN) {
1185 info.f_advance = f_space_advance;
1186 info.f_index = SSWF_FONT_SPACE_INDEX;
1187 info.f_position = p;
1188 info.f_saved_index = 0; // this one shouldn't be used
1189 info.f_is_empty = true;
1190 return true;
1191 }
1192
1193 // Ooops doesn't exist!
1194 // 'p' is the closest position (i.e. if we are adding a new
1195 // glyph that's where we want it!)
1196 info.f_index = (unsigned short) (info.f_position = p);
1197 info.f_saved_index = (unsigned short) info.f_glyph;
1198
1199 return false;
1200 }
1201
1202
1203
1204 /** \brief Returns the default ascent.
1205 *
1206 * This function returns the value representing the default ascent for
1207 * an SWF font. It is recommanded to use that value for your font
1208 * ascent if possible.
1209 *
1210 * \return The default ascent.
1211 */
DefaultAscent(void) const1212 long TagFont::DefaultAscent(void) const
1213 {
1214 return 750;
1215 }
1216
1217
1218 /** \brief Returns the default descent.
1219 *
1220 * This function returns the value representing the default descent for
1221 * an SWF font. It is recommanded to use that value for your font
1222 * descent if possible.
1223 *
1224 * \return The default descent.
1225 */
DefaultDescent(void) const1226 long TagFont::DefaultDescent(void) const
1227 {
1228 return 1024 - DefaultAscent();
1229 }
1230
1231
1232 /** \brief Returns the default leading height.
1233 *
1234 * This function returns the value representing the default leading
1235 * height for an SWF font. It is recommanded that you use that value
1236 * for your own fonts if possible.
1237 *
1238 * \return The default leading height
1239 */
DefaultLeadingHeight(void) const1240 long TagFont::DefaultLeadingHeight(void) const
1241 {
1242 return 0;
1243 }
1244
1245
1246 /** \brief Defines the name of the font.
1247 *
1248 * This function defines the name of the font.
1249 *
1250 * A font name starting with an underscore is taken as a "direct font name"
1251 * and requires V6.x. The currently supported names are:
1252 *
1253 * \code
1254 * _sans
1255 * _serif
1256 * _typewriter
1257 * 5F E3 82 B4 E3 82 B7 E3 83 83 E3 82 AF (Gothic—Japanese)
1258 * 5F E7 AD 89 E5 B9 85 (Tohaba, Gothic Mono—Japanese)
1259 * 5F E6 98 8E E6 9C 9D (Mincho—Japanese)
1260 * \endcode
1261 *
1262 * We use that mechanism rather than checking for special names so additional
1263 * names added by Macromedia/Adobe are automatically supported.
1264 *
1265 * This function overwrites the previous name if one existed.
1266 *
1267 * \param[in] font_name The new name of the font.
1268 */
SetName(const char * font_name)1269 void TagFont::SetName(const char *font_name)
1270 {
1271 MemFree(f_font_name);
1272 f_font_name = StrDup(font_name);
1273 }
1274
1275
1276 /** \brief Defines the display name of the font.
1277 *
1278 * This function can be used to define the display name of the font
1279 * opposed to the exact system name.
1280 *
1281 * For instance, a font can be called "ArialBld" and the display name
1282 * would then be "Arial Bold"
1283 *
1284 * \param[in] display_name The name of the font as we want to show it to an end user
1285 */
SetDisplayName(const char * display_name)1286 void TagFont::SetDisplayName(const char *display_name)
1287 {
1288 MemFree(f_display_name);
1289 f_display_name = StrDup(display_name);
1290 }
1291
1292
1293 /** \brief Defines a copyright or license for the font.
1294 *
1295 * This function defines a copyright string to save along the font.
1296 * This can include any information such as how the font can be
1297 * used.
1298 *
1299 * \param[in] copyright The copyright or license for the embedded font
1300 */
SetCopyright(const char * copyright)1301 void TagFont::SetCopyright(const char *copyright)
1302 {
1303 MemFree(f_copyright);
1304 f_copyright = StrDup(copyright);
1305 }
1306
1307
1308 /** \brief Set the font layout
1309 *
1310 * This function sets the ascent, descent and leading height of the font.
1311 *
1312 * The ascent represents the distance from the base to the top of the font.
1313 *
1314 * The descent represents the distance from the base to the bottom of the font.
1315 *
1316 * The leading height is added the ascent and the descent to move to the
1317 * next of text. The default is zero assuming that the ascent and descent
1318 * include enough space to separate two lines of text.
1319 *
1320 * \param[in] ascent The ascent of the font.
1321 * \param[in] descent The descent of the font.
1322 * \param[in] leading_height The leading height of the font.
1323 */
SetLayout(long ascent,long descent,long leading_height)1324 void TagFont::SetLayout(long ascent, long descent, long leading_height)
1325 {
1326 f_ascent = ascent;
1327 f_descent = descent;
1328 f_leading_height = leading_height;
1329 }
1330
1331
1332 /** \brief Set the default advance.
1333 *
1334 * This function can be used to define the default advance of
1335 * a glyph. This is useful to avoid having to define the
1336 * advance parameter each time a new glyph is added.
1337 *
1338 * By default this value is set to zero: not advance.
1339 *
1340 * \param[in] advance The amount to advance to go where the next glyph should be rendered
1341 */
SetDefaultAdvance(long advance)1342 void TagFont::SetDefaultAdvance(long advance)
1343 {
1344 f_default_advance = advance;
1345 }
1346
1347
1348 /** \brief Set the width of the regular space glyph.
1349 *
1350 * This function can be used to define the width of the space
1351 * glyph. This is the glyph with Unicde number 0x20 (32).
1352 * That glyph is never included in the final font.
1353 *
1354 * \param[in] advance The size of one space character
1355 */
SetSpaceAdvance(long advance)1356 void TagFont::SetSpaceAdvance(long advance)
1357 {
1358 f_space_advance = advance;
1359 }
1360
1361
1362 /** \brief Set the type of font.
1363 *
1364 * The type of font to use with the TagFont.
1365 *
1366 * This applies to SWF version 5 and earlier. Since version 6,
1367 * the font type is automatically Unicode, which encompass all
1368 * the other possible fonts.
1369 *
1370 * The available types are:
1371 *
1372 * \code
1373 * TagFont::FONT_TYPE_BEST
1374 * TagFont::FONT_TYPE_ASCII
1375 * TagFont::FONT_TYPE_UNICODE
1376 * TagFont::FONT_TYPE_SHIFTJIS
1377 * \endcode
1378 *
1379 * \param[in] type The font type.
1380 */
SetType(font_type_t type)1381 void TagFont::SetType(font_type_t type)
1382 {
1383 f_type = type;
1384 }
1385
1386
1387 /** \brief Set the language corresponding to this font.
1388 *
1389 * This function sets the language corresponding to this font.
1390 * This is not very useful since version 6 since all fonts use
1391 * Unicode which include all possible languages today (and tomorrow
1392 * once we have Klingon in Unicode.)
1393 *
1394 * You can use the TagFont::StringToLanguage(const char *language)
1395 * to transform a string to a language code as required by this
1396 * function.
1397 *
1398 * The available languages are defined here:
1399 *
1400 * \code
1401 * FONT_LANGUAGE_UNKNOWN
1402 * FONT_LANGUAGE_LOCALE
1403 * FONT_LANGUAGE_LATIN
1404 * FONT_LANGUAGE_JAPANESE
1405 * FONT_LANGUAGE_KOREAN
1406 * FONT_LANGUAGE_SIMPLIFIED_CHINESE
1407 * FONT_LANGUAGE_TRADITIONAL_CHINESE
1408 * \endcode
1409 *
1410 * Unknown is used to mark a font as language-less.
1411 *
1412 * \param[in] language The language code
1413 *
1414 * \sa sswf::TagFont::StringToLanguage(const char *language)
1415 */
SetLanguage(font_language_t language)1416 void TagFont::SetLanguage(font_language_t language)
1417 {
1418 f_language = language < 0 || language >= FONT_LANGUAGE_max
1419 ? FONT_LANGUAGE_UNKNOWN : language;
1420 }
1421
1422
1423 /** \brief Mark the font as representing a bold style.
1424 *
1425 * Set this flag if your font represents a bold version of the
1426 * font. If you want to use a system font, use this flag so
1427 * the bold version of the font is used.
1428 *
1429 * \param[in] bold true if the font is bold
1430 */
SetBold(bool bold)1431 void TagFont::SetBold(bool bold)
1432 {
1433 f_bold = bold;
1434 }
1435
1436
1437 /** \brief Mark the font as representing an italic style.
1438 *
1439 * Set this flag if your font represents an italic version of the
1440 * font. If you want to use a system font, use this flag so
1441 * the italic version of the font is used.
1442 *
1443 * \param[in] italic true if the font is italic
1444 */
SetItalic(bool italic)1445 void TagFont::SetItalic(bool italic)
1446 {
1447 f_italic = italic;
1448 }
1449
1450
1451 /** \brief Mark the font as being a small text font.
1452 *
1453 * Set this flag to true as a hint to the Flash Player that the font
1454 * will be used to draw small text.
1455 *
1456 * \param[in] small_text true to mark the font as used for small text
1457 */
SetSmallText(bool small_text)1458 void TagFont::SetSmallText(bool small_text)
1459 {
1460 f_small_text = small_text;
1461 }
1462
1463
1464 /** \brief Define the thickness of the font.
1465 *
1466 * This value is set to Unknown by default meaning that the
1467 * thickness is not specified.
1468 *
1469 * It can be set to Thin, Medium or Thick:
1470 *
1471 * \code
1472 * FONT_THICKNESS_THIN
1473 * FONT_THICKNESS_MEDIUM
1474 * FONT_THICKNESS_THICK
1475 * \endcode
1476 *
1477 * The thickness will not be saved in the font if the EM square
1478 * is not also marked as large and all glyphs got an align zone
1479 * defined.
1480 *
1481 * \param[in] thickness The new thickness
1482 *
1483 * \sa TagFont::SetEMSize(font_em_size_t font_em_size)
1484 */
SetThickness(font_thickness_t thickness)1485 void TagFont::SetThickness(font_thickness_t thickness)
1486 {
1487 f_thickness = thickness;
1488 }
1489
1490
1491 /** \brief Define the size of the EM square of the font.
1492 *
1493 * This function is used to define the size of the EM square
1494 * used to draw the glyphs. This could be done automatically
1495 * by checking the size of the glyphs, but that's not done
1496 * yet and it would not automatically work in all cases.
1497 *
1498 * The EM square can be small or large:
1499 *
1500 * \code
1501 * FONT_EM_SMALL
1502 * FONT_EM_LARGE
1503 * \endcode
1504 *
1505 * \param[in] font_em_size The new size of the EM square
1506 */
SetEMSize(font_em_size_t font_em_size)1507 void TagFont::SetEMSize(font_em_size_t font_em_size)
1508 {
1509 f_font_em_size = font_em_size;
1510 }
1511
1512
1513 /** \brief Mark the font as a Unicode font.
1514 *
1515 * This flag is ignored in SWF version 6 and over. In that case, all fonts must
1516 * be defined an Unicode (wide).
1517 *
1518 * Otherwise, use this flag to mark whether you want to use the 256 glyphs
1519 * font or the 65536 glyphs font.
1520 *
1521 * \param[in] wide true to make the font Unicode
1522 */
SetWide(bool wide)1523 void TagFont::SetWide(bool wide)
1524 {
1525 f_wide = wide;
1526 }
1527
1528
1529
1530 /** \brief Set which glyphs are used.
1531 *
1532 * This function can be used to define the glyphs that other tags use.
1533 *
1534 * \param[in] used_glyphs A string representing the glyphs in use or NULL
1535 * \param[in] mark_empty_in_use Whether empty glyphs should be marked in use
1536 *
1537 * \return An error code or ErrorManager::ERROR_CODE_NONE
1538 *
1539 * \sa TagFont::SetUsedGlyphs(const sswf_ucs4_t *used_glyphs, bool mark_empty_in_use)
1540 */
SetUsedGlyphs(const char * used_glyphs,bool mark_empty_in_use)1541 ErrorManager::error_code_t TagFont::SetUsedGlyphs(const char *used_glyphs, bool mark_empty_in_use)
1542 {
1543 ErrorManager::error_code_t ec;
1544 sswf_ucs4_t *wc_used_glyphs, *d;
1545 size_t l, sz;
1546
1547 if(used_glyphs == 0 || (used_glyphs[0] == '*' && used_glyphs[1] == '\0')) {
1548 return SetUsedGlyphs(static_cast<const sswf_ucs4_t *>(0), mark_empty_in_use);
1549 }
1550 l = strlen(used_glyphs);
1551 sz = l * sizeof(sswf_ucs4_t);
1552 wc_used_glyphs = new sswf_ucs4_t[l + 1];
1553 d = wc_used_glyphs;
1554 mbtowc(used_glyphs, l, d, sz);
1555 *d = (sswf_ucs4_t) '\0'; // mbtowc() doesn't terminate the strings
1556 ec = SetUsedGlyphs(wc_used_glyphs, true);
1557 delete [] wc_used_glyphs;
1558
1559 return ec;
1560 }
1561
1562
1563 /** \brief Set which glyphs are used.
1564 *
1565 * This function can be used to define the glyphs that other tags use.
1566 *
1567 * This is the official function which accepts a Unicode string as input.
1568 *
1569 * The special strings "*" and NULL can be used in the used_glyphs parameter
1570 * to mark all the glyphs in used at once.
1571 *
1572 * The string can otherwise be defined with a range defined by two glyphs
1573 * separated by a dash (-). For instance, to include all the ASCII upper case
1574 * characters, one can use "A-Z". Several ranges can be included in the same
1575 * string and the dash (-) can be included at the very beginning or the end
1576 * of the string to be included as a glyph in use. The code accepts ranges
1577 * which are written backward; so "9-0" is taken as "0-9".
1578 *
1579 * \param[in] used_glyphs A string representing the glyphs in use or NULL
1580 * \param[in] mark_empty_in_use Whether empty glyphs should be marked in use
1581 *
1582 * \return An error code or ErrorManager::ERROR_CODE_NONE
1583 *
1584 * \sa TagFont::SetUsedGlyphs(const char *used_glyphs, bool mark_empty_in_use)
1585 */
SetUsedGlyphs(const sswf_ucs4_t * used_glyphs,bool mark_empty_in_use)1586 ErrorManager::error_code_t TagFont::SetUsedGlyphs(const sswf_ucs4_t *used_glyphs, bool mark_empty_in_use)
1587 {
1588 font_info_t info;
1589 int a, b, max, idx;
1590 ErrorManager::error_code_t err_code;
1591
1592 // if no glyph, just forget it altogether in this case
1593 max = f_glyphs.Count();
1594 if(max == 0) {
1595 return ErrorManager::ERROR_CODE_NONE;
1596 }
1597
1598 if(used_glyphs == 0 || (used_glyphs[0] == '*' && used_glyphs[1] == '\0')) {
1599 // all the characters need to be marked in use
1600 for(idx = 0; idx < max; idx++) {
1601 dynamic_cast<font_glyph_t *>(f_glyphs.Get(idx))->f_in_use = true;
1602 }
1603 return ErrorManager::ERROR_CODE_NONE;
1604 }
1605
1606 err_code = ErrorManager::ERROR_CODE_NONE;
1607
1608 while(*used_glyphs != '\0') {
1609 a = used_glyphs[0];
1610 if(used_glyphs[1] == '-' && used_glyphs[2] != '\0') {
1611 b = used_glyphs[2];
1612 if(a > b) {
1613 b = a;
1614 a = used_glyphs[2];
1615 }
1616 used_glyphs += 3;
1617 }
1618 else {
1619 b = a;
1620 used_glyphs++;
1621 }
1622 while(a <= b) {
1623 info.f_glyph = a;
1624 if(!FindGlyph(info, mark_empty_in_use)) {
1625 char buf[16];
1626 err_code = OnError(ErrorManager::ERROR_CODE_NO_SUCH_GLYPH, "TagEditText: the character %s (%d) does not exist in the font named \"%s\". (2)\n", wcname(a, buf), a, f_font_name);
1627 }
1628 a++;
1629 }
1630 }
1631
1632 return err_code;
1633 }
1634
1635
1636 /** \brief Defines whether the font is used by a TagEditText box
1637 *
1638 * A TagEditText cannot use a DefineFont. Thus it is important to know whether the
1639 * font will be used by an Edit Text box. At times it is not possible to infer such
1640 * a thing until the movie runs. For this reason, this flag is included to force the
1641 * font to be saved in DefineFont2 or DefineFont3.
1642 *
1643 * \param[in] used True if the font is used in a TagEditText
1644 */
SetUsedByEditText(bool used)1645 void TagFont::SetUsedByEditText(bool used)
1646 {
1647 f_used_by_edit_text = used;
1648 }
1649
1650
1651
1652
1653
1654
1655
1656 /* The following options fold the documentation; use 'zi' to turn on and off
1657 *
1658 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
1659 */
1660