//--------------------------------------------------------------------//
        //                                                        M e t h o d //
        // w r i t e C h a r                                                  //
        //--------------------------------------------------------------------//
        //                                                                    //
        // Write PCL format character data:                                   //
        //                                                                    //
        //    <esc>*c#E         Character Code:                               //
        //                      #      = decimal character code               //
        //    <esc>(s#W[data]   Character Descriptor / Data                   //
        //                      #      = number of bytes of data              //
        //                      [data] = font character data                  //
        //                                                                    //
        // Note that the function may be called recursively, if a glyph is    //
        // composite (i.e. made up of two or more components).                //
        //                                                                    //
        //--------------------------------------------------------------------//

        private void writeChar(UInt16 charCode,
                               UInt16 codepoint,
                               UInt16 glyphId,
                               UInt16 depth,
                               UInt16 maxGlyphId)
        {
            UInt16 glyphWidth    = 0,
                   glyphHeight   = 0,
                   charBlockSize = 0,
                   charDataSize  = 0;

            Int16 glyphLSB = 0,
                  glyphTSB = 0;

            UInt32 glyphOffset = 0,
                   glyphLength = 0;

            Boolean glyphComposite = false;

            Byte checksumMod256;

            Byte[] charHddr      = new Byte[cSizeCharHddr];
            Byte[] charGlyphHddr = new Byte[cSizeCharGlyphHddr];
            Byte[] charTrail     = new Byte[cSizeCharTrail];
            Byte[] glyphData     = null;

            //----------------------------------------------------------------//
            //                                                                //
            // Mark glyph as used.                                            //
            // These markers are checked for composite sub-glyphs.            //
            //                                                                //
            //----------------------------------------------------------------//

            _ttfHandler.glyphReferencedMark(glyphId);

            //----------------------------------------------------------------//
            //                                                                //
            // Get glyph details:                                             //
            //    advance width.                                              //
            //    left-side bearing.                                          //
            //    offset and length of the glyph data in the TTF file.        //
            //                                                                //
            //----------------------------------------------------------------//

            _ttfHandler.getGlyphData(glyphId,
                                     ref glyphWidth,
                                     ref glyphHeight,   // not used here
                                     ref glyphLSB,
                                     ref glyphTSB,      // not used here
                                     ref glyphOffset,
                                     ref glyphLength,
                                     ref glyphComposite);

            //----------------------------------------------------------------//
            //                                                                //
            // Log character details.                                         //
            //                                                                //
            //----------------------------------------------------------------//

            ToolSoftFontGenLog.logCharDetails(_tableLog,
                                              false,
                                              glyphComposite,
                                              charCode,
                                              codepoint,
                                              glyphId,
                                              depth,
                                              glyphWidth,
                                              glyphHeight,
                                              glyphLSB,
                                              glyphTSB,
                                              glyphOffset,
                                              glyphLength);

            //----------------------------------------------------------------//
            //                                                                //
            // Calculate total size of header.                                //
            //                                                                //
            // Write PCL 'Character Code' escape sequence.                    //
            // Write PCL 'Character Definition' escape sequence.              //
            //                                                                //
            //----------------------------------------------------------------//

            charBlockSize = (UInt16)(cSizeCharHddr + cSizeCharGlyphHddr +
                                     glyphLength + cSizeCharTrail);

            PCLWriter.charDownloadCode(_binWriter, charCode);

            PCLWriter.charDownloadDesc(_binWriter, charBlockSize);

            //----------------------------------------------------------------//
            //                                                                //
            // Write Format 15 header.                                        //
            // This character format is used with both Format 15 and          //
            // Format 16 font headers.                                        //
            //                                                                //
            //----------------------------------------------------------------//

            charHddr[0] = 15;                   // Format = 15
            charHddr[1] = 0;                    // Continuation = false
            charHddr[2] = 2;                    // Descriptor size
            charHddr[3] = 15;                   // Class = 15

            _baseHandler.writeBuffer(cSizeCharHddr, charHddr);

            //----------------------------------------------------------------//
            //                                                                //
            // Write glyph header.                                            //
            // This counts towards the checksum recorded in the trailer.      //
            //                                                                //
            //----------------------------------------------------------------//

            checksumMod256 = 0;

            charDataSize = (UInt16)(cSizeCharGlyphHddr + glyphLength);

            charGlyphHddr[0] = msByte(charDataSize);
            charGlyphHddr[1] = lsByte(charDataSize);
            charGlyphHddr[2] = msByte(glyphId);
            charGlyphHddr[3] = lsByte(glyphId);

            _baseHandler.writeCharFragment(cSizeCharGlyphHddr,
                                           charGlyphHddr,
                                           ref checksumMod256);

            //----------------------------------------------------------------//
            //                                                                //
            // Write TrueType glyph data (copied from TrueType font file).    //
            // The data is read into a dynamically allocated buffer because:  //
            //    -  This avoids the complication of having a fixed-length    //
            //       buffer and a loop to read the data in chunks.            //
            //    -  Not having a static buffer allows the function to be     //
            //       called recursively.                                      //
            //                                                                //
            //----------------------------------------------------------------//

            if (glyphLength > 0)
            {
                Boolean flagOK = true;

                glyphData = new Byte[glyphLength];

                flagOK = _ttfHandler.readByteArray((Int32)glyphOffset,
                                                   (Int32)glyphLength,
                                                   ref glyphData);
                // TODO: what if flagOK = true (i.e. read fails?

                _baseHandler.writeCharFragment((Int32)glyphLength,
                                               glyphData,
                                               ref checksumMod256);
            }

            //----------------------------------------------------------------//
            //                                                                //
            // Write trailer (Reserved byte and Checksum byte).               //
            //                                                                //
            //----------------------------------------------------------------//

            checksumMod256 = (Byte)((256 - checksumMod256) % 256);

            charTrail[0] = 0;                   // Reserved byte
            charTrail[1] = checksumMod256;      // Checksum byte

            _baseHandler.writeBuffer(cSizeCharTrail, charTrail);

            //----------------------------------------------------------------//
            //                                                                //
            // Handler composite glyphs.                                      //
            //                                                                //
            //----------------------------------------------------------------//

            if (glyphComposite)
            {
                // if we move this to TTFHandler, do the maxGlyphId check there instead

                Int32 indBuf;

                UInt16 glyphCompFlags,
                       glyphCompId;

                indBuf = 10; // point to first set of component data //

                do
                {
                    glyphCompFlags = (UInt16)((glyphData[indBuf] << 8) +
                                              glyphData[indBuf + 1]);
                    glyphCompId = (UInt16)((glyphData[indBuf + 2] << 8) +
                                           glyphData[indBuf + 3]);

                    if (glyphCompId > maxGlyphId)
                    {
                        // flagOK = false;

                        ToolSoftFontGenLog.logError(
                            _tableLog, MessageBoxImage.Error,
                            "Composite glyph identifier " + glyphCompId +
                            " > maximum of " + maxGlyphId);
                    }
                    else
                    {
                        if (_ttfHandler.glyphReferencedCheck(glyphCompId))
                        {
                            ToolSoftFontGenLog.logCharDetails(
                                _tableLog,
                                true,
                                _ttfHandler.glyphCompositeCheck(glyphCompId),
                                0,
                                0,
                                glyphCompId,
                                depth,
                                0,
                                0,
                                0,
                                0,
                                0,
                                0);
                        }
                        else
                        {
                            // flagOK =
                            writeChar(0xffff, 0, glyphCompId,
                                      (UInt16)(depth + 1), maxGlyphId);
                        }
                    }

                    // if flagOK
                    {
                        indBuf += 4;

                        if ((glyphCompFlags &
                             ToolSoftFontGenTTF.mask_glyf_compFlag_ARG_1_AND_2_ARE_WORDS) != 0)
                        {
                            indBuf += 4;
                        }
                        else
                        {
                            indBuf += 2;
                        }

                        if ((glyphCompFlags &
                             ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_A_TWO_BY_TWO) != 0)
                        {
                            indBuf += 8;
                        }
                        else if ((glyphCompFlags &
                                  ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_AN_X_AND_Y_SCALE) != 0)
                        {
                            indBuf += 4;
                        }
                        else if ((glyphCompFlags &
                                  ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_A_SCALE) != 0)
                        {
                            indBuf += 2;
                        }
                    }
                } while ((glyphCompFlags &
                          ToolSoftFontGenTTF.mask_glyf_compFlag_MORE_COMPONENTS) != 0);
            }
        }
