// File: /workspace/github_cpp_makefile_star2_O1/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 $0xb8, %rsp
movsd %xmm5, 0x10(%rsp)
movsd %xmm4, 0x30(%rsp)
movsd %xmm3, 0x40(%rsp)
movq %r8, 0x60(%rsp)
movsd %xmm2, 0x18(%rsp)
movsd %xmm1, 0x28(%rsp)
movsd %xmm0, 0x38(%rsp)
movl %ecx, %ebp
movl %edx, %r12d
movq %rsi, %r15
movq %rdi, %rbx
callq 0xb37c
movq %r15, %rdi
callq 0x2120
leaq 0x90(%rax), %rdi
movl $0x1, %esi
callq 0x2d54
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 0x38(%rsp), %xmm0
movsd %xmm0, 0x58(%r14)
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x60(%r14)
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x68(%r14)
leaq 0x70(%r14), %rax
movq %rax, 0x20(%rsp)
movsd 0x40(%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 0x22b0
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 0x2d54
movq %rax, 0x48(%r14)
movb %r12b, 0x24(%rax)
movq 0x48(%r14), %rax
movb %bpl, 0x25(%rax)
movsd 0x2e64(%rip), %xmm0     # 0x10218
movsd 0x38(%rsp), %xmm1
mulsd %xmm0, %xmm1
movsd 0x42aa(%rip), %xmm2     # 0x11670
movsd 0x20020(%rbx), %xmm3
mulsd %xmm2, %xmm3
divsd %xmm3, %xmm1
movsd 0x324a(%rip), %xmm3     # 0x10628
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 0xd4ac
movsd 0x18(%rsp), %xmm0
mulsd 0x4215(%rip), %xmm0     # 0x11678
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 0x20(%rsp), %rsi
callq 0xb2b7
movl $0x3a, %ebp
jmp 0xd597
movsd 0x18(%rsp), %xmm0
movq 0x20(%rsp), %r12
movq 0x60(%rsp), %rax
testq %rax, %rax
je 0xd4cd
movupd (%rax), %xmm0
movapd %xmm0, 0x70(%rsp)
jmp 0xd4d7
leaq 0x70(%rsp), %rdi
callq 0x862c
movq %r12, %rsi
movl 0x70(%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 0x74(%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 0x78(%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 0x7c(%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 0xb2b7
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 0x2240
movq %r14, %rsi
callq 0xc46f
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
xorl %r12d, %r12d
movq %r12, 0x80(%rsp)
movq %r15, %rdi
callq 0x2120
movq %rax, %xmm0
punpckldq 0x432d(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x4335(%rip), %xmm0     # 0x11950
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
mulsd 0x38(%rsp), %xmm2
movsd 0x40(%rsp), %xmm1
addsd %xmm1, %xmm2
movsd %xmm2, 0xa0(%rsp)
movsd 0x28(%rsp), %xmm0
movsd 0x30(%rsp), %xmm3
addsd %xmm3, %xmm0
movsd %xmm0, 0xa8(%rsp)
movq %r12, 0xb0(%rsp)
subsd %xmm1, %xmm2
movsd %xmm0, 0x98(%rsp)
movapd %xmm0, %xmm1
subsd %xmm3, %xmm1
movsd %xmm1, 0x18(%rsp)
mulsd %xmm1, %xmm1
movapd %xmm2, 0x60(%rsp)
movapd %xmm2, %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0xd6a2
sqrtsd %xmm0, %xmm0
jmp 0xd6a7
callq 0x2220
movsd %xmm0, 0x10(%rsp)
leaq 0x70(%rsp), %r12
movsd (%r12), %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x8(%r12), %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0x68(%r14), %xmm0
mulsd 0x3fb4(%rip), %xmm0     # 0x11690
divsd 0x3514(%rip), %xmm0     # 0x10bf8
callq 0x2560
mulsd 0x60(%rsp), %xmm0
addsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x8(%r12), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x68(%r14), %xmm0
mulsd 0x3f77(%rip), %xmm0     # 0x11690
divsd 0x34d7(%rip), %xmm0     # 0x10bf8
callq 0x20b0
movapd 0x60(%rsp), %xmm1
mulsd %xmm1, %xmm0
addsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd (%r12), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x68(%r14), %xmm0
mulsd 0x3f3a(%rip), %xmm0     # 0x11690
divsd 0x349a(%rip), %xmm0     # 0x10bf8
movsd %xmm0, 0x48(%rsp)
movsd 0x18(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
callq 0x2250
addsd 0x48(%rsp), %xmm0
callq 0x2560
mulsd 0x10(%rsp), %xmm0
addsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x8(%r12), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x68(%r14), %xmm0
mulsd 0x3edf(%rip), %xmm0     # 0x11690
divsd 0x343f(%rip), %xmm0     # 0x10bf8
movsd %xmm0, 0x48(%rsp)
movsd 0x50(%rsp), %xmm0
callq 0x2250
addsd 0x48(%rsp), %xmm0
callq 0x20b0
mulsd 0x10(%rsp), %xmm0
addsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd (%r12), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x68(%r14), %xmm0
addsd 0x4127(%rip), %xmm0     # 0x11928
mulsd 0x3e87(%rip), %xmm0     # 0x11690
divsd 0x33e7(%rip), %xmm0     # 0x10bf8
callq 0x2560
mulsd 0x18(%rsp), %xmm0
addsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x8(%r12), %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x40eb(%rip), %xmm0     # 0x11928
addsd 0x68(%r14), %xmm0
mulsd 0x3e45(%rip), %xmm0     # 0x11690
divsd 0x33a5(%rip), %xmm0     # 0x10bf8
callq 0x20b0
mulsd 0x18(%rsp), %xmm0
addsd 0x50(%rsp), %xmm0
movsd 0x8(%rsp), %xmm9
movapd %xmm9, %xmm1
movsd 0x60(%rsp), %xmm7
minsd %xmm7, %xmm1
movsd 0x88(%rsp), %xmm5
movapd %xmm5, %xmm2
minsd %xmm1, %xmm2
movsd 0x20(%rsp), %xmm4
movapd %xmm4, %xmm1
minsd %xmm2, %xmm1
movsd %xmm1, (%r12)
movapd %xmm0, %xmm1
movsd 0x10(%rsp), %xmm8
minsd %xmm8, %xmm1
movsd 0x58(%rsp), %xmm6
movapd %xmm6, %xmm2
minsd %xmm1, %xmm2
movsd 0x90(%rsp), %xmm3
movapd %xmm3, %xmm1
minsd %xmm2, %xmm1
movsd %xmm1, 0x8(%r12)
movapd %xmm9, %xmm1
maxsd %xmm7, %xmm1
movapd %xmm5, %xmm2
maxsd %xmm1, %xmm2
movapd %xmm4, %xmm1
maxsd %xmm2, %xmm1
leaq 0xa0(%rsp), %r13
movsd %xmm1, (%r13)
maxsd %xmm8, %xmm0
movapd %xmm6, %xmm1
maxsd %xmm0, %xmm1
movapd %xmm3, %xmm0
maxsd %xmm1, %xmm0
movsd %xmm0, 0x8(%r13)
movq %r15, %rdi
callq 0x2120
movq %rax, %xmm0
punpckldq 0x4014(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x401c(%rip), %xmm0     # 0x11950
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd 0x38(%rsp), %xmm2
mulsd %xmm1, %xmm2
movsd 0x40(%rsp), %xmm1
movapd %xmm1, %xmm0
subsd %xmm2, %xmm0
movsd %xmm0, (%r12)
movsd 0x30(%rsp), %xmm0
subsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x8(%r12)
xorl %eax, %eax
movq %rax, 0x10(%r12)
addsd %xmm1, %xmm2
movsd %xmm2, (%r13)
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x8(%r13)
movq %rax, 0x10(%r13)
movq %rbx, %rdi
movq %r14, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0xc80f
movq %r14, %rax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq