// File: /workspace/github_cpp_makefile_star2_O2/rurban[P]dgnlib/dgnwrite.cpp
// Function: DGNCreateCellHeaderElem
DGNElemCore CPL_DLL  *
DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName, 
                         short nClass, short *panLevels, 
                         DGNPoint *psRangeLow, DGNPoint *psRangeHigh, 
                         DGNPoint *psOrigin, double dfXScale, double dfYScale,
                         double dfRotation )

/**
 * Create cell header.
 *
 * The newly created element will still need to be written to file using
 * DGNWriteElement(). Also the level and other core values will be defaulted.
 * Use DGNUpdateElemCore() on the element before writing to set these values.
 *
 * Generally speaking the function DGNCreateCellHeaderFromGroup() should
 * be used instead of this function.
 *
 * @param hDGN the file handle on which the element is to be written.
 * @param nTotLength total length of cell in words not including the 38 bytes
 * of the cell header that occur before the totlength indicator. 
 * @param nClass the class value for the cell. 
 * @param panLevels an array of shorts holding the bit mask of levels in
 * effect for this cell.  This array should contain 4 shorts (64 bits). 
 * @param psRangeLow the cell diagonal origin in original cell file 
 * coordinates.
 * @param psRangeHigh the cell diagonal top left corner in original cell file 
 * coordinates.
 * @param psOrigin the origin of the cell in output file coordinates. 
 * @param dfXScale the amount of scaling applied in the X dimension in 
 * mapping from cell file coordinates to output file coordinates.
 * @param dfYScale the amount of scaling applied in the Y dimension in 
 * mapping from cell file coordinates to output file coordinates.
 * @param dfRotation the amount of rotation (degrees counterclockwise) in 
 * mapping from cell coordinates to output file coordinates. 
 *
 * @return the new element (DGNElemCellHeader) or NULL on failure. 
 */

{
    DGNElemCellHeader *psCH;
    DGNElemCore *psCore;
    DGNInfo *psInfo = (DGNInfo *) hDGN;

    DGNLoadTCB( hDGN );

/* -------------------------------------------------------------------- */
/*      Allocate element.                                               */
/* -------------------------------------------------------------------- */
    psCH = (DGNElemCellHeader *) CPLCalloc( sizeof(DGNElemCellHeader), 1 );
    psCore = &(psCH->core);

    DGNInitializeElemCore( hDGN, psCore );
    psCore->stype = DGNST_CELL_HEADER;
    psCore->type = DGNT_CELL_HEADER;

/* -------------------------------------------------------------------- */
/*      Set complex header specific information in the structure.       */
/* -------------------------------------------------------------------- */
    psCH->totlength = nTotLength;

/* -------------------------------------------------------------------- */
/*      Setup Raw data for the cell header specific portion.            */
/* -------------------------------------------------------------------- */
    if( psInfo->dimension == 2 )
        psCore->raw_bytes = 92;
    else
        psCore->raw_bytes = 124;
    psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);

    psCore->raw_data[36] = (unsigned char) (nTotLength % 256);
    psCore->raw_data[37] = (unsigned char) (nTotLength / 256);
    
    DGNAsciiToRad50( pszName, (unsigned short *) (psCore->raw_data + 38) );
    if( strlen(pszName) > 3 )
        DGNAsciiToRad50( pszName+3, (unsigned short *) (psCore->raw_data+40) );

    psCore->raw_data[42] = (unsigned char) (nClass % 256);
    psCore->raw_data[43] = (unsigned char) (nClass / 256);

    memcpy( psCore->raw_data + 44, panLevels, 8 );

    if( psInfo->dimension == 2 )
    {
        DGNPointToInt( psInfo, psRangeLow, psCore->raw_data + 52 );
        DGNPointToInt( psInfo, psRangeHigh, psCore->raw_data+ 60 );
        
        DGNInverseTransformPointToInt( psInfo, psOrigin, 
                                       psCore->raw_data + 84 );
    }
    else
    {
        DGNPointToInt( psInfo, psRangeLow, psCore->raw_data + 52 );
        DGNPointToInt( psInfo, psRangeHigh, psCore->raw_data+ 64 );
        
        DGNInverseTransformPointToInt( psInfo, psOrigin, 
                                       psCore->raw_data + 112 );
    }

/* -------------------------------------------------------------------- */
/*      Produce a transformation matrix that approximates the           */
/*      requested scaling and rotation.                                 */
/* -------------------------------------------------------------------- */
    if( psInfo->dimension == 2 )
    {
        long anTrans[4];
        double cos_a = cos(-dfRotation * PI / 180.0);
        double sin_a = sin(-dfRotation * PI / 180.0);
        
        anTrans[0] = (long) (cos_a * dfXScale * 214748);
        anTrans[1] = (long) (sin_a * dfYScale * 214748);
        anTrans[2] = (long)(-sin_a * dfXScale * 214748);
        anTrans[3] = (long) (cos_a * dfYScale * 214748);
        
        DGN_WRITE_INT32( anTrans[0], psCore->raw_data + 68 );
        DGN_WRITE_INT32( anTrans[1], psCore->raw_data + 72 );
        DGN_WRITE_INT32( anTrans[2], psCore->raw_data + 76 );
        DGN_WRITE_INT32( anTrans[3], psCore->raw_data + 80 );
    }
    else
    {
    }

/* -------------------------------------------------------------------- */
/*      Set the core raw data.                                          */
/* -------------------------------------------------------------------- */
    DGNUpdateElemCoreExtended( hDGN, psCore );
    
    return psCore;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movsd %xmm2, 0x8(%rsp)
