int RenderCurses::render(Pagination* pagination, unsigned int pageNum, bool doBlit) { clc::Log::info("ocher.render.ncurses", "render page %u %u", pageNum, doBlit); m_x = 0; m_y = 0; if (m_height) { wclear(m_scr); } unsigned int layoutOffset; unsigned int strOffset; if (!pageNum) { layoutOffset = 0; strOffset = 0; } else if (! pagination->get(pageNum-1, &layoutOffset, &strOffset)) { // Previous page not already paginated? // Perhaps at end of book? clc::Log::error("ocher.renderer.ncurses", "page %u not found", pageNum); return -1; } const unsigned int N = m_layout.size(); const char *raw = m_layout.data(); ASSERT(layoutOffset < N); for (unsigned int i = layoutOffset; i < N; ) { ASSERT(i+2 <= N); uint16_t code = *(uint16_t*)(raw+i); i += 2; unsigned int opType = (code>>12)&0xf; unsigned int op = (code>>8)&0xf; unsigned int arg = code & 0xff; switch (opType) { case Layout::OpPushTextAttr: clc::Log::debug("ocher.render.ncurses", "OpPushTextAttr"); switch (op) { case Layout::AttrBold: pushAttrs(); a[ai].b = 1; if (doBlit) applyAttrs(1); break; case Layout::AttrUnderline: pushAttrs(); a[ai].ul = 1; if (doBlit) applyAttrs(1); break; case Layout::AttrItalics: pushAttrs(); a[ai].em = 1; if (doBlit) applyAttrs(1); break; case Layout::AttrSizeRel: pushAttrs(); break; case Layout::AttrSizeAbs: pushAttrs(); break; default: clc::Log::error("ocher.render.ncurses", "unknown OpPushTextAttr"); ASSERT(0); break; } break; case Layout::OpPushLineAttr: clc::Log::debug("ocher.render.ncurses", "OpPushLineAttr"); switch (op) { case Layout::LineJustifyLeft: break; case Layout::LineJustifyCenter: break; case Layout::LineJustifyFull: break; case Layout::LineJustifyRight: break; default: clc::Log::error("ocher.render.ncurses", "unknown OpPushLineAttr"); ASSERT(0); break; } break; case Layout::OpCmd: switch (op) { case Layout::CmdPopAttr: clc::Log::trace("ocher.render.ncurses", "OpCmd CmdPopAttr"); if (arg == 0) arg = 1; while (arg--) popAttrs(); break; case Layout::CmdOutputStr: { clc::Log::trace("ocher.render.ncurses", "OpCmd CmdOutputStr"); ASSERT(i + sizeof(clc::Buffer*) <= N); clc::Buffer *str = *(clc::Buffer**)(raw+i); ASSERT(strOffset <= str->size()); int breakOffset = outputWrapped(str, strOffset, doBlit); strOffset = 0; if (breakOffset >= 0) { pagination->set(pageNum, i-2, breakOffset); if (doBlit) { refreshCDKScreen(m_screen); } clc::Log::debug("ocher.renderer.ncurses", "page %u break", pageNum); return 0; } i += sizeof(clc::Buffer*); break; } case Layout::CmdForcePage: clc::Log::trace("ocher.render.ncurses", "OpCmd CmdForcePage"); break; default: clc::Log::error("ocher.render.ncurses", "unknown OpCmd"); ASSERT(0); break; } break; case Layout::OpSpacing: break; case Layout::OpImage: break; default: clc::Log::error("ocher.render.ncurses", "unknown op type"); ASSERT(0); break; }; } clc::Log::debug("ocher.renderer.ncurses", "page %u done", pageNum); refreshCDKScreen(m_screen); return 1; }
// TODO: speed stats // TODO: faster: max_advance_width int RenderFb::render(Pagination* pagination, unsigned int pageNum, bool doBlit) { clc::Log::info("ocher.renderer.fb", "render page %u %u", pageNum, doBlit); m_penX = settings.marginLeft; m_penY = settings.marginTop + g_ft->getAscender(); if (doBlit) m_fb->clear(); unsigned int layoutOffset; unsigned int strOffset; if (!pageNum) { layoutOffset = 0; strOffset = 0; } else if (! pagination->get(pageNum-1, &layoutOffset, &strOffset)) { // Previous page not already paginated? // Perhaps at end of book? clc::Log::error("ocher.renderer.fb", "page %u not found", pageNum); return -1; } const unsigned int N = m_layout.size(); const char *raw = m_layout.data(); Rect fullPage(0, 0, m_fb->width(), m_fb->height()); ASSERT(layoutOffset < N); for (unsigned int i = layoutOffset; i < N; ) { ASSERT(i+2 <= N); uint16_t code = *(uint16_t*)(raw+i); i += 2; unsigned int opType = (code>>12)&0xf; unsigned int op = (code>>8)&0xf; unsigned int arg = code & 0xff; switch (opType) { case Layout::OpPushTextAttr: clc::Log::trace("ocher.render.fb", "OpPushTextAttr"); switch (op) { case Layout::AttrBold: pushAttrs(); a[ai].b = 1; break; case Layout::AttrUnderline: pushAttrs(); a[ai].ul = 1; break; case Layout::AttrItalics: pushAttrs(); a[ai].em = 1; break; case Layout::AttrSizeRel: pushAttrs(); clc::Log::debug("ocher.render.fb", "font rel %d", (int)arg); a[ai].pts += (int)arg; m_ft->setSize(a[ai].pts); break; case Layout::AttrSizeAbs: pushAttrs(); clc::Log::debug("ocher.render.fb", "font abs %d", (int)arg); a[ai].pts = (int)arg; m_ft->setSize(a[ai].pts); break; default: clc::Log::error("ocher.render.fb", "unknown OpPushTextAttr"); ASSERT(0); break; } break; case Layout::OpPushLineAttr: clc::Log::debug("ocher.render.fb", "OpPushLineAttr"); switch (op) { case Layout::LineJustifyLeft: break; case Layout::LineJustifyCenter: break; case Layout::LineJustifyFull: break; case Layout::LineJustifyRight: break; default: clc::Log::error("ocher.render.fb", "unknown OpPushLineAttr"); ASSERT(0); break; } break; case Layout::OpCmd: switch (op) { case Layout::CmdPopAttr: clc::Log::trace("ocher.render.fb", "OpCmd CmdPopAttr"); if (arg == 0) arg = 1; while (arg--) popAttrs(); // TODO: only reset what has changed clc::Log::debug("ocher.render.fb", "font pop %d", a[ai].pts); m_ft->setSize(a[ai].pts); break; case Layout::CmdOutputStr: { clc::Log::trace("ocher.render.fb", "OpCmd CmdOutputStr"); ASSERT(i + sizeof(clc::Buffer*) <= N); clc::Buffer *str = *(clc::Buffer**)(raw+i); ASSERT(strOffset <= str->size()); int breakOffset = outputWrapped(str, strOffset, doBlit); strOffset = 0; if (breakOffset >= 0) { pagination->set(pageNum, i-2, breakOffset); clc::Log::debug("ocher.renderer.fb", "page %u break", pageNum); if (doBlit) m_fb->update(&fullPage, false); return 0; } i += sizeof(clc::Buffer*); break; } case Layout::CmdForcePage: clc::Log::trace("ocher.render.fb", "OpCmd CmdForcePage"); break; default: clc::Log::error("ocher.render.fb", "unknown OpCmd"); ASSERT(0); break; } break; case Layout::OpSpacing: break; case Layout::OpImage: break; default: clc::Log::error("ocher.render.fb", "unknown op type"); ASSERT(0); break; }; } clc::Log::debug("ocher.renderer.fb", "page %u done", pageNum); if (doBlit) m_fb->update(&fullPage, false); return 1; }
int RenderFb::render(unsigned int pageNum, bool doBlit) { m_penX = settings.marginLeft; m_penY = settings.marginTop; m_fb->clear(); unsigned int layoutOffset; unsigned int strOffset; if (!pageNum) { layoutOffset = 0; strOffset = 0; } else if (! m_pagination.get(pageNum-1, &layoutOffset, &strOffset)) { // Previous page not already paginated? // Perhaps at end of book? return -1; } const unsigned int N = m_layout.size(); const char *raw = m_layout.data(); ASSERT(layoutOffset < N); for (unsigned int i = layoutOffset; i < N; ) { ASSERT(i+2 <= N); uint16_t code = *(uint16_t*)(raw+i); i += 2; unsigned int opType = (code>>12)&0xf; unsigned int op = (code>>8)&0xf; unsigned int arg = code & 0xff; switch (opType) { case Layout::OpPushTextAttr: clc::Log::debug("ocher.render.fb", "OpPushTextAttr"); switch (op) { case Layout::AttrBold: pushAttrs(); a[ai].b = 1; break; case Layout::AttrUnderline: pushAttrs(); a[ai].ul = 1; break; case Layout::AttrItalics: pushAttrs(); a[ai].em = 1; break; case Layout::AttrSizeRel: pushAttrs(); break; case Layout::AttrSizeAbs: pushAttrs(); break; default: clc::Log::error("ocher.render.fb", "unknown OpPushTextAttr"); ASSERT(0); break; } break; case Layout::OpPushLineAttr: clc::Log::debug("ocher.render.fb", "OpPushLineAttr"); switch (op) { case Layout::LineJustifyLeft: break; case Layout::LineJustifyCenter: break; case Layout::LineJustifyFull: break; case Layout::LineJustifyRight: break; default: clc::Log::error("ocher.render.fb", "unknown OpPushLineAttr"); ASSERT(0); break; } break; case Layout::OpCmd: switch (op) { case Layout::CmdPopAttr: clc::Log::debug("ocher.render.fb", "OpCmd CmdPopAttr"); if (arg == 0) arg = 1; while (arg--) popAttrs(); break; case Layout::CmdOutputStr: { clc::Log::debug("ocher.render.fb", "OpCmd CmdOutputStr"); ASSERT(i + sizeof(clc::Buffer*) <= N); clc::Buffer *str = *(clc::Buffer**)(raw+i); ASSERT(strOffset <= str->size()); int breakOffset = outputWrapped(str, strOffset, doBlit); strOffset = 0; if (breakOffset >= 0) { if (!doBlit) { m_pagination.set(pageNum, i-2, breakOffset); } m_fb->update(0, 0, m_fb->width(), m_fb->height(), false); // DDD return 0; } i += sizeof(clc::Buffer*); break; } case Layout::CmdForcePage: clc::Log::debug("ocher.render.fb", "OpCmd CmdForcePage"); break; default: clc::Log::error("ocher.render.fb", "unknown OpCmd"); ASSERT(0); break; } break; case Layout::OpSpacing: break; case Layout::OpImage: break; default: clc::Log::error("ocher.render.fb", "unknown op type"); ASSERT(0); break; }; } m_fb->update(0, 0, m_fb->width(), m_fb->height(), false); // DDD return 1; }