Example #1
0
////////////////////////////////////////////////////////////////////////////////
// EndProcessingInstruction
//
bool XmlWriter::EndProcessingInstruction()
{
    mbSimpleElement = false;

    switch (mnState) {
        case kStateProcessingInstruction:
            mnState = kStateChars;
            return WriteText( "?>", 2 );

        case kStateElement:
            EA_FAIL_MESSAGE( "XmlWriter: Cannot close processing instruction because we are in an element." );
            mnState = kStateChars;
            return false;

        case kStateChars:
            EA_FAIL_MESSAGE( "XmlWriter: Cannot close processing instruction because it was already closed." );
            mnState = kStateChars;
            return false;

        case kStateCDATA:
            EA_FAIL_MESSAGE( "XmlWriter: Cannot close processing instruction because we are in a CDATA section." );
            return false;
    }

    return false;
}
Example #2
0
bool XmlWriter::WriteCDATA( const char16_t *psCharData, size_t nCount )
{
    // Verify that there is no "]]>" sequence in the input text.
    #if (defined(EA_TRACE_ENABLED) && EA_TRACE_ENABLED) || defined(EA_ASSERT_ENABLED)  // If the EATrace or EAAssert packages are configured to enable assertions...
        // We can't use a built-in function such as strstr because our text might not
        // be 0-terminated. We could however use the STL find algorithm.
        const size_t nStrlen        = ((nCount == kSizeTypeNull) ? wcslen(psCharData) : nCount);
        const size_t nStrlenToCheck = ((nStrlen > 2) ? (nStrlen - 2) : 0);

        for(size_t i = 0; i < nStrlenToCheck; ++i)
        {
            if((psCharData[i] == ']') && (psCharData[i + 1] == ']') && (psCharData[i + 2] == '>'))
            {
                EA_FAIL_MESSAGE("XmlWriter: User-specified CDATA has embedded ]]> sequence.");
                break;  
            }
        }
    #endif

    if (mnState != kStateCDATA) {
        if (!CloseCurrentElement())
            return false;
        if (!WriteText( "<![CDATA[", 9 ))
            return false;

        mnState = kStateCDATA;
    }

    return WriteText( psCharData, nCount );
}
Example #3
0
////////////////////////////////////////////////////////////////////////////////
// EndElement
//
bool XmlWriter::EndElement( const char *psElementName ) {
    EA_ASSERT(mnIndentLevel > 0);

    mnIndentLevel--;

    switch (mnState) {
        case kStateProcessingInstruction:
            EA_FAIL_MESSAGE( "XmlWriter: Cannot close element because we are in a processing instruction." );
            return false;

        case kStateElement:
            mnState = kStateChars;
            mbSimpleElement = false;
            return WriteText( "/>", 2 );

        case kStateCDATA:
            CloseCurrentElement();
            // Fall through.

        case kStateChars:
            if (!mbSimpleElement ) { // If the current element has no child elements...
                if (!WriteIndent() ) // Then write an indent before writing the element end.
                    return false;
            }

            mbSimpleElement = false;

            return ( WriteText( "</", 2 )
                    && WriteText( psElementName, kSizeTypeNull )
                    && WriteText( ">", 1 ) );
    }

    return false;
}
Example #4
0
///////////////////////////////////////////////////////////////////////////////
// AppendHangulCharCluster
//
eastl_size_t Typesetter::AppendHangulCharCluster(eastl_size_t iCharBegin, eastl_size_t charCount, 
                                                 const Char* pCharCluster, eastl_size_t clusterSize, int clusterType)
{
    // The 'iCharBegin' argument refers to the position of pCharCluster in mLineLayout.mCharArray. 
    // There is a possibility that pCharCluster doesn't point to mLineLayout.mCharArray[iCharBegin],
    // as we may be doing some kind of implicit substitution. Thus we have pCharCluster 
    // as an explicit parameter.

    const AnalysisInfo* const pAnalysisInfo = &mLineLayout.mAnalysisInfoArray[iCharBegin];
    GlyphId                   pGlyphIdArray[kMaxHangulGlyphClusterSize];
    eastl_size_t              glyphCount = 0;
    eastl_size_t              charsEaten = 0; // Number of chars read from pCharCluster.
    
    EA_ASSERT(clusterSize && ((iCharBegin + charCount) <= mLineLayout.mCharArray.size()));
    #ifdef EA_DEBUG
        memset(pGlyphIdArray, 0, sizeof(pGlyphIdArray));
    #endif

    switch(clusterType)
    {
        case kHangulClusterTypeJamo:
        {
            const Char cTone       = pCharCluster[clusterSize - 1];
            const bool bAppendTone = IsTone(cTone);
            int        syllableLength;
            Char       c;

            if(bAppendTone)
                --clusterSize; // Pretend it isn't there for now.

            if((clusterSize >= 3) && IsLSyllable(pCharCluster[0]) && IsVSyllable(pCharCluster[1]) && IsTSyllable(pCharCluster[2]))
                syllableLength = 3;
            else if((clusterSize >= 2) && IsLSyllable(pCharCluster[0]) && IsVSyllable(pCharCluster[1]))
                syllableLength = 2;
            else
                syllableLength = 0;

            if(syllableLength)
            {
                if(syllableLength == 3)
                    c = GetSyllableLVT(pCharCluster[0], pCharCluster[1], pCharCluster[2]);
                else
                    c = GetSyllableLV(pCharCluster[0], pCharCluster[1]);

                GetGlyphsForChar(&c, 1, pAnalysisInfo, pGlyphIdArray + glyphCount, glyphCount);

                charsEaten += syllableLength;
            }

            // If there are any other chars to shape (usually there aren't), just append them.
            for(eastl_size_t i = charsEaten; i < clusterSize; i += charsEaten)
            {
                if((pCharCluster[i] != kJamoLFiller) &&  // Outright ignore filler chars.
                   (pCharCluster[i] != kJamoVFiller))
                {
                    // The font selection in use had better have the desired glyphs or 
                    // else we will be displaying a lot of square boxes on the screen.
                    charsEaten += GetGlyphsForChar(pCharCluster + i, clusterSize - i, pAnalysisInfo, 
                                                    pGlyphIdArray + glyphCount, glyphCount);
                }
                else
                    ++charsEaten;
            }

            EA_ASSERT(glyphCount > 0); // Do we have just a single Jamo filler char?
            if(glyphCount == 0)
            {
                const Char cHangulFiller = 0x3164; // 0x3164 is the Hangul filler char. It's just blank like a space char.

                charsEaten += GetGlyphsForChar(&cHangulFiller, 1, pAnalysisInfo, pGlyphIdArray + glyphCount, glyphCount, L"\x25CB _o", 4);
            }

            if(bAppendTone)
            {
                charsEaten += GetGlyphsForChar(&cTone, 1, pAnalysisInfo, pGlyphIdArray + glyphCount, glyphCount, 
                                                 (cTone == kHangulTone1) ? L"\x00b7" : L":", 1);
            }

            break;
        }

        case kHangulClusterTypeTone: // Standalone tone with no preceeding base glyph.
        {
            // We prepend a character which is a circle implemented with dotted lines. 
            // It is the Unicode standard for generic base character to be represented
            // by such a dotted circle. It is a defacto standard that we prepend such 
            // a character when none is provided. It makes the text look more sensible.
            const Char cDottedCircle = 0x25CC;

            for(eastl_size_t i = charsEaten; i < clusterSize; i += charsEaten) // clusterSize should usually (always?) be just one.
            {
                // Note that in practice we're going to need to put the tone to the 
                // left of the glyph, though here we stuff it afterwards. What we have
                // here won't do. Also, the tone chars ideally have a zero advance,
                // but the fallbacks definitely do not. 

                // We draw the tone, using fallback characters if the tone char isn't present.
                charsEaten += GetGlyphsForChar(pCharCluster + i, clusterSize - i, pAnalysisInfo, 
                                               pGlyphIdArray + glyphCount, glyphCount, 
                                               (pCharCluster[i] == kHangulTone1) ? L"\x00b7" : L":", 1);

                // Append a dotted-circle glyph, with a fallback of some other glyphs.
                GetGlyphsForChar(&cDottedCircle, 1, pAnalysisInfo, 
                                  pGlyphIdArray + glyphCount, glyphCount, L"\x25CB _o", 4);
            }

            break;
        }

        case kHangulClusterTypeUnicode:
        {
            // We just convert the Unicode Chars to glyphs.
            for(eastl_size_t i = charsEaten; i < clusterSize; i += charsEaten)
            {
                charsEaten += GetGlyphsForChar(pCharCluster + i, clusterSize - i, pAnalysisInfo, 
                                                pGlyphIdArray + glyphCount, glyphCount);
            }
            break;
        }

        default:
            EA_FAIL_MESSAGE("Typesetter::AppendHangulCharCluster: Unknown cluster type.");
            break;
    }

    // Assert that all of the passed in cluster was processed.
    EA_ASSERT(charsEaten == clusterSize);

    // We use the general glyph append function.
    AppendGeneralGlyphCluster(iCharBegin, charCount, pCharCluster, charsEaten, pGlyphIdArray, glyphCount, pAnalysisInfo->mnBidiLevel);

    // We use the general glyph placement function.
    PlaceGeneralGlyphCluster(iCharBegin, charsEaten);

    // As it stands now, all chars must result in at least one glyph, though that 
    // one glyph could be a zero-width space character. Note that the render code
    // has the opportunity to remove such a "no-op" instruction from the display list.
    EA_ASSERT(glyphCount > 0);
    return glyphCount;
}