mirror of
https://github.com/google/pebble.git
synced 2025-05-22 11:24:52 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
302
tests/fw/graphics/test_gbitmap_processor.c
Normal file
302
tests/fw/graphics/test_gbitmap_processor.c
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "clar.h"
|
||||
|
||||
#include "applib/graphics/framebuffer.h"
|
||||
|
||||
// Stubs
|
||||
///////////////////////
|
||||
|
||||
#include "stubs_app_state.h"
|
||||
#include "stubs_graphics_circle.h"
|
||||
#include "stubs_graphics_line.h"
|
||||
#include "stubs_graphics_private.h"
|
||||
#include "stubs_logging.h"
|
||||
#include "stubs_passert.h"
|
||||
#include "stubs_process_manager.h"
|
||||
|
||||
const GDrawRawImplementation g_default_draw_implementation;
|
||||
|
||||
// Statics
|
||||
///////////////////////
|
||||
|
||||
static GContext s_ctx;
|
||||
static FrameBuffer s_fb;
|
||||
|
||||
typedef struct MockBitbltBitmapIntoBitmapTiledCallRecording {
|
||||
GBitmap *dest_bitmap;
|
||||
const GBitmap *src_bitmap;
|
||||
GRect dest_rect;
|
||||
GPoint src_origin_offset;
|
||||
GCompOp compositing_mode;
|
||||
GColor8 tint_color;
|
||||
} MockBitbltBitmapIntoBitmapTiledCallRecording;
|
||||
|
||||
typedef struct MockBitbltBitmapIntoBitmapTiledCallRecordings {
|
||||
unsigned int call_count;
|
||||
MockBitbltBitmapIntoBitmapTiledCallRecording last_call;
|
||||
} MockBitbltBitmapIntoBitmapTiledCallRecordings;
|
||||
|
||||
static MockBitbltBitmapIntoBitmapTiledCallRecordings s_bitblt_bitmap_into_bitmap_tiled_calls;
|
||||
|
||||
// Fakes
|
||||
///////////////////////
|
||||
|
||||
GContext *graphics_context_get_current_context(void) {
|
||||
return &s_ctx;
|
||||
}
|
||||
|
||||
void bitblt_bitmap_into_bitmap_tiled(GBitmap* dest_bitmap, const GBitmap *src_bitmap,
|
||||
GRect dest_rect, GPoint src_origin_offset,
|
||||
GCompOp compositing_mode, GColor8 tint_color) {
|
||||
s_bitblt_bitmap_into_bitmap_tiled_calls.call_count++;
|
||||
s_bitblt_bitmap_into_bitmap_tiled_calls.last_call =
|
||||
(MockBitbltBitmapIntoBitmapTiledCallRecording) {
|
||||
.dest_bitmap = dest_bitmap,
|
||||
.src_bitmap = src_bitmap,
|
||||
.dest_rect = dest_rect,
|
||||
.src_origin_offset = src_origin_offset,
|
||||
.compositing_mode = compositing_mode,
|
||||
.tint_color = tint_color,
|
||||
};
|
||||
}
|
||||
|
||||
// Helpers
|
||||
///////////////////////
|
||||
|
||||
static void cl_assert_equal_rect(const GRect a, const GRect b) {
|
||||
cl_assert_equal_i(a.origin.x, b.origin.x);
|
||||
cl_assert_equal_i(a.origin.y, b.origin.y);
|
||||
cl_assert_equal_i(a.size.w, b.size.w);
|
||||
cl_assert_equal_i(a.size.h, b.size.h);
|
||||
}
|
||||
|
||||
// Setup
|
||||
///////////////////////
|
||||
|
||||
void test_gbitmap_processor__initialize(void) {
|
||||
s_fb = (FrameBuffer) {};
|
||||
framebuffer_init(&s_fb, &(GSize) {DISP_COLS, DISP_ROWS});
|
||||
graphics_context_init(&s_ctx, &s_fb, GContextInitializationMode_App);
|
||||
s_bitblt_bitmap_into_bitmap_tiled_calls = (MockBitbltBitmapIntoBitmapTiledCallRecordings) {};
|
||||
}
|
||||
|
||||
void test_gbitmap_processor__cleanup(void) {
|
||||
}
|
||||
|
||||
// Tests
|
||||
///////////////////////
|
||||
|
||||
#define EXPECTED_RECT_IN_PRE_FUNCTION (GRect(4, 3, 2, 1))
|
||||
|
||||
void test_gbitmap_processor__null_arguments(void) {
|
||||
GBitmap bitmap = {0};
|
||||
const GRect rect = EXPECTED_RECT_IN_PRE_FUNCTION;
|
||||
|
||||
// Passing NULL for the processor shouldn't cause any problems
|
||||
graphics_draw_bitmap_in_rect_processed(&s_ctx, &bitmap, &rect, NULL);
|
||||
// And it should try to draw the bitmap
|
||||
cl_assert_equal_i(s_bitblt_bitmap_into_bitmap_tiled_calls.call_count, 1);
|
||||
|
||||
// Passing a processor with NULL functions shouldn't cause any problems
|
||||
GBitmapProcessor processor = {0};
|
||||
graphics_draw_bitmap_in_rect_processed(&s_ctx, &bitmap, &rect, &processor);
|
||||
// And it should once again try to draw the bitmap
|
||||
cl_assert_equal_i(s_bitblt_bitmap_into_bitmap_tiled_calls.call_count, 2);
|
||||
}
|
||||
|
||||
#define EXPECTED_COMPOSITING_MODE_BEFORE_AND_AFTER_PRE_FUNCTION (GCompOpSet)
|
||||
#define EXPECTED_TINT_COLOR_BEFORE_AND_AFTER_PRE_FUNCTION (GColorShockingPink)
|
||||
|
||||
#define COMPOSITING_MODE_TO_SPECIFY_IN_PRE_FUNCTION (GCompOpTint)
|
||||
#define TINT_COLOR_TO_SPECIFY_IN_PRE_FUNCTION (GColorTiffanyBlue)
|
||||
#define RECT_TO_SPECIFY_IN_PRE_FUNCTION (GRect(-50, -50, 100, 100))
|
||||
#define BITMAP_TO_SPECIFY_IN_PRE_FUNCTION ((GBitmap *)1234)
|
||||
|
||||
#define EXPECTED_CLIPPED_RECT_AFTER_DRAWING_BITMAP (GRect(0, 0, 50, 50))
|
||||
|
||||
typedef struct PreAndPostFunctionsTestProcessor {
|
||||
GBitmapProcessor processor;
|
||||
GCompOp previous_compositing_mode;
|
||||
GColor previous_tint_color;
|
||||
} PreAndPostFunctionsTestProcessor;
|
||||
|
||||
static void prv_pre_and_post_functions__pre(GBitmapProcessor *processor, GContext *ctx,
|
||||
const GBitmap **bitmap_to_use,
|
||||
GRect *global_grect_to_use) {
|
||||
PreAndPostFunctionsTestProcessor *processor_with_data =
|
||||
(PreAndPostFunctionsTestProcessor *)processor;
|
||||
|
||||
// Record the existing compositing mode and tint color and check that they are what we expect
|
||||
cl_assert(ctx->draw_state.compositing_mode ==
|
||||
EXPECTED_COMPOSITING_MODE_BEFORE_AND_AFTER_PRE_FUNCTION);
|
||||
processor_with_data->previous_compositing_mode = ctx->draw_state.compositing_mode;
|
||||
cl_assert(gcolor_equal(ctx->draw_state.tint_color,
|
||||
EXPECTED_TINT_COLOR_BEFORE_AND_AFTER_PRE_FUNCTION));
|
||||
processor_with_data->previous_tint_color = ctx->draw_state.tint_color;
|
||||
|
||||
// Set the compositing mode and tint color to different values
|
||||
ctx->draw_state.compositing_mode = COMPOSITING_MODE_TO_SPECIFY_IN_PRE_FUNCTION;
|
||||
ctx->draw_state.tint_color = TINT_COLOR_TO_SPECIFY_IN_PRE_FUNCTION;
|
||||
|
||||
// Check that the rect here is what we gave to graphics_draw_bitmap_in_rect_processed()
|
||||
cl_assert_equal_rect(*global_grect_to_use, EXPECTED_RECT_IN_PRE_FUNCTION);
|
||||
|
||||
// Change the rect
|
||||
*global_grect_to_use = RECT_TO_SPECIFY_IN_PRE_FUNCTION;
|
||||
|
||||
// Change the bitmap
|
||||
*bitmap_to_use = BITMAP_TO_SPECIFY_IN_PRE_FUNCTION;
|
||||
}
|
||||
|
||||
static void prv_pre_and_post_functions__post(GBitmapProcessor *processor, GContext *ctx,
|
||||
const GBitmap *bitmap_used,
|
||||
const GRect *global_clipped_grect_used) {
|
||||
PreAndPostFunctionsTestProcessor *processor_with_data =
|
||||
(PreAndPostFunctionsTestProcessor *)processor;
|
||||
|
||||
// Check that the changes made to the GContext in .pre are still present
|
||||
cl_assert(ctx->draw_state.compositing_mode == COMPOSITING_MODE_TO_SPECIFY_IN_PRE_FUNCTION);
|
||||
cl_assert(gcolor_equal(ctx->draw_state.tint_color, TINT_COLOR_TO_SPECIFY_IN_PRE_FUNCTION));
|
||||
|
||||
// Reverse the changes to the GContext that were made in .pre
|
||||
ctx->draw_state.compositing_mode = processor_with_data->previous_compositing_mode;
|
||||
ctx->draw_state.tint_color = processor_with_data->previous_tint_color;
|
||||
|
||||
// Check that the bitmap here is the bitmap we specified in the .pre function
|
||||
cl_assert_equal_p(bitmap_used, BITMAP_TO_SPECIFY_IN_PRE_FUNCTION);
|
||||
|
||||
// Check that the rect here is the clipped version of the rect we specified in the .pre function
|
||||
cl_assert_equal_rect(*global_clipped_grect_used, EXPECTED_CLIPPED_RECT_AFTER_DRAWING_BITMAP);
|
||||
}
|
||||
|
||||
void test_gbitmap_processor__pre_and_post_functions(void) {
|
||||
GBitmap bitmap = {0};
|
||||
const GRect rect = EXPECTED_RECT_IN_PRE_FUNCTION;
|
||||
|
||||
// Set the compositing mode and tint color to known values
|
||||
s_ctx.draw_state.compositing_mode = EXPECTED_COMPOSITING_MODE_BEFORE_AND_AFTER_PRE_FUNCTION;
|
||||
s_ctx.draw_state.tint_color = EXPECTED_TINT_COLOR_BEFORE_AND_AFTER_PRE_FUNCTION;
|
||||
|
||||
PreAndPostFunctionsTestProcessor processor = (PreAndPostFunctionsTestProcessor) {
|
||||
.processor.pre = prv_pre_and_post_functions__pre,
|
||||
.processor.post = prv_pre_and_post_functions__post,
|
||||
};
|
||||
graphics_draw_bitmap_in_rect_processed(&s_ctx, &bitmap, &rect, &processor.processor);
|
||||
|
||||
// Check that the bitmap was drawn
|
||||
cl_assert_equal_i(s_bitblt_bitmap_into_bitmap_tiled_calls.call_count, 1);
|
||||
|
||||
// Check that the modifications made in the .pre function propagated to the bitmap drawing
|
||||
cl_assert(s_bitblt_bitmap_into_bitmap_tiled_calls.last_call.compositing_mode ==
|
||||
COMPOSITING_MODE_TO_SPECIFY_IN_PRE_FUNCTION);
|
||||
cl_assert(gcolor_equal(s_bitblt_bitmap_into_bitmap_tiled_calls.last_call.tint_color,
|
||||
TINT_COLOR_TO_SPECIFY_IN_PRE_FUNCTION));
|
||||
cl_assert_equal_rect(s_bitblt_bitmap_into_bitmap_tiled_calls.last_call.dest_rect,
|
||||
EXPECTED_CLIPPED_RECT_AFTER_DRAWING_BITMAP);
|
||||
cl_assert_equal_p(s_bitblt_bitmap_into_bitmap_tiled_calls.last_call.src_bitmap,
|
||||
BITMAP_TO_SPECIFY_IN_PRE_FUNCTION);
|
||||
|
||||
// Check that the modifications made to the GContext in the .pre function were reversed in .post
|
||||
cl_assert(s_ctx.draw_state.compositing_mode ==
|
||||
EXPECTED_COMPOSITING_MODE_BEFORE_AND_AFTER_PRE_FUNCTION);
|
||||
cl_assert(gcolor_equal(s_ctx.draw_state.tint_color,
|
||||
EXPECTED_TINT_COLOR_BEFORE_AND_AFTER_PRE_FUNCTION));
|
||||
|
||||
// Note that additional checks are performed in the .pre and .post functions
|
||||
}
|
||||
|
||||
typedef struct PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor {
|
||||
GBitmapProcessor processor;
|
||||
const GBitmap *expected_bitmap_in_post;
|
||||
bool post_func_called;
|
||||
} PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor;
|
||||
|
||||
static void post_function_called_even_if_pre_function_causes_nothing_to_be_drawn__post(
|
||||
GBitmapProcessor *processor, GContext *ctx, const GBitmap *bitmap_used,
|
||||
const GRect *global_clipped_grect_used) {
|
||||
PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *processor_with_data =
|
||||
(PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *)processor;
|
||||
|
||||
// Check that the rectangle here is empty to verify that nothing was drawn
|
||||
cl_assert_equal_rect(*global_clipped_grect_used, GRectZero);
|
||||
|
||||
// Check that bitmap_used is what we expect it to be (the expected value is set in .pre)
|
||||
cl_assert_equal_p(bitmap_used, processor_with_data->expected_bitmap_in_post);
|
||||
|
||||
// Record that the .post function was called
|
||||
processor_with_data->post_func_called = true;
|
||||
}
|
||||
|
||||
//! Helper function for testing that the .post function is called even if the .pre function
|
||||
//! causes no bitmap to be drawn
|
||||
static void prv_post_function_called_even_if_pre_function_causes_nothing_to_be_drawn_test(
|
||||
GBitmapProcessorPreFunc pre_func) {
|
||||
GBitmap bitmap = {0};
|
||||
const GRect rect = EXPECTED_RECT_IN_PRE_FUNCTION;
|
||||
|
||||
PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor processor =
|
||||
(PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor) {
|
||||
.processor.pre = pre_func,
|
||||
.processor.post = post_function_called_even_if_pre_function_causes_nothing_to_be_drawn__post,
|
||||
};
|
||||
graphics_draw_bitmap_in_rect_processed(&s_ctx, &bitmap, &rect, &processor.processor);
|
||||
|
||||
// Check that the bitmap was not drawn
|
||||
cl_assert_equal_i(s_bitblt_bitmap_into_bitmap_tiled_calls.call_count, 0);
|
||||
|
||||
// Check that the .post function was called even though the .pre function makes some change
|
||||
// that causes no bitmap to be drawn
|
||||
cl_assert(processor.post_func_called);
|
||||
}
|
||||
|
||||
static void post_function_called_even_if_pre_function_specifies_null_bitmap__pre(
|
||||
GBitmapProcessor *processor, GContext *ctx, const GBitmap **bitmap_to_use,
|
||||
GRect *global_grect_to_use) {
|
||||
PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *processor_with_data =
|
||||
(PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *)processor;
|
||||
|
||||
// Change the bitmap to use to NULL to cause nothing to be drawn
|
||||
*bitmap_to_use = NULL;
|
||||
|
||||
// We'll expect the bitmap we set there to be the bitmap passed into .post
|
||||
processor_with_data->expected_bitmap_in_post = *bitmap_to_use;
|
||||
}
|
||||
|
||||
void test_gbitmap_processor__post_function_called_even_if_pre_function_specifies_null_bitmap(void) {
|
||||
prv_post_function_called_even_if_pre_function_causes_nothing_to_be_drawn_test(
|
||||
post_function_called_even_if_pre_function_specifies_null_bitmap__pre);
|
||||
};
|
||||
|
||||
static void post_function_called_even_if_pre_function_specifies_empty_rect__pre(
|
||||
GBitmapProcessor *processor, GContext *ctx, const GBitmap **bitmap_to_use,
|
||||
GRect *global_grect_to_use) {
|
||||
PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *processor_with_data =
|
||||
(PostFunctionCalledEvenIfPreFunctionCausesNothingToBeDrawnTestProcessor *)processor;
|
||||
|
||||
// Change the rectangle to be empty to cause nothing to be drawn
|
||||
*global_grect_to_use = GRectZero;
|
||||
|
||||
// We'll expect the bitmap we passed into graphics_draw_bitmap_in_rect_processed() in .post
|
||||
// even though nothing will be drawn
|
||||
processor_with_data->expected_bitmap_in_post = *bitmap_to_use;
|
||||
}
|
||||
|
||||
void test_gbitmap_processor__post_function_called_even_if_pre_function_specifies_empty_rect(void) {
|
||||
prv_post_function_called_even_if_pre_function_causes_nothing_to_be_drawn_test(
|
||||
post_function_called_even_if_pre_function_specifies_empty_rect__pre);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue