Skip to content

Commit

Permalink
Merge branch 'CocoaBob-master'
Browse files Browse the repository at this point in the history
adds Pebble Time Round support and fixes #16
  • Loading branch information
unlobito committed Mar 10, 2016
2 parents e73e810 + 9437ba0 commit 913c083
Show file tree
Hide file tree
Showing 10 changed files with 774 additions and 74 deletions.
9 changes: 5 additions & 4 deletions appinfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,18 @@
{
"file": "images/error.png",
"name": "IMAGE_ERROR",
"type": "png"
"type": "bitmap"
},
{
"file": "images/refresh.png",
"name": "IMAGE_REFRESH",
"type": "png"
"type": "bitmap"
},
{
"file": "images/icon.png",
"menuIcon": true,
"name": "IMAGE_MENU_ICON",
"type": "png"
"type": "bitmap"
}
]
},
Expand All @@ -49,6 +49,7 @@
},
"targetPlatforms": [
"aplite",
"basalt"
"basalt",
"chalk"
]
}
Binary file modified resources/images/error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified resources/images/refresh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
653 changes: 653 additions & 0 deletions skunk.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

87 changes: 58 additions & 29 deletions src/card_layer.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ struct CardLayer {
TextLayer *value_text_layer;
char *name_text;
TextLayer *name_text_layer;
Layer *name_background_layer;
};

static void background_update_proc(Layer *layer, GContext* ctx);
static void name_background_update_proc(Layer *layer, GContext* ctx);

