/*
//  Given an input string of characters and a location in which to start looking
//  calculate, using the state table, which one is the last character of the syllable
//  that starts in the starting position.
*/
static int myanmar_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
{
    const HB_UChar16 *uc = s + start;
    int state = 0;
    int pos = start;
    *invalid = FALSE;

    while (pos < end) {
        MymrCharClass charClass = getMyanmarCharClass(*uc);
        state = mymrStateTable[state][charClass & Mymr_CF_CLASS_MASK];
        if (pos == start)
            *invalid = (HB_Bool)(charClass & Mymr_CF_DOTTED_CIRCLE);

        MMDEBUG("state[%d]=%d class=%8x (uc=%4x)", pos - start, state, charClass, *uc);

        if (state < 0) {
            if (state < -1)
                --pos;
            break;
        }
        ++uc;
        ++pos;
    }
    return pos;
}
bool
Track::Private::play(int _iterations)
{
	/* sanity checks */
	if (_iterations == 0) {
		MMDEBUG("Trying to play track with no iterations");
		if (iterations) stop();
		return(false);
	}
	else if (iterations) {
		MMERROR("Track already playing!");
		return(false);
	}

	iterations = _iterations;
	skip_decode = false;
	codec->reset();

	bsize = pcm->bufferSize();
	buffer = new char[bsize];

	update();

	return(true);
}
void
Track::Private::update(void)
{
	if (!buffer) return;

	/* sanity checks */

	if (!pcm) {
		MMDEBUG("Trying to play on an invalid PCM, stopping!");
		stop();
		return;
	}

	if (!pcm->isOpen()) {
		MMDEBUG("Trying to play on a closed PCM, stopping!");
		stop();
		return;
	}

	/* stop check */

	if (!skip_decode) {

		if (!iterations) {
			stop();
			return;
		}

		memset(buffer, 0, bsize);
		size_t l_read = codec->read(buffer, bsize);

		/*
		 * Reaching the end, check if we need to loop
		 */
		if (l_read < bsize && (iterations == -1 || --iterations)) {
			codec->reset();
			l_read += codec->read(buffer + l_read, bsize - l_read);
		}
		bdecoded = l_read;
	}
	else skip_decode = false;

	skip_decode = !pcm->mix(buffer, bdecoded);
}
void
PCM::Close(Handle *pcm_handle)
{
	assert(pcm_handle && "Tried to use invalid PCM device!");
	assert(pcm_handle->buffer && "Buffer missing from PCM handle!");

	delete[] pcm_handle->buffer, pcm_handle->buffer = 0;
	delete pcm_handle;

	MMDEBUG("Dummy PCM device closed.");
}
Exemple #5
0
/// @fn void termination_handler (int signum)
/// @brief termination signal handler.
/// @param[in] signum signal number
/// @return none
static void s_termination_handler (int signum)
{
    switch (signum) {
        case SIGINT:
        case SIGHUP:
        case SIGTERM:
            MMDEBUG(ID_APP,"\nsig received[%d]\n",signum);
            g_interrupt=true;
            break;
        default:
            fprintf(stderr,"\ns_termination_handler: sig not handled[%d]\n",signum);
            break;
    }
}
PCM::Handle *
PCM::Open(uint32_t sample_rate, uint8_t bit_depth, uint8_t channels)
{
	MMUNUSED(sample_rate);

	PCM::Handle *l_handle(new Handle);

	l_handle->buffer_size = (sample_rate/MARSHMALLOW_ENGINE_FRAMERATE) * (bit_depth/8) * channels;
	l_handle->buffer = new char[l_handle->buffer_size];

	MMDEBUG("Dummy PCM device opened.");

	return(l_handle);
}
HB_Bool HB_MyanmarShape(HB_ShaperItem *item)
{
    HB_Bool openType = FALSE;
    unsigned short *logClusters = item->log_clusters;

    HB_ShaperItem syllable = *item;
    int first_glyph = 0;

    int sstart = item->item.pos;
    int end = sstart + item->item.length;
    int i = 0;

    assert(item->item.script == HB_Script_Myanmar);
#ifndef NO_OPENTYPE
    openType = HB_SelectScript(item, myanmar_features);
#endif

    MMDEBUG("myanmar_shape: from %d length %d", item->item.pos, item->item.length);
    while (sstart < end) {
        HB_Bool invalid;
        int send = myanmar_nextSyllableBoundary(item->string, sstart, end, &invalid);
        MMDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
               invalid ? "TRUE" : "FALSE");
        syllable.item.pos = sstart;
        syllable.item.length = send-sstart;
        syllable.glyphs = item->glyphs + first_glyph;
        syllable.attributes = item->attributes + first_glyph;
        syllable.advances = item->advances + first_glyph;
        syllable.offsets = item->offsets + first_glyph;
        syllable.num_glyphs = item->num_glyphs - first_glyph;
        if (!myanmar_shape_syllable(openType, &syllable, invalid)) {
            MMDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);
            item->num_glyphs += syllable.num_glyphs;
            return FALSE;
        }

        /* fix logcluster array */
        MMDEBUG("syllable:");
        for (i = first_glyph; i < first_glyph + (int)syllable.num_glyphs; ++i)
            MMDEBUG("        %d -> glyph %x", i, item->glyphs[i]);
        MMDEBUG("    logclusters:");
        for (i = sstart; i < send; ++i) {
            MMDEBUG("        %d -> glyph %d", i, first_glyph);
            logClusters[i-item->item.pos] = first_glyph;
        }
        sstart = send;
        first_glyph += syllable.num_glyphs;
    }
    item->num_glyphs = first_glyph;
    return TRUE;
}
Exemple #8
0
MARSHMALLOW_NAMESPACE_USE

