示例#1
0
/* Return the size of function parameters or -1 if size could
 * not be determined (symbol isn't a function or is variadic)
 */
static unsigned GetParmsSize( SYM_HANDLE sym_handle )
{
    unsigned    total_parm_size = 0;
    unsigned    parm_size;
    TYPEPTR     fn_typ;
    TYPEPTR     *parm_types;
    TYPEPTR     typ;
    SYM_ENTRY   sym;

    SymGet( &sym, sym_handle );
    fn_typ = sym.sym_type;
    SKIP_TYPEDEFS( fn_typ );
    if( fn_typ->decl_type == TYPE_FUNCTION ) {
        if( fn_typ->u.fn.parms != NULL ) {
            for( parm_types = fn_typ->u.fn.parms; (typ = *parm_types) != NULL; ++parm_types ) {
                if( typ->decl_type == TYPE_DOT_DOT_DOT ) {
                    total_parm_size = (unsigned)-1;
                    break;
                }

                SKIP_TYPEDEFS( typ );
                if( typ->decl_type == TYPE_VOID )
                    break;

                parm_size = _RoundUp( TypeSize( typ ), TARGET_INT );
                total_parm_size += parm_size;
            }
        }
    } else {
        total_parm_size = (unsigned)-1;
    }
    return( total_parm_size );
}
示例#2
0
static void addAutoLocn( sym s, cg_type type )
{
    AUTO_LOCN* curr;

    curr = CGAlloc( sizeof( AUTO_LOCN ) );
    curr->s = s;
    curr->offset = next_auto_offset;
    curr->next = auto_locations;
    auto_locations = curr;
    next_auto_offset += _RoundUp( BETypeLength( type ), AUTO_PACK );
}
示例#3
0
target_offset_t SegmentAlignment(   // SEGMENT: ALIGNMENT FOR TYPE
    TYPE type )                     // - TYPE to align
{
    target_offset_t align;
    TYPE align_type;

    if( CompFlags.dont_align_segs ) {
        return( TARGET_CHAR );
    }
#if _CPU == _AXP
    if( PackAmount != TARGET_CHAR ) {
#else
    if( OptSize <= 50 || PackAmount != TARGET_CHAR ) {
#endif
        align_type = AlignmentType( type );
        align = segmentTypeSize( align_type );
        if( align == TARGET_CHAR ) {
            // no alignment; let PackAlignment know the real size
            align = segmentTypeSize( type );
        }
        align = PackAlignment( TARGET_MAX_PACKING, align );
    } else {
        align = TARGET_CHAR;
    }
    return( align );
}


target_offset_t SegmentAdjust(  // SEGMENT: ADJUST OFFSET TO ALIGN
    fe_seg_id segid,            // - segment identifier
    target_size_t offset,       // - current offset
    target_offset_t align )     // - required aligment
{
    target_size_t   calc_offset;
    target_offset_t adjust;

    switch( segid ) {
    case SEG_INIT_BEG:
    case SEG_INIT_REF:
    case SEG_INIT_END:
    case SEG_FINI_BEG:
    case SEG_FINI_REF:
    case SEG_FINI_END:
        /* no padding in these segments */
        return( 0 );
    }
    calc_offset = _RoundUp( offset, align );
    adjust = calc_offset - offset;
    if( _CHECK_ADJUST( calc_offset, offset ) ) {
        adjust = 0;
    }
    return( adjust );
}
示例#4
0
static void getAsmLine( VBUF *buff )
{
    char line[256];

    if( endOfAsmStmt() )
        return;
    /* reserve at least MAX_INSTR_SIZE bytes in the buffer */
    VbufReqd( buff, _RoundUp( ( AsmCodeAddress + MAX_INSTR_SIZE ), MAX_INSTR_SIZE ) );
    AsmCodeBuffer = VbufBuffer( buff );
    ensureBufferReflectsCurToken();
    if( IS_ID_OR_KEYWORD( CurToken ) && strcmp( Buffer, "__emit" ) == 0 ) {
        strcpy( line, AsmSysDefineByte() );
        strcat( line, " " );
        NextToken();
        ensureBufferReflectsCurToken();
    } else {
        line[0] = '\0';
    }
    for(;;) {
        if( endOfAsmStmt() ) break;
        strncat( line, Buffer, sizeof(line)-1 );
        switch( CurToken ) {
        case T_ALT_XOR:
        case T_ALT_EXCLAMATION:
        case T_ALT_AND_AND:
        case T_ALT_OR_OR:
            strncat( line, " ", sizeof(line)-1 );
            break;
        default:
            if( IS_ID_OR_KEYWORD( CurToken ) )
                strncat( line, " ", sizeof(line)-1 );
            break;
        }
        NextToken();
        ensureBufferReflectsCurToken();
    }
    if( line[0] != '\0' ) {
        AsmSysLine( line );
    }
    VbufSetLen( buff, AsmCodeAddress );
    if( CurToken == T_SEMI_COLON ) {
        // ; .ASM comment
        for(;;) {
            NextToken();
            if( CurToken == T_EOF ) break;
            if( CurToken == T_NULL ) break;
        }
    }
}
示例#5
0
short _FastMap( long _WCI86FAR *colours, short num )
//=============================================

{
    short               i;
    long                colour;
    struct rgb          *rgb;

    i = _RoundUp( sizeof( struct rgb ) * num );
    if( _stackavail() - i <= 0x100 ) {
        return( FALSE );
    } else {
        rgb = __alloca( i );
    }
    for( i = 0; i < num; ++i ) {
        colour = *colours;
        rgb[ i ].blue = ( (unsigned long)colour & 0x00ff0000 ) >> 16;
        rgb[ i ].green = (unsigned short)( colour & 0x0000ff00 ) >> 8;
        rgb[ i ].red = colour & 0x000000ff;
        ++colours;
    }
    VideoIntDAC( _BIOS_SET_PALETTE + 0x12, 0, num, rgb );
    return( TRUE );
}
示例#6
0
void _L1GetPic( short x1, short y1, short x2, short y2,
/*===============================*/ struct picture _WCI86HUGE *image )

/*  Copy that portion of the screen inside the viewport to the buffer
    pointed by 'image'. */

{
    short               dx;             /* width of rectangle in pixels     */
    short               dy;             /* height of rectangle in pixels    */
    short               t;
#if defined( _DEFAULT_WINDOWS )
    WPI_PRES            dc;
    short               srcy;
#else
    short               line_len;       /* length of each line in bytes     */
  #if !defined( __386__ )
    unsigned short      new_off;
  #endif
    char                *tmp;
    gr_device _FARD     *dev_ptr;       /* pointer to _CurrState->deviceptr */
    char _WCI86HUGE     *pic;           /* buffer to store image            */
    copy_fn             *copy;          /* pointer to copy routine          */
    setup_fn            *setup;
#endif

    if( x1 > x2 ) {         // ensure x1 < x2
        t = x1;
        x1 = x2;
        x2 = t;
    }
    if( y1 > y2 ) {         // ensure y1 < y2
        t = y1;
        y1 = y2;
        y2 = t;
    }
    if( _L0BlockClip( &x1, &y1, &x2, &y2 ) != 0 ) {     /* clip image to    */
        image->picwidth = 0;                            /* active viewport  */
        image->picheight = 0;
        _ErrorStatus = _GRNOOUTPUT;
        return;
    }
    dx = x2 - x1 + 1;                               /* row width in pixels  */
    dy = y2 - y1 + 1;                               /* height in pixel rows */
    image->picwidth = dx;                   /* save width in image picture  */
    image->picheight = dy;                  /* save height in image picture */
#if defined( _DEFAULT_WINDOWS )
    dc = _Mem_dc;

// Create a memory DC to put the image in
    image->buffer = _wpi_createcompatiblepres( dc, _GetInst(), &( image->pdc ) );
    image->bmp = _wpi_createcompatiblebitmap( dc, dx, dy );
    if( ( image->buffer == NULL ) || ( image->bmp == NULL ) ) {
         _ErrorStatus = _GRINSUFFICIENTMEMORY;
         return;
    }
    _wpi_selectbitmap( image->buffer, image->bmp );

// Transfer the image to a memory DC
  #if defined( __OS2__ )
    srcy = _wpi_cvth_y( y2, _GetPresHeight() );
  #else
    srcy = y1;
  #endif
    _wpi_bitblt( image->buffer, 0, 0, dx, dy, dc, x1, srcy, SRCCOPY );

#else
    image->bpp = _CurrState->vc.bitsperpixel;   /* save bpp - never used ?  */
    line_len = _RowLen( dx );                   /* width of row in bytes    */

    _StartDevice();

    dev_ptr = _CurrState->deviceptr;
    copy = dev_ptr->readrow;
    pic = &image->buffer;
    tmp = NULL;
    setup = dev_ptr->setup;
    for( ; y1 <= y2; ++y1 ) {               /* copy screen image to buffer  */
        ( *setup )( x1, y1, 0 );
  #if !defined( __386__ )
        // check whether the entire row will fit in the buffer
        new_off = FP_OFF( pic ) + line_len - 1;
        if( new_off < FP_OFF( pic ) ) {
            if( tmp == NULL ) {     // may have been already allocated
                if( _stackavail() - line_len > 0x100 ) {
                    tmp = __alloca( _RoundUp( line_len ) );
                }
            }
            if( tmp != NULL ) {
                ( *copy )( tmp, _Screen.mem, dx, _Screen.bit_pos, 0 );
                for( t = 0; t < line_len; ++t ) {
                    *pic = tmp[ t ];
                    ++pic;      // the PIA function will handle this properly
                }
            } else {
                _ErrorStatus = _GRINSUFFICIENTMEMORY;
                pic += line_len;
            }
        } else {
  #endif
            ( *copy )( pic, _Screen.mem, dx, _Screen.bit_pos, 0 );
            pic += line_len;
  #if !defined( __386__ )
        }
  #endif
    }

    _ResetDevice();
#endif
}
示例#7
0
static int insertFixups( VBUF *src_code )
{
    struct asmfixup     *fix;
    struct asmfixup     *head;
    struct asmfixup     *chk;
    struct asmfixup     *next;
    struct asmfixup     **owner;
    unsigned char       *src;
    unsigned char       *src_start;
    unsigned char       *src_end;
    unsigned char       cg_fix;
    bool                perform_fixups;
    byte_seq            *seq;
    SYMBOL              sym;
    NAME                name;
    unsigned char       *dst;
    byte_seq_len        len;
    unsigned            skip;
    int                 mutate_to_segment;
    bool                uses_auto;
#if _CPU == 8086
    int                 fixup_padding;
#endif
    VBUF                out_code;

    uses_auto = FALSE;
    perform_fixups = FALSE;
    head = FixupHead;
    if( head == NULL ) {
        out_code = *src_code;
    } else {
        VbufInit( &out_code );
        FixupHead = NULL;
        /* sort the fixup list in increasing fixup_loc's */
        for( fix = head; fix != NULL; fix = next ) {
            owner = &FixupHead;
            for( ;; ) {
                chk = *owner;
                if( chk == NULL ) break;
                if( chk->fixup_loc > fix->fixup_loc ) break;
                owner = &chk->next;
            }
            next = fix->next;
            fix->next = *owner;
            *owner = fix;
        }
        len = 0;
        cg_fix = 0;
        sym = NULL;
        src_start = VbufBuffer( src_code );
        src_end = src_start + VbufLen( src_code );
        fix = FixupHead;
        owner = &FixupHead;
        /* insert fixup escape sequences */
        for( src = src_start; src < src_end; ) {
            /* reserve at least ASM_BLOCK bytes in the buffer */
            VbufReqd( &out_code, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) );
            dst = VbufBuffer( &out_code );
            if( fix != NULL && fix->fixup_loc == (src - src_start) ) {
                name = NULL;
                if( fix->name != NULL ) {
                    name = NameCreateNoLen( fix->name );
                    sym = ScopeASMUseSymbol( name, &uses_auto );
                    if( sym == NULL ) {
                        return( 0 );
                    }
                }
                /* insert fixup information */
                skip = 0;
                dst[len++] = FLOATING_FIXUP_BYTE;
                mutate_to_segment = 0;
#if _CPU == 8086
                fixup_padding = 0;
#endif
                switch( fix->fixup_type ) {
                case FIX_FPPATCH:
                    dst[len++] = fix->offset;
                    break;
                case FIX_SEG:
                    if( name == NULL ) {
                        // special case for floating point fixup
                        if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) {
                           // inline assembler FWAIT instruction 0x90, 0x9b
                            dst[len++] = FIX_FPP_WAIT;
                        } else if( src[0] == 0x9b && (src[1] & 0xd8) == 0xd8 ) {
                           // FWAIT as first byte and FPU instruction opcode as second byte
                            dst[len++] = FIX_FPP_NORMAL;
                        } else if( src[0] == 0x9b && (src[2] & 0xd8) == 0xd8 ) {
                           // FWAIT as first byte and FPU instruction opcode as third byte
                           // second byte should be segment override prefix
                            switch( src[1] ) {
                            case PREFIX_ES: dst[len++] = FIX_FPP_ES;    break;
                            case PREFIX_CS: dst[len++] = FIX_FPP_CS;    break;
                            case PREFIX_SS: dst[len++] = FIX_FPP_SS;    break;
                            case PREFIX_DS: dst[len++] = FIX_FPP_DS;    break;
                            case PREFIX_GS: dst[len++] = FIX_FPP_GS;    break;
                            case PREFIX_FS: dst[len++] = FIX_FPP_FS;    break;
                            default: --len; break;  // skip FP patch
                            }
                        } else {
                            // skip FP patch
                            --len;
                        }
                    } else {
                        skip = 2;
                        cg_fix = FIX_SYM_SEGMENT;
                    }
                    break;
                case FIX_RELOFF16:
                    skip = 2;
                    cg_fix = FIX_SYM_RELOFF;
                    break;
                case FIX_RELOFF32:
                    skip = 4;
                    cg_fix = FIX_SYM_RELOFF;
#if _CPU == 8086
                    fixup_padding = 1;
#endif
                    break;
                case FIX_PTR16:
                    mutate_to_segment = 1;
                    /* fall through */
                case FIX_OFF16:
                    skip = 2;
                    cg_fix = FIX_SYM_OFFSET;
                    break;
                case FIX_PTR32:
                    mutate_to_segment = 1;
                    /* fall through */
                case FIX_OFF32:
                    skip = 4;
                    cg_fix = FIX_SYM_OFFSET;
#if _CPU == 8086
                    fixup_padding = 1;
#endif
                    break;
                default:
                    CErr2p( ERR_ASSEMBLER_ERROR, "cannot reach label" );
                    break;
                }
                if( skip != 0 ) {
                    dst[len++] = cg_fix;
                    *((BYTE_SEQ_SYM *)&dst[len]) = sym;
                    len += sizeof( BYTE_SEQ_SYM );
                    *((BYTE_SEQ_OFF *)&dst[len]) = fix->offset;
                    len += sizeof( BYTE_SEQ_OFF );
                    src += skip;
                }
#if _CPU == 8086
                if( fixup_padding ) {
                    // add offset fixup padding to 32-bit
                    // cg create only 16-bit offset fixup
                    dst[len++] = 0;
                    dst[len++] = 0;
                    //
                }
#endif
                if( mutate_to_segment ) {
                    /*
                        Since the CG escape sequences don't allow for
                        FAR pointer fixups, we have to split them into two.
                        This is done by doing the offset fixup first, then
                        mutating the fixup structure to look like a segment
                        fixup one near pointer size later.
                    */
                    fix->fixup_type = FIX_SEG;
                    fix->fixup_loc += skip;
                    fix->offset = 0;
                } else {
                    head = fix;
                    fix = fix->next;
                    if( head->external ) {
                        *owner = fix;
                        CMemFree( head->name );
                        CMemFree( head );
                    } else {
                        owner = &head->next;
                    }
                }
            } else {
                if( *src == FLOATING_FIXUP_BYTE ) {
                    dst[len++] = FLOATING_FIXUP_BYTE;
                }
                dst[len++] = *src++;
            }
            VbufSetLen( &out_code, len );
        }
        perform_fixups = TRUE;
    }
    len = VbufLen( &out_code );
    seq = CMemAlloc( offsetof( byte_seq, data ) + len );
    seq->relocs = perform_fixups;
    seq->length = len;
    memcpy( seq->data, VbufBuffer( &out_code ), len );
    CurrInfo->code = seq;
    if( VbufBuffer( &out_code ) != VbufBuffer( src_code ) )
        VbufFree( &out_code );
    return( uses_auto );
}
示例#8
0
static int GetByteSeq( void )
{
    int             len;
    char            *name;
    unsigned        offset;
    unsigned        fixword;
    int             uses_auto;
    VBUF            code_buffer;
#if _CPU == 8086
    bool            use_fpu_emu = FALSE;
#endif

    VbufInit( &code_buffer );
    AsmSysInit();
    PPCTL_ENABLE_MACROS();
    NextToken();
    len = 0;
    offset = 0;
    name = NULL;
    for( ;; ) {
        /* reserve at least ASM_BLOCK bytes in the buffer */
        VbufReqd( &code_buffer, _RoundUp( len + ASM_BLOCK, ASM_BLOCK ) );
        if( CurToken == T_STRING ) {
            AsmCodeAddress = len;
            AsmCodeBuffer = VbufBuffer( &code_buffer );
#if _CPU == 8086
            AsmLine( Buffer, use_fpu_emu );
            use_fpu_emu = FALSE;
#else
            AsmLine( Buffer, FALSE );
#endif
            len = AsmCodeAddress;
            NextToken();
            if( CurToken == T_COMMA ) {
                NextToken();
            }
        } else if( CurToken == T_CONSTANT ) {
#if _CPU == 8086
            if( use_fpu_emu ) {
                AddAFix( len, NULL, FIX_SEG, 0 );
                use_fpu_emu = FALSE;
            }
#endif
            VbufBuffer( &code_buffer )[ len++ ] = U32Fetch( Constant64 );
            NextToken();
        } else {
#if _CPU == 8086
            use_fpu_emu = FALSE;
#endif
            fixword = FixupKeyword();
            if( fixword == FIXWORD_NONE )
                break;
            if( fixword == FIXWORD_FLOAT ) {
#if _CPU == 8086
                if( GET_FPU_EMU( CpuSwitches ) ) {
                    use_fpu_emu = TRUE;
                }
#endif
            } else { /* seg or offset */
                if( !IS_ID_OR_KEYWORD( CurToken ) ) {
                    CErr1( ERR_EXPECTING_ID );
                } else {
                    name = strsave( Buffer );
                    offset = 0;
                    NextToken();
                    if( CurToken == T_PLUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = U32Fetch( Constant64 );
                            NextToken();
                        }
                    } else if( CurToken == T_MINUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = - U32Fetch( Constant64 );
                            NextToken();
                        }
                    }
                }
                switch( fixword ) {
                case FIXWORD_RELOFF:
#if _CPU == 8086
                    AddAFix( len, name, FIX_RELOFF16, offset );
                    len += 2;
#else
                    AddAFix( len, name, FIX_RELOFF32, offset );
                    len += 4;
#endif
                    break;
                case FIXWORD_OFFSET:
#if _CPU == 8086
                    AddAFix( len, name, FIX_OFF16, offset );
                    len += 2;
#else
                    AddAFix( len, name, FIX_OFF32, offset );
                    len += 4;
#endif
                    break;
                case FIXWORD_SEGMENT:
                    AddAFix( len, name, FIX_SEG, 0 );
                    len += 2;
                    break;
                }
            }
        }
        VbufSetLen( &code_buffer, len );
    }
    PPCTL_DISABLE_MACROS();
    uses_auto = AsmSysInsertFixups( &code_buffer );
    AsmSysFini();
    VbufFree( &code_buffer );
    return( uses_auto );
}
示例#9
0
static void checkPrologSize( unsigned *p )
{
    *p = _RoundUp( *p, TARGET_UINT );
}
示例#10
0
static  void    Far16Parms( cn call ) {
/*************************************/

    instruction         *ins;
    type_length         parm_size;
    pn                  parm, next;
    instruction         *call_ins;
    name                *eax;
    name                *ecx;
    name                *esi;
    label_handle        lbl;
    type_length         offset;
    name                *parmlist;
    call_state          *state;
    rt_class            rtindex;

    call_ins = call->ins;
    parm_size = 0;
    state = call->state;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm_size += _RoundUp( parm->name->tipe->length, 2 );
    }
    parmlist = SAllocTemp( XX, parm_size );
    parmlist->v.usage |= NEEDS_MEMORY | USE_IN_ANOTHER_BLOCK | USE_ADDRESS;
    offset = 0;
    for( parm = call->parms; parm != NULL; parm = parm->next ) {
        parm->name->u.i.ins->result = STempOffset( parmlist, offset,
                                                 TypeClass( parm->name->tipe ),
                                                 parm->name->tipe->length );
        offset += _RoundUp( parm->name->tipe->length, 2 );
    }
    for( parm = call->parms; parm != NULL; parm = next ) {
        next = parm->next;
        parm->name->format = NF_ADDR;   /* so instruction doesn't get freed! */
        BGDone( parm->name );
        CGFree( parm );
    }
    eax = AllocRegName( HW_EAX );
    ecx = AllocRegName( HW_ECX );
    esi = AllocRegName( HW_ESI );
    HW_TurnOn( state->parm.used, eax->r.reg );
    HW_TurnOn( state->parm.used, ecx->r.reg );
    HW_TurnOn( state->parm.used, esi->r.reg );
    ins = MakeMove( AllocS32Const( parm_size ), ecx, WD );
    AddIns( ins );
    ins = MakeUnary( OP_LA, parmlist, esi, WD );
    AddIns( ins );
    if( ins->head.opcode == OP_CALL ) {
        ins = MakeUnary( OP_LA, call->name->u.n.name, eax, WD );
    } else {
        ins = MakeMove( GenIns( call->name ), eax, WD );
        call_ins->head.opcode = OP_CALL;
    }
    call_ins->num_operands = 2;
    AddIns( ins );
    if( call_ins->type_class == XX ) {
        if( state->attr & ROUTINE_ALLOCS_RETURN ) {
            rtindex = RT_Far16Cdecl;
        } else {
            rtindex = RT_Far16Pascal;
        }
    } else {
        rtindex = RT_Far16Func;
    }
    lbl = RTLabel( rtindex );
    call->name->u.n.name = AllocMemory( lbl, 0, CG_LBL, WD );
    call_ins->flags.call_flags |= CALL_FAR16 | CALL_POPS_PARMS;
    call_ins->operands[CALL_OP_USED] = AllocRegName( state->parm.used );
    call_ins->operands[CALL_OP_POPS] = AllocS32Const( 0 );
    call_ins->zap = &call_ins->operands[CALL_OP_USED]->r;
}
示例#11
0
_WCRTLINK short _WCI86FAR _CGRAPH _polygon_wxy( short fill, short numpts,
/*============================*/ struct _wxycoord _WCI86FAR *points )

