暂无描述

OutlineComposite.php 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. /**
  3. * @package php-font-lib
  4. * @link https://github.com/PhenX/php-font-lib
  5. * @author Fabien Ménager <fabien.menager@gmail.com>
  6. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  7. * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
  8. */
  9. namespace FontLib\Glyph;
  10. /**
  11. * Composite glyph outline
  12. *
  13. * @package php-font-lib
  14. */
  15. class OutlineComposite extends Outline {
  16. const ARG_1_AND_2_ARE_WORDS = 0x0001;
  17. const ARGS_ARE_XY_VALUES = 0x0002;
  18. const ROUND_XY_TO_GRID = 0x0004;
  19. const WE_HAVE_A_SCALE = 0x0008;
  20. const MORE_COMPONENTS = 0x0020;
  21. const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
  22. const WE_HAVE_A_TWO_BY_TWO = 0x0080;
  23. const WE_HAVE_INSTRUCTIONS = 0x0100;
  24. const USE_MY_METRICS = 0x0200;
  25. const OVERLAP_COMPOUND = 0x0400;
  26. /**
  27. * @var OutlineComponent[]
  28. */
  29. public $components = array();
  30. function getGlyphIDs() {
  31. if (empty($this->components)) {
  32. $this->parseData();
  33. }
  34. $glyphIDs = array();
  35. foreach ($this->components as $_component) {
  36. $glyphIDs[] = $_component->glyphIndex;
  37. $_glyph = $this->table->data[$_component->glyphIndex];
  38. if ($_glyph !== $this) {
  39. $glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
  40. }
  41. }
  42. return $glyphIDs;
  43. }
  44. /*function parse() {
  45. //$this->parseData();
  46. }*/
  47. function parseData() {
  48. parent::parseData();
  49. $font = $this->getFont();
  50. do {
  51. $flags = $font->readUInt16();
  52. $glyphIndex = $font->readUInt16();
  53. $a = 1.0;
  54. $b = 0.0;
  55. $c = 0.0;
  56. $d = 1.0;
  57. $e = 0.0;
  58. $f = 0.0;
  59. $point_compound = null;
  60. $point_component = null;
  61. $instructions = null;
  62. if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
  63. if ($flags & self::ARGS_ARE_XY_VALUES) {
  64. $e = $font->readInt16();
  65. $f = $font->readInt16();
  66. }
  67. else {
  68. $point_compound = $font->readUInt16();
  69. $point_component = $font->readUInt16();
  70. }
  71. }
  72. else {
  73. if ($flags & self::ARGS_ARE_XY_VALUES) {
  74. $e = $font->readInt8();
  75. $f = $font->readInt8();
  76. }
  77. else {
  78. $point_compound = $font->readUInt8();
  79. $point_component = $font->readUInt8();
  80. }
  81. }
  82. if ($flags & self::WE_HAVE_A_SCALE) {
  83. $a = $d = $font->readInt16();
  84. }
  85. elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
  86. $a = $font->readInt16();
  87. $d = $font->readInt16();
  88. }
  89. elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
  90. $a = $font->readInt16();
  91. $b = $font->readInt16();
  92. $c = $font->readInt16();
  93. $d = $font->readInt16();
  94. }
  95. //if ($flags & self::WE_HAVE_INSTRUCTIONS) {
  96. //
  97. //}
  98. $component = new OutlineComponent();
  99. $component->flags = $flags;
  100. $component->glyphIndex = $glyphIndex;
  101. $component->a = $a;
  102. $component->b = $b;
  103. $component->c = $c;
  104. $component->d = $d;
  105. $component->e = $e;
  106. $component->f = $f;
  107. $component->point_compound = $point_compound;
  108. $component->point_component = $point_component;
  109. $component->instructions = $instructions;
  110. $this->components[] = $component;
  111. } while ($flags & self::MORE_COMPONENTS);
  112. }
  113. function encode() {
  114. $font = $this->getFont();
  115. $gids = $font->getSubset();
  116. $size = $font->writeInt16(-1);
  117. $size += $font->writeFWord($this->xMin);
  118. $size += $font->writeFWord($this->yMin);
  119. $size += $font->writeFWord($this->xMax);
  120. $size += $font->writeFWord($this->yMax);
  121. foreach ($this->components as $_i => $_component) {
  122. $flags = 0;
  123. if ($_component->point_component === null && $_component->point_compound === null) {
  124. $flags |= self::ARGS_ARE_XY_VALUES;
  125. if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
  126. $flags |= self::ARG_1_AND_2_ARE_WORDS;
  127. }
  128. }
  129. elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
  130. $flags |= self::ARG_1_AND_2_ARE_WORDS;
  131. }
  132. if ($_component->b == 0 && $_component->c == 0) {
  133. if ($_component->a == $_component->d) {
  134. if ($_component->a != 1.0) {
  135. $flags |= self::WE_HAVE_A_SCALE;
  136. }
  137. }
  138. else {
  139. $flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
  140. }
  141. }
  142. else {
  143. $flags |= self::WE_HAVE_A_TWO_BY_TWO;
  144. }
  145. if ($_i < count($this->components) - 1) {
  146. $flags |= self::MORE_COMPONENTS;
  147. }
  148. $size += $font->writeUInt16($flags);
  149. $new_gid = array_search($_component->glyphIndex, $gids);
  150. $size += $font->writeUInt16($new_gid);
  151. if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
  152. if ($flags & self::ARGS_ARE_XY_VALUES) {
  153. $size += $font->writeInt16($_component->e);
  154. $size += $font->writeInt16($_component->f);
  155. }
  156. else {
  157. $size += $font->writeUInt16($_component->point_compound);
  158. $size += $font->writeUInt16($_component->point_component);
  159. }
  160. }
  161. else {
  162. if ($flags & self::ARGS_ARE_XY_VALUES) {
  163. $size += $font->writeInt8($_component->e);
  164. $size += $font->writeInt8($_component->f);
  165. }
  166. else {
  167. $size += $font->writeUInt8($_component->point_compound);
  168. $size += $font->writeUInt8($_component->point_component);
  169. }
  170. }
  171. if ($flags & self::WE_HAVE_A_SCALE) {
  172. $size += $font->writeInt16($_component->a);
  173. }
  174. elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
  175. $size += $font->writeInt16($_component->a);
  176. $size += $font->writeInt16($_component->d);
  177. }
  178. elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
  179. $size += $font->writeInt16($_component->a);
  180. $size += $font->writeInt16($_component->b);
  181. $size += $font->writeInt16($_component->c);
  182. $size += $font->writeInt16($_component->d);
  183. }
  184. }
  185. return $size;
  186. }
  187. public function getSVGContours() {
  188. $contours = array();
  189. /** @var \FontLib\Table\Type\glyf $glyph_data */
  190. $glyph_data = $this->getFont()->getTableObject("glyf");
  191. /** @var Outline[] $glyphs */
  192. $glyphs = $glyph_data->data;
  193. foreach ($this->components as $component) {
  194. $_glyph = $glyphs[$component->glyphIndex];
  195. if ($_glyph !== $this) {
  196. $contours[] = array(
  197. "contours" => $_glyph->getSVGContours(),
  198. "transform" => $component->getMatrix(),
  199. );
  200. }
  201. }
  202. return $contours;
  203. }
  204. }