CardLayer *card_layer_create(GRect frame) {
static const size_t CardLayer_size = sizeof(CardLayer);
Expand All @@ -26,17 +28,30 @@ CardLayer *card_layer_create(GRect frame) {
card_layer->layer = layer_create_with_data(frame, sizeof(CardLayer *));
layer_set_update_proc(card_layer->layer, background_update_proc);
*(CardLayer **)layer_get_data(card_layer->layer) = card_layer;

card_layer->name_text_layer = text_layer_create(GRect(0, 0, PEBBLE_WIDTH, NAME_LAYER_HEIGHT));

card_layer->name_background_layer = layer_create(GRect(0, 0, PEBBLE_WIDTH, CARD_LAYER_NAME_HEIGHT));
layer_set_update_proc(card_layer->name_background_layer, name_background_update_proc);
layer_add_child(card_layer->layer, (Layer *)card_layer->name_background_layer);
int16_t text_y = (CARD_LAYER_NAME_HEIGHT - TEXT_HEIGHT) / 2;
#ifdef PBL_ROUND
text_y += 4; // Magic number to avoid round screen border
#endif
card_layer->name_text_layer = text_layer_create(GRect(0, text_y, PEBBLE_WIDTH, TEXT_HEIGHT));
text_layer_set_background_color(card_layer->name_text_layer, GColorBlack);
text_layer_set_font(card_layer->name_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_overflow_mode(card_layer->name_text_layer, GTextOverflowModeTrailingEllipsis);
text_layer_set_text_alignment(card_layer->name_text_layer, GTextAlignmentCenter);
text_layer_set_text_color(card_layer->name_text_layer, GColorWhite);
layer_add_child(card_layer->layer, (Layer *)card_layer->name_text_layer);
#ifdef PBL_ROUND
// Note: The text_layer_enable_screen_text_flow_and_paging() function must be called after
// the TextLayer is added to the view heirachy (i.e.: after using layer_add_child()),
// or else it will have no effect.
text_layer_enable_screen_text_flow_and_paging(card_layer->name_text_layer, 2);
#endif


card_layer->value_text_layer = text_layer_create(GRect(0, 115, PEBBLE_WIDTH, 22)); // TODO: Fix magic numbers
card_layer->value_text_layer = text_layer_create(GRect(0, frame.size.h - CARD_LAYER_VALUE_HEIGHT, PEBBLE_WIDTH, CARD_LAYER_VALUE_HEIGHT));
text_layer_set_background_color(card_layer->value_text_layer, GColorWhite);
text_layer_set_font(card_layer->value_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_overflow_mode(card_layer->value_text_layer, GTextOverflowModeTrailingEllipsis);
Expand All @@ -52,6 +67,7 @@ void card_layer_destroy(CardLayer *card_layer) {
if (card_layer->barcode) gbitmap_destroy(card_layer->barcode);
if (card_layer->barcode_data) free(card_layer->barcode_data);
if (card_layer->name_text) free(card_layer->name_text);
layer_destroy(card_layer->name_background_layer);
text_layer_destroy(card_layer->name_text_layer);
if (card_layer->value_text) free(card_layer->value_text);
text_layer_destroy(card_layer->value_text_layer);
Expand All @@ -71,47 +87,52 @@ static void draw_barcode_matrix(CardLayer *card_layer, GContext* ctx) {

// name_text_layer and pager_layer need to be subtracted from the pebble height
// as does twice the WHITE_BORDER
const int16_t MAX_HEIGHT = PEBBLE_HEIGHT - NAME_LAYER_HEIGHT - PAGER_LAYER_HEIGHT;
const int16_t MAX_HEIGHT = PEBBLE_HEIGHT - CARD_LAYER_NAME_HEIGHT - PAGER_LAYER_HEIGHT;

// The mid point between the black border at the top (name_layer) and at the bottom (pager_layer)
// is not exactly in the middle of the screen
const int16_t MID_HEIGHT = (PEBBLE_HEIGHT - NAME_LAYER_HEIGHT - PAGER_LAYER_HEIGHT) / 2 + NAME_LAYER_HEIGHT;
const int16_t MID_HEIGHT = (PEBBLE_HEIGHT - CARD_LAYER_NAME_HEIGHT - PAGER_LAYER_HEIGHT) / 2 + CARD_LAYER_NAME_HEIGHT;

const int16_t MID_WIDTH = PEBBLE_WIDTH / 2;

const int16_t CONTENT_MARGIN = 1;

// Non-linear barcodes are scaled to save persistent storage space. Dynamically calculate
// the maximum integer scaling factor, keep a white border of 1 units around.

const int16_t SCALING_FACTOR_X = PEBBLE_WIDTH / (card_layer->barcode_width + 2);
const int16_t SCALING_FACTOR_Y = MAX_HEIGHT / (card_layer->barcode_height + 2);
const int16_t SCALING_FACTOR_X = PEBBLE_WIDTH / (card_layer->barcode_width + CONTENT_MARGIN * 2);
const int16_t SCALING_FACTOR_Y = MAX_HEIGHT / (card_layer->barcode_height + CONTENT_MARGIN * 2);

// actual scaling factor is the least of x and y scaling, but at least 1
const int16_t SCALING_FACTOR = MAX( MIN(SCALING_FACTOR_X, SCALING_FACTOR_Y), 1);

APP_LOG(APP_LOG_LEVEL_DEBUG, "image size %ix%i, scaling by %i", card_layer->barcode_width, card_layer->barcode_height, SCALING_FACTOR);

const int16_t first_point_x = MID_WIDTH - SCALING_FACTOR * (card_layer->barcode_width / 2);
const int16_t first_point_y = MID_HEIGHT - SCALING_FACTOR * (card_layer->barcode_height / 2);

// The comparison part of this loop adds 7 to the barcode width to allow C
// to ceil the byte count. Since the server will always pad incomplete bytes
// with 0, this is reasonably safe.
for (
int16_t current_byte = IMG_HEADER_OFFSET;
current_byte < (IMG_HEADER_OFFSET + ( img_pixels + IMG_BIT_SIZE - 1 ) / IMG_BIT_SIZE );
current_byte++
) {

int16_t current_byte = IMG_HEADER_OFFSET;
current_byte < (IMG_HEADER_OFFSET + ( img_pixels + IMG_BIT_SIZE - 1 ) / IMG_BIT_SIZE );
current_byte++
) {
for (int8_t p = 0; p < 8; p++) {
if (card_layer->barcode_data[current_byte] & (1 << p)) {

for(int8_t s_x = 0; s_x < SCALING_FACTOR; s_x++) {
for(int8_t s_y = 0; s_y < SCALING_FACTOR; s_y++) {
point_x = ( PEBBLE_WIDTH/2 - (SCALING_FACTOR * card_layer->barcode_width)/2 ) + SCALING_FACTOR*raw_x + s_x;
point_y = ( MID_HEIGHT - (SCALING_FACTOR * card_layer->barcode_height)/2 ) + SCALING_FACTOR*raw_y + s_y;

point_x = first_point_x + SCALING_FACTOR * raw_x + s_x;
point_y = first_point_y + SCALING_FACTOR * raw_y + s_y;
graphics_draw_pixel(ctx, GPoint(point_x, point_y));
}
}
}

raw_x++;
if (raw_x == card_layer->barcode_width ) {
if (raw_x == card_layer->barcode_width) {
raw_x = 0;
raw_y++;
}
Expand All @@ -125,33 +146,35 @@ static void draw_barcode_linear(CardLayer *card_layer, GContext* ctx) {
raw_x = 0;

int16_t img_pixels = card_layer->barcode_width;

const int16_t CONTENT_MARGIN = 1;

// Try to do an integer scale if possible, keep white border of 1 unit on each side
const int16_t SCALING_FACTOR_X = PEBBLE_WIDTH / (card_layer->barcode_width + 2);
const int16_t SCALING_FACTOR_X = PEBBLE_WIDTH / (card_layer->barcode_width + CONTENT_MARGIN * 2);
const int16_t SCALING_FACTOR = MAX( SCALING_FACTOR_X, 1);

const int16_t first_point_x = PEBBLE_WIDTH / 2 - (SCALING_FACTOR * card_layer->barcode_width) / 2;
const int16_t first_point_y = PEBBLE_HEIGHT / 2 - card_layer->barcode_height / 2;

// The comparison part of this loop adds 7 to the barcode width to allow C
// to ceil the byte count. Since the server will always pad incomplete bytes
// with 0, this is reasonably safe.
for (
int16_t current_byte = IMG_HEADER_OFFSET;
current_byte < (IMG_HEADER_OFFSET + ( img_pixels + IMG_BIT_SIZE - 1 ) / IMG_BIT_SIZE );
current_byte++
) {

int16_t current_byte = IMG_HEADER_OFFSET;
current_byte < (IMG_HEADER_OFFSET + ( img_pixels + IMG_BIT_SIZE - 1 ) / IMG_BIT_SIZE );
current_byte++
) {
for (int16_t current_pixel = 0; current_pixel < 8; current_pixel++) {
if (card_layer->barcode_data[current_byte] & (1 << current_pixel)) {
for(int8_t s_x = 0; s_x < SCALING_FACTOR; s_x++) {
point_x = ( PEBBLE_WIDTH/2 - (SCALING_FACTOR * card_layer->barcode_width)/2 ) + SCALING_FACTOR*raw_x + s_x;

point_x = first_point_x + SCALING_FACTOR * raw_x + s_x;
for (int16_t current_vertical = 0; current_vertical < card_layer->barcode_height; current_vertical++) {
point_y = ( PEBBLE_HEIGHT / 2 - card_layer->barcode_height / 2 ) + current_vertical;

point_y = first_point_y + current_vertical;
graphics_draw_pixel(ctx, GPoint(point_x, point_y));
}
}
}

raw_x++;
}
}
Expand All @@ -177,6 +200,12 @@ static void background_update_proc(Layer *layer, GContext* ctx) {
}
}

static void name_background_update_proc(Layer *layer, GContext* ctx) {
GRect bounds = layer_get_bounds(layer);
graphics_context_set_fill_color(ctx, GColorBlack);
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
}

bool card_layer_set_index(CardLayer *card_layer, uint8_t index) {
index = index + 1;

Expand Down
21 changes: 18 additions & 3 deletions src/defines.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
#pragma once

#ifdef PBL_ROUND
#define PEBBLE_HEIGHT 180
#define PEBBLE_WIDTH 180
#else
#define PEBBLE_HEIGHT 168
#define PEBBLE_WIDTH 144
#define STATUS_HEIGHT 16
#define NAME_LAYER_HEIGHT 22
#define PAGER_LAYER_HEIGHT 30
#endif

#define TEXT_MARGIN 4
#define TEXT_HEIGHT 22

#define REFRESH_LAYER_HEIGHT 66
#define REFRESH_LAYER_TEXT_HEIGHT 40

#define CARD_LAYER_NAME_HEIGHT 22
#define CARD_LAYER_VALUE_HEIGHT 22

#define PAGER_LAYER_HEIGHT 22
#define PAGER_LAYER_CIRCLE_DISTANCE 11
#define PAGER_LAYER_CIRCLE_RADIUS 3

#define IMG_HEADER_OFFSET 3
#define IMG_BIT_SIZE 8
Expand Down
7 changes: 2 additions & 5 deletions src/error_window.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "a2_strdup.h"
#include "error_window.h"
#include "defines.h"

static GBitmap *error_bitmap;
static Window *window;
Expand All @@ -18,10 +19,6 @@ void error_window_init(void) {
window_set_background_color(window, GColorBlack);
window_set_click_config_provider(window, window_click_config_provider);

#ifdef PBL_PLATFORM_APLITE
window_set_fullscreen(window, true);
#endif

static const WindowHandlers window_handlers = {
.load = window_load,
};
Expand Down Expand Up @@ -59,7 +56,7 @@ static void window_load(Window *window) {
bitmap_layer_set_bitmap(icon_layer, error_bitmap);
bitmap_layer_set_compositing_mode(icon_layer, GCompOpAssignInverted);

GRect text_layer_frame = GRect(4, 83, 136, 50);
GRect text_layer_frame = GRect(TEXT_MARGIN, 83, 136, 50);
text_layer = text_layer_create(text_layer_frame);
text_layer_set_background_color(text_layer, GColorBlack);
text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
Expand Down
10 changes: 3 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ static void init(void) {
window_set_background_color(window, GColorBlack);
window_set_click_config_provider(window, window_click_config_provider);

#ifdef PBL_PLATFORM_APLITE
window_set_fullscreen(window, true);
#endif

static const WindowHandlers window_handlers = {
.load = window_load,
.unload = window_unload,
Expand Down Expand Up @@ -303,7 +299,7 @@ static void app_message_send_fetch_data(void) {
}

static void card_layer_init(void) {
card_layer = card_layer_create(GRect(0, 0, PEBBLE_WIDTH, 140)); // TODO: fix 140 magic number
card_layer = card_layer_create(GRect(0, 0, PEBBLE_WIDTH, PEBBLE_HEIGHT - PAGER_LAYER_HEIGHT));
card_layer_set_index(card_layer, 0);

Layer *root_layer = window_get_root_layer(window);
Expand All @@ -315,7 +311,7 @@ static void card_layer_deinit(void) {
}

static void pager_layer_init(void) {
pager_layer = pager_layer_create(GRect(0, PEBBLE_HEIGHT - 18, PEBBLE_WIDTH, 7)); // TODO: fix magic numbers
pager_layer = pager_layer_create(GRect(0, PEBBLE_HEIGHT - PAGER_LAYER_HEIGHT, PEBBLE_WIDTH, PAGER_LAYER_HEIGHT));
pager_layer_set_values(pager_layer, 0, 1);

Layer *root_layer = window_get_root_layer(window);
Expand All @@ -327,7 +323,7 @@ static void pager_layer_deinit(void) {
}

static void refresh_layer_init(void) {
refresh_layer = refresh_layer_create(GRect(4, 50, 136, 66)); // TODO: fix magic numbers
refresh_layer = refresh_layer_create(GRect(TEXT_MARGIN, (PEBBLE_HEIGHT - REFRESH_LAYER_HEIGHT) / 2, PEBBLE_WIDTH - TEXT_MARGIN * 2, REFRESH_LAYER_HEIGHT));

Layer *base_layer = refresh_layer_get_layer(refresh_layer);
layer_set_hidden(base_layer, true);
Expand Down
53 changes: 31 additions & 22 deletions src/pager_layer.c
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#include "pager_layer.h"
#include "defines.h"

struct PagerLayer {
Layer *layer;
uint8_t index;
uint8_t count;
/*interval use only: GTextLayoutCacheRef cache; */
#ifdef PBL_ROUND
GTextAttributes *attributes;
#endif
};

static const GSize outer_size = { 7, 7 }; // TODO: Fix magic numbers
static const uint16_t outer_radius = 3; // TODO: extract to #define?
static const int16_t padding = 5; // TODO: extract to #define?
static void background_update_proc(Layer *layer, GContext* ctx);

PagerLayer *pager_layer_create(GRect frame) {
Expand All @@ -23,11 +24,18 @@ PagerLayer *pager_layer_create(GRect frame) {

pager_layer->index = 0;
pager_layer->count = 0;
#ifdef PBL_ROUND
pager_layer->attributes = graphics_text_attributes_create();
graphics_text_attributes_enable_screen_text_flow(pager_layer->attributes, TEXT_MARGIN);
#endif

return pager_layer;
}

void pager_layer_destroy(PagerLayer *pager_layer) {
#ifdef PBL_ROUND
graphics_text_attributes_destroy(pager_layer->attributes);
#endif
layer_destroy(pager_layer->layer);
free(pager_layer);
}
Expand Down Expand Up @@ -60,30 +68,31 @@ static void background_update_proc(Layer *layer, GContext* ctx) {
char buffer[16];
snprintf(buffer, sizeof(buffer), "page %d/%d", index + 1, count);
graphics_draw_text(
ctx,
buffer,
fonts_get_system_font(FONT_KEY_GOTHIC_18),
bounds,
GTextOverflowModeFill,
GTextAlignmentCenter,
NULL //pager_layer->cache (always NULL for third-party apps)
);
ctx,
buffer,
fonts_get_system_font(FONT_KEY_GOTHIC_18),
bounds,
GTextOverflowModeFill,
GTextAlignmentCenter,
#ifdef PBL_ROUND
pager_layer->attributes
#else
NULL //pager_layer->cache (always NULL for third-party apps)
#endif
);
} else {
GRect rect = GRect(0, 0, outer_size.w * count + padding * (count - 1), outer_size.h);
grect_align(&rect, &bounds, GAlignCenter, false);

GRect circle_rect = rect;
circle_rect.size.w = outer_size.w;
const int16_t dx = outer_size.w + padding;

int16_t y = bounds.origin.y + bounds.size.h / 2;
#ifdef PBL_ROUND
y -= 4; // Magic number to avoid round screen border
#endif
int16_t x = (bounds.origin.x + bounds.size.w - PAGER_LAYER_CIRCLE_DISTANCE * (count-1)) / 2;
for (uint8_t i = 0; i < count; i++) {
if (i == index) {
graphics_fill_rect(ctx, circle_rect, outer_radius, GCornersAll);
graphics_fill_circle(ctx, GPoint(x, y), PAGER_LAYER_CIRCLE_RADIUS);
} else {
graphics_draw_round_rect(ctx, circle_rect, outer_radius);
graphics_draw_circle(ctx, GPoint(x, y), PAGER_LAYER_CIRCLE_RADIUS);
}

circle_rect.origin.x += dx;
x += PAGER_LAYER_CIRCLE_DISTANCE;
}
}
}
Loading

0 comments on commit 913c083

Please sign in to comment.