From ce0b3acd6bb49a54b3eda7a1f0e76d517840f396 Mon Sep 17 00:00:00 2001 From: chrox Date: Fri, 26 Oct 2012 00:37:50 +0800 Subject: [PATCH] add config dialog for koptreader For now only line spaceing and word spaceing are configurable with 'F'/'Aa' commands. And device size are passed to k2pdfopt in place of the hard-coded default width and height(via @dpavlin). Conflicts: koptreader.lua --- djvu.c | 8 +- k2pdfopt.c | 20 ++++- k2pdfopt.h | 6 +- koptconfig.lua | 226 +++++++++++++++++++++++++++++++++++++++++++++++++ pdf.c | 9 +- 5 files changed, 261 insertions(+), 8 deletions(-) create mode 100644 koptconfig.lua diff --git a/djvu.c b/djvu.c index 7c75158b8..18b78737d 100644 --- a/djvu.c +++ b/djvu.c @@ -475,9 +475,13 @@ static int reflowPage(lua_State *L) { DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage"); DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext"); ddjvu_render_mode_t mode = (int) luaL_checkint(L, 3); + int width = luaL_checkint(L, 4); // framebuffer size + int height = luaL_checkint(L, 5); + double line_spacing = luaL_checknumber(L, 6); + double word_spacing = luaL_checknumber(L, 7); - int width, height; - k2pdfopt_djvu_reflow(page->page_ref, page->doc->context, mode, page->doc->pixelformat, dc->zoom); + k2pdfopt_djvu_reflow(page->page_ref, page->doc->context, mode, page->doc->pixelformat, dc->zoom, \ + width, height, line_spacing, word_spacing); k2pdfopt_rfbmp_size(&width, &height); k2pdfopt_rfbmp_zoom(&dc->zoom); diff --git a/k2pdfopt.c b/k2pdfopt.c index 5f2859129..889b92766 100644 --- a/k2pdfopt.c +++ b/k2pdfopt.c @@ -472,7 +472,8 @@ static void k2pdfopt_reflow_bmp(MASTERINFO *masterinfo, WILLUSBITMAP *src) { } void k2pdfopt_mupdf_reflow(fz_document *doc, fz_page *page, fz_context *ctx, \ - double zoom, double gamma, double rot_deg) { + double zoom, double gamma, double rot_deg, \ + int bb_width, int bb_height, double line_space, double word_space) { fz_device *dev; fz_pixmap *pix; fz_rect bounds,bounds2; @@ -480,6 +481,14 @@ void k2pdfopt_mupdf_reflow(fz_document *doc, fz_page *page, fz_context *ctx, \ fz_bbox bbox; WILLUSBITMAP _src, *src; + dst_userwidth = bb_width; // dst_width is adjusted in adjust_params_init + dst_userheight = bb_height; + vertical_line_spacing = line_space; + word_spacing = word_space; + + printf("k2pdfopt_mupdf_reflow width:%d height:%d, line space:%.2f, word space:%.2f\n", \ + bb_width,bb_height,vertical_line_spacing,word_spacing); + double dpp; double dpi = 250*zoom; do { @@ -533,11 +542,18 @@ void k2pdfopt_mupdf_reflow(fz_document *doc, fz_page *page, fz_context *ctx, \ } void k2pdfopt_djvu_reflow(ddjvu_page_t *page, ddjvu_context_t *ctx, \ - ddjvu_render_mode_t mode, ddjvu_format_t *fmt, double zoom) { + ddjvu_render_mode_t mode, ddjvu_format_t *fmt, double zoom, \ + int bb_width, int bb_height, double line_space, double word_space) { WILLUSBITMAP _src, *src; ddjvu_rect_t prect; ddjvu_rect_t rrect; int i, iw, ih, idpi, status; + + dst_userwidth = bb_width; // dst_width is adjusted in adjust_params_init + dst_userheight = bb_height; + vertical_line_spacing = line_space; + word_spacing = word_space; + double dpi = 250*zoom; while (!ddjvu_page_decoding_done(page)) diff --git a/k2pdfopt.h b/k2pdfopt.h index 1fef6d24d..51743b3c5 100644 --- a/k2pdfopt.h +++ b/k2pdfopt.h @@ -27,9 +27,11 @@ #include void k2pdfopt_mupdf_reflow(fz_document *doc, fz_page *page, fz_context *ctx, \ - double dpi, double gamma, double rot_deg); + double zoom, double gamma, double rot_deg, int bb_width, int bb_height, \ + double line_spacing, double word_spacing); void k2pdfopt_djvu_reflow(ddjvu_page_t *page, ddjvu_context_t *ctx, \ - ddjvu_render_mode_t mode, ddjvu_format_t *fmt, double dpi); + ddjvu_render_mode_t mode, ddjvu_format_t *fmt, double zoom, int bb_width, int bb_height, \ + double line_spacing, double word_spacing); void k2pdfopt_rfbmp_size(int *width, int *height); void k2pdfopt_rfbmp_ptr(unsigned char** bmp_ptr_ptr); void k2pdfopt_rfbmp_zoom(double *zoom); diff --git a/koptconfig.lua b/koptconfig.lua new file mode 100644 index 000000000..64f02c605 --- /dev/null +++ b/koptconfig.lua @@ -0,0 +1,226 @@ +require "font" +require "keys" +require "settings" + +KOPTOptions = { + { + name="line_spacing", + option_text="Line Spacing", + items_text={"small","medium","large"}, + current_item=2, + text_dirty=true, + marker_dirty={true, true, true}, + space={1.0, 1.2, 1.4}}, + { + name="word_spacing", + option_text="Word Spacing", + items_text={"small","medium","large"}, + current_item=2, + text_dirty=true, + marker_dirty={true, true, true}, + space={0.2, 0.375, 0.5}}, +} + +KOPTConfig = { + -- UI constants + HEIGHT = 200, -- height + MARGIN_BOTTOM = 20, -- window bottom margin + MARGIN_HORISONTAL = 75, -- window horisontal margin + OPTION_PADDING_T = 50, -- options top padding + OPTION_PADDING_H = 50, -- options horisontal padding + OPTION_SPACING_V = 35, -- options vertical spacing + VALUE_PADDING_H = 150, -- values horisontal padding + VALUE_SPACING_H = 10, -- values horisontal spacing + OPT_NAME_FONT_SIZE = 20, -- option name font size + OPT_VALUE_FONT_SIZE = 16, -- option value font size + + -- last pos text is drawn + text_pos = 0, + -- current selected option + current_option = 1, + -- page dirty + page_dirty = false, +} + +configurable = { + font_size = 1.0, + page_margin = 0.06, + line_spacing = 1.2, + word_spacing = 0.375, +} + +function KOPTConfig:drawBox(xpos, ypos, width, hight, bgcolor, bdcolor) + -- draw dialog border + local r = 6 -- round corners + fb.bb:paintRect(xpos, ypos+r, width, hight - 2*r, bgcolor) + blitbuffer.paintBorder(fb.bb, xpos, ypos, width, r, r, bgcolor, r) + blitbuffer.paintBorder(fb.bb, xpos, ypos+hight-2*r, width, r, r, bgcolor, r) +end + +function KOPTConfig:drawOptionName(xpos, ypos, option_index, text, font_face, refresh) + local xpos, ypos = xpos+self.OPTION_PADDING_H, ypos+self.OPTION_PADDING_T + if KOPTOptions[option_index].text_dirty or refresh then + --Debug("drawing option name:", KOPTOptions[option_index].option_text) + renderUtf8Text(fb.bb, xpos, ypos+self.OPTION_SPACING_V*(option_index-1), font_face, text, true) + end +end + +function KOPTConfig:drawOptionItem(xpos, ypos, option_index, item_index, text, font_face, refresh) + if item_index == 1 then + self.text_pos = 0 + end + + local xpos = xpos+self.OPTION_PADDING_H+self.VALUE_PADDING_H+self.VALUE_SPACING_H*(item_index-1)+self.text_pos + local ypos = ypos+self.OPTION_PADDING_T+self.OPTION_SPACING_V*(option_index-1) + + if KOPTOptions[option_index].text_dirty or refresh then + --Debug("drawing option:", KOPTOptions[option_index].option_text, "item:", text) + renderUtf8Text(fb.bb, xpos, ypos, font_face, text, true) + end + + local text_len = sizeUtf8Text(0, G_width, font_face, text, true).x + self.text_pos = self.text_pos + text_len + + if KOPTOptions[option_index].marker_dirty[item_index] then + --Debug("drawing option:", KOPTOptions[option_index].option_text, "marker:", text) + if item_index == KOPTOptions[option_index].current_item then + fb.bb:paintRect(xpos, ypos+5, text_len, 3,(option_index == self.current_option) and 15 or 5) + fb:refresh(1, xpos, ypos+5, text_len, 3) + else + fb.bb:paintRect(xpos, ypos+5, text_len, 3, 3) + fb:refresh(1, xpos, ypos+5, text_len, 3) + end + KOPTOptions[option_index].marker_dirty[item_index] = false + end +end + +function KOPTConfig:drawOptions(xpos, ypos, name_font, value_font, refresh) + local width, height = fb.bb:getWidth()-2*self.MARGIN_HORISONTAL, self.HEIGHT + for i=1,#KOPTOptions do + self:drawOptionName(xpos, ypos, i, KOPTOptions[i].option_text, name_font, refresh) + for j=1,#KOPTOptions[i].items_text do + self:drawOptionItem(xpos, ypos, i, j, KOPTOptions[i].items_text[j], value_font, refresh) + end + KOPTOptions[i].text_dirty = false + end +end + +function KOPTConfig:config(callback, reader) + local kopt_callback = callback + local koptreader = reader + self:addAllCommands() + + local name_font = Font:getFace("tfont", self.OPT_NAME_FONT_SIZE) + local value_font = Font:getFace("cfont", self.OPT_VALUE_FONT_SIZE) + + -- base window coordinates + local width, height = fb.bb:getWidth()-2*self.MARGIN_HORISONTAL, self.HEIGHT + local topleft_x, topleft_y = self.MARGIN_HORISONTAL, fb.bb:getHeight()-self.MARGIN_BOTTOM-height + local botleft_x, botleft_y = self.MARGIN_HORISONTAL, topleft_y+height + + self:drawBox(topleft_x, topleft_y, width, height, 3, 15) + self:drawOptions(topleft_x, topleft_y, name_font, value_font) + fb:refresh(1, topleft_x, topleft_y, width, height) + + local ev, keydef, command, ret_code + while true do + configurable.line_spacing = KOPTOptions[1].space[KOPTOptions[1].current_item] + configurable.word_spacing = KOPTOptions[2].space[KOPTOptions[2].current_item] + --Debug("Line spacing:", configurable.line_spacing, "Word spacing:", configurable.word_spacing) + if self.page_dirty then + kopt_callback(koptreader, configurable) + self:drawBox(topleft_x, topleft_y, width, height, 3, 15) + self:drawOptions(topleft_x, topleft_y, name_font, value_font, true) + fb:refresh(1, topleft_x, topleft_y, width, height) + self.page_dirty = false + end + self:drawOptions(topleft_x, topleft_y, name_font, value_font) + + ev = input.saveWaitForEvent() + ev.code = adjustKeyEvents(ev) + if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then + keydef = Keydef:new(ev.code, getKeyModifier()) + Debug("key pressed: "..tostring(keydef)) + command = self.commands:getByKeydef(keydef) + if command ~= nil then + Debug("command to execute: "..tostring(command)) + ret_code = command.func(self, keydef) + else + Debug("command not found: "..tostring(command)) + end + if ret_code == "break" then + ret_code = nil + if self.final_choice then + return self.readers[self.final_choice] + else + return nil + end + end + end -- if + end -- while +end + +-- add available commands +function KOPTConfig:addAllCommands() + self.commands = Commands:new{} + self.commands:add(KEY_FW_DOWN, nil, "joypad down", + "next item", + function(self) + local last_option = self.current_option + self.current_option = (self.current_option + #KOPTOptions + 1)%#KOPTOptions + self.current_option = (self.current_option == 0) and #KOPTOptions or self.current_option + + last_option_item = KOPTOptions[last_option].current_item + KOPTOptions[last_option].marker_dirty[last_option_item] = true + current_option_item = KOPTOptions[self.current_option].current_item + KOPTOptions[self.current_option].marker_dirty[current_option_item] = true + end + ) + self.commands:add(KEY_FW_UP, nil, "joypad up", + "previous item", + function(self) + local last_option = self.current_option + self.current_option = (self.current_option + #KOPTOptions - 1)%#KOPTOptions + self.current_option = (self.current_option == 0) and #KOPTOptions or self.current_option + + last_option_item = KOPTOptions[last_option].current_item + KOPTOptions[last_option].marker_dirty[last_option_item] = true + current_option_item = KOPTOptions[self.current_option].current_item + KOPTOptions[self.current_option].marker_dirty[current_option_item] = true + end + ) + self.commands:add(KEY_FW_LEFT, nil, "joypad left", + "last item", + function(self) + local last_item = KOPTOptions[self.current_option].current_item + local item_count = #KOPTOptions[self.current_option].items_text + local current_item = (KOPTOptions[self.current_option].current_item + item_count - 1)%item_count + current_item = (current_item == 0) and item_count or current_item + KOPTOptions[self.current_option].current_item = current_item + + KOPTOptions[self.current_option].marker_dirty[last_item] = true + KOPTOptions[self.current_option].marker_dirty[current_item] = true + self.page_dirty = true + end + ) + self.commands:add(KEY_FW_RIGHT, nil, "joypad right", + "next item", + function(self) + local last_item = KOPTOptions[self.current_option].current_item + local item_count = #KOPTOptions[self.current_option].items_text + local current_item = (KOPTOptions[self.current_option].current_item + item_count + 1)%item_count + current_item = (current_item == 0) and item_count or current_item + KOPTOptions[self.current_option].current_item = current_item + + KOPTOptions[self.current_option].marker_dirty[last_item] = true + KOPTOptions[self.current_option].marker_dirty[current_item] = true + self.page_dirty = true + end + ) + self.commands:add({KEY_F,KEY_AA,KEY_BACK}, nil, "Back", + "back", + function(self) + return "break" + end + ) +end \ No newline at end of file diff --git a/pdf.c b/pdf.c index b51d6a73a..579dc8a02 100644 --- a/pdf.c +++ b/pdf.c @@ -515,9 +515,14 @@ static int reflowPage(lua_State *L) { PdfPage *page = (PdfPage*) luaL_checkudata(L, 1, "pdfpage"); DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext"); + int width = (int) luaL_checkint(L, 4); // framebuffer size + int height = (int) luaL_checkint(L, 5); + double line_spacing = luaL_checknumber(L, 6); + double word_spacing = luaL_checknumber(L, 7); - int width, height; - k2pdfopt_mupdf_reflow(page->doc->xref, page->page, page->doc->context, dc->zoom, dc->gamma, 0); + //printf("reflowPage width:%d height:%d\n", width, height); + + k2pdfopt_mupdf_reflow(page->doc->xref, page->page, page->doc->context, dc->zoom, dc->gamma, 0.0, width, height, line_spacing, word_spacing); k2pdfopt_rfbmp_size(&width, &height); k2pdfopt_rfbmp_zoom(&dc->zoom);