// File: 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
movq %rsp, %rbp
subq $0xa0, %rsp
movw %cx, %ax
movq 0x18(%rbp), %rcx
movq 0x10(%rbp), %rcx
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movw %ax, -0x1a(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movsd %xmm0, -0x38(%rbp)
movsd %xmm1, -0x40(%rbp)
movsd %xmm2, -0x48(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rdi
callq 0x11190
movl $0x110, %edi            # imm = 0x110
movl $0x1, %esi
callq 0x2fc0
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x135f0
movq -0x58(%rbp), %rax
movl $0x8, 0xc(%rax)
movq -0x58(%rbp), %rax
movl $0x2, 0x14(%rax)
movl -0xc(%rbp), %ecx
movq -0x50(%rbp), %rax
movl %ecx, 0x50(%rax)
movq -0x60(%rbp), %rax
cmpl $0x2, 0x20018(%rax)
jne 0x16acf
movq -0x58(%rbp), %rax
movl $0x5c, 0x40(%rax)
jmp 0x16ada
movq -0x58(%rbp), %rax
movl $0x7c, 0x40(%rax)
movq -0x58(%rbp), %rax
movslq 0x40(%rax), %rdi
movl $0x1, %esi
callq 0x2fc0
movq %rax, %rcx
movq -0x58(%rbp), %rax
movq %rcx, 0x48(%rax)
movl -0xc(%rbp), %eax
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movb %dl, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x24(%rax)
movl -0xc(%rbp), %eax
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x25(%rax)
movq -0x18(%rbp), %rdi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rsi
addq $0x26, %rsi
callq 0xabb0
movq -0x18(%rbp), %rdi
callq 0x2120
cmpq $0x3, %rax
jbe 0x16b64
movq -0x18(%rbp), %rdi
addq $0x3, %rdi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rsi
addq $0x28, %rsi
callq 0xabb0
movswl -0x1a(%rbp), %eax
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movb %dl, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x2a(%rax)
movswl -0x1a(%rbp), %eax
movl $0x100, %ecx            # imm = 0x100
cltd
idivl %ecx
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x2b(%rax)
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x28(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0x2c(%rax)
movq -0x60(%rbp), %rax
cmpl $0x2, 0x20018(%rax)
jne 0x16c03
movq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x34, %rdx
callq 0x16f80
movq -0x60(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x3c, %rdx
callq 0x16f80
movq -0x60(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x54, %rdx
callq 0x10fd0
jmp 0x16c4e
movq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x34, %rdx
callq 0x16f80
movq -0x60(%rbp), %rdi
movq 0x10(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x40, %rdx
callq 0x16f80
movq -0x60(%rbp), %rdi
movq 0x18(%rbp), %rsi
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rdx
addq $0x70, %rdx
callq 0x10fd0
movq -0x60(%rbp), %rax
cmpl $0x2, 0x20018(%rax)
jne 0x16f5a
movsd -0x48(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd 0x2c45(%rip), %xmm1     # 0x198c8
mulsd %xmm1, %xmm0
movsd 0x2c41(%rip), %xmm1     # 0x198d0
divsd %xmm1, %xmm0
callq 0x2540
movsd %xmm0, -0x88(%rbp)
movsd -0x48(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd 0x2c04(%rip), %xmm1     # 0x198c8
mulsd %xmm1, %xmm0
movsd 0x2c00(%rip), %xmm1     # 0x198d0
divsd %xmm1, %xmm0
callq 0x20b0
movsd %xmm0, -0x90(%rbp)
movsd -0x88(%rbp), %xmm0
mulsd -0x38(%rbp), %xmm0
movsd 0x3662(%rip), %xmm1     # 0x1a358
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x80(%rbp)
movsd -0x90(%rbp), %xmm0
mulsd -0x40(%rbp), %xmm0
movsd 0x3640(%rip), %xmm1     # 0x1a358
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x78(%rbp)
movsd -0x90(%rbp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
mulsd -0x38(%rbp), %xmm0
movsd 0x3607(%rip), %xmm1     # 0x1a358
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x70(%rbp)
movsd -0x88(%rbp), %xmm0
mulsd -0x40(%rbp), %xmm0
movsd 0x35e5(%rip), %xmm1     # 0x1a358
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x68(%rbp)
movq -0x80(%rbp), %rax
movl %eax, -0x94(%rbp)
movl -0x94(%rbp), %eax
andl $0xff0000, %eax         # imm = 0xFF0000
sarl $0x10, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x44(%rax)
movl -0x94(%rbp), %eax
andl $0xff000000, %eax       # imm = 0xFF000000
shrl $0x18, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x45(%rax)
movl -0x94(%rbp), %eax
andl $0xff, %eax
sarl $0x0, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x46(%rax)
movl -0x94(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x47(%rax)
movq -0x78(%rbp), %rax
movl %eax, -0x98(%rbp)
movl -0x98(%rbp), %eax
andl $0xff0000, %eax         # imm = 0xFF0000
sarl $0x10, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x48(%rax)
movl -0x98(%rbp), %eax
andl $0xff000000, %eax       # imm = 0xFF000000
shrl $0x18, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x49(%rax)
movl -0x98(%rbp), %eax
andl $0xff, %eax
sarl $0x0, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4a(%rax)
movl -0x98(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4b(%rax)
movq -0x70(%rbp), %rax
movl %eax, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
andl $0xff0000, %eax         # imm = 0xFF0000
sarl $0x10, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4c(%rax)
movl -0x9c(%rbp), %eax
andl $0xff000000, %eax       # imm = 0xFF000000
shrl $0x18, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4d(%rax)
movl -0x9c(%rbp), %eax
andl $0xff, %eax
sarl $0x0, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4e(%rax)
movl -0x9c(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x4f(%rax)
movq -0x68(%rbp), %rax
movl %eax, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
andl $0xff0000, %eax         # imm = 0xFF0000
sarl $0x10, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x50(%rax)
movl -0xa0(%rbp), %eax
andl $0xff000000, %eax       # imm = 0xFF000000
shrl $0x18, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x51(%rax)
movl -0xa0(%rbp), %eax
andl $0xff, %eax
sarl $0x0, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x52(%rax)
movl -0xa0(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
movb %al, %cl
movq -0x58(%rbp), %rax
movq 0x48(%rax), %rax
movb %cl, 0x53(%rax)
jmp 0x16f5c
jmp 0x16f5c
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x12f50
movq -0x58(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)