diff --git a/frontend/document/document.lua b/frontend/document/document.lua index fca96135b..e5ee097c8 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -252,7 +252,7 @@ end -- load implementations: -require "document/pdfdocument" -require "document/djvudocument" +--require "document/pdfdocument" +--require "document/djvudocument" require "document/koptdocument" require "document/credocument" diff --git a/frontend/document/koptdocument.lua b/frontend/document/koptdocument.lua index dcd265699..a67fd1daf 100644 --- a/frontend/document/koptdocument.lua +++ b/frontend/document/koptdocument.lua @@ -3,6 +3,175 @@ require "ui/geometry" require "ui/screen" require "ui/device" +KOPTOptions = { + { + name="font_size", + option_text="", + items_text={"Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa","Aa"}, + text_font_size={14,16,20,23,26,30,34,38,42,46}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true, true, true, true, true, true, true, true}, + values={0.2, 0.3, 0.4, 0.6, 0.8, 1.0, 1.2, 1.6, 2.2, 2.8}, + default_value=DKOPTREADER_CONFIG_FONT_SIZE, + show = true, + draw_index = nil,}, + { + name="text_wrap", + option_text="Reflow", + items_text={"on","off"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true}, + values={1, 0}, + default_value=DKOPTREADER_CONFIG_TEXT_WRAP, + show = true, + draw_index = nil,}, + { + name="trim_page", + option_text="Trim Page", + items_text={"auto","manual"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true}, + values={1, 0}, + default_value=DKOPTREADER_CONFIG_TRIM_PAGE, + show = true, + draw_index = nil,}, + { + name="detect_indent", + option_text="Indentation", + items_text={"enable","disable"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true}, + values={1, 0}, + default_value=DKOPTREADER_CONFIG_DETECT_INDENT, + show = false, + draw_index = nil,}, + { + name="defect_size", + option_text="Defect Size", + items_text={"small","medium","large"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={0.5, 1.0, 2.0}, + default_value=DKOPTREADER_CONFIG_DEFECT_SIZE, + show = true, + draw_index = nil,}, + { + name="page_margin", + option_text="Page Margin", + items_text={"small","medium","large"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={0.02, 0.06, 0.10}, + default_value=DKOPTREADER_CONFIG_PAGE_MARGIN, + show = true, + draw_index = nil,}, + { + name="line_spacing", + option_text="Line Spacing", + items_text={"small","medium","large"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={1.0, 1.2, 1.4}, + default_value=DKOPTREADER_CONFIG_LINE_SPACING, + show = true, + draw_index = nil,}, + { + name="word_spacing", + option_text="Word Spacing", + items_text={"small","medium","large"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={0.05, 0.15, 0.375}, + default_value=DKOPTREADER_CONFIG_WORD_SAPCING, + show = true, + draw_index = nil,}, + { + name="multi_threads", + option_text="Multi Threads", + items_text={"on","off"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true}, + values={1, 0}, + default_value=DKOPTREADER_CONFIG_MULTI_THREADS, + show = true, + draw_index = nil,}, + { + name="quality", + option_text="Render Quality", + items_text={"low","medium","high"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={0.5, 0.8, 1.0}, + default_value=DKOPTREADER_CONFIG_RENDER_QUALITY, + show = true, + draw_index = nil,}, + { + name="auto_straighten", + option_text="Auto Straighten", + items_text={"0","5","10"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true}, + values={0, 5, 10}, + default_value=DKOPTREADER_CONFIG_AUTO_STRAIGHTEN, + show = true, + draw_index = nil,}, + { + name="justification", + option_text="Justification", + items_text={"auto","left","center","right","full"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true, true, true}, + values={-1,0,1,2,3}, + default_value=DKOPTREADER_CONFIG_JUSTIFICATION, + show = true, + draw_index = nil,}, + { + name="max_columns", + option_text="Columns", + items_text={"1","2","3","4"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true, true}, + values={1,2,3,4}, + default_value=DKOPTREADER_CONFIG_MAX_COLUMNS, + show = true, + draw_index = nil,}, + { + name="contrast", + option_text="Contrast", + items_text={"lightest","lighter","default","darker","darkest"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true, true, true}, + values={2.0, 1.5, 1.0, 0.5, 0.2}, + default_value=DKOPTREADER_CONFIG_CONTRAST, + show = true, + draw_index = nil,}, + { + name="screen_rotation", + option_text="Screen Rotation", + items_text={"0","90","180","270"}, + current_item=nil, + text_dirty=true, + marker_dirty={true, true, true, true}, + values={0, 90, 180, 270}, + default_value=DKOPTREADER_CONFIG_SCREEN_ROTATION, + show = true, + draw_index = nil,}, +} + -- Any document processed by K2pdfopt is called a koptdocument KoptDocument = Document:new{ _document = false, @@ -12,6 +181,7 @@ KoptDocument = Document:new{ dc_null = DrawContext.new(), screen_size = Screen:getSize(), screen_dpi = Device:getModel() == "KindlePaperWhite" and 212 or 167, + options = KOPTOptions, configurable = { font_size = 1.0, page_margin = 0.06, @@ -28,7 +198,7 @@ KoptDocument = Document:new{ max_columns = 2, contrast = 1.0, screen_rotation = 0, - } + }, } function KoptDocument:init() @@ -42,6 +212,7 @@ function KoptDocument:init() end self.is_open = true self.info.has_pages = true + self.info.configurable = true if self._document:needsPassword() then self.is_locked = true else @@ -62,6 +233,7 @@ function KoptDocument:init() end self.is_open = true self.info.has_pages = true + self.info.configurable = true self:_readMetadata() end end @@ -161,7 +333,7 @@ function KoptDocument:getPageDimensions(pageno, zoom, rotation) Cache:insert(hash, CacheItem:new{ kctx = kc }) return page_size end - DEBUG("Found cached koptcontex on page", pageno, cached) + --DEBUG("Found cached koptcontex on page", pageno, cached) local fullwidth, fullheight = cached.kctx:getPageDim() local page_size = Geom:new{ w = fullwidth, h = fullheight } return page_size diff --git a/frontend/ui/config.lua b/frontend/ui/config.lua new file mode 100644 index 000000000..a9c72eccd --- /dev/null +++ b/frontend/ui/config.lua @@ -0,0 +1,213 @@ +require "ui/widget" +require "ui/focusmanager" +require "ui/infomessage" +require "ui/font" + +ConfigMenuItem = InputContainer:new{ + dimen = nil, +} + +function ConfigMenuItem:init() +-- we need this table per-instance, so we declare it here + if Device:isTouchDevice() then + self.ges_events = { + TapSelect = { + GestureRange:new{ + ges = "tap", + range = self.dimen, + }, + doc = "Select Menu Item", + }, + } + else + self.active_key_events = { + Select = { {"Press"}, doc = "chose selected item" }, + } + end +end + +function ConfigMenuItem:onFocus() + self[1].inverse = true + self.key_events = self.active_key_events + return true +end + +function ConfigMenuItem:onUnfocus() + self[1].inverse = false + self.key_events = { } + return true +end + +function ConfigMenuItem:onTapSelect() + self.config:onShowDialog(self.dialog) + return true +end + +MenuItemDialog = FocusManager:new{ + dimen = nil, + menu_item = nil, + title = nil, + is_borderless = false, +} + +--[[ +Widget that displays config menu +--]] +ConfigDialog = FocusManager:new{ + -- set this to true to not paint as popup menu + is_borderless = false, +} + +function ConfigDialog:init() + self.menu_dimen = self.dimen:copy() + ----------------------------------- + -- start to set up widget layout -- + ----------------------------------- + self.screen_rotate_options = HorizontalGroup:new{ + + } + self.screen_rotate_icon = ImageWidget:new{ + file = "resources/icons/appbar.transform.rotate.right.large.png" + } + self.screen_rotate_dialog = FrameContainer:new{ + dimen = self.screen_rotate_options:getSize(), + background = 0, + bordersize = 0, + padding = 0, + margin = 0, + self.screen_rotate_options, + } + self.page_crop_icon = ImageWidget:new{ + file = "resources/icons/appbar.crop.large.png" + } + self.page_layout_icon = ImageWidget:new{ + file = "resources/icons/appbar.column.two.large.png" + } + self.text_font_icon = ImageWidget:new{ + file = "resources/icons/appbar.text.size.large.png" + } + self.contrast_icon = ImageWidget:new{ + file = "resources/icons/appbar.grade.b.large.png" + } + self.more_options_icon = ImageWidget:new{ + file = "resources/icons/appbar.settings.large.png" + } + self.icon_spacing = HorizontalSpan:new{ + width = (Screen:getWidth() - 64*6 - 20) / 7 + } + + self.icon_dimen = Geom:new{ + w = 64, + h = 64, -- hardcoded for now + } + + -- group for config layout + local config_dialog = VerticalGroup:new{ + align = "center", + HorizontalGroup:new{ + align = "center", + MenuItemDialog:new{ + self.screen_rotate_dialog, + dimen = self.screen_rotate_dialog:getSize(), + title = "Screen Rotation", + }, + }, + HorizontalGroup:new{ + align = "center", + self.icon_spacing, + ConfigMenuItem:new{ + self.screen_rotate_icon, + dimen = self.icon_dimen:new(), + config = self, + }, + self.icon_spacing, + ConfigMenuItem:new{ + self.page_crop_icon, + dimen = self.icon_dimen:new(), + dialog = "Crop dialog", + config = self, + }, + self.icon_spacing, + ConfigMenuItem:new{ + self.page_layout_icon, + dimen = self.icon_dimen:new(), + config = self, + }, + self.icon_spacing, + ConfigMenuItem:new{ + self.text_font_icon, + dimen = self.icon_dimen:new(), + config = self, + }, + self.icon_spacing, + ConfigMenuItem:new{ + self.contrast_icon, + dimen = self.icon_dimen:new(), + config = self, + }, + self.icon_spacing, + ConfigMenuItem:new{ + self.more_options_icon, + dimen = self.icon_dimen:new(), + config = self, + }, + self.icon_spacing, + } + } + -- maintain reference to content so we can change it later + self.config_dialog = config_dialog + + self[1] = BottomContainer:new{ + dimen = Screen:getSize(), + FrameContainer:new{ + dimen = config_dialog:getSize(), + background = 0, + config_dialog + } + } + + ------------------------------------------ + -- start to set up input event callback -- + ------------------------------------------ + if Device:isTouchDevice() then + self.ges_events.TapCloseMenu = { + GestureRange:new{ + ges = "tap", + range = Geom:new{ + x = 0, y = 0, + w = Screen:getWidth(), + h = Screen:getHeight(), + } + } + } + else + -- set up keyboard events + self.key_events.Close = { {"Back"}, doc = "close config menu" } + -- we won't catch presses to "Right" + self.key_events.FocusRight = nil + end + self.key_events.Select = { {"Press"}, doc = "select current menu item"} + + UIManager.repaint_all = true +end + +function ConfigDialog:onShowDialog(dialog) + DEBUG("Showing dialog of item", dialog) + UIManager:show(dialog) + return true +end + +function ConfigDialog:onCloseMenu() + UIManager:close(self) + if self.close_callback then + self.close_callback() + end + return true +end + +function ConfigDialog:onTapCloseMenu(arg, ges_ev) + if ges_ev.pos:notIntersectWith(self.menu_dimen) then + self:onCloseMenu() + return true + end +end \ No newline at end of file diff --git a/frontend/ui/reader/readerconfig.lua b/frontend/ui/reader/readerconfig.lua new file mode 100644 index 000000000..626b1ac83 --- /dev/null +++ b/frontend/ui/reader/readerconfig.lua @@ -0,0 +1,66 @@ +require "ui/config" + +ReaderConfig = InputContainer:new{ + dimen = Geom:new{ + x = 0, + y = 7*Screen:getHeight()/8, + w = Screen:getWidth(), + h = Screen:getHeight()/8, + } +} + +function ReaderConfig:init() + DEBUG("init ReaderConfig.") + if Device:isTouchDevice() then + self.ges_events = { + TapShowConfigMenu = { + GestureRange:new{ + ges = "tap", + range = self.dimen:copy(), + } + } + } + else + self.key_events = { + ShowConfigMenu = { { "AA" }, doc = "show config dialog" }, + } + end +end + +function ReaderConfig:onShowConfigMenu() + local config_dialog = ConfigDialog:new{ + configurable = self.configurable, + options = self.options, + dimen = self.dimen:copy(), + } + + function config_dialog:onConfigChoice(item) + if item.callback then + item.callback() + end + end + + local dialog_container = CenterContainer:new{ + config_dialog, + dimen = self.dimen:copy(), + } + config_dialog.close_callback = function () + UIManager:close(menu_container) + end + -- maintain a reference to menu_container + self.dialog_container = dialog_container + + UIManager:show(config_dialog) + + return true +end + +function ReaderConfig:onTapShowConfigMenu() + self:onShowConfigMenu() + return true +end + +function ReaderConfig:onSetDimensions(dimen) + -- update gesture listenning range according to new screen orientation + self:init() +end diff --git a/frontend/ui/reader/readermenu.lua b/frontend/ui/reader/readermenu.lua index 4f7214267..91b754ccf 100644 --- a/frontend/ui/reader/readermenu.lua +++ b/frontend/ui/reader/readermenu.lua @@ -15,7 +15,7 @@ function ReaderMenu:init() range = Geom:new{ x = 0, y = 0, w = Screen:getWidth(), - h = Screen:getHeight()/2 + h = Screen:getHeight()/4, } } }, diff --git a/frontend/ui/reader/readerpaging.lua b/frontend/ui/reader/readerpaging.lua index f06739123..64f804180 100644 --- a/frontend/ui/reader/readerpaging.lua +++ b/frontend/ui/reader/readerpaging.lua @@ -14,10 +14,10 @@ function ReaderPaging:init() GestureRange:new{ ges = "tap", range = Geom:new{ - x = Screen:getWidth()/2, - y = Screen:getHeight()/2, - w = Screen:getWidth(), - h = Screen:getHeight() + x = Screen:getWidth()/4, + y = Screen:getHeight()/4, + w = 3*Screen:getWidth()/4, + h = 5*Screen:getHeight()/8, } } }, @@ -26,9 +26,9 @@ function ReaderPaging:init() ges = "tap", range = Geom:new{ x = 0, - y = Screen:getHeight()/2, - w = Screen:getWidth()/2, - h = Screen:getHeight()/2, + y = Screen:getHeight()/4, + w = Screen:getWidth()/4, + h = 5*Screen:getHeight()/8, } } } diff --git a/frontend/ui/readerui.lua b/frontend/ui/readerui.lua index 19d953540..a56b99c4d 100644 --- a/frontend/ui/readerui.lua +++ b/frontend/ui/readerui.lua @@ -8,6 +8,7 @@ require "ui/reader/readerrolling" require "ui/reader/readertoc" require "ui/reader/readerfont" require "ui/reader/readermenu" +require "ui/reader/readerconfig" --[[ This is an abstraction for a reader interface @@ -113,6 +114,17 @@ function ReaderUI:init() } table.insert(self, font_menu) end + if self.document.info.configurable then + -- configurable controller + local config_dialog = ReaderConfig:new{ + configurable = self.document.configurable, + options = self.document.options, + dialog = self.dialog, + view = self[1], + ui = self + } + table.insert(self, config_dialog) + end --DEBUG(self.doc_settings) -- we only read settings after all the widgets are initialized self:handleEvent(Event:new("ReadSettings", self.doc_settings)) diff --git a/frontend/ui/widget.lua b/frontend/ui/widget.lua index df50504d0..e6f8819e7 100644 --- a/frontend/ui/widget.lua +++ b/frontend/ui/widget.lua @@ -113,7 +113,21 @@ function WidgetContainer:free() end end +--[[ +BottomContainer contains its content (1 widget) at the bottom of its own dimensions +]] +BottomContainer = WidgetContainer:new() +function BottomContainer:paintTo(bb, x, y) + local contentSize = self[1]:getSize() + if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then + -- throw error? paint to scrap buffer and blit partially? + -- for now, we ignore this + end + self[1]:paintTo(bb, + x + (self.dimen.w - contentSize.w)/2, + y + (self.dimen.h - contentSize.h)) +end --[[ CenterContainer centers its content (1 widget) within its own dimensions @@ -326,6 +340,7 @@ end ImageWidget shows an image from a file ]] ImageWidget = Widget:new{ + invert = nil, file = nil, _bb = nil } @@ -349,6 +364,9 @@ end function ImageWidget:paintTo(bb, x, y) local size = self:getSize() bb:blitFrom(self._bb, x, y, 0, 0, size.w, size.h) + if self.invert then + bb:invertRect(x, y, size.w, size.h) + end end function ImageWidget:free() @@ -635,8 +653,8 @@ end function InputContainer:onGesture(ev) for name, gsseq in pairs(self.ges_events) do for _, gs_range in ipairs(gsseq) do + --DEBUG("gs_range", gs_range) if gs_range:match(ev) then - --DEBUG(gs_range) local eventname = gsseq.event or name return self:handleEvent(Event:new(eventname, gsseq.args, ev)) end diff --git a/resources/icons/appbar.checkmark.thick.png b/resources/icons/appbar.checkmark.thick.png new file mode 100644 index 000000000..1daf67824 Binary files /dev/null and b/resources/icons/appbar.checkmark.thick.png differ diff --git a/resources/icons/appbar.checkmark.thick.unchecked.png b/resources/icons/appbar.checkmark.thick.unchecked.png new file mode 100644 index 000000000..02625bf22 Binary files /dev/null and b/resources/icons/appbar.checkmark.thick.unchecked.png differ diff --git a/resources/icons/appbar.chevron.left.png b/resources/icons/appbar.chevron.left.png new file mode 100644 index 000000000..7c96681b0 Binary files /dev/null and b/resources/icons/appbar.chevron.left.png differ diff --git a/resources/icons/appbar.chevron.right.png b/resources/icons/appbar.chevron.right.png new file mode 100644 index 000000000..8e213a67c Binary files /dev/null and b/resources/icons/appbar.chevron.right.png differ diff --git a/resources/icons/appbar.column.two.large.png b/resources/icons/appbar.column.two.large.png new file mode 100644 index 000000000..6fc0150b7 Binary files /dev/null and b/resources/icons/appbar.column.two.large.png differ diff --git a/resources/icons/appbar.crop.large.png b/resources/icons/appbar.crop.large.png new file mode 100644 index 000000000..e2d342d24 Binary files /dev/null and b/resources/icons/appbar.crop.large.png differ diff --git a/resources/icons/appbar.grade.b.large.png b/resources/icons/appbar.grade.b.large.png new file mode 100644 index 000000000..b7e62c28f Binary files /dev/null and b/resources/icons/appbar.grade.b.large.png differ diff --git a/resources/icons/appbar.settings.large.png b/resources/icons/appbar.settings.large.png new file mode 100644 index 000000000..f43f732f6 Binary files /dev/null and b/resources/icons/appbar.settings.large.png differ diff --git a/resources/icons/appbar.text.size.large.png b/resources/icons/appbar.text.size.large.png new file mode 100644 index 000000000..a1dc6b305 Binary files /dev/null and b/resources/icons/appbar.text.size.large.png differ diff --git a/resources/icons/appbar.transform.rotate.right.large.png b/resources/icons/appbar.transform.rotate.right.large.png new file mode 100644 index 000000000..141c71e96 Binary files /dev/null and b/resources/icons/appbar.transform.rotate.right.large.png differ diff --git a/resources/icons/src/appbar.checkmark.thick.unchecked.xaml b/resources/icons/src/appbar.checkmark.thick.unchecked.xaml new file mode 100644 index 000000000..9f16e9023 --- /dev/null +++ b/resources/icons/src/appbar.checkmark.thick.unchecked.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.checkmark.thick.xaml b/resources/icons/src/appbar.checkmark.thick.xaml new file mode 100644 index 000000000..4f4dd3e02 --- /dev/null +++ b/resources/icons/src/appbar.checkmark.thick.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.chevron.left.xaml b/resources/icons/src/appbar.chevron.left.xaml new file mode 100644 index 000000000..84d295396 --- /dev/null +++ b/resources/icons/src/appbar.chevron.left.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.chevron.right.xaml b/resources/icons/src/appbar.chevron.right.xaml new file mode 100644 index 000000000..482e1aa94 --- /dev/null +++ b/resources/icons/src/appbar.chevron.right.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.column.one.xaml b/resources/icons/src/appbar.column.one.xaml new file mode 100644 index 000000000..a0c661538 --- /dev/null +++ b/resources/icons/src/appbar.column.one.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.column.three.xaml b/resources/icons/src/appbar.column.three.xaml new file mode 100644 index 000000000..8ba3afd46 --- /dev/null +++ b/resources/icons/src/appbar.column.three.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.column.two.xaml b/resources/icons/src/appbar.column.two.xaml new file mode 100644 index 000000000..ee5bd4ecb --- /dev/null +++ b/resources/icons/src/appbar.column.two.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.crop.xaml b/resources/icons/src/appbar.crop.xaml new file mode 100644 index 000000000..76ed90bc1 --- /dev/null +++ b/resources/icons/src/appbar.crop.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.grade.b.xaml b/resources/icons/src/appbar.grade.b.xaml new file mode 100644 index 000000000..45e0a2b02 --- /dev/null +++ b/resources/icons/src/appbar.grade.b.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.settings.xaml b/resources/icons/src/appbar.settings.xaml new file mode 100644 index 000000000..be1618ed8 --- /dev/null +++ b/resources/icons/src/appbar.settings.xaml @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/icons/src/appbar.text.size.xaml b/resources/icons/src/appbar.text.size.xaml new file mode 100644 index 000000000..a8b5f6378 --- /dev/null +++ b/resources/icons/src/appbar.text.size.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/appbar.transform.rotate.right.xaml b/resources/icons/src/appbar.transform.rotate.right.xaml new file mode 100644 index 000000000..343073b23 --- /dev/null +++ b/resources/icons/src/appbar.transform.rotate.right.xaml @@ -0,0 +1,4 @@ + + + + diff --git a/resources/icons/src/license.txt b/resources/icons/src/license.txt new file mode 100644 index 000000000..a35a4c656 --- /dev/null +++ b/resources/icons/src/license.txt @@ -0,0 +1,44 @@ +Read the license: +http://creativecommons.org/licenses/by/3.0/ * + +Basicaly, use it anyway you want but include this license file in the source if your project is open source. Nothing is needed in the front facing project (UNLESS you are using any of the icons listed below). Commercial use is not only allowed but encouraged. This pack was made to promote consistency in applications. + +Creator +- Austin Andrews (@templarian) + +Contributor** +- Oren Nachman + - appbar.chevron.down + - appbar.chevron.up + - appbar.chevron.left + - appbar.chevron.right + +Attribution*** +- Kris Vandermotten (@kvandermotten) + - appbar.medical.pulse +- Constantin Kichinsky (@kichinsky) + - appbar.currency.rubles + - appbar.currency.grivna +- Massimo Savazzi (@msavazzi) + - List of missing exported icons +- Proletkult Graphik, from The Noun Project + - appbar.draw.pen (inspired) +- Olivier Guin, from The Noun Project + - appbar.draw.marker +- Gibran Bisio, from The Noun Project + - appbar.draw.bucket +Andrew Forrester, from The Noun Project + - appbar.fingerprint + +** Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added. +*** Icons I've copied so closely you want to attribute them and are also under the CC license. + +Contact +- http://templarian.com/ +- admin[@]templarian[.]com + +* Does not apply to copyrighted logos +- Skype +- Facebook +- Twitter +- etc... \ No newline at end of file