/* This routine draws or fills a polygon specified by the array
   points[], in window coordinates. */

{
    short                   i;
    short                   needed_bytes;
    short                   x1, y1, x2, y2;
    short                   success;
    struct xycoord _WCI86FAR *   stack;


    if( numpts <= 2 ) {
        _ErrorStatus = _GRINVALIDPARAMETER;
        return( 0 );
    }
    success = 0;                            /* assume not successful    */
    if( _GrProlog() ) {
        if( fill == _GFILLINTERIOR ) {
            needed_bytes = _RoundUp( numpts * sizeof( struct xycoord ) );
#if defined( _DEFAULT_WINDOWS )
            stack = _MyAlloc( needed_bytes );
#else
            if( _stackavail() - needed_bytes > 0x100 ) {
                stack = __alloca( needed_bytes );
#endif
                for( i = 0; i < numpts; i++ ) {
                    stack[i].xcoord = _WtoPhysX( points[i].wx );
                    stack[i].ycoord = _WtoPhysY( points[i].wy );
                }
                success = _L1FillArea( numpts, stack );
#if defined( _DEFAULT_WINDOWS )
            _MyFree( stack );
            _GrEpilog();
#else
            } else {
                _ErrorStatus = _GRINSUFFICIENTMEMORY;
            }
#endif
        } else {
            x1 = _WtoPhysX( points[numpts-1].wx );
            y1 = _WtoPhysY( points[numpts-1].wy );
            for( i = 0; i < numpts; i++ ) {
                x2 = _WtoPhysX( points[i].wx );
                y2 = _WtoPhysY( points[i].wy );
                if( y1 < y2 ) {
                    _L1Line( x2, y2, x1, y1 );
                } else {
                    _L1Line( x1, y1, x2, y2 );
                }
                x1 = x2;
                y1 = y2;
            }
            success = 1;
        }
        _GrEpilog();
    }
    return( success );
}
示例#12
0
bool UT_Xpm2Bmp(UT_uint32 maxWidth,
				   UT_uint32 maxHeight,
				   const char ** pIconData,
				   UT_uint32 sizeofData,
				   HDC hdc,
				   UT_RGBColor * pBackgroundColor,
				   HBITMAP * pBitmap)
{
	// convert an XPM into a BMP using a DIB.
	// return true if successful.

	UT_ASSERT(pIconData && *pIconData);
	UT_ASSERT(sizeofData > 0);
	UT_ASSERT(pBackgroundColor);
	UT_ASSERT(pBitmap);

	// first row contains: width height, number of colors, chars per pixel

	UT_uint32 width, height, xpm_width, xpm_height, nrColors, charsPerPixel;
	UT_uint32 cut_left, cut_top;
	UT_uint32 n = sscanf(pIconData[0],"%ld %ld %ld %ld",
						 &xpm_width,&xpm_height,&nrColors,&charsPerPixel);
	UT_ASSERT(n == 4);
	UT_ASSERT(xpm_width > 0);
	UT_ASSERT(xpm_height > 0);

	UT_ASSERT(charsPerPixel > 0);

	width = xpm_width < maxWidth ? xpm_width : maxWidth;
	cut_left = xpm_width - width;
	cut_left -= cut_left / 2;
	height = xpm_height < maxHeight ? xpm_height : maxHeight;
	cut_top = xpm_height - height;
	cut_top -= cut_top / 2;
	
	UT_uint32 sizeofColorData = nrColors * sizeof(RGBQUAD);
	UT_uint32 widthRoundedUp = _RoundUp(width,sizeof(LONG));
	UT_uint32 rowPadding = widthRoundedUp - width;
	UT_uint32 sizeofPixelData = widthRoundedUp * height;
	UT_uint32 sizeofStructure = sizeof(BITMAPINFOHEADER) + sizeofColorData + sizeofPixelData;

	UT_Byte * pInfo = (UT_Byte *)UT_calloc(1,sizeofStructure);
	if (!pInfo)
		return false;

	BITMAPINFO * pbmi = (BITMAPINFO *)pInfo;
	BITMAPINFOHEADER * pbmih = &pbmi->bmiHeader;
	RGBQUAD * pRGB = (RGBQUAD *)(pInfo + sizeof(BITMAPINFOHEADER));
	UT_Byte * pPixel = (UT_Byte *)(pInfo + sizeof(BITMAPINFOHEADER) + sizeofColorData);

	pbmih->biSize			= sizeof(BITMAPINFOHEADER);
	pbmih->biWidth			= width;
	pbmih->biHeight			= -(LONG)height;	// minus height gives us a top-down bitmap
	pbmih->biPlanes			= 1;
	pbmih->biBitCount		= 8;
	pbmih->biCompression	= BI_RGB;
	pbmih->biSizeImage		= 0;
	pbmih->biXPelsPerMeter	= 0;
	pbmih->biYPelsPerMeter	= 0;
	pbmih->biClrUsed		= nrColors;	// should we verify that they are all actually used ??
	pbmih->biClrImportant	= 0;

	UT_StringPtrMap hash(256);
	UT_RGBColor color(0,0,0);
	
	// walk thru the palette

	// use a local UT_String, else every call to hash.insert and hash.pick
	// creates and destroys its own UT_String
	UT_String sTmp;

	const char ** pIconDataPalette = &pIconData[1];
	for (UT_uint32 k=0; (k < nrColors); k++)
	{
		char bufSymbol[10] = { 0 };
		char bufKey[10];
		char bufColorValue[100];

		// we expect something of the form: ".. c #000000"
		// or we can accpet ".. g #000000" for gray scale
		// but we allow a space as a character in the symbol, so we
		// get the first field the hard way.

		for (UT_uint32 kPx=0; (kPx < charsPerPixel); kPx++)
			bufSymbol[kPx] = pIconDataPalette[k][kPx];
		UT_ASSERT(strlen(bufSymbol) == charsPerPixel);
		
		UT_uint32 nf = sscanf(&pIconDataPalette[k][charsPerPixel+1]," %s %s",&bufKey,&bufColorValue);
		UT_ASSERT(nf == 2);
		UT_ASSERT(bufKey[0] == 'c' || bufKey[0] == 'g');

		// make the ".." a hash key and store our color index as the data.
		// we add k+1 because the hash code does not like null pointers...
		sTmp = bufSymbol;
		hash.insert(sTmp, (void *)(k+1));

		// store the actual color value in the rgb quad array with our color index.

		if (g_ascii_strcasecmp(bufColorValue,"None")==0)
		{
			pRGB[k].rgbRed		= pBackgroundColor->m_red;
			pRGB[k].rgbGreen	= pBackgroundColor->m_grn;
			pRGB[k].rgbBlue		= pBackgroundColor->m_blu;
			pRGB[k].rgbReserved	= 0;
		}
		else
		{
			// TODO fix this to also handle #ffffeeeedddd type color references
			
			UT_ASSERT((bufColorValue[0] == '#') && strlen(bufColorValue)==7);
			UT_parseColor(bufColorValue, color);
			pRGB[k].rgbRed		= color.m_red;
			pRGB[k].rgbGreen	= color.m_grn;
			pRGB[k].rgbBlue		= color.m_blu;
			pRGB[k].rgbReserved	= 0;
		}
	}

	// walk thru the image data

	const char ** pIconDataImage = &pIconDataPalette[nrColors];
	for (UT_uint32 kRow=0; (kRow < height); kRow++)
	{
		const char * p = pIconDataImage[kRow+cut_top];
		
		p += cut_left * charsPerPixel;
		for (UT_uint32 kCol=0; (kCol < width); kCol++)
		{
			char bufPixel[10] = { 0 };
			for (UT_uint32 kPx=0; (kPx < charsPerPixel); kPx++)
				bufPixel[kPx] = *p++;

			sTmp = bufPixel;
			guint32 pEntry = (guint32) hash.pick(sTmp);
			*pPixel++ = ((UT_Byte)(pEntry)) - 1;
		}

		pPixel += rowPadding;
	}

	UT_ASSERT(pPixel == (pInfo + sizeofStructure));
	pPixel = (UT_Byte *)(pInfo + sizeof(BITMAPINFOHEADER) + sizeofColorData);
	
	HBITMAP hBitmap = CreateDIBitmap(hdc,pbmih,CBM_INIT,pPixel,pbmi,DIB_RGB_COLORS);
	*pBitmap = hBitmap;

	g_free(pInfo);
	
	return (hBitmap != 0);
}