/** * @param $data integer * @param $pos integer * @return \stdClass * @link http://msdn.microsoft.com/en-us/library/dd772849%28v=office.12%29.aspx */ private function readPrl($data, $pos, $cbNum) { $posStart = $pos; $oStylePrl = new \stdClass(); // Variables $sprmCPicLocation = null; $sprmCFData = null; $sprmCFSpec = null; do { // Variables $operand = null; $sprm = self::getInt2d($data, $pos); $oSprm = $this->readSprm($sprm); $pos += 2; $cbNum -= 2; $arrayReturn = $this->readSprmSpra($data, $pos, $oSprm); $pos += $arrayReturn['length']; $cbNum -= $arrayReturn['length']; $operand = $arrayReturn['operand']; switch (dechex($oSprm->sgc)) { // Paragraph property case 0x1: break; // Character property // Character property case 0x2: if (!isset($oStylePrl->styleFont)) { $oStylePrl->styleFont = array(); } switch ($oSprm->isPmd) { // sprmCFRMarkIns case 0x1: break; // sprmCFFldVanish // sprmCFFldVanish case 0x2: break; // sprmCPicLocation // sprmCPicLocation case 0x3: $sprmCPicLocation = $operand; break; // sprmCFData // sprmCFData case 0x6: $sprmCFData = dechex($operand) == 0x0 ? false : true; break; // sprmCFItalic // sprmCFItalic case 0x36: // By default, text is not italicized. switch ($operand) { case false: case true: $oStylePrl->styleFont['italic'] = $operand; break; case self::SPRA_VALUE: $oStylePrl->styleFont['italic'] = false; break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['italic'] = true; break; } break; // sprmCIstd // sprmCIstd case 0x30: //print_r('sprmCIstd : '.dechex($operand).PHP_EOL.PHP_EOL); break; // sprmCFBold // sprmCFBold case 0x35: // By default, text is not bold. switch ($operand) { case false: case true: $oStylePrl->styleFont['bold'] = $operand; break; case self::SPRA_VALUE: $oStylePrl->styleFont['bold'] = false; break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['bold'] = true; break; } break; // sprmCFStrike // sprmCFStrike case 0x37: // By default, text is not struck through. switch ($operand) { case false: case true: $oStylePrl->styleFont['strikethrough'] = $operand; break; case self::SPRA_VALUE: $oStylePrl->styleFont['strikethrough'] = false; break; case self::SPRA_VALUE_OPPOSITE: $oStylePrl->styleFont['strikethrough'] = true; break; } break; // sprmCKul // sprmCKul case 0x3e: switch (dechex($operand)) { case 0x0: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; break; case 0x1: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_SINGLE; break; case 0x2: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WORDS; break; case 0x3: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOUBLE; break; case 0x4: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTED; break; case 0x6: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_HEAVY; break; case 0x7: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASH; break; case 0x9: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTHASH; break; case 0xa: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASH; break; case 0xb: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVY; break; case 0x14: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTTEDHEAVY; break; case 0x17: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHHEAVY; break; case 0x19: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTHASHHEAVY; break; case 0x1a: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DOTDOTDASHHEAVY; break; case 0x1b: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYHEAVY; break; case 0x27: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONG; break; case 0x2b: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_WAVYDOUBLE; break; case 0x37: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_DASHLONGHEAVY; break; default: $oStylePrl->styleFont['underline'] = Style\Font::UNDERLINE_NONE; break; } break; // sprmCIco //@link http://msdn.microsoft.com/en-us/library/dd773060%28v=office.12%29.aspx // sprmCIco //@link http://msdn.microsoft.com/en-us/library/dd773060%28v=office.12%29.aspx case 0x42: switch (dechex($operand)) { case 0x0: case 0x1: $oStylePrl->styleFont['color'] = '000000'; break; case 0x2: $oStylePrl->styleFont['color'] = '0000FF'; break; case 0x3: $oStylePrl->styleFont['color'] = '00FFFF'; break; case 0x4: $oStylePrl->styleFont['color'] = '00FF00'; break; case 0x5: $oStylePrl->styleFont['color'] = 'FF00FF'; break; case 0x6: $oStylePrl->styleFont['color'] = 'FF0000'; break; case 0x7: $oStylePrl->styleFont['color'] = 'FFFF00'; break; case 0x8: $oStylePrl->styleFont['color'] = 'FFFFFF'; break; case 0x9: $oStylePrl->styleFont['color'] = '000080'; break; case 0xa: $oStylePrl->styleFont['color'] = '008080'; break; case 0xb: $oStylePrl->styleFont['color'] = '008000'; break; case 0xc: $oStylePrl->styleFont['color'] = '800080'; break; case 0xd: $oStylePrl->styleFont['color'] = '800080'; break; case 0xe: $oStylePrl->styleFont['color'] = '808000'; break; case 0xf: $oStylePrl->styleFont['color'] = '808080'; break; case 0x10: $oStylePrl->styleFont['color'] = 'C0C0C0'; } break; // sprmCHps // sprmCHps case 0x43: $oStylePrl->styleFont['size'] = dechex($operand / 2); break; // sprmCIss // sprmCIss case 0x48: if (!isset($oStylePrl->styleFont['superScript'])) { $oStylePrl->styleFont['superScript'] = false; } if (!isset($oStylePrl->styleFont['subScript'])) { $oStylePrl->styleFont['subScript'] = false; } switch (dechex($operand)) { case 0x0: // Normal text break; case 0x1: $oStylePrl->styleFont['superScript'] = true; break; case 0x2: $oStylePrl->styleFont['subScript'] = true; break; } break; // sprmCRgFtc0 // sprmCRgFtc0 case 0x4f: $oStylePrl->styleFont['name'] = ''; if (isset($this->arrayFonts[$operand])) { $oStylePrl->styleFont['name'] = $this->arrayFonts[$operand]['main']; } break; // sprmCRgFtc1 // sprmCRgFtc1 case 0x50: // if the language for the text is an East Asian language break; // sprmCRgFtc2 // sprmCRgFtc2 case 0x51: // if the character falls outside the Unicode character range break; // sprmCFSpec // sprmCFSpec case 0x55: $sprmCFSpec = $operand; break; // sprmCFtcBi // sprmCFtcBi case 0x5e: break; // sprmCFItalicBi // sprmCFItalicBi case 0x5d: break; // sprmCHpsBi // sprmCHpsBi case 0x61: break; // sprmCShd80 //@link http://msdn.microsoft.com/en-us/library/dd923447%28v=office.12%29.aspx // sprmCShd80 //@link http://msdn.microsoft.com/en-us/library/dd923447%28v=office.12%29.aspx case 0x66: // $operand = self::getInt2d($data, $pos); $pos += 2; $cbNum -= 2; // $ipat = ($operand >> 0) && bindec('111111'); // $icoBack = ($operand >> 6) && bindec('11111'); // $icoFore = ($operand >> 11) && bindec('11111'); break; // sprmCCv //@link : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx // sprmCCv //@link : http://msdn.microsoft.com/en-us/library/dd952824%28v=office.12%29.aspx case 0x70: $red = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); $pos += 1; $green = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); $pos += 1; $blue = str_pad(dechex(self::getInt1d($this->dataWorkDocument, $pos)), 2, '0', STR_PAD_LEFT); $pos += 1; $pos += 1; $oStylePrl->styleFont['color'] = $red . $green . $blue; $cbNum -= 4; break; default: // print_r('@todo Character : 0x'.dechex($oSprm->isPmd)); // print_r(PHP_EOL); } break; // Picture property // Picture property case 0x3: break; // Section property // Section property case 0x4: if (!isset($oStylePrl->styleSection)) { $oStylePrl->styleSection = array(); } switch ($oSprm->isPmd) { // sprmSNfcPgn case 0xe: // numbering format used for page numbers break; // sprmSXaPage // sprmSXaPage case 0x1f: $oStylePrl->styleSection['pageSizeW'] = $operand; break; // sprmSYaPage // sprmSYaPage case 0x20: $oStylePrl->styleSection['pageSizeH'] = $operand; break; // sprmSDxaLeft // sprmSDxaLeft case 0x21: $oStylePrl->styleSection['marginLeft'] = $operand; break; // sprmSDxaRight // sprmSDxaRight case 0x22: $oStylePrl->styleSection['marginRight'] = $operand; break; // sprmSDyaTop // sprmSDyaTop case 0x23: $oStylePrl->styleSection['marginTop'] = $operand; break; // sprmSDyaBottom // sprmSDyaBottom case 0x24: $oStylePrl->styleSection['marginBottom'] = $operand; break; // sprmSFBiDi // sprmSFBiDi case 0x28: // RTL layout break; // sprmSDxtCharSpace // sprmSDxtCharSpace case 0x30: // characpter pitch break; // sprmSDyaLinePitch // sprmSDyaLinePitch case 0x31: // line height break; // sprmSClm // sprmSClm case 0x32: // document grid mode break; // sprmSTextFlow // sprmSTextFlow case 0x33: // text flow break; default: // print_r('@todo Section : 0x'.dechex($oSprm->isPmd)); // print_r(PHP_EOL); } break; // Table property // Table property case 0x5: break; } } while ($cbNum > 0); if (!is_null($sprmCPicLocation)) { if (!is_null($sprmCFData) && $sprmCFData == 0x1) { // NilPICFAndBinData //@todo Read Hyperlink structure /*$lcb = self::getInt4d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 4; $cbHeader = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // ignored $sprmCPicLocation += 62; // depending of the element // Hyperlink => HFD // HFD > bits $sprmCPicLocation += 1; // HFD > clsid $sprmCPicLocation += 16; // HFD > hyperlink //@link : http://msdn.microsoft.com/en-us/library/dd909835%28v=office.12%29.aspx $streamVersion = self::getInt4d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 4; $data = self::getInt4d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 4; $hlstmfAbsFromGetdataRel = ($data >> 9) & bindec('1'); $hlstmfMonikerSavedAsStr = ($data >> 8) & bindec('1'); $hlstmfHasFrameName = ($data >> 7) & bindec('1'); $hlstmfHasCreationTime = ($data >> 6) & bindec('1'); $hlstmfHasGUID = ($data >> 5) & bindec('1'); $hlstmfHasDisplayName = ($data >> 4) & bindec('1'); $hlstmfHasLocationStr = ($data >> 3) & bindec('1'); $hlstmfSiteGaveDisplayName = ($data >> 2) & bindec('1'); $hlstmfIsAbsolute = ($data >> 1) & bindec('1'); $hlstmfHasMoniker = ($data >> 0) & bindec('1'); for ($inc = 0; $inc <= 32; $inc++) { echo ($data >> $inc) & bindec('1'); } print_r('$hlstmfHasMoniker > '.$hlstmfHasMoniker.PHP_EOL); print_r('$hlstmfIsAbsolute > '.$hlstmfIsAbsolute.PHP_EOL); print_r('$hlstmfSiteGaveDisplayName > '.$hlstmfSiteGaveDisplayName.PHP_EOL); print_r('$hlstmfHasLocationStr > '.$hlstmfHasLocationStr.PHP_EOL); print_r('$hlstmfHasDisplayName > '.$hlstmfHasDisplayName.PHP_EOL); print_r('$hlstmfHasGUID > '.$hlstmfHasGUID.PHP_EOL); print_r('$hlstmfHasCreationTime > '.$hlstmfHasCreationTime.PHP_EOL); print_r('$hlstmfHasFrameName > '.$hlstmfHasFrameName.PHP_EOL); print_r('$hlstmfMonikerSavedAsStr > '.$hlstmfMonikerSavedAsStr.PHP_EOL); print_r('$hlstmfAbsFromGetdataRel > '.$hlstmfAbsFromGetdataRel.PHP_EOL); if ($streamVersion == 2) { $AAA = self::getInt4d($this->dataData, $sprmCPicLocation); echo 'AAAA : '.$AAA.PHP_EOL; if ($hlstmfHasDisplayName == 1) { echo 'displayName'.PHP_EOL; } if ($hlstmfHasFrameName == 1) { echo 'targetFrameName'.PHP_EOL; } if ($hlstmfHasMoniker == 1 || $hlstmfMonikerSavedAsStr == 1) { $sprmCPicLocation += 16; $length = self::getInt4d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 4; for ($inc = 0; $inc < ($length / 2); $inc++) { $chr = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; print_r(chr($chr)); } echo PHP_EOL; echo 'moniker : '.$length.PHP_EOL; } if ($hlstmfHasMoniker == 1 || $hlstmfMonikerSavedAsStr == 1) { echo 'oleMoniker'.PHP_EOL; } if ($hlstmfHasLocationStr == 1) { echo 'location'.PHP_EOL; } if ($hlstmfHasGUID == 1) { echo 'guid'.PHP_EOL; $sprmCPicLocation += 16; } if ($hlstmfHasCreationTime == 1) { echo 'fileTime'.PHP_EOL; $sprmCPicLocation += 4; } echo 'HYPERLINK'.PHP_EOL; }*/ } else { // Pictures //@link : http://msdn.microsoft.com/en-us/library/dd925458%28v=office.12%29.aspx //@link : http://msdn.microsoft.com/en-us/library/dd926136%28v=office.12%29.aspx // PICF : lcb $sprmCPicLocation += 4; // PICF : cbHeader $sprmCPicLocation += 2; // PICF : mfpf : mm $mfpfMm = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : mfpf : xExt $sprmCPicLocation += 2; // PICF : mfpf : yExt $sprmCPicLocation += 2; // PICF : mfpf : swHMF $sprmCPicLocation += 2; // PICF : innerHeader : grf $sprmCPicLocation += 4; // PICF : innerHeader : padding1 $sprmCPicLocation += 4; // PICF : innerHeader : mmPM $sprmCPicLocation += 2; // PICF : innerHeader : padding2 $sprmCPicLocation += 4; // PICF : picmid : dxaGoal $picmidDxaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : dyaGoal $picmidDyaGoal = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : mx $picmidMx = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : my $picmidMy = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : dxaReserved1 $picmidDxaCropLeft = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : dyaReserved1 $picmidDxaCropTop = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : dxaReserved2 $picmidDxaCropRight = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : dyaReserved2 $picmidDxaCropBottom = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; // PICF : picmid : fReserved $sprmCPicLocation += 1; // PICF : picmid : bpp $sprmCPicLocation += 1; // PICF : picmid : brcTop80 $sprmCPicLocation += 4; // PICF : picmid : brcLeft80 $sprmCPicLocation += 4; // PICF : picmid : brcBottom80 $sprmCPicLocation += 4; // PICF : picmid : brcRight80 $sprmCPicLocation += 4; // PICF : picmid : dxaReserved3 $sprmCPicLocation += 2; // PICF : picmid : dyaReserved3 $sprmCPicLocation += 2; // PICF : cProps $sprmCPicLocation += 2; if ($mfpfMm == 0x66) { // cchPicName $cchPicName = self::getInt1d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 1; // stPicName $stPicName = ''; for ($inc = 0; $inc <= $cchPicName; $inc++) { $chr = self::getInt1d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 1; $stPicName .= chr($chr); } } // picture (OfficeArtInlineSpContainer) // picture : shape $shapeRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 8; if ($shapeRH['recVer'] == 0xf && $shapeRH['recInstance'] == 0x0 && $shapeRH['recType'] == 0xf004) { $sprmCPicLocation += $shapeRH['recLen']; } // picture : rgfb //@link : http://msdn.microsoft.com/en-us/library/dd950560%28v=office.12%29.aspx $fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); while ($fileBlockRH['recType'] == 0xf007 || $fileBlockRH['recType'] >= 0xf018 && $fileBlockRH['recType'] <= 0xf117) { $sprmCPicLocation += 8; switch ($fileBlockRH['recType']) { // OfficeArtFBSE //@link : http://msdn.microsoft.com/en-us/library/dd944923%28v=office.12%29.aspx case 0xf007: // btWin32 $sprmCPicLocation += 1; // btMacOS $sprmCPicLocation += 1; // rgbUid $sprmCPicLocation += 16; // tag $sprmCPicLocation += 2; // size $sprmCPicLocation += 4; // cRef $sprmCPicLocation += 4; // foDelay $sprmCPicLocation += 4; // unused1 $sprmCPicLocation += 1; // cbName $cbName = self::getInt1d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 1; // unused2 $sprmCPicLocation += 1; // unused3 $sprmCPicLocation += 1; // nameData if ($cbName > 0) { $nameData = ''; for ($inc = 0; $inc <= $cbName / 2; $inc++) { $chr = self::getInt2d($this->dataData, $sprmCPicLocation); $sprmCPicLocation += 2; $nameData .= chr($chr); } } // embeddedBlip //@link : http://msdn.microsoft.com/en-us/library/dd910081%28v=office.12%29.aspx $embeddedBlipRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); switch ($embeddedBlipRH['recType']) { case self::OFFICEARTBLIPJPG: case self::OFFICEARTBLIPJPEG: if (!isset($oStylePrl->image)) { $oStylePrl->image = array(); } $sprmCPicLocation += 8; // embeddedBlip : rgbUid1 $sprmCPicLocation += 16; if ($embeddedBlipRH['recInstance'] == 0x6e1) { // rgbUid2 $sprmCPicLocation += 16; } // embeddedBlip : tag $sprmCPicLocation += 1; // embeddedBlip : BLIPFileData $oStylePrl->image['data'] = substr($this->dataData, $sprmCPicLocation, $embeddedBlipRH['recLen']); $oStylePrl->image['format'] = 'jpg'; // Image Size $iCropWidth = $picmidDxaGoal - ($picmidDxaCropLeft + $picmidDxaCropRight); $iCropHeight = $picmidDyaGoal - ($picmidDxaCropTop + $picmidDxaCropBottom); if (!$iCropWidth) { $iCropWidth = 1; } if (!$iCropHeight) { $iCropHeight = 1; } $oStylePrl->image['width'] = Drawing::twipsToPixels($iCropWidth * $picmidMx / 1000); $oStylePrl->image['height'] = Drawing::twipsToPixels($iCropHeight * $picmidMy / 1000); $sprmCPicLocation += $embeddedBlipRH['recLen']; break; default: // print_r(dechex($embeddedBlipRH['recType'])); } break; } $fileBlockRH = $this->loadRecordHeader($this->dataData, $sprmCPicLocation); } } } $oStylePrl->length = $pos - $posStart; return $oStylePrl; }
/** */ public function testTwips() { $value = rand(1, 100); // Centimeters $this->assertEquals(0, Drawing::centimetersToTwips()); $this->assertEquals($value * 566.928, Drawing::centimetersToTwips($value)); $this->assertEquals(0, Drawing::twipsToCentimeters()); $this->assertEquals($value / 566.928, Drawing::twipsToCentimeters($value)); // Inches $this->assertEquals(0, Drawing::inchesToTwips()); $this->assertEquals($value * 1440, Drawing::inchesToTwips($value)); $this->assertEquals(0, Drawing::twipsToInches()); $this->assertEquals($value / 1440, Drawing::twipsToInches($value)); // Pixels $this->assertEquals(0, Drawing::twipsToPixels()); $this->assertEquals(round($value / 15.873984), Drawing::twipsToPixels($value)); }