1 /* 2 * $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ 3 * 4 * Typecast - The Font Development Environment 5 * 6 * Copyright (c) 2004-2007 David Schweinsberg 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package jogamp.graph.font.typecast.t2; 22 23 import java.util.ArrayList; 24 25 import jogamp.graph.font.typecast.ot.Point; 26 import jogamp.graph.font.typecast.ot.table.CharstringType2; 27 28 29 30 /** 31 * Type 2 Charstring Interpreter. Operator descriptions are quoted from 32 * Adobe's Type 2 Charstring Format document -- 5117.Type2.pdf. 33 * @author <a href="mailto:davidsch@dev.java.net">David Schweinsberg</a> 34 * @version $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ 35 */ 36 public class T2Interpreter { 37 38 private static final int ARGUMENT_STACK_LIMIT = 48; 39 private static final int SUBR_STACK_LIMIT = 10; 40 private static final int TRANSIENT_ARRAY_ELEMENT_COUNT = 32; 41 42 private final Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT]; 43 private int _argStackIndex = 0; 44 private final int[] _subrStack = new int[SUBR_STACK_LIMIT]; 45 private int _subrStackIndex = 0; 46 private final Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; 47 48 private ArrayList<Point> _points; 49 50 /** Creates a new instance of T2Interpreter */ T2Interpreter()51 public T2Interpreter() { 52 } 53 54 /** 55 * Moves the current point to a position at the relative coordinates 56 * (dx1, dy1). 57 */ _rmoveto()58 private void _rmoveto() { 59 final int dy1 = popArg().intValue(); 60 final int dx1 = popArg().intValue(); 61 clearArg(); 62 final Point lastPoint = getLastPoint(); 63 moveTo(lastPoint.x + dx1, lastPoint.y + dy1); 64 } 65 66 /** 67 * Moves the current point dx1 units in the horizontal direction. 68 */ _hmoveto()69 private void _hmoveto() { 70 final int dx1 = popArg().intValue(); 71 clearArg(); 72 final Point lastPoint = getLastPoint(); 73 moveTo(lastPoint.x + dx1, lastPoint.y); 74 } 75 76 /** 77 * Moves the current point dy1 units in the vertical direction. 78 */ _vmoveto()79 private void _vmoveto() { 80 final int dy1 = popArg().intValue(); 81 clearArg(); 82 final Point lastPoint = getLastPoint(); 83 moveTo(lastPoint.x, lastPoint.y + dy1); 84 } 85 86 /** 87 * Appends a line from the current point to a position at the 88 * relative coordinates dxa, dya. Additional rlineto operations are 89 * performed for all subsequent argument pairs. The number of 90 * lines is determined from the number of arguments on the stack. 91 */ _rlineto()92 private void _rlineto() { 93 final int count = getArgCount() / 2; 94 final int[] dx = new int[count]; 95 final int[] dy = new int[count]; 96 for (int i = 0; i < count; ++i) { 97 dy[count - i - 1] = popArg().intValue(); 98 dx[count - i - 1] = popArg().intValue(); 99 } 100 for (int i = 0; i < count; ++i) { 101 final Point lastPoint = getLastPoint(); 102 lineTo(lastPoint.x + dx[i], lastPoint.y + dy[i]); 103 } 104 clearArg(); 105 } 106 107 /** 108 * Appends a horizontal line of length dx1 to the current point. 109 * With an odd number of arguments, subsequent argument pairs 110 * are interpreted as alternating values of dy and dx, for which 111 * additional lineto operators draw alternating vertical and 112 * horizontal lines. With an even number of arguments, the 113 * arguments are interpreted as alternating horizontal and 114 * vertical lines. The number of lines is determined from the 115 * number of arguments on the stack. 116 */ _hlineto()117 private void _hlineto() { 118 final int count = getArgCount(); 119 final Number[] nums = new Number[count]; 120 for (int i = 0; i < count; ++i) { 121 nums[count - i - 1] = popArg(); 122 } 123 for (int i = 0; i < count; ++i) { 124 final Point lastPoint = getLastPoint(); 125 if (i % 2 == 0) { 126 lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); 127 } else { 128 lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); 129 } 130 } 131 clearArg(); 132 } 133 134 /** 135 * Appends a vertical line of length dy1 to the current point. With 136 * an odd number of arguments, subsequent argument pairs are 137 * interpreted as alternating values of dx and dy, for which 138 * additional lineto operators draw alternating horizontal and 139 * vertical lines. With an even number of arguments, the 140 * arguments are interpreted as alternating vertical and 141 * horizontal lines. The number of lines is determined from the 142 * number of arguments on the stack. 143 */ _vlineto()144 private void _vlineto() { 145 final int count = getArgCount(); 146 final Number[] nums = new Number[count]; 147 for (int i = 0; i < count; ++i) { 148 nums[count - i - 1] = popArg(); 149 } 150 for (int i = 0; i < count; ++i) { 151 final Point lastPoint = getLastPoint(); 152 if (i % 2 == 0) { 153 lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); 154 } else { 155 lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); 156 } 157 } 158 clearArg(); 159 } 160 161 /** 162 * Appends a Bezier curve, defined by dxa...dyc, to the current 163 * point. For each subsequent set of six arguments, an additional 164 * curve is appended to the current point. The number of curve 165 * segments is determined from the number of arguments on the 166 * number stack and is limited only by the size of the number 167 * stack. 168 */ _rrcurveto()169 private void _rrcurveto() { 170 final int count = getArgCount() / 6; 171 final int[] dxa = new int[count]; 172 final int[] dya = new int[count]; 173 final int[] dxb = new int[count]; 174 final int[] dyb = new int[count]; 175 final int[] dxc = new int[count]; 176 final int[] dyc = new int[count]; 177 for (int i = 0; i < count; ++i) { 178 dyc[count - i - 1] = popArg().intValue(); 179 dxc[count - i - 1] = popArg().intValue(); 180 dyb[count - i - 1] = popArg().intValue(); 181 dxb[count - i - 1] = popArg().intValue(); 182 dya[count - i - 1] = popArg().intValue(); 183 dxa[count - i - 1] = popArg().intValue(); 184 } 185 for (int i = 0; i < count; ++i) { 186 final Point lastPoint = getLastPoint(); 187 final int xa = lastPoint.x + dxa[i]; 188 final int ya = lastPoint.y + dya[i]; 189 final int xb = xa + dxb[i]; 190 final int yb = ya + dyb[i]; 191 final int xc = xb + dxc[i]; 192 final int yc = yb + dyc[i]; 193 curveTo(xa, ya, xb, yb, xc, yc); 194 } 195 clearArg(); 196 } 197 198 /** 199 * Appends one or more Bezier curves, as described by the 200 * dxa...dxc set of arguments, to the current point. For each curve, 201 * if there are 4 arguments, the curve starts and ends horizontal. 202 * The first curve need not start horizontal (the odd argument 203 * case). Note the argument order for the odd argument case. 204 */ _hhcurveto()205 private void _hhcurveto() { 206 final int count = getArgCount() / 4; 207 int dy1 = 0; 208 final int[] dxa = new int[count]; 209 final int[] dxb = new int[count]; 210 final int[] dyb = new int[count]; 211 final int[] dxc = new int[count]; 212 for (int i = 0; i < count; ++i) { 213 dxc[count - i - 1] = popArg().intValue(); 214 dyb[count - i - 1] = popArg().intValue(); 215 dxb[count - i - 1] = popArg().intValue(); 216 dxa[count - i - 1] = popArg().intValue(); 217 } 218 if (getArgCount() == 1) { 219 dy1 = popArg().intValue(); 220 } 221 for (int i = 0; i < count; ++i) { 222 final Point lastPoint = getLastPoint(); 223 final int xa = lastPoint.x + dxa[i]; 224 final int ya = lastPoint.y + (i == 0 ? dy1 : 0); 225 final int xb = xa + dxb[i]; 226 final int yb = ya + dyb[i]; 227 final int xc = xb + dxc[i]; 228 final int yc = yb; 229 curveTo(xa, ya, xb, yb, xc, yc); 230 } 231 clearArg(); 232 } 233 234 /** 235 * Appends one or more Bezier curves to the current point. The 236 * tangent for the first Bezier must be horizontal, and the second 237 * must be vertical (except as noted below). 238 * If there is a multiple of four arguments, the curve starts 239 * horizontal and ends vertical. Note that the curves alternate 240 * between start horizontal, end vertical, and start vertical, and 241 * end horizontal. The last curve (the odd argument case) need not 242 * end horizontal/vertical. 243 */ _hvcurveto()244 private void _hvcurveto() { 245 if (getArgCount() % 8 <= 1) { 246 final int count = getArgCount() / 8; 247 final int[] dxa = new int[count]; 248 final int[] dxb = new int[count]; 249 final int[] dyb = new int[count]; 250 final int[] dyc = new int[count]; 251 final int[] dyd = new int[count]; 252 final int[] dxe = new int[count]; 253 final int[] dye = new int[count]; 254 final int[] dxf = new int[count]; 255 int dyf = 0; 256 if (getArgCount() % 8 == 1) { 257 dyf = popArg().intValue(); 258 } 259 for (int i = 0; i < count; ++i) { 260 dxf[count - i - 1] = popArg().intValue(); 261 dye[count - i - 1] = popArg().intValue(); 262 dxe[count - i - 1] = popArg().intValue(); 263 dyd[count - i - 1] = popArg().intValue(); 264 dyc[count - i - 1] = popArg().intValue(); 265 dyb[count - i - 1] = popArg().intValue(); 266 dxb[count - i - 1] = popArg().intValue(); 267 dxa[count - i - 1] = popArg().intValue(); 268 } 269 for (int i = 0; i < count; ++i) { 270 final Point lastPoint = getLastPoint(); 271 final int xa = lastPoint.x + dxa[i]; 272 final int ya = lastPoint.y; 273 final int xb = xa + dxb[i]; 274 final int yb = ya + dyb[i]; 275 final int xc = xb; 276 final int yc = yb + dyc[i]; 277 final int xd = xc; 278 final int yd = yc + dyd[i]; 279 final int xe = xd + dxe[i]; 280 final int ye = yd + dye[i]; 281 final int xf = xe + dxf[i]; 282 final int yf = ye + dyf; 283 curveTo(xa, ya, xb, yb, xc, yc); 284 curveTo(xd, yd, xe, ye, xf, yf); 285 } 286 } else { 287 final int count = getArgCount() / 8; 288 final int[] dya = new int[count]; 289 final int[] dxb = new int[count]; 290 final int[] dyb = new int[count]; 291 final int[] dxc = new int[count]; 292 final int[] dxd = new int[count]; 293 final int[] dxe = new int[count]; 294 final int[] dye = new int[count]; 295 final int[] dyf = new int[count]; 296 int dxf = 0; 297 if (getArgCount() % 8 == 1) { 298 dxf = popArg().intValue(); 299 } 300 for (int i = 0; i < count; ++i) { 301 dyf[count - i - 1] = popArg().intValue(); 302 dye[count - i - 1] = popArg().intValue(); 303 dxe[count - i - 1] = popArg().intValue(); 304 dxd[count - i - 1] = popArg().intValue(); 305 dxc[count - i - 1] = popArg().intValue(); 306 dyb[count - i - 1] = popArg().intValue(); 307 dxb[count - i - 1] = popArg().intValue(); 308 dya[count - i - 1] = popArg().intValue(); 309 } 310 /** 311 * Not using the 'popped' arguments, 312 * hence simply pop them from stack! 313 * 314 final int dy3 = popArg().intValue(); 315 final int dy2 = popArg().intValue(); 316 final int dx2 = popArg().intValue(); 317 final int dx1 = popArg().intValue(); 318 */ 319 popArg(); 320 popArg(); 321 popArg(); 322 popArg(); 323 324 for (int i = 0; i < count; ++i) { 325 final Point lastPoint = getLastPoint(); 326 final int xa = lastPoint.x; 327 final int ya = lastPoint.y + dya[i]; 328 final int xb = xa + dxb[i]; 329 final int yb = ya + dyb[i]; 330 final int xc = xb + dxc[i]; 331 final int yc = yb; 332 final int xd = xc + dxd[i]; 333 final int yd = yc; 334 final int xe = xd + dxe[i]; 335 final int ye = yd + dye[i]; 336 final int xf = xe + dxf; 337 final int yf = ye + dyf[i]; 338 curveTo(xa, ya, xb, yb, xc, yc); 339 curveTo(xd, yd, xe, ye, xf, yf); 340 341 // What on earth do we do with dx1, dx2, dy2 and dy3? 342 } 343 } 344 clearArg(); 345 } 346 347 /** 348 * Is equivalent to one rrcurveto for each set of six arguments 349 * dxa...dyc, followed by exactly one rlineto using the dxd, dyd 350 * arguments. The number of curves is determined from the count 351 * on the argument stack. 352 */ _rcurveline()353 private void _rcurveline() { 354 final int count = (getArgCount() - 2) / 6; 355 final int[] dxa = new int[count]; 356 final int[] dya = new int[count]; 357 final int[] dxb = new int[count]; 358 final int[] dyb = new int[count]; 359 final int[] dxc = new int[count]; 360 final int[] dyc = new int[count]; 361 final int dyd = popArg().intValue(); 362 final int dxd = popArg().intValue(); 363 for (int i = 0; i < count; ++i) { 364 dyc[count - i - 1] = popArg().intValue(); 365 dxc[count - i - 1] = popArg().intValue(); 366 dyb[count - i - 1] = popArg().intValue(); 367 dxb[count - i - 1] = popArg().intValue(); 368 dya[count - i - 1] = popArg().intValue(); 369 dxa[count - i - 1] = popArg().intValue(); 370 } 371 int xc = 0; 372 int yc = 0; 373 for (int i = 0; i < count; ++i) { 374 final Point lastPoint = getLastPoint(); 375 final int xa = lastPoint.x + dxa[i]; 376 final int ya = lastPoint.y + dya[i]; 377 final int xb = xa + dxb[i]; 378 final int yb = ya + dyb[i]; 379 xc = xb + dxc[i]; 380 yc = yb + dyc[i]; 381 curveTo(xa, ya, xb, yb, xc, yc); 382 } 383 lineTo(xc + dxd, yc + dyd); 384 clearArg(); 385 } 386 387 /** 388 * Is equivalent to one rlineto for each pair of arguments beyond 389 * the six arguments dxb...dyd needed for the one rrcurveto 390 * command. The number of lines is determined from the count of 391 * items on the argument stack. 392 */ _rlinecurve()393 private void _rlinecurve() { 394 final int count = (getArgCount() - 6) / 2; 395 final int[] dxa = new int[count]; 396 final int[] dya = new int[count]; 397 final int dyd = popArg().intValue(); 398 final int dxd = popArg().intValue(); 399 final int dyc = popArg().intValue(); 400 final int dxc = popArg().intValue(); 401 final int dyb = popArg().intValue(); 402 final int dxb = popArg().intValue(); 403 for (int i = 0; i < count; ++i) { 404 dya[count - i - 1] = popArg().intValue(); 405 dxa[count - i - 1] = popArg().intValue(); 406 } 407 int xa = 0; 408 int ya = 0; 409 for (int i = 0; i < count; ++i) { 410 final Point lastPoint = getLastPoint(); 411 xa = lastPoint.x + dxa[i]; 412 ya = lastPoint.y + dya[i]; 413 lineTo(xa, ya); 414 } 415 final int xb = xa + dxb; 416 final int yb = ya + dyb; 417 final int xc = xb + dxc; 418 final int yc = yb + dyc; 419 final int xd = xc + dxd; 420 final int yd = yc + dyd; 421 curveTo(xb, yb, xc, yc, xd, yd); 422 clearArg(); 423 } 424 425 /** 426 * Appends one or more Bezier curves to the current point, where 427 * the first tangent is vertical and the second tangent is horizontal. 428 * This command is the complement of hvcurveto; see the 429 * description of hvcurveto for more information. 430 */ _vhcurveto()431 private void _vhcurveto() { 432 if (getArgCount() % 8 <= 1) { 433 final int count = getArgCount() / 8; 434 final int[] dya = new int[count]; 435 final int[] dxb = new int[count]; 436 final int[] dyb = new int[count]; 437 final int[] dxc = new int[count]; 438 final int[] dxd = new int[count]; 439 final int[] dxe = new int[count]; 440 final int[] dye = new int[count]; 441 final int[] dyf = new int[count]; 442 int dxf = 0; 443 if (getArgCount() % 8 == 1) { 444 dxf = popArg().intValue(); 445 } 446 for (int i = 0; i < count; ++i) { 447 dyf[count - i - 1] = popArg().intValue(); 448 dye[count - i - 1] = popArg().intValue(); 449 dxe[count - i - 1] = popArg().intValue(); 450 dxd[count - i - 1] = popArg().intValue(); 451 dxc[count - i - 1] = popArg().intValue(); 452 dyb[count - i - 1] = popArg().intValue(); 453 dxb[count - i - 1] = popArg().intValue(); 454 dya[count - i - 1] = popArg().intValue(); 455 } 456 for (int i = 0; i < count; ++i) { 457 final Point lastPoint = getLastPoint(); 458 final int xa = lastPoint.x; 459 final int ya = lastPoint.y + dya[i]; 460 final int xb = xa + dxb[i]; 461 final int yb = ya + dyb[i]; 462 final int xc = xb + dxc[i]; 463 final int yc = yb; 464 final int xd = xc + dxd[i]; 465 final int yd = yc; 466 final int xe = xd + dxe[i]; 467 final int ye = yd + dye[i]; 468 final int xf = xe + dxf; 469 final int yf = ye + dyf[i]; 470 curveTo(xa, ya, xb, yb, xc, yc); 471 curveTo(xd, yd, xe, ye, xf, yf); 472 } 473 } else { 474 final int foo = 0; 475 } 476 clearArg(); 477 } 478 479 /** 480 * Appends one or more curves to the current point. If the argument 481 * count is a multiple of four, the curve starts and ends vertical. If 482 * the argument count is odd, the first curve does not begin with a 483 * vertical tangent. 484 */ _vvcurveto()485 private void _vvcurveto() { 486 487 clearArg(); 488 } 489 490 /** 491 * Causes two Bezier curves, as described by the arguments (as 492 * shown in Figure 2 below), to be rendered as a straight line when 493 * the flex depth is less than fd /100 device pixels, and as curved lines 494 * when the flex depth is greater than or equal to fd/100 device 495 * pixels. 496 */ _flex()497 private void _flex() { 498 499 clearArg(); 500 } 501 502 /** 503 * Causes the two curves described by the arguments dx1...dx6 to 504 * be rendered as a straight line when the flex depth is less than 505 * 0.5 (that is, fd is 50) device pixels, and as curved lines when the 506 * flex depth is greater than or equal to 0.5 device pixels. 507 */ _hflex()508 private void _hflex() { 509 510 clearArg(); 511 } 512 513 /** 514 * Causes the two curves described by the arguments to be 515 * rendered as a straight line when the flex depth is less than 0.5 516 * device pixels, and as curved lines when the flex depth is greater 517 * than or equal to 0.5 device pixels. 518 */ _hflex1()519 private void _hflex1() { 520 521 clearArg(); 522 } 523 524 /** 525 * Causes the two curves described by the arguments to be 526 * rendered as a straight line when the flex depth is less than 0.5 527 * device pixels, and as curved lines when the flex depth is greater 528 * than or equal to 0.5 device pixels. 529 */ _flex1()530 private void _flex1() { 531 532 clearArg(); 533 } 534 535 /** 536 * Finishes a charstring outline definition, and must be the 537 * last operator in a character's outline. 538 */ _endchar()539 private void _endchar() { 540 endContour(); 541 clearArg(); 542 } 543 _hstem()544 private void _hstem() { 545 546 clearArg(); 547 } 548 _vstem()549 private void _vstem() { 550 551 clearArg(); 552 } 553 _hstemhm()554 private void _hstemhm() { 555 556 clearArg(); 557 } 558 _vstemhm()559 private void _vstemhm() { 560 561 clearArg(); 562 } 563 _hintmask()564 private void _hintmask() { 565 566 clearArg(); 567 } 568 _cntrmask()569 private void _cntrmask() { 570 571 clearArg(); 572 } 573 574 /** 575 * Returns the absolute value of num. 576 */ _abs()577 private void _abs() { 578 final double num = popArg().doubleValue(); 579 pushArg(Math.abs(num)); 580 } 581 582 /** 583 * Returns the sum of the two numbers num1 and num2. 584 */ _add()585 private void _add() { 586 final double num2 = popArg().doubleValue(); 587 final double num1 = popArg().doubleValue(); 588 pushArg(num1 + num2); 589 } 590 591 /** 592 * Returns the result of subtracting num2 from num1. 593 */ _sub()594 private void _sub() { 595 final double num2 = popArg().doubleValue(); 596 final double num1 = popArg().doubleValue(); 597 pushArg(num1 - num2); 598 } 599 600 /** 601 * Returns the quotient of num1 divided by num2. The result is 602 * undefined if overflow occurs and is zero for underflow. 603 */ _div()604 private void _div() { 605 final double num2 = popArg().doubleValue(); 606 final double num1 = popArg().doubleValue(); 607 pushArg(num1 / num2); 608 } 609 610 /** 611 * Returns the negative of num. 612 */ _neg()613 private void _neg() { 614 final double num = popArg().doubleValue(); 615 pushArg(-num); 616 } 617 618 /** 619 * Returns a pseudo random number num2 in the range (0,1], that 620 * is, greater than zero and less than or equal to one. 621 */ _random()622 private void _random() { 623 pushArg(1.0 - Math.random()); 624 } 625 626 /** 627 * Returns the product of num1 and num2. If overflow occurs, the 628 * result is undefined, and zero is returned for underflow. 629 */ _mul()630 private void _mul() { 631 final double num2 = popArg().doubleValue(); 632 final double num1 = popArg().doubleValue(); 633 pushArg(num1 * num2); 634 } 635 636 /** 637 * Returns the square root of num. If num is negative, the result is 638 * undefined. 639 */ _sqrt()640 private void _sqrt() { 641 final double num = popArg().doubleValue(); 642 pushArg(Math.sqrt(num)); 643 } 644 645 /** 646 * Removes the top element num from the Type 2 argument stack. 647 */ _drop()648 private void _drop() { 649 popArg(); 650 } 651 652 /** 653 * Exchanges the top two elements on the argument stack. 654 */ _exch()655 private void _exch() { 656 final Number num2 = popArg(); 657 final Number num1 = popArg(); 658 pushArg(num2); 659 pushArg(num1); 660 } 661 662 /** 663 * Retrieves the element i from the top of the argument stack and 664 * pushes a copy of that element onto that stack. If i is negative, 665 * the top element is copied. If i is greater than X, the operation is 666 * undefined. 667 */ _index()668 private void _index() { 669 final int i = popArg().intValue(); 670 final Number[] nums = new Number[i]; 671 for (int j = 0; j < i; ++j) { 672 nums[j] = popArg(); 673 } 674 for (int j = i - 1; j >= 0; --j) { 675 pushArg(nums[j]); 676 } 677 pushArg(nums[i]); 678 } 679 680 /** 681 * Performs a circular shift of the elements num(Nx1) ... num0 on 682 * the argument stack by the amount J. Positive J indicates upward 683 * motion of the stack; negative J indicates downward motion. 684 * The value N must be a non-negative integer, otherwise the 685 * operation is undefined. 686 */ _roll()687 private void _roll() { 688 final int j = popArg().intValue(); 689 final int n = popArg().intValue(); 690 final Number[] nums = new Number[n]; 691 for (int i = 0; i < n; ++i) { 692 nums[i] = popArg(); 693 } 694 for (int i = n - 1; i >= 0; --i) { 695 pushArg(nums[(n + i + j) % n]); 696 } 697 } 698 699 /** 700 * Duplicates the top element on the argument stack. 701 */ _dup()702 private void _dup() { 703 final Number any = popArg(); 704 pushArg(any); 705 pushArg(any); 706 } 707 708 /** 709 * Stores val into the transient array at the location given by i. 710 */ _put()711 private void _put() { 712 final int i = popArg().intValue(); 713 final Number val = popArg(); 714 _transientArray[i] = val; 715 } 716 717 /** 718 * Retrieves the value stored in the transient array at the location 719 * given by i and pushes the value onto the argument stack. If get 720 * is executed prior to put for i during execution of the current 721 * charstring, the value returned is undefined. 722 */ _get()723 private void _get() { 724 final int i = popArg().intValue(); 725 pushArg(_transientArray[i]); 726 } 727 728 /** 729 * Puts a 1 on the stack if num1 and num2 are both non-zero, and 730 * puts a 0 on the stack if either argument is zero. 731 */ _and()732 private void _and() { 733 final double num2 = popArg().doubleValue(); 734 final double num1 = popArg().doubleValue(); 735 pushArg((num1!=0.0) && (num2!=0.0) ? 1 : 0); 736 } 737 738 /** 739 * Puts a 1 on the stack if either num1 or num2 are non-zero, and 740 * puts a 0 on the stack if both arguments are zero. 741 */ _or()742 private void _or() { 743 final double num2 = popArg().doubleValue(); 744 final double num1 = popArg().doubleValue(); 745 pushArg((num1!=0.0) || (num2!=0.0) ? 1 : 0); 746 } 747 748 /** 749 * Returns a 0 if num1 is non-zero; returns a 1 if num1 is zero. 750 */ _not()751 private void _not() { 752 final double num1 = popArg().doubleValue(); 753 pushArg((num1!=0.0) ? 0 : 1); 754 } 755 756 /** 757 * Puts a 1 on the stack if num1 equals num2, otherwise a 0 (zero) 758 * is put on the stack. 759 */ _eq()760 private void _eq() { 761 final double num2 = popArg().doubleValue(); 762 final double num1 = popArg().doubleValue(); 763 pushArg(num1 == num2 ? 1 : 0); 764 } 765 766 /** 767 * Leaves the value s1 on the stack if v1 ? v2, or leaves s2 on the 768 * stack if v1 > v2. The value of s1 and s2 is usually the biased 769 * number of a subroutine. 770 */ _ifelse()771 private void _ifelse() { 772 final double v2 = popArg().doubleValue(); 773 final double v1 = popArg().doubleValue(); 774 final Number s2 = popArg(); 775 final Number s1 = popArg(); 776 pushArg(v1 <= v2 ? s1 : s2); 777 } 778 779 /** 780 * Calls a charstring subroutine with index subr# (actually the subr 781 * number plus the subroutine bias number, as described in section 782 * 2.3) in the Subrs array. Each element of the Subrs array is a 783 * charstring encoded like any other charstring. Arguments 784 * pushed on the Type 2 argument stack prior to calling the 785 * subroutine, and results pushed on this stack by the subroutine, 786 * act according to the manner in which the subroutine is coded. 787 * Calling an undefined subr (gsubr) has undefined results. 788 */ _callsubr()789 private void _callsubr() { 790 791 } 792 793 /** 794 * Operates in the same manner as callsubr except that it calls a 795 * global subroutine. 796 */ _callgsubr()797 private void _callgsubr() { 798 799 } 800 801 /** 802 * Returns from either a local or global charstring subroutine, and 803 * continues execution after the corresponding call(g)subr. 804 */ _return()805 private void _return() { 806 807 } 808 execute(final CharstringType2 cs)809 public Point[] execute(final CharstringType2 cs) { 810 _points = new ArrayList<Point>(); 811 cs.resetIP(); 812 while (cs.moreBytes()) { 813 while (cs.isOperandAtIndex()) { 814 pushArg(cs.nextOperand()); 815 } 816 int operator = cs.nextByte(); 817 if (operator == 12) { 818 operator = cs.nextByte(); 819 820 // Two-byte operators 821 switch (operator) { 822 case T2Mnemonic.AND: 823 _and(); 824 break; 825 case T2Mnemonic.OR: 826 _or(); 827 break; 828 case T2Mnemonic.NOT: 829 _not(); 830 break; 831 case T2Mnemonic.ABS: 832 _abs(); 833 break; 834 case T2Mnemonic.ADD: 835 _add(); 836 break; 837 case T2Mnemonic.SUB: 838 _sub(); 839 break; 840 case T2Mnemonic.DIV: 841 _div(); 842 break; 843 case T2Mnemonic.NEG: 844 _neg(); 845 break; 846 case T2Mnemonic.EQ: 847 _eq(); 848 break; 849 case T2Mnemonic.DROP: 850 _drop(); 851 break; 852 case T2Mnemonic.PUT: 853 _put(); 854 break; 855 case T2Mnemonic.GET: 856 _get(); 857 break; 858 case T2Mnemonic.IFELSE: 859 _ifelse(); 860 break; 861 case T2Mnemonic.RANDOM: 862 _random(); 863 break; 864 case T2Mnemonic.MUL: 865 _mul(); 866 break; 867 case T2Mnemonic.SQRT: 868 _sqrt(); 869 break; 870 case T2Mnemonic.DUP: 871 _dup(); 872 break; 873 case T2Mnemonic.EXCH: 874 _exch(); 875 break; 876 case T2Mnemonic.INDEX: 877 _index(); 878 break; 879 case T2Mnemonic.ROLL: 880 _roll(); 881 break; 882 case T2Mnemonic.HFLEX: 883 _hflex(); 884 break; 885 case T2Mnemonic.FLEX: 886 _flex(); 887 break; 888 case T2Mnemonic.HFLEX1: 889 _hflex1(); 890 break; 891 case T2Mnemonic.FLEX1: 892 _flex1(); 893 break; 894 default: 895 //throw new Exception(); 896 return null; 897 } 898 } else { 899 900 // One-byte operators 901 switch (operator) { 902 case T2Mnemonic.HSTEM: 903 _hstem(); 904 break; 905 case T2Mnemonic.VSTEM: 906 _vstem(); 907 break; 908 case T2Mnemonic.VMOVETO: 909 _vmoveto(); 910 break; 911 case T2Mnemonic.RLINETO: 912 _rlineto(); 913 break; 914 case T2Mnemonic.HLINETO: 915 _hlineto(); 916 break; 917 case T2Mnemonic.VLINETO: 918 _vlineto(); 919 break; 920 case T2Mnemonic.RRCURVETO: 921 _rrcurveto(); 922 break; 923 case T2Mnemonic.CALLSUBR: 924 _callsubr(); 925 break; 926 case T2Mnemonic.RETURN: 927 _return(); 928 break; 929 case T2Mnemonic.ENDCHAR: 930 _endchar(); 931 break; 932 case T2Mnemonic.HSTEMHM: 933 _hstemhm(); 934 break; 935 case T2Mnemonic.HINTMASK: 936 _hintmask(); 937 break; 938 case T2Mnemonic.CNTRMASK: 939 _cntrmask(); 940 break; 941 case T2Mnemonic.RMOVETO: 942 _rmoveto(); 943 break; 944 case T2Mnemonic.HMOVETO: 945 _hmoveto(); 946 break; 947 case T2Mnemonic.VSTEMHM: 948 _vstemhm(); 949 break; 950 case T2Mnemonic.RCURVELINE: 951 _rcurveline(); 952 break; 953 case T2Mnemonic.RLINECURVE: 954 _rlinecurve(); 955 break; 956 case T2Mnemonic.VVCURVETO: 957 _vvcurveto(); 958 break; 959 case T2Mnemonic.HHCURVETO: 960 _hhcurveto(); 961 break; 962 case T2Mnemonic.CALLGSUBR: 963 _callgsubr(); 964 break; 965 case T2Mnemonic.VHCURVETO: 966 _vhcurveto(); 967 break; 968 case T2Mnemonic.HVCURVETO: 969 _hvcurveto(); 970 break; 971 default: 972 //throw new Exception(); 973 return null; 974 } 975 } 976 } 977 final Point[] pointArray = new Point[_points.size()]; 978 _points.toArray(pointArray); 979 return pointArray; 980 } 981 982 /** 983 * The number of arguments on the argument stack 984 */ getArgCount()985 private int getArgCount() { 986 return _argStackIndex; 987 } 988 989 /** 990 * Pop a value off the argument stack 991 */ popArg()992 private Number popArg() { 993 return _argStack[--_argStackIndex]; 994 } 995 996 /** 997 * Push a value on to the argument stack 998 */ pushArg(final Number n)999 private void pushArg(final Number n) { 1000 _argStack[_argStackIndex++] = n; 1001 } 1002 1003 /** 1004 * Pop a value off the subroutine stack 1005 */ popSubr()1006 private int popSubr() { 1007 return _subrStack[--_subrStackIndex]; 1008 } 1009 1010 /** 1011 * Push a value on to the subroutine stack 1012 */ pushSubr(final int n)1013 private void pushSubr(final int n) { 1014 _subrStack[_subrStackIndex++] = n; 1015 } 1016 1017 /** 1018 * Clear the argument stack 1019 */ clearArg()1020 private void clearArg() { 1021 _argStackIndex = 0; 1022 } 1023 getLastPoint()1024 private Point getLastPoint() { 1025 final int size = _points.size(); 1026 if (size > 0) { 1027 return _points.get(size - 1); 1028 } else { 1029 return new Point(0, 0, true, false); 1030 } 1031 } 1032 moveTo(final int x, final int y)1033 private void moveTo(final int x, final int y) { 1034 endContour(); 1035 _points.add(new Point(x, y, true, false)); 1036 } 1037 lineTo(final int x, final int y)1038 private void lineTo(final int x, final int y) { 1039 _points.add(new Point(x, y, true, false)); 1040 } 1041 curveTo(final int cx1, final int cy1, final int cx2, final int cy2, final int x, final int y)1042 private void curveTo(final int cx1, final int cy1, final int cx2, final int cy2, final int x, final int y) { 1043 _points.add(new Point(cx1, cy1, false, false)); 1044 _points.add(new Point(cx2, cy2, false, false)); 1045 _points.add(new Point(x, y, true, false)); 1046 } 1047 endContour()1048 private void endContour() { 1049 final Point lastPoint = getLastPoint(); 1050 if (lastPoint != null) { 1051 lastPoint.endOfContour = true; 1052 } 1053 } 1054 } 1055