powered by nequal
Home » Packages » IO_SWF » Source

IO_SWF / trunk/IO/SWF/Type/SHAPE.php

Subversion URL: http://svn.openpear.org/IO_SWF/trunk/IO/SWF/Type/SHAPE.php

Recent change

yoya [2952] -- 2013-04-16 00:35:56
abstract => extends でなく interface で継承するように変更
(PHP5.4 では abstract static が使えないので。元々意味的に変だったけど。。)
thank you! > s-satoshi

<?php
 
/*
 * 2011/4/15- (c) yoya@awm.jp
 */
 
require_once 'IO/Bit.php';
require_once dirname(__FILE__).'/../Type.php';
require_once dirname(__FILE__).'/../Type/FILLSTYLEARRAY.php';
require_once dirname(__FILE__).'/../Type/LINESTYLEARRAY.php';
 
class IO_SWF_Type_SHAPE extends IO_SWF_Type {
    static function parse(&$reader, $opts = array()) {
        $tagCode = $opts['tagCode'];
        $shapeRecords = array();
 
    	$reader->byteAlign();
    	// 描画スタイルを参照するインデックスのビット幅
    	$numFillBits = $reader->getUIBits(4);
	    $numLineBits = $reader->getUIBits(4);
 
    	$currentDrawingPositionX = 0;
    	$currentDrawingPositionY = 0;
    	$currentFillStyle0 = 0;
    	$currentFillStyle1 = 0;
    	$currentLineStyle = 0;
    	$done = false;
 
    	// ShapeRecords
    	while ($done === false) {
    	    $shapeRecord = array();
            $typeFlag = $reader->getUIBit();
            $shapeRecord['TypeFlag'] = $typeFlag;
            if ($typeFlag == 0) {
                $endOfShape = $reader->getUIBits(5);
               if ($endOfShape == 0) {
                    // EndShapeRecord
                    $shapeRecord['EndOfShape'] = $endOfShape;
                    $done = true;
               } else {
                    // StyleChangeRecord
                    $reader->incrementOffset(0, -5);
                    $stateNewStyles = $reader->getUIBit();
                    $stateLineStyle = $reader->getUIBit();
                    $stateFillStyle1 = $reader->getUIBit();
                    $stateFillStyle0 = $reader->getUIBit();
 
                    $stateMoveTo = $reader->getUIBit();
                    if ($stateMoveTo) {
                    $moveBits = $reader->getUIBits(5);
//                        $shapeRecord['(MoveBits)'] = $moveBits;
                        $moveDeltaX = $reader->getSIBits($moveBits);
                        $moveDeltaY = $reader->getSIBits($moveBits);
//                        $currentDrawingPositionX += $moveDeltaX;
//                        $currentDrawingPositionY += $moveDeltaY;
                        $currentDrawingPositionX = $moveDeltaX;
                        $currentDrawingPositionY = $moveDeltaY;
                        $shapeRecord['MoveX'] = $currentDrawingPositionX;
                        $shapeRecord['MoveY'] = $currentDrawingPositionY;
                    }
                    $shapeRecord['MoveX'] = $currentDrawingPositionX;
                    $shapeRecord['MoveY'] = $currentDrawingPositionY;
 
                    if ($stateFillStyle0) {
                        $currentFillStyle0 = $reader->getUIBits($numFillBits);
                    }
                    if ($stateFillStyle1) {
                        $currentFillStyle1 = $reader->getUIBits($numFillBits);
                    }
                    if ($stateLineStyle) {
                        $currentLineStyle = $reader->getUIBits($numLineBits);
                    }
                    $shapeRecord['FillStyle0'] = $currentFillStyle0;
                    $shapeRecord['FillStyle1'] = $currentFillStyle1;
                    $shapeRecord['LineStyle']  = $currentLineStyle;
                    if ($stateNewStyles) {
                        $opts = array('tagCode' => $tagCode);
                        $shapeRecord['FillStyles'] = IO_SWF_TYPE_FILLSTYLEARRAY::parse($reader, $opts);
                        $shapeRecord['LineStyles'] = IO_SWF_TYPE_LINESTYLEARRAY::parse($reader, $opts);
                        $reader->byteAlign();
                        $numFillBits = $reader->getUIBits(4);
                        $numLineBits = $reader->getUIBits(4);
                    }
                }
            } else { // Edge records
                $shapeRecord['StraightFlag'] = $reader->getUIBit();
                if ($shapeRecord['StraightFlag']) {
                    // StraightEdgeRecord
                    $numBits = $reader->getUIBits(4);
//                    $shapeRecord['(NumBits)'] = $numBits;
                     $generalLineFlag = $reader->getUIBit();
                    if ($generalLineFlag == 0) {
                        $vertLineFlag = $reader->getUIBit();
                    }
                    if ($generalLineFlag || ($vertLineFlag == 0)) {
                        $deltaX = $reader->getSIBits($numBits + 2);
                        $currentDrawingPositionX += $deltaX;
                    }
                    if ($generalLineFlag || $vertLineFlag) {
                        $deltaY = $reader->getSIBits($numBits + 2);
                        $currentDrawingPositionY += $deltaY;
                    }
                    $shapeRecord['X'] = $currentDrawingPositionX;
                    $shapeRecord['Y'] = $currentDrawingPositionY;
                } else {
                    // CurvedEdgeRecord
                    $numBits = $reader->getUIBits(4);
//                    $shapeRecord['(NumBits)'] = $numBits;
 
                    $controlDeltaX = $reader->getSIBits($numBits + 2);
                    $controlDeltaY = $reader->getSIBits($numBits + 2);
                    $anchorDeltaX = $reader->getSIBits($numBits + 2);
                    $anchorDeltaY = $reader->getSIBits($numBits + 2);
 
                    $currentDrawingPositionX += $controlDeltaX;
                    $currentDrawingPositionY += $controlDeltaY;
                    $shapeRecord['ControlX'] = $currentDrawingPositionX;
                    $shapeRecord['ControlY'] = $currentDrawingPositionY;
 
                    $currentDrawingPositionX += $anchorDeltaX;
                    $currentDrawingPositionY += $anchorDeltaY;
                    $shapeRecord['AnchorX'] = $currentDrawingPositionX;
                    $shapeRecord['AnchorY'] = $currentDrawingPositionY;
                }
            }
            $shapeRecords []= $shapeRecord;
       }
    	return $shapeRecords;
    }
    static function build(&$writer, $shapeRecords, $opts = array()) {
        $tagCode = $opts['tagCode'];
        $fillStyleCount = $opts['fillStyleCount'];
        $lineStyleCount = $opts['lineStyleCount'];
        if ($fillStyleCount == 0) {
            $numFillBits = 0;
        } else {
            // $fillStyleCount == fillStyle MaxValue because 'undefined' use 0
            $numFillBits = $writer->need_bits_unsigned($fillStyleCount);
        }
        if ($lineStyleCount == 0) {
            $numLineBits = 0;
        } else {
            // $lineStyleCount == lineStyle MaxValue because 'undefined' use 0
            $numLineBits = $writer->need_bits_unsigned($lineStyleCount);
        }
 
        $writer->byteAlign();
        $writer->putUIBits($numFillBits, 4);
        $writer->putUIBits($numLineBits, 4);
        $currentDrawingPositionX = 0;
        $currentDrawingPositionY = 0;
        $currentFillStyle0 = 0;
        $currentFillStyle1 = 0;
        $currentLineStyle = 0;
        foreach ($shapeRecords as $shapeRecordIndex => $shapeRecord) {
            $typeFlag = $shapeRecord['TypeFlag'];
            $writer->putUIBit($typeFlag);
            if($typeFlag == 0) {
                if (isset($shapeRecord['EndOfShape']) && ($shapeRecord['EndOfShape']) == 0) {
                    // EndShapeRecord
                    $writer->putUIBits(0, 5);
                } else {
                    // StyleChangeRecord
                    $stateNewStyles =  isset($shapeRecord['FillStyles'])?1:0;
                    $stateLineStyle = ($shapeRecord['LineStyle'] != $currentLineStyle)?1:0;
                    $stateFillStyle1 = ($shapeRecord['FillStyle1'] != $currentFillStyle1)?1:0;
                    $stateFillStyle0 = ($shapeRecord['FillStyle0'] != $currentFillStyle0)?1:0;
 
                    $writer->putUIBit($stateNewStyles);
                    $writer->putUIBit($stateLineStyle);
                    $writer->putUIBit($stateFillStyle1);
                    $writer->putUIBit($stateFillStyle0);
 
                    if (($shapeRecord['MoveX'] != $currentDrawingPositionX) || ($shapeRecord['MoveY'] != $currentDrawingPositionY)) {
                        $stateMoveTo = true;
                    } else {
                        $stateMoveTo = false;
                    }
                    $writer->putUIBit($stateMoveTo);
                    if ($stateMoveTo) {
                        $moveX = $shapeRecord['MoveX'];
                        $moveY = $shapeRecord['MoveY'];
                        $currentDrawingPositionX = $moveX;
                        $currentDrawingPositionY = $moveY;
                        if ($moveX | $moveY) { 
                            $XmoveBits = $writer->need_bits_signed($moveX);
                            $YmoveBits = $writer->need_bits_signed($moveY);
                            $moveBits = max($XmoveBits, $YmoveBits);
                        } else {
                            $moveBits = 0;
                        }
                        $writer->putUIBits($moveBits, 5);
                        $writer->putSIBits($moveX, $moveBits);
                        $writer->putSIBits($moveY, $moveBits);
                    }
                    if ($stateFillStyle0) {
                        $currentFillStyle0 = $shapeRecord['FillStyle0'];
                        $writer->putUIBits($currentFillStyle0, $numFillBits);
                    }
                    if ($stateFillStyle1) {
                        $currentFillStyle1 = $shapeRecord['FillStyle1'];
                        $writer->putUIBits($currentFillStyle1, $numFillBits);
                    }
                    if ($stateLineStyle) {
                        $currentLineStyle = $shapeRecord['LineStyle'];
                        $writer->putUIBits($currentLineStyle, $numLineBits);
                    }
                    if ($stateNewStyles) {
                        $opts = array('tagCode' => $tagCode);
                        IO_SWF_Type_FILLSTYLEARRAY::build($writer, $shapeRecord['FillStyles'], $opts);
                        IO_SWF_Type_LINESTYLEARRAY::build($writer, $shapeRecord['LineStyles'], $opts);
                        $fillStyleCount = count($shapeRecord['FillStyles']);
                        if ($fillStyleCount == 0) {
                            $numFillBits = 0;
                        } else {
                            // $fillStyleCount == fillStyle MaxValue because 'undefined' use 0
                            $numFillBits = $writer->need_bits_unsigned($fillStyleCount);
                        }
                        if ($lineStyleCount == 0) {
                            $numLineBits = 0;
                        } else {
                            // $lineStyleCount == lineStyle MaxValue because 'undefined' use 0
                            $numLineBits = $writer->need_bits_unsigned($lineStyleCount);
                        }
                        $writer->byteAlign();
                        $writer->putUIBits($numFillBits, 4);
                        $writer->putUIBits($numLineBits, 4);
                    }
                }
            } else {
                $straightFlag = $shapeRecord['StraightFlag'];
                $writer->putUIBit($straightFlag);
                if ($straightFlag) {
                    $deltaX = $shapeRecord['X'] - $currentDrawingPositionX;
                    $deltaY = $shapeRecord['Y'] - $currentDrawingPositionY;
                    if ($deltaX | $deltaY) {
                       $XNumBits = $writer->need_bits_signed($deltaX);
                       $YNumBits = $writer->need_bits_signed($deltaY);
                       $numBits = max($XNumBits, $YNumBits);
                    } else {
                        $numBits = 0;
                    }
                    if ($numBits < 2) {
                        $numBits = 2;
                    }
                    $writer->putUIBits($numBits - 2, 4);
                    if ($deltaX && $deltaY) {
                        $writer->putUIBit(1); // GeneralLineFlag
                        $writer->putSIBits($deltaX, $numBits);
                        $writer->putSIBits($deltaY, $numBits);
                    } else {
                        $writer->putUIBit(0); // GeneralLineFlag
                        if ($deltaX) {
                           $writer->putUIBit(0); // VertLineFlag
                           $writer->putSIBits($deltaX, $numBits);
                        } else {
                           $writer->putUIBit(1); // VertLineFlag
                           $writer->putSIBits($deltaY, $numBits);
                        }
                    }
                    $currentDrawingPositionX = $shapeRecord['X'];
                    $currentDrawingPositionY = $shapeRecord['Y'];
                } else {
                    $controlDeltaX = $shapeRecord['ControlX'] - $currentDrawingPositionX;
                    $controlDeltaY = $shapeRecord['ControlY'] - $currentDrawingPositionY;
                    $currentDrawingPositionX = $shapeRecord['ControlX'];
                    $currentDrawingPositionY = $shapeRecord['ControlY'];
                    $anchorDeltaX = $shapeRecord['AnchorX'] - $currentDrawingPositionX;
                    $anchorDeltaY = $shapeRecord['AnchorY'] - $currentDrawingPositionY;
                    $currentDrawingPositionX = $shapeRecord['AnchorX'];
                    $currentDrawingPositionY = $shapeRecord['AnchorY'];
 
                    $numBitsControlDeltaX = $writer->need_bits_signed($controlDeltaX);
                    $numBitsControlDeltaY = $writer->need_bits_signed($controlDeltaY);
                    $numBitsAnchorDeltaX = $writer->need_bits_signed($anchorDeltaX);
                    $numBitsAnchorDeltaY = $writer->need_bits_signed($anchorDeltaY);
                    $numBits = max($numBitsControlDeltaX, $numBitsControlDeltaY, $numBitsAnchorDeltaX, $numBitsAnchorDeltaY);
                    if ($numBits < 2) {
                       $numBits = 2;
                    }
                    $writer->putUIBits($numBits - 2, 4);
                    $writer->putSIBits($controlDeltaX, $numBits);
                    $writer->putSIBits($controlDeltaY, $numBits);
                    $writer->putSIBits($anchorDeltaX, $numBits);
                    $writer->putSIBits($anchorDeltaY, $numBits);
                }
            }
        }
        return true;
    }
    static function string($shapeRecords, $opts = array()) {
        $tagCode = $opts['tagCode'];
        foreach ($shapeRecords as $shapeRecord) {
            $typeFlag = $shapeRecord['TypeFlag'];
            if ($typeFlag == 0) {
               if (isset($shapeRecord['EndOfShape'])) {
                   break;
               } else {
                   $moveX = $shapeRecord['MoveX'] / 20;
                   $moveY = $shapeRecord['MoveY'] / 20;
                   echo "\tChangeStyle: MoveTo: ($moveX, $moveY)";
                   $style_list = array('FillStyle0', 'FillStyle1', 'LineStyle');
                   echo "  FillStyle: ".$shapeRecord['FillStyle0']."|".$shapeRecord['FillStyle1'];
                   echo "  LineStyle: ".$shapeRecord['LineStyle']."\n";
                   if (isset($shapeRecord['FillStyles'])) {
                       echo "    FillStyles:\n";
                       echo IO_SWF_Type_FILLSTYLEARRAY::string($shapeRecord['FillStyles']);
                   }
                   if (isset($shapeRecord['LineStyles'])) {
                        echo "    LineStyles:\n";
                        echo IO_SWF_Type_FILLSTYLEARRAY::string($shapeRecord['LineStyles']);
                   }
               }
            } else {
                $straightFlag = $shapeRecord['StraightFlag'];
                if ($straightFlag) {
                    $x = $shapeRecord['X'] / 20;
                    $y = $shapeRecord['Y'] / 20;
                    echo "\tStraightEdge: MoveTo: ($x, $y)\n";
                } else {
                    $controlX = $shapeRecord['ControlX'] / 20;
                    $controlY = $shapeRecord['ControlY'] / 20;
                    $anchorX = $shapeRecord['AnchorX'] / 20;
                    $anchorY = $shapeRecord['AnchorY'] / 20;
                    echo "\tCurvedEdge: MoveTo: Control($controlX, $controlY) Anchor($anchorX, $anchorY)\n";
                }
            }
        }
    }
}