Пример #2
0
        //--------------------------------------------------------------------//
        //                                                        M e t h o d //
        // w r i t e C h a r                                                  //
        //--------------------------------------------------------------------//
        //                                                                    //
        // Write PCL XL format character:                                     //
        //                                                                    //
        //  ReadChar operator                                                 //
        //  Embedded Data header                                              //
        //  character data                                                    //
        //                                                                    //
        // Note that the function may be called recursively, if a glyph is    //
        // composite (i.e. made up of two or more components).                //
        //                                                                    //
        // Unbound fonts: write Class 0 characters; these rely on the GT      //
        //                              GT segment in the font header         //
        //                              containing the 'hhea' and 'htmx'      //
        //                              tables.                               //
        // Bound fonts:   write Class 1 characters, which include advance     //
        //                              width and LSB in each character       //
        //                              header.                               //
        //                                                                    //
        //--------------------------------------------------------------------//

        private void writeChar(Int32 charClass,
                               UInt16 charCode,
                               UInt16 codepoint,
                               UInt16 glyphId,
                               UInt16 depth,
                               UInt16 maxGlyphId)
        {
            UInt16 glyphWidth   = 0,
                   glyphHeight  = 0,
                   charDataSize = 0,
                   charSize,
                   hddrSize;

            Int16 glyphLSB = 0,
                  glyphTSB = 0;

            UInt32 glyphOffset = 0,
                   glyphLength = 0;

            Boolean glyphComposite = false;

            Byte checksumMod256 = 0;

            Byte[] glyphData = null;

            Byte[] charHddr;

            if (charClass == 1)
            {
                hddrSize = cSizeCharHddrClass1;
            }
            else if (charClass == 2)
            {
                hddrSize = cSizeCharHddrClass2;
            }
            else
            {
                hddrSize = cSizeCharHddrClass0;
            }

            charHddr = new Byte[hddrSize];

            //----------------------------------------------------------------//
            //                                                                //
            // Mark glyph as used.                                            //
            // These markers are checked for composite sub-glyphs.            //
            //                                                                //
            //----------------------------------------------------------------//

            _ttfHandler.glyphReferencedMark(glyphId);

            //----------------------------------------------------------------//
            //                                                                //
            // Get glyph details:                                             //
            //    advance width.                                              //
            //    left-side bearing.                                          //
            //    offset and length of the glyph data in the TTF file.        //
            //                                                                //
            //----------------------------------------------------------------//

            _ttfHandler.getGlyphData(glyphId,
                                     ref glyphWidth,
                                     ref glyphHeight,   // not used
                                     ref glyphLSB,
                                     ref glyphTSB,
                                     ref glyphOffset,
                                     ref glyphLength,
                                     ref glyphComposite);

            //----------------------------------------------------------------//
            //                                                                //
            // Log character details.                                         //
            //                                                                //
            //----------------------------------------------------------------//

            ToolSoftFontGenLog.logCharDetails(_tableLog,
                                              false,
                                              glyphComposite,
                                              charCode,
                                              codepoint,
                                              glyphId,
                                              depth,
                                              glyphWidth,
                                              glyphHeight,
                                              glyphLSB,
                                              glyphTSB,
                                              glyphOffset,
                                              glyphLength);

            //----------------------------------------------------------------//
            //                                                                //
            // Calculate total size of header.                                //
            //                                                                //
            // Write ReadChar operator and associated Attribute List.         //
            // Write Embedded Data Introduction sequence.                     //
            //                                                                //
            //----------------------------------------------------------------//

            charDataSize = (UInt16)(hddrSize + glyphLength);
            charSize     = (UInt16)(charDataSize - 2);

            PCLXLWriter.fontCharRead(_binWriter, false,
                                     charCode, charDataSize);

            PCLXLWriter.embedDataIntro(_binWriter,
                                       false,
                                       charDataSize);
            if (charClass == 0)
            {
                //------------------------------------------------------------//
                //                                                            //
                // Write Format 1 Class 0 header.                             //
                //                                                            //
                //------------------------------------------------------------//

                charHddr [0] = 1;                   // Format
                charHddr [1] = 0;                   // Class
                charHddr [2] = msByte(charSize);    // CharSize MSB
                charHddr [3] = lsByte(charSize);    // CharSize LSB
                charHddr [4] = msByte(glyphId);     // Glyph Id MSB
                charHddr [5] = lsByte(glyphId);     // Glyph Id LSB
            }
            else if (charClass == 1)
            {
                //------------------------------------------------------------//
                //                                                            //
                // Write Format 1 Class 1 header.                             //
                //                                                            //
                //------------------------------------------------------------//

                charHddr [0] = 1;                        // Format
                charHddr [1] = 1;                        // Class
                charHddr [2] = msByte(charSize);         // CharSize MSB
                charHddr [3] = lsByte(charSize);         // CharSize LSB
                charHddr [4] = msByte((UInt16)glyphLSB); // Glyph Left Side Bearing
                charHddr [5] = lsByte((UInt16)glyphLSB); // Glyph Left Side Bearing
                charHddr [6] = msByte(glyphWidth);       // Glyph Width MSB
                charHddr [7] = lsByte(glyphWidth);       // Glyph Width LSB
                charHddr [8] = msByte(glyphId);          // Glyph Id MSB
                charHddr [9] = lsByte(glyphId);          // Glyph Id LSB
            }
            else // charClass == 2
            {
                //------------------------------------------------------------//
                //                                                            //
                // Write Format 1 Class 2 header.                             //
                //                                                            //
                //------------------------------------------------------------//

                charHddr [0]  = 1;                        // Format
                charHddr [1]  = 2;                        // Class
                charHddr [2]  = msByte(charSize);         // CharSize MSB
                charHddr [3]  = lsByte(charSize);         // CharSize LSB
                charHddr [4]  = msByte((UInt16)glyphLSB); // Glyph Left Side Bearing
                charHddr [5]  = lsByte((UInt16)glyphLSB); // Glyph Left Side Bearing
                charHddr [6]  = msByte(glyphWidth);       // Glyph Width MSB
                charHddr [7]  = lsByte(glyphWidth);       // Glyph Width LSB
                charHddr [8]  = msByte((UInt16)glyphTSB); // Glyph Top Side Bearing
                charHddr [9]  = lsByte((UInt16)glyphTSB); // Glyph Top Side Bearing
                charHddr [10] = msByte(glyphId);          // Glyph Id MSB
                charHddr [11] = lsByte(glyphId);          // Glyph Id LSB
            }

            _baseHandler.writeBuffer(hddrSize, charHddr);

            //----------------------------------------------------------------//
            //                                                                //
            // Write TrueType glyph data (copied from TrueType font file).    //
            // The data is read into a dynamically allocated buffer because:  //
            //    -  This avoids the complication of having a fixed-length    //
            //       buffer and a loop to read the data in chunks.            //
            //    -  Not having a static buffer allows the function to be     //
            //       called recursively.                                      //
            //                                                                //
            //----------------------------------------------------------------//

            if (glyphLength > 0)
            {
                Boolean flagOK = true;

                glyphData = new Byte[glyphLength];

                flagOK = _ttfHandler.readByteArray((Int32)glyphOffset,
                                                   (Int32)glyphLength,
                                                   ref glyphData);
                // TODO: what if flagOK = true (i.e. read fails?

                _baseHandler.writeCharFragment((Int32)glyphLength,
                                               glyphData,
                                               ref checksumMod256);
            }

            //----------------------------------------------------------------//
            //                                                                //
            // Handler composite glyphs.                                      //
            //                                                                //
            //----------------------------------------------------------------//

            if (glyphComposite)
            {
                // if we move this to TTFHandler, do the maxGlyphId check there instead

                Int32 indBuf;

                UInt16 glyphCompFlags,
                       glyphCompId;

                indBuf = 10; // point to first set of component data //

                do
                {
                    glyphCompFlags = (UInt16)((glyphData[indBuf] << 8) +
                                              glyphData[indBuf + 1]);
                    glyphCompId = (UInt16)((glyphData[indBuf + 2] << 8) +
                                           glyphData[indBuf + 3]);

                    if (glyphCompId > maxGlyphId)
                    {
                        // flagOK = false;

                        ToolSoftFontGenLog.logError(
                            _tableLog, MessageBoxImage.Error,
                            "Composite glyph identifier " + glyphCompId +
                            " > maximum of " + maxGlyphId);
                    }
                    else
                    {
                        if (_ttfHandler.glyphReferencedCheck(glyphCompId))
                        {
                            ToolSoftFontGenLog.logCharDetails(
                                _tableLog,
                                true,
                                _ttfHandler.glyphCompositeCheck(glyphCompId),
                                0,
                                0,
                                glyphCompId,
                                depth,
                                0,
                                0,
                                0,
                                0,
                                0,
                                0);
                        }
                        else
                        {
                            // flagOK =
                            writeChar(charClass, 0xffff, 0, glyphCompId,
                                      (UInt16)(depth + 1), maxGlyphId);
                        }
                    }

                    // if flagOK
                    {
                        indBuf += 4;

                        if ((glyphCompFlags &
                             ToolSoftFontGenTTF.mask_glyf_compFlag_ARG_1_AND_2_ARE_WORDS) != 0)
                        {
                            indBuf += 4;
                        }
                        else
                        {
                            indBuf += 2;
                        }

                        if ((glyphCompFlags &
                             ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_A_TWO_BY_TWO) != 0)
                        {
                            indBuf += 8;
                        }
                        else if ((glyphCompFlags &
                                  ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_AN_X_AND_Y_SCALE) != 0)
                        {
                            indBuf += 4;
                        }
                        else if ((glyphCompFlags &
                                  ToolSoftFontGenTTF.mask_glyf_compFlag_WE_HAVE_A_SCALE) != 0)
                        {
                            indBuf += 2;
                        }
                    }
                } while ((glyphCompFlags &
                          ToolSoftFontGenTTF.mask_glyf_compFlag_MORE_COMPONENTS) != 0);
            }
        }