short Fl_MIDIKeyboard::find_key(int X, int Y) { X -= keyboard->x(); Y = (_type == MKB_HORIZONTAL ? Y - keyboard->y() : keyboard->y() + keyboard->h() - Y); if (X < 0 || Y < 0 || X > keyboard->w() || Y > keyboard->h()) return -1; uchar min = _firstkey; // binary search uchar max = _lastkey; uchar mid = min + (max - min) / 2; if(_type == MKB_HORIZONTAL) { if (X >= keyscoord[max]) return max; do { if (X >= keyscoord[mid]) min = mid; else max = mid; mid = min + (max - min) / 2; } while (max - min > 1); if (Y > _b_height) return (is_black(min) ? mid -1 : mid); // (X, Y) is below black keys else if (is_black(mid)) return mid; // (X, Y) is on the left side of a black key else if (isCF(mid)) return mid; // (X, Y) is on a C or F else if (X - keyscoord[mid] <= _b_width / 2 && mid > _firstkey) return mid - 1; // (X, Y) is on the right side of a black key else return mid; // (X, Y) is between two black keys } else { if (Y >= keyscoord[max]) return max; do { if (Y >= keyscoord[mid]) min = mid; else max = mid; mid = min + (max - min) / 2; } while (max - min > 1); if (X > _b_height) return (is_black(min) ? mid -1 : mid); else if (is_black(mid)) return mid; else if (isCF(mid)) return mid; else if (Y - keyscoord[mid] <= _b_width / 2 && mid > _firstkey) return mid - 1; else return mid; } }
void Fl_MIDIKeyboard::draw(void) { // fltk draw() override Fl_Scroll::draw(); fl_push_clip(x()+Fl::box_dx(box()), y()+Fl::box_dy(box()), w()-Fl::box_dw(box()), h()-Fl::box_dh(box())); int X = keyboard->x(), Y = keyboard->y(); int press_diam = _b_width-2; int press_w_h_offs = _b_height + (_key_height - _b_height - press_diam) / 2; int press_w_w_offs = (int)((_key_width-press_diam) / 2); int press_b_h_offs = _b_height - press_diam - 2; uchar bk = is_black(_bottomkey) ? _bottomkey-1 : _bottomkey; // need to begin with a white key fl_color(FL_BLACK); if (_type == MKB_HORIZONTAL) { int y_b_offs = Y + _b_height; for (int i = bk, cur_x = X + keyscoord[bk]; i <= _topkey; i++, cur_x = X + keyscoord[i]) { if (is_black(i)) { fl_rectf(cur_x, Y, _b_width, _b_height); if (pressed_keys[i]) { fl_color(FL_RED); fl_pie(cur_x, Y + press_b_h_offs, press_diam, press_diam, 0, 360); fl_color(FL_BLACK); } } else { if (pressed_keys[i]) { fl_color(FL_RED); fl_pie(cur_x + press_w_w_offs, Y + press_w_h_offs, press_diam, press_diam, 0, 360); fl_color(FL_BLACK); } isCF(i) ? fl_line(cur_x, Y, cur_x, Y + _key_height) : fl_line(cur_x, y_b_offs, cur_x, Y + _key_height); } } } else { Y += keyboard->h(); int x_b_offs = X + _b_height; for (int i = bk, cur_y = Y - keyscoord[bk]; i <= _topkey; i++, cur_y = Y - keyscoord[i]) { if (is_black(i)) { fl_rectf(X, cur_y - _b_width, _b_height, _b_width); if (pressed_keys[i]) { fl_color(FL_RED); fl_pie(X + press_b_h_offs, cur_y - press_diam, press_diam, press_diam, 0, 360); fl_color(FL_BLACK); } } else { if (pressed_keys[i]) { fl_color(FL_RED); fl_pie(X + press_w_h_offs, cur_y - press_w_w_offs - press_diam, press_diam, press_diam, 0, 360); fl_color(FL_BLACK); } isCF(i) ? fl_line(X, cur_y, X + _key_height, cur_y) : fl_line(x_b_offs, cur_y, X + _key_height, cur_y); } } } fl_pop_clip(); }
/** * Create blocks for each entry point as well as ordinary control * flow boundaries. Calls are not treated as basic-block ends. */ void GraphBuilder::createBlocks() { PC bc = m_unit->entry(); m_graph->param_count = m_func->params().size(); m_graph->first_linear = createBlock(m_func->base()); // DV entry points m_graph->entries = new (m_arena) Block*[m_graph->param_count + 1]; int dv_index = 0; for (Range<Func::ParamInfoVec> p(m_func->params()); !p.empty(); ) { const Func::ParamInfo& param = p.popFront(); m_graph->entries[dv_index++] = !param.hasDefaultValue() ? 0 : createBlock(param.funcletOff()); } // main entry point assert(dv_index == m_graph->param_count); m_graph->entries[dv_index] = createBlock(m_func->base()); // ordinary basic block boundaries for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); if (isCF(pc) && !i.empty()) createBlock(i.front()); if (isSwitch(*reinterpret_cast<const Op*>(pc))) { foreachSwitchTarget(reinterpret_cast<const Op*>(pc), [&](Offset& o) { createBlock(pc + o); }); } else { Offset target = instrJumpTarget((Op*)bc, pc - bc); if (target != InvalidAbsoluteOffset) createBlock(target); } } }
/** * Create blocks for each entry point as well as ordinary control * flow boundaries. Calls are not treated as basic-block ends. */ void GraphBuilder::createBlocks() { PC bc = m_unit->entry(); m_graph->param_count = m_func->params().size(); m_graph->first_linear = createBlock(m_func->base()); // DV entry points m_graph->entries = new (m_arena) Block*[m_graph->param_count + 1]; int dv_index = 0; for (auto& param : m_func->params()) { m_graph->entries[dv_index++] = !param.hasDefaultValue() ? 0 : createBlock(param.funcletOff); } // main entry point assert(dv_index == m_graph->param_count); m_graph->entries[dv_index] = createBlock(m_func->base()); // ordinary basic block boundaries for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); if ((isCF(pc) || isTF(pc)) && !i.empty()) createBlock(i.front()); if (isSwitch(peek_op(pc))) { foreachSwitchTarget(pc, [&](Offset o) { createBlock(pc + o); }); } else { Offset target = instrJumpTarget(bc, pc - bc); if (target != InvalidAbsoluteOffset) createBlock(target); } } }
void printInstr(const Unit* unit, PC pc) { std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" << (isCF(pc) ? "C":" ") << (isTF(pc) ? "T":" ") << (isFF(pc) ? "F":" ") << std::setw(3) << instrLen(pc) << " " << instrToString(pc, unit) << std::endl; }
void printInstr(const Unit* unit, PC pc) { Opcode* op = (Opcode*)pc; std::cout << " " << std::setw(4) << (pc - unit->entry()) << ":" << (isCF(pc) ? "C":" ") << (isTF(pc) ? "T":" ") << (isFF(pc) ? "F":" ") << std::setw(3) << instrLen(op) << " " << instrToString(op, unit) << std::endl; }
/** * Link ordinary blocks with ordinary edges and set their last instruction * and end offsets */ void GraphBuilder::linkBlocks() { PC bc = m_unit->entry(); Block* block = m_graph->first_linear; block->id = m_graph->block_count++; for (InstrRange i = funcInstrs(m_func); !i.empty(); ) { PC pc = i.popFront(); block->last = pc; if (isCF(pc)) { if (isSwitch(*reinterpret_cast<const Op*>(pc))) { int i = 0; foreachSwitchTarget((Op*)pc, [&](Offset& o) { succs(block)[i++] = at(pc + o); }); } else { Offset target = instrJumpTarget((Op*)bc, pc - bc); if (target != InvalidAbsoluteOffset) { assert(numSuccBlocks(block) > 0); succs(block)[numSuccBlocks(block) - 1] = at(target); } } } PC next_pc = !i.empty() ? i.front() : m_unit->at(m_func->past()); Block* next = at(next_pc); if (next) { block->next_linear = next; block->end = next_pc; if (!isTF(pc)) { assert(numSuccBlocks(block) > 0); succs(block)[0] = next; } block = next; block->id = m_graph->block_count++; } } block->end = m_unit->at(m_func->past()); }