static void
SignalHandler(int signal, siginfo_t *siginfo, void *context)
{
	MMUNUSED(signal);
	MMUNUSED(siginfo);
	MMUNUSED(context);

	if (!Event::EventManager::Instance()) {
		MMERROR("\n*** Unix system signal received. But can't queueing quit event message yet... Ignoring. ***\n");
		return;
	}

	MMDEBUG("\n*** Unix system signal received. Queueing quit event message. ***\n");
	Event::SharedEvent l_event = new Event::QuitEvent;
	Event::EventManager::Instance()->queue(l_event);
}
static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)
{
    /*
//    MMDEBUG("\nsyllable from %d len %d, str='%s'", item->item.pos, item->item.length,
//	    item->string->mid(item->from, item->length).toUtf8().data());
    */

#ifndef NO_OPENTYPE
    const int availableGlyphs = item->num_glyphs;
#endif
    const HB_UChar16 *uc = item->string + item->item.pos;
    int vowel_e = -1;
    int kinzi = -1;
    int medial_ra = -1;
    int base = -1;
    int i;
    int len = 0;
    unsigned short reordered[32];
    unsigned char properties[32];
    enum {
	AboveForm = 0x01,
	PreForm = 0x02,
	PostForm = 0x04,
	BelowForm = 0x08
    };
    HB_Bool lastWasVirama = FALSE;
    int basePos = -1;

    memset(properties, 0, 32*sizeof(unsigned char));

    /* according to the table the max length of a syllable should be around 14 chars */
    assert(item->item.length < 32);

#ifdef MYANMAR_DEBUG
    printf("original:");
    for (i = 0; i < (int)item->item.length; i++) {
        printf("    %d: %4x", i, uc[i]);
    }
#endif
    for (i = 0; i < (int)item->item.length; ++i) {
        HB_UChar16 chr = uc[i];

        if (chr == Mymr_C_VOWEL_E) {
            vowel_e = i;
            continue;
        }
        if (i == 0
            && chr == Mymr_C_NGA
            && i + 2 < (int)item->item.length
            && uc[i+1] == Mymr_C_VIRAMA) {
            int mc = getMyanmarCharClass(uc[i+2]);
            /*MMDEBUG("maybe kinzi: mc=%x", mc);*/
            if ((mc & Mymr_CF_CONSONANT) == Mymr_CF_CONSONANT) {
                kinzi = i;
                continue;
            }
        }
        if (base >= 0
            && chr == Mymr_C_VIRAMA
            && i + 1 < (int)item->item.length
            && uc[i+1] == Mymr_C_RA) {
            medial_ra = i;
            continue;
        }
        if (base < 0)
            base = i;
    }

    MMDEBUG("\n  base=%d, vowel_e=%d, kinzi=%d, medial_ra=%d", base, vowel_e, kinzi, medial_ra);
    /* write vowel_e if found */
    if (vowel_e >= 0) {
        reordered[0] = Mymr_C_VOWEL_E;
        len = 1;
    }
    /* write medial_ra */
    if (medial_ra >= 0) {
        reordered[len] = Mymr_C_VIRAMA;
        reordered[len+1] = Mymr_C_RA;
        properties[len] = PreForm;
        properties[len+1] = PreForm;
        len += 2;
    }

    /* shall we add a dotted circle?
       If in the position in which the base should be (first char in the string) there is
       a character that has the Dotted circle flag (a character that cannot be a base)
       then write a dotted circle */
    if (invalid) {
        reordered[len] = C_DOTTED_CIRCLE;
        ++len;
    }

    /* copy the rest of the syllable to the output, inserting the kinzi
       at the correct place */
    for (i = 0; i < (int)item->item.length; ++i) {
        hb_uint16 chr = uc[i];
        MymrCharClass cc;
        if (i == vowel_e)
            continue;
        if (i == medial_ra || i == kinzi) {
            ++i;
            continue;
        }

        cc = getMyanmarCharClass(uc[i]);
        if (kinzi >= 0 && i > base && (cc & Mymr_CF_AFTER_KINZI)) {
            reordered[len] = Mymr_C_NGA;
            reordered[len+1] = Mymr_C_VIRAMA;
            if (len > 0)
                properties[len-1] = AboveForm;
            properties[len] = AboveForm;
            len += 2;
            kinzi = -1;
        }

        if (lastWasVirama) {
            int prop = 0;
            switch(cc & Mymr_CF_POS_MASK) {
            case Mymr_CF_POS_BEFORE:
                prop = PreForm;
                break;
            case Mymr_CF_POS_BELOW:
                prop = BelowForm;
                break;
            case Mymr_CF_POS_ABOVE:
                prop = AboveForm;
                break;
            case Mymr_CF_POS_AFTER:
                prop = PostForm;
                break;
            default:
                break;
            }
            properties[len-1] = prop;
            properties[len] = prop;
            if(basePos >= 0 && basePos == len-2)
                properties[len-2] = prop;
        }
        lastWasVirama = (chr == Mymr_C_VIRAMA);
        if(i == base)
            basePos = len;

        if ((chr != Mymr_C_SIGN_ZWNJ && chr != Mymr_C_SIGN_ZWJ) || !len) {
            reordered[len] = chr;
            ++len;
        }
    }
    if (kinzi >= 0) {
        reordered[len] = Mymr_C_NGA;
        reordered[len+1] = Mymr_C_VIRAMA;
        properties[len] = AboveForm;
        properties[len+1] = AboveForm;
        len += 2;
    }

    if (!item->font->klass->convertStringToGlyphIndices(item->font,
                                                        reordered, len,
                                                        item->glyphs, &item->num_glyphs,
                                                        item->item.bidiLevel % 2))
        return FALSE;

    MMDEBUG("after shaping: len=%d", len);
    for (i = 0; i < len; i++) {
	item->attributes[i].mark = FALSE;
	item->attributes[i].clusterStart = FALSE;
	item->attributes[i].justification = 0;
	item->attributes[i].zeroWidth = FALSE;
	MMDEBUG("    %d: %4x property=%x", i, reordered[i], properties[i]);
    }

    /* now we have the syllable in the right order, and can start running it through open type. */

#ifndef NO_OPENTYPE
    if (openType) {
 	hb_uint32 where[32];

        for (i = 0; i < len; ++i) {
            where[i] = ~(PreSubstProperty
                         | BelowSubstProperty
                         | AboveSubstProperty
                         | PostSubstProperty
                         | CligProperty
                         | PositioningProperties);
            if (properties[i] & PreForm)
                where[i] &= ~PreFormProperty;
            if (properties[i] & BelowForm)
                where[i] &= ~BelowFormProperty;
            if (properties[i] & AboveForm)
                where[i] &= ~AboveFormProperty;
            if (properties[i] & PostForm)
                where[i] &= ~PostFormProperty;
        }

        HB_OpenTypeShape(item, where);
        if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
            return FALSE;
    } else
#endif
    {
	MMDEBUG("Not using openType");
        HB_HeuristicPosition(item);
    }

    item->attributes[0].clusterStart = TRUE;
    return TRUE;
}
Exemple #10
0
/// @fn int s_trnc_state_machine(iow_socket_t *s, app_cfg_t *cfg)
/// @brief state machine implementation
/// @param[in] s iow_socket_t reference
/// @param[in] cfg app_cfg reference
/// @return none
static int s_trnc_state_machine(iow_socket_t *s, app_cfg_t *cfg)
{
    int retval=-1;
    int scycles=cfg->cycles;
    int trn_tx_count=0;
    int trn_rx_count=0;
    int trn_tx_bytes=0;
    int trn_rx_bytes=0;
    int trn_msg_count=0;
    int trn_msg_bytes=0;
    const char *reqstr="REQ\0";
    
    if (NULL!=s) {
        
        // initialize variables
        trn_message_t message;
        trn_message_t *pmessage = &message;
        mbtrn_header_t *pheader = &pmessage->data.header;
        mbtrn_sounding_t *psounding = &pmessage->data.sounding;
        
        memset(pmessage,0,sizeof(message));
        int hbeat_counter=0;
        int64_t test=0;
        byte *pread=NULL;
        uint32_t readlen=0;
        
        trnc_state_t state=ST_INIT;
        trnc_action_t action=AT_NOP;
        
        // state machine entry point
        while (state != ST_DONE && !g_interrupt) {
            
            // check states, assign actions
            switch (state) {
                case ST_INIT:
                    memset(&message,0,MBTRN_MAX_MSG_BYTES);
                    action = AT_CONNECT;
                    break;
                case ST_CONNECTED:
                    action=AT_WR_REQ;
                    break;
                case ST_REQ_PENDING:
                case ST_SUBSCRIBED:
                    memset(&message,0,MBTRN_MAX_MSG_BYTES);
                    action=AT_RD_MSG;
                    break;
                case ST_HBEAT_EXPIRED:
                    action=AT_WR_REQ;
                    break;
                    
                default:
                    break;
            }// switch
            
            // action: connect
            if (action == AT_CONNECT) {
                MMDEBUG(ID_APP,"connecting [%s:%d]\n",cfg->host,cfg->port);
                if( (test=iow_connect(s))==0 ) {
                    MMDEBUG(ID_APP,"connect OK\n");
                    state=ST_CONNECTED;
                }else{
                    MERROR("connect failed [%"PRId64"]\n",test);
                }
            }
            
            // action: write request
            if (action == AT_WR_REQ) {
                
                test=iow_sendto(s,NULL,(byte *)reqstr,4,0);
                
                MMDEBUG(ID_APP,"sendto REQ ret[%"PRId64"] [%d/%s]\n",test,errno,strerror(errno));
                
                if( test>0 ){
                    trn_tx_count++;
                    trn_tx_bytes+=test;
                    state=ST_REQ_PENDING;
                }else{
                    MMDEBUG(ID_APP,"sendto failed ret[%"PRId64"] [%d/%s]\n",test,errno,strerror(errno));
                }
            }
            
            // action: read response
            if (action == AT_RD_MSG) {
                pread = (byte *)&message;
                readlen = MBTRN_MAX_MSG_BYTES;
                // request message
                if ((test = iow_recvfrom(s, NULL, pread, readlen))>0) {
                    
                    trn_rx_bytes+=test;
                    trn_rx_count++;
                    
                    // check message type
                    if (pheader->type==MBTRN_MSGTYPE_ACK) {
                        MMDEBUG(ID_APP,"received ACK ret[%"PRId64"] [%08X]\n",test,pheader->type);
                        hbeat_counter=0;
                        state=ST_SUBSCRIBED;
                    }else if (pheader->type==MBTRN_MSGTYPE_MB1) {
                        MMDEBUG(ID_APP,"received MSG ret[%"PRId64"] type[%08X] size[%d] ping[%06d]\n",test,pheader->type,pheader->size,psounding->ping_number);
                        trn_msg_count++;
                        trn_msg_bytes+=test;
                        
                        action=AT_SHOW_MSG;
                        
                        if (state==ST_REQ_PENDING) {
                            state=ST_REQ_PENDING;
                        }else{
                            state=ST_SUBSCRIBED;
                        }
                        hbeat_counter++;
                        MMDEBUG(ID_APP,"hbeat[%d/%d]\n",hbeat_counter,cfg->hbeat);
                        if ( (hbeat_counter!=0) && (hbeat_counter%cfg->hbeat==0)) {
                            state=ST_HBEAT_EXPIRED;
                        }
                    }else{
                        // response not recognized
                        MMDEBUG(ID_APP,"invalid message [%08X]\n",pheader->type);
                    }
                }else{
                    // read returned error
                    //  MMDEBUG(ID_APP,"invalid message [%d]\n",test);
                    switch (errno) {
                        case EWOULDBLOCK:
                            // nothing to read
                            //   MMDEBUG(ID_APP,"err - [%d/%s]\n",errno, strerror(errno));
                            break;
                        case ENOTCONN:
                        case ECONNREFUSED:
                            // host disconnected
                            MMDEBUG(ID_APP,"err - server not connected [%d/%s]\n",errno, strerror(errno));
                            iow_socket_destroy(&s);
                            s = iow_socket_new(cfg->host, cfg->port, ST_UDP);
                            iow_set_blocking(s,(cfg->blocking==0?false:true));
                            sleep(5);
                            state=ST_INIT;
                            retval=-1;
                            break;
                        default:
                            MMDEBUG(ID_APP,"err ? [%d/%s]\n",errno, strerror(errno));
                            break;
                    }//switch
                }
            }
            
            // action: show message
            if (action == AT_SHOW_MSG) {
                MMDEBUG(ID_APP,"\nts[%.3f] ping[%06d] lat[%.4lf] lon[%.4lf]\nsd[%7.2lf] hdg[%6.2lf] nb[%03"PRIu32"]\n",
                        psounding->ts,
                        psounding->ping_number,
                        psounding->lat,
                        psounding->lon,
                        psounding->depth,
                        psounding->hdg,
                        (uint32_t)psounding->nbeams);
                uint32_t j=0;
                struct mbtrn_beam_data *bd=psounding->beams;
                for (j=0; j<psounding->nbeams; j++,bd++){
                    MMDEBUG(ID_APP,"n[%03"PRIu32"] atrk/X[% 10.3lf] ctrk/Y[% 10.3lf] dpth/Z[% 10.3lf]\n",
                            (uint32_t)bd->beam_num,
                            bd->rhox,
                            bd->rhoy,
                            bd->rhoz);
                }
            }
            
            // action: quit state machine
            if (action == AT_QUIT) {
                break;
            }
            
            // check cycles and signals
            scycles--;
            if(scycles==0){
                MTRACE();
                retval=0;
                state=ST_DONE;
            }
            
            if(g_interrupt){
                MTRACE();
                retval=-1;
                state=ST_DONE;
            }
            
        }// while !ST_DONE
    }//else invalid arg
    
    MMINFO(ID_APP,"tx count/bytes[%d/%d]\n",trn_tx_count,trn_tx_bytes);
    MMINFO(ID_APP,"rx count/bytes[%d/%d]\n",trn_rx_count,trn_rx_bytes);
    MMINFO(ID_APP,"trn count/bytes[%d/%d]\n",trn_msg_count,trn_msg_bytes);
    
    return retval;
}
Exemple #11
0
/// @fn void parse_args(int argc, char ** argv, app_cfg_t * cfg)
/// @brief parse command line args, set application configuration.
/// @param[in] argc number of arguments
/// @param[in] argv array of command line arguments (strings)
/// @param[in] cfg application config structure
/// @return none
void parse_args(int argc, char **argv, app_cfg_t *cfg)
{
    extern char WIN_DECLSPEC *optarg;
    int option_index;
    int c;
    bool help=false;
    bool version=false;
    
    static struct option options[] = {
        {"verbose", required_argument, NULL, 0},
        {"help", no_argument, NULL, 0},
        {"version", no_argument, NULL, 0},
        {"host", required_argument, NULL, 0},
        {"hbeat", required_argument, NULL, 0},
        {"blocking", required_argument, NULL, 0},
        {"cycles", required_argument, NULL, 0},
        {"bsize", required_argument, NULL, 0},
       {NULL, 0, NULL, 0}};

    // process argument list 
    while ((c = getopt_long(argc, argv, "", options, &option_index)) != -1){
        switch (c) {
                // long options all return c=0 
            case 0:
                // verbose 
                if (strcmp("verbose", options[option_index].name) == 0) {
                    sscanf(optarg,"%d",&cfg->verbose);
                }
                
                // help 
                else if (strcmp("help", options[option_index].name) == 0) {
                    help = true;
                }
                
                // version
                else if (strcmp("version", options[option_index].name) == 0) {
                    version = true;
                }
                
                // host 
                else if (strcmp("host", options[option_index].name) == 0) {

                    char *hsave=cfg->host;
                    char *ocopy=strdup(optarg);
                    cfg->host=strtok(ocopy,":");
                    if (cfg->host==NULL) {
                        cfg->host=TRNC_HOST_DFL;
                    }
                    char *ip = strtok(NULL,":");
                    if (ip!=NULL) {
                        sscanf(ip,"%d",&cfg->port);
                    }
                    // don't free ocopy here
                    if(hsave!=NULL){
                        free(hsave);
                    }
                }
                // blocking
                else if (strcmp("blocking", options[option_index].name) == 0) {
                    sscanf(optarg,"%d",&cfg->blocking);
                }
                // hbeat
                else if (strcmp("hbeat", options[option_index].name) == 0) {
                    sscanf(optarg,"%d",&cfg->hbeat);
                }
                // cycles 
                else if (strcmp("cycles", options[option_index].name) == 0) {
                    sscanf(optarg,"%d",&cfg->cycles);
                }
                // buffer size 
                else if (strcmp("bsize", options[option_index].name) == 0) {
                    sscanf(optarg,"%u",&cfg->bsize);
                    cfg->bsize = (cfg->bsize>0 ? cfg->bsize : TRNC_BUF_LEN);

                }
                break;
            default:
                help=true;
                break;
        }
        if (version) {
            mbtrn_show_app_version(TRNC_NAME,TRNC_BUILD);
            exit(0);
        }
        if (help) {
            mbtrn_show_app_version(TRNC_NAME,TRNC_BUILD);
            s_show_help();
            exit(0);
        }
    }// while
    
    // configure debug output
    switch (cfg->verbose) {
        case 0:
            mdb_set(ID_APP,MDL_INFO);
            break;
        case 1:
            mdb_set(ID_APP,MDL_DEBUG);
            break;
        case 2:
            mdb_set(ID_APP,MDL_DEBUG);
            mdb_set(ID_APP2,MDL_DEBUG);
            break;
        case 3:
            mdb_set(ID_APP,MDL_DEBUG);
            mdb_set(ID_APP2,MDL_DEBUG);
            mdb_set(ID_APP3,MDL_DEBUG);
            break;
        default:
            mdb_set(ID_APP,MDL_ERROR);
            break;
    }
    
    
    MMDEBUG(ID_APP,"verbose [%s]\n",(cfg->verbose?"Y":"N"));
    MMDEBUG(ID_APP,"host    [%s]\n",cfg->host);
    MMDEBUG(ID_APP,"port    [%d]\n",cfg->port);
    MMDEBUG(ID_APP,"hbeat   [%d]\n",cfg->hbeat);
    MMDEBUG(ID_APP,"block   [%s]\n",(cfg->blocking==0?"N":"Y"));
    MMDEBUG(ID_APP,"cycles  [%d]\n",cfg->cycles);
    MMDEBUG(ID_APP,"bsize   [%d]\n",cfg->bsize);
}
void
Backend::Finalize(void)
{
	MMDEBUG("Dummy audio backend finalized");
}
bool
Backend::Initialize(void)
{
	MMDEBUG("Dummy audio backend initialized");
	return(true);
}
Exemple #14
0
// Porting the pango-myanmar module for reordering a syllable correctly when shape it.
static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)
{
    /*
//    MMDEBUG("\nsyllable from %d len %d, str='%s'", item->item.pos, item->item.length,
//      item->string->mid(item->from, item->length).toUtf8().data());
    */

#ifndef NO_OPENTYPE
    const int availableGlyphs = item->num_glyphs;
#endif
    const HB_UChar16 *uc = item->string + item->item.pos;
    int vowel_e = -1;
    int kinzi = -1;
    int medial_ra = -1;
    int i;
    int len = 0;
    unsigned short reordered[32];
    unsigned char properties[32];
    enum {
        AboveForm = 0x01, PreForm = 0x02, PostForm = 0x04, BelowForm = 0x08
    };

    memset(properties, 0, 32*sizeof(unsigned char));

    /* according to the table the max length of a syllable should be around 14 chars */
    assert(item->item.length < 32);

#ifdef MYANMAR_DEBUG
    printf("original:");
    for (i = 0; i < (int)item->item.length; i++) {
        MMDEBUG("    %d: %4x", i, uc[i]);
    }
#endif

    len = 0;
    MymrCharClass char_class;
    int basE = 0, cursor = 0;
    while (basE < (int)item->item.length) {
        medial_ra = -1;  /* There is no Medial Ra, if found this value will change */
        kinzi = -1; /* There is no Kinzi, if found this value will change */
        if (getMyanmarCharClass(uc[cursor]) & Mymr_CF_VIRAMA)
            basE = findBase(uc, cursor, (int)item->item.length);
        else
            basE = findBase(uc, cursor + 1, (int)item->item.length);

        for (i = cursor; i < basE; i += 1) {
            char_class = getMyanmarCharClass(uc[i]);

            /* look for kinzi and remember position */
            if (((char_class & Mymr_CF_CLASS_MASK) == Mymr_CC_NGA) && (i + 2 < basE)
                    && ((getMyanmarCharClass(uc[i + 1]) & Mymr_CF_CLASS_MASK) == Mymr_CC_ASAT)
                    && (getMyanmarCharClass(uc[i + 2]) & Mymr_CF_VIRAMA)) {
                if (i + 3 == (int)item->item.length) {
                    reordered[len] = Mymr_C_DOTTED_CIRCLE;
                    len += 1;
                } else if (getMyanmarCharClass(uc[i + 3]) & Mymr_CF_CONSONANT) {
                    kinzi = i;
                    cursor += 3;
                }
            }

            /* if vowel e, wirte it out */
            if (i > 0 && ((getMyanmarCharClass(uc[i -1]) & Mymr_CF_CLASS_MASK) != Mymr_CC_CONSONANT)
                    && (char_class & Mymr_CF_DEP_VOWEL) && (char_class & Mymr_CF_POS_BEFORE)) {
                reordered[len] = Mymr_C_VOWEL_E;
                properties[len] = PostForm;
                len += 1;
            }

            /* look for medial ra and remember position */
            if ((char_class & Mymr_CF_CLASS_MASK) == Mymr_CC_MEDIAL_R) {
                medial_ra = i;
            }
        }

        /* write medial ra if found  */
        if (medial_ra > -1) {
            reordered[len] = Mymr_C_MEDIAL_R;
            properties[len] = PreForm;
            len += 1;
        }

        /* shall we add a dotted circle?
         * If in the position in which the base should be (first char in the string) there is
         * a character that has the Dotted circle flag (a character that cannot be a base)
         * then write a dotted circle
         */
        if (getMyanmarCharClass(uc[cursor]) & Mymr_CF_DOTTED_CIRCLE) {
            /* add dotted circle */
            reordered[len] = Mymr_C_DOTTED_CIRCLE;
            len += 1;
        }

        /* copy what is left to the output, skipping before vowels and
         * medial Ra if they are present
         */
        for (i = cursor; i < basE; i += 1) {
            char_class = getMyanmarCharClass(uc[i]);

            /* skip vowel e, it was already processed */
            if (i > 0 && ((getMyanmarCharClass(uc[i -1]) & Mymr_CF_CLASS_MASK) != Mymr_CC_CONSONANT)
                    &&(char_class & Mymr_CF_DEP_VOWEL) && (char_class & Mymr_CF_POS_BEFORE)) {
                continue;
            }

            /* skip medial ra, it was already processed */
            if (i == medial_ra) {
                continue;
            }

            switch (char_class & Mymr_CF_POS_MASK) {
            case Mymr_CF_POS_ABOVE:
                reordered[len] = uc[i];
                properties[len] = AboveForm;
                len += 1;
                break;

            case Mymr_CF_POS_AFTER:
                reordered[len] = uc[i];
                properties[len] = PostForm;
                len += 1;
                break;

            case Mymr_CF_POS_BELOW:
                reordered[len] = uc[i];
                properties[len] = BelowForm;
                len += 1;
                break;

            default:
                /* assign the correct flags to Medials */
                if ((char_class & Mymr_CF_MEDIAL) && i + 1 < basE) {
                    if ((char_class & Mymr_CF_CLASS_MASK) == Mymr_CC_MEDIAL_Y) { /* medial ya which possess below and right */
                        reordered[len] = uc[i];
                        properties[len] = PostForm;
                        len += 1;
                        break;
                    } else { /* others wa, ha only below */
                        reordered[len] = uc[i];
                        properties[len] = BelowForm;
                        len += 1;
                        break;
                    }
                }

                if ((char_class & Mymr_CF_VIRAMA) && i + 1 < basE) {
                    if ((getMyanmarCharClass(uc[i + 1]) & Mymr_CF_CLASS_MASK) == Mymr_CC_CONSONANT) { /* subscript consonant */
                        reordered[len] = uc[i];
                        properties[len] = BelowForm;
                        len += 1;
                        break;
                    }
                }

                /* assign the correct flags to consonant with subscript consonant */
                if ((char_class & Mymr_CF_CONSONANT) && i + 2 < basE) {
                    if ((getMyanmarCharClass(uc[i + 1]) & Mymr_CF_VIRAMA)
                            && (getMyanmarCharClass(uc[i + 2]) & Mymr_CF_CLASS_MASK) == Mymr_CC_CONSONANT) {
                        reordered[len] = uc[i];
                        properties[len] = BelowForm;
                        len += 1;
                        break;
                    }
                }

                /* kinzi_to_be */
                if (((char_class & Mymr_CF_CLASS_MASK) == Mymr_CC_NGA)
                        && (getMyanmarCharClass(uc[i + 1]) & Mymr_CF_ASAT)
                        && (getMyanmarCharClass(uc[i + 2]) & Mymr_CF_VIRAMA)
                        ) {
                    reordered[len] = uc[i];
                    i += 1;
                    reordered[len + 1] = uc[i];
                    i += 1;
                    reordered[len + 2] = uc[i];
                    properties[len] = AboveForm;
                    properties[len + 1] = AboveForm;
                    properties[len + 2] = AboveForm;
                    len += 3;
                    break;
                }

                /* default - any others */
                reordered[len] = uc[i];
                len += 1;
                break;
            }/* switch */

            if (kinzi > -1 && i == cursor) {
                reordered[len] = Mymr_C_NGA;
                reordered[len + 1] = Mymr_C_ASAT;
                reordered[len + 2] = Mymr_C_VIRAMA;
                properties[len] = AboveForm;
                properties[len + 1] = AboveForm;
                properties[len + 2] = AboveForm;
                len += 3;
            }
        } /* for: loop for a baseE */
        cursor = basE;
    } /* while: loop for a syllable*/

    if (!item->font->klass->convertStringToGlyphIndices(item->font,
                                                        reordered, len,
                                                        item->glyphs, &item->num_glyphs,
                                                        item->item.bidiLevel % 2))
        return FALSE;

    MMDEBUG("after shaping: len=%d", len);
    for (i = 0; i < len; i++) {
        item->attributes[i].mark = FALSE;
        item->attributes[i].clusterStart = FALSE;
        item->attributes[i].justification = 0;
        item->attributes[i].zeroWidth = FALSE;
        MMDEBUG("    %d: %4x property=%x", i, reordered[i], properties[i]);
    }

    /* now we have the syllable in the right order, and can start running it through open type. */

#ifndef NO_OPENTYPE
    if (openType) {
        hb_uint32 where[32];

        for (i = 0; i < len; ++i) {
            where[i] = ~(PreSubstProperty | BelowSubstProperty
                    | AboveSubstProperty | PostSubstProperty | CligProperty
                    | PositioningProperties);
            if (properties[i] & PreForm)
                where[i] &= ~PreFormProperty;
            if (properties[i] & BelowForm)
                where[i] &= ~BelowFormProperty;
            if (properties[i] & AboveForm)
                where[i] &= ~AboveFormProperty;
            if (properties[i] & PostForm)
                where[i] &= ~PostFormProperty;
        }

        HB_OpenTypeShape(item, where);
        if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
            return FALSE;
    } else
#endif
    {
        MMDEBUG("Not using openType");
        HB_HeuristicPosition(item);
    }

    item->attributes[0].clusterStart = TRUE;
    return TRUE;
}