// File: /workspace/github_cpp_makefile_star2_O3/rurban[P]dgnlib/dgnwrite.cpp
// Function: DGNCreateTextElem
DGNElemCore *
DGNCreateTextElem( DGNHandle hDGN, const char *pszText, 
                   int nFontId, int nJustification, 
                   double dfLengthMult, double dfHeightMult, 
                   double dfRotation, int *panQuaternion,
                   double dfOriginX, double dfOriginY, double dfOriginZ )

{
    DGNElemText *psText;
    DGNElemCore *psCore;
    DGNInfo *psDGN = (DGNInfo *) hDGN;
    DGNPoint sMin, sMax, sLowLeft, sLowRight, sUpLeft, sUpRight;
    GInt32 nIntValue, nBase;
    double length, height, diagonal;

    DGNLoadTCB( hDGN );

/* -------------------------------------------------------------------- */
/*      Allocate element.                                               */
/* -------------------------------------------------------------------- */
    psText = (DGNElemText *) 
        CPLCalloc( sizeof(DGNElemText)+strlen(pszText), 1 );
    psCore = &(psText->core);

    DGNInitializeElemCore( hDGN, psCore );
    psCore->stype = DGNST_TEXT;
    psCore->type = DGNT_TEXT;

/* -------------------------------------------------------------------- */
/*      Set arc specific information in the structure.                  */
/* -------------------------------------------------------------------- */
    psText->font_id = nFontId;
    psText->justification = nJustification;
    psText->length_mult = dfLengthMult;
    psText->height_mult = dfHeightMult;
    psText->rotation = dfRotation;
    psText->origin.x = dfOriginX;
    psText->origin.y = dfOriginY;
    psText->origin.z = dfOriginZ;
    strcpy( psText->string, pszText );

/* -------------------------------------------------------------------- */
/*      Setup Raw data for the text specific portion.                   */
/* -------------------------------------------------------------------- */
    if( psDGN->dimension == 2 )
        psCore->raw_bytes = 60 + strlen(pszText);
    else
        psCore->raw_bytes = 76 + strlen(pszText);

    psCore->raw_bytes += (psCore->raw_bytes % 2);
    psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);

    psCore->raw_data[36] = (unsigned char) nFontId;
    psCore->raw_data[37] = (unsigned char) nJustification;

    nIntValue = (int) (dfLengthMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
    DGN_WRITE_INT32( nIntValue, psCore->raw_data + 38 );
    
    nIntValue = (int) (dfHeightMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
    DGN_WRITE_INT32( nIntValue, psCore->raw_data + 42 );

    if( psDGN->dimension == 2 )
    {
        nIntValue = (int) (dfRotation * 360000.0);
        DGN_WRITE_INT32( nIntValue, psCore->raw_data + 46 );

        DGNInverseTransformPointToInt( psDGN, &(psText->origin), 
                                       psCore->raw_data + 50 );

        nBase = 58;
    }
    else
    {
        int anQuaternion[4];

        if( panQuaternion == NULL )
            DGNRotationToQuaternion( dfRotation, anQuaternion );
        else
            memcpy( anQuaternion, panQuaternion, sizeof(int) * 4 );

        DGN_WRITE_INT32( anQuaternion[0], psCore->raw_data + 46 );
        DGN_WRITE_INT32( anQuaternion[1], psCore->raw_data + 50 );
        DGN_WRITE_INT32( anQuaternion[2], psCore->raw_data + 54 );
        DGN_WRITE_INT32( anQuaternion[3], psCore->raw_data + 58 );

        DGNInverseTransformPointToInt( psDGN, &(psText->origin), 
                                       psCore->raw_data + 62 );
        nBase = 74;
    }

    psCore->raw_data[nBase] = (unsigned char) strlen(pszText);
    psCore->raw_data[nBase+1] = 0; /* edflds? */
    memcpy( psCore->raw_data + nBase+2, pszText, strlen(pszText) );
    
/* -------------------------------------------------------------------- */
/*      Set the core raw data, including the bounds.                    */
/*                                                                      */
/*      Code contributed by Mart Kelder.                                */
/* -------------------------------------------------------------------- */
    DGNUpdateElemCoreExtended( hDGN, psCore );

    //calculate bounds if rotation is 0
    sMin.x = dfOriginX;
    sMin.y = dfOriginY;
    sMin.z = 0.0;
    sMax.x = dfOriginX + dfLengthMult * strlen(pszText);
    sMax.y = dfOriginY + dfHeightMult;
    sMax.z = 0.0;

    //calculate rotated bounding box coordinates
    length = sMax.x-sMin.x;
    height = sMax.y-sMin.y;
    diagonal=sqrt(length*length+height*height);
    sLowLeft.x=sMin.x;
    sLowLeft.y=sMin.y;
    sLowRight.x=sMin.x+cos(psText->rotation*PI/180.0)*length;
    sLowRight.y=sMin.y+sin(psText->rotation*PI/180.0)*length;
    sUpRight.x=sMin.x+cos((psText->rotation*PI/180.0)+atan(height/length))*diagonal;
    sUpRight.y=sMin.y+sin((psText->rotation*PI/180.0)+atan(height/length))*diagonal;
    sUpLeft.x=sMin.x+cos((psText->rotation+90.0)*PI/180.0)*height;
    sUpLeft.y=sMin.y+sin((psText->rotation+90.0)*PI/180.0)*height;

    //calculate new values for bounding box
    sMin.x=MIN(sLowLeft.x,MIN(sLowRight.x,MIN(sUpLeft.x,sUpRight.x)));
    sMin.y=MIN(sLowLeft.y,MIN(sLowRight.y,MIN(sUpLeft.y,sUpRight.y)));
    sMax.x=MAX(sLowLeft.x,MAX(sLowRight.x,MAX(sUpLeft.x,sUpRight.x)));
    sMax.y=MAX(sLowLeft.y,MAX(sLowRight.y,MAX(sUpLeft.y,sUpRight.y)));
    sMin.x = dfOriginX - dfLengthMult * strlen(pszText);
    sMin.y = dfOriginY - dfHeightMult;
    sMin.z = 0.0;
    sMax.x = dfOriginX + dfLengthMult * strlen(pszText);
    sMax.y = dfOriginY + dfHeightMult;
    sMax.z = 0.0;

    DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
    
    return psCore;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movsd %xmm5, 0x10(%rsp)
movsd %xmm4, 0x30(%rsp)
movsd %xmm3, 0x38(%rsp)
movq %r8, 0x58(%rsp)
movsd %xmm2, 0x8(%rsp)
movsd %xmm1, 0x28(%rsp)
movsd %xmm0, 0x20(%rsp)
movl %ecx, %ebp
movl %edx, %r12d
movq %rsi, %r15
movq %rdi, %rbx
callq 0xae76
movq %r15, %rdi
callq 0x2120
leaq 0x90(%rax), %rdi
movl $0x1, %esi
callq 0x2d20
movq %rax, %r14
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movups %xmm0, 0x20(%rax)
movups %xmm0, 0x30(%rax)
movups %xmm0, 0x40(%rax)
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movabsq $0x6ffffffff, %rax      # imm = 0x6FFFFFFFF
movq %rax, 0x8(%r14)
movl $0x11, 0x14(%r14)
movl %r12d, 0x50(%r14)
movl %ebp, 0x54(%r14)
movsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x58(%r14)
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x60(%r14)
movsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x68(%r14)
leaq 0x70(%r14), %rax
movq %rax, 0x18(%rsp)
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x70(%r14)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x78(%r14)
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x80(%r14)
leaq 0x88(%r14), %rdi
movq %r15, %rsi
callq 0x22a0
xorl %r13d, %r13d
cmpl $0x2, 0x20018(%rbx)
setne %r13b
movq %r15, %rdi
callq 0x2120
shll $0x4, %r13d
leal (%rax,%r13), %ecx
addl %r13d, %eax
addl $0x3c, %eax
movl %eax, %edx
shrl $0x1f, %edx
addl %ecx, %edx
addl $0x3c, %edx
andl $-0x2, %edx
subl %edx, %eax
addl %ecx, %eax
addl $0x3c, %eax
movl %eax, 0x40(%r14)
movslq %eax, %rdi
movl $0x1, %esi
callq 0x2d20
movq %rax, 0x48(%r14)
movb %r12b, 0x24(%rax)
movq 0x48(%r14), %rax
movb %bpl, 0x25(%rax)
movsd 0x2405(%rip), %xmm0     # 0xf210
movsd 0x20(%rsp), %xmm1
mulsd %xmm0, %xmm1
movsd 0x388b(%rip), %xmm2     # 0x106a8
movsd 0x20020(%rbx), %xmm3
mulsd %xmm2, %xmm3
divsd %xmm3, %xmm1
movsd 0x2813(%rip), %xmm3     # 0xf648
addsd %xmm3, %xmm1
cvttsd2si %xmm1, %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x26(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x27(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x28(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x29(%rcx)
mulsd 0x28(%rsp), %xmm0
mulsd 0x20020(%rbx), %xmm2
divsd %xmm2, %xmm0
addsd %xmm3, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2a(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2b(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x2c(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x2d(%rcx)
cmpl $0x2, 0x20018(%rbx)
jne 0xcf03
movsd 0x8(%rsp), %xmm0
mulsd 0x37f6(%rip), %xmm0     # 0x106b0
cvttsd2si %xmm0, %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2e(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2f(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x30(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x31(%rcx)
movq 0x48(%r14), %rdx
addq $0x32, %rdx
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0xadbc
movl $0x3a, %ebp
jmp 0xcfee
movsd 0x8(%rsp), %xmm0
movq 0x18(%rsp), %r12
movq 0x58(%rsp), %rax
testq %rax, %rax
je 0xcf24
movupd (%rax), %xmm0
movapd %xmm0, 0x40(%rsp)
jmp 0xcf2e
leaq 0x40(%rsp), %rdi
callq 0x84e8
movq %r12, %rsi
movl 0x40(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2e(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x2f(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x30(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x31(%rcx)
movl 0x44(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x32(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x33(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x34(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x35(%rcx)
movl 0x48(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x36(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x37(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x38(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x39(%rcx)
movl 0x4c(%rsp), %eax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x3a(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%r14), %rdx
movb %cl, 0x3b(%rdx)
movq 0x48(%r14), %rcx
movb %al, 0x3c(%rcx)
movq 0x48(%r14), %rcx
movb %ah, 0x3d(%rcx)
movq 0x48(%r14), %rdx
addq $0x3e, %rdx
movq %rbx, %rdi
callq 0xadbc
movl $0x4a, %ebp
movq %r15, %rdi
callq 0x2120
movq 0x48(%r14), %rcx
movl %ebp, %edx
movb %al, (%rcx,%rdx)
movq 0x48(%r14), %rax
movb $0x0, 0x1(%rax,%rdx)
movq 0x48(%r14), %rax
leaq (%rax,%rdx), %r12
addq $0x2, %r12
movq %r15, %rdi
callq 0x2120
movq %r12, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x2230
movq %r14, %rsi
callq 0xbf25
movq %r15, %rdi
callq 0x2120
movq %rax, %xmm0
punpckldq 0x3999(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x39a1(%rip), %xmm0     # 0x109f0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd 0x20(%rsp), %xmm1
movsd 0x38(%rsp), %xmm2
addsd %xmm2, %xmm1
movsd 0x28(%rsp), %xmm0
movsd 0x30(%rsp), %xmm3
addsd %xmm3, %xmm0
movsd %xmm0, 0x18(%rsp)
subsd %xmm2, %xmm1
subsd %xmm3, %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x68(%r14), %xmm0
mulsd 0x361f(%rip), %xmm0     # 0x106c0
divsd 0x2b6f(%rip), %xmm0     # 0xfc18
callq 0x2550
movsd 0x68(%r14), %xmm0
mulsd 0x3604(%rip), %xmm0     # 0x106c0
divsd 0x2b54(%rip), %xmm0     # 0xfc18
callq 0x20b0
movsd 0x68(%r14), %xmm0
mulsd 0x35e9(%rip), %xmm0     # 0x106c0
divsd 0x2b39(%rip), %xmm0     # 0xfc18
movsd %xmm0, 0x10(%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x2240
addsd 0x10(%rsp), %xmm0
callq 0x2550
movsd 0x68(%r14), %xmm0
mulsd 0x35b7(%rip), %xmm0     # 0x106c0
divsd 0x2b07(%rip), %xmm0     # 0xfc18
movsd %xmm0, 0x10(%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x2240
addsd 0x10(%rsp), %xmm0
callq 0x20b0
movsd 0x68(%r14), %xmm0
addsd 0x3885(%rip), %xmm0     # 0x109c0
mulsd 0x357d(%rip), %xmm0     # 0x106c0
divsd 0x2acd(%rip), %xmm0     # 0xfc18
callq 0x2550
movsd 0x3868(%rip), %xmm0     # 0x109c0
addsd 0x68(%r14), %xmm0
mulsd 0x355a(%rip), %xmm0     # 0x106c0
divsd 0x2aaa(%rip), %xmm0     # 0xfc18
callq 0x20b0
movq %r15, %rdi
callq 0x2120
movq %rax, %xmm0
punpckldq 0x3858(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x3860(%rip), %xmm0     # 0x109f0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
mulsd 0x20(%rsp), %xmm1
movsd 0x38(%rsp), %xmm2
movapd %xmm2, %xmm0
subsd %xmm1, %xmm0
leaq 0x40(%rsp), %rdx
movsd %xmm0, (%rdx)
movsd 0x30(%rsp), %xmm0
subsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x8(%rdx)
xorl %eax, %eax
movq %rax, 0x10(%rdx)
addsd %xmm2, %xmm1
leaq 0x60(%rsp), %rcx
movsd %xmm1, (%rcx)
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x8(%rcx)
movq %rax, 0x10(%rcx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0xc286
movq %r14, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq