diff --git a/blitbuffer.c b/blitbuffer.c index 6c6ab70cf..cf4c8c107 100644 --- a/blitbuffer.c +++ b/blitbuffer.c @@ -20,6 +20,20 @@ #include #include "blitbuffer.h" + +inline int setPixel(BlitBuffer *bb, int x, int y, int c) { + uint8_t *dstptr = (uint8_t*)(bb->data) + (y * bb->pitch) + (x / 2); + + if(x % 2 == 0) { + *dstptr &= 0x0F; + *dstptr |= c << 4; + } else { + *dstptr &= 0xF0; + *dstptr |= c; + } + return 0; +} + int newBlitBufferNative(lua_State *L, int w, int h, BlitBuffer **newBuffer) { BlitBuffer *bb = (BlitBuffer*) lua_newuserdata(L, sizeof(BlitBuffer)); luaL_getmetatable(L, "blitbuffer"); @@ -78,7 +92,6 @@ static int blitFullToBuffer(lua_State *L) { } memcpy(dst->data, src->data, src->pitch * src->h); - return 0; } @@ -485,6 +498,172 @@ static int dimRect(lua_State *L) { return 0; } +/* + * @r: radius + * @c: color of the line to draw + * @w: width of the line to draw + */ +static int paintCircle(lua_State *L) { + BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer"); + int center_x = luaL_checkint(L, 2); + int center_y = luaL_checkint(L, 3); + int r = luaL_checkint(L, 4); + int c = luaL_optint(L, 5, 15); + int w = luaL_optint(L, 6, r); + + if( (center_x + r > dst->h) || (center_x - r < 0) || + (center_y + r > dst->w) || (center_y - r < 0) || + (r == 0)) { + return 0; + } + if(w > r) { + w = r; + } + + + int tmp_y; + /* for outer circle */ + int x = 0, y = r; + float delta = 5/4 - r; + /* for inter circle */ + int r2 = r - w; + int x2 = 0, y2 = r2; + float delta2 = 5/4 - r; + + /* draw two axles */ + for(tmp_y = r; tmp_y > r2; tmp_y--) { + setPixel(dst, center_x+0, center_y+tmp_y, c); + setPixel(dst, center_x-0, center_y-tmp_y, c); + setPixel(dst, center_x+tmp_y, center_y+0, c); + setPixel(dst, center_x-tmp_y, center_y-0, c); + } + + while(x < y) { + /* decrease y if we are out of circle */ + x++; + if (delta > 0) { + y--; + delta = delta + 2*x - 2*y + 2; + } else { + delta = delta + 2*x + 1; + } + + /* inner circle finished drawing, increase y linearly for filling */ + if(x2 > y2) { + y2++; + x2++; + } else { + x2++; + if (delta2 > 0) { + y2--; + delta2 = delta2 + 2*x2 - 2*y2 + 2; + } else { + delta2 = delta2 + 2*x2 + 1; + } + } + + for(tmp_y = y; tmp_y > y2; tmp_y--) { + setPixel(dst, center_x+x, center_y+tmp_y, c); + setPixel(dst, center_x+tmp_y, center_y+x, c); + + setPixel(dst, center_x+tmp_y, center_y-x, c); + setPixel(dst, center_x+x, center_y-tmp_y, c); + + setPixel(dst, center_x-x, center_y-tmp_y, c); + setPixel(dst, center_x-tmp_y, center_y-x, c); + + setPixel(dst, center_x-tmp_y, center_y+x, c); + setPixel(dst, center_x-x, center_y+tmp_y, c); + } + } + if(r == w) { + setPixel(dst, center_x, center_y, c); + } + return 0; +} + +static int paintRoundedCorner(lua_State *L) { + BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer"); + int off_x = luaL_checkint(L, 2); + int off_y = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + int bw = luaL_checkint(L, 6); + int r = luaL_checkint(L, 7); + int c = luaL_optint(L, 8, 15); + + if((2*r > h) || (2*r > w) || (r == 0)) { + return 0; + } + if(r > h) { + r = h; + } + if(r > w) { + r = w; + } + if(bw > r) { + bw = r; + } + + + int tmp_y; + /* for outer circle */ + int x = 0, y = r; + float delta = 5/4 - r; + /* for inter circle */ + int r2 = r - bw; + int x2 = 0, y2 = r2; + float delta2 = 5/4 - r; + + /* draw two axles */ + /*for(tmp_y = r; tmp_y > r2; tmp_y--) {*/ + /*setPixel(dst, (w-r)+off_x+0, (h-r)+off_y+tmp_y-1, c);*/ + /*setPixel(dst, (w-r)+off_x-0, (r)+off_y-tmp_y, c);*/ + /*setPixel(dst, (w-r)+off_x+tmp_y, (h-r)+off_y+0, c);*/ + /*setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y-0-1, c);*/ + /*}*/ + + while(x < y) { + /* decrease y if we are out of circle */ + x++; + if (delta > 0) { + y--; + delta = delta + 2*x - 2*y + 2; + } else { + delta = delta + 2*x + 1; + } + + /* inner circle finished drawing, increase y linearly for filling */ + if(x2 > y2) { + y2++; + x2++; + } else { + x2++; + if (delta2 > 0) { + y2--; + delta2 = delta2 + 2*x2 - 2*y2 + 2; + } else { + delta2 = delta2 + 2*x2 + 1; + } + } + + for(tmp_y = y; tmp_y > y2; tmp_y--) { + setPixel(dst, (w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c); + setPixel(dst, (w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c); + + setPixel(dst, (w-r)+off_x+tmp_y-1, (r)+off_y-x, c); + setPixel(dst, (w-r)+off_x+x-1, (r)+off_y-tmp_y, c); + + setPixel(dst, (r)+off_x-x, (r)+off_y-tmp_y, c); + setPixel(dst, (r)+off_x-tmp_y, (r)+off_y-x, c); + + setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y+x-1, c); + setPixel(dst, (r)+off_x-x, (h-r)+off_y+tmp_y-1, c); + } + } + return 0; +} + static const struct luaL_Reg blitbuffer_func[] = { {"new", newBlitBuffer}, {NULL, NULL} @@ -497,6 +676,8 @@ static const struct luaL_Reg blitbuffer_meth[] = { {"addblitFrom", addblitToBuffer}, {"blitFullFrom", blitFullToBuffer}, {"paintRect", paintRect}, + {"paintCircle", paintCircle}, + {"paintRoundedCorner", paintRoundedCorner}, {"invertRect", invertRect}, {"dimRect", dimRect}, {"free", freeBlitBuffer}, diff --git a/commands.lua b/commands.lua index 2168fb57d..83e2381cf 100644 --- a/commands.lua +++ b/commands.lua @@ -166,6 +166,7 @@ function Commands:new(obj) "toggle screen saver", function() Screen:saveCurrentBB() + InfoMessage:show("Going into screensaver... ", 0) Screen.kpv_rotation_mode = Screen.cur_rotation_mode fb:setOrientation(Screen.native_rotation_mode) util.sleep(1) diff --git a/crereader.lua b/crereader.lua index 8b0f14a4f..4aaad0c39 100644 --- a/crereader.lua +++ b/crereader.lua @@ -310,39 +310,38 @@ function CREReader:adjustCreReaderCommands() self.commands:del(KEY_N, MOD_SHIFT, "N") -- show highlights -- overwrite commands - self.commands:add({KEY_PGFWD, KEY_LPGFWD}, MOD_SHIFT, ">", - "increase font size", + + self.commands:addGroup(MOD_SHIFT.."< >",{ + Keydef:new(KEY_PGBCK,MOD_SHIFT),Keydef:new(KEY_PGFWD,MOD_SHIFT), + Keydef:new(KEY_LPGBCK,MOD_SHIFT),Keydef:new(KEY_LPGFWD,MOD_SHIFT)}, + "increase/decrease font size", function(self) - self.doc:zoomFont(1) - self:redrawCurrentPage() - end - ) - self.commands:add({KEY_PGBCK, KEY_LPGBCK}, MOD_SHIFT, "<", - "decrease font size", - function(self) - self.doc:zoomFont(-1) - self:redrawCurrentPage() - end - ) - self.commands:add({KEY_PGFWD, KEY_LPGFWD}, MOD_ALT, ">", - "increase line spacing", - function(self) - self.line_space_percent = self.line_space_percent + 10 - if self.line_space_percent > 200 then - self.line_space_percent = 200 + local delta = 1 + local change = "increase" + if keydef.keycode == KEY_PGBCK or keydef.keycode == KEY_LPGBCK then + delta = -1 + change = "decrease" end - InfoMessage:show("line spacing "..self.line_space_percent.."%", 0) - debug("line spacing set to", self.line_space_percent) - self.doc:setDefaultInterlineSpace(self.line_space_percent) + InfoMessage:show(change.." font size", 0) + self.doc:zoomFont(delta) self:redrawCurrentPage() end ) - self.commands:add({KEY_PGBCK, KEY_LPGBCK}, MOD_ALT, "<", - "decrease line spacing", + self.commands:addGroup(MOD_ALT.."< >",{ + Keydef:new(KEY_PGBCK,MOD_ALT),Keydef:new(KEY_PGFWD,MOD_ALT), + Keydef:new(KEY_LPGBCK,MOD_ALT),Keydef:new(KEY_LPGFWD,MOD_ALT)}, + "increase/decrease line spacing", function(self) - self.line_space_percent = self.line_space_percent - 10 - if self.line_space_percent < 100 then - self.line_space_percent = 100 + if keydef.keycode == KEY_PGBCK or keydef.keycode == KEY_LPGBCK then + self.line_space_percent = self.line_space_percent - 10 + if self.line_space_percent < 100 then + self.line_space_percent = 100 + end + else + self.line_space_percent = self.line_space_percent + 10 + if self.line_space_percent > 200 then + self.line_space_percent = 200 + end end InfoMessage:show("line spacing "..self.line_space_percent.."%", 0) debug("line spacing set to", self.line_space_percent) @@ -378,11 +377,11 @@ function CREReader:adjustCreReaderCommands() local item_no = fonts_menu:choose(0, G_height) debug(face_list[item_no]) if item_no then + Screen:restoreFromSavedBB() self.doc:setFontFace(face_list[item_no]) self.font_face = face_list[item_no] InfoMessage:show("Redrawing with "..face_list[item_no], 0) end - Screen:restoreFromSavedBB() self:redrawCurrentPage() end ) diff --git a/graphics.lua b/graphics.lua index 267cb9469..562bdd995 100644 --- a/graphics.lua +++ b/graphics.lua @@ -1,12 +1,33 @@ +--[[ +Draw a border -blitbuffer.paintBorder = function (bb, x, y, w, h, bw, c) - bb:paintRect(x, y, w, bw, c) - bb:paintRect(x, y+h-bw, w, bw, c) - bb:paintRect(x, y+bw, bw, h - 2*bw, c) - bb:paintRect(x+w-bw, y+bw, bw, h - 2*bw, c) +@x: start position in x axis +@y: start position in y axis +@w: width of the border +@h: height of the border +@bw: line width of the border +@c: color for loading bar +@r: radius of for border's corner (nil or 0 means right corner border) +--]] +function blitbuffer.paintBorder(bb, x, y, w, h, bw, c, r) + if not r or r == 0 then + bb:paintRect(x, y, w, bw, c) + bb:paintRect(x, y+h-bw, w, bw, c) + bb:paintRect(x, y+bw, bw, h - 2*bw, c) + bb:paintRect(x+w-bw, y+bw, bw, h - 2*bw, c) + else + if h < 2*r then h = 2 * r end + if w < 2*r then w = 2 * r end + bb:paintRoundedCorner(x, y, w, h, bw, r, c) + bb:paintRect(r+x, y, w-2*r, bw, c) + bb:paintRect(r+x, y+h-bw, w-2*r, bw, c) + bb:paintRect(x, r+y, bw, h-2*r, c) + bb:paintRect(x+w-bw, r+y, bw, h-2*r, c) + end end + --[[ Draw a progress bar according to following args: @@ -19,8 +40,8 @@ Draw a progress bar according to following args: @load_percent: progress in percent @c: color for loading bar --]] -blitbuffer.progressBar = function (bb, x, y, w, h, - load_m_w, load_m_h, load_percent, c) +function blitbuffer.progressBar(bb, x, y, w, h, + load_m_w, load_m_h, load_percent, c) if load_m_h*2 > h then load_m_h = h/2 end diff --git a/unireader.lua b/unireader.lua index 81cef0f3f..8b6b4bfb8 100644 --- a/unireader.lua +++ b/unireader.lua @@ -40,6 +40,7 @@ UniReader = { -- size of current page for current zoom level in pixels cur_full_width = 0, cur_full_height = 0, + cur_bbox = {}, -- current page bbox offset_x = 0, offset_y = 0, dest_x = 0, -- real offset_x when it's smaller than screen, so it's centered @@ -54,7 +55,7 @@ UniReader = { pan_by_page = false, -- using shift_[xy] or width/height pan_x = 0, -- top-left offset of page when pan activated pan_y = 0, - pan_margin = 20, -- horizontal margin for two-column zoom + pan_margin = 5, -- horizontal margin for two-column zoom (in pixels) pan_overlap_vertical = 30, show_overlap = 0, @@ -1260,13 +1261,11 @@ function UniReader:setzoom(page, preCache) or self.globalzoom_mode == self.ZOOM_FIT_TO_CONTENT_HALF_WIDTH_MARGIN then local margin = self.pan_margin if self.globalzoom_mode == self.ZOOM_FIT_TO_CONTENT_HALF_WIDTH then margin = 0 end - local pg_margin = 0 -- margin scaled to page size - if margin > 0 then pg_margin = margin * 2 / self.globalzoom end - self.globalzoom = width / (x1 - x0 + pg_margin) + self.globalzoom = width / (x1 - x0 + margin) self.offset_x = -1 * x0 * self.globalzoom * 2 + margin - self.globalzoom = height / (y1 - y0 + pg_margin) + self.globalzoom = height / (y1 - y0 + margin) self.offset_y = -1 * y0 * self.globalzoom * 2 + margin - self.globalzoom = width / (x1 - x0 + pg_margin) * 2 + self.globalzoom = width / (x1 - x0 + margin) * 2 debug("column mode offset:", self.offset_x, self.offset_y, " zoom:", self.globalzoom); self.globalzoom_mode = self.ZOOM_BY_VALUE -- enable pan mode self.pan_x = self.offset_x @@ -1282,6 +1281,15 @@ function UniReader:setzoom(page, preCache) if not preCache then -- save current page fullsize self.cur_full_width = self.fullwidth self.cur_full_height = self.fullheight + + self.cur_bbox = { + ["x0"] = x0, + ["y0"] = y0, + ["x1"] = x1, + ["y1"] = y1, + } + debug("cur_bbox", self.cur_bbox) + end self.min_offset_x = fb.bb:getWidth() - self.fullwidth self.min_offset_y = fb.bb:getHeight() - self.fullheight @@ -2067,6 +2075,16 @@ function UniReader:addAllCommands() end debug("bbox override", unireader.bbox.enabled); end) + self.commands:add(KEY_X,nil,"X", + "invert page bbox", + function(unireader) + local bbox = unireader.cur_bbox + debug("bbox", bbox) + x,y,w,h = unireader:getRectInScreen( bbox["x0"], bbox["y0"], bbox["x1"], bbox["y1"] ) + debug("inxertRect",x,y,w,h) + fb.bb:invertRect( x,y, w,h ) + fb:refresh(0) + end) self.commands:add(KEY_MENU,nil,"Menu", "toggle info box", function(unireader)