movsd %xmm1, 0x18(%rsp)
movsd %xmm0, 0x10(%rsp)
movq %r9, (%rsp)
movq %r8, 0x20(%rsp)
movl %ecx, %r15d
movq %rdx, %r12
movl %esi, %r13d
movq %rdi, %r14
callq 0xa500
pushq $0x1
popq %rbp
movl $0x110, %edi            # imm = 0x110
movq %rbp, %rsi
callq 0x2c6c
movq %rax, %rbx
xorpd %xmm0, %xmm0
movupd %xmm0, (%rax)
movupd %xmm0, 0x10(%rax)
movupd %xmm0, 0x20(%rax)
movupd %xmm0, 0x30(%rax)
orl $-0x1, (%rax)
movupd %xmm0, 0x40(%rax)
movabsq $0x8ffffffff, %rax      # imm = 0x8FFFFFFFF
movq %rax, 0x8(%rbx)
movl $0x2, 0x14(%rbx)
movl %r13d, 0x50(%rbx)
xorl %edi, %edi
cmpl $0x2, 0x20018(%r14)
setne %dil
shll $0x5, %edi
orl $0x5c, %edi
movl %edi, 0x40(%rbx)
movq %rbp, %rsi
callq 0x2c6c
movq %rax, 0x48(%rbx)
movb %r13b, 0x24(%rax)
movl $0x100, %ecx            # imm = 0x100
movl %r13d, %eax
cltd
idivl %ecx
movq 0x48(%rbx), %rcx
movb %al, 0x25(%rcx)
movq 0x48(%rbx), %rsi
addq $0x26, %rsi
movq %r12, %rdi
callq 0x6ecf
movq %r12, %rdi
callq 0x2120
cmpq $0x4, %rax
jb 0xce66
addq $0x3, %r12
movq 0x48(%rbx), %rsi
addq $0x28, %rsi
movq %r12, %rdi
callq 0x6ecf
movq 0x48(%rbx), %rax
movb %r15b, 0x2a(%rax)
movw $0x100, %cx             # imm = 0x100
movl %r15d, %eax
cwtd
idivw %cx
movq 0x48(%rbx), %rcx
movb %al, 0x2b(%rcx)
movq 0x48(%rbx), %rax
movq 0x20(%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, 0x2c(%rax)
movl 0x20018(%r14), %ebp
movq 0x48(%rbx), %rdx
addq $0x34, %rdx
movq %r14, %rdi
movq (%rsp), %rsi
callq 0xd03e
xorl %eax, %eax
cmpl $0x2, %ebp
setne %al
movq 0x48(%rbx), %rcx
pushq $0x54
popq %rdx
pushq $0x70
popq %r15
cmoveq %rdx, %r15
leaq (%rcx,%rax,4), %rdx
addq $0x3c, %rdx
movq %r14, %rdi
movq 0x60(%rsp), %rsi
callq 0xd03e
addq 0x48(%rbx), %r15
movq %r14, %rdi
movq 0x68(%rsp), %rsi
movq %r15, %rdx
callq 0xa44d
cmpl $0x2, 0x20018(%r14)
jne 0xd024
movsd 0x8(%rsp), %xmm0
mulsd 0x1d18(%rip), %xmm0     # 0xec20
divsd 0x1d08(%rip), %xmm0     # 0xec18
movsd %xmm0, 0x8(%rsp)
callq 0x2550
movsd %xmm0, (%rsp)
movsd 0x8(%rsp), %xmm0
callq 0x20b0
movsd (%rsp), %xmm5
movapd %xmm5, %xmm2
movsd 0x10(%rsp), %xmm4
mulsd %xmm4, %xmm2
movsd 0x2a92(%rip), %xmm1     # 0xf9d8
mulsd %xmm1, %xmm2
cvttsd2si %xmm2, %rax
movapd %xmm0, %xmm2
movsd 0x18(%rsp), %xmm3
mulsd %xmm3, %xmm2
mulsd %xmm1, %xmm2
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x44(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x45(%rdx)
movq 0x48(%rbx), %rcx
movb %al, 0x46(%rcx)
movq 0x48(%rbx), %rcx
movb %ah, 0x47(%rcx)
cvttsd2si %xmm2, %rax
xorpd 0x12bc(%rip), %xmm0     # 0xe250
mulsd %xmm4, %xmm0
mulsd %xmm1, %xmm0
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x48(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x49(%rdx)
movq 0x48(%rbx), %rcx
movb %al, 0x4a(%rcx)
movq 0x48(%rbx), %rcx
movb %ah, 0x4b(%rcx)
cvttsd2si %xmm0, %rax
movapd %xmm5, %xmm0
mulsd %xmm3, %xmm0
mulsd %xmm1, %xmm0
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x4c(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x4d(%rdx)
movq 0x48(%rbx), %rcx
movb %al, 0x4e(%rcx)
movq 0x48(%rbx), %rcx
movb %ah, 0x4f(%rcx)
cvttsd2si %xmm0, %rax
movl %eax, %ecx
shrl $0x10, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x50(%rdx)
movl %eax, %ecx
shrl $0x18, %ecx
movq 0x48(%rbx), %rdx
movb %cl, 0x51(%rdx)
movq 0x48(%rbx), %rcx
movb %al, 0x52(%rcx)
movq 0x48(%rbx), %rcx
movb %ah, 0x53(%rcx)
movq %rbx, %rsi
callq 0xb380
movq %rbx, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq